K64 as SPI master with DMA, TX only, don't need RX

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

K64 as SPI master with DMA, TX only, don't need RX

Jump to solution
1,040 Views
gerhardheinzel
Contributor I

Hi, I want to use K64 to send lots of data to a display with SPI. It works using polling but is too slow, and moreover the CPU also has other stuff to do. So I want to use DMA instead, using large buffers (~kbytes) at a time. However, the example provided in sdk/boards/frdmk64f/driver_examples/dspi/edma_transfer activates DMA for both TX and RX directions. But I don't want any activity for RX since no useful data is coming in. So I want to avoid the overhead of assigning an RX buffer that I don't need and any DMA activity associated with RX, but instead simply ignore RX. How can I achieve that?

Many thanks,

Gerhard

0 Kudos
1 Solution
1,010 Views
myke_predko
Senior Contributor III

@gerhardheinzel 

That's the trick.  

The issue isn't that we don't want SPI RX - SPI will always receive data when it's working (ie transmitting) - we just don't want to store the incoming data.  

myke

View solution in original post

0 Kudos
4 Replies
1,034 Views
myke_predko
Senior Contributor III

Hey @gerhardheinzel 

I'm doing exactly what you are trying to do with an OLED controlled by an SSD1322.  

I started with the dspi_edma_b2b_transfer code and focused on the transmission (master) side of things (which ignores the receive and does not require an SIN pin or receive buffer).  When I specify the Kinetis pins using the Mux, I ignore the SIN pin (and actually use it for something else).  Going further, I updated the transmission callback so that after the block of data (I chose 510 bytes as a maximum) had been transmitted if there was more data to send, I would restart the transmission for the next block of data until it was all done.  

[EDIT: Added SPI Code]

I've attached my SPI code to this post - looking at it again, the "OLEDSPIProcs.c/.h" are not all that receiving device specific (when I wrote the post originally, I thought they were). 

To setup the port, called the unfortunately named "OLEDSPIInt" method to initialize the port.  I specify the pins/mux in the MCUXpresso Pin Wizard.   At the end of the method, you'll see a couple of pin writes which are specific to the SD1322 (which probably should be moved outside the method to make it more generic.  You'll have to check your clocks as well but if you look at my code as well as the SDK example(s) you shouldn't have any issues getting it working. 

With the SPI port initialized, you can send data through the SPI port by calling "OLEDSPI_BulkTransfer" after setting up the variables.  You must send at least two bytes (tthere is no maximum) so if you have a single byte transfer, you will need to start off with a byte that the receiver will ignore. 

I recommend calling OLEDSPI_BulkTransfer using something like:

  for (; !oledSPITransferCompleted;) { }
oledSPITransferCompleted = FALSE;

oledSPIXfer.txData = oledSPICmdBuffer;
for (i = 0, oledSPIXfer.daaSize = numberofBytes; numberOfBytes > i; ++i) {
oledSPICmdBuffer[i] = sourceData[i];
}

OLEDSPI_BulkTransfer();

// Note the start which waits for the previous transfer to complete before starting the next one

I should also point out that EDMA needs at least two transfers - if you're going to send one, find a byte that the receiver will ignore with the second one being the required one to send.  

Looking over the code, it could be written better (and used some better method names), but I was doing a lot of experimenting trying to get things working right (and fast).  I can say that the code is rock solid running at 10Mbps.  It was written for FreeRTOS, but the assumption was that display updates had to happen as fast as possible which is why I do not put in a delay (to force a task swap) when sending multiple instructions to the display.  

I'm happy to answer some questions, but please understand that I'm not in a position nor do I have the time to support you or modify the code for your application. 

As a suggestion, you may want to first get byte sends working first, to ensure you understand the operation of your peripheral, before blasting data at it using the SPI.  

Goodl luck!

myke

0 Kudos
1,021 Views
gerhardheinzel
Contributor I

Dear @myke_predko 

Many thanks! That is exactly what I was looking for. My device is of course different (ILI9341) but I already succeed in talking to it with the slow SPI methods, so the DMA init part what what as I was lacking.

Cheers,

Gerhard

 

 

0 Kudos
1,013 Views
gerhardheinzel
Contributor I

Dear@myke_predko 

after looking at your code (from which I threw out things that I don't need) I am still confused.

Even though I believe that both of us do neither need not want any DMA activity for the RX direction,
there is still code referring to RX like

#define LCD_SPI_DMA_RX_REQUEST_SOURCE kDmaRequestMux0SPI1

DMAMUX_SetSource (LCD_SPI_DMA_MUX_BASEADDR, masterRxChannel, LCD_SPI_DMA_RX_REQUEST_SOURCE);
DMAMUX_EnableChannel (LCD_SPI_DMA_MUX_BASEADDR, masterRxChannel);
...
EDMA_CreateHandle (&oledDSPIEdmaMasterRxRegToRxDataHandle, LCD_SPI_DMA_BASEADDR, masterRxChannel);

-------------

The only places where I could guess the RX DMA is de-activated are the three NULL pointers in the following:

dspi_transfer_t oledSPIXfer = {.rxData = NULL, .configFlags = kDSPI_MasterCtar0 | kDSPI_MasterPcs0 | kDSPI_MasterPcsContinuous};

dspi_transfer_t actualOLEDSPIXfer = {.rxData = NULL,.configFlags = kDSPI_MasterCtar0 | kDSPI_MasterPcs0 | kDSPI_MasterPcsContinuous};

DSPI_MasterTransferCreateHandleEDMA (LCD_SPI_BASEADDR, &oledDSPIEDMAMasterHandle, OLEDDSPI_MasterEDMACallback, NULL, &oledDSPIEdmaMasterRxRegToRxDataHandle, &oledDSPIEdmaMasterTxDataToIntermediaryHandle, &oledDSPIEdmaMasterIntermediaryToTxRegHandle);

Is that the trick?

With best greetings
Gerhard

0 Kudos
1,011 Views
myke_predko
Senior Contributor III

@gerhardheinzel 

That's the trick.  

The issue isn't that we don't want SPI RX - SPI will always receive data when it's working (ie transmitting) - we just don't want to store the incoming data.  

myke

0 Kudos