1 /*
2 * Copyright (c) 2022-2023, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /** ============================================================================
33 * @file UDMALPF3.h
34 *
35 * @brief UDMALPF3 driver implementation.
36 *
37 * # Driver include #
38 * The UDMALPF3 header file should be included in an application as follows:
39 * @code
40 * #include <ti/drivers/dma/UDMALPF3.h>
41 * @endcode
42 *
43 * # Overview #
44 * The UDMALPF3 driver currently only supports internal use by the drivers
45 * that use the uDMA peripheral (e.g., SPILPF3DMA).
46 * In other words, the application should never call any of the functions in this
47 * file.
48 *
49 * # General Behavior #
50 * This driver is used implicitly by other drivers (e.g., the SPILPF3DMA
51 * driver) so users should not have to interface to this driver from the
52 * application.
53 * The uDMA hardware makes use of a control table in RAM which must be 1024 bytes
54 * aligned. The default base address of this control table is 0x20000400, however
55 * this can be changed simply by defining UDMALPF3_CONFIG_BASE.
56 * The SPILPF3DMA.h supports SPI0, and uses both TX and RX DMA channels.
57 * Each control table entry is 16 bytes, so if an application uses SPI0
58 * the total RAM usage will be 2*16=32 bytes. Please see [Use cases] (@ref
59 * UDMA_23XX_USE_CASES) for example.
60 *
61 * # Error handling #
62 * Error handling is handled by the overlying driver which uses the DMA.
63 *
64 * # Power management #
65 * Power management is handled by the overlying driver which uses the DMA.
66 *
67 * # Supported functions #
68 * Note that these functions should never be called from the application, they
69 * are only called from other drivers. They are however included here for completeness:
70 *
71 * | API function | Description |
72 * |------------------------- |------------------------------------------------|
73 * | UDMALPF3_init() | Initialize the uDMA HW. |
74 *
75 * @note These functions should not be called by code. These functions are called
76 * by drivers using the DMA.
77 *
78 * # Unsupported Functionality #
79 * No known limitations
80 *
81 * # Use Cases @anchor UDMA_23XX_USE_CASES #
82 * In a system that has available SPI and UART peripherals, the following
83 * scenarios are possible:
84 * @code
85 * #define UDMALPF3_CONFIG_BASE 0x20000400
86 * @endcode
87 * - If only SPI0 is used (with TX mapped on channel 0 and RX mapped on channel
88 * 1), this will allocate 2*16=32 RAM bytes at address:\n
89 * [0x20000400-0x2000041F] = SPI0 RX/TX DMA channels
90 * - If only UART0 (with TX mapped on channel 2 and RX mapped on channel 3) is
91 * used, this will allocate 2*16=32 RAM bytes at address:\n
92 * [0x20000420-0x2000043F] = UART0 RX/TX DMA channels
93 * - If both SPI0 and UART0 are used, this will allocate 4*16=64 RAM bytes at addresses:\n
94 * [0x20000400-0x2000041F] = SPI0 RX/TX DMA channels\n
95 * [0x20000420-0x2000043F] = UART0 RX/TX DMA channels
96 *
97 * ============================================================================
98 */
99
100 #ifndef ti_drivers_UDMALPF3__include
101 #define ti_drivers_UDMALPF3__include
102
103 #include <stdint.h>
104 #include <stdbool.h>
105
106 #include <ti/drivers/Power.h>
107
108 #include <ti/devices/DeviceFamily.h>
109 #include DeviceFamily_constructPath(inc/hw_types.h)
110 #include DeviceFamily_constructPath(driverlib/udma.h)
111
112 #ifdef __cplusplus
113 extern "C" {
114 #endif
115
116 /*! Base address for the DMA control table, must be 1024 bytes aligned */
117 #if !defined(UDMALPF3_CONFIG_BASE)
118 #define UDMALPF3_CONFIG_BASE 0x20000400
119 #endif
120
121 /*! Make sure DMA control table base address is 1024 bytes aligned */
122 #if (UDMALPF3_CONFIG_BASE & 0x3FF)
123 #error "Base address for DMA control table 'UDMALPF3_CONFIG_BASE' must be 1024 bytes aligned."
124 #endif
125
126 /*! Compiler specific macros to allocate DMA control table entries */
127 #if defined(__IAR_SYSTEMS_ICC__)
128 #define ALLOCATE_CONTROL_TABLE_ENTRY(ENTRY_NAME, CHANNEL_INDEX) \
129 __no_init __root static volatile uDMAControlTableEntry ENTRY_NAME @UDMALPF3_CONFIG_BASE + \
130 (CHANNEL_INDEX) * sizeof(uDMAControlTableEntry)
131 #elif defined(__TI_COMPILER_VERSION__) || defined(__clang__)
132 #define ALLOCATE_CONTROL_TABLE_ENTRY(ENTRY_NAME, CHANNEL_INDEX) \
133 static volatile uDMAControlTableEntry ENTRY_NAME \
134 __attribute__((retain, \
135 location((UDMALPF3_CONFIG_BASE) + (CHANNEL_INDEX) * sizeof(uDMAControlTableEntry))))
136 #elif defined(__GNUC__)
137 #define ALLOCATE_CONTROL_TABLE_ENTRY(ENTRY_NAME, CHANNEL_INDEX) \
138 extern int UDMALPF3_##ENTRY_NAME##_is_placed; \
139 __attribute__((section("." #ENTRY_NAME), used)) static volatile uDMAControlTableEntry ENTRY_NAME = { \
140 &UDMALPF3_##ENTRY_NAME##_is_placed}
141 #else
142 #error "don't know how to define ALLOCATE_CONTROL_TABLE_ENTRY for this toolchain"
143 #endif
144
145 /*! Sets the DMA transfer size in number of items */
146 #define UDMALPF3_SET_TRANSFER_SIZE(SIZE) (((SIZE - 1) << UDMA_XFER_SIZE_S) & UDMA_XFER_SIZE_M)
147 /*! Gets the DMA transfer size in number of items*/
148 #define UDMALPF3_GET_TRANSFER_SIZE(CONTROL) (((CONTROL & UDMA_XFER_SIZE_M) >> UDMA_XFER_SIZE_S) + 1)
149
150 /*!
151 * @brief UDMALPF3 Global configuration
152 */
153 typedef struct
154 {
155 uint32_t CtrlBaseAddr; /*!< Base address for UDMALPF3 control table */
156 } UDMALPF3_Config;
157
158 /* Externs from ti_drivers_config.c */
159 extern const UDMALPF3_Config UDMALPF3_config;
160
161 /*!
162 * @brief Function to initialize the LPF3 DMA driver and peripheral
163 *
164 * The function will initialize the DMA peripheral and set the Control table
165 * base address. The call powers up and clocks the DMA module only during
166 * initialization. Each driver using DMA must set a power dependency
167 * on the module before starting to use it (e.g. when opening the driver) and
168 * release that dependency when DMA is no longer needed (e.g. when closing the
169 * driver).
170 *
171 * @pre Calling context: Hwi, Swi, Task
172 *
173 * @return none
174 *
175 * @sa
176 */
177 extern void UDMALPF3_init(void);
178
179 /*!
180 * @internal
181 * @brief Function to enable the given DMA channel(s)
182 *
183 * @pre UDMALPF3_init() has to be called first.
184 * Calling context: Hwi, Swi, Task
185 *
186 * @param channelBitMask A bitmask of the channels to be enabled.
187 *
188 * @sa UDMALPF3_channelDisable
189 */
UDMALPF3_channelEnable(uint32_t channelBitMask)190 __STATIC_INLINE void UDMALPF3_channelEnable(uint32_t channelBitMask)
191 {
192 /* Enable DMA channel */
193 uDMAEnableChannel(channelBitMask);
194 }
195
196 /*!
197 * @internal
198 * @brief Function to check if a given DMA channel is done.
199 *
200 * Will read the request done signal for the given channels
201 * and return true if all channels are done, otherwise false.
202 *
203 * @pre UDMALPF3_init() has to be called first.
204 * Calling context: Hwi, Swi, Task
205 *
206 * @param channelBitMask A bitmask of the channels to be checked.
207 *
208 * @return True if the channels are done, false otherwise.
209 *
210 * @sa UDMALPF3_channelDisable
211 */
UDMALPF3_channelDone(uint32_t channelBitMask)212 __STATIC_INLINE bool UDMALPF3_channelDone(uint32_t channelBitMask)
213 {
214 /* Check if REQDONE is set for the specified channels */
215 return (uDMAIntStatus() & channelBitMask) ? true : false;
216 }
217
218 /*!
219 * @internal
220 * @brief Function to clear a given DMA channel interrupt.
221 *
222 * Will clear the DMA interrupt(s) for the given bitmask provided.
223 *
224 * @pre Calling context: Hwi, Swi, Task
225 *
226 * @param channelBitMask A bitmask of the channels to clear interrupts for.
227 *
228 * @return none
229 */
UDMALPF3_clearInterrupt(uint32_t channelBitMask)230 __STATIC_INLINE void UDMALPF3_clearInterrupt(uint32_t channelBitMask)
231 {
232 /* Clear UDMA done interrupt */
233 uDMAClearInt(channelBitMask);
234 }
235
236 /*!
237 * @internal
238 * @brief Function to disable one or more DMA channels.
239 *
240 * Will disable the channel(s) for the given bitmask provided.
241 *
242 * @pre Calling context: Hwi, Swi, Task
243 *
244 * @param channelBitMask A bitmask of the channels to be disabled.
245 *
246 * @return none
247 *
248 * @sa UDMALPF3_channelEnable
249 */
UDMALPF3_channelDisable(uint32_t channelBitMask)250 __STATIC_INLINE void UDMALPF3_channelDisable(uint32_t channelBitMask)
251 {
252 /* Disable provided channels(s) */
253 uDMADisableChannel(channelBitMask);
254 }
255
256 /*!
257 * @internal
258 * @brief Function to disable a DMA channel's attributes.
259 *
260 * Will disable a channel's attributes.
261 *
262 * @pre Calling context: Hwi, Swi, Task
263 *
264 * @param channelBitMask A bitmask of the channels to configure.
265 *
266 * @param attr Channel attribute to disable.
267 *
268 *
269 * @return none
270 *
271 * @sa UDMALPF3_channelEnable
272 */
UDMALPF3_disableAttribute(uint32_t channelBitMask,uint32_t attr)273 __STATIC_INLINE void UDMALPF3_disableAttribute(uint32_t channelBitMask, uint32_t attr)
274 {
275 /* disable provided attribute for the given channel */
276 uDMADisableChannelAttribute(channelBitMask, attr);
277 }
278
279 #ifdef __cplusplus
280 }
281 #endif
282
283 #endif /* ti_drivers_UDMALPF3__include */
284