/** * @file hv_drv_Dma.c * @brief wdg driver chip file. * * @author HiView SoC Software Team * @version 1.0.0 * @date 2023-06-05 * @copyright Copyright(c),2023-6, Hiview Software. All rights reserved. * */ #include "hv_chip_Config.h" #include "hv_vos_Comm.h" #include "hv_comm_DataType.h" #include "hv_comm_Define.h" #include "hv_cal_Dma.h" #include "hv_drv_Dma.h" #define SIZE_NO_CARE 2048 typedef void (*Hv_Dma_Callback)(void); static DmaSelf* g_apDmaSelf[DMA_CHANNEL_COUNT] = {NULL}; static Hv_Dma_Callback g_apDmaCallback[DMA_CHANNEL_COUNT] = {NULL}; static DmaLinkedList* g_apLLI[DMA_CHANNEL_COUNT] = {NULL}; static void Hv_Drv_Dma_MemMove_LinkedList(DmaSelf* pstself,DmaLinkedList* pstStemAddr, UINT32 uiSrcAddr, UINT32 uiDstAddr) { Hv_Cal_Dma_SetLinkedListAddr(pstself, pstStemAddr); Hv_Cal_Dma_MemMove(pstself, uiSrcAddr, uiDstAddr, SIZE_NO_CARE); return; } static Status Hv_Dma_CpltCallback(void* arg) { DmaSelf* pstSelf = (DmaSelf*)arg; DmaPortChannel enPortChannelNum = Hv_Cal_Dma_GetPortChannelNum(pstSelf); if (NULL != g_apLLI[enPortChannelNum]) { Hv_Vos_Free(g_apLLI[enPortChannelNum]); g_apLLI[enPortChannelNum] = NULL; } Hv_Vos_InvalidAllDCache(); g_apDmaCallback[enPortChannelNum](); return HV_SUCCESS; } /** @brief dma初始化,选择通道和设置回调函数。type类型0:1个src对应1个dst,size可能超过block_ts,函数内部生成linklist. * @self channelparam no. * @param Callback callback when move over. */ void Hv_Drv_Dma_Init(DmaPortChannel enPortChannelNum, void* Callback) { DmaInitParam InitParam; HV_MEMSET(&InitParam,0, sizeof(DmaInitParam)); InitParam.PortChannelNum = enPortChannelNum; InitParam.Application = DMA_APPLI_MEM; InitParam.transType = DMA_TYPE_LINKEDLIST; InitParam.XferCpltCallback = (XferCpltCallbackType)Hv_Dma_CpltCallback; g_apDmaCallback[enPortChannelNum] = (Hv_Dma_Callback)Callback; g_apDmaSelf[enPortChannelNum] = Hv_Cal_Dma_ChannelInit(&InitParam); return; } /** @brief dma move。 * @self channelparam no. * @param SrcAddr src address。 * @param DstAddr dst address。 * @param Size size to move。 */ void Hv_Drv_Dma_MemMove(DmaPortChannel enPortChannelNum, UINT32 uiSrcAddr, UINT32 uiDstAddr, UINT32 uiSize) { DmaSelf* pstSelf = g_apDmaSelf[enPortChannelNum]; UINT32 uiBlockSize = DMA_MEM_BLOCK_SIZE; UINT32 uiTotolListNum = 0; UINT32 uiLast = 0; HV_LOG_DEBUG(SYSTEM, "Hv_Drv_Dma_MemMove src %x, dst %x, size %x!\n", uiSrcAddr, uiDstAddr, uiSize); uiTotolListNum = uiSize / uiBlockSize; if (uiSize % uiBlockSize) { uiTotolListNum++; } g_apLLI[enPortChannelNum] = (DmaLinkedList*)Hv_Vos_Malloc(uiTotolListNum * sizeof(DmaLinkedList)); if (g_apLLI[enPortChannelNum] == NULL) { HV_LOG_ERROR(SYSTEM, "Hv_Drv_Dma_MemMove Malloc Fail, size = 0x%x!\n", uiTotolListNum * sizeof(DmaLinkedList)); return; } Hv_Cal_Dma_LLIbuild_BothContinous(g_apLLI[enPortChannelNum], uiSrcAddr, uiDstAddr, uiSize, 1); Hv_Drv_Dma_MemMove_LinkedList(pstSelf, g_apLLI[enPortChannelNum], uiSrcAddr, uiDstAddr); return; } /** @brief dma move with multy src。 * @self channelparam no. * @param SrcArray src1 address, src1 size, src2 address, src2 size...。 * @param ArraySize src number。 * @param DstAddr dst address。 */ void Hv_Drv_Dma_MemMoveArray(DmaPortChannel enPortChannelNum, UINT32 *puiSrcArray, UINT32 uiArraySize, UINT32 uiDstAddr) { DmaSelf* pstSelf = g_apDmaSelf[enPortChannelNum]; UINT32 uiStemAddr = 0x00; UINT32 uiLoop = 0; UINT32 uiAarryNum = 0; UINT32 uiSize = 0; UINT32 uiBlockSize = DMA_MEM_BLOCK_SIZE; UINT32 uiTotolListNum = 0; UINT32 uiIndexListNum = 0; UINT32 uiLast = 0; uiAarryNum = uiArraySize; for (uiLoop = 0; uiLoop < uiAarryNum; uiLoop++) { uiSize = *(puiSrcArray + 1 + uiLoop * 2); uiTotolListNum += uiSize / uiBlockSize; if (uiSize % uiBlockSize) { uiTotolListNum++; } } g_apLLI[enPortChannelNum] = (DmaLinkedList*)Hv_Vos_Malloc(uiTotolListNum * sizeof(DmaLinkedList)); if (g_apLLI[enPortChannelNum] == NULL) { return; } for (uiLoop = 0; uiLoop < uiAarryNum; uiLoop++) { uiStemAddr = (UINT32)(g_apLLI[enPortChannelNum] + uiIndexListNum); if (uiLoop == (uiAarryNum - 1)) { uiLast = 1; } uiSize = *(puiSrcArray + 1 + uiLoop * 2); Hv_Cal_Dma_LLIbuild_BothContinous((DmaLinkedList*)uiStemAddr, *(puiSrcArray + uiLoop * 2), uiDstAddr, uiSize, uiLast); uiIndexListNum += (uiSize / uiBlockSize); if (uiSize % uiBlockSize) { uiIndexListNum++; } } Hv_Drv_Dma_MemMove_LinkedList(pstSelf, g_apLLI[enPortChannelNum], *puiSrcArray, uiDstAddr); return; }