SPI linking to DMA Channel without trigger

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

SPI linking to DMA Channel without trigger

1,337 Views
shaileshnsec
Contributor II

Hi, 

We are working SPI DMA. As we know MKE15z is having 8 DMA channel with 59 sources. We can see example SDK_2_10_0_FRDM-KE15Z\boards\frdmke15z\driver_examples\lpspi\edma_b2b_transfer\master where SPI0 is linked to DMA channel 0 and channel 1 which is trigger based. But when I configure SPI0 DMA with channel 4 and 5 which not trigger based, it is not working. 

What all configuration we need to do to link SPI0 DMA with channel 4,5,6 and 7. Do you have any example which you can share to us.

Thanks,

Shailesh 

0 Kudos
6 Replies

1,310 Views
Omar_Anguiano
NXP TechSupport
NXP TechSupport

Hello
Hope you are well.

Because of the mux, there is not a hard correlation between any of the DMA request sources and a specific DMA channel. So changing the macro EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL and EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL set a different channel with the functions "DMAMUX_SetSource()" and "DMAMUX_EnableChannel()".

Does this issue happen in channels 1 and 2?

If you have more questions do not hesitate to ask me.
Best regards,
Omar

0 Kudos

1,281 Views
shaileshnsec
Contributor II

Hi,

Thank you for reply.

Does this issue happen in channels 1 and 2? -> No , with this SPI is working fine since these channel are trigger based.

But our requirement is to use non trigger channel like 4 or 5 for SPI, but with this example code did not work. I see all example given by NXP is using 0 or 1. So for which purpose we can use non trigger channel, how to use and what all configuration do we need to do. 

Could you please provide any example which uses non trigger DMA channel (4,5,6,7).

Thanks,

Shailesh Kumar

0 Kudos

1,170 Views
Omar_Anguiano
NXP TechSupport
NXP TechSupport

Hello
I apologize for my delayed reply.
After some tests with the DMA example using multiple channels, DMA_TX was successfully used in all channels while DMA_RX was limited to channels from 0 to 3.
I apologize for the inconvenience this is causing you.

If you have more questions do not hesitate to ask me.
Best regards,
Omar

0 Kudos

1,142 Views
shaileshnsec
Contributor II

Hi,

Thank you for the reply.

Can we use DMA TX and RX transmission for SPI DMA using channel 4-7 in DMA Normal mode?

or Do you have example where we can use SPI DMA in normal mode?

Thanks and Regards,

Shailesh Kumar

0 Kudos

1,054 Views
Omar_Anguiano
NXP TechSupport
NXP TechSupport

Unfortunately, DMA_RX is limited to channels from 0 to 3. If you want to use SPI with DMA it is necessary to assign these first channels to DMA_RX while DMA_TX can be assigned to all the available channels.
The SDK example is the best example alternative, unfortunately,  the module has those limitations.

I apologize for the inconvenience this may cause you, If you have more questions do not hesitate to ask me.
Best regards,
Omar

0 Kudos

1,223 Views
shaileshnsec
Contributor II

Hi,

I tried to configure SPI0 to with Channel 4 and channel 5 using LPIT trigger. But not able to get result. May be I am wrong in this.

Kindly let me know how to resolve this ?


#define EXAMPLE_LPSPI_MASTER_BASEADDR LPSPI0
#define EXAMPLE_LPSPI_MASTER_CLOCK_NAME kCLOCK_Lpspi0
#define LPSPI_MASTER_CLK_FREQ (CLOCK_GetIpFreq(EXAMPLE_LPSPI_MASTER_CLOCK_NAME))
#define EXAMPLE_LPSPI_MASTER_CLOCK_SOURCE (kCLOCK_IpSrcFircAsync)
#define EXAMPLE_LPSPI_MASTER_PCS_FOR_INIT kLPSPI_Pcs3
#define EXAMPLE_LPSPI_MASTER_PCS_FOR_TRANSFER kLPSPI_MasterPcs3

#define EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE DMAMUX
#define EXAMPLE_LPSPI_MASTER_DMA_RX_REQUEST_SOURCE kDmaRequestMux0LPSPI0Rx
#define EXAMPLE_LPSPI_MASTER_DMA_TX_REQUEST_SOURCE kDmaRequestMux0LPSPI0Tx
#define EXAMPLE_LPSPI_MASTER_DMA_BASE DMA0
#define EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL 4U
#define EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL 5U

#define EXAMPLE_LPSPI_DEALY_COUNT 0xfffff
#define TRANSFER_SIZE 64U /* Transfer dataSize */
#define TRANSFER_BAUDRATE 500000U /* Transfer baudrate - 500k */

/*******************************************************************************
* Prototypes
******************************************************************************/
/* LPSPI user callback */
void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, status_t status, void *userData);

/*******************************************************************************
* Variables
******************************************************************************/
AT_NONCACHEABLE_SECTION_INIT(uint8_t masterRxData[TRANSFER_SIZE]) = {0};
AT_NONCACHEABLE_SECTION_INIT(uint8_t masterTxData[TRANSFER_SIZE]) = {0};

AT_NONCACHEABLE_SECTION_INIT(lpspi_master_edma_handle_t g_m_edma_handle) = {0};
edma_handle_t lpspiEdmaMasterRxRegToRxDataHandle;
edma_handle_t lpspiEdmaMasterTxDataToTxRegHandle;

volatile bool isTransferCompleted = false;
volatile uint32_t g_systickCounter = 20U;
/*******************************************************************************
* Code
******************************************************************************/
#define DEMO_LPIT_USER_CHANNEL kLPIT_Chnl_0
#define DEMO_LPIT_USER_TIMER_CH kLPIT_Trigger_TimerChn0
#define DEMO_LPIT_SOURCECLOCK CLOCK_GetIpFreq(kCLOCK_Lpit0)
/* LPIT triggers ADC every LPIT_TRIGGER_TIME us*/
#define LPIT_TRIGGER_TIME (1000000U)
static void DEMO_InitLpitTrigger(void)
{
/* Structure of initialize LPIT */
lpit_config_t lpitConfig;
lpit_chnl_params_t lpitChannelConfig;

LPIT_GetDefaultConfig(&lpitConfig);
/* Init lpit module */
LPIT_Init(LPIT0, &lpitConfig);

lpitChannelConfig.chainChannel = false;
lpitChannelConfig.enableReloadOnTrigger = false;
lpitChannelConfig.enableStartOnTrigger = false;
lpitChannelConfig.enableStopOnTimeout = false;
lpitChannelConfig.timerMode = kLPIT_PeriodicCounter;
/* Set default values for the trigger source */
lpitChannelConfig.triggerSelect = DEMO_LPIT_USER_TIMER_CH;
lpitChannelConfig.triggerSource = kLPIT_TriggerSource_External;

/* Init lpit channel 0 */
LPIT_SetupChannel(LPIT0, DEMO_LPIT_USER_CHANNEL, &lpitChannelConfig);

/* Set timer period for channel 0 */
LPIT_SetTimerPeriod(LPIT0, DEMO_LPIT_USER_CHANNEL, USEC_TO_COUNT(LPIT_TRIGGER_TIME, DEMO_LPIT_SOURCECLOCK));

/* Disable timer interrupts for channel 0 */
// LPIT_DisableInterrupts(LPIT0, kLPIT_Channel0TimerInterruptEnable);

/* Start the timer */
// LPIT_StartTimer(LPIT0, kLPIT_Chnl_0);

TRGMUX_SetTriggerSource(TRGMUX0, kTRGMUX_Dmamux0, kTRGMUX_TriggerInput0, kTRGMUX_SourceLpit0Ch0); // Connect the LPIT trigger source to the DMAMUX
}

void SysTick_Handler(void)
{
if (g_systickCounter != 0U)
{
g_systickCounter--;
}
}

void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, status_t status, void *userData)
{
if (status == kStatus_Success)
{
PRINTF("This is LPSPI master edma transfer completed callback. \r\n\r\n");
}

isTransferCompleted = true;
}

/*!
* @brief Main function
*/
int main(void)
{
uint32_t srcClock_Hz;
uint32_t errorCount;
uint32_t loopCount = 1U;
uint32_t i;
lpspi_master_config_t masterConfig;
lpspi_transfer_t masterXfer;
edma_config_t userConfig;

BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
/* Set the source for the LPIT module */
CLOCK_SetIpSrc(kCLOCK_Lpit0, kCLOCK_IpSrcSircAsync);
/* Configure the lpit to trigger ADC periodically */
DEMO_InitLpitTrigger();
/*Set clock source for LPSPI and get master clock source*/
CLOCK_SetIpSrc(EXAMPLE_LPSPI_MASTER_CLOCK_NAME, EXAMPLE_LPSPI_MASTER_CLOCK_SOURCE);

PRINTF("LPSPI board to board edma example.\r\n");
PRINTF("This example use one board as master and another as slave.\r\n");
PRINTF("Master and slave uses EDMA way. Slave should start first. \r\n");
PRINTF("Please make sure you make the correct line connection. Basically, the connection is: \r\n");
PRINTF("LPSPI_master -- LPSPI_slave \r\n");
PRINTF(" CLK -- CLK \r\n");
PRINTF(" PCS -- PCS \r\n");
PRINTF(" SOUT -- SIN \r\n");
PRINTF(" SIN -- SOUT \r\n");
PRINTF(" GND -- GND \r\n");

/*DMA Mux setting and EDMA init*/
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
/* DMA MUX 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);

DMAMUX_SetSource(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL,
EXAMPLE_LPSPI_MASTER_DMA_TX_REQUEST_SOURCE);
DMAMUX_EnableChannel(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);
#endif

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

//TRGMUX_SetTriggerSource(TRGMUX0, kTRGMUX_ExtOut4_7, kTRGMUX_TriggerInput0, kTRGMUX_SourceLpit0Ch0);
//TRGMUX_SetTriggerSource(TRGMUX0, kTRGMUX_Lpspi0, kTRGMUX_TriggerInput0, kTRGMUX_SourceLpspi0Frame);

/* EDMA init*/
/*
* userConfig.enableRoundRobinArbitration = false;
* userConfig.enableHaltOnError = true;
* userConfig.enableContinuousLinkMode = false;
* userConfig.enableDebugMode = false;
*/
EDMA_GetDefaultConfig(&userConfig);
EDMA_Init(EXAMPLE_LPSPI_MASTER_DMA_BASE, &userConfig);

/*Master config*/
LPSPI_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate = TRANSFER_BAUDRATE;
masterConfig.whichPcs = EXAMPLE_LPSPI_MASTER_PCS_FOR_INIT;

srcClock_Hz = LPSPI_MASTER_CLK_FREQ;
LPSPI_MasterInit(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterConfig, srcClock_Hz);

/*Set up lpspi master*/
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

EDMA_EnableChannelRequest(EXAMPLE_LPSPI_MASTER_DMA_BASE, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
EDMA_EnableChannelRequest(EXAMPLE_LPSPI_MASTER_DMA_BASE, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);

LPIT_StartTimer(LPIT0, kLPIT_Chnl_0);

LPSPI_MasterTransferCreateHandleEDMA(EXAMPLE_LPSPI_MASTER_BASEADDR, &g_m_edma_handle, LPSPI_MasterUserCallback,
NULL, &lpspiEdmaMasterRxRegToRxDataHandle,
&lpspiEdmaMasterTxDataToTxRegHandle);

while (1)
{
/* Set up the transfer data */
for (i = 0U; i < TRANSFER_SIZE; i++)
{
masterTxData[i] = (i + loopCount) % 256U;
masterRxData[i] = 0U;
}

/* Print out transmit buffer */
PRINTF("\r\n Master transmit:\r\n");
for (i = 0; i < TRANSFER_SIZE; i++)
{
/* Print 16 numbers in a line */
if ((i & 0x0FU) == 0U)
{
PRINTF("\r\n");
}
PRINTF(" %02X", masterTxData[i]);
}
PRINTF("\r\n");

/*Start master transfer*/
masterXfer.txData = masterTxData;
masterXfer.rxData = NULL;
masterXfer.dataSize = TRANSFER_SIZE;
masterXfer.configFlags =
EXAMPLE_LPSPI_MASTER_PCS_FOR_TRANSFER | kLPSPI_MasterByteSwap | kLPSPI_MasterPcsContinuous;

isTransferCompleted = false;
LPSPI_MasterTransferEDMA(EXAMPLE_LPSPI_MASTER_BASEADDR, &g_m_edma_handle, &masterXfer);

/* Wait until transfer completed */
while (!isTransferCompleted)
{
}

/* Delay to wait slave is ready */
if (SysTick_Config(SystemCoreClock / 1000U))
{
while (1)
{
}
}
/* Delay 20 ms */
g_systickCounter = 20U;
while (g_systickCounter != 0U)
{
}
/* Start master transfer, receive data from slave */
isTransferCompleted = false;
masterXfer.txData = NULL;
masterXfer.rxData = masterRxData;
masterXfer.dataSize = TRANSFER_SIZE;
masterXfer.configFlags =
EXAMPLE_LPSPI_MASTER_PCS_FOR_TRANSFER | kLPSPI_MasterByteSwap | kLPSPI_MasterPcsContinuous;

LPSPI_MasterTransferEDMA(EXAMPLE_LPSPI_MASTER_BASEADDR, &g_m_edma_handle, &masterXfer);

/* Wait until transfer completed */
while (!isTransferCompleted)
{
}

errorCount = 0;
for (i = 0; i < TRANSFER_SIZE; i++)
{
if (masterTxData[i] != masterRxData[i])
{
errorCount++;
}
}
if (errorCount == 0)
{
PRINTF(" \r\nLPSPI transfer all data matched! \r\n");
/* Print out receive buffer */
PRINTF("\r\n Master received:\r\n");
for (i = 0; i < TRANSFER_SIZE; i++)
{
/* Print 16 numbers in a line */
if ((i & 0x0FU) == 0U)
{
PRINTF("\r\n");
}
PRINTF(" %02X", masterRxData[i]);
}
PRINTF("\r\n");
}
else
{
PRINTF(" \r\nError occurred in LPSPI transfer ! \r\n");
}

/* Wait for press any key */
PRINTF("\r\n Press any key to run again\r\n");
GETCHAR();
/* Increase loop count to change transmit buffer */
loopCount++;
}
}

Regards,

Shailesh

0 Kudos