Executing the first Cortex m3 instruction

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, #0 b LoopCopyDataInit CopyDataInit: ldr r3, =_sidata ldr r3, [r3, r1] str r3, [r0, r1] adds r1, r1, #4 LoopCopyDataInit: ldr r0, =_sdata ldr r3, =_edata adds r2, r0, r1 cmp r2, r3 bcc CopyDataInit ldr r2, =_sbss b LoopFillZerobss ... 

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:

 /* Copy the data segment initializers from flash to SRAM */ 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.

+4
source share
2 answers

Sounds like a bug in your debugger. He probably sets a breakpoint in the first command and either completely skips it, or somehow re-sets it, it does not work correctly. The problem can be complicated by the fact that this is a reset vector, it may just be impossible to reliably stop the first command. Since the help of NOPs, I would recommend leaving them in place while you design your program.

However, there is an alternative solution. Since it is unlikely that you will need to modify the array, you really do not need this in the write section. In order for the compiler to put the array in a flash, usually it is enough to declare it as const:

 GPIO_TypeDef* const GPIO_PORT[LEDn] = {LED3_GPIO_PORT, LED4_GPIO_PORT}; 
+3
source

Nothing jumps right away, which might be wrong there. First off, how do you debug this code? Do you attach a debugger and then issue a reset to the processor via JTAG? I would put b Reset_Handler there right after your Reset_Handler: label Reset_Handler: as your first instruction, Reset_Handler: on the board, and then plug in the JTAG so that you can minimize any possible oddities from the debugger. Then install the computer on this mov instruction and see if it works. Is the bootloader or boot disk running this code? It could be something weird with an instruction or data cache.

+1
source

All Articles