I use DMA for reading with SPI flash using USART. MCU - master, flash - slave. I read 1029 bytes per transaction. Exchange algorithm:
- I activate the flash (CS = 0)
- I configure the DMA channel to receive 1029 bytes. Allow IRQ_RX read interrupt
- I configure another DMA channel to transmit 1029 bytes. Allow IRQ_TX interrupt, enable channel-at this time send / receive
- In the IRQ_TX handler, clear the interrupt enable flag
- In the IRQ_RX handler, I clear the interrupt enable flag + deactivate the flash (CS = 1)
It works. But very rarely there is an error when I send 1029 bytes, but only 1028 is received. In the debugger, I see that the DMA counter sent bytes is 0 (sent 1029), and the counter read is 1 (up to 1028). Since DMA did not receive the last byte, RX interrupt does not occur, and I can not enter the RX interrupt handler. The interrupt handler TX is called, that is, 1029 bytes are accurately sent. Error flags are zero. This error occurs rarely. Why don't I get the last byte, what could be wrong?
MCU - F2MC-16FX MB96600 Series. IDE Softune Workbench
void USART_start_DMA_read(void)
{
/* correct size_pic and address */
//INIT DMA FOR READ
if(UART2_SSR2_RDRF==0)
UART2_ESIR2_RDRF=0; //clear RDRF - Reception data register full
DSR_DTE2 = 0x0; //Clear possible DMA 2 request
DER_EN2 = 0x0; //DMA 2 channel disable
DISEL2 = _IRQ_LINR2; //< LIN USART 2 RX
DCT2 = 1029; //how much to read
IOA2 = (unsigned long)&UART2_RDR2;
DMACS2 = 0x10; //no IOA update, BAP update, byte transfer, IOA -> BAP
BAPH2 = (unsigned long) &graph_buf[beg_byte] >> 16;
BAPM2 = (unsigned long) &graph_buf[beg_byte] >> 8;
BAPL2 = (unsigned long) &graph_buf[beg_byte] & 0xFF;
DER_EN2 = 1; // DMA 2 channel enable
UART2_SSR2_RIE = 1; //enable irq RX - at this point the channel is ready to receive bytes
FLASH_CS = FLASH_ON; //enable flash
//INIT DMA FOR SEND
if(UART2_SSR2_TDRE==0)
UART2_ESIR2_TDRE=0; //clear TDRF - Transmit data register full
DSR_DTE3 = 0x0; //Clear possible DMA 3 request
DER_EN3 = 0x0; //DMA 3 channel disable
DISEL3 = _IRQ_LINT2; //< LIN USART 2 TX
DCT3 = DCT2; //how much to send
IOA3 = (unsigned long)&UART2_TDR2;
DMACS3 = 0x12; //no IOA update, BAP update, byte transfer, BAP -> IOA
BAPH3 = (unsigned long) &read_flash_cmd[0] >> 16;
BAPM3 = (unsigned long) &read_flash_cmd[0] >> 8;
BAPL3 = ((unsigned long) &read_flash_cmd[0] & 0xFF);
DER_EN3 = 1; // DMA 3 channel enable
UART2_SSR2_TIE = 1; //enable irq TX - at this point the transmission / reading starts
}
void IRQ_USART2_TX()
{
//after transferring 1029 bytes
UART2_SSR2_TIE=0; //disable irq TX
DSR_DTE3 = 0x0; //clear DMA channel request
__wait_nop();
__wait_nop();
__wait_nop();
__wait_nop();
__wait_nop();
}
void IRQ_USART2_RX(void)
{
//after reading 1029 bytes
FLASH_CS = FLASH_OFF; //disable flash
UART2_SSR2_RIE = 0; //disable irq RX
DSR_DTE2 = 0x0; //clear DMA channel request
//if not the entire object is read - read the following data block
if(size_pic)
{
USART_start_DMA_read();
}
}
Updated. Failure occurs if I run the firmware through the debugger. If I run without debugger, everything works without failures. What do you think, can the debugger affect the work?