]> git.sur5r.net Git - freertos/blob
8590871cb6f58bc0151c15e8a38616370e0e55e8
[freertos] /
1 /***************************************************************************//**\r
2  * @file em_dma.h\r
3  * @brief Direct memory access (DMA) API\r
4  * @version 4.2.1\r
5  *******************************************************************************\r
6  * @section License\r
7  * <b>(C) Copyright 2015 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 #ifndef __SILICON_LABS_EM_DMA_H__\r
34 #define __SILICON_LABS_EM_DMA_H__\r
35 \r
36 #include "em_device.h"\r
37 #if defined( DMA_PRESENT )\r
38 \r
39 #include <stdio.h>\r
40 #include <stdbool.h>\r
41 \r
42 #ifdef __cplusplus\r
43 extern "C" {\r
44 #endif\r
45 \r
46 /***************************************************************************//**\r
47  * @addtogroup EM_Library\r
48  * @{\r
49  ******************************************************************************/\r
50 \r
51 /***************************************************************************//**\r
52  * @addtogroup DMA\r
53  * @{\r
54  ******************************************************************************/\r
55 \r
56 /*******************************************************************************\r
57  ********************************   ENUMS   ************************************\r
58  ******************************************************************************/\r
59 \r
60 /**\r
61  * Amount source/destination address should be incremented for each data\r
62  * transfer.\r
63  */\r
64 typedef enum\r
65 {\r
66   dmaDataInc1    = _DMA_CTRL_SRC_INC_BYTE,     /**< Increment address 1 byte. */\r
67   dmaDataInc2    = _DMA_CTRL_SRC_INC_HALFWORD, /**< Increment address 2 bytes. */\r
68   dmaDataInc4    = _DMA_CTRL_SRC_INC_WORD,     /**< Increment address 4 bytes. */\r
69   dmaDataIncNone = _DMA_CTRL_SRC_INC_NONE      /**< Do not increment address. */\r
70 } DMA_DataInc_TypeDef;\r
71 \r
72 \r
73 /** Data sizes (in number of bytes) to be read/written by DMA transfer. */\r
74 typedef enum\r
75 {\r
76   dmaDataSize1 = _DMA_CTRL_SRC_SIZE_BYTE,     /**< 1 byte DMA transfer size. */\r
77   dmaDataSize2 = _DMA_CTRL_SRC_SIZE_HALFWORD, /**< 2 byte DMA transfer size. */\r
78   dmaDataSize4 = _DMA_CTRL_SRC_SIZE_WORD      /**< 4 byte DMA transfer size. */\r
79 } DMA_DataSize_TypeDef;\r
80 \r
81 \r
82 /** Type of DMA transfer. */\r
83 typedef enum\r
84 {\r
85   /** Basic DMA cycle. */\r
86   dmaCycleCtrlBasic            = _DMA_CTRL_CYCLE_CTRL_BASIC,\r
87   /** Auto-request DMA cycle. */\r
88   dmaCycleCtrlAuto             = _DMA_CTRL_CYCLE_CTRL_AUTO,\r
89   /** Ping-pong DMA cycle. */\r
90   dmaCycleCtrlPingPong         = _DMA_CTRL_CYCLE_CTRL_PINGPONG,\r
91   /** Memory scatter-gather DMA cycle. */\r
92   dmaCycleCtrlMemScatterGather = _DMA_CTRL_CYCLE_CTRL_MEM_SCATTER_GATHER,\r
93   /** Peripheral scatter-gather DMA cycle. */\r
94   dmaCycleCtrlPerScatterGather = _DMA_CTRL_CYCLE_CTRL_PER_SCATTER_GATHER\r
95 } DMA_CycleCtrl_TypeDef;\r
96 \r
97 \r
98 /** Number of transfers before controller does new arbitration. */\r
99 typedef enum\r
100 {\r
101   dmaArbitrate1    = _DMA_CTRL_R_POWER_1,    /**< Arbitrate after 1 DMA transfer. */\r
102   dmaArbitrate2    = _DMA_CTRL_R_POWER_2,    /**< Arbitrate after 2 DMA transfers. */\r
103   dmaArbitrate4    = _DMA_CTRL_R_POWER_4,    /**< Arbitrate after 4 DMA transfers. */\r
104   dmaArbitrate8    = _DMA_CTRL_R_POWER_8,    /**< Arbitrate after 8 DMA transfers. */\r
105   dmaArbitrate16   = _DMA_CTRL_R_POWER_16,   /**< Arbitrate after 16 DMA transfers. */\r
106   dmaArbitrate32   = _DMA_CTRL_R_POWER_32,   /**< Arbitrate after 32 DMA transfers. */\r
107   dmaArbitrate64   = _DMA_CTRL_R_POWER_64,   /**< Arbitrate after 64 DMA transfers. */\r
108   dmaArbitrate128  = _DMA_CTRL_R_POWER_128,  /**< Arbitrate after 128 DMA transfers. */\r
109   dmaArbitrate256  = _DMA_CTRL_R_POWER_256,  /**< Arbitrate after 256 DMA transfers. */\r
110   dmaArbitrate512  = _DMA_CTRL_R_POWER_512,  /**< Arbitrate after 512 DMA transfers. */\r
111   dmaArbitrate1024 = _DMA_CTRL_R_POWER_1024  /**< Arbitrate after 1024 DMA transfers. */\r
112 } DMA_ArbiterConfig_TypeDef;\r
113 \r
114 \r
115 /*******************************************************************************\r
116  *******************************   STRUCTS   ***********************************\r
117  ******************************************************************************/\r
118 \r
119 /**\r
120  * @brief\r
121  *   DMA interrupt callback function pointer.\r
122  * @details\r
123  *   Parameters:\r
124  *   @li channel - The DMA channel the callback function is invoked for.\r
125  *   @li primary - Indicates if callback is invoked for completion of primary\r
126  *     (true) or alternate (false) descriptor. This is mainly useful for\r
127  *     ping-pong DMA cycles, in order to know which descriptor to refresh.\r
128  *   @li user - User definable reference that may be used to pass information\r
129  *     to be used by the callback handler. If used, the referenced data must be\r
130  *     valid at the point when the interrupt handler invokes the callback.\r
131  *     If callback changes  any data in the provided user structure, remember\r
132  *     that those changes are done in interrupt context, and proper protection\r
133  *     of data may be required.\r
134  */\r
135 typedef void (*DMA_FuncPtr_TypeDef)(unsigned int channel, bool primary, void *user);\r
136 \r
137 \r
138 /**\r
139  * @brief\r
140  *   Callback structure that can be used to define DMA complete actions.\r
141  * @details\r
142  *   A reference to this structure is only stored in the primary descriptor\r
143  *   for a channel (if callback feature is used). If callback is required\r
144  *   for both primary and alternate descriptor completion, this must be\r
145  *   handled by one common callback, using the provided 'primary' parameter\r
146  *   with the callback function.\r
147  */\r
148 typedef struct\r
149 {\r
150   /**\r
151    * Pointer to callback function to invoke when DMA transfer cycle done.\r
152    * Notice that this function is invoked in interrupt context, and therefore\r
153    * should be short and non-blocking.\r
154    */\r
155   DMA_FuncPtr_TypeDef cbFunc;\r
156 \r
157   /** User defined pointer to provide with callback function. */\r
158   void                *userPtr;\r
159 \r
160   /**\r
161    * For internal use only: Indicates if next callback applies to primary\r
162    * or alternate descriptor completion. Mainly useful for ping-pong DMA\r
163    * cycles. Set this value to 0 prior to configuring callback handling.\r
164    */\r
165   uint8_t             primary;\r
166 } DMA_CB_TypeDef;\r
167 \r
168 \r
169 /** Configuration structure for a channel. */\r
170 typedef struct\r
171 {\r
172   /**\r
173    * Select if channel priority is in the high or default priority group\r
174    * with respect to arbitration. Within a priority group, lower numbered\r
175    * channels have higher priority than higher numbered channels.\r
176    */\r
177   bool     highPri;\r
178 \r
179   /**\r
180    * Select if interrupt shall be enabled for channel (triggering interrupt\r
181    * handler when dma_done signal is asserted). It should normally be\r
182    * enabled if using the callback feature for a channel, and disabled if\r
183    * not using the callback feature.\r
184    */\r
185   bool     enableInt;\r
186 \r
187   /**\r
188    * Channel control specifying the source of DMA signals. If accessing\r
189    * peripherals, use one of the DMAREQ_nnn defines available for the\r
190    * peripheral. Set it to 0 for memory-to-memory DMA cycles.\r
191    */\r
192   uint32_t select;\r
193 \r
194   /**\r
195    * @brief\r
196    *   User definable callback handling configuration.\r
197    * @details\r
198    *   Please refer to structure definition for details. The callback\r
199    *   is invoked when the specified DMA cycle is complete (when dma_done\r
200    *   signal asserted). The callback is invoked in interrupt context,\r
201    *   and should be efficient and non-blocking. Set to NULL to not\r
202    *   use the callback feature.\r
203    * @note\r
204    *   The referenced structure is used by the interrupt handler, and must\r
205    *   be available until no longer used. Thus, in most cases it should\r
206    *   not be located on the stack.\r
207    */\r
208   DMA_CB_TypeDef *cb;\r
209 } DMA_CfgChannel_TypeDef;\r
210 \r
211 \r
212 /**\r
213  * Configuration structure for primary or alternate descriptor\r
214  * (not used for scatter-gather DMA cycles).\r
215  */\r
216 typedef struct\r
217 {\r
218   /** Destination increment size for each DMA transfer */\r
219   DMA_DataInc_TypeDef       dstInc;\r
220 \r
221   /** Source increment size for each DMA transfer */\r
222   DMA_DataInc_TypeDef       srcInc;\r
223 \r
224   /** DMA transfer unit size. */\r
225   DMA_DataSize_TypeDef      size;\r
226 \r
227   /**\r
228    * Arbitration rate, ie number of DMA transfers done before rearbitration\r
229    * takes place.\r
230    */\r
231   DMA_ArbiterConfig_TypeDef arbRate;\r
232 \r
233   /**\r
234    * HPROT signal state, please refer to reference manual, DMA chapter for\r
235    * further details. Normally set to 0 if protection is not an issue.\r
236    * The following bits are available:\r
237    * @li bit 0 - HPROT[1] control for source read accesses,\r
238    *   privileged/non-privileged access\r
239    * @li bit 3 - HPROT[1] control for destination write accesses,\r
240    *   privileged/non-privileged access\r
241    */\r
242   uint8_t hprot;\r
243 } DMA_CfgDescr_TypeDef;\r
244 \r
245 \r
246 #if defined( _DMA_LOOP0_MASK ) && defined( _DMA_LOOP1_MASK )\r
247 /**\r
248  * Configuration structure for loop mode\r
249  */\r
250 typedef struct\r
251 {\r
252   /** Enable repeated loop */\r
253   bool      enable;\r
254   /** Width of transfer, reload value for nMinus1 */\r
255   uint16_t  nMinus1;\r
256 } DMA_CfgLoop_TypeDef;\r
257 #endif\r
258 \r
259 \r
260 #if defined( _DMA_RECT0_MASK )\r
261 /**\r
262  * Configuration structure for rectangular copy\r
263  */\r
264 typedef struct\r
265 {\r
266   /** DMA channel destination stride (width of destination image, distance between lines) */\r
267   uint16_t dstStride;\r
268   /** DMA channel source stride (width of source image, distance between lines) */\r
269   uint16_t srcStride;\r
270   /** 2D copy height */\r
271   uint16_t height;\r
272 } DMA_CfgRect_TypeDef;\r
273 #endif\r
274 \r
275 \r
276 /** Configuration structure for alternate scatter-gather descriptor. */\r
277 typedef struct\r
278 {\r
279   /** Pointer to location to transfer data from. */\r
280   void                      *src;\r
281 \r
282   /** Pointer to location to transfer data to. */\r
283   void                      *dst;\r
284 \r
285   /** Destination increment size for each DMA transfer */\r
286   DMA_DataInc_TypeDef       dstInc;\r
287 \r
288   /** Source increment size for each DMA transfer */\r
289   DMA_DataInc_TypeDef       srcInc;\r
290 \r
291   /** DMA transfer unit size. */\r
292   DMA_DataSize_TypeDef      size;\r
293 \r
294   /**\r
295    * Arbitration rate, ie number of DMA transfers done before rearbitration\r
296    * takes place.\r
297    */\r
298   DMA_ArbiterConfig_TypeDef arbRate;\r
299 \r
300   /** Number of DMA transfers minus 1 to do. Must be <= 1023. */\r
301   uint16_t                  nMinus1;\r
302 \r
303   /**\r
304    * HPROT signal state, please refer to reference manual, DMA chapter for\r
305    * further details. Normally set to 0 if protection is not an issue.\r
306    * The following bits are available:\r
307    * @li bit 0 - HPROT[1] control for source read accesses,\r
308    *   privileged/non-privileged access\r
309    * @li bit 3 - HPROT[1] control for destination write accesses,\r
310    *   privileged/non-privileged access\r
311    */\r
312   uint8_t hprot;\r
313 \r
314   /** Specify if a memory or peripheral scatter-gather DMA cycle. Notice\r
315    *  that this parameter should be the same for all alternate\r
316    *  descriptors.\r
317    *  @li true - this is a peripheral scatter-gather cycle\r
318    *  @li false - this is a memory scatter-gather cycle\r
319    */\r
320   bool    peripheral;\r
321 } DMA_CfgDescrSGAlt_TypeDef;\r
322 \r
323 \r
324 /** DMA init structure */\r
325 typedef struct\r
326 {\r
327   /**\r
328    * HPROT signal state when accessing the primary/alternate\r
329    * descriptors. Normally set to 0 if protection is not an issue.\r
330    * The following bits are available:\r
331    * @li bit 0 - HPROT[1] control for descriptor accesses (ie when\r
332    *   the DMA controller accesses the channel control block itself),\r
333    *   privileged/non-privileged access\r
334    */\r
335   uint8_t hprot;\r
336 \r
337   /**\r
338    * Pointer to the controlblock in memory holding descriptors (channel\r
339    * control data structures). This memory must be properly aligned\r
340    * at a 256 bytes. I.e. the 8 least significant bits must be zero.\r
341    *\r
342    * Please refer to the reference manual, DMA chapter for more details.\r
343    *\r
344    * It is possible to provide a smaller memory block, only covering\r
345    * those channels actually used, if not all available channels are used.\r
346    * Ie, if only using 4 channels (0-3), both primary and alternate\r
347    * structures, then only 16*2*4 = 128 bytes must be provided. This\r
348    * implementation has however no check if later exceeding such a limit\r
349    * by configuring for instance channel 4, in which case memory overwrite\r
350    * of some other data will occur.\r
351    */\r
352   DMA_DESCRIPTOR_TypeDef *controlBlock;\r
353 } DMA_Init_TypeDef;\r
354 \r
355 \r
356 /*******************************************************************************\r
357  *****************************   PROTOTYPES   **********************************\r
358  ******************************************************************************/\r
359 \r
360 void DMA_ActivateAuto(unsigned int channel,\r
361                       bool primary,\r
362                       void *dst,\r
363                       void *src,\r
364                       unsigned int nMinus1);\r
365 void DMA_ActivateBasic(unsigned int channel,\r
366                        bool primary,\r
367                        bool useBurst,\r
368                        void *dst,\r
369                        void *src,\r
370                        unsigned int nMinus1);\r
371 void DMA_ActivatePingPong(unsigned int channel,\r
372                           bool useBurst,\r
373                           void *primDst,\r
374                           void *primSrc,\r
375                           unsigned int primNMinus1,\r
376                           void *altDst,\r
377                           void *altSrc,\r
378                           unsigned int altNMinus1);\r
379 void DMA_ActivateScatterGather(unsigned int channel,\r
380                                bool useBurst,\r
381                                DMA_DESCRIPTOR_TypeDef *altDescr,\r
382                                unsigned int count);\r
383 void DMA_CfgChannel(unsigned int channel, DMA_CfgChannel_TypeDef *cfg);\r
384 void DMA_CfgDescr(unsigned int channel,\r
385                   bool primary,\r
386                   DMA_CfgDescr_TypeDef *cfg);\r
387 #if defined( _DMA_LOOP0_MASK ) && defined( _DMA_LOOP1_MASK )\r
388 void DMA_CfgLoop(unsigned int channel, DMA_CfgLoop_TypeDef *cfg);\r
389 #endif\r
390 \r
391 #if defined( _DMA_RECT0_MASK )\r
392 void DMA_CfgRect(unsigned int channel, DMA_CfgRect_TypeDef *cfg);\r
393 #endif\r
394 \r
395 #if defined( _DMA_LOOP0_MASK ) && defined( _DMA_LOOP1_MASK )\r
396 /***************************************************************************//**\r
397  * @brief\r
398  *   Clear Loop configuration for channel\r
399  *\r
400  * @param[in] channel\r
401  *   Channel to reset loop configuration for\r
402  ******************************************************************************/\r
403 __STATIC_INLINE void DMA_ResetLoop(unsigned int channel)\r
404 {\r
405   /* Clean loop copy operation */\r
406   switch(channel)\r
407   {\r
408     case 0:\r
409       DMA->LOOP0 = _DMA_LOOP0_RESETVALUE;\r
410       break;\r
411     case 1:\r
412       DMA->LOOP1 = _DMA_LOOP1_RESETVALUE;\r
413       break;\r
414     default:\r
415       break;\r
416   }\r
417 }\r
418 #endif\r
419 \r
420 \r
421 #if defined( _DMA_RECT0_MASK )\r
422 /***************************************************************************//**\r
423  * @brief\r
424  *   Clear Rect/2D DMA configuration for channel\r
425  *\r
426  * @param[in] channel\r
427  *   Channel to reset loop configuration for\r
428  ******************************************************************************/\r
429 __STATIC_INLINE void DMA_ResetRect(unsigned int channel)\r
430 {\r
431   (void) channel;\r
432 \r
433   /* Clear rect copy operation */\r
434   DMA->RECT0 = _DMA_RECT0_RESETVALUE;\r
435 }\r
436 #endif\r
437 void DMA_CfgDescrScatterGather(DMA_DESCRIPTOR_TypeDef *descr,\r
438                                unsigned int indx,\r
439                                DMA_CfgDescrSGAlt_TypeDef *cfg);\r
440 void DMA_ChannelEnable(unsigned int channel, bool enable);\r
441 bool DMA_ChannelEnabled(unsigned int channel);\r
442 void DMA_Init(DMA_Init_TypeDef *init);\r
443 void DMA_IRQHandler(void);\r
444 void DMA_RefreshPingPong(unsigned int channel,\r
445                          bool primary,\r
446                          bool useBurst,\r
447                          void *dst,\r
448                          void *src,\r
449                          unsigned int nMinus1,\r
450                          bool last);\r
451 void DMA_Reset(void);\r
452 \r
453 /***************************************************************************//**\r
454  * @brief\r
455  *   Clear one or more pending DMA interrupts.\r
456  *\r
457  * @param[in] flags\r
458  *   Pending DMA interrupt sources to clear. Use one or more valid\r
459  *   interrupt flags for the DMA module (DMA_IFC_nnn).\r
460  ******************************************************************************/\r
461 __STATIC_INLINE void DMA_IntClear(uint32_t flags)\r
462 {\r
463   DMA->IFC = flags;\r
464 }\r
465 \r
466 \r
467 /***************************************************************************//**\r
468  * @brief\r
469  *   Disable one or more DMA interrupts.\r
470  *\r
471  * @param[in] flags\r
472  *   DMA interrupt sources to disable. Use one or more valid\r
473  *   interrupt flags for the DMA module (DMA_IEN_nnn).\r
474  ******************************************************************************/\r
475 __STATIC_INLINE void DMA_IntDisable(uint32_t flags)\r
476 {\r
477   DMA->IEN &= ~flags;\r
478 }\r
479 \r
480 \r
481 /***************************************************************************//**\r
482  * @brief\r
483  *   Enable one or more DMA interrupts.\r
484  *\r
485  * @note\r
486  *   Depending on the use, a pending interrupt may already be set prior to\r
487  *   enabling the interrupt. Consider using DMA_IntClear() prior to enabling\r
488  *   if such a pending interrupt should be ignored.\r
489  *\r
490  * @param[in] flags\r
491  *   DMA interrupt sources to enable. Use one or more valid\r
492  *   interrupt flags for the DMA module (DMA_IEN_nnn).\r
493  ******************************************************************************/\r
494 __STATIC_INLINE void DMA_IntEnable(uint32_t flags)\r
495 {\r
496   DMA->IEN |= flags;\r
497 }\r
498 \r
499 \r
500 /***************************************************************************//**\r
501  * @brief\r
502  *   Get pending DMA interrupt flags.\r
503  *\r
504  * @note\r
505  *   The event bits are not cleared by the use of this function.\r
506  *\r
507  * @return\r
508  *   DMA interrupt sources pending. Returns one or more valid\r
509  *   interrupt flags for the DMA module (DMA_IF_nnn).\r
510  ******************************************************************************/\r
511 __STATIC_INLINE uint32_t DMA_IntGet(void)\r
512 {\r
513   return DMA->IF;\r
514 }\r
515 \r
516 \r
517 /***************************************************************************//**\r
518  * @brief\r
519  *   Get enabled and pending DMA interrupt flags.\r
520  *   Useful for handling more interrupt sources in the same interrupt handler.\r
521  *\r
522  * @note\r
523  *   Interrupt flags are not cleared by the use of this function.\r
524  *\r
525  * @return\r
526  *   Pending and enabled DMA interrupt sources\r
527  *   The return value is the bitwise AND of\r
528  *   - the enabled interrupt sources in DMA_IEN and\r
529  *   - the pending interrupt flags DMA_IF\r
530  ******************************************************************************/\r
531 __STATIC_INLINE uint32_t DMA_IntGetEnabled(void)\r
532 {\r
533   uint32_t ien;\r
534 \r
535   ien = DMA->IEN;\r
536   return DMA->IF & ien;\r
537 }\r
538 \r
539 \r
540 /***************************************************************************//**\r
541  * @brief\r
542  *   Set one or more pending DMA interrupts\r
543  *\r
544  * @param[in] flags\r
545  *   DMA interrupt sources to set to pending. Use one or more valid\r
546  *   interrupt flags for the DMA module (DMA_IFS_nnn).\r
547  ******************************************************************************/\r
548 __STATIC_INLINE void DMA_IntSet(uint32_t flags)\r
549 {\r
550   DMA->IFS = flags;\r
551 }\r
552 \r
553 /** @} (end addtogroup DMA) */\r
554 /** @} (end addtogroup EM_Library) */\r
555 \r
556 #ifdef __cplusplus\r
557 }\r
558 #endif\r
559 \r
560 #endif /* defined( DMA_PRESENT ) */\r
561 #endif /* __SILICON_LABS_EM_DMA_H__ */\r