Electronic – Does not trigger an interrupt DMA when reading SPI. Last byte transaction not coming

dmaspiuart

I use DMA for reading with SPI flash using USART. MCU – master, flash – slave. I read 1029 bytes per transaction. Exchange algorithm:

  1. I activate the flash (CS = 0)
  2. I configure the DMA channel to receive 1029 bytes. Allow IRQ_RX read interrupt
  3. I configure another DMA channel to transmit 1029 bytes. Allow IRQ_TX interrupt, enable channel-at this time send / receive
  4. In the IRQ_TX handler, clear the interrupt enable flag
  5. 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?

Best Answer

I am new to this microcontroller, and here's what I see:

  • its hardware manual http://www.cypress.com/file/241411/download (called "MB96600 Series: F2MC-16FX Hardware Manual") contains only one mention of SPI through USART;
  • I can not find readily available application note explaining how to interface SPI through USART, and I hope what you try to achieve is actually achievable with required level of reliability;
  • you do not state what your flash device is, and do not provide circuit diagram, so no way to check how devices may work together;
  • you see how hardware issue and your architecture (hardware and software) may cause system stall. Most probably you will have to redesign software (firmware) of the MCU to handle such situations, or choose another hardware architecture;
  • you say that flash device you use is SPI. As I know SPI protocol provides very weak algorithm of feedback from the slave device (through MISO), thus in native SPI there's very limited way to know the remote device state and why it does not perform up to expectations;
  • and, finally, you must do two things:
    • explain to us, and to yourself, how communication should work from your perspective and from your understanding of the datasheets. It may happen at this stage that you have some wrong expectations, or miss some bit of information about devices;
    • look at how it works in reality using some hardware sniffer, and compare to how you consider it should work. You may find out glitches in clock, or discrepancies in following serial algorithm (I am speculating here, as have no further idea about your hardware design).

I would put these thoughts as comment to the question, but it has more letters than comment can hold.