1 /**
2  * @file
3  * @brief   Direct Memory Access (DMA) driver function prototypes and data types.
4  */
5 
6 /* ****************************************************************************
7  * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the "Software"),
11  * to deal in the Software without restriction, including without limitation
12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  * and/or sell copies of the Software, and to permit persons to whom the
14  * Software is furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included
17  * in all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22  * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
23  * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  *
27  * Except as contained in this notice, the name of Maxim Integrated
28  * Products, Inc. shall not be used except as stated in the Maxim Integrated
29  * Products, Inc. Branding Policy.
30  *
31  * The mere transfer of this software does not imply any licenses
32  * of trade secrets, proprietary technology, copyrights, patents,
33  * trademarks, maskwork rights, or any other form of intellectual
34  * property whatsoever. Maxim Integrated Products, Inc. retains all
35  * ownership rights.
36  *
37  * $Date: 2019-07-01 11:06:19 -0500 (Mon, 01 Jul 2019) $
38  * $Revision: 44383 $
39  *
40  *************************************************************************** */
41 
42 #ifndef _DMA_H_
43 #define _DMA_H_
44 
45 /* **** Includes **** */
46 #include "mxc_config.h"
47 #include "dma_regs.h"
48 
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
52 
53 /**
54  * @defgroup dma Direct Memory Access (DMA)
55  * @ingroup periphlibs
56  * @{
57  */
58 
59 /* **** Definitions **** */
60 
61 /**
62  * Enumeration for the DMA Channel's priority level.
63  */
64 typedef enum {
65     DMA_PRIO_HIGH = MXC_S_DMA_CFG_PRI_HIGH,         /**< High Priority */
66     DMA_PRIO_MEDHIGH = MXC_S_DMA_CFG_PRI_MEDHIGH,   /**< Medium High Priority */
67     DMA_PRIO_MEDLOW = MXC_S_DMA_CFG_PRI_MEDLOW,     /**< Medium Low Priority */
68     DMA_PRIO_LOW = MXC_S_DMA_CFG_PRI_LOW,           /**< Low Priority */
69 } dma_priority_t;
70 
71 /** @brief DMA request select */
72 typedef enum {
73     DMA_REQSEL_MEMTOMEM = MXC_S_DMA_CFG_REQSEL_MEMTOMEM,        /**< Memory to Memory DMA Request Selection */
74     DMA_REQSEL_SPI0RX = MXC_S_DMA_CFG_REQSEL_SPI0RX,            /**< SPI0 Receive DMA Request Selection */
75     DMA_REQSEL_SPI1RX = MXC_S_DMA_CFG_REQSEL_SPI1RX,            /**< SPI1 Receive DMA Request Selection */
76     DMA_REQSEL_UART0RX = MXC_S_DMA_CFG_REQSEL_UART0RX,          /**< UART0 Receive DMA Request Selection */
77     DMA_REQSEL_UART1RX = MXC_S_DMA_CFG_REQSEL_UART1RX,          /**< UART1 Receive DMA Request Selection */
78     DMA_REQSEL_I2C0RX = MXC_S_DMA_CFG_REQSEL_I2C0RX,            /**< I2C0 Receive DMA Request Selection */
79     DMA_REQSEL_I2C1RX = MXC_S_DMA_CFG_REQSEL_I2C1RX,            /**< I2C1 Receive DMA Request Selection */
80     DMA_REQSEL_SPI0TX = MXC_S_DMA_CFG_REQSEL_SPI0TX,            /**< SPI0 Transmit DMA Request Selection */
81     DMA_REQSEL_SPI1TX = MXC_S_DMA_CFG_REQSEL_SPI1TX,            /**< SPI1 Transmit DMA Request Selection */
82     DMA_REQSEL_UART0TX = MXC_S_DMA_CFG_REQSEL_UART0TX,          /**< UART0 Transmit DMA Request Selection */
83     DMA_REQSEL_UART1TX = MXC_S_DMA_CFG_REQSEL_UART1TX,          /**< UART1 Transmit DMA Request Selection */
84     DMA_REQSEL_I2C0TX = MXC_S_DMA_CFG_REQSEL_I2C0TX,            /**< I2C0 Transmit DMA Request Selection */
85     DMA_REQSEL_I2C1TX = MXC_S_DMA_CFG_REQSEL_I2C1TX,            /**< I2C1 Transmit DMA Request Selection */
86 } dma_reqsel_t;
87 
88 /** @brief Enumeration for the DMA prescaler */
89 typedef enum {
90     DMA_PRESCALE_DISABLE = MXC_S_DMA_CFG_PSSEL_DIS,     /**< Prescaler disabled */
91     DMA_PRESCALE_DIV256 = MXC_S_DMA_CFG_PSSEL_DIV256,   /**< Divide by 256 */
92     DMA_PRESCALE_DIV64K = MXC_S_DMA_CFG_PSSEL_DIV64K,   /**< Divide by 65,536 */
93     DMA_PRESCALE_DIV16M = MXC_S_DMA_CFG_PSSEL_DIV16M,   /**< Divide by 16,777,216 */
94 } dma_prescale_t;
95 
96 /** @brief Enumeration for the DMA timeout value */
97 typedef enum {
98     DMA_TIMEOUT_4_CLK = MXC_S_DMA_CFG_TOSEL_TO4,        /**< DMA timeout of 4 clocks */
99     DMA_TIMEOUT_8_CLK = MXC_S_DMA_CFG_TOSEL_TO8,        /**< DMA timeout of 8 clocks */
100     DMA_TIMEOUT_16_CLK = MXC_S_DMA_CFG_TOSEL_TO16,      /**< DMA timeout of 16 clocks */
101     DMA_TIMEOUT_32_CLK = MXC_S_DMA_CFG_TOSEL_TO32,      /**< DMA timeout of 32 clocks */
102     DMA_TIMEOUT_64_CLK = MXC_S_DMA_CFG_TOSEL_TO64,      /**< DMA timeout of 64 clocks */
103     DMA_TIMEOUT_128_CLK = MXC_S_DMA_CFG_TOSEL_TO128,    /**< DMA timeout of 128 clocks */
104     DMA_TIMEOUT_256_CLK = MXC_S_DMA_CFG_TOSEL_TO256,    /**< DMA timeout of 256 clocks */
105     DMA_TIMEOUT_512_CLK = MXC_S_DMA_CFG_TOSEL_TO512,    /**< DMA timeout of 512 clocks */
106 } dma_timeout_t;
107 
108 /** @brief DMA transfer data width */
109 typedef enum {
110     /* Using the '_V_' define instead of the '_S_' since these same values will be used to
111        specify the DSTWD also.  The API functions will shift the value the correct amount
112        prior to writing the cfg register. */
113     DMA_WIDTH_BYTE = MXC_V_DMA_CFG_SRCWD_BYTE,          /**< DMA transfer in bytes */
114     DMA_WIDTH_HALFWORD = MXC_V_DMA_CFG_SRCWD_HALFWORD,  /**< DMA transfer in 16-bit half-words */
115     DMA_WIDTH_WORD = MXC_V_DMA_CFG_SRCWD_WORD,          /**< DMA transfer in 32-bit words */
116 } dma_width_t;
117 
118 /** @brief Convenience defines for options */
119 #define DMA_FALSE 0 /**< Define for passing 0 to DMA functions */
120 #define DMA_TRUE  1 /**< Define for passing 1 to DMA functions */
121 
122 /* **** Function Prototypes **** */
123 
124 /**
125  * @brief      Initialize DMA resources
126  * @details    This initialization is required before using the DMA driver functions.
127  * @return     #E_NO_ERROR if successful
128  */
129 int DMA_Init(void);
130 
131 
132 /**
133  * @brief      Request DMA channel
134  * @details    Returns a handle to the first free DMA channel, which can be used via API calls
135  *             or direct access to channel registers using the DMA_GetCHRegs(int ch) function.
136  * @return     Non-negative channel handle (inclusive of zero).
137  * @return     #E_NONE_AVAIL    All channels in use.
138  * @return     #E_BAD_STATE     DMA is not initialized, call DMA_Init() first.
139  * @return     #E_BUSY          DMA is currently busy (locked), try again later.
140  */
141 int DMA_AcquireChannel(void);
142 
143 /**
144  * @brief      Release DMA channel
145  * @details    Stops any DMA operation on the channel and returns it to the pool of free channels.
146  *
147  * @param          ch   channel handle to release
148  *
149  * @return     #E_BAD_PARAM if an unused or invalid channel handle, #E_NO_ERROR otherwise
150  */
151 int DMA_ReleaseChannel(int ch);
152 
153 /**
154  * @brief      Configure the DMA channel
155  * @details    Configures the channel, which was previously requested by DMA_Getchannel()
156  *
157  * @param      ch           The channel to configure
158  * @param      prio         The channel's priority
159  * @param      reqsel       Select the DMA request line
160  * @param      reqwait_en   The enable delay before request
161  * @param      tosel        The transfer timer timeout select
162  * @param      pssel        The transfer timer prescale select
163  * @param      srcwd        The size of the read transactions
164  * @param      srcinc_en    Enable auto-increment source pointer
165  * @param      dstwd        The size of write transactions
166  * @param      dstinc_en    Enable auto-increment destination pointer
167  * @param      burst_size   The number of bytes transferred in one transaction
168  * @param      chdis_inten  The channel disable interrupt enable
169  * @param      ctz_inten    The count-to-zero interrupt enable
170  *
171  * @return     #E_BAD_PARAM if an unused or invalid channel handle
172  * @return     #E_NO_ERROR otherwise
173  */
174 int DMA_ConfigChannel(int ch,
175                       dma_priority_t prio,
176                       dma_reqsel_t reqsel, unsigned int reqwait_en,
177                       dma_timeout_t tosel, dma_prescale_t pssel,
178                       dma_width_t srcwd, unsigned int srcinc_en,
179                       dma_width_t dstwd, unsigned int dstinc_en,
180                       unsigned int burst_size, unsigned int chdis_inten,
181                       unsigned int ctz_inten);
182 
183 /**
184  * @brief      Set channel source, destination, and count for transfer
185  * @param      ch   channel handle
186  * @param      src_addr  source address (*)
187  * @param      dst_addr  destination address (*)
188  * @param      count  number of bytes to transfer
189  * @details    This function is used to set the source and destination addresses and the number
190  *             of bytes to transfer using the channel, @p ch.
191  * @note       Unless the channel request select is #DMA_REQSEL_MEMTOMEM,
192  *             either src_addr or dst_addr will be ignored by the DMA engine.
193  *             In these cases, the address is a don't-care. See the User's
194  *             Guide for more information.
195  * @return     #E_BAD_PARAM if an unused or invalid channel handle
196  * @return     #E_NO_ERROR otherwise
197  */
198 int DMA_SetSrcDstCnt(int ch,
199                      void *src_addr,
200                      void *dst_addr,
201                      unsigned int count);
202 
203 /**
204  * @brief      Set channel reload values
205  * @param      ch   channel handle
206  * @param      src_addr_reload  source address
207  * @param      dst_addr_reload  destination address
208  * @param      count_reload  number of bytes to transfer
209  * @details    This function will set the values which will be loaded after the
210  *             channel count register reaches zero. After enabling, call with
211  *             count_reload set to zero to disable reload.
212  * @return     #E_BAD_PARAM if an unused or invalid channel handle
213  * @return     #E_NO_ERROR otherwise
214  */
215 int DMA_SetReload(int ch,
216                   void *src_addr_reload,
217                   void *dst_addr_reload,
218                   unsigned int count_reload);
219 
220 /**
221  * @brief      Set channel interrupt callback
222  * @param      ch        channel handle
223  * @param      callback  Pointer to a function to call when the channel
224  *                       interrupt flag is set and interrupts are enabled or
225  *                       when DMA is shutdown by the driver.
226  * @details    Configures the channel interrupt callback. The @p callback
227  *             function is called for two conditions:
228  *               -# When the channel's interrupt flag is set and DMA interrupts
229  *                  are enabled.
230  *               -# If the driver calls the DMA_Shutdown() function. The
231  *                  callback function prototype is:
232  * @code
233  *             void callback_fn(int ch, int reason);
234  * @endcode
235  *             @p ch indicates the channel that generated the callback, @p
236  *             reason is either #E_NO_ERROR for a DMA interrupt or #E_SHUTDOWN
237  *             if the DMA is being shutdown.
238  *
239  * @return     #E_BAD_PARAM if an unused or invalid channel handle
240  * @return     #E_NO_ERROR otherwise
241  */
242 int DMA_SetCallback(int ch, void (*callback)(int, int));
243 
244 /**
245  * @brief      Enable channel interrupt
246  * @param      ch   channel handle
247  * @return     #E_BAD_PARAM if an unused or invalid channel handle
248  * @return     #E_NO_ERROR otherwise
249  */
250 int DMA_EnableInterrupt(int ch);
251 
252 /**
253  * @brief      Disable channel interrupt
254  * @param      ch   channel handle
255  * @return     #E_BAD_PARAM if an unused or invalid channel handle
256  * @return     #E_NO_ERROR otherwise
257  */
258 int DMA_DisableInterrupt(int ch);
259 
260 /**
261  * @brief Read channel interrupt flags
262  * @param      ch channel handle
263  * @param      fl flags to get
264  * @return    #E_BAD_PARAM if an unused or invalid channel handle
265  * @return    #E_NO_ERROR otherwise
266  */
267 int DMA_GetFlags(int ch, unsigned int *fl);
268 
269 /**
270  * @brief      Clear channel interrupt flags
271  * @param      ch   channel handle
272  * @return     #E_BAD_PARAM if an unused or invalid channel handle
273  * @return     #E_NO_ERROR otherwise
274  */
275 int DMA_ClearFlags(int ch);
276 
277 /**
278  * @brief      Start transfer
279  * @param      ch   channel handle
280  * @details    Start the DMA channel transfer, assumes that DMA_SetSrcDstCnt() has been called beforehand.
281  * @return     #E_BAD_PARAM if an unused or invalid channel handle
282  * @return     #E_NO_ERROR otherwise
283  */
284 int DMA_Start(int ch);
285 
286 /**
287  * @brief      Stop DMA transfer, irrespective of status (complete or in-progress)
288  * @param      ch   channel handle
289  * @return     #E_BAD_PARAM if an unused or invalid channel handle
290  * @return     #E_NO_ERROR otherwise
291  */
292 int DMA_Stop(int ch);
293 
294 /**
295  * @brief      Get a pointer to the DMA channel registers
296  * @param      ch   channel handle
297  * @details    If direct access to DMA channel registers is required, this
298  *             function can be used on a channel handle returned by DMA_AcquireChannel().
299  * @return     NULL if an unused or invalid channel handle, or a valid pointer otherwise
300  */
301 mxc_dma_ch_regs_t *DMA_GetCHRegs(int ch);
302 
303 /**
304  * @brief      Interrupt handler function
305  * @param      ch   channel handle
306  * @details    Call this function as the ISR for each DMA channel under driver control.
307  *             Interrupt flags for channel ch will be automatically cleared before return.
308  * @return     NULL if an unused or invalid channel handle, or a valid pointer otherwise
309  */
310 void DMA_Handler(int ch);
311 
312 /**@} end of group dma */
313 #ifdef __cplusplus
314 }
315 #endif
316 
317 #endif /* _DMA_H_ */
318