/* * Copyright 2019 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include "pin_mux.h" #include "clock_config.h" #include "board.h" #include "fsl_lpuart_edma.h" #if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT #include "fsl_dmamux.h" #endif //COMMON #define EXAMPLE_LPUART_CLK_FREQ BOARD_DebugConsoleSrcFreq() #define EXAMPLE_LPUART_DMAMUX_BASEADDR DMAMUX #define EXAMPLE_LPUART_DMA_BASEADDR DMA0 //COMMON //LPUART1 #define EXAMPLE_LPUART LPUART1 #define LPUART_TX_DMA_CHANNEL 0U #define LPUART_RX_DMA_CHANNEL 1U #define LPUART_TX_DMA_REQUEST kDmaRequestMuxLPUART1Tx #define LPUART_RX_DMA_REQUEST kDmaRequestMuxLPUART1Rx #define EXAMPLE_LPUART_IRQHandler LPUART1_IRQHandler #define EXAMPLE_LPUART_IRQn LPUART1_IRQn //LPUART1 //LPUART2 #define EXAMPLE_LPUART2 LPUART2 #define LPUART_TX_DMA_CHANNEL2 2U #define LPUART_RX_DMA_CHANNEL2 3U #define LPUART_TX_DMA_REQUEST2 kDmaRequestMuxLPUART2Tx #define LPUART_RX_DMA_REQUEST2 kDmaRequestMuxLPUART2Rx #define EXAMPLE_LPUART_IRQHandler2 LPUART2_IRQHandler #define EXAMPLE_LPUART_IRQn2 LPUART2_IRQn //LPUART1 #define EXAMPLE_RING_BUFFER_SIZE (32U) static void EXAMPLE_InitEDMA(void); static void EXAMPLE_InitLPUART(void); static void EXAMPLE_StartRingBufferEDMA(void); static void EXAMPLE_ReadRingBuffer(uint8_t *ringBuffer, uint8_t *receiveBuffer, uint32_t length); void EXAMPLE_RxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds); void EXAMPLE_TxEDMACallback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData); //For LPUART2 static void EXAMPLE_StartRingBufferEDMA2(void); static void EXAMPLE_ReadRingBuffer2(uint8_t *ringBuffer, uint8_t *receiveBuffer, uint32_t length); void EXAMPLE_RxEDMACallback2(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds); void EXAMPLE_TxEDMACallback2(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData); lpuart_edma_handle_t g_lpuartEdmaHandle; edma_handle_t g_lpuartTxEdmaHandle; edma_handle_t g_lpuartRxEdmaHandle; AT_NONCACHEABLE_SECTION_INIT(uint8_t g_rxBuffer[EXAMPLE_RING_BUFFER_SIZE]) = {0}; AT_NONCACHEABLE_SECTION_INIT(uint8_t g_ringBuffer[EXAMPLE_RING_BUFFER_SIZE]) = {0}; volatile bool txOnGoing = false; volatile bool isIdleLineDetected = false; volatile uint32_t ringBufferFlag = 0U; volatile uint32_t receivedBytes = 0U; volatile uint32_t ringBufferIndex = 0U; //FOR LPUART2 //Should I use separate lpuart_edma_handle_t for each UARTn object? //lpuart_edma_handle_t g_lpuartEdmaHandle2; NO NEED, THEY WILL BE LINK THE SAME lpuart_edma_handle_t edma_handle_t g_lpuartTxEdmaHandle2; edma_handle_t g_lpuartRxEdmaHandle2; AT_NONCACHEABLE_SECTION_INIT(uint8_t g_rxBuffer2[EXAMPLE_RING_BUFFER_SIZE]) = {0}; AT_NONCACHEABLE_SECTION_INIT(uint8_t g_ringBuffer2[EXAMPLE_RING_BUFFER_SIZE]) = {0}; volatile bool txOnGoing2 = false; volatile bool isIdleLineDetected2 = false; volatile uint32_t ringBufferFlag2 = 0U; volatile uint32_t receivedBytes2 = 0U; volatile uint32_t ringBufferIndex2 = 0U; //Increased tcdMemoryPoolPtr[1] to tcdMemoryPoolPtr[2] AT_NONCACHEABLE_SECTION_ALIGN(static edma_tcd_t tcdMemoryPoolPtr[2], sizeof(edma_tcd_t)); static void EXAMPLE_InitLPUART(void) { lpuart_config_t lpuartConfig; LPUART_GetDefaultConfig(&lpuartConfig); lpuartConfig.rxIdleType = kLPUART_IdleTypeStopBit; lpuartConfig.rxIdleConfig = kLPUART_IdleCharacter2; lpuartConfig.baudRate_Bps = BOARD_DEBUG_UART_BAUDRATE; lpuartConfig.enableTx = true; lpuartConfig.enableRx = true; LPUART_Init(EXAMPLE_LPUART, &lpuartConfig, EXAMPLE_LPUART_CLK_FREQ); //FOR LPUART2 LPUART_Init(EXAMPLE_LPUART2, &lpuartConfig, EXAMPLE_LPUART_CLK_FREQ); } static void EXAMPLE_InitEDMA(void) { edma_config_t config; #if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT DMAMUX_Init(EXAMPLE_LPUART_DMAMUX_BASEADDR); DMAMUX_SetSource(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_TX_DMA_CHANNEL, LPUART_TX_DMA_REQUEST); DMAMUX_SetSource(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_RX_DMA_CHANNEL, LPUART_RX_DMA_REQUEST); DMAMUX_EnableChannel(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_TX_DMA_CHANNEL); DMAMUX_EnableChannel(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_RX_DMA_CHANNEL); //FOR LPUART2 DMAMUX_SetSource(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_TX_DMA_CHANNEL2, LPUART_TX_DMA_REQUEST); DMAMUX_SetSource(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_RX_DMA_CHANNEL2, LPUART_RX_DMA_REQUEST2); DMAMUX_EnableChannel(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_TX_DMA_CHANNEL2); DMAMUX_EnableChannel(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_RX_DMA_CHANNEL2); #endif EDMA_GetDefaultConfig(&config); EDMA_Init(EXAMPLE_LPUART_DMA_BASEADDR, &config); EDMA_CreateHandle(&g_lpuartTxEdmaHandle, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_TX_DMA_CHANNEL); EDMA_CreateHandle(&g_lpuartRxEdmaHandle, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_RX_DMA_CHANNEL); //FOR LPUART2 EDMA_CreateHandle(&g_lpuartTxEdmaHandle2, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_TX_DMA_CHANNEL2); EDMA_CreateHandle(&g_lpuartRxEdmaHandle2, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_RX_DMA_CHANNEL2); LPUART_TransferCreateHandleEDMA(EXAMPLE_LPUART, &g_lpuartEdmaHandle, EXAMPLE_TxEDMACallback, NULL, &g_lpuartTxEdmaHandle, &g_lpuartRxEdmaHandle); LPUART_TransferCreateHandleEDMA(EXAMPLE_LPUART2, &g_lpuartEdmaHandle, EXAMPLE_TxEDMACallback2, NULL, &g_lpuartTxEdmaHandle2, &g_lpuartRxEdmaHandle2); } static void EXAMPLE_StartRingBufferEDMA(void) { edma_transfer_config_t xferConfig; EDMA_InstallTCDMemory(&g_lpuartRxEdmaHandle, (edma_tcd_t *)&tcdMemoryPoolPtr[0], 1U); EDMA_PrepareTransfer(&xferConfig, (void *)(uint32_t *)LPUART_GetDataRegisterAddress(EXAMPLE_LPUART), sizeof(uint8_t), g_ringBuffer, sizeof(uint8_t), sizeof(uint8_t), EXAMPLE_RING_BUFFER_SIZE, kEDMA_PeripheralToMemory); g_lpuartRxEdmaHandle.tcdUsed = 1U; g_lpuartRxEdmaHandle.tail = 0U; EDMA_TcdReset(&g_lpuartRxEdmaHandle.tcdPool[0U]); EDMA_TcdSetTransferConfig(&g_lpuartRxEdmaHandle.tcdPool[0U], &xferConfig, tcdMemoryPoolPtr); g_lpuartRxEdmaHandle.tcdPool[0U].CSR |= DMA_CSR_INTMAJOR_MASK; EDMA_InstallTCD(g_lpuartRxEdmaHandle.base, g_lpuartRxEdmaHandle.channel, &g_lpuartRxEdmaHandle.tcdPool[0U]); EDMA_SetCallback(&g_lpuartRxEdmaHandle, EXAMPLE_RxEDMACallback, NULL); EDMA_StartTransfer(&g_lpuartRxEdmaHandle); LPUART_EnableRxDMA(EXAMPLE_LPUART, true); LPUART_EnableInterrupts(EXAMPLE_LPUART, kLPUART_IdleLineInterruptEnable); EnableIRQ(EXAMPLE_LPUART_IRQn); } static void EXAMPLE_ReadRingBuffer(uint8_t *ringBuffer, uint8_t *receiveBuffer, uint32_t length) { assert(ringBuffer); assert(receiveBuffer); assert(length); uint32_t index = length; if (length > EXAMPLE_RING_BUFFER_SIZE) { ringBufferIndex = ((ringBufferIndex + length) % EXAMPLE_RING_BUFFER_SIZE); index = EXAMPLE_RING_BUFFER_SIZE; } while (index) { *(receiveBuffer++) = ringBuffer[ringBufferIndex++]; if (ringBufferIndex == EXAMPLE_RING_BUFFER_SIZE) { ringBufferIndex = 0U; ringBufferFlag--; } index--; } } void EXAMPLE_LPUART_IRQHandler(void) { uint32_t status = LPUART_GetStatusFlags(EXAMPLE_LPUART); uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(EXAMPLE_LPUART); if ((0U != ((uint32_t)kLPUART_IdleLineFlag & status)) && (0U != ((uint32_t)kLPUART_IdleLineInterruptEnable & enabledInterrupts))) { (void)LPUART_ClearStatusFlags(EXAMPLE_LPUART, kLPUART_IdleLineFlag); isIdleLineDetected = true; receivedBytes = EXAMPLE_RING_BUFFER_SIZE - EDMA_GetRemainingMajorLoopCount(EXAMPLE_LPUART_DMA_BASEADDR, LPUART_RX_DMA_CHANNEL); receivedBytes += (EXAMPLE_RING_BUFFER_SIZE * ringBufferFlag) - ringBufferIndex; if (receivedBytes > 32U) { __NOP(); } } LPUART_TransferEdmaHandleIRQ(EXAMPLE_LPUART, &g_lpuartEdmaHandle); SDK_ISR_EXIT_BARRIER; } void EXAMPLE_RxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { if (true == transferDone) { ringBufferFlag++; } } void EXAMPLE_TxEDMACallback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData) { userData = userData; if (kStatus_LPUART_TxIdle == status) { txOnGoing = false; } } //Should I use sepera "edma_handle_t g_lpuartRxEdmaHandle2;" for each rxEdmaHandle or Can I use all rxEdmaHandle for 1 and only change tcdUsed? static void EXAMPLE_StartRingBufferEDMA2(void) { edma_transfer_config_t xferConfig; EDMA_InstallTCDMemory(&g_lpuartRxEdmaHandle2, (edma_tcd_t *)&tcdMemoryPoolPtr[1], 1U); //NOT SURE EDMA_PrepareTransfer(&xferConfig, (void *)(uint32_t *)LPUART_GetDataRegisterAddress(EXAMPLE_LPUART2), sizeof(uint8_t), g_ringBuffer2, sizeof(uint8_t), sizeof(uint8_t), EXAMPLE_RING_BUFFER_SIZE, kEDMA_PeripheralToMemory); g_lpuartRxEdmaHandle2.tcdUsed = 2U; //NOT SURE 1U or 2U g_lpuartRxEdmaHandle2.tail = 0U; //NOT SURE What? EDMA_TcdReset(&g_lpuartRxEdmaHandle2.tcdPool[1U]); EDMA_TcdSetTransferConfig(&g_lpuartRxEdmaHandle2.tcdPool[1U], &xferConfig, tcdMemoryPoolPtr); g_lpuartRxEdmaHandle2.tcdPool[1U].CSR |= DMA_CSR_INTMAJOR_MASK; EDMA_InstallTCD(g_lpuartRxEdmaHandle2.base, g_lpuartRxEdmaHandle2.channel, &g_lpuartRxEdmaHandle2.tcdPool[1U]); EDMA_SetCallback(&g_lpuartRxEdmaHandle2, EXAMPLE_RxEDMACallback2, NULL); EDMA_StartTransfer(&g_lpuartRxEdmaHandle2); LPUART_EnableRxDMA(EXAMPLE_LPUART2, true); LPUART_EnableInterrupts(EXAMPLE_LPUART2, kLPUART_IdleLineInterruptEnable); EnableIRQ(EXAMPLE_LPUART_IRQn2); } static void EXAMPLE_ReadRingBuffer2(uint8_t *ringBuffer, uint8_t *receiveBuffer, uint32_t length) { assert(ringBuffer); assert(receiveBuffer); assert(length); uint32_t index = length; if (length > EXAMPLE_RING_BUFFER_SIZE) { ringBufferIndex2 = ((ringBufferIndex2 + length) % EXAMPLE_RING_BUFFER_SIZE); index = EXAMPLE_RING_BUFFER_SIZE; } while (index) { *(receiveBuffer++) = ringBuffer[ringBufferIndex2++]; if (ringBufferIndex2 == EXAMPLE_RING_BUFFER_SIZE) { ringBufferIndex2 = 0U; ringBufferFlag2--; } index--; } } void EXAMPLE_LPUART_IRQHandler2(void) { uint32_t status = LPUART_GetStatusFlags(EXAMPLE_LPUART2); uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(EXAMPLE_LPUART2); if ((0U != ((uint32_t)kLPUART_IdleLineFlag & status)) && (0U != ((uint32_t)kLPUART_IdleLineInterruptEnable & enabledInterrupts))) { (void)LPUART_ClearStatusFlags(EXAMPLE_LPUART2, kLPUART_IdleLineFlag); isIdleLineDetected2 = true; receivedBytes2 = EXAMPLE_RING_BUFFER_SIZE - EDMA_GetRemainingMajorLoopCount(EXAMPLE_LPUART_DMA_BASEADDR, LPUART_RX_DMA_CHANNEL2); receivedBytes2 += (EXAMPLE_RING_BUFFER_SIZE * ringBufferFlag2) - ringBufferIndex2; if (receivedBytes2 > 32U) { __NOP(); } } LPUART_TransferEdmaHandleIRQ(EXAMPLE_LPUART2, &g_lpuartEdmaHandle); SDK_ISR_EXIT_BARRIER; } void EXAMPLE_RxEDMACallback2(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { if (true == transferDone) { ringBufferFlag2++; } } void EXAMPLE_TxEDMACallback2(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData) { userData = userData; if (kStatus_LPUART_TxIdle == status) { txOnGoing2 = false; } } int main(void) { lpuart_transfer_t sendXfer; BOARD_ConfigMPU(); BOARD_InitBootPins(); BOARD_InitBootClocks(); EXAMPLE_InitLPUART(); EXAMPLE_InitEDMA(); EXAMPLE_StartRingBufferEDMA(); //SEND + RECEIVE OPERATIONS }