I'm using the RT1052 MCU
Currently we want to use PIT to trigger DMA, which receives LPSPI data. However, after trying some configurations, this function is not implemented (PIT does not trigger DMA, LPSPI does not generate any waveform). Is there any relevant example for reference?
RT1050 SDK sample also did not find a corresponding sample program.
我抛砖引玉编写了下面二个例程,并通过了实际测试。
Hi.
I used SDK_2_13_0_MIMXRT1052xxxxB SDK,
Where is the DMA_SetupTransfer function
I searched the SDK and did not find this function
Hello @Hank888,
Where is the DMA_SetupTransfer function
You could use the configuration of the lpspi_edma_b2b_transfer_master example to configure and initialize the EDMA.
/*DMA Mux setting and EDMA init*/
DMAMUX_Init(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE);
DMAMUX_SetSource(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE,EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL,EXAMPLE_LPSPI_MASTER_DMA_RX_REQUEST_SOURCE);
DMAMUX_EnableChannel(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE,EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
EDMA_GetDefaultConfig(&userConfig);
EDMA_Init(EXAMPLE_LPSPI_MASTER_DMA_BASE, &userConfig);
[Code snippet of lpspi_edma_b2b_transfer_master.c]
Best regards, Raul.
Could you please help me see what's wrong
The PIT cannot trigger the DMA module to perform the send/receive action of LPSPI
/* DMA MUX init*/
DMAMUX_Init(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE);
// Close RX channel
DMAMUX_DisableChannel(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
DMAMUX_DisablePeriodTrigger(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
DMAMUX_EnableAlwaysOn(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL, false);
// Close TX channel
DMAMUX_DisableChannel(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);
DMAMUX_DisablePeriodTrigger(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);
DMAMUX_EnableAlwaysOn(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL, false);
// Initialize EMDA
EDMA_GetDefaultConfig(&userConfig);
EDMA_Init(EXAMPLE_LPSPI_MASTER_DMA_BASE, &userConfig);
// Initialize LPSPI
LPSPI_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate = TRANSFER_BAUDRATE;
masterConfig.whichPcs = EXAMPLE_LPSPI_MASTER_PCS_FOR_INIT;
masterConfig.pcsToSckDelayInNanoSec = 100;
masterConfig.lastSckToPcsDelayInNanoSec = 100;
masterConfig.betweenTransferDelayInNanoSec = 0;
srcClock_Hz = 105600000UL;
LPSPI_Deinit(EXAMPLE_LPSPI_MASTER_BASEADDR);
LPSPI_MasterInit(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterConfig, srcClock_Hz);
//
memset(&(lpspiEdmaMasterRxRegToRxDataHandle), 0, sizeof(lpspiEdmaMasterRxRegToRxDataHandle));
memset(&(lpspiEdmaMasterTxDataToTxRegHandle), 0, sizeof(lpspiEdmaMasterTxDataToTxRegHandle));
//
EDMA_CreateHandle(&(lpspiEdmaMasterRxRegToRxDataHandle), EXAMPLE_LPSPI_MASTER_DMA_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
EDMA_CreateHandle(&(lpspiEdmaMasterTxDataToTxRegHandle), EXAMPLE_LPSPI_MASTER_DMA_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);
#if defined(FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) && FSL_FEATURE_EDMA_HAS_CHANNEL_MUX
EDMA_SetChannelMux(EXAMPLE_LPSPI_MASTER_DMA_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL, DEMO_LPSPI_TRANSMIT_EDMA_CHANNEL);
EDMA_SetChannelMux(EXAMPLE_LPSPI_MASTER_DMA_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL, DEMO_LPSPI_RECEIVE_EDMA_CHANNEL);
#endif
LPSPI_MasterTransferCreateHandleEDMA(EXAMPLE_LPSPI_MASTER_BASEADDR, &g_m_edma_handle, LPSPI_MasterUserCallback, NULL, &lpspiEdmaMasterRxRegToRxDataHandle, &lpspiEdmaMasterTxDataToTxRegHandle);
//Initialize PIT
const pit_config_t PIT_config = {
.enableRunInDebug = false,
};
const uint32_t count = (20 * 1000) / (1 * 1000 * 1000 * 1000 / 75000000); // 20us
PIT_Init(PIT, &PIT_config);
PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, count);
PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, count);
PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, count);
PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, count);
/* Start channel 0. */
PIT_StartTimer(PIT, kPIT_Chnl_0);
PIT_StartTimer(PIT, kPIT_Chnl_1);
PIT_StartTimer(PIT, kPIT_Chnl_2);
PIT_StartTimer(PIT, kPIT_Chnl_3);
// Set source and enable periodic triggering
DMAMUX_SetSource(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL, EXAMPLE_LPSPI_MASTER_DMA_RX_REQUEST_SOURCE);
DMAMUX_EnablePeriodTrigger(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
// DMAMUX_EnableAlwaysOn(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL, true);
DMAMUX_EnableChannel(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
//
DMAMUX_SetSource(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL, EXAMPLE_LPSPI_MASTER_DMA_TX_REQUEST_SOURCE);
DMAMUX_EnablePeriodTrigger(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);
DMAMUX_EnableChannel(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);
Hello @Hank888,
First of all, we apologize for taking too much time to answer you.
Looking at your code and i.MX RT1050 Processor Reference Manual. Chapter 5. Direct Memory Access Multiplexer (DMAMUX). Section 5.5.1. Enabling and configuring sources, we noticed that to enable a source with periodic triggering you should follow the next steps:
[i.MX RT1050 RM. Section 5.5.1. Enabling and configuring sources]
With the help of pit and lpspi_edma_b2b_transfer_master examples, using your code, and the mentioned steps above, you could try writing something similar to the following to configure the PIT triggering the DMA + LPSPI:
/* DMA MUX init*/
DMAMUX_Init(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE);
// Enable periodic triggering
DMAMUX_EnablePeriodTrigger(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
DMAMUX_EnableChannel(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
DMAMUX_EnablePeriodTrigger(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);
DMAMUX_EnableChannel(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);
//Initialize PIT
const pit_config_t PIT_config = {
.enableRunInDebug = false,
};
const uint32_t count = (20 * 1000) / (1 * 1000 * 1000 * 1000 / 75000000); // 20us
PIT_Init(PIT, &PIT_config);
PIT_SetTimerPeriod(PIT, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL, count);
PIT_SetTimerPeriod(PIT, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL, count);
//Set source of DMAMUX
DMAMUX_SetSource(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL, EXAMPLE_LPSPI_MASTER_DMA_RX_REQUEST_SOURCE);
DMAMUX_SetSource(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL, EXAMPLE_LPSPI_MASTER_DMA_TX_REQUEST_SOURCE);
// Initialize EMDA
EDMA_GetDefaultConfig(&userConfig);
EDMA_Init(EXAMPLE_LPSPI_MASTER_DMA_BASE, &userConfig);
// Initialize LPSPI
LPSPI_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate = TRANSFER_BAUDRATE;
masterConfig.whichPcs = EXAMPLE_LPSPI_MASTER_PCS_FOR_INIT;
masterConfig.pcsToSckDelayInNanoSec = 100;
masterConfig.lastSckToPcsDelayInNanoSec = 100;
masterConfig.betweenTransferDelayInNanoSec = 0;
srcClock_Hz = 105600000UL;
LPSPI_Deinit(EXAMPLE_LPSPI_MASTER_BASEADDR);
LPSPI_MasterInit(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterConfig, srcClock_Hz);
//
memset(&(lpspiEdmaMasterRxRegToRxDataHandle), 0, sizeof(lpspiEdmaMasterRxRegToRxDataHandle));
memset(&(lpspiEdmaMasterTxDataToTxRegHandle), 0, sizeof(lpspiEdmaMasterTxDataToTxRegHandle));
//
EDMA_CreateHandle(&(lpspiEdmaMasterRxRegToRxDataHandle), EXAMPLE_LPSPI_MASTER_DMA_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
EDMA_CreateHandle(&(lpspiEdmaMasterTxDataToTxRegHandle), EXAMPLE_LPSPI_MASTER_DMA_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);
#if defined(FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) && FSL_FEATURE_EDMA_HAS_CHANNEL_MUX
EDMA_SetChannelMux(EXAMPLE_LPSPI_MASTER_DMA_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL, DEMO_LPSPI_TRANSMIT_EDMA_CHANNEL);
EDMA_SetChannelMux(EXAMPLE_LPSPI_MASTER_DMA_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL, DEMO_LPSPI_RECEIVE_EDMA_CHANNEL);
#endif
LPSPI_MasterTransferCreateHandleEDMA(EXAMPLE_LPSPI_MASTER_BASEADDR, &g_m_edma_handle, LPSPI_MasterUserCallback, NULL, &lpspiEdmaMasterRxRegToRxDataHandle, &lpspiEdmaMasterTxDataToTxRegHandle);
//Start PIT
PIT_StartTimer(PIT, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
PIT_StartTimer(PIT, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);
Could you please try this arrangement in your code?
Best regards, Raul.
Hi @Hank888 It seems like you're trying to use the Periodic Interrupt Timer (PIT) to trigger Direct Memory Access (DMA) for receiving Low Power Serial Peripheral Interface (LPSPI) data on the RT1052 MCU. While there may not be a direct example in the RT1050 SDK, you can still achieve this by configuring the PIT, DMA, and LPSPI modules correctly.
Firstly, you need to initialize the PIT. You can use the PIT_Init() function to do this. Here is an example:
PIT_Init(PIT, &pitConfig);
Next, you need to set up the DMA channel to be triggered by the PIT. You can use the DMA_SetupTransfer() function to do this. Here is an example:
DMA_SetupTransfer(DMA0, &transferConfig);
Finally, you need to set up the LPSPI to receive data. You can use the LPSPI_MasterTransferCreateHandle() and LPSPI_MasterTransferNonBlocking() functions to do this. Here is an example:
LPSPI_MasterTransferCreateHandle(LPSPI0, &g_m_handle, LPSPI_MasterUserCallback, NULL); LPSPI_MasterTransferNonBlocking(LPSPI0, &g_m_handle, &transfer);
Remember to enable the PIT after all the configurations. You can use the PIT_StartTimer() function to do this. Here is an example:
PIT_StartTimer(PIT, kPIT_Chnl_0);
Please note that you need to replace the parameters in the functions with your own configurations. You can find more information about these functions in the SDK Driver Usage Tips article.
Also, make sure that the PIT, DMA, and LPSPI modules are enabled in the clock gate control. You can use the CLOCK_EnableClock() function to do this. Here is an example:
CLOCK_EnableClock(kCLOCK_Pit); CLOCK_EnableClock(kCLOCK_Dma0); CLOCK_EnableClock(kCLOCK_Lpspi0);
Regards,
Prakash
Hi @prakashram72 and @Hank888 and @RaRo,
I'm having a similar issue with the iMXRT1062. Were you ever able to get this working?
Thanks for any advice,
Matt
Just an update, I was able to get this working.