cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L433 flash update executing from SRAM

Barber.Mark
Associate III

Hi,

I have a very confusing problem and looking for some outside thinking. I have a project designed around the STM32L433 a nice process that works very well. I am having a problem updating the flash with new firmware remotely. It is an iot type device with gsm connectivity. At the moment the system works by doing an ftp call to get the latest firmware. This is then saved in a local SPI flash memory chip. Then the program running in flash calls a firmware update routine now running in SRAM to reprogram the system flash. I have used this methodology before with the F745 family and works very nicely. Quick and clean.

The code is running in SRAM as it executes it spits out status information to a USART as it progresses. The firmware update function is declared as, this links it into SRAM.

__attribute__((long_call, section(".data"))) void program_flash(void)

Then when I update the flash I use the following instructions as part of the firmware update code.

           *(__IO uint32_t*)(prg_address)=(uint32_t)prog_data;

           __ISB();

           *(__IO uint32_t*)(prg_address+4)=(uint32_t)(prog_data>>32);

while((FLASH->SR&FLASH_SR_BSY)==FLASH_SR_BSY);

 

clearly “prg_address�? is the address to be programmed and “prog_data�? is the double word to program. The STM32L433 does its flash update a double word at a time.

Here is the interesting point, that has me stumped. This fails to program the flash even if I try only one double word, while debugging. If I change the “program_flash�? function so it executes out of flash not SRAM. Declared as s normal function.

void program_flash(void)

Then pick a “prg_address�? above any used code. The above programming instructions work and the flash is changed. So it appears the code works if I run from flash and program flash, but fails when I run from SRAM and try to program flash. Is this a limitation of the CPU or have I coded the programming instruction incorrectly? Do I need to make some special “far call�?. I am using GCC compiler. I lodged a support request with ST but it has been ignored, flicked to the too hard basket I suspect.

Mark

7 REPLIES 7
TDK
Guru

Are you accessing the flash at all within that function? Keep in mind constants are typically stored in flash. Constants which are sometimes hidden within macros. If so, those values may not be valid once the flash is changed, even if the code is being executed from RAM.

Post your code. The snippet of code you posted doesn't seem to be stored in RAM by the linker.

If you feel a post has answered your question, please click "Accept as Solution".
Barber.Mark
Associate III

Hi TDK,

Thanks for the folow up.

When executing from SRAM you cannot use any flash based code or fixed variables as the first thing the firmware update code does is mass erase the flash. I stopped the code executing before it did anything and using the STM32CubeProgrammer examined the SRAM and the flashupdate code is sitting in RAM so it is being compilied and linked into the SRAM.

i have attached the core of the firmware update code. i have left out the code to talk to the SPI flash, for clarity, for testing and program just one location. if i compile this to run out of flash again for testing i then do not preform the mass flash erase. it will work and program the flash location selected.

TDK
Guru

You're right, putting it in the "data" section should put it into RAM. I missed that.

I can't see anything that stands out as a problem to me.

Is "RCC->AHB1ENR|=RCC_AHB1ENR_FLASHEN;" doing anything? It doesn't seem like you'd disable this clock anywhere in your program. If it does, you should probably enable the clock before accessing any FLASH registers.

The "__ISB();" call isn't in the HAL functions and probably isn't necessary, but likely isn't the problem either.

I know you've simplified the example, so I can't see the original source. For example, the definitions of "prg_address" and "prog_data" aren't there. Probably not the problem either as these are probably in RAM. But if you've done something like "const uint32_t prg_address = 0x08010010" then that won't work as it'll be in flash and it'll have the value 0xFFFFFFFF after you erase the flash. Sounds like you are aware of this.

I would just step through and verify (a) the flash actually gets erased after issuing MER1/STRT command, (b) verify the prg_address/prog_data variables have the values you expect, (c) verify the flash does or doesn't get programmed after the two programming commands.

If you feel a post has answered your question, please click "Accept as Solution".
Barber.Mark
Associate III

Thanks, while some of the initial setup seem superfluous and not necessary. It makes no difference if i remove it. The unit runs in low power so I do turn the clock off when in deep sleep mode, in fact I turn almost everything off.

I have while debugging put the usual stop at this point while(1); then used the STM32CubeProgrammer to examine the flash and it does erase which means I am unlocking the FLASH_CR register.

The variables are declared as follows

uint64_t prg_address;

have also tried

unsigned long prg_address;

uint64_t prog_data;

however this might be a clue if the address variable i am using is not large enough to reach the flash address, when running from SRAM, this would account for the error. if the addressing is relavive to the flash base not absolute then this would fail in SRAM but pass in when running in flash. However i assume that defining

prg_address=0x08010010;

is absolute.

Bassett.David
Senior

How about the interrupt vectors?

TDK
Guru

Turn off low power and try it. I know some FLASH operation require a certain amount of voltage. Could be something to do with that.

There's nothing fundamentally wrong with what you're trying to do. Gotta be a bug somewhere.

So trying to flash from SRAM does absolutely nothing? It makes no changes to the FLASH? It doesn't hard fault either? Seems odd.

32 bits is all you need to reach any address on the chip. Yes it's absolute.

If you feel a post has answered your question, please click "Accept as Solution".
Barber.Mark
Associate III

Hi, thanks for the follow ups it turns out the solution is very simple just porrly documented. After mass erasing the flash, i needed to clear the MER1 flag if i wanted to write to the flash

   // Clear MER1

   FLASH->CR&=~FLASH_CR_MER1;

i then could write to the flash no problem.

Thanks

Mark