Loading...
 

Zephyr project on STM32

   Zephyr Workbench, a VSCode extension to manage Zephyr on STM32.
It enables users to easily create, develop, and debug Zephyr applications.
Main features:
  • Install host dependencies.
  • Import toolchain and SDK.
  • Create, configure, build and manage apps.
  • Debug STM32.
You can directly download it from the VSCode marketplace
For more details, visit the Zephyr Workbench

System Workbench for STM32


MCU boot-up sequence question

So I’ve been reading up on how to make my own bootloader, because I want to understand how they work on the low level and apply that understanding for my own one. I don’t want to use the ST’s own bootloader in the system memory (addr. 0x1FFF 0000 - 0x1FFF 7A0F). I’m using my own little bare metal board with a STM32F415RGT (Pic below). I’m using the STM32 AC6 workbench IDE.

IMAG0780

At the moment I’m using a very light debug test build, which enables GPIO clocks and then configures the LED GPIOs as outputs and in the while loop toggles their state according to the pushbutton state on the board (SW not-actuated -> LEDS on, SW actuated -> LEDS off). The startup file “startup_stm32f415xx.s” (is this file defined somewhere in the project settings, because I couldn’t find it’s declaration?) inits the RAM and configures the basic clock with the “systemInit” from “system_stm32f4xx.c”.



So far I have never needed to change the default linker scripts, because I haven’t used a bootloader before or have needed to change where the application was written in FLASH, so I had never actually touched the linker script even.But I have figured that out now through my own experimenting and googling how to change where the application is being written in FLASH.

following snippet from the “STM32F415RGTx_FLASH.ld” linker script.

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = 0x20020000; /* end of RAM */
/* Generate a link error if heap and stack don’t fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x200; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
RAM (xrw)  : ORIGIN = 0x20000000, LENGTH = 128K
CCMRAM (rw)  : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx)  : ORIGIN = 0x8008000, LENGTH = 992K //been experimenting with changing this address and length and confirmed through debug that the application has moved according to it.
}


Now the part I’m really interested is the “ENTRY(Reset_Handler)”, because it seems to define the address where the MCU will jump to when it resets. Where is it located in the memory? And also, does it jump to the “reset vector” on the vector table and from there to the “reset_handler” or directly to the actual “reset_handler” address?

This question rose after debugging and having flashed the same app to FLASH at addresses 0x0800 0000, 0x0800 4000 and 0x0800 8000 (debugging doesn’t erase FLASH, so it left the old apps in place. I then later chip erased the FLASH with ST-LINK UTILITY to clean it up) and wondered where the jump vector is defined so it knows which apps reset_handler address to jump to.

BootConf

Where is this “reset vector” located in the memory, because I believe it to be a fixed memory address, which then gets updated during flashing. How would the MCU otherwise know which of the three app locations and their respective reset_handles to jump to? This has to be one of the very first things things the MCU does when booting-up.


Ok, I figured what was going on and why it was going on.

Following was in the programming manual PM0214
Stack pointer
The Stack Pointer (SP) is register R13. In Thread mode, bit1 of the CONTROL register
indicates the stack pointer to use:
• 0 = Main Stack Pointer (MSP). This is the reset value.
• 1 = Process Stack Pointer (PSP).
On reset, the processor loads the MSP with the value from address 0x00000000.

Link register
The Link Register (LR) is register R14. It stores the return information for subroutines,
function calls, and exceptions. On reset, the processor loads the LR value 0xFFFFFFFF.

Program counter
The Program Counter (PC) is register R15. It contains the current program address. Bit0 is
always 0 because instruction fetches must be halfword aligned. On reset, the processor
loads the PC with the value of the reset vector, which is at address 0x00000004.



This made me very confused at first, because I had done a chip erase and the adr, 0x0800 0000, onto which the 0x0000 0000 address is aliased to in normal boot didn’t contain anything else except 0xFFFF FFFF. “Well how the heck is the MCU then booting to 0x0800 8000, where my application is?”. I had only used the openocd debugger in AC6 when testing my application until this point, so I decided to just use the ST-LINK UTILITY, because I know that it doesn’t do anything else except write the .bin file contents to the chosen memory address. So I then proceeded to do a chip erase and then write the application’s .bin file to the 0x0800 8000 address. Application doesn’t run now... what?

Turns out running the debugger in AC6 jumps itself to the 0x0800 8000 and that’s why it begins running the app no problem and why my other apps in the FLASH didn’t confuse it. But testing this through the ST-LINK UTILITY showed that writing the .bin on a erased chip to either 0x0800 0000 or 0x0800 8000 yielded no running code but writing to both addresses did... What?

Actually it makes very much sense after thinking about it.
If the app is only written to the 0x0800 0000 it begins running, but the reset handler then jumps to 0x0800 8000 area, which contains no running code and therefore hangs.
If the app is only written to the 0x0800 8000 then it won’t ever be run because as the code execution starts from the 0x0800 0000, which now only contains invalid instructions and hangs.
But if it’s written in both places then it will jump from 0x0800 0000 to the 0x0800 8000, which now does contain running code and goes happily running on it’s way.

TLDR: Code running starts from (in this case) 0x0800 0000, but AC6 debugger jumped automatically to 0x0800 8000 at the start of debugging.


 

Newest Forum Posts

  1. SPI on Nucleo_STMH533RE by royjamil, 2025-05-04 20:13
  2. SPI on Nucleo_STMH533RE by higginsa1, 2025-03-25 07:37
  3. SPI on Nucleo_STMH533RE by royjamil, 2025-03-23 11:31
  4. SPI on Nucleo_STMH533RE by higginsa1, 2025-03-23 09:33
  5. Configuring DMA for ADC in SW? by sam.hodgson, 2025-03-04 12:58
  6. Build a project in "release" mode by info@creosrl.it, 2025-02-20 18:12
  7. Build a project in "release" mode by info@creosrl.it, 2025-02-20 17:05
  8. Build a project in "release" mode by tang, 2025-02-20 10:36
  9. Build a project in "release" mode by info@creosrl.it, 2025-02-19 17:35
  10. Fail to debug in Win 11 C/C++ by mortenlund, 2024-12-26 20:27

Last-Modified Blogs