Can't debug after using SysTick_Config

3

I - an embedded beginner - am fighting my way through the black magic world of embedded programming. So far I won already a bunch of fights, but this new bug seems to be a hard one.

First, my embedded setup:

  • Olimex STM32-P207 (STM32F207)
  • Olimex ARM-USB-OCD-H JTAG
  • OpenOCD
  • Eclipse (with CDT and GDB hardware debugging)
  • Codesourcery Toolchain
  • Startup file and linker script (adapted memory map for the STM32F207) for RIDE (what uses GCC)
  • STM32F2xx_StdPeriph_Lib_V1.1.0

Using the many tutorials and Q&As out there I was able to set-up makefile, linker and startup code and got some simple examples running using STM's standard library (classic blinky, using buttons and interrupts etc.). However, once I started playing around with the SysTick interrupts, things got messy.

If add the SysTick_Config() call to my code (even with an empty SysTick_Handler), ...

int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured, 
       [...]
  */
  if (SysTick_Config(SystemCoreClock / 120000))
  {
    // Catch config error
    while(1);
  }
[...]

... then my debugger starts at the (inline) function NVIC_SetPriority() and once I hit "run" I end up in the HardFault_Handler(). This only happens, when using the debugger. Otherwise the code runs normal (telling from the blinking LEDs).

I already read a lot and tried a lot (modifying compiler options, linker, startup, trying other code with SysTick_Config() calls), but nothing solved this problem.

One thing could be a hint: The compiler starts in both cases (with and without the SysTick_Config call) at 0x00000184. In the case without the SysTick_Config call this points at the beginnig of main(). Using SysTick_Config this pionts at NVIC_SetPriority().

Does anybody have a clue what's going on? Any hint about where I could continue my search for a solution?

I don't know what further information would be helpful to solve this riddle. Please let me know and I will be happy to provide the missing pieces.

Thanks a lot!

/edit1: Added results of arm-none-eabi-readelf, -objdump and -size.

/edit2: I removed the code info to make space for the actual code. With this new simplified version debugging starts at

08000184:   stmdaeq r0, {r4, r6, r8, r9, r10, r11, sp}

readelf:

[ 2] .text             PROGBITS        08000184 008184 002dcc 00  AX  0   0  4
...
 2: 08000184     0 SECTION LOCAL  DEFAULT    2
...
46: 08000184     0 NOTYPE  LOCAL  DEFAULT    2 $d

main.c

/* Includes ------------------------------------------------------------------*/
#include "stm32f2xx.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint16_t counter = 0;

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void assert_failed(uint8_t* file, uint32_t line);
void Delay(__IO uint32_t nCount);
void SysTick_Handler(void);
/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
int main(void)
{
  if (SysTick_Config(SystemCoreClock / 12000))
  {
    // Catch config error
    while(1);
  }
  /*
   * Configure the LEDs
   */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); // LEDs

  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOF, &GPIO_InitStructure);

  GPIOF->BSRRL = GPIO_Pin_6;

  while (1)
  {
    if (GPIO_ReadInputDataBit(GPIOF, GPIO_Pin_9) == SET)
    {
      GPIOF->BSRRH = GPIO_Pin_9;
    }
    else
    {
      GPIOF->BSRRL = GPIO_Pin_9;
    }
    Delay(500000);
  }
  return 0;
}

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

/**
 * @brief  Delay Function.
 * @param  nCount:specifies the Delay time length.
 * @retval None
 */
void Delay(__IO uint32_t nCount)
{
  while (nCount > 0)
  {
    nCount--;
  }
}

/**
  * @brief  This function handles Hard Fault exception.
  * @param  None
  * @retval None
  */
void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {
  }
}

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
  if (counter > 10000 )
  {
    if (GPIO_ReadInputDataBit(GPIOF, GPIO_Pin_8) == SET)
    {
      GPIOF->BSRRH = GPIO_Pin_8;
    }
    else
    {
      GPIOF->BSRRL = GPIO_Pin_8;
    }
    counter = 0;
  }
  else
  {
    counter++;
  }
}

/edit3:

Soultion: Because the solution is burrowed in a comment, I put it up here:

My linker file was missing ENTRY(your_function_of_choice); (e.g. Reset_Handler). Adding this made my debugger work again (it now starts at the right point).

Thanks everybody!

debugging
embedded
inline
stm32
asked on Stack Overflow Jul 4, 2012 by bit-pirate • edited Jul 5, 2012 by bit-pirate

1 Answer

3

I have a strong feeling that the entry point isn't specified correctly in the compiler options or linker script...

And whatever code comes first at link time in the ".text" section, it gets to have the entry point.

The entry point, however, should point to a special "init" function that would set up the stack, initialize the ".bss" section (and maybe some other sections as well), initialize any hardware that's necessary for basic operation (e.g. the interrupt controller and maybe some system timer) and any remaining portions of the and standard libraries before actually transferring control to main().

I'm not familiar with the tools and your hardware, so I can't say exactly what that special "init" function is, but that's pretty much the problem. It's not being pointed to by the entry point of the compiled program. NVIC_SetPriority() doesn't make any sense there.

answered on Stack Overflow Jul 5, 2012 by Alexey Frunze

User contributions licensed under CC BY-SA 3.0