2023-03-06 04:12 PM
Hi,
As far as I understand, for the STM32F103, after a reset or power on without the use of the bootloader, the first task that happens is load SP with the content of address 0x00 (alias of 0x8000000) , followed by the load of the content of address 0x04 to the PC.
My question is where are the code to performs this tasks written?
Thanks.
2023-03-06 11:12 PM
Depends on your tool chain. Look for a startup*.s assembler file in your STM232CubeMX generated project folder.
The startup code could also be written in C with some attributes like:
// Cortex-M startup code using gcc-none-eabi toolchain
#include <stdint.h>
#include <string.h>
// symbols provided by the .ld linker script file
extern uint32_t _etext;
extern uint32_t _sdata;
extern uint32_t _edata;
extern uint32_t _sidata;
extern uint32_t _sbss;
extern uint32_t _ebss;
extern uint32_t _estack;
extern int main(void);
#pragma GCC optimize("O3")
__attribute__ ((naked))
void Reset_Handler(void)
{
// copy initialized global variables in .data from flash to SRAM
memcpy(&_sdata, &_sidata, (size_t)&_edata - (size_t)&_sdata);
// init uninitialized global variables in .bss with zero
memset(&_sbss, 0, (size_t)&_ebss - (size_t)&_sbss);
// now invoke main()
main();
// if main() returns:
for (;;)
;
}
void* vectors[128] __attribute__((section(".isr_vector"))) =
{
&_estack,
Reset_Handler,
// more IRQ handlers go here
};
hth
KnarfB
2023-03-06 11:41 PM
Where i decide it is.
Your code fragment is just a right step on proper programming.
Second step would be using open source compiler, -nostdlib
to not waste stack put main in vectors instead of reset handler and then do
void __attribute__ ((noreturn)) main() {
system_init();
while(1) {
//main loop here;
}
}
and in system init do this memcpy, memset. I recommend to configure FLASH_ACR and then clocks first so it gets up to speed as soon as possible. Unless you want to run on lower than default clock then set up clock after init.
If you would make your own linker script stack definition could be much easier - just declare global variable with right section (like noinit).
Too i recommend to not abuse memcpy and memset. Make use of fact that both data and bss is 4 byte aligned at least - you may copy by words.
I like to put stack at beginning, not end of RAM (by defining section in linkerscript), as stack overflow would result in hard crash, not silent overwrite of global variables. But that's my preference.
2023-03-07 09:48 AM
Hi,
The code I mean is not my code, it is the code that after a reset load SP and PC with the values I put in address 0x00 and 0x04.
This code runs before my code, it is a kind of bootloader?
2023-03-07 09:59 AM
No, it's a vector table pointing at start up code.
The function is called Reset_Handler, and it typically contains or calls code to initialize the processor and perform the C run-time start up requirements, typically copying initial content of the statics to RAM, and zeroing other stuff, and in the case of C++ running the constructors, before handing off to the user's main() function.
...
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD SecureFault_Handler ; Secure Fault Handler
...
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR SP, =__initial_sp
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
...
2023-03-07 03:36 PM
Thanks all for the answers, they helped me.