This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SPI Compatibility Mode and DMA

Hello,

I have a question. I've been reading about the DMA module and the SPi module for a while, and I have 2 questions.

1 - According to something I read in a question posted here, the SPI module, in compatibility mode, only supports 16 bit transfers with DMA (can't find the link to the question posted).

2 - Is it possible to use the SPI module receiving separate bytes and the after reading some of them start receiving a frame with the DMA module? Maybe this question is a little foggy. Here's my problem: My hercules board would send a request for a slave. The response for this request varies according to what the slave has, sometimes it could have 50 bytes, and sometimes it could have 1kB, so I would need a way to read the first few bytes like a normal byte to byte transfer and then adjust the DMA receive frame size, according to the information received. Also the package sent to the slave will vary, although not as much as the slave's response.

For example:The master would send a request and the slave needs to respond with 100 frames of 512 bytes, but the frame size is in the 2nd byte (the last frame may have only 10 bytes) and the total size is in the 3rd 4th and 5th byte (lots of data).

PS: I've never needed to work with the DMA module, so I really have no idea if some of these thing I want to do are possible

  • Pablo,

    SPI char length is 2-16 bits, and In compatability mode SPI RX data into SPIBUF and generates RXDMA request (while multi-buffer mode generates a DMA reaquest when RX data into a TG data slot.) So it make sense to transfer just one 16 bit on a RX event in compatability mode. SPI module itself don't have any restriction on how many transfers you do with one RX DMA event.

    To your design issue you could

    1. Setup DMA to do 16 bits per frame and size of your message header (5 in your case) to be the block size. Generate an interrupt on BTC (or on Last Frame started which will give you a head start).

    2. In your interrupt routine decode your header info and alter # of frames for your block and re-enable dma channel and BTC to receive all your message and get interrupted at the end of the message.

    Note: In Compatability mode you have only 1 SPI-char time to spare for the ISR, If SPI receives the third char the first one will be overwritten. Why not use multi-buffer mode?

  • I'm using it to communicate to another microcontroller running as slave which is running as a coprocessor to the main board. If that isn't an issue, then I'll get on wirting the MIBSPI drivers.

    This coprocessor, will be the one responsible for making the hercules microcontroller communicate with the outsied world. This means that many different types of data must be able to pass from one side to another. The thing is that sometimes the coprocessor will hace huge amounts of data to pass onto the other side, depending on the master's request.

    Because of compatibility issues an 8 bit transfer must be used. But heres's the thing. The master would send a 4 - 10 bytes message to the slave, and the slave's response would vary a lot. From 20 bytes to 5MB (sent in frames of 1kB max). The master would never have to send something much larger than 10 bytes. Also this must not generate an interrupt (again .. compatibility reasons). 

    So, is it possible to receive unknown amounts of data via DMA? That's why I wanted to receive 5 bytes the "old fashioned way" from the slave, without using DMA, so that I could know the frame size of the remaining package, and adjust to it in real time, without using any sort of interruptions.

    It's confusing, I know. It's not ideal, I know. But That's what I gotta work with. At the moment I'm doing it all via simple byte transfers, but i thought that there must be another way to do this, a better way, and my conclusion was DMA, but, as stated before, I've never used it and because of that I have many questions.

  • Pablo,

    I'm not aware of any way to automatically extract some count from the receive data stream and move this to the DMA control packet's element or frame count without the intervention of a processor.   So I think the answer from J Joson is correct. 

    Thanks J for answering this one.

     

  • My slave is a microcontroller from ST. 

    2 more questions:

    1 - Could I receive a few bytes in a normal SPi byte transfer, in order to set how many bytes will be sent afterwards via a DMA transfer from the slave? By that it means it would receive the first few bytes of the protocol to adjust the DMA for reception. I think it's possible, but I'm a bit apprehensive about this approach. It seems to be feasable, but, if possible I'd like to hear someone say it might be possible. 

    2 - Can I use DMA on the slave, but not use it on the master? Can I receive a full transfer from the slave, which is using DMA,  using just the receive_byte() function? Is it necessary for me to configure DMA on both sides?

  • Pablo,

    The best use of DMA is to service a peripheral with little cpu involvement. For example you can enable “RX event” to trigger a DMA request that transfer the received data to a circular buffer and the cpu can process that data in the background loop. Similarly you can fill up a response in a buffer and enable “TX empty” event to trigger a DMA request to move that data out without further cpu involvement. You can do TX/RX or both using DMA. DMA can be used to create a FIFO that can be sized and placed to meet your need.

    If RX->DMA transfer data into circular buffer one data byte/word at a time, you don't have to worry about adjusting the DMA transfer block size. Set the block size to the size of the buffer and set DMA control packet to wrap to the beginning after filling the block. Your background task can decode the response received in the buffer and can prep the response, setup TX circular buffer and enable TX->DMA for the next access.

    If you are trying to achieve a full duplex communication over SPI, it can get tricky- Normally SPI master transmit a command followed by ‘n’ dummy tx to read the response from slave.

    Good luck,

    Joe

     

  • I understand what you are saying, but I have many requirements for the project. One of them is that the slave cannot spend a long time processing/sending a block of more than 1kB, since it has many important tasks at hand, that's why I was thinking of a little synchronizing between master and slave, before initiating a DMA transfer via the slave device.

    That's why I wanted to know if it is possible to use DMA only on one side (slave), and on the other (master) use a regular byte transfer. The thing for this is that the master isn't subject to the same restrictions as the slave.

    I'll get on with some experiments and then post the results here.