796 lines
26 KiB
C
796 lines
26 KiB
C
/**
|
|
* @file fc7xxx_driver_dma.c
|
|
* @author Flagchip0126
|
|
* @brief FC7xxx DMA driver source code
|
|
* @version 0.1.0
|
|
* @date 2024-01-15
|
|
*
|
|
* @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd.
|
|
*
|
|
*/
|
|
/* ********************************************************************************
|
|
* Revision History:
|
|
*
|
|
* Version Date Author CR# Descriptions
|
|
* --------- ---------- ------------ ---------- ---------------
|
|
* 0.1.0 2024-01-15 Flagchip0126 N/A First version for FC7240
|
|
******************************************************************************** */
|
|
|
|
#include "fc7xxx_driver_dma.h"
|
|
#include "interrupt_manager.h"
|
|
|
|
#define DMA_CHANNEL_INVALID (0xFFU)
|
|
|
|
#define CPM_CORE_ID_CORE0 (0x0U)
|
|
#define CPM_CORE_ID_CORE1 (0x2U)
|
|
#define CPM_CORE_ID_CORE2 (0x4U)
|
|
|
|
static uint8_t s_aDmaDumoUsedStatus[DMA_DUMO_COUNT] = {DMA_CHANNEL_INVALID, DMA_CHANNEL_INVALID, DMA_CHANNEL_INVALID, DMA_CHANNEL_INVALID};
|
|
|
|
static DMA_TransferCompleteCallbackType s_dmaTransferCompleteNotify[DMA_INSTANCE_COUNT][DMA_CFG_COUNT] = {NULL};
|
|
static DMA_TransferErrorCallbackType s_dmaTransferErrorNotify[DMA_INSTANCE_COUNT][DMA_CFG_COUNT] = {NULL};
|
|
|
|
/**
|
|
* @brief DMA IRQ function prototypes
|
|
*
|
|
*/
|
|
void DMA0_IRQHandler(void);
|
|
void DMA1_IRQHandler(void);
|
|
void DMA2_IRQHandler(void);
|
|
void DMA3_IRQHandler(void);
|
|
void DMA4_IRQHandler(void);
|
|
void DMA5_IRQHandler(void);
|
|
void DMA6_IRQHandler(void);
|
|
void DMA7_IRQHandler(void);
|
|
void DMA8_IRQHandler(void);
|
|
void DMA9_IRQHandler(void);
|
|
void DMA10_IRQHandler(void);
|
|
void DMA11_IRQHandler(void);
|
|
void DMA12_IRQHandler(void);
|
|
void DMA13_IRQHandler(void);
|
|
void DMA14_IRQHandler(void);
|
|
void DMA15_IRQHandler(void);
|
|
void DMA_Error_IRQHandler(void);
|
|
|
|
|
|
/**
|
|
* @brief Get the first unused DUMO register index
|
|
*
|
|
* @param [out] pDumoIndex the DUMO register index
|
|
* @return DMA_StatusType whether there is unused DUMO index
|
|
* @return DMA_STATUS_SUCCESS the DUMO register index is successfully get
|
|
* @return DMA_STATUS_NO_RESOURCE all DUMO registers are already occupied
|
|
*/
|
|
static inline DMA_StatusType DMA_GetDumoIndex(uint8_t *pDumoIndex);
|
|
|
|
/**
|
|
* @brief Check whether the value is power of 2 and return the ceil value of the log2(u32Value)
|
|
*
|
|
* @param [in] u32Value the value to check
|
|
* @param [out] u8Log2 the ceil value of log2(u32Value)
|
|
* @return true the u32Value is power of 2
|
|
* @return false the u32Value is not power of 2
|
|
*/
|
|
static bool DMA_IsPowerOf2(uint32_t u32Value, uint8_t *u8Log2);
|
|
|
|
/**
|
|
* @brief Reset the DMAMUX config values
|
|
* @param Dmamux_Instance the selected DMA Instance
|
|
*
|
|
*/
|
|
static inline void Dmamux_Reset(DMAMUX_Type * const Dmamux_Instance);
|
|
|
|
/**
|
|
* @brief Get the data offset value of the selected increment mode and data size
|
|
*
|
|
* @param eIncMode the selected increment mode
|
|
* @param eDataSize the selected data size
|
|
* @return int16_t the calculated data offset
|
|
*/
|
|
static inline uint16_t DMA_GetDataOffset(DMA_IncrementModeType eIncMode,
|
|
DMA_TransferSizeType eDataSize);
|
|
|
|
/**
|
|
* @brief Get the IRQ number of the selected DMA channel
|
|
*
|
|
* @param u8Channel the selected DMA channel
|
|
* @return IRQn_Type the IRQ number of the selected DMA channel
|
|
*/
|
|
//static inline IRQn_Type DMA_GetChannelIRQn(const DMA_InstanceType eDma_Instance);
|
|
|
|
/**
|
|
* @brief The internal interrupt handler for DMA transfer complete
|
|
*
|
|
* @param u8Channel the channel of the DMA interrpt
|
|
*/
|
|
static inline void DMA_Transfer_Complete_IRQHandler(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel);
|
|
|
|
static inline DMA_StatusType DMA_GetDumoIndex(uint8_t *pDumoIndex)
|
|
{
|
|
DMA_StatusType ret = DMA_STATUS_ERROR;
|
|
for (*pDumoIndex = 0U; *pDumoIndex < DMA_DUMO_COUNT; (*pDumoIndex)++)
|
|
{
|
|
if (s_aDmaDumoUsedStatus[*pDumoIndex] == DMA_CHANNEL_INVALID)
|
|
{
|
|
ret = DMA_STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
if (*pDumoIndex == DMA_DUMO_COUNT)
|
|
{
|
|
ret = DMA_STATUS_NO_RESOURCE;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static bool DMA_IsPowerOf2(uint32_t u32Value, uint8_t *u8Log2)
|
|
{
|
|
bool ret = (bool)false;
|
|
*u8Log2 = 0U;
|
|
while (u32Value > (1UL << *u8Log2))
|
|
{
|
|
(*u8Log2)++;
|
|
}
|
|
if ((u32Value & ((1UL << *u8Log2) - 1U)) == 0U)
|
|
{
|
|
ret = (bool)true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static inline uint16_t DMA_GetDataOffset(DMA_IncrementModeType eIncMode,
|
|
DMA_TransferSizeType eDataSize)
|
|
{
|
|
uint16_t u16DataOffset = 0U;
|
|
switch (eIncMode)
|
|
{
|
|
case DMA_INCREMENT_DISABLE:
|
|
{
|
|
u16DataOffset = 0U;
|
|
break;
|
|
}
|
|
|
|
case DMA_INCREMENT_DATA_SIZE:
|
|
{
|
|
u16DataOffset = (uint16_t)(1UL << ((uint8_t)eDataSize));
|
|
break;
|
|
}
|
|
|
|
case DMA_INCREMENT_DATA_SIZE_4BYTE_ALIGNED:
|
|
{
|
|
switch (eDataSize)
|
|
{
|
|
case DMA_TRANSFER_SIZE_1B:
|
|
case DMA_TRANSFER_SIZE_2B:
|
|
case DMA_TRANSFER_SIZE_4B:
|
|
u16DataOffset = 4U;
|
|
break;
|
|
|
|
case DMA_TRANSFER_SIZE_8B:
|
|
u16DataOffset = 8U;
|
|
break;
|
|
|
|
case DMA_TRANSFER_SIZE_32B:
|
|
u16DataOffset = 32U;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return u16DataOffset;
|
|
}
|
|
|
|
void DMA0_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_0);
|
|
}
|
|
|
|
void DMA1_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_1);
|
|
}
|
|
|
|
void DMA2_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_2);
|
|
}
|
|
|
|
void DMA3_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_3);
|
|
}
|
|
|
|
void DMA4_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_4);
|
|
}
|
|
|
|
void DMA5_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_5);
|
|
}
|
|
|
|
void DMA6_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_6);
|
|
}
|
|
|
|
void DMA7_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_7);
|
|
}
|
|
|
|
void DMA8_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_8);
|
|
}
|
|
|
|
void DMA9_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_9);
|
|
}
|
|
|
|
void DMA10_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_10);
|
|
}
|
|
|
|
void DMA11_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_11);
|
|
}
|
|
|
|
void DMA12_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_12);
|
|
}
|
|
|
|
void DMA13_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_13);
|
|
}
|
|
|
|
void DMA14_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_14);
|
|
}
|
|
|
|
void DMA15_IRQHandler(void)
|
|
{
|
|
DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_15);
|
|
}
|
|
|
|
void DMA_Error_IRQHandler(void)
|
|
{
|
|
uint8_t u8Channel;
|
|
DMA_InstanceType eDma_Instance;
|
|
DMA_Type *pDma;
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
|
|
eDma_Instance = DMA_INSTANCE_0;
|
|
|
|
pDma = aDma[DMA_INSTANCE_0];
|
|
for (u8Channel = 0U; u8Channel < DMA_CFG_COUNT; u8Channel++)
|
|
{
|
|
if (DMA_HWA_GetChannelErrorFlag(pDma, u8Channel) == true)
|
|
{
|
|
DMA_HWA_ClearChannelErrorFlag(pDma, u8Channel);
|
|
if (s_dmaTransferErrorNotify[eDma_Instance][u8Channel] != NULL)
|
|
{
|
|
s_dmaTransferErrorNotify[eDma_Instance][u8Channel]();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void DMA_Transfer_Complete_IRQHandler(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel)
|
|
{
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[eDma_Instance];
|
|
|
|
DMA_HWA_ClearChannelInterruptFlag(pDma, (uint8_t)eChannel);
|
|
if (s_dmaTransferCompleteNotify[eDma_Instance][eChannel] != NULL)
|
|
{
|
|
s_dmaTransferCompleteNotify[eDma_Instance][eChannel]();
|
|
}
|
|
}
|
|
|
|
static inline void Dmamux_Reset(DMAMUX_Type * const Dmamux_Instance)
|
|
{
|
|
uint8_t u8Index;
|
|
for (u8Index = 0U; u8Index < DMAMUX_CHCFG_COUNT; u8Index++)
|
|
{
|
|
DMAMUX_HWA_SetRequestSource(Dmamux_Instance, u8Index, false, DMA_REQ_DISABLED);
|
|
}
|
|
for (u8Index = 0U; u8Index < DMAMUX_CHTRG_TRG_COUNT; u8Index++)
|
|
{
|
|
//DMAMUX_HWA_SetPeriodicTrigFlag(Dmamux_Instance, u8Index, false);
|
|
}
|
|
}
|
|
|
|
void DMA_Init(const DMA_InstanceType eDma_Instance, const DMA_InitType *const pInitCfg)
|
|
{
|
|
DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX);
|
|
DEV_ASSERT(pInitCfg != NULL);
|
|
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[eDma_Instance];
|
|
|
|
DMA_DeInit(eDma_Instance);
|
|
DMA_HWA_SetHaltOnErrorFlag(pDma, pInitCfg->bHaltOnError);
|
|
DMA_HWA_SetArbitrationAlgorithm(pDma, pInitCfg->eArbitrationAlgorithm);
|
|
DMA_HWA_SetInnerLoopMappingEnableFlag(pDma, true);
|
|
}
|
|
|
|
void DMA_DeInit(const DMA_InstanceType eDma_Instance)
|
|
{
|
|
DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX);
|
|
|
|
uint8_t u8Index;
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[eDma_Instance];
|
|
DMAMUX_Type * aDmamux[] = DMAMUX_BASE_PTRS;
|
|
DMAMUX_Type *const pDmamux = aDmamux[eDma_Instance];
|
|
|
|
DMA_HWA_SetControlRegister(pDma, 0U);
|
|
DMA_HWA_DisableAllChannelErrorInterrupt(pDma);
|
|
DMA_HWA_DisableAllChannelRequest(pDma);
|
|
DMA_HWA_ClearAllChannelDoneStatus(pDma);
|
|
DMA_HWA_ClearAllChannelErrorFlag(pDma);
|
|
DMA_HWA_ClearAllChannelInterruptFlag(pDma);
|
|
pDma->DUME[0] = 0U;
|
|
for (u8Index = 0U; u8Index < DMA_DUMO_COUNT; u8Index++)
|
|
{
|
|
DMA_HWA_SetUnalignModulo(pDma, u8Index, 0U, 0U);
|
|
}
|
|
for (u8Index = 0U; u8Index < DMA_CFG_COUNT; u8Index++)
|
|
{
|
|
DMA_HWA_SetUnalignModuloEnableFlag(pDma, u8Index, false, false);
|
|
DMA_HWA_SetPriority(pDma, u8Index, u8Index);
|
|
DMA_HWA_SetSrcAddr(pDma, u8Index, 0U);
|
|
DMA_HWA_SetSrcOffset(pDma, u8Index, 0);
|
|
DMA_HWA_SetSrcLastAddrAdjustment(pDma, u8Index, 0);
|
|
DMA_HWA_SetDestAddr(pDma, u8Index, 0U);
|
|
DMA_HWA_SetDestOffset(pDma, u8Index, 0);
|
|
DMA_HWA_SetDestLastAddrAdjustment(pDma, u8Index, 0);
|
|
DMA_HWA_SetSrcDataSize(pDma, u8Index, DMA_TRANSFER_SIZE_1B);
|
|
DMA_HWA_SetSrcModulo(pDma, u8Index, 0U);
|
|
DMA_HWA_SetDestDataSize(pDma, u8Index, DMA_TRANSFER_SIZE_1B);
|
|
DMA_HWA_SetDestModulo(pDma, u8Index, 0U);
|
|
DMA_HWA_SetInnerLoopSize(pDma, u8Index, 0U);
|
|
DMA_HWA_SetChannelControlStatus(pDma, u8Index, 0U);
|
|
DMA_HWA_SetChannelToChannelTrig(pDma, u8Index, false, 0U);
|
|
DMA_HWA_SetLoopCount(pDma, u8Index, 0U);
|
|
}
|
|
Dmamux_Reset(pDmamux);
|
|
|
|
}
|
|
|
|
DMA_StatusType DMA_InitChannel(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel, const DMA_ChannelCfgType *const pChnCfg)
|
|
{
|
|
DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX);
|
|
DEV_ASSERT(eChannel < DMA_CHANNEL_MAX);
|
|
DEV_ASSERT(pChnCfg != NULL);
|
|
DEV_ASSERT(pChnCfg->u16BlockCount > 0U);
|
|
DEV_ASSERT(pChnCfg->u32BlockSize > 0U);
|
|
DEV_ASSERT(((pChnCfg->u32BlockSize >> pChnCfg->eSrcDataSize) << pChnCfg->eSrcDataSize == pChnCfg->u32BlockSize) &&
|
|
((pChnCfg->u32BlockSize >> pChnCfg->eDestDataSize) << pChnCfg->eDestDataSize == pChnCfg->u32BlockSize));
|
|
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[eDma_Instance];
|
|
DMAMUX_Type * aDmamux[] = DMAMUX_BASE_PTRS;
|
|
DMAMUX_Type *const pDmamux = aDmamux[eDma_Instance];
|
|
|
|
DMA_StatusType ret;
|
|
|
|
uint16_t u16SrcDataOffset = DMA_GetDataOffset(pChnCfg->eSrcIncMode, pChnCfg->eSrcDataSize);
|
|
uint16_t u16DestDataOffset = DMA_GetDataOffset(pChnCfg->eDestIncMode, pChnCfg->eDestDataSize);
|
|
|
|
int32_t s32SrcLastOffset;
|
|
int32_t s32DestLastOffset;
|
|
|
|
uint8_t u8SrcMod = 0U;
|
|
uint8_t u8DestMod = 0U;
|
|
|
|
bool bUseSrcDumo = (bool)false;
|
|
bool bUseDestDumo = (bool)false;
|
|
uint8_t u8DumoIndex = 0U;
|
|
uint16_t u16Sumo = 0U;
|
|
uint16_t u16Dumo = 0U;
|
|
|
|
if ((pChnCfg->bSrcCircularBufferEn == true) || (pChnCfg->bDestCircularBufferEn == true))
|
|
{
|
|
/* If the circular buffer size is not power of 2 aligned, need to use the DUMO */
|
|
if (pChnCfg->bSrcCircularBufferEn == true)
|
|
{
|
|
DEV_ASSERT(pChnCfg->u32SrcCircBufferSize != 0U);
|
|
bUseSrcDumo = (bool)(DMA_IsPowerOf2(pChnCfg->u32SrcCircBufferSize, &u8SrcMod) ? false : true);
|
|
}
|
|
if (pChnCfg->bDestCircularBufferEn == true)
|
|
{
|
|
DEV_ASSERT(pChnCfg->u32DestCircBufferSize != 0U);
|
|
bUseDestDumo = (bool)(DMA_IsPowerOf2(pChnCfg->u32DestCircBufferSize, &u8DestMod) ? false : true);
|
|
}
|
|
|
|
/* If circular buffer is enabled, the buffer address must be power of 2 aligned */
|
|
if (((pChnCfg->bSrcCircularBufferEn == true) &&
|
|
(((uint32_t)pChnCfg->pSrcBuffer & ((1UL << u8SrcMod) - 1U)) != 0U)) ||
|
|
((pChnCfg->bDestCircularBufferEn == true) &&
|
|
(((uint32_t)pChnCfg->pDestBuffer & ((1UL << u8DestMod) - 1U)) != 0U)))
|
|
{
|
|
ret = DMA_STATUS_INVALID_ADDRESS;
|
|
}
|
|
/* If circular buffer is enabled, the buffer size must not less than the data offset */
|
|
else if (((pChnCfg->bSrcCircularBufferEn == true) &&
|
|
(pChnCfg->u32SrcCircBufferSize < u16SrcDataOffset)) ||
|
|
((pChnCfg->bDestCircularBufferEn == true) &&
|
|
(pChnCfg->u32DestCircBufferSize < u16SrcDataOffset)))
|
|
{
|
|
ret = DMA_STATUS_UNSUPPORTED;
|
|
}
|
|
/* If source or destination unalign modulo is used, check whether all DUMO registers are occupied */
|
|
else if ((bUseSrcDumo == true) || (bUseDestDumo == true))
|
|
{
|
|
ret = DMA_GetDumoIndex(&u8DumoIndex);
|
|
if (ret == DMA_STATUS_SUCCESS)
|
|
{
|
|
s_aDmaDumoUsedStatus[u8DumoIndex] = (uint8_t)eChannel;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret = DMA_STATUS_SUCCESS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret = DMA_STATUS_SUCCESS;
|
|
}
|
|
|
|
if (ret == DMA_STATUS_SUCCESS)
|
|
{
|
|
if (pChnCfg->bSrcAddrLoopbackEn == true)
|
|
{
|
|
if (pChnCfg->bSrcBlockOffsetEn == false)
|
|
{
|
|
s32SrcLastOffset = -((int32_t)((pChnCfg->u32BlockSize >> pChnCfg->eSrcDataSize) * u16SrcDataOffset) *
|
|
(int32_t)(pChnCfg->u16BlockCount));
|
|
}
|
|
else
|
|
{
|
|
s32SrcLastOffset = -(((int32_t)((pChnCfg->u32BlockSize >> pChnCfg->eSrcDataSize) * u16SrcDataOffset)) *
|
|
(int32_t)(pChnCfg->u16BlockCount)) - ((pChnCfg->s32BlockOffset) * (int32_t)(pChnCfg->u16BlockCount - 1U));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s32SrcLastOffset = 0;
|
|
}
|
|
if (pChnCfg->bDestAddrLoopbackEn == true)
|
|
{
|
|
if (pChnCfg->bDestBlockOffsetEn == false)
|
|
{
|
|
s32DestLastOffset = -(((pChnCfg->u32BlockSize >> pChnCfg->eDestDataSize) * u16DestDataOffset) *
|
|
(pChnCfg->u16BlockCount));
|
|
}
|
|
else
|
|
{
|
|
s32DestLastOffset = -(((int32_t)((pChnCfg->u32BlockSize >> pChnCfg->eDestDataSize) * u16DestDataOffset)) *
|
|
(int32_t)(pChnCfg->u16BlockCount)) - ((pChnCfg->s32BlockOffset) * (int32_t)(pChnCfg->u16BlockCount - 1U));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s32DestLastOffset = 0;
|
|
}
|
|
|
|
DMA_HWA_SetSrcAddr(pDma, (uint8_t)eChannel, (uint32_t)pChnCfg->pSrcBuffer);
|
|
DMA_HWA_SetDestAddr(pDma, (uint8_t)eChannel, (uint32_t)pChnCfg->pDestBuffer);
|
|
DMA_HWA_SetPriority(pDma, (uint8_t)eChannel, pChnCfg->u8ChannelPriority);
|
|
|
|
if ((pChnCfg->bSrcCircularBufferEn == true) && (pChnCfg->bDestCircularBufferEn == true))
|
|
{
|
|
DMA_HWA_SetSrcDataSize(pDma, (uint8_t)eChannel, pChnCfg->eSrcDataSize);
|
|
DMA_HWA_SetSrcModulo(pDma, (uint8_t)eChannel, u8SrcMod);
|
|
DMA_HWA_SetDestDataSize(pDma, (uint8_t)eChannel, pChnCfg->eDestDataSize);
|
|
DMA_HWA_SetDestModulo(pDma, (uint8_t)eChannel, u8DestMod);
|
|
}
|
|
else if (pChnCfg->bSrcCircularBufferEn == true)
|
|
{
|
|
DMA_HWA_SetSrcDataSize(pDma, (uint8_t)eChannel, pChnCfg->eSrcDataSize);
|
|
DMA_HWA_SetSrcModulo(pDma, (uint8_t)eChannel, u8SrcMod);
|
|
DMA_HWA_SetDestDataSize(pDma, (uint8_t)eChannel, pChnCfg->eDestDataSize);
|
|
DMA_HWA_SetDestModulo(pDma, (uint8_t)eChannel, 0U);
|
|
}
|
|
else if (pChnCfg->bDestCircularBufferEn == true)
|
|
{
|
|
DMA_HWA_SetSrcDataSize(pDma, (uint8_t)eChannel, pChnCfg->eSrcDataSize);
|
|
DMA_HWA_SetSrcModulo(pDma, (uint8_t)eChannel, 0U);
|
|
DMA_HWA_SetDestDataSize(pDma, (uint8_t)eChannel, pChnCfg->eDestDataSize);
|
|
DMA_HWA_SetDestModulo(pDma, (uint8_t)eChannel, u8DestMod);
|
|
}
|
|
else
|
|
{
|
|
DMA_HWA_SetSrcDataSize(pDma, (uint8_t)eChannel, pChnCfg->eSrcDataSize);
|
|
DMA_HWA_SetSrcModulo(pDma, (uint8_t)eChannel, 0U);
|
|
DMA_HWA_SetDestDataSize(pDma, (uint8_t)eChannel, pChnCfg->eDestDataSize);
|
|
DMA_HWA_SetDestModulo(pDma, (uint8_t)eChannel, 0U);
|
|
}
|
|
|
|
if (bUseSrcDumo == true)
|
|
{
|
|
u16Sumo = (uint16_t)((pChnCfg->u32SrcCircBufferSize / u16SrcDataOffset - 1U) * u16SrcDataOffset);
|
|
}
|
|
if (bUseDestDumo == true)
|
|
{
|
|
u16Dumo = (uint16_t)((pChnCfg->u32DestCircBufferSize / u16DestDataOffset - 1U) * u16DestDataOffset);
|
|
}
|
|
if ((bUseSrcDumo == true) || (bUseDestDumo == true))
|
|
{
|
|
DMA_HWA_SetUnalignModulo(pDma, u8DumoIndex, u16Sumo, u16Dumo);
|
|
DMA_HWA_SetUnalignModuloEnableFlag(pDma, (uint8_t)eChannel, bUseSrcDumo, bUseDestDumo);
|
|
DMA_HWA_SetUnalignModuloSel(pDma, (uint8_t)eChannel, u8DumoIndex);
|
|
}
|
|
DMA_HWA_SetAutoDisableReuqestEnableFlag(pDma, (uint8_t)eChannel, pChnCfg->bAutoStop);
|
|
|
|
DMA_HWA_SetSrcOffset(pDma, (uint8_t)eChannel, (int16_t)u16SrcDataOffset);
|
|
DMA_HWA_SetDestOffset(pDma, (uint8_t)eChannel, (int16_t)u16DestDataOffset);
|
|
|
|
DMA_HWA_SetInnerLoopOffset(pDma, (uint8_t)eChannel, pChnCfg->bSrcBlockOffsetEn, pChnCfg->bDestBlockOffsetEn,
|
|
pChnCfg->s32BlockOffset);
|
|
DMA_HWA_SetInnerLoopSize(pDma, (uint8_t)eChannel, pChnCfg->u32BlockSize);
|
|
|
|
if ((pChnCfg->u16BlockCount > 1U) && (true == pChnCfg->bInnerChannelChain))
|
|
{
|
|
DMA_HWA_SetChannelToChannelTrig(pDma, (uint8_t)eChannel, true, (uint8_t)eChannel);
|
|
DMA_HWA_SetLoopCount(pDma, (uint8_t)eChannel, pChnCfg->u16BlockCount);
|
|
}
|
|
else
|
|
{
|
|
DMA_HWA_SetChannelToChannelTrig(pDma, (uint8_t)eChannel, false, 0U);
|
|
DMA_HWA_SetLoopCount(pDma, (uint8_t)eChannel, pChnCfg->u16BlockCount);
|
|
}
|
|
|
|
DMA_HWA_SetSrcLastAddrAdjustment(pDma, (uint8_t)eChannel, s32SrcLastOffset);
|
|
DMA_HWA_SetDestLastAddrAdjustment(pDma, (uint8_t)eChannel, s32DestLastOffset);
|
|
|
|
if (pChnCfg->eTriggerSrc == DMA_REQ_DISABLED)
|
|
{
|
|
DMAMUX_HWA_SetRequestSource(pDmamux, (uint8_t)eChannel, false, DMA_REQ_DISABLED);
|
|
}
|
|
else
|
|
{
|
|
DMAMUX_HWA_SetRequestSource(pDmamux, (uint8_t)eChannel, true, pChnCfg->eTriggerSrc);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void DMA_DeinitChannel(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel)
|
|
{
|
|
DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX);
|
|
DEV_ASSERT(eChannel < DMA_CHANNEL_MAX);
|
|
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[eDma_Instance];
|
|
uint8_t u8DumoIndex;
|
|
|
|
for (u8DumoIndex = 0U; u8DumoIndex < DMA_DUMO_COUNT; u8DumoIndex++)
|
|
{
|
|
if (s_aDmaDumoUsedStatus[u8DumoIndex] == (uint8_t)eChannel)
|
|
{
|
|
s_aDmaDumoUsedStatus[u8DumoIndex] = DMA_CHANNEL_INVALID;
|
|
DMA_HWA_SetUnalignModulo(pDma, u8DumoIndex, 0U, 0U);
|
|
}
|
|
}
|
|
DMA_HWA_SetUnalignModuloEnableFlag(pDma, (uint8_t)eChannel, false, false);
|
|
DMA_HWA_DisableChannelErrorInterrupt(pDma, (uint8_t)eChannel);
|
|
DMA_HWA_DisableChannelRequest(pDma, (uint8_t)eChannel);
|
|
DMA_HWA_ClearChannelDoneStatus(pDma, (uint8_t)eChannel);
|
|
DMA_HWA_ClearChannelErrorFlag(pDma, (uint8_t)eChannel);
|
|
DMA_HWA_ClearChannelInterruptFlag(pDma, (uint8_t)eChannel);
|
|
|
|
DMA_HWA_SetSrcAddr(pDma, (uint8_t)eChannel, 0U);
|
|
DMA_HWA_SetSrcOffset(pDma, (uint8_t)eChannel, 0);
|
|
DMA_HWA_SetSrcLastAddrAdjustment(pDma, (uint8_t)eChannel, 0);
|
|
DMA_HWA_SetDestAddr(pDma, (uint8_t)eChannel, 0U);
|
|
DMA_HWA_SetDestOffset(pDma, (uint8_t)eChannel, 0);
|
|
DMA_HWA_SetDestLastAddrAdjustment(pDma, (uint8_t)eChannel, 0);
|
|
DMA_HWA_SetSrcDataSize(pDma, (uint8_t)eChannel, DMA_TRANSFER_SIZE_1B);
|
|
DMA_HWA_SetSrcModulo(pDma, (uint8_t)eChannel, 0U);
|
|
DMA_HWA_SetDestDataSize(pDma, (uint8_t)eChannel, DMA_TRANSFER_SIZE_1B);
|
|
DMA_HWA_SetDestModulo(pDma, (uint8_t)eChannel, 0U);
|
|
DMA_HWA_SetInnerLoopOffset(pDma, (uint8_t)eChannel, false, false, 0);
|
|
DMA_HWA_SetInnerLoopSize(pDma, (uint8_t)eChannel, 0U);
|
|
DMA_HWA_SetChannelControlStatus(pDma, (uint8_t)eChannel, 0U);
|
|
DMA_HWA_SetChannelToChannelTrig(pDma, (uint8_t)eChannel, false, 0U);
|
|
DMA_HWA_SetLoopCount(pDma, (uint8_t)eChannel, 0U);
|
|
}
|
|
|
|
void DMA_InitChannelInterrupt(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel, const DMA_InterruptCfgType *const pInterruptCfg)
|
|
{
|
|
DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX);
|
|
DEV_ASSERT(eChannel < DMA_CHANNEL_MAX);
|
|
DEV_ASSERT(pInterruptCfg != NULL);
|
|
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[eDma_Instance];
|
|
|
|
if (pInterruptCfg->bTransferCompleteIntEn)
|
|
{
|
|
s_dmaTransferCompleteNotify[eDma_Instance][eChannel] = pInterruptCfg->pTransferCompleteNotify;
|
|
DMA_HWA_EnableTransferCompleteInterrupt(pDma, (uint8_t)eChannel);
|
|
//IntMgr_EnableInterrupt(DMA_GetChannelIRQn(eChannel));
|
|
}
|
|
else
|
|
{
|
|
DMA_HWA_DisableTransferCompleteInterrupt(pDma, (uint8_t)eChannel);
|
|
s_dmaTransferCompleteNotify[eDma_Instance][eChannel] = NULL;
|
|
//IntMgr_DisableInterrupt(DMA_GetChannelIRQn(eChannel));
|
|
}
|
|
|
|
if (pInterruptCfg->bTransferErrorIntEn)
|
|
{
|
|
s_dmaTransferErrorNotify[eDma_Instance][eChannel] = pInterruptCfg->pTransferErrorNotify;
|
|
DMA_HWA_EnableChannelErrorInterrupt(pDma, (uint8_t)eChannel);
|
|
//IntMgr_EnableInterrupt(DMA_error_IRQn);
|
|
}
|
|
else
|
|
{
|
|
DMA_HWA_DisableChannelErrorInterrupt(pDma, (uint8_t)eChannel);
|
|
s_dmaTransferErrorNotify[eDma_Instance][eChannel] = NULL;
|
|
//if (DMA_HWA_GetAllChannelErrorInterruptEnableFlag(pDma) == 0U)
|
|
//{
|
|
//IntMgr_DisableInterrupt(DMA_error_IRQn);
|
|
//}
|
|
}
|
|
}
|
|
|
|
void DMA_ConfigChainedTransfer(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel,
|
|
const DMA_ChainTransferType *const pChainTransferCfg)
|
|
{
|
|
DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX);
|
|
DEV_ASSERT(eChannel < DMA_CHANNEL_MAX);
|
|
DEV_ASSERT(pChainTransferCfg != NULL);
|
|
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[eDma_Instance];
|
|
|
|
DMA_HWA_SetOuterLoopTrigEnableFlag(pDma, (uint8_t)eChannel, pChainTransferCfg->bChanelChainEn);
|
|
DMA_HWA_SetOuterLoopTrigChannel(pDma, (uint8_t)eChannel, pChainTransferCfg->u8ChainedChannel);
|
|
}
|
|
|
|
DMA_StatusType DMA_ModifyAddress(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel,
|
|
const volatile void *pSrcBuffer, const volatile void *pDestBuffer)
|
|
{
|
|
DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX);
|
|
DEV_ASSERT(eChannel < DMA_CHANNEL_MAX);
|
|
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[eDma_Instance];
|
|
DMA_StatusType ret;
|
|
|
|
if (DMA_GetChannelStatus(eDma_Instance, eChannel) == DMA_RUNNING_STATUS_IDLE)
|
|
{
|
|
if (pSrcBuffer != NULL)
|
|
{
|
|
DMA_HWA_SetSrcAddr(pDma, (uint8_t)eChannel, (uint32_t)pSrcBuffer);
|
|
}
|
|
if (pDestBuffer != NULL)
|
|
{
|
|
DMA_HWA_SetDestAddr(pDma, (uint8_t)eChannel, (uint32_t)pDestBuffer);
|
|
}
|
|
ret = DMA_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
ret = DMA_STATUS_BUSY;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void DMA_StartChannel(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel)
|
|
{
|
|
DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX);
|
|
DEV_ASSERT(eChannel < DMA_CHANNEL_MAX);
|
|
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[eDma_Instance];
|
|
|
|
if (DMA_GetChannelRequestSrc(eDma_Instance, eChannel) == DMA_REQ_DISABLED)
|
|
{
|
|
DMA_HWA_SetChannelStart(pDma, (uint8_t)eChannel);
|
|
}
|
|
else
|
|
{
|
|
DMA_HWA_EnableChannelRequest(pDma, (uint8_t)eChannel);
|
|
}
|
|
}
|
|
|
|
void DMA_StopChannel(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel)
|
|
{
|
|
DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX);
|
|
DEV_ASSERT(eChannel < DMA_CHANNEL_MAX);
|
|
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[eDma_Instance];
|
|
|
|
DMA_HWA_DisableChannelRequest(pDma, (uint8_t)eChannel);
|
|
}
|
|
|
|
DMA_StatusType DMA_CancelTransfer(const DMA_InstanceType eDma_Instance, bool bGenerateErr)
|
|
{
|
|
DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX);
|
|
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[eDma_Instance];
|
|
DMA_StatusType eRet;
|
|
uint32_t u32TimeOut = 15000000U;
|
|
|
|
if (bGenerateErr)
|
|
{
|
|
DMA_HWA_ErrorCancelTransfer(pDma);
|
|
while ((DMA_HWA_GetErrorCancelTransferStatus(pDma) == true) && (u32TimeOut != 0U))
|
|
{
|
|
u32TimeOut--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DMA_HWA_CancelTransfer(pDma);
|
|
while ((DMA_HWA_GetCancelTransferStatus(pDma) == true) && (u32TimeOut != 0U))
|
|
{
|
|
u32TimeOut--;
|
|
}
|
|
}
|
|
if (u32TimeOut != 0U)
|
|
{
|
|
eRet = DMA_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
eRet = DMA_STATUS_TIMEOUT;
|
|
}
|
|
return eRet;
|
|
}
|
|
|
|
DMA_RequestSourceType DMA_GetChannelRequestSrc(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel)
|
|
{
|
|
DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX);
|
|
DEV_ASSERT(eChannel < DMA_CHANNEL_MAX);
|
|
|
|
DMAMUX_Type * aDmamux[] = DMAMUX_BASE_PTRS;
|
|
DMAMUX_Type *const pDmamux = aDmamux[eDma_Instance];
|
|
|
|
DMA_RequestSourceType eReqSrc = DMAMUX_HWA_GetRequestSource(pDmamux, (uint8_t)eChannel);
|
|
|
|
return eReqSrc;
|
|
}
|
|
|
|
DMA_RunningStatusType DMA_GetStatus(const DMA_InstanceType eDma_Instance)
|
|
{
|
|
DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX);
|
|
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[eDma_Instance];
|
|
DMA_RunningStatusType eDMAStatus = DMA_HWA_GetStatus(pDma);
|
|
return eDMAStatus;
|
|
}
|
|
|
|
DMA_RunningStatusType DMA_GetChannelStatus(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel)
|
|
{
|
|
DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX);
|
|
DEV_ASSERT(eChannel < DMA_CHANNEL_MAX);
|
|
|
|
DMA_Type * aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[eDma_Instance];
|
|
DMA_RunningStatusType eChannelStatus = DMA_HWA_GetChannelActiveStatus(pDma, (uint8_t)eChannel);
|
|
return eChannelStatus;
|
|
}
|