The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.
Dependents: hello SerialTestv11 SerialTestv12 Sierpinski ... more
mbed 2
This is the mbed 2 library. If you'd like to learn about Mbed OS please see the mbed-os docs.
Diff: TARGET_EFM32HG_STK3400/TOOLCHAIN_GCC_ARM/em_dma.h
- Revision:
- 171:3a7713b1edbc
- Parent:
- 160:5571c4ff569f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TARGET_EFM32HG_STK3400/TOOLCHAIN_GCC_ARM/em_dma.h Thu Nov 08 11:45:42 2018 +0000 @@ -0,0 +1,532 @@ +/***************************************************************************//** + * @file em_dma.h + * @brief Direct memory access (DMA) API + * @version 5.3.3 + ******************************************************************************* + * # License + * <b>Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com</b> + ******************************************************************************* + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no + * obligation to support this Software. Silicon Labs is providing the + * Software "AS IS", with no express or implied warranties of any kind, + * including, but not limited to, any implied warranties of merchantability + * or fitness for any particular purpose or warranties against infringement + * of any proprietary rights of a third party. + * + * Silicon Labs will not be liable for any consequential, incidental, or + * special damages, or any other relief, or for any claim by any third party, + * arising from your use of this Software. + * + ******************************************************************************/ + +#ifndef EM_DMA_H +#define EM_DMA_H + +#include "em_device.h" +#if defined(DMA_PRESENT) + +#include <stdio.h> +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************//** + * @addtogroup emlib + * @{ + ******************************************************************************/ + +/***************************************************************************//** + * @addtogroup DMA + * @{ + ******************************************************************************/ + +/******************************************************************************* + ******************************** ENUMS ************************************ + ******************************************************************************/ + +/** + * Amount source/destination address should be incremented for each data + * transfer. + */ +typedef enum { + dmaDataInc1 = _DMA_CTRL_SRC_INC_BYTE, /**< Increment address 1 byte. */ + dmaDataInc2 = _DMA_CTRL_SRC_INC_HALFWORD, /**< Increment address 2 bytes. */ + dmaDataInc4 = _DMA_CTRL_SRC_INC_WORD, /**< Increment address 4 bytes. */ + dmaDataIncNone = _DMA_CTRL_SRC_INC_NONE /**< Do not increment address. */ +} DMA_DataInc_TypeDef; + +/** Data sizes (in number of bytes) to be read/written by DMA transfer. */ +typedef enum { + dmaDataSize1 = _DMA_CTRL_SRC_SIZE_BYTE, /**< 1 byte DMA transfer size. */ + dmaDataSize2 = _DMA_CTRL_SRC_SIZE_HALFWORD, /**< 2 byte DMA transfer size. */ + dmaDataSize4 = _DMA_CTRL_SRC_SIZE_WORD /**< 4 byte DMA transfer size. */ +} DMA_DataSize_TypeDef; + +/** Type of DMA transfer. */ +typedef enum { + /** Basic DMA cycle. */ + dmaCycleCtrlBasic = _DMA_CTRL_CYCLE_CTRL_BASIC, + /** Auto-request DMA cycle. */ + dmaCycleCtrlAuto = _DMA_CTRL_CYCLE_CTRL_AUTO, + /** Ping-pong DMA cycle. */ + dmaCycleCtrlPingPong = _DMA_CTRL_CYCLE_CTRL_PINGPONG, + /** Memory scatter-gather DMA cycle. */ + dmaCycleCtrlMemScatterGather = _DMA_CTRL_CYCLE_CTRL_MEM_SCATTER_GATHER, + /** Peripheral scatter-gather DMA cycle. */ + dmaCycleCtrlPerScatterGather = _DMA_CTRL_CYCLE_CTRL_PER_SCATTER_GATHER +} DMA_CycleCtrl_TypeDef; + +/** Number of transfers before controller does new arbitration. */ +typedef enum { + dmaArbitrate1 = _DMA_CTRL_R_POWER_1, /**< Arbitrate after 1 DMA transfer. */ + dmaArbitrate2 = _DMA_CTRL_R_POWER_2, /**< Arbitrate after 2 DMA transfers. */ + dmaArbitrate4 = _DMA_CTRL_R_POWER_4, /**< Arbitrate after 4 DMA transfers. */ + dmaArbitrate8 = _DMA_CTRL_R_POWER_8, /**< Arbitrate after 8 DMA transfers. */ + dmaArbitrate16 = _DMA_CTRL_R_POWER_16, /**< Arbitrate after 16 DMA transfers. */ + dmaArbitrate32 = _DMA_CTRL_R_POWER_32, /**< Arbitrate after 32 DMA transfers. */ + dmaArbitrate64 = _DMA_CTRL_R_POWER_64, /**< Arbitrate after 64 DMA transfers. */ + dmaArbitrate128 = _DMA_CTRL_R_POWER_128, /**< Arbitrate after 128 DMA transfers. */ + dmaArbitrate256 = _DMA_CTRL_R_POWER_256, /**< Arbitrate after 256 DMA transfers. */ + dmaArbitrate512 = _DMA_CTRL_R_POWER_512, /**< Arbitrate after 512 DMA transfers. */ + dmaArbitrate1024 = _DMA_CTRL_R_POWER_1024 /**< Arbitrate after 1024 DMA transfers. */ +} DMA_ArbiterConfig_TypeDef; + +/******************************************************************************* + ******************************* STRUCTS *********************************** + ******************************************************************************/ + +/** + * @brief + * DMA interrupt callback function pointer. + * @details + * Parameters: + * @li channel - The DMA channel the callback function is invoked for. + * @li primary - Indicates if callback is invoked for completion of primary + * (true) or alternate (false) descriptor. This is mainly useful for + * ping-pong DMA cycles, in order to know which descriptor to refresh. + * @li user - User definable reference that may be used to pass information + * to be used by the callback handler. If used, the referenced data must be + * valid at the point when the interrupt handler invokes the callback. + * If callback changes any data in the provided user structure, remember + * that those changes are done in interrupt context, and proper protection + * of data may be required. + */ +typedef void (*DMA_FuncPtr_TypeDef)(unsigned int channel, bool primary, void *user); + +/** + * @brief + * Callback structure that can be used to define DMA complete actions. + * @details + * A reference to this structure is only stored in the primary descriptor + * for a channel (if callback feature is used). If callback is required + * for both primary and alternate descriptor completion, this must be + * handled by one common callback, using the provided 'primary' parameter + * with the callback function. + */ +typedef struct { + /** + * Pointer to callback function to invoke when DMA transfer cycle done. + * Notice that this function is invoked in interrupt context, and therefore + * should be short and non-blocking. + */ + DMA_FuncPtr_TypeDef cbFunc; + + /** User defined pointer to provide with callback function. */ + void *userPtr; + + /** + * For internal use only: Indicates if next callback applies to primary + * or alternate descriptor completion. Mainly useful for ping-pong DMA + * cycles. Set this value to 0 prior to configuring callback handling. + */ + uint8_t primary; +} DMA_CB_TypeDef; + +/** Configuration structure for a channel. */ +typedef struct { + /** + * Select if channel priority is in the high or default priority group + * with respect to arbitration. Within a priority group, lower numbered + * channels have higher priority than higher numbered channels. + */ + bool highPri; + + /** + * Select if interrupt shall be enabled for channel (triggering interrupt + * handler when dma_done signal is asserted). It should normally be + * enabled if using the callback feature for a channel, and disabled if + * not using the callback feature. + */ + bool enableInt; + + /** + * Channel control specifying the source of DMA signals. If accessing + * peripherals, use one of the DMAREQ_nnn defines available for the + * peripheral. Set it to 0 for memory-to-memory DMA cycles. + */ + uint32_t select; + + /** + * @brief + * User definable callback handling configuration. + * @details + * Please refer to structure definition for details. The callback + * is invoked when the specified DMA cycle is complete (when dma_done + * signal asserted). The callback is invoked in interrupt context, + * and should be efficient and non-blocking. Set to NULL to not + * use the callback feature. + * @note + * The referenced structure is used by the interrupt handler, and must + * be available until no longer used. Thus, in most cases it should + * not be located on the stack. + */ + DMA_CB_TypeDef *cb; +} DMA_CfgChannel_TypeDef; + +/** + * Configuration structure for primary or alternate descriptor + * (not used for scatter-gather DMA cycles). + */ +typedef struct { + /** Destination increment size for each DMA transfer */ + DMA_DataInc_TypeDef dstInc; + + /** Source increment size for each DMA transfer */ + DMA_DataInc_TypeDef srcInc; + + /** DMA transfer unit size. */ + DMA_DataSize_TypeDef size; + + /** + * Arbitration rate, ie number of DMA transfers done before rearbitration + * takes place. + */ + DMA_ArbiterConfig_TypeDef arbRate; + + /** + * HPROT signal state, please refer to reference manual, DMA chapter for + * further details. Normally set to 0 if protection is not an issue. + * The following bits are available: + * @li bit 0 - HPROT[1] control for source read accesses, + * privileged/non-privileged access + * @li bit 3 - HPROT[1] control for destination write accesses, + * privileged/non-privileged access + */ + uint8_t hprot; +} DMA_CfgDescr_TypeDef; + +#if defined(_DMA_LOOP0_MASK) && defined(_DMA_LOOP1_MASK) +/** + * Configuration structure for loop mode + */ +typedef struct { + /** Enable repeated loop */ + bool enable; + /** Width of transfer, reload value for nMinus1 */ + uint16_t nMinus1; +} DMA_CfgLoop_TypeDef; +#endif + +#if defined(_DMA_RECT0_MASK) +/** + * Configuration structure for rectangular copy + */ +typedef struct { + /** DMA channel destination stride (width of destination image, distance between lines) */ + uint16_t dstStride; + /** DMA channel source stride (width of source image, distance between lines) */ + uint16_t srcStride; + /** 2D copy height */ + uint16_t height; +} DMA_CfgRect_TypeDef; +#endif + +/** Configuration structure for alternate scatter-gather descriptor. */ +typedef struct { + /** Pointer to location to transfer data from. */ + void *src; + + /** Pointer to location to transfer data to. */ + void *dst; + + /** Destination increment size for each DMA transfer */ + DMA_DataInc_TypeDef dstInc; + + /** Source increment size for each DMA transfer */ + DMA_DataInc_TypeDef srcInc; + + /** DMA transfer unit size. */ + DMA_DataSize_TypeDef size; + + /** + * Arbitration rate, ie number of DMA transfers done before rearbitration + * takes place. + */ + DMA_ArbiterConfig_TypeDef arbRate; + + /** Number of DMA transfers minus 1 to do. Must be <= 1023. */ + uint16_t nMinus1; + + /** + * HPROT signal state, please refer to reference manual, DMA chapter for + * further details. Normally set to 0 if protection is not an issue. + * The following bits are available: + * @li bit 0 - HPROT[1] control for source read accesses, + * privileged/non-privileged access + * @li bit 3 - HPROT[1] control for destination write accesses, + * privileged/non-privileged access + */ + uint8_t hprot; + + /** Specify if a memory or peripheral scatter-gather DMA cycle. Notice + * that this parameter should be the same for all alternate + * descriptors. + * @li true - this is a peripheral scatter-gather cycle + * @li false - this is a memory scatter-gather cycle + */ + bool peripheral; +} DMA_CfgDescrSGAlt_TypeDef; + +/** DMA init structure */ +typedef struct { + /** + * HPROT signal state when accessing the primary/alternate + * descriptors. Normally set to 0 if protection is not an issue. + * The following bits are available: + * @li bit 0 - HPROT[1] control for descriptor accesses (ie when + * the DMA controller accesses the channel control block itself), + * privileged/non-privileged access + */ + uint8_t hprot; + + /** + * Pointer to the controlblock in memory holding descriptors (channel + * control data structures). This memory must be properly aligned + * at a 256 bytes. I.e. the 8 least significant bits must be zero. + * + * Please refer to the reference manual, DMA chapter for more details. + * + * It is possible to provide a smaller memory block, only covering + * those channels actually used, if not all available channels are used. + * Ie, if only using 4 channels (0-3), both primary and alternate + * structures, then only 16*2*4 = 128 bytes must be provided. This + * implementation has however no check if later exceeding such a limit + * by configuring for instance channel 4, in which case memory overwrite + * of some other data will occur. + */ + DMA_DESCRIPTOR_TypeDef *controlBlock; +} DMA_Init_TypeDef; + +/******************************************************************************* + ***************************** PROTOTYPES ********************************** + ******************************************************************************/ + +void DMA_ActivateAuto(unsigned int channel, + bool primary, + void *dst, + const void *src, + unsigned int nMinus1); +void DMA_ActivateBasic(unsigned int channel, + bool primary, + bool useBurst, + void *dst, + const void *src, + unsigned int nMinus1); +void DMA_ActivatePingPong(unsigned int channel, + bool useBurst, + void *primDst, + const void *primSrc, + unsigned int primNMinus1, + void *altDst, + const void *altSrc, + unsigned int altNMinus1); +void DMA_ActivateScatterGather(unsigned int channel, + bool useBurst, + DMA_DESCRIPTOR_TypeDef *altDescr, + unsigned int count); +void DMA_CfgChannel(unsigned int channel, DMA_CfgChannel_TypeDef *cfg); +void DMA_CfgDescr(unsigned int channel, + bool primary, + DMA_CfgDescr_TypeDef *cfg); +#if defined(_DMA_LOOP0_MASK) && defined(_DMA_LOOP1_MASK) +void DMA_CfgLoop(unsigned int channel, DMA_CfgLoop_TypeDef *cfg); +#endif + +#if defined(_DMA_RECT0_MASK) +void DMA_CfgRect(unsigned int channel, DMA_CfgRect_TypeDef *cfg); +#endif + +#if defined(_DMA_LOOP0_MASK) && defined(_DMA_LOOP1_MASK) +/***************************************************************************//** + * @brief + * Clear Loop configuration for channel + * + * @param[in] channel + * Channel to reset loop configuration for + ******************************************************************************/ +__STATIC_INLINE void DMA_ResetLoop(unsigned int channel) +{ + /* Clean loop copy operation */ + switch (channel) { + case 0: + DMA->LOOP0 = _DMA_LOOP0_RESETVALUE; + break; + case 1: + DMA->LOOP1 = _DMA_LOOP1_RESETVALUE; + break; + default: + break; + } +} +#endif + +#if defined(_DMA_RECT0_MASK) +/***************************************************************************//** + * @brief + * Clear Rect/2D DMA configuration for channel + * + * @param[in] channel + * Channel to reset loop configuration for + ******************************************************************************/ +__STATIC_INLINE void DMA_ResetRect(unsigned int channel) +{ + (void) channel; + + /* Clear rect copy operation */ + DMA->RECT0 = _DMA_RECT0_RESETVALUE; +} +#endif +void DMA_CfgDescrScatterGather(DMA_DESCRIPTOR_TypeDef *descr, + unsigned int indx, + DMA_CfgDescrSGAlt_TypeDef *cfg); +void DMA_ChannelEnable(unsigned int channel, bool enable); +bool DMA_ChannelEnabled(unsigned int channel); +void DMA_ChannelRequestEnable(unsigned int channel, bool enable); +void DMA_Init(DMA_Init_TypeDef *init); +void DMA_IRQHandler(void); +void DMA_RefreshPingPong(unsigned int channel, + bool primary, + bool useBurst, + void *dst, + const void *src, + unsigned int nMinus1, + bool last); +void DMA_Reset(void); + +/***************************************************************************//** + * @brief + * Clear one or more pending DMA interrupts. + * + * @param[in] flags + * Pending DMA interrupt sources to clear. Use one or more valid + * interrupt flags for the DMA module (DMA_IFC_nnn). + ******************************************************************************/ +__STATIC_INLINE void DMA_IntClear(uint32_t flags) +{ + DMA->IFC = flags; +} + +/***************************************************************************//** + * @brief + * Disable one or more DMA interrupts. + * + * @param[in] flags + * DMA interrupt sources to disable. Use one or more valid + * interrupt flags for the DMA module (DMA_IEN_nnn). + ******************************************************************************/ +__STATIC_INLINE void DMA_IntDisable(uint32_t flags) +{ + DMA->IEN &= ~flags; +} + +/***************************************************************************//** + * @brief + * Enable one or more DMA interrupts. + * + * @note + * Depending on the use, a pending interrupt may already be set prior to + * enabling the interrupt. Consider using DMA_IntClear() prior to enabling + * if such a pending interrupt should be ignored. + * + * @param[in] flags + * DMA interrupt sources to enable. Use one or more valid + * interrupt flags for the DMA module (DMA_IEN_nnn). + ******************************************************************************/ +__STATIC_INLINE void DMA_IntEnable(uint32_t flags) +{ + DMA->IEN |= flags; +} + +/***************************************************************************//** + * @brief + * Get pending DMA interrupt flags. + * + * @note + * The event bits are not cleared by the use of this function. + * + * @return + * DMA interrupt sources pending. Returns one or more valid + * interrupt flags for the DMA module (DMA_IF_nnn). + ******************************************************************************/ +__STATIC_INLINE uint32_t DMA_IntGet(void) +{ + return DMA->IF; +} + +/***************************************************************************//** + * @brief + * Get enabled and pending DMA interrupt flags. + * Useful for handling more interrupt sources in the same interrupt handler. + * + * @note + * Interrupt flags are not cleared by the use of this function. + * + * @return + * Pending and enabled DMA interrupt sources + * The return value is the bitwise AND of + * - the enabled interrupt sources in DMA_IEN and + * - the pending interrupt flags DMA_IF + ******************************************************************************/ +__STATIC_INLINE uint32_t DMA_IntGetEnabled(void) +{ + uint32_t ien; + + ien = DMA->IEN; + return DMA->IF & ien; +} + +/***************************************************************************//** + * @brief + * Set one or more pending DMA interrupts + * + * @param[in] flags + * DMA interrupt sources to set to pending. Use one or more valid + * interrupt flags for the DMA module (DMA_IFS_nnn). + ******************************************************************************/ +__STATIC_INLINE void DMA_IntSet(uint32_t flags) +{ + DMA->IFS = flags; +} + +/** @} (end addtogroup DMA) */ +/** @} (end addtogroup emlib) */ + +#ifdef __cplusplus +} +#endif + +#endif /* defined( DMA_PRESENT ) */ +#endif /* EM_DMA_H */