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?