cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L1 : interrupts not fired during flash programming

JulienD
Senior
Posted on May 01, 2016 at 23:19

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-interrupt
9 REPLIES 9
JulienD
Senior
Posted on May 02, 2016 at 00:06

I did the same measurements with eeprom, the result are even worse. All interrupts are

fired about twice less than with flash.

Posted on May 02, 2016 at 02:24

Writing to FLASH will stall execution from FLASH, erase will be even worse. Run your critical code and interrupt tables, from RAM 

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
JulienD
Senior
Posted on May 02, 2016 at 13:37

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. : Move

SysTick_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&currentviews=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 ?
knielsen
Associate II
Posted on May 06, 2016 at 10:39

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.

JulienD
Senior
Posted on May 06, 2016 at 18:02

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).

0690X00000605NxQAI.png

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:

https://we.tl/aABjEN7jvy

Thanks in advance.

knielsen
Associate II
Posted on May 07, 2016 at 09:39

> 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.

JulienD
Senior
Posted on May 07, 2016 at 10:13

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.

re.wolff9
Senior
Posted on May 07, 2016 at 12:58

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!

JulienD
Senior
Posted on May 08, 2016 at 23:44

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