Just FYI, by choosing to include the SPL framework you automatically pull in code from the SPL’s startup assembly code startup_stm32f30x.S
and the Reset_Handler()
(first functon that is executed)) from system_stm32f30x.c
that will initialize the processor and memory, and the tries to initialize the clocks.
The flow here is
Reset_Handler()
-> Copy the data segment initializers from flash to SRAM
-> Zero fill the bss segment
-> call SystemInit()
-> init HSI
-> SetSysClock() [attempts to turn on HSE oscillator]
-> call main()
But that should be okay, it shouldn’t get stuck there.
However, I’m 99% sure that the situation that I hinted at before is happening: Compiler optimizatons.
I recommend that in your header file all register fields
Are marked as volatile
, just like the STM’s SPL code does with __IO
. Otherwise the compiler might try to optimize it and not execute your code correctly.
You can see that this is happening because if I take your header file and compile the firmware I get as a compilatin result
RAM: [ ] 2.3% (used 1132 bytes from 49152 bytes)
Flash: [ ] 0.7% (used 1792 bytes from 262144 bytes)
Building .pio\build\disco_f303vc\firmware.bin
however, when I replace your header file with this
#define __IO volatile /*!< Defines 'read / write' permissions */
typedef struct{
__IO unsigned int CR;
__IO unsigned int CFGR;
__IO unsigned int CIR;
__IO unsigned int APB2RSTR;
__IO unsigned int APB1RSTR;
union{__IO unsigned int AHBENR;
struct{
__IO unsigned DMA1EN:1;
__IO unsigned DMA2EN:1;
__IO unsigned SRAMEN:1;
__IO unsigned Res:1;
__IO unsigned FLITFEN:1;
__IO unsigned Res1:1;
__IO unsigned CRCEN:1;
__IO unsigned Res2:10;
__IO unsigned IOPAEN:1;
__IO unsigned IOPBEN:1;
__IO unsigned IOPCEN:1;
__IO unsigned IOPDEN:1;
__IO unsigned IOPEEN:1;
__IO unsigned IOPFEN:1;
__IO unsigned Res3:1;
__IO unsigned TSCEN:1;
__IO unsigned Res4:3;
__IO unsigned ADC12:1;
__IO unsigned ADC34:1;
__IO unsigned Res5:2;
};//END STRUCT ahbenr
};//end union AHBENR
__IO unsigned int APB2ENR;
__IO unsigned int APB1ENR;
__IO unsigned int BDCR;
__IO unsigned int CSR;
__IO unsigned int AHBRSTR;
__IO unsigned int CFGR2;
__IO unsigned int CFGR3;
}RCC_Type;
typedef struct{
union{__IO unsigned int MODER;
struct{
__IO unsigned MODER0:2;
__IO unsigned MODER1:2;
__IO unsigned MODER2:2;
__IO unsigned MODER3:2;
__IO unsigned MODER4:2;
__IO unsigned MODER5:2;
__IO unsigned MODER6:2;
__IO unsigned MODER7:2;
__IO unsigned MODER8:2;
__IO unsigned MODER9:2;
__IO unsigned MODER10:2;
__IO unsigned MODER11:2;
__IO unsigned MODER12:2;
__IO unsigned MODER13:2;
__IO unsigned MODER14:2;
__IO unsigned MODER15:2;
};
};
__IO unsigned int OTYPER;
__IO unsigned int OSPEEDR;
__IO unsigned int PUPDR;
union{ __IO unsigned int IDR;
struct{
__IO unsigned IDR0:1;
__IO unsigned IDR1:1;
__IO unsigned IDR2:1;
__IO unsigned IDR3:1;
__IO unsigned IDR4:1;
__IO unsigned IDR5:1;
__IO unsigned IDR6:1;
__IO unsigned IDR7:1;
__IO unsigned IDR8:1;
__IO unsigned IDR9:1;
__IO unsigned IDR10:1;
__IO unsigned IDR11:1;
__IO unsigned IDR12:1;
__IO unsigned IDR13:1;
__IO unsigned IDR14:1;
__IO unsigned IDR15:1;
};
};
union{ __IO unsigned int ODR;
struct{
__IO unsigned OR0:1;
__IO unsigned ODR1:1;
__IO unsigned ODR2:1;
__IO unsigned ODR3:1;
__IO unsigned ODR4:1;
__IO unsigned ODR5:1;
__IO unsigned ODR6:1;
__IO unsigned ODR7:1;
__IO unsigned ODR8:1;
__IO unsigned ODR9:1;
__IO unsigned ODR10:1;
__IO unsigned ODR11:1;
__IO unsigned ODR12:1;
__IO unsigned ODR13:1;
__IO unsigned ODR14:1;
__IO unsigned ODR15:1;
};
};
/*
__IO unsigned int BSRR;
__IO unsigned int LCKR;
__IO unsigned int AFRL;
__IO unsigned int AFRH;
__IO unsigned int BRR;
*/
}GPIO_Type;
#define Input 0
#define Output 1
#define Alternate 2
#define Analog 3
#define RCC ((RCC_Type*) 0x40021000)
#define GPIOA ((GPIO_Type*) 0x48000000)
#define GPIOE ((GPIO_Type*) 0x48001000)
so, everything is marked as __IO
, and I recompile, I get
RAM: [ ] 2.3% (used 1132 bytes from 49152 bytes)
Flash: [ ] 0.7% (used 1844 bytes from 262144 bytes)
so, 52 more bytes have been added to the code. Those might the those instructions actually reading the register and not doing optimizations like reading it once and assuming it never changes (which GCC does since there’s no volatile
on the variable).
I recommend you try the above header file.
Also, I see that you’ve flashed the firmware via the STLink. PlatformIO has built-in debugging capabilities, you can just set a breakpoint anywhere and “Run & Debug” tab at the left side to start debugging.
However, be careful: When using this, the firmware is also recompiled in debug mode (-Og
instead of -Os
), and then those exact compiler optimizations destroying your firmware previously may not appear in debug mode anymore.