added prescaler for 16 bit pwm in LPC1347 target
Fork of mbed-dev by
targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_dma.c@147:ba84b7dc41a7, 2016-09-10 (annotated)
- Committer:
- JojoS
- Date:
- Sat Sep 10 15:32:04 2016 +0000
- Revision:
- 147:ba84b7dc41a7
- Parent:
- 144:ef7eb2e8f9f7
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
<> | 144:ef7eb2e8f9f7 | 1 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 2 | * @file em_dma.c |
<> | 144:ef7eb2e8f9f7 | 3 | * @brief Direct memory access (DMA) module peripheral API |
<> | 144:ef7eb2e8f9f7 | 4 | * @version 4.2.1 |
<> | 144:ef7eb2e8f9f7 | 5 | ******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 6 | * @section License |
<> | 144:ef7eb2e8f9f7 | 7 | * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b> |
<> | 144:ef7eb2e8f9f7 | 8 | ******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 9 | * |
<> | 144:ef7eb2e8f9f7 | 10 | * Permission is granted to anyone to use this software for any purpose, |
<> | 144:ef7eb2e8f9f7 | 11 | * including commercial applications, and to alter it and redistribute it |
<> | 144:ef7eb2e8f9f7 | 12 | * freely, subject to the following restrictions: |
<> | 144:ef7eb2e8f9f7 | 13 | * |
<> | 144:ef7eb2e8f9f7 | 14 | * 1. The origin of this software must not be misrepresented; you must not |
<> | 144:ef7eb2e8f9f7 | 15 | * claim that you wrote the original software. |
<> | 144:ef7eb2e8f9f7 | 16 | * 2. Altered source versions must be plainly marked as such, and must not be |
<> | 144:ef7eb2e8f9f7 | 17 | * misrepresented as being the original software. |
<> | 144:ef7eb2e8f9f7 | 18 | * 3. This notice may not be removed or altered from any source distribution. |
<> | 144:ef7eb2e8f9f7 | 19 | * |
<> | 144:ef7eb2e8f9f7 | 20 | * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no |
<> | 144:ef7eb2e8f9f7 | 21 | * obligation to support this Software. Silicon Labs is providing the |
<> | 144:ef7eb2e8f9f7 | 22 | * Software "AS IS", with no express or implied warranties of any kind, |
<> | 144:ef7eb2e8f9f7 | 23 | * including, but not limited to, any implied warranties of merchantability |
<> | 144:ef7eb2e8f9f7 | 24 | * or fitness for any particular purpose or warranties against infringement |
<> | 144:ef7eb2e8f9f7 | 25 | * of any proprietary rights of a third party. |
<> | 144:ef7eb2e8f9f7 | 26 | * |
<> | 144:ef7eb2e8f9f7 | 27 | * Silicon Labs will not be liable for any consequential, incidental, or |
<> | 144:ef7eb2e8f9f7 | 28 | * special damages, or any other relief, or for any claim by any third party, |
<> | 144:ef7eb2e8f9f7 | 29 | * arising from your use of this Software. |
<> | 144:ef7eb2e8f9f7 | 30 | * |
<> | 144:ef7eb2e8f9f7 | 31 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 32 | |
<> | 144:ef7eb2e8f9f7 | 33 | #include "em_dma.h" |
<> | 144:ef7eb2e8f9f7 | 34 | #if defined( DMA_PRESENT ) |
<> | 144:ef7eb2e8f9f7 | 35 | |
<> | 144:ef7eb2e8f9f7 | 36 | #include "em_cmu.h" |
<> | 144:ef7eb2e8f9f7 | 37 | #include "em_assert.h" |
<> | 144:ef7eb2e8f9f7 | 38 | #include "em_bus.h" |
<> | 144:ef7eb2e8f9f7 | 39 | |
<> | 144:ef7eb2e8f9f7 | 40 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 41 | * @addtogroup EM_Library |
<> | 144:ef7eb2e8f9f7 | 42 | * @{ |
<> | 144:ef7eb2e8f9f7 | 43 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 44 | |
<> | 144:ef7eb2e8f9f7 | 45 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 46 | * @addtogroup DMA |
<> | 144:ef7eb2e8f9f7 | 47 | * @brief Direct Memory Access (DMA) Peripheral API |
<> | 144:ef7eb2e8f9f7 | 48 | * @details |
<> | 144:ef7eb2e8f9f7 | 49 | * These DMA access functions provide basic support for the following |
<> | 144:ef7eb2e8f9f7 | 50 | * types of DMA cycles: |
<> | 144:ef7eb2e8f9f7 | 51 | * |
<> | 144:ef7eb2e8f9f7 | 52 | * @li @b Basic, used for transferring data between memory and peripherals. |
<> | 144:ef7eb2e8f9f7 | 53 | * @li @b Auto-request, used for transferring data between memory locations. |
<> | 144:ef7eb2e8f9f7 | 54 | * @li @b Ping-pong, used for for continuous transfer of data between memory |
<> | 144:ef7eb2e8f9f7 | 55 | * and peripherals, automatically toggling between primary and alternate |
<> | 144:ef7eb2e8f9f7 | 56 | * descriptors. |
<> | 144:ef7eb2e8f9f7 | 57 | * @li @b Memory @b scatter-gather, used for transferring a number of buffers |
<> | 144:ef7eb2e8f9f7 | 58 | * between memory locations. |
<> | 144:ef7eb2e8f9f7 | 59 | * @li @b Peripheral @b scatter-gather, used for transferring a number of |
<> | 144:ef7eb2e8f9f7 | 60 | * buffers between memory and peripherals. |
<> | 144:ef7eb2e8f9f7 | 61 | * |
<> | 144:ef7eb2e8f9f7 | 62 | * A basic understanding of the DMA controller is assumed. Please refer to |
<> | 144:ef7eb2e8f9f7 | 63 | * the reference manual for further details. |
<> | 144:ef7eb2e8f9f7 | 64 | * |
<> | 144:ef7eb2e8f9f7 | 65 | * The term 'descriptor' is used as a synonym to the 'channel control data |
<> | 144:ef7eb2e8f9f7 | 66 | * structure' term. |
<> | 144:ef7eb2e8f9f7 | 67 | * |
<> | 144:ef7eb2e8f9f7 | 68 | * In order to use the DMA controller, the initialization function must have |
<> | 144:ef7eb2e8f9f7 | 69 | * been executed once (normally during system init): |
<> | 144:ef7eb2e8f9f7 | 70 | * @verbatim |
<> | 144:ef7eb2e8f9f7 | 71 | * DMA_Init(); |
<> | 144:ef7eb2e8f9f7 | 72 | * @endverbatim |
<> | 144:ef7eb2e8f9f7 | 73 | * |
<> | 144:ef7eb2e8f9f7 | 74 | * Then, normally a user of a DMA channel configures the channel: |
<> | 144:ef7eb2e8f9f7 | 75 | * @verbatim |
<> | 144:ef7eb2e8f9f7 | 76 | * DMA_CfgChannel(); |
<> | 144:ef7eb2e8f9f7 | 77 | * @endverbatim |
<> | 144:ef7eb2e8f9f7 | 78 | * |
<> | 144:ef7eb2e8f9f7 | 79 | * The channel configuration only has to be done once, if reusing the channel |
<> | 144:ef7eb2e8f9f7 | 80 | * for the same purpose later. |
<> | 144:ef7eb2e8f9f7 | 81 | * |
<> | 144:ef7eb2e8f9f7 | 82 | * In order to set up a DMA cycle, the primary and/or alternate descriptor |
<> | 144:ef7eb2e8f9f7 | 83 | * has to be set up as indicated below. |
<> | 144:ef7eb2e8f9f7 | 84 | * |
<> | 144:ef7eb2e8f9f7 | 85 | * For basic or auto-request cycles, use once on either primary or alternate |
<> | 144:ef7eb2e8f9f7 | 86 | * descriptor: |
<> | 144:ef7eb2e8f9f7 | 87 | * @verbatim |
<> | 144:ef7eb2e8f9f7 | 88 | * DMA_CfgDescr(); |
<> | 144:ef7eb2e8f9f7 | 89 | * @endverbatim |
<> | 144:ef7eb2e8f9f7 | 90 | * |
<> | 144:ef7eb2e8f9f7 | 91 | * For ping-pong cycles, configure both primary or alternate descriptors: |
<> | 144:ef7eb2e8f9f7 | 92 | * @verbatim |
<> | 144:ef7eb2e8f9f7 | 93 | * DMA_CfgDescr(); // Primary descriptor config |
<> | 144:ef7eb2e8f9f7 | 94 | * DMA_CfgDescr(); // Alternate descriptor config |
<> | 144:ef7eb2e8f9f7 | 95 | * @endverbatim |
<> | 144:ef7eb2e8f9f7 | 96 | * |
<> | 144:ef7eb2e8f9f7 | 97 | * For scatter-gather cycles, the alternate descriptor array must be programmed: |
<> | 144:ef7eb2e8f9f7 | 98 | * @verbatim |
<> | 144:ef7eb2e8f9f7 | 99 | * // 'n' is the number of scattered buffers |
<> | 144:ef7eb2e8f9f7 | 100 | * // 'descr' points to the start of the alternate descriptor array |
<> | 144:ef7eb2e8f9f7 | 101 | * |
<> | 144:ef7eb2e8f9f7 | 102 | * // Fill in 'cfg' |
<> | 144:ef7eb2e8f9f7 | 103 | * DMA_CfgDescrScatterGather(descr, 0, cfg); |
<> | 144:ef7eb2e8f9f7 | 104 | * // Fill in 'cfg' |
<> | 144:ef7eb2e8f9f7 | 105 | * DMA_CfgDescrScatterGather(descr, 1, cfg); |
<> | 144:ef7eb2e8f9f7 | 106 | * : |
<> | 144:ef7eb2e8f9f7 | 107 | * // Fill in 'cfg' |
<> | 144:ef7eb2e8f9f7 | 108 | * DMA_CfgDescrScatterGather(descr, n - 1, cfg); |
<> | 144:ef7eb2e8f9f7 | 109 | * @endverbatim |
<> | 144:ef7eb2e8f9f7 | 110 | * |
<> | 144:ef7eb2e8f9f7 | 111 | * In many cases, the descriptor configuration only has to be done once, if |
<> | 144:ef7eb2e8f9f7 | 112 | * re-using the channel for the same type of DMA cycles later. |
<> | 144:ef7eb2e8f9f7 | 113 | * |
<> | 144:ef7eb2e8f9f7 | 114 | * In order to activate the DMA cycle, use the respective DMA_Activate...() |
<> | 144:ef7eb2e8f9f7 | 115 | * function. |
<> | 144:ef7eb2e8f9f7 | 116 | * |
<> | 144:ef7eb2e8f9f7 | 117 | * For ping-pong DMA cycles, use DMA_RefreshPingPong() from the callback to |
<> | 144:ef7eb2e8f9f7 | 118 | * prepare the completed descriptor for reuse. Notice that the refresh must |
<> | 144:ef7eb2e8f9f7 | 119 | * be done prior to the other active descriptor completes, otherwise the |
<> | 144:ef7eb2e8f9f7 | 120 | * ping-pong DMA cycle will halt. |
<> | 144:ef7eb2e8f9f7 | 121 | * @{ |
<> | 144:ef7eb2e8f9f7 | 122 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 123 | |
<> | 144:ef7eb2e8f9f7 | 124 | /******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 125 | ************************** LOCAL FUNCTIONS ******************************** |
<> | 144:ef7eb2e8f9f7 | 126 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 127 | |
<> | 144:ef7eb2e8f9f7 | 128 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ |
<> | 144:ef7eb2e8f9f7 | 129 | |
<> | 144:ef7eb2e8f9f7 | 130 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 131 | * @brief |
<> | 144:ef7eb2e8f9f7 | 132 | * Prepare descriptor for DMA cycle. |
<> | 144:ef7eb2e8f9f7 | 133 | * |
<> | 144:ef7eb2e8f9f7 | 134 | * @details |
<> | 144:ef7eb2e8f9f7 | 135 | * This function prepares the last pieces of configuration required to start a |
<> | 144:ef7eb2e8f9f7 | 136 | * DMA cycle. Since the DMA controller itself modifies some parts of the |
<> | 144:ef7eb2e8f9f7 | 137 | * descriptor during use, those parts need to be refreshed if reusing a |
<> | 144:ef7eb2e8f9f7 | 138 | * descriptor configuration. |
<> | 144:ef7eb2e8f9f7 | 139 | * |
<> | 144:ef7eb2e8f9f7 | 140 | * @note |
<> | 144:ef7eb2e8f9f7 | 141 | * If using this function on a descriptor already activated and in use by the |
<> | 144:ef7eb2e8f9f7 | 142 | * DMA controller, the behaviour is undefined. |
<> | 144:ef7eb2e8f9f7 | 143 | * |
<> | 144:ef7eb2e8f9f7 | 144 | * @param[in] channel |
<> | 144:ef7eb2e8f9f7 | 145 | * DMA channel to prepare for DMA cycle. |
<> | 144:ef7eb2e8f9f7 | 146 | * |
<> | 144:ef7eb2e8f9f7 | 147 | * @param[in] cycleCtrl |
<> | 144:ef7eb2e8f9f7 | 148 | * DMA cycle type to prepare for. |
<> | 144:ef7eb2e8f9f7 | 149 | * |
<> | 144:ef7eb2e8f9f7 | 150 | * @param[in] primary |
<> | 144:ef7eb2e8f9f7 | 151 | * @li true - prepare primary descriptor |
<> | 144:ef7eb2e8f9f7 | 152 | * @li false - prepare alternate descriptor |
<> | 144:ef7eb2e8f9f7 | 153 | * |
<> | 144:ef7eb2e8f9f7 | 154 | * @param[in] useBurst |
<> | 144:ef7eb2e8f9f7 | 155 | * The burst feature is only used on peripherals supporting DMA bursts. |
<> | 144:ef7eb2e8f9f7 | 156 | * Bursts must not be used if the total length (as given by nMinus1) is |
<> | 144:ef7eb2e8f9f7 | 157 | * less than the arbitration rate configured for the descriptor. Please |
<> | 144:ef7eb2e8f9f7 | 158 | * refer to the reference manual for further details on burst usage. |
<> | 144:ef7eb2e8f9f7 | 159 | * |
<> | 144:ef7eb2e8f9f7 | 160 | * @param[in] dst |
<> | 144:ef7eb2e8f9f7 | 161 | * Address to start location to transfer data to. If NULL, leave setting in |
<> | 144:ef7eb2e8f9f7 | 162 | * descriptor as is. |
<> | 144:ef7eb2e8f9f7 | 163 | * |
<> | 144:ef7eb2e8f9f7 | 164 | * @param[in] src |
<> | 144:ef7eb2e8f9f7 | 165 | * Address to start location to transfer data from. If NULL, leave setting in |
<> | 144:ef7eb2e8f9f7 | 166 | * descriptor as is. |
<> | 144:ef7eb2e8f9f7 | 167 | * |
<> | 144:ef7eb2e8f9f7 | 168 | * @param[in] nMinus1 |
<> | 144:ef7eb2e8f9f7 | 169 | * Number of elements (minus 1) to transfer (<= 1023). |
<> | 144:ef7eb2e8f9f7 | 170 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 171 | static void DMA_Prepare(unsigned int channel, |
<> | 144:ef7eb2e8f9f7 | 172 | DMA_CycleCtrl_TypeDef cycleCtrl, |
<> | 144:ef7eb2e8f9f7 | 173 | bool primary, |
<> | 144:ef7eb2e8f9f7 | 174 | bool useBurst, |
<> | 144:ef7eb2e8f9f7 | 175 | void *dst, |
<> | 144:ef7eb2e8f9f7 | 176 | void *src, |
<> | 144:ef7eb2e8f9f7 | 177 | unsigned int nMinus1) |
<> | 144:ef7eb2e8f9f7 | 178 | { |
<> | 144:ef7eb2e8f9f7 | 179 | DMA_DESCRIPTOR_TypeDef *descr; |
<> | 144:ef7eb2e8f9f7 | 180 | DMA_DESCRIPTOR_TypeDef *primDescr; |
<> | 144:ef7eb2e8f9f7 | 181 | DMA_CB_TypeDef *cb; |
<> | 144:ef7eb2e8f9f7 | 182 | uint32_t inc; |
<> | 144:ef7eb2e8f9f7 | 183 | uint32_t chBit; |
<> | 144:ef7eb2e8f9f7 | 184 | uint32_t tmp; |
<> | 144:ef7eb2e8f9f7 | 185 | |
<> | 144:ef7eb2e8f9f7 | 186 | primDescr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE)) + channel; |
<> | 144:ef7eb2e8f9f7 | 187 | |
<> | 144:ef7eb2e8f9f7 | 188 | /* Find descriptor to configure */ |
<> | 144:ef7eb2e8f9f7 | 189 | if (primary) |
<> | 144:ef7eb2e8f9f7 | 190 | { |
<> | 144:ef7eb2e8f9f7 | 191 | descr = primDescr; |
<> | 144:ef7eb2e8f9f7 | 192 | } |
<> | 144:ef7eb2e8f9f7 | 193 | else |
<> | 144:ef7eb2e8f9f7 | 194 | { |
<> | 144:ef7eb2e8f9f7 | 195 | descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE)) + channel; |
<> | 144:ef7eb2e8f9f7 | 196 | } |
<> | 144:ef7eb2e8f9f7 | 197 | |
<> | 144:ef7eb2e8f9f7 | 198 | /* If callback defined, update info on whether callback is issued */ |
<> | 144:ef7eb2e8f9f7 | 199 | /* for primary or alternate descriptor. Mainly needed for ping-pong */ |
<> | 144:ef7eb2e8f9f7 | 200 | /* cycles. */ |
<> | 144:ef7eb2e8f9f7 | 201 | cb = (DMA_CB_TypeDef *)(primDescr->USER); |
<> | 144:ef7eb2e8f9f7 | 202 | if (cb) |
<> | 144:ef7eb2e8f9f7 | 203 | { |
<> | 144:ef7eb2e8f9f7 | 204 | cb->primary = (uint8_t)primary; |
<> | 144:ef7eb2e8f9f7 | 205 | } |
<> | 144:ef7eb2e8f9f7 | 206 | |
<> | 144:ef7eb2e8f9f7 | 207 | if (src) |
<> | 144:ef7eb2e8f9f7 | 208 | { |
<> | 144:ef7eb2e8f9f7 | 209 | inc = (descr->CTRL & _DMA_CTRL_SRC_INC_MASK) >> _DMA_CTRL_SRC_INC_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 210 | if (inc == _DMA_CTRL_SRC_INC_NONE) |
<> | 144:ef7eb2e8f9f7 | 211 | { |
<> | 144:ef7eb2e8f9f7 | 212 | descr->SRCEND = src; |
<> | 144:ef7eb2e8f9f7 | 213 | } |
<> | 144:ef7eb2e8f9f7 | 214 | else |
<> | 144:ef7eb2e8f9f7 | 215 | { |
<> | 144:ef7eb2e8f9f7 | 216 | descr->SRCEND = (void *)((uint32_t)src + (nMinus1 << inc)); |
<> | 144:ef7eb2e8f9f7 | 217 | } |
<> | 144:ef7eb2e8f9f7 | 218 | } |
<> | 144:ef7eb2e8f9f7 | 219 | |
<> | 144:ef7eb2e8f9f7 | 220 | if (dst) |
<> | 144:ef7eb2e8f9f7 | 221 | { |
<> | 144:ef7eb2e8f9f7 | 222 | inc = (descr->CTRL & _DMA_CTRL_DST_INC_MASK) >> _DMA_CTRL_DST_INC_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 223 | if (inc == _DMA_CTRL_DST_INC_NONE) |
<> | 144:ef7eb2e8f9f7 | 224 | { |
<> | 144:ef7eb2e8f9f7 | 225 | descr->DSTEND = dst; |
<> | 144:ef7eb2e8f9f7 | 226 | } |
<> | 144:ef7eb2e8f9f7 | 227 | else |
<> | 144:ef7eb2e8f9f7 | 228 | { |
<> | 144:ef7eb2e8f9f7 | 229 | descr->DSTEND = (void *)((uint32_t)dst + (nMinus1 << inc)); |
<> | 144:ef7eb2e8f9f7 | 230 | } |
<> | 144:ef7eb2e8f9f7 | 231 | } |
<> | 144:ef7eb2e8f9f7 | 232 | |
<> | 144:ef7eb2e8f9f7 | 233 | chBit = 1 << channel; |
<> | 144:ef7eb2e8f9f7 | 234 | if (useBurst) |
<> | 144:ef7eb2e8f9f7 | 235 | { |
<> | 144:ef7eb2e8f9f7 | 236 | DMA->CHUSEBURSTS = chBit; |
<> | 144:ef7eb2e8f9f7 | 237 | } |
<> | 144:ef7eb2e8f9f7 | 238 | else |
<> | 144:ef7eb2e8f9f7 | 239 | { |
<> | 144:ef7eb2e8f9f7 | 240 | DMA->CHUSEBURSTC = chBit; |
<> | 144:ef7eb2e8f9f7 | 241 | } |
<> | 144:ef7eb2e8f9f7 | 242 | |
<> | 144:ef7eb2e8f9f7 | 243 | if (primary) |
<> | 144:ef7eb2e8f9f7 | 244 | { |
<> | 144:ef7eb2e8f9f7 | 245 | DMA->CHALTC = chBit; |
<> | 144:ef7eb2e8f9f7 | 246 | } |
<> | 144:ef7eb2e8f9f7 | 247 | else |
<> | 144:ef7eb2e8f9f7 | 248 | { |
<> | 144:ef7eb2e8f9f7 | 249 | DMA->CHALTS = chBit; |
<> | 144:ef7eb2e8f9f7 | 250 | } |
<> | 144:ef7eb2e8f9f7 | 251 | |
<> | 144:ef7eb2e8f9f7 | 252 | /* Set cycle control */ |
<> | 144:ef7eb2e8f9f7 | 253 | tmp = descr->CTRL & ~(_DMA_CTRL_CYCLE_CTRL_MASK | _DMA_CTRL_N_MINUS_1_MASK); |
<> | 144:ef7eb2e8f9f7 | 254 | tmp |= nMinus1 << _DMA_CTRL_N_MINUS_1_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 255 | tmp |= (uint32_t)cycleCtrl << _DMA_CTRL_CYCLE_CTRL_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 256 | descr->CTRL = tmp; |
<> | 144:ef7eb2e8f9f7 | 257 | } |
<> | 144:ef7eb2e8f9f7 | 258 | |
<> | 144:ef7eb2e8f9f7 | 259 | /** @endcond */ |
<> | 144:ef7eb2e8f9f7 | 260 | |
<> | 144:ef7eb2e8f9f7 | 261 | /******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 262 | ************************ INTERRUPT FUNCTIONS ****************************** |
<> | 144:ef7eb2e8f9f7 | 263 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 264 | |
<> | 144:ef7eb2e8f9f7 | 265 | #ifndef EXCLUDE_DEFAULT_DMA_IRQ_HANDLER |
<> | 144:ef7eb2e8f9f7 | 266 | |
<> | 144:ef7eb2e8f9f7 | 267 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 268 | * @brief |
<> | 144:ef7eb2e8f9f7 | 269 | * Interrupt handler for DMA cycle completion handling. |
<> | 144:ef7eb2e8f9f7 | 270 | * |
<> | 144:ef7eb2e8f9f7 | 271 | * @details |
<> | 144:ef7eb2e8f9f7 | 272 | * Clears any pending flags and calls registered callback (if any). |
<> | 144:ef7eb2e8f9f7 | 273 | * |
<> | 144:ef7eb2e8f9f7 | 274 | * If using the default interrupt vector table setup provided, this function |
<> | 144:ef7eb2e8f9f7 | 275 | * is automatically placed in the IRQ table due to weak linking. If taking |
<> | 144:ef7eb2e8f9f7 | 276 | * control over the interrupt vector table in some other way, this interrupt |
<> | 144:ef7eb2e8f9f7 | 277 | * handler must be installed in order to be able to support callback actions. |
<> | 144:ef7eb2e8f9f7 | 278 | * |
<> | 144:ef7eb2e8f9f7 | 279 | * In order for the user to implement a custom IRQ handler or run without |
<> | 144:ef7eb2e8f9f7 | 280 | * a DMA IRQ handler, the user can define EXCLUDE_DEFAULT_DMA_IRQ_HANDLER |
<> | 144:ef7eb2e8f9f7 | 281 | * with a \#define statement or with the compiler option -D. |
<> | 144:ef7eb2e8f9f7 | 282 | * |
<> | 144:ef7eb2e8f9f7 | 283 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 284 | void DMA_IRQHandler(void) |
<> | 144:ef7eb2e8f9f7 | 285 | { |
<> | 144:ef7eb2e8f9f7 | 286 | int channel; |
<> | 144:ef7eb2e8f9f7 | 287 | DMA_CB_TypeDef *cb; |
<> | 144:ef7eb2e8f9f7 | 288 | uint32_t pending; |
<> | 144:ef7eb2e8f9f7 | 289 | uint32_t pendingPrio; |
<> | 144:ef7eb2e8f9f7 | 290 | uint32_t prio; |
<> | 144:ef7eb2e8f9f7 | 291 | uint32_t primaryCpy; |
<> | 144:ef7eb2e8f9f7 | 292 | int i; |
<> | 144:ef7eb2e8f9f7 | 293 | |
<> | 144:ef7eb2e8f9f7 | 294 | /* Get all pending and enabled interrupts */ |
<> | 144:ef7eb2e8f9f7 | 295 | pending = DMA->IF; |
<> | 144:ef7eb2e8f9f7 | 296 | pending &= DMA->IEN; |
<> | 144:ef7eb2e8f9f7 | 297 | |
<> | 144:ef7eb2e8f9f7 | 298 | /* Check for bus error */ |
<> | 144:ef7eb2e8f9f7 | 299 | if (pending & DMA_IF_ERR) |
<> | 144:ef7eb2e8f9f7 | 300 | { |
<> | 144:ef7eb2e8f9f7 | 301 | /* Loop here to enable the debugger to see what has happened */ |
<> | 144:ef7eb2e8f9f7 | 302 | while (1) |
<> | 144:ef7eb2e8f9f7 | 303 | ; |
<> | 144:ef7eb2e8f9f7 | 304 | } |
<> | 144:ef7eb2e8f9f7 | 305 | |
<> | 144:ef7eb2e8f9f7 | 306 | /* Process all pending channel interrupts. First process channels */ |
<> | 144:ef7eb2e8f9f7 | 307 | /* defined with high priority, then those with default priority. */ |
<> | 144:ef7eb2e8f9f7 | 308 | prio = DMA->CHPRIS; |
<> | 144:ef7eb2e8f9f7 | 309 | pendingPrio = pending & prio; |
<> | 144:ef7eb2e8f9f7 | 310 | for (i = 0; i < 2; i++) |
<> | 144:ef7eb2e8f9f7 | 311 | { |
<> | 144:ef7eb2e8f9f7 | 312 | channel = 0; |
<> | 144:ef7eb2e8f9f7 | 313 | /* Process pending interrupts within high/default priority group */ |
<> | 144:ef7eb2e8f9f7 | 314 | /* honouring priority within group. */ |
<> | 144:ef7eb2e8f9f7 | 315 | while (pendingPrio) |
<> | 144:ef7eb2e8f9f7 | 316 | { |
<> | 144:ef7eb2e8f9f7 | 317 | if (pendingPrio & 1) |
<> | 144:ef7eb2e8f9f7 | 318 | { |
<> | 144:ef7eb2e8f9f7 | 319 | DMA_DESCRIPTOR_TypeDef *descr = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE); |
<> | 144:ef7eb2e8f9f7 | 320 | uint32_t chmask = 1 << channel; |
<> | 144:ef7eb2e8f9f7 | 321 | |
<> | 144:ef7eb2e8f9f7 | 322 | /* Clear pending interrupt prior to invoking callback, in case it */ |
<> | 144:ef7eb2e8f9f7 | 323 | /* sets up another DMA cycle. */ |
<> | 144:ef7eb2e8f9f7 | 324 | DMA->IFC = chmask; |
<> | 144:ef7eb2e8f9f7 | 325 | |
<> | 144:ef7eb2e8f9f7 | 326 | /* Normally, no point in enabling interrupt without callback, but */ |
<> | 144:ef7eb2e8f9f7 | 327 | /* check if callback is defined anyway. Callback info is always */ |
<> | 144:ef7eb2e8f9f7 | 328 | /* located in primary descriptor. */ |
<> | 144:ef7eb2e8f9f7 | 329 | cb = (DMA_CB_TypeDef *)(descr[channel].USER); |
<> | 144:ef7eb2e8f9f7 | 330 | if (cb) |
<> | 144:ef7eb2e8f9f7 | 331 | { |
<> | 144:ef7eb2e8f9f7 | 332 | /* Toggle next-descriptor indicator always prior to invoking */ |
<> | 144:ef7eb2e8f9f7 | 333 | /* callback (in case callback reconfigurs something) */ |
<> | 144:ef7eb2e8f9f7 | 334 | primaryCpy = cb->primary; |
<> | 144:ef7eb2e8f9f7 | 335 | cb->primary ^= 1; |
<> | 144:ef7eb2e8f9f7 | 336 | if (cb->cbFunc) |
<> | 144:ef7eb2e8f9f7 | 337 | { |
<> | 144:ef7eb2e8f9f7 | 338 | cb->cbFunc(channel, (bool)primaryCpy, cb->userPtr); |
<> | 144:ef7eb2e8f9f7 | 339 | } |
<> | 144:ef7eb2e8f9f7 | 340 | } |
<> | 144:ef7eb2e8f9f7 | 341 | } |
<> | 144:ef7eb2e8f9f7 | 342 | |
<> | 144:ef7eb2e8f9f7 | 343 | pendingPrio >>= 1; |
<> | 144:ef7eb2e8f9f7 | 344 | channel++; |
<> | 144:ef7eb2e8f9f7 | 345 | } |
<> | 144:ef7eb2e8f9f7 | 346 | |
<> | 144:ef7eb2e8f9f7 | 347 | /* On second iteration, process default priority channels */ |
<> | 144:ef7eb2e8f9f7 | 348 | pendingPrio = pending & ~prio; |
<> | 144:ef7eb2e8f9f7 | 349 | } |
<> | 144:ef7eb2e8f9f7 | 350 | } |
<> | 144:ef7eb2e8f9f7 | 351 | |
<> | 144:ef7eb2e8f9f7 | 352 | #endif /* EXCLUDE_DEFAULT_DMA_IRQ_HANDLER */ |
<> | 144:ef7eb2e8f9f7 | 353 | |
<> | 144:ef7eb2e8f9f7 | 354 | |
<> | 144:ef7eb2e8f9f7 | 355 | /******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 356 | ************************** GLOBAL FUNCTIONS ******************************* |
<> | 144:ef7eb2e8f9f7 | 357 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 358 | |
<> | 144:ef7eb2e8f9f7 | 359 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 360 | * @brief |
<> | 144:ef7eb2e8f9f7 | 361 | * Activate DMA auto-request cycle (used for memory-memory transfers). |
<> | 144:ef7eb2e8f9f7 | 362 | * |
<> | 144:ef7eb2e8f9f7 | 363 | * @details |
<> | 144:ef7eb2e8f9f7 | 364 | * Prior to activating the DMA cycle, the channel and descriptor to be used |
<> | 144:ef7eb2e8f9f7 | 365 | * must have been properly configured. |
<> | 144:ef7eb2e8f9f7 | 366 | * |
<> | 144:ef7eb2e8f9f7 | 367 | * @note |
<> | 144:ef7eb2e8f9f7 | 368 | * If using this function on a channel already activated and in use by the |
<> | 144:ef7eb2e8f9f7 | 369 | * DMA controller, the behaviour is undefined. |
<> | 144:ef7eb2e8f9f7 | 370 | * |
<> | 144:ef7eb2e8f9f7 | 371 | * @param[in] channel |
<> | 144:ef7eb2e8f9f7 | 372 | * DMA channel to activate DMA cycle for. |
<> | 144:ef7eb2e8f9f7 | 373 | * |
<> | 144:ef7eb2e8f9f7 | 374 | * @param[in] primary |
<> | 144:ef7eb2e8f9f7 | 375 | * @li true - activate using primary descriptor |
<> | 144:ef7eb2e8f9f7 | 376 | * @li false - activate using alternate descriptor |
<> | 144:ef7eb2e8f9f7 | 377 | * |
<> | 144:ef7eb2e8f9f7 | 378 | * @param[in] dst |
<> | 144:ef7eb2e8f9f7 | 379 | * Address to start location to transfer data to. If NULL, leave setting in |
<> | 144:ef7eb2e8f9f7 | 380 | * descriptor as is from a previous activation. |
<> | 144:ef7eb2e8f9f7 | 381 | * |
<> | 144:ef7eb2e8f9f7 | 382 | * @param[in] src |
<> | 144:ef7eb2e8f9f7 | 383 | * Address to start location to transfer data from. If NULL, leave setting in |
<> | 144:ef7eb2e8f9f7 | 384 | * descriptor as is from a previous activation. |
<> | 144:ef7eb2e8f9f7 | 385 | * |
<> | 144:ef7eb2e8f9f7 | 386 | * @param[in] nMinus1 |
<> | 144:ef7eb2e8f9f7 | 387 | * Number of DMA transfer elements (minus 1) to transfer (<= 1023). The |
<> | 144:ef7eb2e8f9f7 | 388 | * size of the DMA transfer element (1, 2 or 4 bytes) is configured with |
<> | 144:ef7eb2e8f9f7 | 389 | * DMA_CfgDescr(). |
<> | 144:ef7eb2e8f9f7 | 390 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 391 | void DMA_ActivateAuto(unsigned int channel, |
<> | 144:ef7eb2e8f9f7 | 392 | bool primary, |
<> | 144:ef7eb2e8f9f7 | 393 | void *dst, |
<> | 144:ef7eb2e8f9f7 | 394 | void *src, |
<> | 144:ef7eb2e8f9f7 | 395 | unsigned int nMinus1) |
<> | 144:ef7eb2e8f9f7 | 396 | { |
<> | 144:ef7eb2e8f9f7 | 397 | uint32_t chBit; |
<> | 144:ef7eb2e8f9f7 | 398 | |
<> | 144:ef7eb2e8f9f7 | 399 | EFM_ASSERT(channel < DMA_CHAN_COUNT); |
<> | 144:ef7eb2e8f9f7 | 400 | EFM_ASSERT(nMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT)); |
<> | 144:ef7eb2e8f9f7 | 401 | |
<> | 144:ef7eb2e8f9f7 | 402 | DMA_Prepare(channel, |
<> | 144:ef7eb2e8f9f7 | 403 | dmaCycleCtrlAuto, |
<> | 144:ef7eb2e8f9f7 | 404 | primary, |
<> | 144:ef7eb2e8f9f7 | 405 | false, |
<> | 144:ef7eb2e8f9f7 | 406 | dst, |
<> | 144:ef7eb2e8f9f7 | 407 | src, |
<> | 144:ef7eb2e8f9f7 | 408 | nMinus1); |
<> | 144:ef7eb2e8f9f7 | 409 | |
<> | 144:ef7eb2e8f9f7 | 410 | chBit = 1 << channel; |
<> | 144:ef7eb2e8f9f7 | 411 | DMA->CHENS = chBit; /* Enable channel */ |
<> | 144:ef7eb2e8f9f7 | 412 | DMA->CHSWREQ = chBit; /* Activate with SW request */ |
<> | 144:ef7eb2e8f9f7 | 413 | } |
<> | 144:ef7eb2e8f9f7 | 414 | |
<> | 144:ef7eb2e8f9f7 | 415 | |
<> | 144:ef7eb2e8f9f7 | 416 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 417 | * @brief |
<> | 144:ef7eb2e8f9f7 | 418 | * Activate DMA basic cycle (used for memory-peripheral transfers). |
<> | 144:ef7eb2e8f9f7 | 419 | * |
<> | 144:ef7eb2e8f9f7 | 420 | * @details |
<> | 144:ef7eb2e8f9f7 | 421 | * Prior to activating the DMA cycle, the channel and descriptor to be used |
<> | 144:ef7eb2e8f9f7 | 422 | * must have been properly configured. |
<> | 144:ef7eb2e8f9f7 | 423 | * |
<> | 144:ef7eb2e8f9f7 | 424 | * @note |
<> | 144:ef7eb2e8f9f7 | 425 | * If using this function on a channel already activated and in use by the |
<> | 144:ef7eb2e8f9f7 | 426 | * DMA controller, the behaviour is undefined. |
<> | 144:ef7eb2e8f9f7 | 427 | * |
<> | 144:ef7eb2e8f9f7 | 428 | * @param[in] channel |
<> | 144:ef7eb2e8f9f7 | 429 | * DMA channel to activate DMA cycle for. |
<> | 144:ef7eb2e8f9f7 | 430 | * |
<> | 144:ef7eb2e8f9f7 | 431 | * @param[in] primary |
<> | 144:ef7eb2e8f9f7 | 432 | * @li true - activate using primary descriptor |
<> | 144:ef7eb2e8f9f7 | 433 | * @li false - activate using alternate descriptor |
<> | 144:ef7eb2e8f9f7 | 434 | * |
<> | 144:ef7eb2e8f9f7 | 435 | * @param[in] useBurst |
<> | 144:ef7eb2e8f9f7 | 436 | * The burst feature is only used on peripherals supporting DMA bursts. |
<> | 144:ef7eb2e8f9f7 | 437 | * Bursts must not be used if the total length (as given by nMinus1) is |
<> | 144:ef7eb2e8f9f7 | 438 | * less than the arbitration rate configured for the descriptor. Please |
<> | 144:ef7eb2e8f9f7 | 439 | * refer to the reference manual for further details on burst usage. |
<> | 144:ef7eb2e8f9f7 | 440 | * |
<> | 144:ef7eb2e8f9f7 | 441 | * @param[in] dst |
<> | 144:ef7eb2e8f9f7 | 442 | * Address to start location to transfer data to. If NULL, leave setting in |
<> | 144:ef7eb2e8f9f7 | 443 | * descriptor as is from a previous activation. |
<> | 144:ef7eb2e8f9f7 | 444 | * |
<> | 144:ef7eb2e8f9f7 | 445 | * @param[in] src |
<> | 144:ef7eb2e8f9f7 | 446 | * Address to start location to transfer data from. If NULL, leave setting in |
<> | 144:ef7eb2e8f9f7 | 447 | * descriptor as is from a previous activation. |
<> | 144:ef7eb2e8f9f7 | 448 | * |
<> | 144:ef7eb2e8f9f7 | 449 | * @param[in] nMinus1 |
<> | 144:ef7eb2e8f9f7 | 450 | * Number of DMA transfer elements (minus 1) to transfer (<= 1023). The |
<> | 144:ef7eb2e8f9f7 | 451 | * size of the DMA transfer element (1, 2 or 4 bytes) is configured with |
<> | 144:ef7eb2e8f9f7 | 452 | * DMA_CfgDescr(). |
<> | 144:ef7eb2e8f9f7 | 453 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 454 | void DMA_ActivateBasic(unsigned int channel, |
<> | 144:ef7eb2e8f9f7 | 455 | bool primary, |
<> | 144:ef7eb2e8f9f7 | 456 | bool useBurst, |
<> | 144:ef7eb2e8f9f7 | 457 | void *dst, |
<> | 144:ef7eb2e8f9f7 | 458 | void *src, |
<> | 144:ef7eb2e8f9f7 | 459 | unsigned int nMinus1) |
<> | 144:ef7eb2e8f9f7 | 460 | { |
<> | 144:ef7eb2e8f9f7 | 461 | EFM_ASSERT(channel < DMA_CHAN_COUNT); |
<> | 144:ef7eb2e8f9f7 | 462 | EFM_ASSERT(nMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT)); |
<> | 144:ef7eb2e8f9f7 | 463 | |
<> | 144:ef7eb2e8f9f7 | 464 | DMA_Prepare(channel, |
<> | 144:ef7eb2e8f9f7 | 465 | dmaCycleCtrlBasic, |
<> | 144:ef7eb2e8f9f7 | 466 | primary, |
<> | 144:ef7eb2e8f9f7 | 467 | useBurst, |
<> | 144:ef7eb2e8f9f7 | 468 | dst, |
<> | 144:ef7eb2e8f9f7 | 469 | src, |
<> | 144:ef7eb2e8f9f7 | 470 | nMinus1); |
<> | 144:ef7eb2e8f9f7 | 471 | |
<> | 144:ef7eb2e8f9f7 | 472 | /* Enable channel, request signal is provided by peripheral device */ |
<> | 144:ef7eb2e8f9f7 | 473 | DMA->CHENS = 1 << channel; |
<> | 144:ef7eb2e8f9f7 | 474 | } |
<> | 144:ef7eb2e8f9f7 | 475 | |
<> | 144:ef7eb2e8f9f7 | 476 | |
<> | 144:ef7eb2e8f9f7 | 477 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 478 | * @brief |
<> | 144:ef7eb2e8f9f7 | 479 | * Activate DMA ping-pong cycle (used for memory-peripheral transfers). |
<> | 144:ef7eb2e8f9f7 | 480 | * |
<> | 144:ef7eb2e8f9f7 | 481 | * @details |
<> | 144:ef7eb2e8f9f7 | 482 | * Prior to activating the DMA cycle, the channel and both descriptors must |
<> | 144:ef7eb2e8f9f7 | 483 | * have been properly configured. The primary descriptor is always the first |
<> | 144:ef7eb2e8f9f7 | 484 | * descriptor to be used by the DMA controller. |
<> | 144:ef7eb2e8f9f7 | 485 | * |
<> | 144:ef7eb2e8f9f7 | 486 | * @note |
<> | 144:ef7eb2e8f9f7 | 487 | * If using this function on a channel already activated and in use by the |
<> | 144:ef7eb2e8f9f7 | 488 | * DMA controller, the behaviour is undefined. |
<> | 144:ef7eb2e8f9f7 | 489 | * |
<> | 144:ef7eb2e8f9f7 | 490 | * @param[in] channel |
<> | 144:ef7eb2e8f9f7 | 491 | * DMA channel to activate DMA cycle for. |
<> | 144:ef7eb2e8f9f7 | 492 | * |
<> | 144:ef7eb2e8f9f7 | 493 | * @param[in] useBurst |
<> | 144:ef7eb2e8f9f7 | 494 | * The burst feature is only used on peripherals supporting DMA bursts. |
<> | 144:ef7eb2e8f9f7 | 495 | * Bursts must not be used if the total length (as given by nMinus1) is |
<> | 144:ef7eb2e8f9f7 | 496 | * less than the arbitration rate configured for the descriptors. Please |
<> | 144:ef7eb2e8f9f7 | 497 | * refer to the reference manual for further details on burst usage. Notice |
<> | 144:ef7eb2e8f9f7 | 498 | * that this setting is used for both the primary and alternate descriptors. |
<> | 144:ef7eb2e8f9f7 | 499 | * |
<> | 144:ef7eb2e8f9f7 | 500 | * @param[in] primDst |
<> | 144:ef7eb2e8f9f7 | 501 | * Address to start location to transfer data to, for primary descriptor. |
<> | 144:ef7eb2e8f9f7 | 502 | * If NULL, leave setting in descriptor as is from a previous activation. |
<> | 144:ef7eb2e8f9f7 | 503 | * |
<> | 144:ef7eb2e8f9f7 | 504 | * @param[in] primSrc |
<> | 144:ef7eb2e8f9f7 | 505 | * Address to start location to transfer data from, for primary descriptor. |
<> | 144:ef7eb2e8f9f7 | 506 | * If NULL, leave setting in descriptor as is from a previous activation. |
<> | 144:ef7eb2e8f9f7 | 507 | * |
<> | 144:ef7eb2e8f9f7 | 508 | * @param[in] primNMinus1 |
<> | 144:ef7eb2e8f9f7 | 509 | * Number of DMA transfer elements (minus 1) to transfer (<= 1023), for |
<> | 144:ef7eb2e8f9f7 | 510 | * primary descriptor. The size of the DMA transfer element (1, 2 or 4 bytes) |
<> | 144:ef7eb2e8f9f7 | 511 | * is configured with DMA_CfgDescr(). |
<> | 144:ef7eb2e8f9f7 | 512 | * |
<> | 144:ef7eb2e8f9f7 | 513 | * @param[in] altDst |
<> | 144:ef7eb2e8f9f7 | 514 | * Address to start location to transfer data to, for alternate descriptor. |
<> | 144:ef7eb2e8f9f7 | 515 | * If NULL, leave setting in descriptor as is from a previous activation. |
<> | 144:ef7eb2e8f9f7 | 516 | * |
<> | 144:ef7eb2e8f9f7 | 517 | * @param[in] altSrc |
<> | 144:ef7eb2e8f9f7 | 518 | * Address to start location to transfer data from, for alternate descriptor. |
<> | 144:ef7eb2e8f9f7 | 519 | * If NULL, leave setting in descriptor as is from a previous activation. |
<> | 144:ef7eb2e8f9f7 | 520 | * |
<> | 144:ef7eb2e8f9f7 | 521 | * @param[in] altNMinus1 |
<> | 144:ef7eb2e8f9f7 | 522 | * Number of DMA transfer elements (minus 1) to transfer (<= 1023), for |
<> | 144:ef7eb2e8f9f7 | 523 | * alternate descriptor. The size of the DMA transfer element (1, 2 or 4 bytes) |
<> | 144:ef7eb2e8f9f7 | 524 | * is configured with DMA_CfgDescr(). |
<> | 144:ef7eb2e8f9f7 | 525 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 526 | void DMA_ActivatePingPong(unsigned int channel, |
<> | 144:ef7eb2e8f9f7 | 527 | bool useBurst, |
<> | 144:ef7eb2e8f9f7 | 528 | void *primDst, |
<> | 144:ef7eb2e8f9f7 | 529 | void *primSrc, |
<> | 144:ef7eb2e8f9f7 | 530 | unsigned int primNMinus1, |
<> | 144:ef7eb2e8f9f7 | 531 | void *altDst, |
<> | 144:ef7eb2e8f9f7 | 532 | void *altSrc, |
<> | 144:ef7eb2e8f9f7 | 533 | unsigned int altNMinus1) |
<> | 144:ef7eb2e8f9f7 | 534 | { |
<> | 144:ef7eb2e8f9f7 | 535 | EFM_ASSERT(channel < DMA_CHAN_COUNT); |
<> | 144:ef7eb2e8f9f7 | 536 | EFM_ASSERT(primNMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT)); |
<> | 144:ef7eb2e8f9f7 | 537 | EFM_ASSERT(altNMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT)); |
<> | 144:ef7eb2e8f9f7 | 538 | |
<> | 144:ef7eb2e8f9f7 | 539 | /* Prepare alternate descriptor first */ |
<> | 144:ef7eb2e8f9f7 | 540 | DMA_Prepare(channel, |
<> | 144:ef7eb2e8f9f7 | 541 | dmaCycleCtrlPingPong, |
<> | 144:ef7eb2e8f9f7 | 542 | false, |
<> | 144:ef7eb2e8f9f7 | 543 | useBurst, |
<> | 144:ef7eb2e8f9f7 | 544 | altDst, |
<> | 144:ef7eb2e8f9f7 | 545 | altSrc, |
<> | 144:ef7eb2e8f9f7 | 546 | altNMinus1); |
<> | 144:ef7eb2e8f9f7 | 547 | |
<> | 144:ef7eb2e8f9f7 | 548 | /* Prepare primary descriptor last in order to start cycle using it */ |
<> | 144:ef7eb2e8f9f7 | 549 | DMA_Prepare(channel, |
<> | 144:ef7eb2e8f9f7 | 550 | dmaCycleCtrlPingPong, |
<> | 144:ef7eb2e8f9f7 | 551 | true, |
<> | 144:ef7eb2e8f9f7 | 552 | useBurst, |
<> | 144:ef7eb2e8f9f7 | 553 | primDst, |
<> | 144:ef7eb2e8f9f7 | 554 | primSrc, |
<> | 144:ef7eb2e8f9f7 | 555 | primNMinus1); |
<> | 144:ef7eb2e8f9f7 | 556 | |
<> | 144:ef7eb2e8f9f7 | 557 | /* Enable channel, request signal is provided by peripheral device */ |
<> | 144:ef7eb2e8f9f7 | 558 | DMA->CHENS = 1 << channel; |
<> | 144:ef7eb2e8f9f7 | 559 | } |
<> | 144:ef7eb2e8f9f7 | 560 | |
<> | 144:ef7eb2e8f9f7 | 561 | |
<> | 144:ef7eb2e8f9f7 | 562 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 563 | * @brief |
<> | 144:ef7eb2e8f9f7 | 564 | * Activate DMA scatter-gather cycle (used for either memory-peripheral |
<> | 144:ef7eb2e8f9f7 | 565 | * or memory-memory transfers). |
<> | 144:ef7eb2e8f9f7 | 566 | * |
<> | 144:ef7eb2e8f9f7 | 567 | * @details |
<> | 144:ef7eb2e8f9f7 | 568 | * Prior to activating the DMA cycle, the array with alternate descriptors |
<> | 144:ef7eb2e8f9f7 | 569 | * must have been properly configured. This function can be reused without |
<> | 144:ef7eb2e8f9f7 | 570 | * reconfiguring the alternate descriptors, as long as @p count is the same. |
<> | 144:ef7eb2e8f9f7 | 571 | * |
<> | 144:ef7eb2e8f9f7 | 572 | * @note |
<> | 144:ef7eb2e8f9f7 | 573 | * If using this function on a channel already activated and in use by the |
<> | 144:ef7eb2e8f9f7 | 574 | * DMA controller, the behaviour is undefined. |
<> | 144:ef7eb2e8f9f7 | 575 | * |
<> | 144:ef7eb2e8f9f7 | 576 | * @param[in] channel |
<> | 144:ef7eb2e8f9f7 | 577 | * DMA channel to activate DMA cycle for. |
<> | 144:ef7eb2e8f9f7 | 578 | * |
<> | 144:ef7eb2e8f9f7 | 579 | * @param[in] useBurst |
<> | 144:ef7eb2e8f9f7 | 580 | * The burst feature is only used on peripherals supporting DMA bursts |
<> | 144:ef7eb2e8f9f7 | 581 | * (and thus this parameter is ignored for memory scatter-gather cycles). |
<> | 144:ef7eb2e8f9f7 | 582 | * This parameter determines if bursts should be enabled during DMA transfers |
<> | 144:ef7eb2e8f9f7 | 583 | * using the alternate descriptors. Bursts must not be used if the total |
<> | 144:ef7eb2e8f9f7 | 584 | * length (as given by nMinus1 for the alternate descriptor) is |
<> | 144:ef7eb2e8f9f7 | 585 | * less than the arbitration rate configured for the descriptor. Please |
<> | 144:ef7eb2e8f9f7 | 586 | * refer to the reference manual for further details on burst usage. |
<> | 144:ef7eb2e8f9f7 | 587 | * |
<> | 144:ef7eb2e8f9f7 | 588 | * @param[in,out] altDescr |
<> | 144:ef7eb2e8f9f7 | 589 | * Pointer to start of array with prepared alternate descriptors. The last |
<> | 144:ef7eb2e8f9f7 | 590 | * descriptor will have its cycle control type reprogrammed to basic type. |
<> | 144:ef7eb2e8f9f7 | 591 | * |
<> | 144:ef7eb2e8f9f7 | 592 | * @param[in] count |
<> | 144:ef7eb2e8f9f7 | 593 | * Number of alternate descriptors in @p altDescr array. Maximum number of |
<> | 144:ef7eb2e8f9f7 | 594 | * alternate descriptors is 256. |
<> | 144:ef7eb2e8f9f7 | 595 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 596 | void DMA_ActivateScatterGather(unsigned int channel, |
<> | 144:ef7eb2e8f9f7 | 597 | bool useBurst, |
<> | 144:ef7eb2e8f9f7 | 598 | DMA_DESCRIPTOR_TypeDef *altDescr, |
<> | 144:ef7eb2e8f9f7 | 599 | unsigned int count) |
<> | 144:ef7eb2e8f9f7 | 600 | { |
<> | 144:ef7eb2e8f9f7 | 601 | DMA_DESCRIPTOR_TypeDef *descr; |
<> | 144:ef7eb2e8f9f7 | 602 | DMA_CB_TypeDef *cb; |
<> | 144:ef7eb2e8f9f7 | 603 | uint32_t cycleCtrl; |
<> | 144:ef7eb2e8f9f7 | 604 | uint32_t chBit; |
<> | 144:ef7eb2e8f9f7 | 605 | |
<> | 144:ef7eb2e8f9f7 | 606 | EFM_ASSERT(channel < DMA_CHAN_COUNT); |
<> | 144:ef7eb2e8f9f7 | 607 | EFM_ASSERT(altDescr); |
<> | 144:ef7eb2e8f9f7 | 608 | EFM_ASSERT(count && (count <= 256)); |
<> | 144:ef7eb2e8f9f7 | 609 | |
<> | 144:ef7eb2e8f9f7 | 610 | /* We have to configure the primary descriptor properly in order to */ |
<> | 144:ef7eb2e8f9f7 | 611 | /* transfer one complete alternate descriptor from the alternate */ |
<> | 144:ef7eb2e8f9f7 | 612 | /* descriptor table into the actual alternate descriptor. */ |
<> | 144:ef7eb2e8f9f7 | 613 | descr = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE) + channel; |
<> | 144:ef7eb2e8f9f7 | 614 | |
<> | 144:ef7eb2e8f9f7 | 615 | /* Set source end address to point to alternate descriptor array */ |
<> | 144:ef7eb2e8f9f7 | 616 | descr->SRCEND = (uint32_t *)altDescr + (count * 4) - 1; |
<> | 144:ef7eb2e8f9f7 | 617 | |
<> | 144:ef7eb2e8f9f7 | 618 | /* The destination end address in the primary descriptor MUST point */ |
<> | 144:ef7eb2e8f9f7 | 619 | /* to the corresponding alternate descriptor in scatter-gather mode. */ |
<> | 144:ef7eb2e8f9f7 | 620 | descr->DSTEND = (uint32_t *)((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE) + |
<> | 144:ef7eb2e8f9f7 | 621 | channel + 1) - 1; |
<> | 144:ef7eb2e8f9f7 | 622 | |
<> | 144:ef7eb2e8f9f7 | 623 | /* The user field of the descriptor is used for callback configuration, */ |
<> | 144:ef7eb2e8f9f7 | 624 | /* and already configured when channel is configured. Do not modify it. */ |
<> | 144:ef7eb2e8f9f7 | 625 | |
<> | 144:ef7eb2e8f9f7 | 626 | /* Determine from alternate configuration whether this is a memory or */ |
<> | 144:ef7eb2e8f9f7 | 627 | /* peripheral scatter-gather, by looking at the first alternate descriptor. */ |
<> | 144:ef7eb2e8f9f7 | 628 | cycleCtrl = altDescr->CTRL & _DMA_CTRL_CYCLE_CTRL_MASK; |
<> | 144:ef7eb2e8f9f7 | 629 | cycleCtrl &= ~(1 << _DMA_CTRL_CYCLE_CTRL_SHIFT); |
<> | 144:ef7eb2e8f9f7 | 630 | |
<> | 144:ef7eb2e8f9f7 | 631 | EFM_ASSERT((cycleCtrl == dmaCycleCtrlMemScatterGather) |
<> | 144:ef7eb2e8f9f7 | 632 | || (cycleCtrl == dmaCycleCtrlPerScatterGather)); |
<> | 144:ef7eb2e8f9f7 | 633 | |
<> | 144:ef7eb2e8f9f7 | 634 | /* Set last alternate descriptor to basic or auto-request cycle type in */ |
<> | 144:ef7eb2e8f9f7 | 635 | /* order to have dma_done signal asserted when complete. Otherwise interrupt */ |
<> | 144:ef7eb2e8f9f7 | 636 | /* will not be triggered when done. */ |
<> | 144:ef7eb2e8f9f7 | 637 | altDescr[count - 1].CTRL &= ~_DMA_CTRL_CYCLE_CTRL_MASK; |
<> | 144:ef7eb2e8f9f7 | 638 | if (cycleCtrl == dmaCycleCtrlMemScatterGather) |
<> | 144:ef7eb2e8f9f7 | 639 | { |
<> | 144:ef7eb2e8f9f7 | 640 | altDescr[count - 1].CTRL |= (uint32_t)dmaCycleCtrlAuto |
<> | 144:ef7eb2e8f9f7 | 641 | << _DMA_CTRL_CYCLE_CTRL_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 642 | } |
<> | 144:ef7eb2e8f9f7 | 643 | else |
<> | 144:ef7eb2e8f9f7 | 644 | { |
<> | 144:ef7eb2e8f9f7 | 645 | altDescr[count - 1].CTRL |= (uint32_t)dmaCycleCtrlBasic |
<> | 144:ef7eb2e8f9f7 | 646 | << _DMA_CTRL_CYCLE_CTRL_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 647 | } |
<> | 144:ef7eb2e8f9f7 | 648 | |
<> | 144:ef7eb2e8f9f7 | 649 | /* If callback defined, update info on whether callback is issued for */ |
<> | 144:ef7eb2e8f9f7 | 650 | /* primary or alternate descriptor. Not really useful for scatter-gather, */ |
<> | 144:ef7eb2e8f9f7 | 651 | /* but do for consistency. Always set to alternate, since that is the last */ |
<> | 144:ef7eb2e8f9f7 | 652 | /* descriptor actually used. */ |
<> | 144:ef7eb2e8f9f7 | 653 | cb = (DMA_CB_TypeDef *)(descr->USER); |
<> | 144:ef7eb2e8f9f7 | 654 | if (cb) |
<> | 144:ef7eb2e8f9f7 | 655 | { |
<> | 144:ef7eb2e8f9f7 | 656 | cb->primary = false; |
<> | 144:ef7eb2e8f9f7 | 657 | } |
<> | 144:ef7eb2e8f9f7 | 658 | |
<> | 144:ef7eb2e8f9f7 | 659 | /* Configure primary descriptor control word */ |
<> | 144:ef7eb2e8f9f7 | 660 | descr->CTRL =((uint32_t)dmaDataInc4 << _DMA_CTRL_DST_INC_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 661 | | ((uint32_t)dmaDataSize4 << _DMA_CTRL_DST_SIZE_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 662 | | ((uint32_t)dmaDataInc4 << _DMA_CTRL_SRC_INC_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 663 | | ((uint32_t)dmaDataSize4 << _DMA_CTRL_SRC_SIZE_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 664 | /* Use same protection scheme as for alternate descriptors */ |
<> | 144:ef7eb2e8f9f7 | 665 | | (altDescr->CTRL & _DMA_CTRL_SRC_PROT_CTRL_MASK) |
<> | 144:ef7eb2e8f9f7 | 666 | | ((uint32_t)dmaArbitrate4 << _DMA_CTRL_R_POWER_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 667 | | (((count * 4) - 1) << _DMA_CTRL_N_MINUS_1_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 668 | | (((uint32_t)useBurst & 1) << _DMA_CTRL_NEXT_USEBURST_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 669 | | cycleCtrl; |
<> | 144:ef7eb2e8f9f7 | 670 | |
<> | 144:ef7eb2e8f9f7 | 671 | chBit = 1 << channel; |
<> | 144:ef7eb2e8f9f7 | 672 | |
<> | 144:ef7eb2e8f9f7 | 673 | /* Start with primary descriptor */ |
<> | 144:ef7eb2e8f9f7 | 674 | DMA->CHALTC = chBit; |
<> | 144:ef7eb2e8f9f7 | 675 | |
<> | 144:ef7eb2e8f9f7 | 676 | /* Enable channel */ |
<> | 144:ef7eb2e8f9f7 | 677 | DMA->CHENS = chBit; |
<> | 144:ef7eb2e8f9f7 | 678 | |
<> | 144:ef7eb2e8f9f7 | 679 | /* Send request if memory scatter-gather, otherwise request signal is */ |
<> | 144:ef7eb2e8f9f7 | 680 | /* provided by peripheral. */ |
<> | 144:ef7eb2e8f9f7 | 681 | if (cycleCtrl == dmaCycleCtrlMemScatterGather) |
<> | 144:ef7eb2e8f9f7 | 682 | { |
<> | 144:ef7eb2e8f9f7 | 683 | DMA->CHSWREQ = chBit; |
<> | 144:ef7eb2e8f9f7 | 684 | } |
<> | 144:ef7eb2e8f9f7 | 685 | } |
<> | 144:ef7eb2e8f9f7 | 686 | |
<> | 144:ef7eb2e8f9f7 | 687 | |
<> | 144:ef7eb2e8f9f7 | 688 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 689 | * @brief |
<> | 144:ef7eb2e8f9f7 | 690 | * Configure a DMA channel. |
<> | 144:ef7eb2e8f9f7 | 691 | * |
<> | 144:ef7eb2e8f9f7 | 692 | * @details |
<> | 144:ef7eb2e8f9f7 | 693 | * Configure miscellaneous issues for a DMA channel. This function is typically |
<> | 144:ef7eb2e8f9f7 | 694 | * used once to setup a channel for a certain type of use. |
<> | 144:ef7eb2e8f9f7 | 695 | * |
<> | 144:ef7eb2e8f9f7 | 696 | * @note |
<> | 144:ef7eb2e8f9f7 | 697 | * If using this function on a channel already in use by the DMA controller, |
<> | 144:ef7eb2e8f9f7 | 698 | * the behaviour is undefined. |
<> | 144:ef7eb2e8f9f7 | 699 | * |
<> | 144:ef7eb2e8f9f7 | 700 | * @param[in] channel |
<> | 144:ef7eb2e8f9f7 | 701 | * DMA channel to configure. |
<> | 144:ef7eb2e8f9f7 | 702 | * |
<> | 144:ef7eb2e8f9f7 | 703 | * @param[in] cfg |
<> | 144:ef7eb2e8f9f7 | 704 | * Configuration to use. |
<> | 144:ef7eb2e8f9f7 | 705 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 706 | void DMA_CfgChannel(unsigned int channel, DMA_CfgChannel_TypeDef *cfg) |
<> | 144:ef7eb2e8f9f7 | 707 | { |
<> | 144:ef7eb2e8f9f7 | 708 | DMA_DESCRIPTOR_TypeDef *descr; |
<> | 144:ef7eb2e8f9f7 | 709 | |
<> | 144:ef7eb2e8f9f7 | 710 | EFM_ASSERT(channel < DMA_CHAN_COUNT); |
<> | 144:ef7eb2e8f9f7 | 711 | EFM_ASSERT(cfg); |
<> | 144:ef7eb2e8f9f7 | 712 | |
<> | 144:ef7eb2e8f9f7 | 713 | /* Always keep callback configuration reference in primary descriptor */ |
<> | 144:ef7eb2e8f9f7 | 714 | descr = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE); |
<> | 144:ef7eb2e8f9f7 | 715 | descr[channel].USER = (uint32_t)(cfg->cb); |
<> | 144:ef7eb2e8f9f7 | 716 | |
<> | 144:ef7eb2e8f9f7 | 717 | /* Set to specified priority for channel */ |
<> | 144:ef7eb2e8f9f7 | 718 | if (cfg->highPri) |
<> | 144:ef7eb2e8f9f7 | 719 | { |
<> | 144:ef7eb2e8f9f7 | 720 | DMA->CHPRIS = 1 << channel; |
<> | 144:ef7eb2e8f9f7 | 721 | } |
<> | 144:ef7eb2e8f9f7 | 722 | else |
<> | 144:ef7eb2e8f9f7 | 723 | { |
<> | 144:ef7eb2e8f9f7 | 724 | DMA->CHPRIC = 1 << channel; |
<> | 144:ef7eb2e8f9f7 | 725 | } |
<> | 144:ef7eb2e8f9f7 | 726 | |
<> | 144:ef7eb2e8f9f7 | 727 | /* Set DMA signal source select */ |
<> | 144:ef7eb2e8f9f7 | 728 | DMA->CH[channel].CTRL = cfg->select; |
<> | 144:ef7eb2e8f9f7 | 729 | |
<> | 144:ef7eb2e8f9f7 | 730 | /* Enable/disable interrupt as specified */ |
<> | 144:ef7eb2e8f9f7 | 731 | if (cfg->enableInt) |
<> | 144:ef7eb2e8f9f7 | 732 | { |
<> | 144:ef7eb2e8f9f7 | 733 | DMA->IFC = (1 << channel); |
<> | 144:ef7eb2e8f9f7 | 734 | BUS_RegBitWrite(&(DMA->IEN), channel, 1); |
<> | 144:ef7eb2e8f9f7 | 735 | } |
<> | 144:ef7eb2e8f9f7 | 736 | else |
<> | 144:ef7eb2e8f9f7 | 737 | { |
<> | 144:ef7eb2e8f9f7 | 738 | BUS_RegBitWrite(&(DMA->IEN), channel, 0); |
<> | 144:ef7eb2e8f9f7 | 739 | } |
<> | 144:ef7eb2e8f9f7 | 740 | } |
<> | 144:ef7eb2e8f9f7 | 741 | |
<> | 144:ef7eb2e8f9f7 | 742 | |
<> | 144:ef7eb2e8f9f7 | 743 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 744 | * @brief |
<> | 144:ef7eb2e8f9f7 | 745 | * Configure DMA descriptor for auto-request, basic or ping-pong DMA cycles. |
<> | 144:ef7eb2e8f9f7 | 746 | * |
<> | 144:ef7eb2e8f9f7 | 747 | * @details |
<> | 144:ef7eb2e8f9f7 | 748 | * This function is used for configuration of a descriptor for the following |
<> | 144:ef7eb2e8f9f7 | 749 | * DMA cycle types: |
<> | 144:ef7eb2e8f9f7 | 750 | * |
<> | 144:ef7eb2e8f9f7 | 751 | * @li auto-request - used for memory/memory transfer |
<> | 144:ef7eb2e8f9f7 | 752 | * @li basic - used for a peripheral/memory transfer |
<> | 144:ef7eb2e8f9f7 | 753 | * @li ping-pong - used for a ping-pong based peripheral/memory transfer |
<> | 144:ef7eb2e8f9f7 | 754 | * style providing time to refresh one descriptor while the other is |
<> | 144:ef7eb2e8f9f7 | 755 | * in use. |
<> | 144:ef7eb2e8f9f7 | 756 | * |
<> | 144:ef7eb2e8f9f7 | 757 | * The DMA cycle is not activated, please see DMA_ActivateAuto(), |
<> | 144:ef7eb2e8f9f7 | 758 | * DMA_ActivateBasic() or DMA_ActivatePingPong() to activate the DMA cycle. |
<> | 144:ef7eb2e8f9f7 | 759 | * In many cases, the configuration only has to be done once, and all |
<> | 144:ef7eb2e8f9f7 | 760 | * subsequent cycles may be activated with the activate function. |
<> | 144:ef7eb2e8f9f7 | 761 | * |
<> | 144:ef7eb2e8f9f7 | 762 | * For ping-pong DMA cycles, this function must be used both on the primary |
<> | 144:ef7eb2e8f9f7 | 763 | * and the alternate descriptor prior to activating the DMA cycle. |
<> | 144:ef7eb2e8f9f7 | 764 | * |
<> | 144:ef7eb2e8f9f7 | 765 | * Notice that the DMA channel must also be configured, see DMA_CfgChannel(). |
<> | 144:ef7eb2e8f9f7 | 766 | * |
<> | 144:ef7eb2e8f9f7 | 767 | * @note |
<> | 144:ef7eb2e8f9f7 | 768 | * If using this function on a descriptor already activated and in use by |
<> | 144:ef7eb2e8f9f7 | 769 | * the DMA controller, the behaviour is undefined. |
<> | 144:ef7eb2e8f9f7 | 770 | * |
<> | 144:ef7eb2e8f9f7 | 771 | * @param[in] channel |
<> | 144:ef7eb2e8f9f7 | 772 | * DMA channel to configure for. |
<> | 144:ef7eb2e8f9f7 | 773 | * |
<> | 144:ef7eb2e8f9f7 | 774 | * @param[in] primary |
<> | 144:ef7eb2e8f9f7 | 775 | * @li true - configure primary descriptor |
<> | 144:ef7eb2e8f9f7 | 776 | * @li false - configure alternate descriptor |
<> | 144:ef7eb2e8f9f7 | 777 | * |
<> | 144:ef7eb2e8f9f7 | 778 | * @param[in] cfg |
<> | 144:ef7eb2e8f9f7 | 779 | * Configuration to use. |
<> | 144:ef7eb2e8f9f7 | 780 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 781 | void DMA_CfgDescr(unsigned int channel, |
<> | 144:ef7eb2e8f9f7 | 782 | bool primary, |
<> | 144:ef7eb2e8f9f7 | 783 | DMA_CfgDescr_TypeDef *cfg) |
<> | 144:ef7eb2e8f9f7 | 784 | { |
<> | 144:ef7eb2e8f9f7 | 785 | DMA_DESCRIPTOR_TypeDef *descr; |
<> | 144:ef7eb2e8f9f7 | 786 | |
<> | 144:ef7eb2e8f9f7 | 787 | EFM_ASSERT(channel < DMA_CHAN_COUNT); |
<> | 144:ef7eb2e8f9f7 | 788 | EFM_ASSERT(cfg); |
<> | 144:ef7eb2e8f9f7 | 789 | |
<> | 144:ef7eb2e8f9f7 | 790 | /* Find descriptor to configure */ |
<> | 144:ef7eb2e8f9f7 | 791 | if (primary) |
<> | 144:ef7eb2e8f9f7 | 792 | { |
<> | 144:ef7eb2e8f9f7 | 793 | descr = (DMA_DESCRIPTOR_TypeDef *)DMA->CTRLBASE; |
<> | 144:ef7eb2e8f9f7 | 794 | } |
<> | 144:ef7eb2e8f9f7 | 795 | else |
<> | 144:ef7eb2e8f9f7 | 796 | { |
<> | 144:ef7eb2e8f9f7 | 797 | descr = (DMA_DESCRIPTOR_TypeDef *)DMA->ALTCTRLBASE; |
<> | 144:ef7eb2e8f9f7 | 798 | } |
<> | 144:ef7eb2e8f9f7 | 799 | descr += channel; |
<> | 144:ef7eb2e8f9f7 | 800 | |
<> | 144:ef7eb2e8f9f7 | 801 | /* Prepare the descriptor */ |
<> | 144:ef7eb2e8f9f7 | 802 | /* Source/destination end addresses set when started */ |
<> | 144:ef7eb2e8f9f7 | 803 | descr->CTRL = (cfg->dstInc << _DMA_CTRL_DST_INC_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 804 | | (cfg->size << _DMA_CTRL_DST_SIZE_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 805 | | (cfg->srcInc << _DMA_CTRL_SRC_INC_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 806 | | (cfg->size << _DMA_CTRL_SRC_SIZE_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 807 | | ((uint32_t)(cfg->hprot) << _DMA_CTRL_SRC_PROT_CTRL_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 808 | | (cfg->arbRate << _DMA_CTRL_R_POWER_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 809 | | (0 << _DMA_CTRL_N_MINUS_1_SHIFT) /* Set when activated */ |
<> | 144:ef7eb2e8f9f7 | 810 | | (0 << _DMA_CTRL_NEXT_USEBURST_SHIFT) /* Set when activated */ |
<> | 144:ef7eb2e8f9f7 | 811 | | DMA_CTRL_CYCLE_CTRL_INVALID; /* Set when activated */ |
<> | 144:ef7eb2e8f9f7 | 812 | } |
<> | 144:ef7eb2e8f9f7 | 813 | |
<> | 144:ef7eb2e8f9f7 | 814 | |
<> | 144:ef7eb2e8f9f7 | 815 | #if defined( _DMA_LOOP0_MASK ) && defined( _DMA_LOOP1_MASK ) |
<> | 144:ef7eb2e8f9f7 | 816 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 817 | * @brief Configure DMA channel for Loop mode or 2D transfer. |
<> | 144:ef7eb2e8f9f7 | 818 | * |
<> | 144:ef7eb2e8f9f7 | 819 | * @details |
<> | 144:ef7eb2e8f9f7 | 820 | * For 2D transfer, set cfg->enable to "false", and only configure nMinus1 |
<> | 144:ef7eb2e8f9f7 | 821 | * to same width as channel descriptor. |
<> | 144:ef7eb2e8f9f7 | 822 | * |
<> | 144:ef7eb2e8f9f7 | 823 | * @param[in] channel |
<> | 144:ef7eb2e8f9f7 | 824 | * DMA channel to configure for. |
<> | 144:ef7eb2e8f9f7 | 825 | * |
<> | 144:ef7eb2e8f9f7 | 826 | * @param[in] cfg |
<> | 144:ef7eb2e8f9f7 | 827 | * Configuration to use. |
<> | 144:ef7eb2e8f9f7 | 828 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 829 | void DMA_CfgLoop(unsigned int channel, DMA_CfgLoop_TypeDef *cfg) |
<> | 144:ef7eb2e8f9f7 | 830 | { |
<> | 144:ef7eb2e8f9f7 | 831 | EFM_ASSERT(channel <= 1); |
<> | 144:ef7eb2e8f9f7 | 832 | EFM_ASSERT(cfg->nMinus1 <= 1023); |
<> | 144:ef7eb2e8f9f7 | 833 | |
<> | 144:ef7eb2e8f9f7 | 834 | /* Configure LOOP setting */ |
<> | 144:ef7eb2e8f9f7 | 835 | switch( channel ) |
<> | 144:ef7eb2e8f9f7 | 836 | { |
<> | 144:ef7eb2e8f9f7 | 837 | case 0: |
<> | 144:ef7eb2e8f9f7 | 838 | DMA->LOOP0 = (cfg->enable << _DMA_LOOP0_EN_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 839 | | (cfg->nMinus1 << _DMA_LOOP0_WIDTH_SHIFT); |
<> | 144:ef7eb2e8f9f7 | 840 | break; |
<> | 144:ef7eb2e8f9f7 | 841 | case 1: |
<> | 144:ef7eb2e8f9f7 | 842 | DMA->LOOP1 = (cfg->enable << _DMA_LOOP1_EN_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 843 | | (cfg->nMinus1 << _DMA_LOOP1_WIDTH_SHIFT); |
<> | 144:ef7eb2e8f9f7 | 844 | break; |
<> | 144:ef7eb2e8f9f7 | 845 | } |
<> | 144:ef7eb2e8f9f7 | 846 | } |
<> | 144:ef7eb2e8f9f7 | 847 | #endif |
<> | 144:ef7eb2e8f9f7 | 848 | |
<> | 144:ef7eb2e8f9f7 | 849 | |
<> | 144:ef7eb2e8f9f7 | 850 | #if defined( _DMA_RECT0_MASK ) |
<> | 144:ef7eb2e8f9f7 | 851 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 852 | * @brief Configure DMA channel 2D transfer properties. |
<> | 144:ef7eb2e8f9f7 | 853 | * |
<> | 144:ef7eb2e8f9f7 | 854 | * @param[in] channel |
<> | 144:ef7eb2e8f9f7 | 855 | * DMA channel to configure for. |
<> | 144:ef7eb2e8f9f7 | 856 | * |
<> | 144:ef7eb2e8f9f7 | 857 | * @param[in] cfg |
<> | 144:ef7eb2e8f9f7 | 858 | * Configuration to use. |
<> | 144:ef7eb2e8f9f7 | 859 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 860 | void DMA_CfgRect(unsigned int channel, DMA_CfgRect_TypeDef *cfg) |
<> | 144:ef7eb2e8f9f7 | 861 | { |
<> | 144:ef7eb2e8f9f7 | 862 | (void)channel; /* Unused parameter */ |
<> | 144:ef7eb2e8f9f7 | 863 | |
<> | 144:ef7eb2e8f9f7 | 864 | EFM_ASSERT(channel == 0); |
<> | 144:ef7eb2e8f9f7 | 865 | EFM_ASSERT(cfg->dstStride <= 2047); |
<> | 144:ef7eb2e8f9f7 | 866 | EFM_ASSERT(cfg->srcStride <= 2047); |
<> | 144:ef7eb2e8f9f7 | 867 | EFM_ASSERT(cfg->height <= 1023); |
<> | 144:ef7eb2e8f9f7 | 868 | |
<> | 144:ef7eb2e8f9f7 | 869 | /* Configure rectangular/2D copy */ |
<> | 144:ef7eb2e8f9f7 | 870 | DMA->RECT0 = (cfg->dstStride << _DMA_RECT0_DSTSTRIDE_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 871 | | (cfg->srcStride << _DMA_RECT0_SRCSTRIDE_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 872 | | (cfg->height << _DMA_RECT0_HEIGHT_SHIFT); |
<> | 144:ef7eb2e8f9f7 | 873 | } |
<> | 144:ef7eb2e8f9f7 | 874 | #endif |
<> | 144:ef7eb2e8f9f7 | 875 | |
<> | 144:ef7eb2e8f9f7 | 876 | |
<> | 144:ef7eb2e8f9f7 | 877 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 878 | * @brief |
<> | 144:ef7eb2e8f9f7 | 879 | * Configure an alternate DMA descriptor for use with scatter-gather DMA |
<> | 144:ef7eb2e8f9f7 | 880 | * cycles. |
<> | 144:ef7eb2e8f9f7 | 881 | * |
<> | 144:ef7eb2e8f9f7 | 882 | * @details |
<> | 144:ef7eb2e8f9f7 | 883 | * In scatter-gather mode, the alternate descriptors are located in one |
<> | 144:ef7eb2e8f9f7 | 884 | * contiguous memory area. Each of the alternate descriptor must be fully |
<> | 144:ef7eb2e8f9f7 | 885 | * configured prior to starting the scatter-gather DMA cycle. |
<> | 144:ef7eb2e8f9f7 | 886 | * |
<> | 144:ef7eb2e8f9f7 | 887 | * The DMA cycle is not activated by this function, please see |
<> | 144:ef7eb2e8f9f7 | 888 | * DMA_ActivateScatterGather() to activate the DMA cycle. In some cases, the |
<> | 144:ef7eb2e8f9f7 | 889 | * alternate configuration only has to be done once, and all subsequent |
<> | 144:ef7eb2e8f9f7 | 890 | * transfers may be activated with the activate function. |
<> | 144:ef7eb2e8f9f7 | 891 | * |
<> | 144:ef7eb2e8f9f7 | 892 | * Notice that the DMA channel must also be configured, see DMA_CfgChannel(). |
<> | 144:ef7eb2e8f9f7 | 893 | * |
<> | 144:ef7eb2e8f9f7 | 894 | * @param[in] descr |
<> | 144:ef7eb2e8f9f7 | 895 | * Points to start of memory area holding the alternate descriptors. |
<> | 144:ef7eb2e8f9f7 | 896 | * |
<> | 144:ef7eb2e8f9f7 | 897 | * @param[in] indx |
<> | 144:ef7eb2e8f9f7 | 898 | * Alternate descriptor index number to configure (numbered from 0). |
<> | 144:ef7eb2e8f9f7 | 899 | * |
<> | 144:ef7eb2e8f9f7 | 900 | * @param[in] cfg |
<> | 144:ef7eb2e8f9f7 | 901 | * Configuration to use. |
<> | 144:ef7eb2e8f9f7 | 902 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 903 | void DMA_CfgDescrScatterGather(DMA_DESCRIPTOR_TypeDef *descr, |
<> | 144:ef7eb2e8f9f7 | 904 | unsigned int indx, |
<> | 144:ef7eb2e8f9f7 | 905 | DMA_CfgDescrSGAlt_TypeDef *cfg) |
<> | 144:ef7eb2e8f9f7 | 906 | { |
<> | 144:ef7eb2e8f9f7 | 907 | uint32_t cycleCtrl; |
<> | 144:ef7eb2e8f9f7 | 908 | |
<> | 144:ef7eb2e8f9f7 | 909 | EFM_ASSERT(descr); |
<> | 144:ef7eb2e8f9f7 | 910 | EFM_ASSERT(cfg); |
<> | 144:ef7eb2e8f9f7 | 911 | |
<> | 144:ef7eb2e8f9f7 | 912 | /* Point to selected entry in alternate descriptor table */ |
<> | 144:ef7eb2e8f9f7 | 913 | descr += indx; |
<> | 144:ef7eb2e8f9f7 | 914 | |
<> | 144:ef7eb2e8f9f7 | 915 | if (cfg->srcInc == dmaDataIncNone) |
<> | 144:ef7eb2e8f9f7 | 916 | { |
<> | 144:ef7eb2e8f9f7 | 917 | descr->SRCEND = cfg->src; |
<> | 144:ef7eb2e8f9f7 | 918 | } |
<> | 144:ef7eb2e8f9f7 | 919 | else |
<> | 144:ef7eb2e8f9f7 | 920 | { |
<> | 144:ef7eb2e8f9f7 | 921 | descr->SRCEND = (void *)((uint32_t)(cfg->src) |
<> | 144:ef7eb2e8f9f7 | 922 | + ((uint32_t)(cfg->nMinus1) << cfg->srcInc)); |
<> | 144:ef7eb2e8f9f7 | 923 | } |
<> | 144:ef7eb2e8f9f7 | 924 | |
<> | 144:ef7eb2e8f9f7 | 925 | if (cfg->dstInc == dmaDataIncNone) |
<> | 144:ef7eb2e8f9f7 | 926 | { |
<> | 144:ef7eb2e8f9f7 | 927 | descr->DSTEND = cfg->dst; |
<> | 144:ef7eb2e8f9f7 | 928 | } |
<> | 144:ef7eb2e8f9f7 | 929 | else |
<> | 144:ef7eb2e8f9f7 | 930 | { |
<> | 144:ef7eb2e8f9f7 | 931 | descr->DSTEND = (void *)((uint32_t)(cfg->dst) |
<> | 144:ef7eb2e8f9f7 | 932 | + ((uint32_t)(cfg->nMinus1) << cfg->dstInc)); |
<> | 144:ef7eb2e8f9f7 | 933 | } |
<> | 144:ef7eb2e8f9f7 | 934 | |
<> | 144:ef7eb2e8f9f7 | 935 | /* User definable part not used */ |
<> | 144:ef7eb2e8f9f7 | 936 | descr->USER = 0; |
<> | 144:ef7eb2e8f9f7 | 937 | |
<> | 144:ef7eb2e8f9f7 | 938 | if (cfg->peripheral) |
<> | 144:ef7eb2e8f9f7 | 939 | { |
<> | 144:ef7eb2e8f9f7 | 940 | cycleCtrl = (uint32_t)dmaCycleCtrlPerScatterGather + 1; |
<> | 144:ef7eb2e8f9f7 | 941 | } |
<> | 144:ef7eb2e8f9f7 | 942 | else |
<> | 144:ef7eb2e8f9f7 | 943 | { |
<> | 144:ef7eb2e8f9f7 | 944 | cycleCtrl = (uint32_t)dmaCycleCtrlMemScatterGather + 1; |
<> | 144:ef7eb2e8f9f7 | 945 | } |
<> | 144:ef7eb2e8f9f7 | 946 | |
<> | 144:ef7eb2e8f9f7 | 947 | descr->CTRL =(cfg->dstInc << _DMA_CTRL_DST_INC_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 948 | | (cfg->size << _DMA_CTRL_DST_SIZE_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 949 | | (cfg->srcInc << _DMA_CTRL_SRC_INC_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 950 | | (cfg->size << _DMA_CTRL_SRC_SIZE_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 951 | | ((uint32_t)(cfg->hprot) << _DMA_CTRL_SRC_PROT_CTRL_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 952 | | (cfg->arbRate << _DMA_CTRL_R_POWER_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 953 | | ((uint32_t)(cfg->nMinus1) << _DMA_CTRL_N_MINUS_1_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 954 | /* Never set next useburst bit, since the descriptor used after the */ |
<> | 144:ef7eb2e8f9f7 | 955 | /* alternate descriptor is the primary descriptor which operates on */ |
<> | 144:ef7eb2e8f9f7 | 956 | /* memory. If the alternate descriptors need to have useBurst set, this */ |
<> | 144:ef7eb2e8f9f7 | 957 | /* done when setting up the primary descriptor, ie when activating. */ |
<> | 144:ef7eb2e8f9f7 | 958 | | (0 << _DMA_CTRL_NEXT_USEBURST_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 959 | | (cycleCtrl << _DMA_CTRL_CYCLE_CTRL_SHIFT); |
<> | 144:ef7eb2e8f9f7 | 960 | } |
<> | 144:ef7eb2e8f9f7 | 961 | |
<> | 144:ef7eb2e8f9f7 | 962 | |
<> | 144:ef7eb2e8f9f7 | 963 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 964 | * @brief |
<> | 144:ef7eb2e8f9f7 | 965 | * Enable or disable a DMA channel. |
<> | 144:ef7eb2e8f9f7 | 966 | * |
<> | 144:ef7eb2e8f9f7 | 967 | * @details |
<> | 144:ef7eb2e8f9f7 | 968 | * Use this function to explicitly enable or disable a DMA channel. A DMA |
<> | 144:ef7eb2e8f9f7 | 969 | * channel is automatically disabled when the DMA controller has finished a |
<> | 144:ef7eb2e8f9f7 | 970 | * transaction. |
<> | 144:ef7eb2e8f9f7 | 971 | * |
<> | 144:ef7eb2e8f9f7 | 972 | * @param[in] channel |
<> | 144:ef7eb2e8f9f7 | 973 | * DMA channel to enable or disable. |
<> | 144:ef7eb2e8f9f7 | 974 | * |
<> | 144:ef7eb2e8f9f7 | 975 | * @param[in] enable |
<> | 144:ef7eb2e8f9f7 | 976 | * If 'true' the channel will be enabled. If 'false' the channel will be |
<> | 144:ef7eb2e8f9f7 | 977 | * disabled. |
<> | 144:ef7eb2e8f9f7 | 978 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 979 | void DMA_ChannelEnable(unsigned int channel, bool enable) |
<> | 144:ef7eb2e8f9f7 | 980 | { |
<> | 144:ef7eb2e8f9f7 | 981 | EFM_ASSERT(channel < DMA_CHAN_COUNT); |
<> | 144:ef7eb2e8f9f7 | 982 | |
<> | 144:ef7eb2e8f9f7 | 983 | if (enable) |
<> | 144:ef7eb2e8f9f7 | 984 | { |
<> | 144:ef7eb2e8f9f7 | 985 | DMA->CHENS = 1<<channel; |
<> | 144:ef7eb2e8f9f7 | 986 | } |
<> | 144:ef7eb2e8f9f7 | 987 | else |
<> | 144:ef7eb2e8f9f7 | 988 | { |
<> | 144:ef7eb2e8f9f7 | 989 | DMA->CHENC = 1<<channel; |
<> | 144:ef7eb2e8f9f7 | 990 | } |
<> | 144:ef7eb2e8f9f7 | 991 | } |
<> | 144:ef7eb2e8f9f7 | 992 | |
<> | 144:ef7eb2e8f9f7 | 993 | |
<> | 144:ef7eb2e8f9f7 | 994 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 995 | * @brief |
<> | 144:ef7eb2e8f9f7 | 996 | * Check if DMA channel is enabled. |
<> | 144:ef7eb2e8f9f7 | 997 | * |
<> | 144:ef7eb2e8f9f7 | 998 | * @details |
<> | 144:ef7eb2e8f9f7 | 999 | * The DMA channel is disabled when the DMA controller has finished a DMA |
<> | 144:ef7eb2e8f9f7 | 1000 | * cycle. |
<> | 144:ef7eb2e8f9f7 | 1001 | * |
<> | 144:ef7eb2e8f9f7 | 1002 | * @param[in] channel |
<> | 144:ef7eb2e8f9f7 | 1003 | * DMA channel to check. |
<> | 144:ef7eb2e8f9f7 | 1004 | * |
<> | 144:ef7eb2e8f9f7 | 1005 | * @return |
<> | 144:ef7eb2e8f9f7 | 1006 | * true if channel is enabled, false if not. |
<> | 144:ef7eb2e8f9f7 | 1007 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 1008 | bool DMA_ChannelEnabled(unsigned int channel) |
<> | 144:ef7eb2e8f9f7 | 1009 | { |
<> | 144:ef7eb2e8f9f7 | 1010 | EFM_ASSERT(channel < DMA_CHAN_COUNT); |
<> | 144:ef7eb2e8f9f7 | 1011 | |
<> | 144:ef7eb2e8f9f7 | 1012 | return (bool)((DMA->CHENS >> channel) & 1); |
<> | 144:ef7eb2e8f9f7 | 1013 | } |
<> | 144:ef7eb2e8f9f7 | 1014 | |
<> | 144:ef7eb2e8f9f7 | 1015 | |
<> | 144:ef7eb2e8f9f7 | 1016 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 1017 | * @brief |
<> | 144:ef7eb2e8f9f7 | 1018 | * Initializes DMA controller. |
<> | 144:ef7eb2e8f9f7 | 1019 | * |
<> | 144:ef7eb2e8f9f7 | 1020 | * @details |
<> | 144:ef7eb2e8f9f7 | 1021 | * This function will reset and prepare the DMA controller for use. Although |
<> | 144:ef7eb2e8f9f7 | 1022 | * it may be used several times, it is normally only used during system |
<> | 144:ef7eb2e8f9f7 | 1023 | * init. If reused during normal operation, notice that any ongoing DMA |
<> | 144:ef7eb2e8f9f7 | 1024 | * transfers will be aborted. When completed, the DMA controller is in |
<> | 144:ef7eb2e8f9f7 | 1025 | * an enabled state. |
<> | 144:ef7eb2e8f9f7 | 1026 | * |
<> | 144:ef7eb2e8f9f7 | 1027 | * @note |
<> | 144:ef7eb2e8f9f7 | 1028 | * Must be invoked before using the DMA controller. |
<> | 144:ef7eb2e8f9f7 | 1029 | * |
<> | 144:ef7eb2e8f9f7 | 1030 | * @param[in] init |
<> | 144:ef7eb2e8f9f7 | 1031 | * Pointer to a structure containing DMA init information. |
<> | 144:ef7eb2e8f9f7 | 1032 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 1033 | void DMA_Init(DMA_Init_TypeDef *init) |
<> | 144:ef7eb2e8f9f7 | 1034 | { |
<> | 144:ef7eb2e8f9f7 | 1035 | EFM_ASSERT(init); |
<> | 144:ef7eb2e8f9f7 | 1036 | |
<> | 144:ef7eb2e8f9f7 | 1037 | /* Make sure control block is properly aligned */ |
<> | 144:ef7eb2e8f9f7 | 1038 | #if (DMA_CHAN_COUNT <= 4) |
<> | 144:ef7eb2e8f9f7 | 1039 | EFM_ASSERT(!((uint32_t)(init->controlBlock) & (128 - 1))); |
<> | 144:ef7eb2e8f9f7 | 1040 | #elif (DMA_CHAN_COUNT <= 8) || (DMA_CHAN_COUNT <= 12) |
<> | 144:ef7eb2e8f9f7 | 1041 | EFM_ASSERT(!((uint32_t)(init->controlBlock) & (256 - 1))); |
<> | 144:ef7eb2e8f9f7 | 1042 | #else |
<> | 144:ef7eb2e8f9f7 | 1043 | #error "Unsupported DMA channel count (em_dma.c)." |
<> | 144:ef7eb2e8f9f7 | 1044 | #endif |
<> | 144:ef7eb2e8f9f7 | 1045 | |
<> | 144:ef7eb2e8f9f7 | 1046 | /* Make sure DMA clock is enabled prior to accessing DMA module */ |
<> | 144:ef7eb2e8f9f7 | 1047 | CMU_ClockEnable(cmuClock_DMA, true); |
<> | 144:ef7eb2e8f9f7 | 1048 | |
<> | 144:ef7eb2e8f9f7 | 1049 | /* Make sure DMA controller is set to a known reset state */ |
<> | 144:ef7eb2e8f9f7 | 1050 | DMA_Reset(); |
<> | 144:ef7eb2e8f9f7 | 1051 | |
<> | 144:ef7eb2e8f9f7 | 1052 | /* Clear/enable DMA interrupts */ |
<> | 144:ef7eb2e8f9f7 | 1053 | NVIC_ClearPendingIRQ(DMA_IRQn); |
<> | 144:ef7eb2e8f9f7 | 1054 | NVIC_EnableIRQ(DMA_IRQn); |
<> | 144:ef7eb2e8f9f7 | 1055 | |
<> | 144:ef7eb2e8f9f7 | 1056 | /* Enable bus error interrupt */ |
<> | 144:ef7eb2e8f9f7 | 1057 | DMA->IEN = DMA_IEN_ERR; |
<> | 144:ef7eb2e8f9f7 | 1058 | |
<> | 144:ef7eb2e8f9f7 | 1059 | /* Set pointer to control block, notice that this ptr must have been */ |
<> | 144:ef7eb2e8f9f7 | 1060 | /* properly aligned, according to requirements defined in the reference */ |
<> | 144:ef7eb2e8f9f7 | 1061 | /* manual. */ |
<> | 144:ef7eb2e8f9f7 | 1062 | DMA->CTRLBASE = (uint32_t)(init->controlBlock); |
<> | 144:ef7eb2e8f9f7 | 1063 | |
<> | 144:ef7eb2e8f9f7 | 1064 | /* Configure and enable the DMA controller */ |
<> | 144:ef7eb2e8f9f7 | 1065 | DMA->CONFIG = ((uint32_t)(init->hprot) << _DMA_CONFIG_CHPROT_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 1066 | | DMA_CONFIG_EN; |
<> | 144:ef7eb2e8f9f7 | 1067 | } |
<> | 144:ef7eb2e8f9f7 | 1068 | |
<> | 144:ef7eb2e8f9f7 | 1069 | |
<> | 144:ef7eb2e8f9f7 | 1070 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 1071 | * @brief |
<> | 144:ef7eb2e8f9f7 | 1072 | * Refresh a descriptor used in a DMA ping-pong cycle. |
<> | 144:ef7eb2e8f9f7 | 1073 | * |
<> | 144:ef7eb2e8f9f7 | 1074 | * @details |
<> | 144:ef7eb2e8f9f7 | 1075 | * During a ping-pong DMA cycle, the DMA controller automatically alternates |
<> | 144:ef7eb2e8f9f7 | 1076 | * between primary and alternate descriptors, when completing use of a |
<> | 144:ef7eb2e8f9f7 | 1077 | * descriptor. While the other descriptor is in use by the DMA controller, |
<> | 144:ef7eb2e8f9f7 | 1078 | * the SW should refresh the completed descriptor. This is typically done from |
<> | 144:ef7eb2e8f9f7 | 1079 | * the callback defined for the ping-pong cycle. |
<> | 144:ef7eb2e8f9f7 | 1080 | * |
<> | 144:ef7eb2e8f9f7 | 1081 | * @param[in] channel |
<> | 144:ef7eb2e8f9f7 | 1082 | * DMA channel to refresh ping-pong descriptor for. |
<> | 144:ef7eb2e8f9f7 | 1083 | * |
<> | 144:ef7eb2e8f9f7 | 1084 | * @param[in] primary |
<> | 144:ef7eb2e8f9f7 | 1085 | * @li true - refresh primary descriptor |
<> | 144:ef7eb2e8f9f7 | 1086 | * @li false - refresh alternate descriptor |
<> | 144:ef7eb2e8f9f7 | 1087 | * |
<> | 144:ef7eb2e8f9f7 | 1088 | * @param[in] useBurst |
<> | 144:ef7eb2e8f9f7 | 1089 | * The burst feature is only used on peripherals supporting DMA bursts. |
<> | 144:ef7eb2e8f9f7 | 1090 | * Bursts must not be used if the total length (as given by nMinus1) is |
<> | 144:ef7eb2e8f9f7 | 1091 | * less than the arbitration rate configured for the descriptor. Please |
<> | 144:ef7eb2e8f9f7 | 1092 | * refer to the reference manual for further details on burst usage. |
<> | 144:ef7eb2e8f9f7 | 1093 | * |
<> | 144:ef7eb2e8f9f7 | 1094 | * @param[in] dst |
<> | 144:ef7eb2e8f9f7 | 1095 | * Address to start location to transfer data to. If NULL, leave setting in |
<> | 144:ef7eb2e8f9f7 | 1096 | * descriptor as is. |
<> | 144:ef7eb2e8f9f7 | 1097 | * |
<> | 144:ef7eb2e8f9f7 | 1098 | * @param[in] src |
<> | 144:ef7eb2e8f9f7 | 1099 | * Address to start location to transfer data from. If NULL, leave setting in |
<> | 144:ef7eb2e8f9f7 | 1100 | * descriptor as is. |
<> | 144:ef7eb2e8f9f7 | 1101 | * |
<> | 144:ef7eb2e8f9f7 | 1102 | * @param[in] nMinus1 |
<> | 144:ef7eb2e8f9f7 | 1103 | * Number of DMA transfer elements (minus 1) to transfer (<= 1023). The |
<> | 144:ef7eb2e8f9f7 | 1104 | * size of the DMA transfer element (1, 2 or 4 bytes) is configured with |
<> | 144:ef7eb2e8f9f7 | 1105 | * DMA_CfgDescr(). |
<> | 144:ef7eb2e8f9f7 | 1106 | * |
<> | 144:ef7eb2e8f9f7 | 1107 | * @param[in] stop |
<> | 144:ef7eb2e8f9f7 | 1108 | * Indicate that the DMA ping-pong cycle shall stop @b after completing use |
<> | 144:ef7eb2e8f9f7 | 1109 | * of this descriptor. |
<> | 144:ef7eb2e8f9f7 | 1110 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 1111 | void DMA_RefreshPingPong(unsigned int channel, |
<> | 144:ef7eb2e8f9f7 | 1112 | bool primary, |
<> | 144:ef7eb2e8f9f7 | 1113 | bool useBurst, |
<> | 144:ef7eb2e8f9f7 | 1114 | void *dst, |
<> | 144:ef7eb2e8f9f7 | 1115 | void *src, |
<> | 144:ef7eb2e8f9f7 | 1116 | unsigned int nMinus1, |
<> | 144:ef7eb2e8f9f7 | 1117 | bool stop) |
<> | 144:ef7eb2e8f9f7 | 1118 | { |
<> | 144:ef7eb2e8f9f7 | 1119 | DMA_CycleCtrl_TypeDef cycleCtrl; |
<> | 144:ef7eb2e8f9f7 | 1120 | DMA_DESCRIPTOR_TypeDef *descr; |
<> | 144:ef7eb2e8f9f7 | 1121 | uint32_t inc; |
<> | 144:ef7eb2e8f9f7 | 1122 | uint32_t chBit; |
<> | 144:ef7eb2e8f9f7 | 1123 | uint32_t tmp; |
<> | 144:ef7eb2e8f9f7 | 1124 | |
<> | 144:ef7eb2e8f9f7 | 1125 | EFM_ASSERT(channel < DMA_CHAN_COUNT); |
<> | 144:ef7eb2e8f9f7 | 1126 | EFM_ASSERT(nMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT)); |
<> | 144:ef7eb2e8f9f7 | 1127 | |
<> | 144:ef7eb2e8f9f7 | 1128 | /* The ping-pong DMA cycle may be stopped by issuing a basic cycle type */ |
<> | 144:ef7eb2e8f9f7 | 1129 | if (stop) |
<> | 144:ef7eb2e8f9f7 | 1130 | { |
<> | 144:ef7eb2e8f9f7 | 1131 | cycleCtrl = dmaCycleCtrlBasic; |
<> | 144:ef7eb2e8f9f7 | 1132 | } |
<> | 144:ef7eb2e8f9f7 | 1133 | else |
<> | 144:ef7eb2e8f9f7 | 1134 | { |
<> | 144:ef7eb2e8f9f7 | 1135 | cycleCtrl = dmaCycleCtrlPingPong; |
<> | 144:ef7eb2e8f9f7 | 1136 | } |
<> | 144:ef7eb2e8f9f7 | 1137 | |
<> | 144:ef7eb2e8f9f7 | 1138 | /* Find descriptor to configure */ |
<> | 144:ef7eb2e8f9f7 | 1139 | if (primary) |
<> | 144:ef7eb2e8f9f7 | 1140 | { |
<> | 144:ef7eb2e8f9f7 | 1141 | descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE)) + channel; |
<> | 144:ef7eb2e8f9f7 | 1142 | } |
<> | 144:ef7eb2e8f9f7 | 1143 | else |
<> | 144:ef7eb2e8f9f7 | 1144 | { |
<> | 144:ef7eb2e8f9f7 | 1145 | descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE)) + channel; |
<> | 144:ef7eb2e8f9f7 | 1146 | } |
<> | 144:ef7eb2e8f9f7 | 1147 | |
<> | 144:ef7eb2e8f9f7 | 1148 | if (src) |
<> | 144:ef7eb2e8f9f7 | 1149 | { |
<> | 144:ef7eb2e8f9f7 | 1150 | inc = (descr->CTRL & _DMA_CTRL_SRC_INC_MASK) >> _DMA_CTRL_SRC_INC_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 1151 | if (inc == _DMA_CTRL_SRC_INC_NONE) |
<> | 144:ef7eb2e8f9f7 | 1152 | { |
<> | 144:ef7eb2e8f9f7 | 1153 | descr->SRCEND = src; |
<> | 144:ef7eb2e8f9f7 | 1154 | } |
<> | 144:ef7eb2e8f9f7 | 1155 | else |
<> | 144:ef7eb2e8f9f7 | 1156 | { |
<> | 144:ef7eb2e8f9f7 | 1157 | descr->SRCEND = (void *)((uint32_t)src + (nMinus1 << inc)); |
<> | 144:ef7eb2e8f9f7 | 1158 | } |
<> | 144:ef7eb2e8f9f7 | 1159 | } |
<> | 144:ef7eb2e8f9f7 | 1160 | |
<> | 144:ef7eb2e8f9f7 | 1161 | if (dst) |
<> | 144:ef7eb2e8f9f7 | 1162 | { |
<> | 144:ef7eb2e8f9f7 | 1163 | inc = (descr->CTRL & _DMA_CTRL_DST_INC_MASK) >> _DMA_CTRL_DST_INC_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 1164 | if (inc == _DMA_CTRL_DST_INC_NONE) |
<> | 144:ef7eb2e8f9f7 | 1165 | { |
<> | 144:ef7eb2e8f9f7 | 1166 | descr->DSTEND = dst; |
<> | 144:ef7eb2e8f9f7 | 1167 | } |
<> | 144:ef7eb2e8f9f7 | 1168 | else |
<> | 144:ef7eb2e8f9f7 | 1169 | { |
<> | 144:ef7eb2e8f9f7 | 1170 | descr->DSTEND = (void *)((uint32_t)dst + (nMinus1 << inc)); |
<> | 144:ef7eb2e8f9f7 | 1171 | } |
<> | 144:ef7eb2e8f9f7 | 1172 | } |
<> | 144:ef7eb2e8f9f7 | 1173 | |
<> | 144:ef7eb2e8f9f7 | 1174 | chBit = 1 << channel; |
<> | 144:ef7eb2e8f9f7 | 1175 | if (useBurst) |
<> | 144:ef7eb2e8f9f7 | 1176 | { |
<> | 144:ef7eb2e8f9f7 | 1177 | DMA->CHUSEBURSTS = chBit; |
<> | 144:ef7eb2e8f9f7 | 1178 | } |
<> | 144:ef7eb2e8f9f7 | 1179 | else |
<> | 144:ef7eb2e8f9f7 | 1180 | { |
<> | 144:ef7eb2e8f9f7 | 1181 | DMA->CHUSEBURSTC = chBit; |
<> | 144:ef7eb2e8f9f7 | 1182 | } |
<> | 144:ef7eb2e8f9f7 | 1183 | |
<> | 144:ef7eb2e8f9f7 | 1184 | /* Set cycle control */ |
<> | 144:ef7eb2e8f9f7 | 1185 | tmp = descr->CTRL & ~(_DMA_CTRL_CYCLE_CTRL_MASK | _DMA_CTRL_N_MINUS_1_MASK); |
<> | 144:ef7eb2e8f9f7 | 1186 | tmp |= nMinus1 << _DMA_CTRL_N_MINUS_1_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 1187 | tmp |= cycleCtrl << _DMA_CTRL_CYCLE_CTRL_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 1188 | descr->CTRL = tmp; |
<> | 144:ef7eb2e8f9f7 | 1189 | } |
<> | 144:ef7eb2e8f9f7 | 1190 | |
<> | 144:ef7eb2e8f9f7 | 1191 | |
<> | 144:ef7eb2e8f9f7 | 1192 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 1193 | * @brief |
<> | 144:ef7eb2e8f9f7 | 1194 | * Reset the DMA controller. |
<> | 144:ef7eb2e8f9f7 | 1195 | * |
<> | 144:ef7eb2e8f9f7 | 1196 | * @details |
<> | 144:ef7eb2e8f9f7 | 1197 | * This functions will disable the DMA controller and set it to a reset |
<> | 144:ef7eb2e8f9f7 | 1198 | * state. |
<> | 144:ef7eb2e8f9f7 | 1199 | * |
<> | 144:ef7eb2e8f9f7 | 1200 | * @note |
<> | 144:ef7eb2e8f9f7 | 1201 | * Notice that any ongoing transfers will be aborted. |
<> | 144:ef7eb2e8f9f7 | 1202 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 1203 | void DMA_Reset(void) |
<> | 144:ef7eb2e8f9f7 | 1204 | { |
<> | 144:ef7eb2e8f9f7 | 1205 | int i; |
<> | 144:ef7eb2e8f9f7 | 1206 | |
<> | 144:ef7eb2e8f9f7 | 1207 | /* Disable DMA interrupts */ |
<> | 144:ef7eb2e8f9f7 | 1208 | NVIC_DisableIRQ(DMA_IRQn); |
<> | 144:ef7eb2e8f9f7 | 1209 | |
<> | 144:ef7eb2e8f9f7 | 1210 | /* Put the DMA controller into a known state, first disabling it. */ |
<> | 144:ef7eb2e8f9f7 | 1211 | DMA->CONFIG = _DMA_CONFIG_RESETVALUE; |
<> | 144:ef7eb2e8f9f7 | 1212 | DMA->CHUSEBURSTC = _DMA_CHUSEBURSTC_MASK; |
<> | 144:ef7eb2e8f9f7 | 1213 | DMA->CHREQMASKC = _DMA_CHREQMASKC_MASK; |
<> | 144:ef7eb2e8f9f7 | 1214 | DMA->CHENC = _DMA_CHENC_MASK; |
<> | 144:ef7eb2e8f9f7 | 1215 | DMA->CHALTC = _DMA_CHALTC_MASK; |
<> | 144:ef7eb2e8f9f7 | 1216 | DMA->CHPRIC = _DMA_CHPRIC_MASK; |
<> | 144:ef7eb2e8f9f7 | 1217 | DMA->ERRORC = DMA_ERRORC_ERRORC; |
<> | 144:ef7eb2e8f9f7 | 1218 | DMA->IEN = _DMA_IEN_RESETVALUE; |
<> | 144:ef7eb2e8f9f7 | 1219 | DMA->IFC = _DMA_IFC_MASK; |
<> | 144:ef7eb2e8f9f7 | 1220 | |
<> | 144:ef7eb2e8f9f7 | 1221 | /* Clear channel control flags */ |
<> | 144:ef7eb2e8f9f7 | 1222 | for (i = 0; i < DMA_CHAN_COUNT; i++) |
<> | 144:ef7eb2e8f9f7 | 1223 | { |
<> | 144:ef7eb2e8f9f7 | 1224 | DMA->CH[i].CTRL = _DMA_CH_CTRL_RESETVALUE; |
<> | 144:ef7eb2e8f9f7 | 1225 | } |
<> | 144:ef7eb2e8f9f7 | 1226 | } |
<> | 144:ef7eb2e8f9f7 | 1227 | |
<> | 144:ef7eb2e8f9f7 | 1228 | |
<> | 144:ef7eb2e8f9f7 | 1229 | /** @} (end addtogroup DMA) */ |
<> | 144:ef7eb2e8f9f7 | 1230 | /** @} (end addtogroup EM_Library) */ |
<> | 144:ef7eb2e8f9f7 | 1231 | #endif /* defined( DMA_PRESENT ) */ |