cancel
Showing results for 
Search instead for 
Did you mean: 

Write into flash while USART interrupt executed

Clemens Ehm
Associate II
Posted on October 23, 2017 at 12:33

Hello,

I have some trouble to write into the flash of my stm32f I can send via usart a lot of commands to the µC, interprete and execute them finally. One command is to write some data into the flash but if I write and the usart is still receiving data, the communication is totally dead - only mcu reset helps.

The only 'solution' which doesn't crash the communication is to deactivate the usart with USART1->CR1 &= ~USART_CR1_UE; before I write into flash and re-enable it after the flash operation - but that's not a real solution cause I will lose data/commands.

What I tried:

- Moving the vector table into SRAM

- Disable the usart interrupt (NVIC_DisableIRQ(USART1_IRQn);)

-

__disable_irq

(

)

;

before the flash operation

Without any effect. The linker script has the following settings:

MEMORY

{

FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K

UNUSED (rx) : ORIGIN = 0x8020000, LENGTH = 128K

RAM (xrw) : ORIGIN = 0x200000C0, LENGTH = 32K - 0xC0

}

I always write into the UNUSED section, not the FLASH where the running firmware is stored.

The best solution would be to disable the interrupt for the flash-write-time, the mcu buffering all incoming packages for the moment and after re-enabling the interrupt I receive the buffered data. Is that somehow possible or you have any other useful hints for me?

Thanks

Note: this post was migrated and contained many threaded conversations, some content may be missing.
19 REPLIES 19
Uwe Bonnes
Principal II
Posted on October 23, 2017 at 13:03

Single bank devices have no read while write capability. So make sure everything related to uart reception is in RAM and not in flash, and chances are good that reception while flashing will not loose character.s

Clemens Ehm
Associate II
Posted on October 23, 2017 at 14:18

Thx for the answer. I did the following now:

#define RAMFUNC __attribute__ ((long_call, section ('.ramfunctions')))

Added '*(.ramfunctions) ' inside the .data section

  .data :

  {

    . = ALIGN(4);

    _sdata = .;        /* create a global symbol at data start */

    *(.data)           /* .data sections */

    *(.data*)          /* .data* sections */

    . = ALIGN(4);

    *(.ramfunctions)

    _edata = .;        /* define a global symbol at data end */

  } >RAM AT> FLASH

And added the define before my IRQ Handler:

RAMFUNC void USART1_IRQHandler(void)

{

    if( ( USART1->ISR & USART_ISR_RXNE ) == USART_ISR_RXNE )

    {

        t_u8 byte = (uint8_t)(USART1->RDR); /* Receive data, clear flag */

        BufferPut( &U1Rx, byte );

    }

}

And also before the BufferPut Function where the data is saved in a struct

RAMFUNC t_bool BufferPut( volatile my_fifo *buffer, t_u8 ch)

{

    buffer->buff[buffer->in++] = ch;

    if( buffer->in == USARTBUFFSIZE )

    {

        buffer->in = 0;//start from beginning

    }

    return true;

}

But I still have the same issue.

Edit: I checked the output.map and it seems okay:

 *(.ramfunctions)

 .ramfunctions  0x20000848       0x48 utils/usart.o

                0x20000848                BufferPut

                0x2000086c                USART1_IRQHandler

                0x20000890                _edata = .
Clemens Ehm
Associate II
Posted on October 23, 2017 at 16:14

Disable the Receivepart of the USART with USART1->CR1 &= ~USART_CR1_RE; before writing into flash is also enough. The mcu will not stuck/freeze anymore. So it must be something with the receive part but I already removed my irq sub function and only call a 3 line IRQ Handler of USART 1. That's all.

Posted on October 23, 2017 at 16:23

If the USART is jamming up check for error status and clear that. FLASH writing will stall the processor long enough to get overrun errors.

Best to make sure all code and data runs from RAM, and nothing touches FLASH like SysTick or anything else. Using RX DMA instead of interrupts can be quite effective.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on October 23, 2017 at 14:26

Is you interrupt table also in RAM?

Posted on October 23, 2017 at 14:33

Should be.  Linker Script:

RAM (xrw)      : ORIGIN = 0x200000C0, LENGTH = 32K - 0xC0

First function I call from main():

♯ define APPLICATION_ADDRESS         (uint32_t)0x08000000

♯ define SYSCFG_MemoryRemap_SRAM     ((uint8_t)0x03)

volatile uint32_t *VectorTable = (uint32_t *) 0x20000000;

void Remap_Table(void)

{

    for (uint32_t i = 0; i < 48; i++)

    {

        VectorTable[i] = *(__IO uint32_t*) (APPLICATION_ADDRESS + (i << 2));

    }

    SYSCFG_MemoryRemapConfig( SYSCFG_MemoryRemap_SRAM );

}
Posted on October 23, 2017 at 14:49

The reference manual tells: ' On the contrary, during a program/erase operation to the Flash memory, any attempt to read the Flash memory will stall the bus'. Is your flash write routine perhaps interrupt driven and gives control to some idle code loading code from flash? Or does the flash write routine itself load code from flash while writing to flash?

Posted on October 23, 2017 at 15:33

The Flash routine itself uses the default functions from the StdPeriph_Driver/stm32f0xx_flash.h

So using these functions like FLASH_ProgramWord should be a problem too. But I did a fast test. Copy all needed stuff from the functions into own functions but still no success.

Like I said in my first post: 'deactivate the usart with USART1->CR1 &= ~USART_CR1_UE; before I write into flash and re-enable it after the flash operation' fix the issue. So it must be still something with the usart, but the irq handler and the called function in the irq handler is - if I can trust the output.map - inside the ram.

Posted on October 25, 2017 at 11:35

I just tried to use DMA for the RX Part of the USART and well... it's at least better than the interrupt implementation.

I still lose data while writing into flash and I have an input on the usart but the mcu is not crashing anymore.