2016-05-01 02:19 PM
Hi,
I experiment a strange behaviour while saving some data in flash: Some interrupts are not fired as they are when not flashing. Timer11 is ''nearly ok'', tick is not, uart reception is not. The joined logic analyzer screen capture shows it. The program is running an infinite loop and based to the rtc writes data in flash roughly every 2s. Meanwhile: - data are received through uart. An interrupt echoes immediatly the received byte to another uart. - timer11 interrupts and toggle high and low a pin - tick interrupts and toggle high and low a pin. The capture shows : Line 1 : state of the program : high during writing to flash. Line 2 : one pulse each time tick interrupt is fired. Line 3 : uart input Line 4 : echo of the uart input Line 5 : one pulse each time timer 11 interrupts. What I see is that during flash writing: - the tick interrupt is fired around 3 times less - uart receive interrupt is fired ''sometimes''. - Timer11 interrupt has a small time offset but is fired and many times as it should. Is it a regular behaviour ? Is there a solution / work around ? Some other experiments i did show that it is the same when using eeprom. STM32L151ZET6 Thanks Julien #flash-interrupt2016-05-01 03:06 PM
I did the same measurements with eeprom, the result are even worse. All interrupts are
fired about twice less than with flash.2016-05-01 05:24 PM
Writing to FLASH will stall execution from FLASH, erase will be even worse. Run your critical code and interrupt tables, from RAM
2016-05-02 04:37 AM
Hi Clive.
Thanks for your answer. I never did that before. I went through several documentations on the web mainly about linking. In order to simplify, I started working only on the tick handler. Goal: raise and lower a pin on each tick. (Don't care about counting for now). I use gcc. Here's what I did. : MoveSysTick_Handler
() to ram:
__attribute__( ( section(''.data'') ) ) void SysTick_Handler(void) {
GPIOD->BSRR = (uint32_t)GPIO_PIN_14;
GPIOD->BSRR = (uint32_t)GPIO_PIN_14 << 16
}
Data section is described like this:
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
Moved the isr_vector section to ram:
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >RAM AT> FLASH
The map file shows that .isr_vector and SysTick_Handler are in ram:
.isr_vector 0x20000000 0x13c load address 0x08000000
0x20000000 . = ALIGN (0x4)
*(.isr_vector)
.isr_vector 0x20000000 0x13c imports/Drivers/CMSIS/Device/ST/STM32L1xx/Source/Templates/gcc/startup_stm32l151xe.o
0x20000000 g_pfnVectors
0x2000013c . = ALIGN (0x4)
*(.data)
.data 0x20000140 0x20 src/interrupts.o
0x20000140 SysTick_Handler
Looking a this post: https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2FSTM32Discovery%2Fstm32f3%20moving%20ISR%20vector&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F¤tviews=28
I added the copy of the interrupt array to SystemInit():
memcpy(0x20000000, 0x08000000, 0x13c);
and change the vector table location :
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET
Ihave several questions :
- I took the 0x13c as interrupts vector size from the map file, but what is the good way to compute it ?
- without copying the array to ram, the system crashes. Does that mean that ''
>RAM AT> FLASH
'', only reserves space in memory and does nothing else ?
- With eveything above done, I still get the same result : interrupts are not regularly fired during flash writing. What's still wrong ?
2016-05-06 01:39 AM
One way to get the size of the section is to define a symbol that points to the end of it (in the linker script, like the `edata' symbol for the data section). Then your code can get the length as (sym_isr_end - isr_start).
The >RAM AT>FLASH computes all address references as if the data was placed in the RAM, but it actually stores the data in the FLASH. So at device boot, the data is available in flash, and the startup code needs to copy it into sram at the correct location. The normal startup code already does this for the data section, but you need to make sure it also happens for the additional isr section you added. But my guess would be that you need to do this for _all_ of your code that can be running while flashing. I would assume that once the CPU is stalled on an instruction fetch, it will be unable to service an interrupt until that stall is released. Hope this helps, - Kristian.2016-05-06 09:02 AM
Thanks.
I started a new project from scratch to be sure that there's no pollution from other code. As can be seen in this capture, the sysTick interrupt (2nd line) is not fired during flash writing(1st line). To be sure that no code in flash is called during flash writing, I deactivated all interrupts. SysTick_Handler () is in ram, like interrupt vector. I don't know what to do more. If anybody is willing to have a look to the full code, it can be downloaded here: Thanks in advance.2016-05-07 12:39 AM
> To be sure that no code in flash is called during flash writing, I
> deactivated all interrupts. SysTick_Handler () is in ram, like > interrupt vector. Yes, but your main code is still in flash - saveToFlash() and the HAL_FLASHEx_Erase() function that it calls, etc. As soon as the flash write operation starts, the CPU will be stalled on fetching the next instruction in the FLASH_PageErase() funtion. I do not have specific experience, but it seems really unlikely that once the CPU is stalled on the instruction fetch, that it is designed to abort that stall, go fetch and execute a pending interrupt, then go back to stalling on the flash. But I understand that it will be complicated to move _all_ related code into ram... - Kristian.2016-05-07 01:13 AM
Hum, hum, I see what you mean.
I thought that interrupt could ''wake up'' the device from stall because everything is hardware and ram from the interrupt point. I'll give a try on putting save functions in ram too. Thanks.2016-05-07 03:58 AM
Is your systick interrupt handler in RAM then?
Is you vector table in RAM then?Roger. Dear ST. I'm giving FREE technical support to ST customers, and when your ''special'' (I have never seen this elsewhere) forum software eats my answers, I give up. Goodbye everyone here!2016-05-08 02:44 PM
Kristian, you're the man. It works. Thanks to you, Clive and Wolfe too. I really appreciate.
The code I wrote is written with C++ and I still have some issue while calling vitual methods ; I suspect that this is because the virtual method's table is in flash. Do you know a way to tell the compiler / linker to move it to ram too ? Julien