How does RT1050 use PIT to trigger DMA, which receives SPI data

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

How does RT1050 use PIT to trigger DMA, which receives SPI data

3,125 次查看
Hank888
Contributor II

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.

标签 (1)
标记 (4)
0 项奖励
回复
8 回复数

2,391 次查看
shaozhongliangs
NXP Employee
NXP Employee

我抛砖引玉编写了下面二个例程,并通过了实际测试。

1.     PIT中断直接触发DMA SPI传输。在SDK的lpspi_edma_b2b_transfer_master例程的基础上增加PIT触发DMA的代码。关键代码如下,PIT模块可以触发头四路DMA通路,并且每个PIT通道对应相应的DMAMux请求路由器(60~63)。只有DMA通道的前四路通道(Channel0~3)具有周期触发DMA的功能。
   DMAMUX_EnableAlwaysOn(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, 0, true);
   DMAMUX_SetSource(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, 0, 60);
   DMAMUX_EnablePeriodTrigger(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, 0);
   DMAMUX_EnableChannel(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, 0);

 

PIT启动后,按设定的定时周期触发一次DMA传输。可以在DMA Finished完成中断ISR处理一组ADC数据,并重新设置DMA的收发buffer。

 

2.     PIT周期触发 DMA memory to peripheral传输。在SDK例程lpspi_interrupt_b2b_master代码基础上,通过PIT DMA定期把数据传输到LPSPIx->TDR寄存器,即PIT DMA代替LPSPI_WriteData( )函数,不需要CPU参与。在lpspi的Rx FiFo满中断ISR中处理一组ADC数据。
0 项奖励
回复

3,066 次查看
Hank888
Contributor II

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

0 项奖励
回复

3,053 次查看
RaRo
NXP TechSupport
NXP TechSupport

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.

0 项奖励
回复

3,037 次查看
Hank888
Contributor II

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);
 

 

标记 (1)
0 项奖励
回复

2,919 次查看
RaRo
NXP TechSupport
NXP TechSupport

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:

RaulRomero_0-1689967315944.png

[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.

0 项奖励
回复

3,102 次查看
prakashram72
Contributor III

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

0 项奖励
回复

2,697 次查看
matt0x000C
Contributor II

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

 

0 项奖励
回复

2,344 次查看
matt0x000C
Contributor II

Just an update, I was able to get this working

0 项奖励
回复