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\$
11
  • 4
    \$\begingroup\$ Please add information about what microcontroller, other hardware and development environment you are using. And please add the relevant code. \$\endgroup\$ Commented Sep 12, 2018 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\$ Commented Sep 12, 2018 at 17:57
  • \$\begingroup\$ Are you able to externally monitor the traffic so you know that it was fully sent? \$\endgroup\$ Commented Sep 12, 2018 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\$ Commented Sep 12, 2018 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\$ Commented Sep 12, 2018 at 21:45

1 Answer 1

1
\$\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\$
2
  • \$\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\$ Commented Sep 13, 2018 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\$ Commented Sep 13, 2018 at 9:09

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.