/** * @file HwA_dma.h * @author Flagchip0126 * @brief Hardware access layer for DMA * @version 0.1.0 * @date 2024-01-15 * * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. * */ /* ******************************************************************************** * Revision History: * * Version Date Initials CR# Descriptions * --------- ---------- ------------ ---------- --------------- * 0.1.0 2024-01-15 Flagchip0126 N/A First version for FC7240 ******************************************************************************** */ #ifndef _HWA_DMA_H_ #define _HWA_DMA_H_ #include "device_header.h" #define DMA_CH_TO_DCHPRI(x) ((x) ^ 3U) /** * @defgroup HwA_dma * @ingroup fc7xxx_driver_dma * @{ */ /** * @brief DMA running status * */ typedef enum { DMA_RUNNING_STATUS_IDLE = 0x0U, /*!< The DMA engine is idle */ DMA_RUNNING_STATUS_ACTIVE = 0x1U /*!< The DMA engine is transferring data */ } DMA_RunningStatusType; /** * @brief DMA channel arbitration algorithm used in the channel arbitration phase * */ typedef enum { DMA_ARBITRATION_ALGORITHM_FIXED_PRIORITY = 0U, /*!< Use the fixed priority for arbitration */ DMA_ARBITRATION_ALGORITHM_ROUND_ROBIN = 1U /*!< Use the channel number for arbitration, higher channel number has higher priority */ } DMA_ArbitrationAlgorithmType; /** * @brief Defines the size of data in one transfer * * One transfer can contain multiple block, and one block may contain multiple * data, this parameter specifies the size of data which the DMA engine will * access one time in the memory. * */ typedef enum { DMA_TRANSFER_SIZE_1B = 0x0U, DMA_TRANSFER_SIZE_2B = 0x1U, DMA_TRANSFER_SIZE_4B = 0x2U, DMA_TRANSFER_SIZE_8B = 0x3U, DMA_TRANSFER_SIZE_32B = 0x5U } DMA_TransferSizeType; /** * @brief Get active status of the DMA instance * * @param pDma the base address of the DMA instance * @return DMA_RUNNING_STATUS_ACTIVE DMA is executing a channel * @return DMA_RUNNING_STATUS_IDLE DMA is idle */ LOCAL_INLINE DMA_RunningStatusType DMA_HWA_GetStatus(const DMA_Type *const pDma) { uint32_t u32TmpVal = (pDma->CR & DMA_CR_ACTIVE_MASK) >> DMA_CR_ACTIVE_SHIFT; return (DMA_RunningStatusType)u32TmpVal; } /** * @brief Get whether the DMA instance is cancelling * * @param pDma the base address of the DMA instance * @return true cancel operation is requested and has not been finished * @return false DMA is under normal operation */ LOCAL_INLINE bool DMA_HWA_GetCancelTransferStatus(const DMA_Type *const pDma) { uint32_t u32TmpVal = (pDma->CR & DMA_CR_CX_MASK) >> DMA_CR_CX_SHIFT; return (bool)((u32TmpVal != 0U) ? true : false); } /** * @brief Cancel the remaining transfer of the DMA * * @param pDma the base address of the DMA instance */ LOCAL_INLINE void DMA_HWA_CancelTransfer(DMA_Type *const pDma) { pDma->CR |= DMA_CR_CX_MASK; } /** * @brief Get whether the DMA instance is cancelling with error * * @param pDma the base address of the DMA instance * @return true cancel operation is requested and has not been finished * @return false DMA is under normal operation */ LOCAL_INLINE bool DMA_HWA_GetErrorCancelTransferStatus(const DMA_Type *const pDma) { uint32_t u32TmpVal = (pDma->CR & DMA_CR_ECX_MASK) >> DMA_CR_ECX_SHIFT; return (bool)((u32TmpVal != 0U) ? true : false); } /** * @brief Set Channel Group 0 Priority * * @param pDma the base address of the DMA instance */ LOCAL_INLINE void DMA_HWA_SetGPR0PRI(DMA_Type *const pDma) { pDma->CR = (pDma->CR & ~DMA_CR_GPR0PRI_MASK) | DMA_CR_GPR0PRI(1U); } /** * @brief Cancel the remaining transfer of the DMA and generate an error after finished cancelling * * @param pDma the base address of the DMA instance */ LOCAL_INLINE void DMA_HWA_ErrorCancelTransfer(DMA_Type *const pDma) { pDma->CR |= DMA_CR_ECX_MASK; } /** * @brief Get whether inner loop mapping is enabled * * @param pDma the base address of the DMA instance * @return true inner loop mapping is enabled * @return false inner loop mapping is disabled */ LOCAL_INLINE bool DMA_HWA_GetInnerLoopMappingEnableFlag(const DMA_Type *const pDma) { uint32_t u32TmpVal = (pDma->CR & DMA_CR_EILM_MASK) >> DMA_CR_EILM_SHIFT; return (bool)((u32TmpVal != 0U) ? true : false); } /** * @brief Set whether to enable inner loop mapping * * @note Only after enabling inner loop mapping, you can apply an offset to the source * and/or destination address after the inner loop finishes. * * @param pDma the base address of the DMA instance * @param bEnable whether to enable the inner loop mapping */ LOCAL_INLINE void DMA_HWA_SetInnerLoopMappingEnableFlag(DMA_Type *const pDma, bool bEnable) { pDma->CR = (pDma->CR & ~DMA_CR_EILM_MASK) | DMA_CR_EILM(bEnable); } /** * @brief Get whether the continuous trig mode is enabled * When continuous trig mode is enabled, channel arbitration is not used for a inner loop * channel trig before being activated again. Upon inner loop completion, the channel * activates again if that channel has a inner loop channel trig enabled and the trig * channel is itself. This effectively applies the inner loop offsets and restarts the next * inner loop. * * @param pDma the base address of the DMA instance * @return true continuous trig mode is enabled * @return false continuous trig mode is disabled */ LOCAL_INLINE bool DMA_HWA_GetContinuousTrigModeEnableFlag(const DMA_Type *const pDma) { uint32_t u32TmpVal = (pDma->CR & DMA_CR_CTM_MASK) >> DMA_CR_CTM_SHIFT; return (bool)((u32TmpVal != 0U) ? true : false); } /** * @brief Set whether to enable the continuous trig mode * * @param pDma the base address of the DMA instance * @param bEnable whether to enable the continuous trig mode */ LOCAL_INLINE void DMA_HWA_SetContinuousTrigModeEnableFlag(DMA_Type *const pDma, bool bEnable) { pDma->CR = (pDma->CR & ~DMA_CR_CTM_MASK) | DMA_CR_CTM(bEnable); } /** * @brief Get whether the DMA is halted * When the DMA is halted, it will ignore all service requests * @param pDma the base address of the DMA instance * @return true the DMA is halted * @return true the DMA is not halted */ LOCAL_INLINE bool DMA_HWA_GetHatlStatus(const DMA_Type *const pDma) { uint32_t u32TmpVal = (pDma->CR & DMA_CR_HALT_MASK) >> DMA_CR_HALT_SHIFT; return (bool)((u32TmpVal != 0U) ? true : false); } /** * @brief Halt the DMA operations * * @param pDma the base address of the DMA instance */ LOCAL_INLINE void DMA_HWA_HaltOperations(DMA_Type *const pDma) { pDma->CR |= DMA_CR_HALT_MASK; } /** * @brief Clear the halt flag of the DMA instance * After HALT is cleared, the DMA could continue to operate * @param pDma the base address of the DMA instance */ LOCAL_INLINE void DMA_HWA_ClearHaltFlag(DMA_Type *const pDma) { pDma->CR &= ~DMA_CR_HALT_MASK; } /** * @brief Get whether halt on error is enabled on the DMA instance * * @param pDma the base address of the DMA instance * @return true halt on error is enabled, any error will cause HALT flag to be set * @return false halt on error is disabled */ LOCAL_INLINE bool DMA_HWA_GetHaltOnErrorFlag(const DMA_Type *const pDma) { uint32_t u32TmpVal = (pDma->CR & DMA_CR_HOE_MASK) >> DMA_CR_HOE_SHIFT; return (bool)((u32TmpVal != 0U) ? true : false); } /** * @brief Set whether to enable halt on error on the DMA instance * * @note Ff halt on error is enabled, any error will cause HALT flag to be set * * @param pDma the base address of the DMA instance * @param bEnable whether to enable halt on error */ LOCAL_INLINE void DMA_HWA_SetHaltOnErrorFlag(DMA_Type *const pDma, bool bEnable) { pDma->CR = (pDma->CR & ~DMA_CR_HOE_MASK) | DMA_CR_HOE(bEnable); } /** * @brief Get the DMA arbitration algorithm * * @param pDma the base address of the DMA instance * @return DMA_ArbitrationAlgorithmType the DMA arbitration algorithm */ LOCAL_INLINE DMA_ArbitrationAlgorithmType DMA_HWA_GetArbitrationAlgorithm(const DMA_Type *const pDma) { uint32_t u32TmpVal = (pDma->CR & DMA_CR_ERCA_MASK) >> DMA_CR_ERCA_SHIFT; return (DMA_ArbitrationAlgorithmType)u32TmpVal; } /** * @brief Set the DMA arbitration algorithm * * @param pDma the base address of the DMA instance * @param eAlgorithm the DMA arbitration algorithm */ LOCAL_INLINE void DMA_HWA_SetArbitrationAlgorithm(DMA_Type *const pDma, DMA_ArbitrationAlgorithmType eAlgorithm) { pDma->CR = (pDma->CR & ~DMA_CR_ERCA_MASK) | DMA_CR_ERCA(eAlgorithm); } /** * @brief Get whether the DMA is configured to stop under debug mode * * @param pDma the base address of the DMA instance * @return true the DMA is will stop under debug mode * @return true the DMA is will continue to operate under debug mode */ LOCAL_INLINE bool DMA_HWA_GetDebugModeStopFlag(const DMA_Type *const pDma) { uint32_t u32TmpVal = (pDma->CR & DMA_CR_DBGS_MASK) >> DMA_CR_DBGS_SHIFT; return (bool)((u32TmpVal != 0U) ? true : false); } /** * @brief Get the control register of the DMA instance * * @param pDma the base address of the DMA instance * @return uint32_t the control register settings */ LOCAL_INLINE uint32_t DMA_HWA_GetControlRegister(const DMA_Type *const pDma) { return pDma->CR; } /** * @brief Set the control register of the DMA instance * * @param pDma the base address of the DMA instance * @param u32Settings the settings of the DMA control register */ LOCAL_INLINE void DMA_HWA_SetControlRegister(DMA_Type *const pDma, uint32_t u32Settings) { pDma->CR = u32Settings; } /** * @brief Set whether to stop DMA under debug mode * * @param pDma the base address of the DMA instance * @param bEnable whether to stop DMA under debug mode */ LOCAL_INLINE void DMA_HWA_SetDebugModeStopFlag(DMA_Type *const pDma, bool bEnable) { pDma->CR = (pDma->CR & ~DMA_CR_DBGS_MASK) | DMA_CR_DBGS(bEnable); } /** * @brief Get the DMA error status * * @param pDma the base address of the DMA instance * @return uint32_t the DMA error status */ LOCAL_INLINE uint32_t DMA_HWA_GetErrorStatus(const DMA_Type *const pDma) { return pDma->ES; } /** * @brief Get whether there is error occured on the specified channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return true there is error on the specified channel * @return false there is no error on the specified channel */ LOCAL_INLINE bool DMA_HWA_GetChannelErrorFlag(const DMA_Type *const pDma, uint8_t u8Channel) { uint32_t u32TmpVal = (pDma->ERR & (1UL << u8Channel)) >> u8Channel; return (bool)((u32TmpVal != 0U) ? true : false); } /** * @brief Get the channel error status, each bit represents a channel * * @param pDma the base address of the DMA instance * @return uint16_t the channel error status */ LOCAL_INLINE uint16_t DMA_HWA_GetAllChannelErrorFlag(const DMA_Type *const pDma) { uint32_t u32TmpVal = pDma->ERR; return (uint16_t)u32TmpVal; } /** * @brief Get whether error interrupt is enabled on the specified channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return true error interrupt is enabled on the specified channel * @return false error interrupt is disabled on the specified channel */ LOCAL_INLINE bool DMA_HWA_GetChannelErrorInterruptEnableFlag(const DMA_Type *const pDma, uint8_t u8Channel) { uint32_t u32TmpVal = (pDma->EEI & (1UL << u8Channel)) >> u8Channel; return (bool)((u32TmpVal != 0U) ? true : false); } /** * @brief Get channel error interrupt enable status * * @param pDma the base address of the DMA instance * @return uint16_t the channel error interrupt enable status */ LOCAL_INLINE uint16_t DMA_HWA_GetAllChannelErrorInterruptEnableFlag(const DMA_Type *const pDma) { uint32_t u32TmpVal = pDma->EEI; return (uint16_t)u32TmpVal; } /** * @brief Enable error interrupt for the specified channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel */ LOCAL_INLINE void DMA_HWA_EnableChannelErrorInterrupt(DMA_Type *const pDma, uint8_t u8Channel) { pDma->SEEI = DMA_SEEI_SEEI(u8Channel); } /** * @brief Enable error interrupt for all channels * * @param pDma the base address of the DMA instance */ LOCAL_INLINE void DMA_HWA_EnableAllChannelErrorInterrupt(DMA_Type *const pDma) { pDma->SEEI = DMA_SEEI_SAEE_MASK; } /** * @brief Disable error interrupt for the specified channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel */ LOCAL_INLINE void DMA_HWA_DisableChannelErrorInterrupt(DMA_Type *const pDma, uint8_t u8Channel) { pDma->CEEI = DMA_CEEI_CEEI(u8Channel); } /** * @brief Disable error interrupt for all channels * * @param pDma the base address of the DMA instance */ LOCAL_INLINE void DMA_HWA_DisableAllChannelErrorInterrupt(DMA_Type *const pDma) { pDma->CEEI = DMA_CEEI_CAEE_MASK; } /** * @brief Enable channel request for the specified channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel */ LOCAL_INLINE void DMA_HWA_EnableChannelRequest(DMA_Type *const pDma, uint8_t u8Channel) { pDma->SERQ = DMA_SERQ_SERQ(u8Channel); } /** * @brief Enable channel request for all channels * * @param pDma the base address of the DMA instance */ LOCAL_INLINE void DMA_HWA_EnableAllChannelRequest(DMA_Type *const pDma) { pDma->SERQ = DMA_SERQ_SAER_MASK; } /** * @brief Disable channel request for the specified channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel */ LOCAL_INLINE void DMA_HWA_DisableChannelRequest(DMA_Type *const pDma, uint8_t u8Channel) { pDma->CERQ = DMA_CERQ_CERQ(u8Channel); } /** * @brief Disable channel request for all channels * * @param pDma the base address of the DMA instance */ LOCAL_INLINE void DMA_HWA_DisableAllChannelRequest(DMA_Type *const pDma) { pDma->CERQ = DMA_CERQ_CAER_MASK; } /** * @brief Clear DONE bit for the specified channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel */ LOCAL_INLINE void DMA_HWA_ClearChannelDoneStatus(DMA_Type *const pDma, uint8_t u8Channel) { pDma->CDNE = DMA_CDNE_CDNE(u8Channel); } /** * @brief Clear DONE bit for the all channels * * @param pDma the base address of the DMA instance */ LOCAL_INLINE void DMA_HWA_ClearAllChannelDoneStatus(DMA_Type *const pDma) { pDma->CDNE = DMA_CDNE_CADN_MASK; } /** * @brief Clear ERR bit for the specified channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel */ LOCAL_INLINE void DMA_HWA_ClearChannelErrorFlag(DMA_Type *const pDma, uint8_t u8Channel) { pDma->CERR = DMA_CERR_CERR(u8Channel); } /** * @brief Clear ERR bit for the all channels * * @param pDma the base address of the DMA instance */ LOCAL_INLINE void DMA_HWA_ClearAllChannelErrorFlag(DMA_Type *const pDma) { pDma->CERR = DMA_CERR_CAEI_MASK; } /** * @brief Clear interrupt flag for the specified channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel */ LOCAL_INLINE void DMA_HWA_ClearChannelInterruptFlag(DMA_Type *const pDma, uint8_t u8Channel) { pDma->CINT = DMA_CINT_CINT(u8Channel); } /** * @brief Clear interrupt flag for the all channels * * @param pDma the base address of the DMA instance */ LOCAL_INLINE void DMA_HWA_ClearAllChannelInterruptFlag(DMA_Type *const pDma) { pDma->CINT = DMA_CINT_CAIR_MASK; } /** * @brief Set start for the specified channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel */ LOCAL_INLINE void DMA_HWA_SetChannelStart(DMA_Type *const pDma, uint8_t u8Channel) { pDma->SSRT = DMA_SSRT_SSRT(u8Channel); } /** * @brief Set start for the all channels * * @param pDma the base address of the DMA instance */ LOCAL_INLINE void DMA_HWA_SetAllChannelStart(DMA_Type *const pDma) { pDma->SSRT = DMA_SSRT_SAST_MASK; } /** * @brief Get whether source unalign modulo is enabled for the specified channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel */ LOCAL_INLINE bool DMA_HWA_GetSrcUnalignModuloEnableFlag(const DMA_Type *const pDma, uint8_t u8Channel) { uint32_t u32TmpVal = (pDma->DUME[u8Channel/16U] & ((uint32_t)DMA_DUME_SUME0_MASK << (2U * (u8Channel % 16U)))) >> (DMA_DUME_SUME0_SHIFT + 2U * (u8Channel % 16U)); return (bool)((u32TmpVal != 0U) ? true : false); } /** * @brief Get whether destination unalign modulo is enabled for the specified channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel */ LOCAL_INLINE bool DMA_HWA_GetDestUnalignModuloEnableFlag(const DMA_Type *const pDma, uint8_t u8Channel) { uint32_t u32TmpVal = (pDma->DUME[u8Channel/16U] & ((uint32_t)DMA_DUME_DUME0_MASK << (2U * (u8Channel % 16U)))) >> (DMA_DUME_DUME0_SHIFT + 2U * (u8Channel % 16U)); return (bool)((u32TmpVal != 0U) ? true : false); } /** * @brief Get whether to enable unalign modulo for the specified channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param bEnableSrcModulo whether source unalign modulo is to be enabled * @param bEnableDestModulo whether destination unalign modulo is to be enabled */ LOCAL_INLINE void DMA_HWA_SetUnalignModuloEnableFlag(DMA_Type *const pDma, uint8_t u8Channel, bool bEnableSrcModulo, bool bEnableDestModulo) { pDma->DUME[u8Channel/16U] = (pDma->DUME[u8Channel/16U] & ~((DMA_DUME_DUME0_MASK | DMA_DUME_SUME0_MASK) << (2U * (u8Channel % 16U)))) | ((DMA_DUME_DUME0(bEnableDestModulo) | DMA_DUME_SUME0(bEnableSrcModulo)) << (2U * (u8Channel % 16U))); } /** * @brief Get the source unalign modulo of the index * * @param pDma the base address of the DMA instance * @param u8Selection the index of the unalign modulo * @return uint16_t the source unalign modulo */ LOCAL_INLINE uint16_t DMA_HWA_GetSrcUnalignModulo(const DMA_Type *const pDma, uint8_t u8Selection) { uint32_t u32TmpVal = (pDma->DUMO[u8Selection] & DMA_DUMO_SUMO_MASK) >> DMA_DUMO_SUMO_SHIFT; return (uint16_t)u32TmpVal; } /** * @brief Get the destination unalign modulo of the index * * @param pDma the base address of the DMA instance * @param u8Selection the index of the unalign modulo * @return uint16_t the destination unalign modulo */ LOCAL_INLINE uint16_t DMA_HWA_GetDestUnalignModulo(const DMA_Type *const pDma, uint8_t u8Selection) { uint32_t u32TmpVal = (pDma->DUMO[u8Selection] & DMA_DUMO_DUMO_MASK) >> DMA_DUMO_DUMO_SHIFT; return (uint16_t)u32TmpVal; } /** * @brief Set unalign modulo of the index * * @param pDma the base address of the DMA instance * @param u8Selection the index of the unalign modulo * @param u16SrcModulo the source unalign modulo * @param u16DestModulo the destination unalign modulo */ LOCAL_INLINE void DMA_HWA_SetUnalignModulo(DMA_Type *const pDma, uint8_t u8Selection, uint16_t u16SrcModulo, uint16_t u16DestModulo) { pDma->DUMO[u8Selection] = DMA_DUMO_SUMO(u16SrcModulo) | DMA_DUMO_DUMO(u16DestModulo); } /** * @brief Get priority of the channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return uint8_t the priority of the channel */ LOCAL_INLINE uint8_t DMA_HWA_GetPriority(const DMA_Type *const pDma, uint8_t u8Channel) { uint8_t u8TmpVal = pDma->DCHPRI[DMA_CH_TO_DCHPRI(u8Channel)]; return u8TmpVal; } /** * @brief Set priority of the channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param u8Priority the priority of the channel */ LOCAL_INLINE void DMA_HWA_SetPriority(DMA_Type *const pDma, uint8_t u8Channel, uint8_t u8Priority) { pDma->DCHPRI[DMA_CH_TO_DCHPRI(u8Channel)] = u8Priority; } /** * @brief Get the source address of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return uint32_t the source address of the DMA channel */ LOCAL_INLINE uint32_t DMA_HWA_GetSrcAddr(const DMA_Type *const pDma, uint8_t u8Channel) { return pDma->CFG[u8Channel].SADDR; } /** * @brief Set the source address of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param u32SrcAddr the source address of the DMA channel */ LOCAL_INLINE void DMA_HWA_SetSrcAddr(DMA_Type *const pDma, uint8_t u8Channel, uint32_t u32SrcAddr) { pDma->CFG[u8Channel].SADDR = u32SrcAddr; } /** * @brief Get the destination address of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return uint32_t the destination address of the DMA channel */ LOCAL_INLINE uint32_t DMA_HWA_GetDestAddr(const DMA_Type *const pDma, uint8_t u8Channel) { return pDma->CFG[u8Channel].DADDR; } /** * @brief Set the destination address of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param u32DestAddr the destination address of the DMA channel */ LOCAL_INLINE void DMA_HWA_SetDestAddr(DMA_Type *const pDma, uint8_t u8Channel, uint32_t u32DestAddr) { pDma->CFG[u8Channel].DADDR = u32DestAddr; } /** * @brief Get source data offset of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return int16_t the source data offset */ LOCAL_INLINE int16_t DMA_HWA_GetSrcOffset(const DMA_Type *const pDma, uint8_t u8Channel) { return (int16_t)pDma->CFG[u8Channel].SOFF; } /** * @brief Set source data offset of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param s16Offset the source data offset */ LOCAL_INLINE void DMA_HWA_SetSrcOffset(DMA_Type *const pDma, uint8_t u8Channel, int16_t s16Offset) { pDma->CFG[u8Channel].SOFF = (uint16_t)s16Offset; } /** * @brief Get destination data offset of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return int16_t the destination data offset */ LOCAL_INLINE int16_t DMA_HWA_GetDestOffset(const DMA_Type *const pDma, uint8_t u8Channel) { return (int16_t)pDma->CFG[u8Channel].DOFF; } /** * @brief Set destination data offset of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param s16Offset the destination data offset */ LOCAL_INLINE void DMA_HWA_SetDestOffset(DMA_Type *const pDma, uint8_t u8Channel, int16_t s16Offset) { pDma->CFG[u8Channel].DOFF = (uint16_t)s16Offset; } /** * @brief Get the source data size of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return DMA_TransferSizeType the source data size of the DMA channel */ LOCAL_INLINE DMA_TransferSizeType DMA_HWA_GetSrcDataSize(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].ATTR & DMA_CFG_ATTR_SSIZE_MASK) >> DMA_CFG_ATTR_SSIZE_SHIFT; return (DMA_TransferSizeType)u16TmpVal; } /** * @brief Set the source data size of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param eDataSize the source data size of the DMA channel */ LOCAL_INLINE void DMA_HWA_SetSrcDataSize(DMA_Type *const pDma, uint8_t u8Channel, DMA_TransferSizeType eDataSize) { pDma->CFG[u8Channel].ATTR = (pDma->CFG[u8Channel].ATTR & ~DMA_CFG_ATTR_SSIZE_MASK) | DMA_CFG_ATTR_SSIZE(eDataSize); } /** * @brief Get the destination data size of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return DMA_TransferSizeType the destination data size of the DMA channel */ LOCAL_INLINE DMA_TransferSizeType DMA_HWA_GetDestDataSize(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].ATTR & DMA_CFG_ATTR_DSIZE_MASK) >> DMA_CFG_ATTR_DSIZE_SHIFT; return (DMA_TransferSizeType)u16TmpVal; } /** * @brief Set the destination data size of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param eDataSize the destination data size of the DMA channel */ LOCAL_INLINE void DMA_HWA_SetDestDataSize(DMA_Type *const pDma, uint8_t u8Channel, DMA_TransferSizeType eDataSize) { pDma->CFG[u8Channel].ATTR = (pDma->CFG[u8Channel].ATTR & ~DMA_CFG_ATTR_DSIZE_MASK) | DMA_CFG_ATTR_DSIZE(eDataSize); } /** * @brief Get the source address aligned modulo of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return uint8_t the source address aligned modulo */ LOCAL_INLINE uint8_t DMA_HWA_GetSrcModulo(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].ATTR & DMA_CFG_ATTR_SMOD_MASK) >> DMA_CFG_ATTR_SMOD_SHIFT; return (uint8_t)u16TmpVal; } /** * @brief Set the source address aligned modulo of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param u8SrcModulo the source address aligned modulo */ LOCAL_INLINE void DMA_HWA_SetSrcModulo(DMA_Type *const pDma, uint8_t u8Channel, uint8_t u8SrcModulo) { pDma->CFG[u8Channel].ATTR = (pDma->CFG[u8Channel].ATTR & ~DMA_CFG_ATTR_SMOD_MASK) | DMA_CFG_ATTR_SMOD(u8SrcModulo); } /** * @brief Get the destination address aligned modulo of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return uint8_t the destination address aligned modulo */ LOCAL_INLINE uint8_t DMA_HWA_GetDestModulo(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].ATTR & DMA_CFG_ATTR_DMOD_MASK) >> DMA_CFG_ATTR_DMOD_SHIFT; return (uint8_t)u16TmpVal; } /** * @brief Set the destination address aligned modulo of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param u8DestModulo the destination address aligned modulo */ LOCAL_INLINE void DMA_HWA_SetDestModulo(DMA_Type *const pDma, uint8_t u8Channel, uint8_t u8DestModulo) { pDma->CFG[u8Channel].ATTR = (pDma->CFG[u8Channel].ATTR & ~DMA_CFG_ATTR_DMOD_MASK) | DMA_CFG_ATTR_DMOD(u8DestModulo); } /** * @brief Get the address adjustment applied to the source address after major loop finished * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return int32_t the address adjustment applied to the source address after major loop finished */ LOCAL_INLINE int32_t DMA_HWA_GetSrcLastAddrAdjustment(const DMA_Type *const pDma, uint8_t u8Channel) { return (int32_t)pDma->CFG[u8Channel].SLAST; } /** * @brief Set the address adjustment applied to the source address after major loop finished * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param s32LastAdj the address adjustment applied to the source address after major loop finished */ LOCAL_INLINE void DMA_HWA_SetSrcLastAddrAdjustment(DMA_Type *const pDma, uint8_t u8Channel, int32_t s32LastAdj) { pDma->CFG[u8Channel].SLAST = (uint32_t)s32LastAdj; } /** * @brief Get the address adjustment applied to the destination address after major loop finished * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return int32_t the address adjustment applied to the destination address after major loop finished */ LOCAL_INLINE int32_t DMA_HWA_GetDestLastAddrAdjustment(const DMA_Type *const pDma, uint8_t u8Channel) { return (int32_t)pDma->CFG[u8Channel].DLAST; } /** * @brief Set the address adjustment applied to the destination address after major loop finished * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param s32LastAdj the address adjustment applied to the destination address after major loop finished */ LOCAL_INLINE void DMA_HWA_SetDestLastAddrAdjustment(DMA_Type *const pDma, uint8_t u8Channel, int32_t s32LastAdj) { pDma->CFG[u8Channel].DLAST = (uint32_t)s32LastAdj; } /** * @brief Get whether source address inner loop offset is enabled * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return true source address inner loop offset is enabled * @return false source address inner loop offset is disabled */ LOCAL_INLINE bool DMA_HWA_GetInnerLoopSrcOffsetEnableFlag(const DMA_Type *const pDma, uint8_t u8Channel) { uint32_t u32TmpVal; if (DMA_HWA_GetInnerLoopMappingEnableFlag(pDma) == false) { u32TmpVal = 0U; } else { u32TmpVal = (pDma->CFG[u8Channel].NBYTES.ILOFFNO & DMA_CFG_NBYTES_ILOFFNO_SILOE_MASK) >> DMA_CFG_NBYTES_ILOFFNO_SILOE_SHIFT; } return (bool)((u32TmpVal != 0U) ? true : false); } /** * @brief Get whether destination address inner loop offset is enabled * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return true destination address inner loop offset is enabled * @return false destination address inner loop offset is disabled */ LOCAL_INLINE bool DMA_HWA_GetInnerLoopDestOffsetEnableFlag(const DMA_Type *const pDma, uint8_t u8Channel) { uint32_t u32TmpVal; if (DMA_HWA_GetInnerLoopMappingEnableFlag(pDma) == false) { u32TmpVal = 0U; } else { u32TmpVal = (pDma->CFG[u8Channel].NBYTES.ILOFFNO & DMA_CFG_NBYTES_ILOFFNO_DILOE_MASK) >> DMA_CFG_NBYTES_ILOFFNO_DILOE_SHIFT; } return (bool)((u32TmpVal != 0U) ? true : false); } /** * @brief Get the inner loop offset of the DMA channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return int32_t the signed inner loop offset */ LOCAL_INLINE int32_t DMA_HWA_GetInnerLoopOffset(const DMA_Type *const pDma, uint8_t u8Channel) { uint32_t u32TmpVal; if (DMA_HWA_GetInnerLoopMappingEnableFlag(pDma) == false) { u32TmpVal = 0U; } else { bool bDmaInnerLoopSrcOffsetEnable = DMA_HWA_GetInnerLoopSrcOffsetEnableFlag(pDma, u8Channel); bool bDmaInnerLoopDestOffsetEnable = DMA_HWA_GetInnerLoopDestOffsetEnableFlag(pDma, u8Channel); if ((bDmaInnerLoopSrcOffsetEnable == false) && (bDmaInnerLoopDestOffsetEnable == false)) { u32TmpVal = 0U; } else { u32TmpVal = (pDma->CFG[u8Channel].NBYTES.ILOFFYES & DMA_CFG_NBYTES_ILOFFYES_ILOFF_MASK) >> DMA_CFG_NBYTES_ILOFFYES_ILOFF_SHIFT; } } /* Convert sign-extended 20bit value to signed 32bit value */ if ((u32TmpVal & (1U << 19U)) != 0U) { u32TmpVal |= 0xFFF00000U; } return (int32_t)u32TmpVal; } /** * @brief Get the transfer data size of the inner loop * @note if inner loop mapping is disabled, the range is 0~2^31-1 * if inner loop mapping is enabled and inner loop offset is disabled, the range is 0~2^30-1 * if inner loop mapping is enabled and inner loop offset is enabled, the range is 0~2^10-1 * 0 means 2^32 * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return uint32_t the transfer data size of the inner loop */ LOCAL_INLINE uint32_t DMA_HWA_GetInnerLoopSize(const DMA_Type *const pDma, uint8_t u8Channel) { uint32_t u32TmpVal; if (DMA_HWA_GetInnerLoopMappingEnableFlag(pDma) == false) { u32TmpVal = pDma->CFG[u8Channel].NBYTES.ILNO; } else { bool bDmaInnerLoopSrcOffsetEnable = DMA_HWA_GetInnerLoopSrcOffsetEnableFlag(pDma, u8Channel); bool bDmaInnerLoopDestOffsetEnable = DMA_HWA_GetInnerLoopDestOffsetEnableFlag(pDma, u8Channel); if ((bDmaInnerLoopSrcOffsetEnable == false) && (bDmaInnerLoopDestOffsetEnable == false)) { u32TmpVal = (pDma->CFG[u8Channel].NBYTES.ILOFFNO & DMA_CFG_NBYTES_ILOFFNO_NBYTES_MASK) >> DMA_CFG_NBYTES_ILOFFNO_NBYTES_SHIFT; } else { u32TmpVal = (pDma->CFG[u8Channel].NBYTES.ILOFFYES & DMA_CFG_NBYTES_ILOFFYES_NBYTES_MASK) >> DMA_CFG_NBYTES_ILOFFYES_NBYTES_SHIFT; } } return u32TmpVal; } /** * @brief Set the inner loop offset of the DMA channel * * @note the inner loop offset can only be enabled when inner loop mapping is enabled * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param bEnableSrcOffset whether to enable source address inner loop offset * @param bEnableDestOffset whether to enable destination address inner loop offset * @param s32Offset the inner loop offset */ LOCAL_INLINE void DMA_HWA_SetInnerLoopOffset(DMA_Type *const pDma, uint8_t u8Channel, bool bEnableSrcOffset, bool bEnableDestOffset, int32_t s32Offset) { if (DMA_HWA_GetInnerLoopMappingEnableFlag(pDma) == false) { //ignore the action } else { if ((bEnableSrcOffset == false) && (bEnableDestOffset == false)) { bool bDmaInnerLoopSrcOffsetEnable = DMA_HWA_GetInnerLoopSrcOffsetEnableFlag(pDma, u8Channel); bool bDmaInnerLoopDestOffsetEnable = DMA_HWA_GetInnerLoopDestOffsetEnableFlag(pDma, u8Channel); /* If inner loop offset is enabled, to disable inner loop offset, we should clear the inner loop offset enable bit and meanwhile the inner loop offset bits */ if ((bDmaInnerLoopSrcOffsetEnable == true) || (bDmaInnerLoopDestOffsetEnable == true)) { pDma->CFG[u8Channel].NBYTES.ILOFFNO &= ~(DMA_CFG_NBYTES_ILOFFNO_SILOE_MASK | DMA_CFG_NBYTES_ILOFFNO_DILOE_MASK | DMA_CFG_NBYTES_ILOFFYES_ILOFF_MASK); } } else { pDma->CFG[u8Channel].NBYTES.ILOFFYES = (pDma->CFG[u8Channel].NBYTES.ILOFFYES & ~(DMA_CFG_NBYTES_ILOFFYES_SILOE_MASK | DMA_CFG_NBYTES_ILOFFYES_DILOE_MASK | DMA_CFG_NBYTES_ILOFFYES_ILOFF_MASK)) | DMA_CFG_NBYTES_ILOFFYES_SILOE(bEnableSrcOffset) | DMA_CFG_NBYTES_ILOFFYES_DILOE(bEnableDestOffset) | DMA_CFG_NBYTES_ILOFFYES_ILOFF(s32Offset); } } } /** * @brief Set the transfer data size of the inner loop * @note if inner loop mapping is disabled, the range is 0~2^31-1 * if inner loop mapping is enabled and inner loop offset is disabled, the range is 0~2^30-1 * if inner loop mapping is enabled and inner loop offset is enabled, the range is 0~2^10-1 * 0 means 2^32 * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param u32Size the transfer data size of the inner loop */ LOCAL_INLINE void DMA_HWA_SetInnerLoopSize(DMA_Type *const pDma, uint8_t u8Channel, uint32_t u32Size) { if (DMA_HWA_GetInnerLoopMappingEnableFlag(pDma) == false) { pDma->CFG[u8Channel].NBYTES.ILNO = DMA_CFG_NBYTES_ILNO_NBYTES(u32Size); } else { bool bDmaInnerLoopSrcOffsetEnable = DMA_HWA_GetInnerLoopSrcOffsetEnableFlag(pDma, u8Channel); bool bDmaInnerLoopDestOffsetEnable = DMA_HWA_GetInnerLoopDestOffsetEnableFlag(pDma, u8Channel); if ((bDmaInnerLoopSrcOffsetEnable == false) && (bDmaInnerLoopDestOffsetEnable == false)) { pDma->CFG[u8Channel].NBYTES.ILOFFNO = (pDma->CFG[u8Channel].NBYTES.ILOFFNO & ~DMA_CFG_NBYTES_ILOFFNO_NBYTES_MASK) | DMA_CFG_NBYTES_ILOFFNO_NBYTES(u32Size); } else { pDma->CFG[u8Channel].NBYTES.ILOFFYES = (pDma->CFG[u8Channel].NBYTES.ILOFFYES & ~DMA_CFG_NBYTES_ILOFFYES_NBYTES_MASK) | DMA_CFG_NBYTES_ILOFFYES_NBYTES(u32Size); } } } /** * @brief Get whether current channel to channel trig is enabled when inner loop complete * @note this field shall always be same with the beginning channel to channel trig enable flag * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return true channel to channel trig is enabled when inner loop complete * @return false channel to channel trig is disabled when inner loop complete */ LOCAL_INLINE bool DMA_HWA_GetCurrentChannelToChannelTrigEnableFlag(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].CLC.CHTRGENNO & DMA_CFG_CLC_CHTRGENNO_CHTRGEN_MASK) >> DMA_CFG_CLC_CHTRGENNO_CHTRGEN_SHIFT; return (bool)((u16TmpVal != 0U) ? true : false); } /** * @brief Get the target channel when current channel to channel trig is enabled * @note this field shall always be same with the beginning traget channel trig field * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return uint8_t the target channel */ LOCAL_INLINE uint8_t DMA_HWA_GetCurrentChannelToChannelTrigChannel(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal; if (DMA_HWA_GetCurrentChannelToChannelTrigEnableFlag(pDma, u8Channel) == true) { u16TmpVal = (pDma->CFG[u8Channel].CLC.CHTRGENYES & DMA_CFG_CLC_CHTRGENYES_TRGCH_MASK) >> DMA_CFG_CLC_CHTRGENYES_TRGCH_SHIFT; } else { u16TmpVal = 0U; } return (uint8_t)u16TmpVal; } /** * @brief Get the current loop count * The current loop count is the same as the beginning loop count initially, and it will decrement * each time a inner loop finishes * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return uint16_t the current loop count */ LOCAL_INLINE uint16_t DMA_HWA_GetCurrentLoopCount(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal; if (DMA_HWA_GetCurrentChannelToChannelTrigEnableFlag(pDma, u8Channel) == false) { u16TmpVal = (pDma->CFG[u8Channel].CLC.CHTRGENNO & DMA_CFG_CLC_CHTRGENNO_CLC_MASK) >> DMA_CFG_CLC_CHTRGENNO_CLC_SHIFT; } else { u16TmpVal = (pDma->CFG[u8Channel].CLC.CHTRGENYES & DMA_CFG_CLC_CHTRGENYES_CLC_MASK) >> DMA_CFG_CLC_CHTRGENYES_CLC_SHIFT; } return u16TmpVal; } /** * @brief Get whether beginning channel to channel trig is enabled when inner loop complete * @note this field shall always be same with the current channel to channel trig enable flag * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return true channel to channel trig is enabled when inner loop complete * @return false channel to channel trig is disabled when inner loop complete */ LOCAL_INLINE bool DMA_HWA_GetBeginningChannelToChannelTrigEnableFlag(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].BLC.CHTRGENNO & DMA_CFG_BLC_CHTRGENNO_CHTRGEN_MASK) >> DMA_CFG_BLC_CHTRGENNO_CHTRGEN_SHIFT; return (bool)((u16TmpVal != 0U) ? true : false); } /** * @brief Get the target channel when beginning channel to channel trig is enabled * @note this field shall always be same with the current traget channel trig field * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return uint8_t the target channel */ LOCAL_INLINE uint8_t DMA_HWA_GetBeginningChannelToChannelTrigChannel(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal; if (DMA_HWA_GetBeginningChannelToChannelTrigEnableFlag(pDma, u8Channel) == true) { u16TmpVal = (pDma->CFG[u8Channel].BLC.CHTRGENYES & DMA_CFG_BLC_CHTRGENYES_TRGCH_MASK) >> DMA_CFG_BLC_CHTRGENYES_TRGCH_SHIFT; } else { u16TmpVal = 0U; } return (uint8_t)u16TmpVal; } /** * @brief Get the beginning loop count * This field specifies how many inner loops will be executed in a DMA transfer * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return uint16_t the beginning loop count */ LOCAL_INLINE uint16_t DMA_HWA_GetBeginningLoopCount(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal; if (DMA_HWA_GetBeginningChannelToChannelTrigEnableFlag(pDma, u8Channel) == false) { u16TmpVal = (pDma->CFG[u8Channel].BLC.CHTRGENNO & DMA_CFG_BLC_CHTRGENNO_BLC_MASK) >> DMA_CFG_BLC_CHTRGENNO_BLC_SHIFT; } else { u16TmpVal = (pDma->CFG[u8Channel].BLC.CHTRGENYES & DMA_CFG_BLC_CHTRGENYES_BLC_MASK) >> DMA_CFG_BLC_CHTRGENYES_BLC_SHIFT; } return u16TmpVal; } /** * @brief Set channel to channel trig when inner loop complete * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param bEnable whether to enbable channel to channel trig when inner loop complete * @param u8TrigChannel the target channel */ LOCAL_INLINE void DMA_HWA_SetChannelToChannelTrig(DMA_Type *const pDma, uint8_t u8Channel, bool bEnable, uint8_t u8TrigChannel) { if (bEnable == false) { if (DMA_HWA_GetBeginningChannelToChannelTrigEnableFlag(pDma, u8Channel) == true) { pDma->CFG[u8Channel].BLC.CHTRGENNO &= ~(DMA_CFG_BLC_CHTRGENNO_CHTRGEN_MASK); pDma->CFG[u8Channel].CLC.CHTRGENNO &= ~(DMA_CFG_CLC_CHTRGENNO_CHTRGEN_MASK); } } else { pDma->CFG[u8Channel].BLC.CHTRGENYES = (pDma->CFG[u8Channel].BLC.CHTRGENYES & ~(DMA_CFG_BLC_CHTRGENYES_CHTRGEN_MASK | DMA_CFG_BLC_CHTRGENYES_TRGCH_MASK)) | DMA_CFG_BLC_CHTRGENYES_CHTRGEN(bEnable) | DMA_CFG_BLC_CHTRGENYES_TRGCH(u8TrigChannel); pDma->CFG[u8Channel].CLC.CHTRGENYES = (pDma->CFG[u8Channel].CLC.CHTRGENYES & ~(DMA_CFG_CLC_CHTRGENYES_CHTRGEN_MASK | DMA_CFG_CLC_CHTRGENYES_TRGCH_MASK)) | DMA_CFG_CLC_CHTRGENYES_CHTRGEN(bEnable) | DMA_CFG_CLC_CHTRGENYES_TRGCH(u8TrigChannel); } } /** * @brief Set the loop count of the DMA transfer * This field specifies how many inner loops will be executed in a DMA transfer * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param u16LoopCnt the inner loop count in a DMA transfer */ LOCAL_INLINE void DMA_HWA_SetLoopCount(DMA_Type *const pDma, uint8_t u8Channel, uint16_t u16LoopCnt) { if (DMA_HWA_GetBeginningChannelToChannelTrigEnableFlag(pDma, u8Channel) == false) { pDma->CFG[u8Channel].BLC.CHTRGENNO = (pDma->CFG[u8Channel].BLC.CHTRGENNO & ~DMA_CFG_BLC_CHTRGENNO_BLC_MASK) | DMA_CFG_BLC_CHTRGENNO_BLC(u16LoopCnt); pDma->CFG[u8Channel].CLC.CHTRGENNO = (pDma->CFG[u8Channel].CLC.CHTRGENNO & ~DMA_CFG_CLC_CHTRGENNO_CLC_MASK) | DMA_CFG_CLC_CHTRGENNO_CLC(u16LoopCnt); } else { pDma->CFG[u8Channel].BLC.CHTRGENYES = (pDma->CFG[u8Channel].BLC.CHTRGENYES & ~DMA_CFG_BLC_CHTRGENYES_BLC_MASK) | DMA_CFG_BLC_CHTRGENYES_BLC(u16LoopCnt); pDma->CFG[u8Channel].CLC.CHTRGENYES = (pDma->CFG[u8Channel].CLC.CHTRGENYES & ~DMA_CFG_CLC_CHTRGENYES_CLC_MASK) | DMA_CFG_CLC_CHTRGENYES_CLC(u16LoopCnt); } } /** * @brief Get the unalign modulo index selection * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return uint8_t the unalign modulo index selection */ LOCAL_INLINE uint8_t DMA_HWA_GetUnalignModuloSel(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].CSR & DMA_CFG_CSR_UMS_MASK) >> DMA_CFG_CSR_UMS_SHIFT; return (uint8_t)u16TmpVal; } /** * @brief Set the unalign modulo index selection * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param u8UnalignModuloSel the unalign modulo index selection */ LOCAL_INLINE void DMA_HWA_SetUnalignModuloSel(DMA_Type *const pDma, uint8_t u8Channel, uint8_t u8UnalignModuloSel) { pDma->CFG[u8Channel].CSR = (pDma->CFG[u8Channel].CSR & ~DMA_CFG_CSR_UMS_MASK) | DMA_CFG_CSR_UMS(u8UnalignModuloSel); } /** * @brief Get the target channel to trig when outer loop is completed * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return uint8_t the target channel */ LOCAL_INLINE uint8_t DMA_HWA_GetOuterLoopTrigChannel(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].CSR & DMA_CFG_CSR_OTRGCH_MASK) >> DMA_CFG_CSR_OTRGCH_SHIFT; return (uint8_t)u16TmpVal; } /** * @brief Set the target channel to trig when outer loop is completed * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param u8TrigChannel the target channel */ LOCAL_INLINE void DMA_HWA_SetOuterLoopTrigChannel(DMA_Type *const pDma, uint8_t u8Channel, uint8_t u8TrigChannel) { pDma->CFG[u8Channel].CSR = (pDma->CFG[u8Channel].CSR & ~DMA_CFG_CSR_OTRGCH_MASK) | DMA_CFG_CSR_OTRGCH(u8TrigChannel); } /** * @brief Get whether the transfer is done on the selected channel * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return true the transfer is done * @return false the transfer has not done */ LOCAL_INLINE bool DMA_HWA_GetChannelDoneStatus(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].CSR & DMA_CFG_CSR_DONE_MASK) >> DMA_CFG_CSR_DONE_SHIFT; return (bool)((u16TmpVal != 0U) ? true : false); } /** * @brief Get the active status of the DMA channel * This flag signals the channel is currently in execution. It is set when channel service begins, * and is cleared by the DMA as the inner loop completes or when any error condition is detected * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return true the channel is in execution * @return false the channel is idle */ LOCAL_INLINE DMA_RunningStatusType DMA_HWA_GetChannelActiveStatus(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].CSR & DMA_CFG_CSR_ACTIVE_MASK) >> DMA_CFG_CSR_ACTIVE_SHIFT; return (DMA_RunningStatusType)u16TmpVal; } /** * @brief Get channel to channel trig is enabled when outer loop is completed * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return true the target channel will be trigged when outer loop is completed * @return false the channel to channel trig when outer loop is completed is disabled */ LOCAL_INLINE bool DMA_HWA_GetOuterLoopTrigEnableFlag(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].CSR & DMA_CFG_CSR_OCHTRGEN_MASK) >> DMA_CFG_CSR_OCHTRGEN_SHIFT; return (bool)((u16TmpVal != 0U) ? true : false); } /** * @brief Set whether to enable channel to channel trig when outer loop is completed * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param bEnable whether to enable channel to channel trig when outer loop is completed */ LOCAL_INLINE void DMA_HWA_SetOuterLoopTrigEnableFlag(DMA_Type *const pDma, uint8_t u8Channel, bool bEnable) { pDma->CFG[u8Channel].CSR = (pDma->CFG[u8Channel].CSR & ~DMA_CFG_CSR_OCHTRGEN_MASK) | DMA_CFG_CSR_OCHTRGEN(bEnable); } /** * @brief Get whether DMA request will be disabled automatically when outer loop is completed * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return true DMA request will be disabled automatically when outer loop is completed * @return false DMA request will not be cleared when outer loop is completed */ LOCAL_INLINE bool DMA_HWA_GetAutoDisableReuqestEnableFlag(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].CSR & DMA_CFG_CSR_DREQ_MASK) >> DMA_CFG_CSR_DREQ_SHIFT; return (bool)((u16TmpVal != 0U) ? true : false); } /** * @brief Set whether to disable DMA request automatically when outer loop is completed * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param bEnable whether to disable DMA request automatically when outer loop is completed */ LOCAL_INLINE void DMA_HWA_SetAutoDisableReuqestEnableFlag(DMA_Type *const pDma, uint8_t u8Channel, bool bEnable) { pDma->CFG[u8Channel].CSR = (pDma->CFG[u8Channel].CSR & ~DMA_CFG_CSR_DREQ_MASK) | DMA_CFG_CSR_DREQ(bEnable); } /** * @brief Get whether DMA interrupt wiil be generated when the outer loop is half done * @note When outer loop count is 1, do not enable half complete interrupt * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return true DMA will generate interrupt when outer loop is half done * @return true DMA will not generate interrupt when outer loop is half done */ LOCAL_INLINE bool DMA_HWA_GetHalfCompleteInterruptEnableFlag(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].CSR & DMA_CFG_CSR_INTHALF_MASK) >> DMA_CFG_CSR_INTHALF_SHIFT; return (bool)((u16TmpVal != 0U) ? true : false); } /** * @brief Set whether to enable DMA interrupt when the outer loop is half done * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param bEnable whether to enable DMA interrupt when the outer loop is half done */ LOCAL_INLINE void DMA_HWA_SetHalfCompleteInterruptEnableFlag(DMA_Type *const pDma, uint8_t u8Channel, bool bEnable) { pDma->CFG[u8Channel].CSR = (pDma->CFG[u8Channel].CSR & ~DMA_CFG_CSR_INTHALF_MASK) | DMA_CFG_CSR_INTHALF(bEnable); } /** * @brief Get whether DMA interrupt is enabled when DMA transfer is completed * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return true DMA will generate interrupt when outer loop is completed * @return false DMA will not generate interrupt when outer loop is completed */ LOCAL_INLINE bool DMA_HWA_GetTransferCompleteInterruptEnableFlag(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].CSR & DMA_CFG_CSR_INTOUTER_MASK) >> DMA_CFG_CSR_INTOUTER_SHIFT; return (bool)((u16TmpVal != 0U) ? true : false); } /** * @brief Enable DMA transfer complete interrupt * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel */ LOCAL_INLINE void DMA_HWA_EnableTransferCompleteInterrupt(DMA_Type *const pDma, uint8_t u8Channel) { pDma->CFG[u8Channel].CSR |= DMA_CFG_CSR_INTOUTER_MASK; } /** * @brief Disable DMA transfer complete interrupt * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel */ LOCAL_INLINE void DMA_HWA_DisableTransferCompleteInterrupt(DMA_Type *const pDma, uint8_t u8Channel) { pDma->CFG[u8Channel].CSR &= ~DMA_CFG_CSR_INTOUTER_MASK; } /** * @brief Get whether the DMA start is requested but has not been executed * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return true the DMA start is requested but has not been executed * @return false the DMA start is not requested or it has started execution */ LOCAL_INLINE bool DMA_HWA_GetWaitStartFlag(const DMA_Type *const pDma, uint8_t u8Channel) { uint16_t u16TmpVal = (pDma->CFG[u8Channel].CSR & DMA_CFG_CSR_START_MASK) >> DMA_CFG_CSR_START_SHIFT; return (bool)((u16TmpVal != 0U) ? true : false); } /** * @brief Get DMA channel control and status * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @return uint16_t control and status of the selected channel */ LOCAL_INLINE uint16_t DMA_HWA_GetChannelControlStatus(const DMA_Type *const pDma, uint8_t u8Channel) { return pDma->CFG[u8Channel].CSR; } /** * @brief Set DMA channel control and status * * @param pDma the base address of the DMA instance * @param u8Channel the selected channel * @param u16Setting control settings of the selected channel */ LOCAL_INLINE void DMA_HWA_SetChannelControlStatus(DMA_Type *const pDma, uint8_t u8Channel, uint16_t u16Setting) { pDma->CFG[u8Channel].CSR = u16Setting; } /** @}*/ #endif /* _HWA_DMA_H_ */