2017-10-23 03:33 AM
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 operationWithout 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.2017-10-23 04:03 AM
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
2017-10-23 05:18 AM
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> FLASHAnd 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 = .2017-10-23 07:14 AM
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.
2017-10-23 07:23 AM
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.
2017-10-23 07:26 AM
Is you interrupt table also in RAM?
2017-10-23 07:33 AM
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 );
}2017-10-23 07:49 AM
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?
2017-10-23 08:33 AM
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.
2017-10-25 04:35 AM
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.