1199 lines
40 KiB
C
1199 lines
40 KiB
C
/**
|
|
* @file module_driver_dma.c
|
|
* @author flagchip
|
|
* @brief DMA driver source code
|
|
* @version 2.0.0
|
|
* @date 2024-08-20
|
|
*
|
|
* SDK Version: 2.6.0
|
|
*
|
|
|
|
* @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd.
|
|
*
|
|
*/
|
|
/* ********************************************************************************
|
|
* Revision History:
|
|
*
|
|
* Version Date Author CR# Descriptions
|
|
* --------- ---------- ------------ ---------- ---------------
|
|
* 0.1.0 2022-12-10 Flagchip N/A First version for FC7300
|
|
* 0.2.0 2023-02-13 Flagchip N/A Fix MISRA issues
|
|
* 0.3.0 2024-08-05 Flagchip099 N/A SDK 2.0 release version
|
|
******************************************************************************** */
|
|
|
|
#include "module_driver_dma.h"
|
|
|
|
#if DMA_INSTANCE_COUNT > 0U
|
|
|
|
#ifndef DMA_DEV_ERROR_REPORT
|
|
#define DMA_DEV_ERROR_REPORT STD_OFF
|
|
#endif
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
#define DMA_ReportDevError(func, error) ReportDevError(DMA_MODULE_ID, func, error)
|
|
#endif
|
|
|
|
/**
|
|
* @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(DMA_HandleType *pDmaHandle, 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
|
|
*/
|
|
#if ((DEVICE_NAME >= FC7300FxMDxxxxxT1B_DEVICE_START) && (DEVICE_NAME <= FC7300F4MDS2P176T1B))
|
|
static inline DMA_StatusType DMA_GetDumoIndex(DMA_HandleType *pDmaHandle, uint8_t *pDumoIndex)
|
|
{
|
|
DMA_StatusType ret = DMA_STATUS_ERROR;
|
|
uint8_t u8Dma_Instance = pDmaHandle->tSettings.pInstance->tSettings.u8Instance;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
uint8_t u8val;
|
|
|
|
if (DMA_HWA_GetOuterLoopTrigEnableFlag(pDma, pDmaHandle->tSettings.u8Channel) == FALSE)
|
|
{
|
|
for (*pDumoIndex = 0U; *pDumoIndex < DMA_UMO_COUNT; (*pDumoIndex)++)
|
|
{
|
|
if (pDmaHandle->tSettings.pInstance->tStatus.u8DmaDumoUsedStatus[*pDumoIndex] == DMA_CHANNEL_INVALID)
|
|
{
|
|
ret = DMA_STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
if (*pDumoIndex == DMA_UMO_COUNT)
|
|
{
|
|
ret = DMA_STATUS_NO_RESOURCE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Workaround for 12 bit conflict in CFG_CSRn */
|
|
u8val = DMA_HWA_GetOuterLoopTrigChannel(pDma, pDmaHandle->tSettings.u8Channel) >> 4;
|
|
for (*pDumoIndex = 0U; *pDumoIndex < DMA_UMO_COUNT; (*pDumoIndex)++)
|
|
{
|
|
if ((pDmaHandle->tSettings.pInstance->tStatus.u8DmaDumoUsedStatus[*pDumoIndex] == DMA_CHANNEL_INVALID) && ((*pDumoIndex & 1U) == u8val))
|
|
{
|
|
ret = DMA_STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
#else
|
|
static inline DMA_StatusType DMA_GetDumoIndex(DMA_HandleType *pDmaHandle, uint8_t *pDumoIndex)
|
|
{
|
|
DMA_StatusType ret = DMA_STATUS_ERROR;
|
|
|
|
for (*pDumoIndex = 0U; *pDumoIndex < DMA_UMO_COUNT; (*pDumoIndex)++)
|
|
{
|
|
if (pDmaHandle->tSettings.pInstance->tStatus.u8DmaDumoUsedStatus[*pDumoIndex] == DMA_CHANNEL_INVALID)
|
|
{
|
|
ret = DMA_STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
if (*pDumoIndex == DMA_UMO_COUNT)
|
|
{
|
|
ret = DMA_STATUS_NO_RESOURCE;
|
|
}
|
|
return ret;
|
|
}
|
|
#endif
|
|
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 DMA_Transfer_Complete_IRQHandler(DMA_HandleType *pDmaHandle)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaHandle->tSettings.pInstance->tSettings.u8Instance;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
|
|
DMA_HWA_ClearChannelInterruptFlag(pDma, pDmaHandle->tSettings.u8Channel);
|
|
if (pDmaHandle->tSettings.callback.pTransferCompleteCallback != NULL)
|
|
{
|
|
pDmaHandle->tSettings.callback.pTransferCompleteCallback(pDmaHandle->tSettings.callback.completedata);
|
|
}
|
|
}
|
|
|
|
void DMA_ProcessErrorInterrupt(DMA_InstanceHandleType *pDmaInstanceHandle)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaInstanceHandle->tSettings.u8Instance;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
uint8_t u8Channel;
|
|
|
|
for (u8Channel = 0U; u8Channel < DMA_CFG_COUNT; u8Channel++)
|
|
{
|
|
if (DMA_HWA_GetChannelErrorFlag(pDma, u8Channel) == true)
|
|
{
|
|
DMA_HWA_ClearChannelErrorFlag(pDma, u8Channel);
|
|
if (pDmaInstanceHandle->tSettings.pTransferErrorCallback[u8Channel] != NULL)
|
|
{
|
|
pDmaInstanceHandle->tSettings.pTransferErrorCallback[u8Channel](pDmaInstanceHandle->tSettings.errdata[u8Channel]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
/* Reset channel0~3 period trigger */
|
|
for (u8Index = 0U; u8Index < DMA_PERIOD_CHANNEL_COUNT; u8Index++)
|
|
{
|
|
DMAMUX_HWA_SetPeriodicTrigFlag(Dmamux_Instance, u8Index, false);
|
|
}
|
|
}
|
|
|
|
#ifdef DMA_HAVE_BACKDOOR
|
|
static uint32_t Dma_SrcTranstoBackdoorAddress(uint32_t u32InputSrc)
|
|
{
|
|
uint32_t u32SrcAddr = u32InputSrc;
|
|
|
|
if ((uint8_t)0U == Dma_GetCoreId())
|
|
{
|
|
if ((u32InputSrc >= DTCM_ADDRESS_START) && (u32InputSrc <= DTCM_ADDRESS_STOP))
|
|
{
|
|
u32SrcAddr = u32InputSrc + DTCM0_BACKDOOR;
|
|
}
|
|
else if (u32InputSrc <= ITCM_ADDRESS_STOP)
|
|
{
|
|
u32SrcAddr = u32InputSrc + ITCM0_BACKDOOR;
|
|
}
|
|
else
|
|
{
|
|
/* SRAM or Reg */
|
|
}
|
|
}
|
|
else if ((uint8_t)1U == Dma_GetCoreId())
|
|
{
|
|
if ((u32InputSrc >= DTCM_ADDRESS_START) && (u32InputSrc <= DTCM_ADDRESS_STOP))
|
|
{
|
|
u32SrcAddr = u32InputSrc + DTCM1_BACKDOOR;
|
|
}
|
|
else if (u32InputSrc <= ITCM_ADDRESS_STOP)
|
|
{
|
|
u32SrcAddr = u32InputSrc + ITCM1_BACKDOOR;
|
|
}
|
|
else
|
|
{
|
|
/* SRAM or Reg */
|
|
}
|
|
}
|
|
else if ((uint8_t)2U == Dma_GetCoreId())
|
|
{
|
|
if ((u32InputSrc >= DTCM_ADDRESS_START) && (u32InputSrc <= DTCM_ADDRESS_STOP))
|
|
{
|
|
u32SrcAddr = u32InputSrc + DTCM2_BACKDOOR;
|
|
}
|
|
else if (u32InputSrc <= ITCM_ADDRESS_STOP)
|
|
{
|
|
u32SrcAddr = u32InputSrc + ITCM2_BACKDOOR;
|
|
}
|
|
else
|
|
{
|
|
/* SRAM or Reg */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* It will never go here */
|
|
}
|
|
return u32SrcAddr;
|
|
}
|
|
|
|
static uint32_t Dma_DesTranstoBackdoorAddress(uint32_t u32InputDes)
|
|
{
|
|
uint32_t u32DesAddr = u32InputDes;
|
|
|
|
if ((uint8_t)0U == Dma_GetCoreId())
|
|
{
|
|
if ((u32InputDes >= DTCM_ADDRESS_START) && (u32InputDes <= DTCM_ADDRESS_STOP))
|
|
{
|
|
/* DTCM0 */
|
|
u32DesAddr = u32InputDes + DTCM0_BACKDOOR;
|
|
}
|
|
else if (u32InputDes <= ITCM_ADDRESS_STOP)
|
|
{
|
|
/* ITCM0 */
|
|
u32DesAddr = u32InputDes + ITCM0_BACKDOOR;
|
|
}
|
|
else
|
|
{
|
|
/* SRAM or Reg */
|
|
}
|
|
}
|
|
else if ((uint8_t)1U == Dma_GetCoreId())
|
|
{
|
|
if ((u32InputDes >= DTCM_ADDRESS_START) && (u32InputDes <= DTCM_ADDRESS_STOP))
|
|
{
|
|
/* DTCM1 */
|
|
u32DesAddr = u32InputDes + DTCM1_BACKDOOR;
|
|
}
|
|
else if (u32InputDes <= ITCM_ADDRESS_STOP)
|
|
{
|
|
/* ITCM1 */
|
|
u32DesAddr = u32InputDes + ITCM1_BACKDOOR;
|
|
}
|
|
else
|
|
{
|
|
/* SRAM or Reg */
|
|
}
|
|
}
|
|
else if ((uint8_t)2U == Dma_GetCoreId())
|
|
{
|
|
if ((u32InputDes >= DTCM_ADDRESS_START) && (u32InputDes <= DTCM_ADDRESS_STOP))
|
|
{
|
|
/* DTCM2 */
|
|
u32DesAddr = u32InputDes + DTCM2_BACKDOOR;
|
|
}
|
|
else if (u32InputDes <= ITCM_ADDRESS_STOP)
|
|
{
|
|
/* ITCM2 */
|
|
u32DesAddr = u32InputDes + ITCM2_BACKDOOR;
|
|
}
|
|
else
|
|
{
|
|
/* SRAM or Reg */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* It will never go here */
|
|
}
|
|
return u32DesAddr;
|
|
}
|
|
#endif
|
|
|
|
void DMA_Init(DMA_InstanceHandleType *pDmaInstanceHandle, const DMA_InitType *const pInitCfg)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaInstanceHandle->tSettings.u8Instance;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else if (pInitCfg == NULL)
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_ID, DMA_E_PARAM_INITCFG);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
|
|
pDmaInstanceHandle->tStatus.u8DmaDumoUsedStatus[0] = 0xFF;
|
|
pDmaInstanceHandle->tStatus.u8DmaDumoUsedStatus[1] = 0xFF;
|
|
pDmaInstanceHandle->tStatus.u8DmaDumoUsedStatus[2] = 0xFF;
|
|
pDmaInstanceHandle->tStatus.u8DmaDumoUsedStatus[3] = 0xFF;
|
|
|
|
DMA_DeInit(pDmaInstanceHandle);
|
|
DMA_HWA_SetHaltOnErrorFlag(pDma, pInitCfg->bHaltOnError);
|
|
DMA_HWA_SetArbitrationAlgorithm(pDma, pInitCfg->eArbitrationAlgorithm);
|
|
DMA_HWA_SetInnerLoopMappingEnableFlag(pDma, true);
|
|
#ifdef DMA_HAVE_GPR
|
|
if (true == pInitCfg->bGRP0HighPriority)
|
|
{
|
|
DMA_HWA_SetGPR1PRIClearGPR0PRI(pDma);
|
|
}
|
|
else
|
|
{
|
|
DMA_HWA_SetGPR0PRIClearGPR1PRI(pDma);
|
|
}
|
|
#endif
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DMA_DeInit(DMA_InstanceHandleType *pDmaInstanceHandle)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaInstanceHandle->tSettings.u8Instance;
|
|
uint8_t u8Index;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
DMAMUX_Type *aDmamux[] = DMAMUX_BASE_PTRS;
|
|
DMAMUX_Type *const pDmamux = aDmamux[u8Dma_Instance];
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
|
|
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->UME[0] = 0U;
|
|
#if (DMA_UME_COUNT == 2)
|
|
pDma->UME[1] = 0U;
|
|
#endif
|
|
for (u8Index = 0U; u8Index < DMA_UMO_COUNT; u8Index++)
|
|
{
|
|
DMA_HWA_SetUnalignModulo(pDma, u8Index, 0U, 0U);
|
|
}
|
|
for (u8Index = 0U; u8Index < DMA_CFG_COUNT; u8Index++)
|
|
{
|
|
DMA_HWA_SetPriority(pDma, u8Index, u8Index);
|
|
pDma->CFG[u8Index].SADDR = 0UL;
|
|
pDma->CFG[u8Index].SOFF = 0U;
|
|
pDma->CFG[u8Index].SLAST = 0UL;
|
|
pDma->CFG[u8Index].DADDR = 0UL;
|
|
pDma->CFG[u8Index].DOFF = 0U;
|
|
pDma->CFG[u8Index].DLAST = 0U;
|
|
pDma->CFG[u8Index].ATTR = 0U;
|
|
pDma->CFG[u8Index].NBYTES.ILNO = 0UL;
|
|
pDma->CFG[u8Index].NBYTES.ILOFFNO = 0UL;
|
|
pDma->CFG[u8Index].NBYTES.ILOFFYES = 0UL;
|
|
pDma->CFG[u8Index].CSR = 0U;
|
|
pDma->CFG[u8Index].BLC.CHTRGENNO = 0U;
|
|
pDma->CFG[u8Index].CLC.CHTRGENNO = 0U;
|
|
pDma->CFG[u8Index].BLC.CHTRGENYES = 0U;
|
|
pDma->CFG[u8Index].CLC.CHTRGENYES = 0U;
|
|
}
|
|
|
|
Dmamux_Reset(pDmamux);
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
DMA_StatusType DMA_InitChannel(DMA_HandleType *pDmaHandle, const DMA_ChannelCfgType *const pChnCfg)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaHandle->tSettings.pInstance->tSettings.u8Instance;
|
|
uint8_t u8Channel = pDmaHandle->tSettings.u8Channel;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
DMAMUX_Type *aDmamux[] = DMAMUX_BASE_PTRS;
|
|
DMAMUX_Type *const pDmamux = aDmamux[u8Dma_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;
|
|
#ifdef DMA_HAVE_BACKDOOR
|
|
uint32_t u32SrcAddr;
|
|
uint32_t u32DesAddr;
|
|
#endif
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else if ((uint32_t)u8Channel >= DMA_CHANNEL_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_CHANNEL_ID, DMA_E_PARAM_CHANNEL);
|
|
}
|
|
else if (pChnCfg == NULL)
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_CHANNEL_ID, DMA_E_PARAM_CHCFG);
|
|
}
|
|
else if (pChnCfg->u16BlockCount == 0U)
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_CHANNEL_ID, DMA_E_PARAM_BLOCKCNT);
|
|
}
|
|
else if (pChnCfg->u32BlockSize == 0U)
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_CHANNEL_ID, DMA_E_PARAM_BLOCKSIZE);
|
|
}
|
|
else if (((pChnCfg->u32BlockSize >> pChnCfg->eSrcDataSize) << pChnCfg->eSrcDataSize != pChnCfg->u32BlockSize) ||
|
|
((pChnCfg->u32BlockSize >> pChnCfg->eDestDataSize) << pChnCfg->eDestDataSize != pChnCfg->u32BlockSize))
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_CHANNEL_ID, DMA_E_PARAM_BLOCKSIZE_DATASIZE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
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)
|
|
{
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if (pChnCfg->u32SrcCircBufferSize == 0U)
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_CHANNEL_ID, DMA_E_PARAM_SRCCIRCULARBUFSIZE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
bUseSrcDumo = (bool)(DMA_IsPowerOf2(pChnCfg->u32SrcCircBufferSize, &u8SrcMod) ? false : true);
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
if (pChnCfg->bDestCircularBufferEn == true)
|
|
{
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if (pChnCfg->u32DestCircBufferSize == 0U)
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_CHANNEL_ID, DMA_E_PARAM_DESTCIRCULARBUFSIZE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
bUseDestDumo = (bool)(DMA_IsPowerOf2(pChnCfg->u32DestCircBufferSize, &u8DestMod) ? false : true);
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* 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(pDmaHandle, &u8DumoIndex);
|
|
if (ret == DMA_STATUS_SUCCESS)
|
|
{
|
|
pDmaHandle->tSettings.pInstance->tStatus.u8DmaDumoUsedStatus[u8DumoIndex] = (uint8_t)u8Channel;
|
|
}
|
|
}
|
|
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 = -((int32_t)((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;
|
|
}
|
|
#ifdef DMA_HAVE_BACKDOOR
|
|
/* Translation the input src address and des address to backdoor address if necessary*/
|
|
u32SrcAddr = Dma_SrcTranstoBackdoorAddress((uint32_t)pChnCfg->pSrcBuffer);
|
|
u32DesAddr = Dma_DesTranstoBackdoorAddress((uint32_t)pChnCfg->pDestBuffer);
|
|
DMA_HWA_SetSrcAddr(pDma, (uint8_t)u8Channel, (uint32_t)u32SrcAddr);
|
|
DMA_HWA_SetDestAddr(pDma, (uint8_t)u8Channel, (uint32_t)u32DesAddr);
|
|
#else
|
|
DMA_HWA_SetSrcAddr(pDma, (uint8_t)u8Channel, (uint32_t)pChnCfg->pSrcBuffer);
|
|
DMA_HWA_SetDestAddr(pDma, (uint8_t)u8Channel, (uint32_t)pChnCfg->pDestBuffer);
|
|
#endif
|
|
DMA_HWA_SetPriority(pDma, (uint8_t)u8Channel, pChnCfg->u8ChannelPriority);
|
|
|
|
if ((pChnCfg->bSrcCircularBufferEn == true) && (pChnCfg->bDestCircularBufferEn == true))
|
|
{
|
|
DMA_HWA_SetSrcDataSize(pDma, (uint8_t)u8Channel, pChnCfg->eSrcDataSize);
|
|
DMA_HWA_SetSrcModulo(pDma, (uint8_t)u8Channel, u8SrcMod);
|
|
DMA_HWA_SetDestDataSize(pDma, (uint8_t)u8Channel, pChnCfg->eDestDataSize);
|
|
DMA_HWA_SetDestModulo(pDma, (uint8_t)u8Channel, u8DestMod);
|
|
}
|
|
else if (pChnCfg->bSrcCircularBufferEn == true)
|
|
{
|
|
DMA_HWA_SetSrcDataSize(pDma, (uint8_t)u8Channel, pChnCfg->eSrcDataSize);
|
|
DMA_HWA_SetSrcModulo(pDma, (uint8_t)u8Channel, u8SrcMod);
|
|
DMA_HWA_SetDestDataSize(pDma, (uint8_t)u8Channel, pChnCfg->eDestDataSize);
|
|
DMA_HWA_SetDestModulo(pDma, (uint8_t)u8Channel, 0U);
|
|
}
|
|
else if (pChnCfg->bDestCircularBufferEn == true)
|
|
{
|
|
DMA_HWA_SetSrcDataSize(pDma, (uint8_t)u8Channel, pChnCfg->eSrcDataSize);
|
|
DMA_HWA_SetSrcModulo(pDma, (uint8_t)u8Channel, 0U);
|
|
DMA_HWA_SetDestDataSize(pDma, (uint8_t)u8Channel, pChnCfg->eDestDataSize);
|
|
DMA_HWA_SetDestModulo(pDma, (uint8_t)u8Channel, u8DestMod);
|
|
}
|
|
else
|
|
{
|
|
DMA_HWA_SetSrcDataSize(pDma, (uint8_t)u8Channel, pChnCfg->eSrcDataSize);
|
|
DMA_HWA_SetSrcModulo(pDma, (uint8_t)u8Channel, 0U);
|
|
DMA_HWA_SetDestDataSize(pDma, (uint8_t)u8Channel, pChnCfg->eDestDataSize);
|
|
DMA_HWA_SetDestModulo(pDma, (uint8_t)u8Channel, 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)u8Channel, bUseSrcDumo, bUseDestDumo);
|
|
DMA_HWA_SetUnalignModuloSel(pDma, (uint8_t)u8Channel, u8DumoIndex);
|
|
}
|
|
DMA_HWA_SetAutoDisableReuqestEnableFlag(pDma, (uint8_t)u8Channel, pChnCfg->bAutoStop);
|
|
|
|
DMA_HWA_SetSrcOffset(pDma, (uint8_t)u8Channel, (int16_t)u16SrcDataOffset);
|
|
DMA_HWA_SetDestOffset(pDma, (uint8_t)u8Channel, (int16_t)u16DestDataOffset);
|
|
|
|
DMA_HWA_SetInnerLoopOffset(pDma, (uint8_t)u8Channel, pChnCfg->bSrcBlockOffsetEn, pChnCfg->bDestBlockOffsetEn,
|
|
pChnCfg->s32BlockOffset);
|
|
DMA_HWA_SetInnerLoopSize(pDma, (uint8_t)u8Channel, pChnCfg->u32BlockSize);
|
|
|
|
if ((pChnCfg->u16BlockCount > 1U) && (true == pChnCfg->bInnerChannelChain))
|
|
{
|
|
DMA_HWA_SetChannelToChannelTrig(pDma, (uint8_t)u8Channel, true, (uint8_t)u8Channel);
|
|
DMA_HWA_SetLoopCount(pDma, (uint8_t)u8Channel, pChnCfg->u16BlockCount);
|
|
}
|
|
else
|
|
{
|
|
DMA_HWA_SetChannelToChannelTrig(pDma, (uint8_t)u8Channel, false, 0U);
|
|
DMA_HWA_SetLoopCount(pDma, (uint8_t)u8Channel, pChnCfg->u16BlockCount);
|
|
}
|
|
|
|
DMA_HWA_SetSrcLastAddrAdjustment(pDma, (uint8_t)u8Channel, s32SrcLastOffset);
|
|
DMA_HWA_SetDestLastAddrAdjustment(pDma, (uint8_t)u8Channel, s32DestLastOffset);
|
|
|
|
if (pChnCfg->eTriggerSrc == DMA_REQ_DISABLED)
|
|
{
|
|
DMAMUX_HWA_SetRequestSource(pDmamux, (uint8_t)u8Channel, false, DMA_REQ_DISABLED);
|
|
}
|
|
else
|
|
{
|
|
DMAMUX_HWA_SetRequestSource(pDmamux, (uint8_t)u8Channel, true, pChnCfg->eTriggerSrc);
|
|
}
|
|
DMA_InitChannelInterrupt(pDmaHandle, pChnCfg);
|
|
}
|
|
return ret;
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DMA_DeinitChannel(DMA_HandleType *pDmaHandle)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaHandle->tSettings.pInstance->tSettings.u8Instance;
|
|
uint8_t u8Channel = pDmaHandle->tSettings.u8Channel;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
uint8_t u8DumoIndex;
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_DEINIT_CHANNEL_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else if ((uint32_t)u8Channel >= DMA_CHANNEL_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_DEINIT_CHANNEL_ID, DMA_E_PARAM_CHANNEL);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
for (u8DumoIndex = 0U; u8DumoIndex < DMA_UMO_COUNT; u8DumoIndex++)
|
|
{
|
|
if (pDmaHandle->tSettings.pInstance->tStatus.u8DmaDumoUsedStatus[u8DumoIndex] == (uint8_t)u8Channel)
|
|
{
|
|
pDmaHandle->tSettings.pInstance->tStatus.u8DmaDumoUsedStatus[u8DumoIndex] = DMA_CHANNEL_INVALID;
|
|
DMA_HWA_SetUnalignModulo(pDma, u8DumoIndex, 0U, 0U);
|
|
}
|
|
}
|
|
DMA_HWA_SetUnalignModuloEnableFlag(pDma, (uint8_t)u8Channel, false, false);
|
|
DMA_HWA_DisableChannelErrorInterrupt(pDma, (uint8_t)u8Channel);
|
|
DMA_HWA_DisableChannelRequest(pDma, (uint8_t)u8Channel);
|
|
DMA_HWA_ClearChannelDoneStatus(pDma, (uint8_t)u8Channel);
|
|
DMA_HWA_ClearChannelErrorFlag(pDma, (uint8_t)u8Channel);
|
|
DMA_HWA_ClearChannelInterruptFlag(pDma, (uint8_t)u8Channel);
|
|
|
|
pDma->CFG[u8Channel].SADDR = 0UL;
|
|
pDma->CFG[u8Channel].SOFF = 0U;
|
|
pDma->CFG[u8Channel].SLAST = 0UL;
|
|
pDma->CFG[u8Channel].DADDR = 0UL;
|
|
pDma->CFG[u8Channel].DOFF = 0U;
|
|
pDma->CFG[u8Channel].DLAST = 0U;
|
|
pDma->CFG[u8Channel].ATTR = 0U;
|
|
pDma->CFG[u8Channel].NBYTES.ILNO = 0UL;
|
|
pDma->CFG[u8Channel].NBYTES.ILOFFNO = 0UL;
|
|
pDma->CFG[u8Channel].NBYTES.ILOFFYES = 0UL;
|
|
pDma->CFG[u8Channel].CSR = 0U;
|
|
pDma->CFG[u8Channel].BLC.CHTRGENNO = 0U;
|
|
pDma->CFG[u8Channel].CLC.CHTRGENNO = 0U;
|
|
pDma->CFG[u8Channel].BLC.CHTRGENYES = 0U;
|
|
pDma->CFG[u8Channel].CLC.CHTRGENYES = 0U;
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DMA_InitChannelInterrupt(DMA_HandleType *pDmaHandle, const DMA_ChannelCfgType *const pChnCfg)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaHandle->tSettings.pInstance->tSettings.u8Instance;
|
|
uint8_t u8Channel = pDmaHandle->tSettings.u8Channel;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_CHANNEL_INT_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else if ((uint32_t)u8Channel >= DMA_CHANNEL_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_CHANNEL_INT_ID, DMA_E_PARAM_CHANNEL);
|
|
}
|
|
else if (pChnCfg == NULL)
|
|
{
|
|
DMA_ReportDevError(DMA_INIT_CHANNEL_INT_ID, DMA_E_PARAM_INTERRUPTCFG);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
if (pChnCfg->bTransferCompleteIntEn)
|
|
{
|
|
pDmaHandle->tSettings.callback.pTransferCompleteCallback = pChnCfg->pTransferCompleteNotify;
|
|
pDmaHandle->tSettings.callback.completedata = pChnCfg->completedata;
|
|
DMA_HWA_EnableTransferCompleteInterrupt(pDma, (uint8_t)u8Channel);
|
|
}
|
|
else
|
|
{
|
|
DMA_HWA_DisableTransferCompleteInterrupt(pDma, (uint8_t)u8Channel);
|
|
pDmaHandle->tSettings.callback.pTransferCompleteCallback = NULL;
|
|
}
|
|
|
|
if (pChnCfg->bTransferErrorIntEn)
|
|
{
|
|
pDmaHandle->tSettings.pInstance->tSettings.pTransferErrorCallback[pDmaHandle->tSettings.u8Channel] = pChnCfg->pTransferErrorNotify;
|
|
pDmaHandle->tSettings.pInstance->tSettings.errdata[pDmaHandle->tSettings.u8Channel] = pChnCfg->errdata;
|
|
DMA_HWA_EnableChannelErrorInterrupt(pDma, (uint8_t)u8Channel);
|
|
}
|
|
else
|
|
{
|
|
DMA_HWA_DisableChannelErrorInterrupt(pDma, (uint8_t)u8Channel);
|
|
pDmaHandle->tSettings.pInstance->tSettings.pTransferErrorCallback[pDmaHandle->tSettings.u8Channel] = NULL;
|
|
}
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DMA_ConfigChainedTransfer(DMA_HandleType *pDmaHandle,
|
|
const DMA_ChainTransferType *const pChainTransferCfg)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaHandle->tSettings.pInstance->tSettings.u8Instance;
|
|
uint8_t u8Channel = pDmaHandle->tSettings.u8Channel;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_CHAINED_TRANS_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else if ((uint32_t)u8Channel >= DMA_CHANNEL_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_CHAINED_TRANS_ID, DMA_E_PARAM_CHANNEL);
|
|
}
|
|
else if (pChainTransferCfg == NULL)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_CHAINED_TRANS_ID, DMA_E_PARAM_INTERRUPTCFG);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
DMA_HWA_SetOuterLoopTrigEnableFlag(pDma, (uint8_t)u8Channel, pChainTransferCfg->bChanelChainEn);
|
|
DMA_HWA_SetOuterLoopTrigChannel(pDma, (uint8_t)u8Channel, pChainTransferCfg->u8ChainedChannel);
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
DMA_StatusType DMA_ModifyAddress(DMA_HandleType *pDmaHandle, const volatile void *pSrcBuffer,
|
|
const volatile void *pDestBuffer)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaHandle->tSettings.pInstance->tSettings.u8Instance;
|
|
uint8_t u8Channel = pDmaHandle->tSettings.u8Channel;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
DMA_StatusType ret;
|
|
#ifdef DMA_HAVE_BACKDOOR
|
|
uint32_t u32SrcAddr;
|
|
uint32_t u32DesAddr;
|
|
#endif
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_MODIFY_ADDR_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else if ((uint32_t)u8Channel >= DMA_CHANNEL_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_MODIFY_ADDR_ID, DMA_E_PARAM_CHANNEL);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
if (DMA_GetChannelStatus(pDmaHandle) == DMA_RUNNING_STATUS_IDLE)
|
|
{
|
|
#ifdef DMA_HAVE_BACKDOOR
|
|
/* Translation the input src address and des address to backdoor address if necessary*/
|
|
u32SrcAddr = Dma_SrcTranstoBackdoorAddress((uint32_t)pSrcBuffer);
|
|
u32DesAddr = Dma_DesTranstoBackdoorAddress((uint32_t)pDestBuffer);
|
|
DMA_HWA_SetSrcAddr(pDma, (uint8_t)u8Channel, (uint32_t)u32SrcAddr);
|
|
DMA_HWA_SetDestAddr(pDma, (uint8_t)u8Channel, (uint32_t)u32DesAddr);
|
|
#else
|
|
if (pSrcBuffer != NULL)
|
|
{
|
|
DMA_HWA_SetSrcAddr(pDma, (uint8_t)u8Channel, (uint32_t)pSrcBuffer);
|
|
}
|
|
if (pDestBuffer != NULL)
|
|
{
|
|
DMA_HWA_SetDestAddr(pDma, (uint8_t)u8Channel, (uint32_t)pDestBuffer);
|
|
}
|
|
#endif
|
|
ret = DMA_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
ret = DMA_STATUS_BUSY;
|
|
}
|
|
return ret;
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DMA_StartChannel(DMA_HandleType *pDmaHandle)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaHandle->tSettings.pInstance->tSettings.u8Instance;
|
|
uint8_t u8Channel = pDmaHandle->tSettings.u8Channel;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_START_CH_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else if ((uint32_t)u8Channel >= DMA_CHANNEL_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_START_CH_ID, DMA_E_PARAM_CHANNEL);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
if (DMA_GetChannelRequestSrc(pDmaHandle) == DMA_REQ_DISABLED)
|
|
{
|
|
DMA_HWA_SetChannelStart(pDma, (uint8_t)u8Channel);
|
|
}
|
|
else
|
|
{
|
|
DMA_HWA_EnableChannelRequest(pDma, (uint8_t)u8Channel);
|
|
}
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DMA_StopChannel(DMA_HandleType *pDmaHandle)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaHandle->tSettings.pInstance->tSettings.u8Instance;
|
|
uint8_t u8Channel = pDmaHandle->tSettings.u8Channel;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_STOP_CH_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else if ((uint32_t)u8Channel >= DMA_CHANNEL_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_STOP_CH_ID, DMA_E_PARAM_CHANNEL);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
DMA_HWA_DisableChannelRequest(pDma, (uint8_t)u8Channel);
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
DMA_StatusType DMA_CancelTransfer(DMA_InstanceHandleType *pDmaInstanceHandle, bool bGenerateErr)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaInstanceHandle->tSettings.u8Instance;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
DMA_StatusType eRet;
|
|
uint32_t u32TimeOut = 15000000U;
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_CANCEL_TRANS_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
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;
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
#ifdef DMA_HAVE_MONCHK
|
|
void DMA_EnableMonitorChecker(DMA_InstanceHandleType *pDmaInstanceHandle)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaInstanceHandle->tSettings.u8Instance;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_EN_MON_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
#ifdef DMA0_HAVE_LOCKSTEP
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_1)
|
|
#endif
|
|
{
|
|
DMA_HWA_EnableMonitorChecker(pDma);
|
|
}
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DMA_DisableMonitorChecker(DMA_InstanceHandleType *pDmaInstanceHandle)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaInstanceHandle->tSettings.u8Instance;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_DISABLE_MON_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
#ifdef DMA0_HAVE_LOCKSTEP
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_1)
|
|
#endif
|
|
{
|
|
DMA_HWA_DisableMonitorChecker(pDma);
|
|
}
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DMA_ClearMonitorCheckerAllError(DMA_InstanceHandleType *pDmaInstanceHandle)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaInstanceHandle->tSettings.u8Instance;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_CLEAR_MON_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
#ifdef DMA0_HAVE_LOCKSTEP
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_1)
|
|
#endif
|
|
{
|
|
DMA_HWA_ClearMonitorCheckerAllError(pDma);
|
|
}
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
uint32_t DMA_GetMonitorCheckerErrStatus(DMA_InstanceHandleType *pDmaInstanceHandle)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaInstanceHandle->tSettings.u8Instance;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
uint32_t temp = 0u;
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_GET_MON_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
#ifdef DMA0_HAVE_LOCKSTEP
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_1)
|
|
#endif
|
|
{
|
|
temp = DMA_HWA_GetMonitorCheckerErrStatus(pDma);
|
|
}
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return temp;
|
|
}
|
|
#endif
|
|
DMA_RequestSourceType DMA_GetChannelRequestSrc(DMA_HandleType *pDmaHandle)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaHandle->tSettings.pInstance->tSettings.u8Instance;
|
|
uint8_t u8Channel = pDmaHandle->tSettings.u8Channel;
|
|
DMAMUX_Type *aDmamux[] = DMAMUX_BASE_PTRS;
|
|
DMAMUX_Type *const pDmamux = aDmamux[u8Dma_Instance];
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_GET_CH_REQ_SOURCE_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else if ((uint32_t)u8Channel >= DMA_CHANNEL_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_GET_CH_REQ_SOURCE_ID, DMA_E_PARAM_CHANNEL);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
DMA_RequestSourceType eReqSrc = DMAMUX_HWA_GetRequestSource(pDmamux, (uint8_t)u8Channel);
|
|
|
|
return eReqSrc;
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef DMA_CR_ACTIVE_MASK
|
|
DMA_RunningStatusType DMA_GetStatus(DMA_InstanceHandleType *pDmaInstanceHandle)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaInstanceHandle->tSettings.u8Instance;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_GET_STATUS_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
DMA_RunningStatusType eDMAStatus = DMA_HWA_GetStatus(pDma);
|
|
return eDMAStatus;
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
DMA_RunningStatusType DMA_GetChannelStatus(DMA_HandleType *pDmaHandle)
|
|
{
|
|
uint8_t u8Dma_Instance = pDmaHandle->tSettings.pInstance->tSettings.u8Instance;
|
|
uint8_t u8Channel = pDmaHandle->tSettings.u8Channel;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[u8Dma_Instance];
|
|
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
if ((uint32_t)u8Dma_Instance >= DMA_INSTANCE_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_GET_CH_STATUS_ID, DMA_E_PARAM_INSTANCE);
|
|
}
|
|
else if ((uint32_t)u8Channel >= DMA_CHANNEL_MAX)
|
|
{
|
|
DMA_ReportDevError(DMA_CONFIG_GET_CH_STATUS_ID, DMA_E_PARAM_CHANNEL);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
DMA_RunningStatusType eChannelStatus = DMA_HWA_GetChannelActiveStatus(pDma, (uint8_t)u8Channel);
|
|
return eChannelStatus;
|
|
#if DMA_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#endif /* #if DMA_INSTANCE_COUNT > 0U */
|