cancel
Showing results for 
Search instead for 
Did you mean: 

CPU stalling when erasing FLASH on STM32F405

vss01
Associate II
Posted on July 15, 2016 at 16:13

Hello,

I have a scenario as follows: I have a Timer 2 that gets interrupted every 1ms. I try to communicate (only Tx) with an external device every 50ms by calling a function inside Timer 2. When the system is running I am updating the flash of the microcontroller (erase then program) and this is causing my CPU to stall.

Before writing this post I did my homework and I am aware that when a write/erase operation is being performed on flash, accessing the flash causes a CPU stall. To prevent this I am putting all the code, constants, ZI data and all other data on the RAM. I am doing this through Keil uVision's environment. I am also loading my Interrupt Vector Table to RAM by running code similar to that of 

https://www.keil.com/pack/doc/CMSIS/Core/html/_using__v_t_o_r_pg.html

.

I can see in my map file that the functions that I'm calling are stored in RAM (their address starts at 0x200...). This means that CPU should not halt even if I'm running code while the flash is being erased, however this isn't the case. The CPU is stalling and stopping the communication.

Can you please advice? Thanks
9 REPLIES 9
Posted on July 15, 2016 at 17:28

Evidently something is touching the FLASH, you'd probably want to disassemble and walk though the code, and review everything in the vector table that might get called.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
knielsen
Associate II
Posted on July 15, 2016 at 17:37

Also be aware that _all_ code that can run around the flash erase needs to be in RAM. It is not enough that the code you call from the interrupt (and the interrupt itself and the vector table) is in RAM. If the code that does the flash erase is in flash, the CPU will be stalled at that point, and it will not be able to service any interrupt until the flash operation is complete, even if such interrupt itself could run in RAM.

vss01
Associate II
Posted on July 18, 2016 at 08:21 Thank you for your replies. I'm using the code below in the beginning of my main function to move the vector table to RAM. The code is fromis from

https://www.keil.com/pack/doc/CMSIS/Core/html/_using__v_t_o_r_pg.html

as is intended for cortex M3 microcontrollers however im using it for my cortex M4 stm32fI don't think this shouldbe an issue. Is there something that needs to be modified? Can this be the issue? Thank you.

/* size Cortex-M3 vector table */
#define VECTORTABLE_SIZE (256)
/* 16 Cortex + 32 ARMCM3 = 48 words */ /* next power of 2 = 256*/
#define VECTORTABLE_ALIGNMENT (0x100ul)
/* new vector table in RAM */
uint32_t vectorTable_RAM[VECTORTABLE_SIZE] __attribute__(( aligned (VECTORTABLE_ALIGNMENT) ));
void relocate_NVIC_to_RAM(void){
uint32_t i;
volatile const uint32_t *org_table = 0x00000000;
for (i = 0; i <

VECTORTABLE_SIZE

; i++) {
vectorTable_RAM[i] = org_table[i]; /* copy vector table to RAM */
}
/* replace SysTick Handler */
vectorTable_RAM[SysTick_IRQn + 16] = (uint32_t)SysTick_Handler_RAM;
/* relocate vector table */
__set_FAULTMASK(1);
SCB->VTOR = (uint32_t)&vectorTable_RAM;
__DSB();
__set_FAULTMASK(0);
}
void SysTick_Handler_RAM(void) {
msTicks_RAM++; /* increment counter */
}

Posted on July 18, 2016 at 21:15

Ok, but perhaps I'm not being clear enough, while it matters where the Vector Table is located, it also matters what routines the vector table points too, and what routine(s) in turn those routines call.

If you don't want things stalling, nothing, I repeat *nothing*, in the chain of execution or memory access must look directly at the FLASH array.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
vss01
Associate II
Posted on July 25, 2016 at 07:49

This is making me go crazy! I stopped all the initialization functions that enable all the peripherals and interrupts except for IWDG and TIM2. In TIM2 IRQ I have the following code:

void TIM2_IRQHandler(void)
{
/* USER CODE BEGIN TIM2_IRQn 0 */
/* USER CODE END TIM2_IRQn 0 */
HAL_TIM_IRQHandler(&htim2);
/* USER CODE BEGIN TIM2_IRQn 1 */
HAL_IWDG_Refresh(&hiwdg);
timer_base++;
if (timer_flash_update++ == 4000){
update_flash();
timer_flash_update = 0;
}
if (timer_base >= 50){
timer_base = 0;
}
if (flag_IT){
GPIO_RESET;
flag_IT = 0;
}
else{
flag_IT = 1;
GPIO_SET;
}
}

Basically I have a GPIO pin that I am toggling every 1 ms. I also try to erase a sector of the flash every 4 seconds. When the a sector is being erased, I can see that the toggling stops thereby indicating the stalling of the CPU. The function update_flash() contains:

void update_setting_in_flash(void){
uint32_t FirstSector = 0, NbOfSectors = 0;
uint32_t SectorError = 0;
FLASH_EraseInitTypeDef EraseInitStruct;
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
FirstSector = FLASH_PARAM_SECTOR; //TODO:correct this
NbOfSectors = 1;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.Sector = FirstSector;
EraseInitStruct.NbSectors = NbOfSectors;
HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
HAL_FLASH_Lock();
}

I am only erasing 1 sector in this function. All my code is placed is in RAM by accessing the project files and setting the ''Memory assignment'' options from the Keil uVision environment to RAM (All the Code/Const, ZI data and other data). I am also moving my vector table to RAM. I have a debugger connected to my board and I can see that all my variables and codes that I am accessing are being stored in the RAM (have an address of 0x..) that matches what is found in the MAP files generated. What can I do about this matter? I mean all the code is in RAM and nothing obvious is being accessed from flashed not just during FLASH ERASE but also during the whole execution period of the code. Please advice. Thank you!
Posted on July 25, 2016 at 09:25

But wouldn't such coding inherently block itself? The interrupt isn't going to reenter, you physically have to leave.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
vss01
Associate II
Posted on July 25, 2016 at 09:34

Why would it block? The pin stops toggling when the flash is erasing and operation is restored back when the erase operation is complete.

vss01
Associate II
Posted on July 25, 2016 at 14:30

OK it worked! I forgot a variable! thanks for your help!

By the way, what attribute loads a function in RAM in Keil uVision IDE (instead of all the functions in a particular .c file) ?

Posted on July 25, 2016 at 15:14

In Keil you'd use section/load-region attribution to direct functions into RAM.

I'd tend to approach this differently as it is very hard to contain what functions a function ends up calling. I'm also a strong advocate for keeping loader and application functionality separate.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..