I am using Sourcery CodeBench Lite 2012.03-56 compiler and gdb package with texane gdb server .
Today I wanted to try the FreeRTOS demo for the cheap STM32VLDISCOVERY board, I copied all the necessary source files compiled without errors, but the example did not work. I activated the debugger and noticed that this example fails when it tries to dereference a pointer to GPIO registers. Global array variable containing pointers to GPIO registers:
GPIO_TypeDef* GPIO_PORT[LEDn] = {LED3_GPIO_PORT, LED4_GPIO_PORT};
was not correctly initialized and filled with some random values. I checked that the preprocessor defines LED3_GPIO_PORT and LED3_GPIO_PORT, and they were valid.
After some research on where the problem might occur, I looked at the initial file provided for trueSTUDIO, found in the CMSIS lib. Original startup_stm32f10x_md_vl.S file:
.section .text.Reset_Handler .weak Reset_Handler .type Reset_Handler, %function Reset_Handler: /* Copy the data segment initializers from flash to SRAM */ movs r1,
During debugging, I noticed that the r1 register is never initialized to zero by the first command movs r1, # 0. The r1 register is used as a counter in the loop, therefore, when execution reaches the LoopCopyDataInit loop, it never enters the loop, since the r1 register is loaded some garbage data from a previous run. As a result, the startup code never initializes the .data strong> section.
When I placed the two nop commands before the movs r1, # 0 command, then the register r1 was initialized to 0, and the example started working:
Modified part of startup_stm32f10x_md_vl.S file:
nop nop movs r1, #0 b LoopCopyDataInit
This is a parsing of the relevant parts of the final code:
Disassembly of section .isr_vector: 08000000 <g_pfnVectors>: 8000000: 20002000 andcs r2, r0, r0 8000004: 08000961 stmdaeq r0, {r0, r5, r6, r8, fp} ... Disassembly of section .text: ... 8000960 <Reset_Handler>: 8000960: 2100 movs r1, #0 8000962: f000 b804 bw 800096e <LoopCopyDataInit> 08000966 <CopyDataInit>: 8000966: 4b0d ldr r3, [pc, #52] ; (800099c <LoopFillZerobss+0x16>) 8000968: 585b ldr r3, [r3, r1] 800096a: 5043 str r3, [r0, r1] 800096c: 3104 adds r1, #4
As you can see, the ISR vector table correctly points to the Reset_Handler address. So what is going on? Why was the first movs r1, # 0 command never executed in the original startup code?
EDIT:
The source code works when I turn off the board and turn it on again. I can reset the MCU several times and it works. When I start the gdb server, then the code does not work, even after reset. I need to activate the loop again in order to work. I guess this is some disgusting oddity.
Note:
I looked at what startup code other people use this MCU are, and they either turn off interrupts or load the SP register with a specific linker value, which in both cases is redundant. If they suffered from this strange behavior, they would never have noticed.