]> git.sur5r.net Git - freertos/blob
c55f134c5c2ac60ec0594cc6c90c57cd5b77b466
[freertos] /
1 /***************************************************************************//**\r
2  * @file em_dma.h\r
3  * @brief Direct memory access (DMA) API\r
4  * @version 4.0.0\r
5  *******************************************************************************\r
6  * @section License\r
7  * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>\r
8  *******************************************************************************\r
9  *\r
10  * Permission is granted to anyone to use this software for any purpose,\r
11  * including commercial applications, and to alter it and redistribute it\r
12  * freely, subject to the following restrictions:\r
13  *\r
14  * 1. The origin of this software must not be misrepresented; you must not\r
15  *    claim that you wrote the original software.\r
16  * 2. Altered source versions must be plainly marked as such, and must not be\r
17  *    misrepresented as being the original software.\r
18  * 3. This notice may not be removed or altered from any source distribution.\r
19  *\r
20  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no\r
21  * obligation to support this Software. Silicon Labs is providing the\r
22  * Software "AS IS", with no express or implied warranties of any kind,\r
23  * including, but not limited to, any implied warranties of merchantability\r
24  * or fitness for any particular purpose or warranties against infringement\r
25  * of any proprietary rights of a third party.\r
26  *\r
27  * Silicon Labs will not be liable for any consequential, incidental, or\r
28  * special damages, or any other relief, or for any claim by any third party,\r
29  * arising from your use of this Software.\r
30  *\r
31  ******************************************************************************/\r
32 \r
33 \r
34 \r
35 #ifndef __SILICON_LABS_EM_DMA_H_\r
36 #define __SILICON_LABS_EM_DMA_H_\r
37 \r
38 #include "em_device.h"\r
39 #if defined( DMA_PRESENT )\r
40 \r
41 #include <stdio.h>\r
42 #include <stdbool.h>\r
43 \r
44 #ifdef __cplusplus\r
45 extern "C" {\r
46 #endif\r
47 \r
48 /***************************************************************************//**\r
49  * @addtogroup EM_Library\r
50  * @{\r
51  ******************************************************************************/\r
52 \r
53 /***************************************************************************//**\r
54  * @addtogroup DMA\r
55  * @{\r
56  ******************************************************************************/\r
57 \r
58 /*******************************************************************************\r
59  ********************************   ENUMS   ************************************\r
60  ******************************************************************************/\r
61 \r
62 /**\r
63  * Amount source/destination address should be incremented for each data\r
64  * transfer.\r
65  */\r
66 typedef enum\r
67 {\r
68   dmaDataInc1    = _DMA_CTRL_SRC_INC_BYTE,     /**< Increment address 1 byte. */\r
69   dmaDataInc2    = _DMA_CTRL_SRC_INC_HALFWORD, /**< Increment address 2 bytes. */\r
70   dmaDataInc4    = _DMA_CTRL_SRC_INC_WORD,     /**< Increment address 4 bytes. */\r
71   dmaDataIncNone = _DMA_CTRL_SRC_INC_NONE      /**< Do not increment address. */\r
72 } DMA_DataInc_TypeDef;\r
73 \r
74 \r
75 /** Data sizes (in number of bytes) to be read/written by DMA transfer. */\r
76 typedef enum\r
77 {\r
78   dmaDataSize1 = _DMA_CTRL_SRC_SIZE_BYTE,     /**< 1 byte DMA transfer size. */\r
79   dmaDataSize2 = _DMA_CTRL_SRC_SIZE_HALFWORD, /**< 2 byte DMA transfer size. */\r
80   dmaDataSize4 = _DMA_CTRL_SRC_SIZE_WORD      /**< 4 byte DMA transfer size. */\r
81 } DMA_DataSize_TypeDef;\r
82 \r
83 \r
84 /** Type of DMA transfer. */\r
85 typedef enum\r
86 {\r
87   /** Basic DMA cycle. */\r
88   dmaCycleCtrlBasic            = _DMA_CTRL_CYCLE_CTRL_BASIC,\r
89   /** Auto-request DMA cycle. */\r
90   dmaCycleCtrlAuto             = _DMA_CTRL_CYCLE_CTRL_AUTO,\r
91   /** Ping-pong DMA cycle. */\r
92   dmaCycleCtrlPingPong         = _DMA_CTRL_CYCLE_CTRL_PINGPONG,\r
93   /** Memory scatter-gather DMA cycle. */\r
94   dmaCycleCtrlMemScatterGather = _DMA_CTRL_CYCLE_CTRL_MEM_SCATTER_GATHER,\r
95   /** Peripheral scatter-gather DMA cycle. */\r
96   dmaCycleCtrlPerScatterGather = _DMA_CTRL_CYCLE_CTRL_PER_SCATTER_GATHER\r
97 } DMA_CycleCtrl_TypeDef;\r
98 \r
99 \r
100 /** Number of transfers before controller does new arbitration. */\r
101 typedef enum\r
102 {\r
103   dmaArbitrate1    = _DMA_CTRL_R_POWER_1,    /**< Arbitrate after 1 DMA transfer. */\r
104   dmaArbitrate2    = _DMA_CTRL_R_POWER_2,    /**< Arbitrate after 2 DMA transfers. */\r
105   dmaArbitrate4    = _DMA_CTRL_R_POWER_4,    /**< Arbitrate after 4 DMA transfers. */\r
106   dmaArbitrate8    = _DMA_CTRL_R_POWER_8,    /**< Arbitrate after 8 DMA transfers. */\r
107   dmaArbitrate16   = _DMA_CTRL_R_POWER_16,   /**< Arbitrate after 16 DMA transfers. */\r
108   dmaArbitrate32   = _DMA_CTRL_R_POWER_32,   /**< Arbitrate after 32 DMA transfers. */\r
109   dmaArbitrate64   = _DMA_CTRL_R_POWER_64,   /**< Arbitrate after 64 DMA transfers. */\r
110   dmaArbitrate128  = _DMA_CTRL_R_POWER_128,  /**< Arbitrate after 128 DMA transfers. */\r
111   dmaArbitrate256  = _DMA_CTRL_R_POWER_256,  /**< Arbitrate after 256 DMA transfers. */\r
112   dmaArbitrate512  = _DMA_CTRL_R_POWER_512,  /**< Arbitrate after 512 DMA transfers. */\r
113   dmaArbitrate1024 = _DMA_CTRL_R_POWER_1024  /**< Arbitrate after 1024 DMA transfers. */\r
114 } DMA_ArbiterConfig_TypeDef;\r
115 \r
116 \r
117 /*******************************************************************************\r
118  *******************************   STRUCTS   ***********************************\r
119  ******************************************************************************/\r
120 \r
121 /**\r
122  * @brief\r
123  *   DMA interrupt callback function pointer.\r
124  * @details\r
125  *   Parameters:\r
126  *   @li channel - The DMA channel the callback function is invoked for.\r
127  *   @li primary - Indicates if callback is invoked for completion of primary\r
128  *     (true) or alternate (false) descriptor. This is mainly useful for\r
129  *     ping-pong DMA cycles, in order to know which descriptor to refresh.\r
130  *   @li user - User definable reference that may be used to pass information\r
131  *     to be used by the callback handler. If used, the referenced data must be\r
132  *     valid at the point when the interrupt handler invokes the callback.\r
133  *     If callback changes  any data in the provided user structure, remember\r
134  *     that those changes are done in interrupt context, and proper protection\r
135  *     of data may be required.\r
136  */\r
137 typedef void (*DMA_FuncPtr_TypeDef)(unsigned int channel, bool primary, void *user);\r
138 \r
139 \r
140 /**\r
141  * @brief\r
142  *   Callback structure that can be used to define DMA complete actions.\r
143  * @details\r
144  *   A reference to this structure is only stored in the primary descriptor\r
145  *   for a channel (if callback feature is used). If callback is required\r
146  *   for both primary and alternate descriptor completion, this must be\r
147  *   handled by one common callback, using the provided 'primary' parameter\r
148  *   with the callback function.\r
149  */\r
150 typedef struct\r
151 {\r
152   /**\r
153    * Pointer to callback function to invoke when DMA transfer cycle done.\r
154    * Notice that this function is invoked in interrupt context, and therefore\r
155    * should be short and non-blocking.\r
156    */\r
157   DMA_FuncPtr_TypeDef cbFunc;\r
158 \r
159   /** User defined pointer to provide with callback function. */\r
160   void                *userPtr;\r
161 \r
162   /**\r
163    * For internal use only: Indicates if next callback applies to primary\r
164    * or alternate descriptor completion. Mainly useful for ping-pong DMA\r
165    * cycles. Set this value to 0 prior to configuring callback handling.\r
166    */\r
167   uint8_t             primary;\r
168 } DMA_CB_TypeDef;\r
169 \r
170 \r
171 /** Configuration structure for a channel. */\r
172 typedef struct\r
173 {\r
174   /**\r
175    * Select if channel priority is in the high or default priority group\r
176    * with respect to arbitration. Within a priority group, lower numbered\r
177    * channels have higher priority than higher numbered channels.\r
178    */\r
179   bool     highPri;\r
180 \r
181   /**\r
182    * Select if interrupt shall be enabled for channel (triggering interrupt\r
183    * handler when dma_done signal is asserted). It should normally be\r
184    * enabled if using the callback feature for a channel, and disabled if\r
185    * not using the callback feature.\r
186    */\r
187   bool     enableInt;\r
188 \r
189   /**\r
190    * Channel control specifying the source of DMA signals. If accessing\r
191    * peripherals, use one of the DMAREQ_nnn defines available for the\r
192    * peripheral. Set it to 0 for memory-to-memory DMA cycles.\r
193    */\r
194   uint32_t select;\r
195 \r
196   /**\r
197    * @brief\r
198    *   User definable callback handling configuration.\r
199    * @details\r
200    *   Please refer to structure definition for details. The callback\r
201    *   is invoked when the specified DMA cycle is complete (when dma_done\r
202    *   signal asserted). The callback is invoked in interrupt context,\r
203    *   and should be efficient and non-blocking. Set to NULL to not\r
204    *   use the callback feature.\r
205    * @note\r
206    *   The referenced structure is used by the interrupt handler, and must\r
207    *   be available until no longer used. Thus, in most cases it should\r
208    *   not be located on the stack.\r
209    */\r
210   DMA_CB_TypeDef *cb;\r
211 } DMA_CfgChannel_TypeDef;\r
212 \r
213 \r
214 /**\r
215  * Configuration structure for primary or alternate descriptor\r
216  * (not used for scatter-gather DMA cycles).\r
217  */\r
218 typedef struct\r
219 {\r
220   /** Destination increment size for each DMA transfer */\r
221   DMA_DataInc_TypeDef       dstInc;\r
222 \r
223   /** Source increment size for each DMA transfer */\r
224   DMA_DataInc_TypeDef       srcInc;\r
225 \r
226   /** DMA transfer unit size. */\r
227   DMA_DataSize_TypeDef      size;\r
228 \r
229   /**\r
230    * Arbitration rate, ie number of DMA transfers done before rearbitration\r
231    * takes place.\r
232    */\r
233   DMA_ArbiterConfig_TypeDef arbRate;\r
234 \r
235   /**\r
236    * HPROT signal state, please refer to reference manual, DMA chapter for\r
237    * further details. Normally set to 0 if protection is not an issue.\r
238    * The following bits are available:\r
239    * @li bit 0 - HPROT[1] control for source read accesses,\r
240    *   privileged/non-privileged access\r
241    * @li bit 3 - HPROT[1] control for destination write accesses,\r
242    *   privileged/non-privileged access\r
243    */\r
244   uint8_t hprot;\r
245 } DMA_CfgDescr_TypeDef;\r
246 \r
247 \r
248 #if defined( _DMA_LOOP0_MASK ) && defined( _DMA_LOOP1_MASK )\r
249 /**\r
250  * Configuration structure for loop mode\r
251  */\r
252 typedef struct\r
253 {\r
254   /** Enable repeated loop */\r
255   bool      enable;\r
256   /** Width of transfer, reload value for nMinus1 */\r
257   uint16_t  nMinus1;\r
258 } DMA_CfgLoop_TypeDef;\r
259 #endif\r
260 \r
261 \r
262 #if defined( _DMA_RECT0_MASK )\r
263 /**\r
264  * Configuration structure for rectangular copy\r
265  */\r
266 typedef struct\r
267 {\r
268   /** DMA channel destination stride (width of destination image, distance between lines) */\r
269   uint16_t dstStride;\r
270   /** DMA channel source stride (width of source image, distance between lines) */\r
271   uint16_t srcStride;\r
272   /** 2D copy height */\r
273   uint16_t height;\r
274 } DMA_CfgRect_TypeDef;\r
275 #endif\r
276 \r
277 \r
278 /** Configuration structure for alternate scatter-gather descriptor. */\r
279 typedef struct\r
280 {\r
281   /** Pointer to location to transfer data from. */\r
282   void                      *src;\r
283 \r
284   /** Pointer to location to transfer data to. */\r
285   void                      *dst;\r
286 \r
287   /** Destination increment size for each DMA transfer */\r
288   DMA_DataInc_TypeDef       dstInc;\r
289 \r
290   /** Source increment size for each DMA transfer */\r
291   DMA_DataInc_TypeDef       srcInc;\r
292 \r
293   /** DMA transfer unit size. */\r
294   DMA_DataSize_TypeDef      size;\r
295 \r
296   /**\r
297    * Arbitration rate, ie number of DMA transfers done before rearbitration\r
298    * takes place.\r
299    */\r
300   DMA_ArbiterConfig_TypeDef arbRate;\r
301 \r
302   /** Number of DMA transfers minus 1 to do. Must be <= 1023. */\r
303   uint16_t                  nMinus1;\r
304 \r
305   /**\r
306    * HPROT signal state, please refer to reference manual, DMA chapter for\r
307    * further details. Normally set to 0 if protection is not an issue.\r
308    * The following bits are available:\r
309    * @li bit 0 - HPROT[1] control for source read accesses,\r
310    *   privileged/non-privileged access\r
311    * @li bit 3 - HPROT[1] control for destination write accesses,\r
312    *   privileged/non-privileged access\r
313    */\r
314   uint8_t hprot;\r
315 \r
316   /** Specify if a memory or peripheral scatter-gather DMA cycle. Notice\r
317    *  that this parameter should be the same for all alternate\r
318    *  descriptors.\r
319    *  @li true - this is a peripheral scatter-gather cycle\r
320    *  @li false - this is a memory scatter-gather cycle\r
321    */\r
322   bool    peripheral;\r
323 } DMA_CfgDescrSGAlt_TypeDef;\r
324 \r
325 \r
326 /** DMA init structure */\r
327 typedef struct\r
328 {\r
329   /**\r
330    * HPROT signal state when accessing the primary/alternate\r
331    * descriptors. Normally set to 0 if protection is not an issue.\r
332    * The following bits are available:\r
333    * @li bit 0 - HPROT[1] control for descriptor accesses (ie when\r
334    *   the DMA controller accesses the channel control block itself),\r
335    *   privileged/non-privileged access\r
336    */\r
337   uint8_t hprot;\r
338 \r
339   /**\r
340    * Pointer to the controlblock in memory holding descriptors (channel\r
341    * control data structures). This memory must be properly aligned\r
342    * at a 256 bytes. I.e. the 8 least significant bits must be zero.\r
343    *\r
344    * Please refer to the reference manual, DMA chapter for more details.\r
345    *\r
346    * It is possible to provide a smaller memory block, only covering\r
347    * those channels actually used, if not all available channels are used.\r
348    * Ie, if only using 4 channels (0-3), both primary and alternate\r
349    * structures, then only 16*2*4 = 128 bytes must be provided. This\r
350    * implementation has however no check if later exceeding such a limit\r
351    * by configuring for instance channel 4, in which case memory overwrite\r
352    * of some other data will occur.\r
353    */\r
354   DMA_DESCRIPTOR_TypeDef *controlBlock;\r
355 } DMA_Init_TypeDef;\r
356 \r
357 \r
358 /*******************************************************************************\r
359  *****************************   PROTOTYPES   **********************************\r
360  ******************************************************************************/\r
361 \r
362 void DMA_ActivateAuto(unsigned int channel,\r
363                       bool primary,\r
364                       void *dst,\r
365                       void *src,\r
366                       unsigned int nMinus1);\r
367 void DMA_ActivateBasic(unsigned int channel,\r
368                        bool primary,\r
369                        bool useBurst,\r
370                        void *dst,\r
371                        void *src,\r
372                        unsigned int nMinus1);\r
373 void DMA_ActivatePingPong(unsigned int channel,\r
374                           bool useBurst,\r
375                           void *primDst,\r
376                           void *primSrc,\r
377                           unsigned int primNMinus1,\r
378                           void *altDst,\r
379                           void *altSrc,\r
380                           unsigned int altNMinus1);\r
381 void DMA_ActivateScatterGather(unsigned int channel,\r
382                                bool useBurst,\r
383                                DMA_DESCRIPTOR_TypeDef *altDescr,\r
384                                unsigned int count);\r
385 void DMA_CfgChannel(unsigned int channel, DMA_CfgChannel_TypeDef *cfg);\r
386 void DMA_CfgDescr(unsigned int channel,\r
387                   bool primary,\r
388                   DMA_CfgDescr_TypeDef *cfg);\r
389 #if defined( _DMA_LOOP0_MASK ) && defined( _DMA_LOOP1_MASK )\r
390 void DMA_CfgLoop(unsigned int channel, DMA_CfgLoop_TypeDef *cfg);\r
391 #endif\r
392 \r
393 #if defined( _DMA_RECT0_MASK )\r
394 void DMA_CfgRect(unsigned int channel, DMA_CfgRect_TypeDef *cfg);\r
395 #endif\r
396 \r
397 #if defined( _DMA_LOOP0_MASK ) && defined( _DMA_LOOP1_MASK )\r
398 /***************************************************************************//**\r
399  * @brief\r
400  *   Clear Loop configuration for channel\r
401  *\r
402  * @param[in] channel\r
403  *   Channel to reset loop configuration for\r
404  ******************************************************************************/\r
405 __STATIC_INLINE void DMA_ResetLoop(unsigned int channel)\r
406 {\r
407   /* Clean loop copy operation */\r
408   switch(channel)\r
409   {\r
410   case 0:\r
411     DMA->LOOP0 = _DMA_LOOP0_RESETVALUE;\r
412     break;\r
413   case 1:\r
414     DMA->LOOP1 = _DMA_LOOP1_RESETVALUE;\r
415     break;\r
416   default:\r
417     break;\r
418   }\r
419 }\r
420 #endif\r
421 \r
422 \r
423 #if defined( _DMA_RECT0_MASK )\r
424 /***************************************************************************//**\r
425  * @brief\r
426  *   Clear Rect/2D DMA configuration for channel\r
427  *\r
428  * @param[in] channel\r
429  *   Channel to reset loop configuration for\r
430  ******************************************************************************/\r
431 __STATIC_INLINE void DMA_ResetRect(unsigned int channel)\r
432 {\r
433   (void) channel;\r
434 \r
435   /* Clear rect copy operation */\r
436   DMA->RECT0 = _DMA_RECT0_RESETVALUE;\r
437 }\r
438 #endif\r
439 void DMA_CfgDescrScatterGather(DMA_DESCRIPTOR_TypeDef *descr,\r
440                                unsigned int indx,\r
441                                DMA_CfgDescrSGAlt_TypeDef *cfg);\r
442 void DMA_ChannelEnable(unsigned int channel, bool enable);\r
443 bool DMA_ChannelEnabled(unsigned int channel);\r
444 void DMA_Init(DMA_Init_TypeDef *init);\r
445 void DMA_IRQHandler(void);\r
446 void DMA_RefreshPingPong(unsigned int channel,\r
447                          bool primary,\r
448                          bool useBurst,\r
449                          void *dst,\r
450                          void *src,\r
451                          unsigned int nMinus1,\r
452                          bool last);\r
453 void DMA_Reset(void);\r
454 \r
455 /** @} (end addtogroup DMA) */\r
456 /** @} (end addtogroup EM_Library) */\r
457 \r
458 #ifdef __cplusplus\r
459 }\r
460 #endif\r
461 \r
462 #endif /* defined( DMA_PRESENT ) */\r
463 #endif /* __SILICON_LABS_EM_DMA_H_ */\r