Hello
I am using an i.MXRT1024 Evk and MCUxpresso for programming. I need to transfert several bytes from a LPSPI to memory every time a GPIO goes low. The process of the received bytes should be done in the DMA channel major loop interruption. The processor is running under FreeRTOS. I am not able to start the transfert nor fire the DMA channel interrupt from the GPIO ISR. Please find below what I discovered so far:
1) When I am starting the DMA transfert from a task, everything is fine. DMA transfer started and DMA interrupt fired. I am using the LPSPI_MasterTransferEDMALite(LPSPI3, &g_m_edma_handle, &eDMA_masterXfer); function
2) When I am starting the DMA transfert whithin the GPIO interrupt using LPSPI_MasterTransferEDMALite(LPSPI3, &g_m_edma_handle, &eDMA_masterXfer); the transfer is not taking place nor the interrupt
3) If I am using the code below extract everything is fine (transfer + completion interrupt) in a task but not within the GPIO interrupt. The transfer is started but not the major loop interrupt
DMA0->TCD[0].DADDR = 0x81E00000; //DADDR reset to beginning of Memory
EDMA_StartTransfer(g_m_edma_handle.edmaTxDataToTxRegHandle);
EDMA_StartTransfer(g_m_edma_handle.edmaRxRegToRxDataHandle);
LPSPI_EnableDMA(LPSPI3, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
Could you please help me in starting the DMA transfer within the interrupt ISR and
generating a DMA channel major loop interrupt after the transfer. Thanks in advance.
Best regards, Jérémy
Solved! Go to Solution.
Dear Mayliu
I finally found what was the problem. It came from the fact that I was mixing blocking SPI transfer and DMA transfer. My program is now working perfectly fine and I can switch on the fly between blocking and DMA transfer without problem.
Thanks a lot for letting me see some hope in solving my issue.
Best regards, Jérémy
Hi @jterrien ,
Thank you so much for your interest in our products and for using our community.
I did a test for you, I can start the DMA transfer within the interrupt ISR and generating a DMA channel major loop interrupt after the transfer.
I merge SDK demo "evkmimxrt1024_igpio_input_interrupt" and "evkmimxrt1024_lpspi_edma_b2b_transfer_master". I use MIMXRT1024-EVK board.
When I press SW4 button, in this GPIO IRQ Handler, call LPSPI_MasterTransferEDMALite function , then I can see that the program can enter LPSPI_MasterUserCallback callback function.
Wish it helps you.
If you still have question about it, please kindly let me know.
Wish you a nice day!
Best Regards
MayLiu
Dear MayLiu
Thanks a lot for your prompt reply. Unfortuneatly, it does not work in my program. I started from the example lwip_ipv4_ipv6_echo. What I discovered is that even if I start the transfer from another task the interrupt is not triggered as well. I can see the clock the spi toggling for the correct number of bytes (28 in my program) but the DONE bit in the TCD is never set and thus the interrupt is not fired. The same occure if I do the whole initialisation of DMAMUX, DMA and DMA channel (extract below) at each pin interrupt. I do not know if running FREERTOS might be the cause of the problem or not. Just in case if it can help I attached the main C and ADS1299_HAL files.
The start of the DMA transfert is done in the function ActivateDMA (ligne 490) of ADS1299_HAL.c.
The pin interrupt is handled in the function void GPIO1_Combined_16_31_IRQHandler(void) ligne 565 in the same file. It raises the NeedActivateDMA = 1; flag to signal to another task to call ActivateDMA().
Thanks for your help.
Best regards, Jérémy
This is the fonction ActivateDMA()
DMAMUX_Init(DMAMUX);
DMAMUX_SetSource(DMAMUX, LPSPI_MASTER_DMA_RX_CHANNEL, kDmaRequestMuxLPSPI3Rx);
DMAMUX_EnableChannel(DMAMUX, LPSPI_MASTER_DMA_RX_CHANNEL);
DMAMUX_SetSource(DMAMUX, LPSPI_MASTER_DMA_TX_CHANNEL, kDmaRequestMuxLPSPI3Tx);
DMAMUX_EnableChannel(DMAMUX, LPSPI_MASTER_DMA_TX_CHANNEL);
/* EDMA init*/
EDMA_GetDefaultConfig(&userConfig);
userConfig.enableDebugMode = true;
EDMA_Init(DMA0, &userConfig);
/*Set up lpspi master*/
memset(&(lpspiEdmaMasterRxRegToRxDataHandle), 0, sizeof(lpspiEdmaMasterRxRegToRxDataHandle));
memset(&(lpspiEdmaMasterTxDataToTxRegHandle), 0, sizeof(lpspiEdmaMasterTxDataToTxRegHandle));
EDMA_CreateHandle(&(lpspiEdmaMasterRxRegToRxDataHandle), DMA0, LPSPI_MASTER_DMA_RX_CHANNEL);
EDMA_CreateHandle(&(lpspiEdmaMasterTxDataToTxRegHandle), DMA0, LPSPI_MASTER_DMA_TX_CHANNEL);
LPSPI_MasterTransferCreateHandleEDMA(LPSPI3, &g_m_edma_handle, LPSPI_MasterUserCallback, NULL, &lpspiEdmaMasterRxRegToRxDataHandle, &lpspiEdmaMasterTxDataToTxRegHandle);
LPSPI_MasterTransferPrepareEDMALite(LPSPI3, &g_m_edma_handle, kLPSPI_MasterPcs0);
/* Start master transfer, receive data from slave */
eDMA_masterXfer.txData = NULL;
eDMA_masterXfer.rxData = eDMA_masterRxData;
eDMA_masterXfer.dataSize = 28;
CS1Low();
isTransferCompleted = false;
//Modifier to not generate transfer at spi level
LPSPI_MasterTransferEDMALite(LPSPI3, &g_m_edma_handle, &eDMA_masterXfer);
LPSPI_EnableDMA(LPSPI3, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
Please refer to my previous post, I am sure It can work.
When you can realize what I did, you can merge the code to your project.
Please try it.
Thanks
Dear Mayliu
I finally found what was the problem. It came from the fact that I was mixing blocking SPI transfer and DMA transfer. My program is now working perfectly fine and I can switch on the fly between blocking and DMA transfer without problem.
Thanks a lot for letting me see some hope in solving my issue.
Best regards, Jérémy