eDMA trigger from GPIO

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

eDMA trigger from GPIO

Jump to solution
2,876 Views
tbiberdorf
Contributor IV

I'm using MCUXpresso IDE v10.1.0 and a FRDM-K64 development board.

I would like to have a DMA memory to memory operation trigger from SW3 event.

I have a github project created that seems to partial work:

GitHub - tsbiberdorf/SPI_ScatterGather: FRDM-K64F sample code for SPI DMAMUX Scatter Gather  

SHA Id: fbedd903fd191013ef8aba7d4587874ac92f5f5b

The project has a DMA event happening on the first press of SW3, then it required 4 SW3 presses, followed by 4 more SW3 presses.  This all matches the TCD operations I have programmed in the method: circularBufferScatterGather()

The part that has me frustrated is that I cannot get the loop to repeat again.  What setting or API call do I have to make to have another loop of SW3 presses of 1/4/4 again?

I believe I need to request a EDMA_TcdSetChannelLink() to link the major scatter/gather operation back to the start, but the call does not work and I'm not sure why.

I will eventually want this operation to work on SPI communication, but to test all available SDK API calls I'm starting with memory to memory operations.

Thanks.

Terry

0 Kudos
1 Solution
2,267 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi Terry

This question was answered internally;

If so, you can specify the number of bytes to transfer in each DMA request in the EDMA_PrepareTransfer function in the bytesEachRequest argument, so your code would be something like:

    EDMA_PrepareTransfer(&transferConfig,
            srcAddr,
            sizeof(srcAddr[0]),
            destAddr,
            sizeof(destAddr[0]),
            4 * sizeof(srcAddr[0]), // 4 * 4 bytes =  16 bytes
            sizeof(srcAddr),
            kEDMA_MemoryToMemory);

But if you refer to perfom a dma transfer of 4 bytes data each time there is a request by the falling-edge in the pin (PTA4), then my code do this. Each time that you press the SW3, it will trigger a data (4 bytes) transfer, as the size buffer (sizeof(srcAddr)) is 4 data, then after 4 requests, it will go to the callback and it will start again.

Now, I have checked your application, if you require a SPI data transfer, then you need a peripheral to memory transfer type, and manage the request by SPI RX. Still you don't need to implement scatter gatter feature. let me explain.

Your will generate DataReady signals at a periodic time, this signal have to inform your K64 that it has to start transfer data, so K64 has to start the communication, and just until data has arrived to SPI data buffer (SPIx_RXFRn), your SPI will generate a RX FIFO drain request that will trigger DMA, and this will transfer data from SPI data buffer to internal memory (so kEDMA_PeripheralToMemory).

This implementation is already in the fsl_edma_spi driver, which you can see in the dspi_edma_b2b_transfer_master example. The only part here that you need to implement is to manage the DataReady signal, but this signal can be managed as a GPIO interrupt and inside the handler, put a Master Start transfer.


Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

View solution in original post

15 Replies
2,267 Views
tbiberdorf
Contributor IV

The code repository has been cleaned up and can now be found at the following link:

https://github.com/tsbiberdorf/dmaSpiOperation.git
0 Kudos
2,267 Views
tbiberdorf
Contributor IV

The part that I want to improve on it to have my data ready signal trigger the DMA transfer.  The current code has the GPIO interrupt calling the DSPI_MasterTransferEDMA() API.  When I measure this code I find that it's taking more than 31uS to complete.

pastedImage_1.png

How do I reduce this time?

0 Kudos
2,267 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi Terry Biberdorf

First of all, I would like to clarify that the latency that you get in your code isn't due to the interruption of the GPIO, so it will not help to change the GPIO part to trigger a DMA request; you cannot trigger SPI transfer with a GPIO DMA requests.

As I can see in your code, the biggest time-consuming part is inside DSPI_MasterTransferEDMA() API, it has to prepare all the DMA and SPI setup to start SPI transfers.

So, I think that you have 2 options here:

1. As you see here in the DSPI_MasterTransferEDMa API, you have all the spi setup, including prepare tcd and buffers; so one option is not to use fsl_edma_dspi driver and using fsl_edma and fsl_dspi drivers setup what you need and in the interruption, start SPI transfers. For this, you could Base your application in the fsl_edma_dspi.

In this case you will have to prepare all tcd and spi setup, and only start the SPI transfer inside the GPIO interruption (Data ready), using DSPI_StartTransfer API for example.

2. The second option is basically the same as the first, prepare tcd and data before getting GPIO interrupt, but modifying fsl_edma_dspi file.

Preparing all the SPI and DMA transfer could be done using DSPI_MasterTransferEDMA but without the start transfer part. For this case, you could comment the DSPI_StartTransfer line in the DSPI_MasterTransferEDMA function, so it will not start transfer after you call it.

Once that you get the GPIO interruption, call the DSPI_StartTransfer.

Hope this could help you.

Best regards

Jorge Alcala

0 Kudos
2,267 Views
tbiberdorf
Contributor IV

Hello Jorge

From your suggestion, if I remove the DSPI_StartTransfer from the DSPI_MasterTransferEDMA and name it DSPI_MasterTransferEDMANoStart as you suggest in option 2.

In my code should I only have to call DSPI_MasterTransferEDMANoStart once to set all registers.

Then in my GPIO IRQ I can continue to call DSPI_StartTransfer on each data ready interrupt without having to re-call the DSPI_MasterTransferEDMANoStart?

Thanks

Terry

0 Kudos
2,267 Views
tbiberdorf
Contributor IV

Hello Jorge

I just tested my code with the DSPI_MasterTransferEDMANoStart, and it seems that I need to perform this logic on every eDMA transfer.  So the time consumed is ether at the point of the trigger IRQ, or it is after the DSPI_MasterUserCallback is called.

My understanding with the eDMA transfer is that when the TCD last major loop has been performed, that it can return back to the first dma operation so that there will be no need to re-configure all operations on every event.

The part that I'm very confused on is that there are no working examples on how to call the various APIs in the fsl_edma class.  Even the existing fsl_ code (eg. fsl_dspi_edma) does not make use of it.  The level of documentation is also very slim.  I can find documents that describe that it can be done but no examples on it.

Can you provide a link to an example code that will perform all the DSPI_MasterTransferEDMA() work but using only fsl_edma() API calls?

Terry

0 Kudos
2,267 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi Terry

Sorry for the late in the reply. After some tests and checking the code, we have noticed that in order to reduce the time that you mentioned, it is needed to reconfigure all the logic in the DSPI_MasterTransferEDMAStart API, which is not recommended, it could affect other parts of the code, and it should behave in a very custom way.

We have concluded that the best approach to do this will have to create the application with fsl_edma and fsl_dspi and use fsl_edma_dspi only as a reference. As you can see in the code, it was implemented 3 channels of DMA, one for Rx->Internal_buffer, one for Internal_buffer->Tx and one last channel used to prepare the next data with data and the command to send. In this driver, it is implemented a linking channel from the second channel to the third channel and a scatter gatter for the "last command" in the third channel. So it is only needed a way to recharge the first and the third command (which are the ones that changed).

Hope this information could help you.

Best regards

Jorge Alcala

0 Kudos
2,267 Views
tbiberdorf
Contributor IV

Hello Jorge:

You make a reference to code that I can analyze, but there are no links to example code.  Can you provide a link or update the github project with this example?

Thanks

Terry

0 Kudos
2,267 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi Terry

Sorry for the confusion I might have caused. I wasn't making a reference to a code, the recommendation I gave you was to refer the methodology that the driver fsl_dspi_edma implement the dspi communication.

As I mentioned, in the driver there is the implementation of 3 DMA channels, one for RX, and 2 for TX.

Also, there was the need to implement the linking channel and scatter gatter in the DSPI communication, you will need to implement the recharge of these TCD channels to achieve what you are trying to do because every transfer of data in the communication will change addresses and flags.

Best regards

Jorge Alcala

0 Kudos
2,267 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi Terry

We still are looking for the correct method to reduce this delay between the interruption and the start of the transmissions.
We have found the root cause of the problem, edma driver needs to reload tcd to restart the transmission , this is the part where most of the time is spent  when using the StartTransmission API.

We are currently looking for the most appropriate way to change this; will continue investigating and performing some tests and we will update you as soon as we discover something.

Regards

0 Kudos
2,267 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi Terry

I still working on this, I have made some tests and try some setups. As you mentioned there shouldn't be a need to reconfigure the TCD once it has been correctly loaded, but I will need some time to check this and find the solution, as soon as we find something I will share the code.

Regards

Jorge Alcala

0 Kudos
2,267 Views
tbiberdorf
Contributor IV

Can someone provide an MCXpresso API SDK example of SPI transfer with eDMA what will continue to cycle from a GPIO trigger?

pastedImage_1.png

So what I'm attempting to do is develop a SPI communicate interface that after the slave device is initialized, the slave device will continue to trigger DR (Data Ready) pulses to indicate that data is ready to be read.  I would like to have my K64 read this pulse event from a GPIO Interrupt. I would like to have the K64 eDMA transfer the data from the slave device on each of these IRQ events.

My working github code example listed above has this working with interrupt handling.  I would like to have it operate from eDMA to reduce the overhead.

Thanks

Terry

0 Kudos
2,268 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi Terry

This question was answered internally;

If so, you can specify the number of bytes to transfer in each DMA request in the EDMA_PrepareTransfer function in the bytesEachRequest argument, so your code would be something like:

    EDMA_PrepareTransfer(&transferConfig,
            srcAddr,
            sizeof(srcAddr[0]),
            destAddr,
            sizeof(destAddr[0]),
            4 * sizeof(srcAddr[0]), // 4 * 4 bytes =  16 bytes
            sizeof(srcAddr),
            kEDMA_MemoryToMemory);

But if you refer to perfom a dma transfer of 4 bytes data each time there is a request by the falling-edge in the pin (PTA4), then my code do this. Each time that you press the SW3, it will trigger a data (4 bytes) transfer, as the size buffer (sizeof(srcAddr)) is 4 data, then after 4 requests, it will go to the callback and it will start again.

Now, I have checked your application, if you require a SPI data transfer, then you need a peripheral to memory transfer type, and manage the request by SPI RX. Still you don't need to implement scatter gatter feature. let me explain.

Your will generate DataReady signals at a periodic time, this signal have to inform your K64 that it has to start transfer data, so K64 has to start the communication, and just until data has arrived to SPI data buffer (SPIx_RXFRn), your SPI will generate a RX FIFO drain request that will trigger DMA, and this will transfer data from SPI data buffer to internal memory (so kEDMA_PeripheralToMemory).

This implementation is already in the fsl_edma_spi driver, which you can see in the dspi_edma_b2b_transfer_master example. The only part here that you need to implement is to manage the DataReady signal, but this signal can be managed as a GPIO interrupt and inside the handler, put a Master Start transfer.


Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

2,267 Views
tbiberdorf
Contributor IV

I'm still trying to work this to best suit my situation and it's not working.

I have code now closely using the fsl_dspi_edma.c API calls.

I also have my code performing a DMA transfer but it will only trigger when I call the DSPI_MasterTransferEDMA() API from inside my GPIO Interrupt handler.

Now I want the interrupt to trigger the DMA operation by configuring it with the kPORT_DMARisingEdge instead of kPORT_InterruptRisingEdge.  Currently I have the IRQ method making a call to DSPI_MasterTransferEDMA() on every instance of my GPIO interrupt.  This is very time wasteful as this API take longer to run then the total time of the SPI transfer.

It gets very confusing with your descriptions above as we're crossing between API's from the fsl_dspi_edmac API and fsl_edma API.

Many of the calls using by fsl_dspi_edmac do not use the fsl_edma API which makes following the code very confusing and frustrating.

Can someone please provide a code example using only APIs from the fsl_edma API file to perform the peripheral to memory eDMA operation from a GPIO?

Thanks.

0 Kudos
2,267 Views
tbiberdorf
Contributor IV

can you please provide a link to the project referenced: dspi_edma_b2b_transfer_master 

The only references that I have to work from are the SDK examples provided: frdmk64f_driver_examples_edma_memory_to_memory

0 Kudos
2,267 Views
tbiberdorf
Contributor IV

I found the example project.  It turns out that I was working from an older SDK build that did not have that project included.

0 Kudos