1
\$\begingroup\$

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?

\$\endgroup\$
  • 4
    \$\begingroup\$ Please add information about what microcontroller, other hardware and development environment you are using. And please add the relevant code. \$\endgroup\$ – Codo Sep 12 '18 at 17:56
  • 1
    \$\begingroup\$ How can you verify it was sent properly at the interface? What other events are synchronous to end of Tx that might cause last byte not to be sent? if no Rx error flags are verified? \$\endgroup\$ – Sunnyskyguy EE75 Sep 12 '18 at 17:57
  • \$\begingroup\$ Are you able to externally monitor the traffic so you know that it was fully sent? \$\endgroup\$ – Annie Sep 12 '18 at 19:35
  • \$\begingroup\$ @Tony EE rocketscientist , the error flags are 0. The TX interrupt handler is called, the DMA counter of the transferred bytes was reduced to zero (see in the debugger), that is, the DMA transmitted all 1029 bytes to the periphary. Do you think the last byte did not come out of the shift register? In parallel with reading from the flash I transfer the data to the display. But it's from another buffer and another DMA channel. Can it influence? \$\endgroup\$ – avg33 Sep 12 '18 at 21:36
  • \$\begingroup\$ @Annie in the debugger, I see that the buffer from the flash reads what it should. But there is no last byte. All that I read, I display on the display. And this is correct information. But data transactions where the last byte did not come can not be displayed \$\endgroup\$ – avg33 Sep 12 '18 at 21:45
0
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ 1. yes, but, judging by the description of the USART, nothing prevents using it for SPI; 2. code examples here cypress.com/file/220826/download Page 21-22 is an example of DMA transfer. Unfortunately there are no examples for reading and passing about SPI, but my code is written by analogy. Except that I do not disable global interrupts at the time of DMA initialization; 3. this is a flash S25FL256S cypress.com/file/177966/download \$\endgroup\$ – avg33 Sep 13 '18 at 9:00
  • \$\begingroup\$ I changed the code and it seems the error has disappeared. I changed the DMA channels (more in the header). How do you think, how can this influence? \$\endgroup\$ – avg33 Sep 13 '18 at 9:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.