CC13xx Driver Library
udma.c
Go to the documentation of this file.
1 /******************************************************************************
2 * Filename: udma.c
3 * Revised: 2015-04-07 14:16:28 +0200 (Tue, 07 Apr 2015)
4 * Revision: 43160
5 *
6 * Description: Driver for the uDMA controller
7 *
8 * Copyright (c) 2015 - 2016, Texas Instruments Incorporated
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
13 *
14 * 1) Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 *
17 * 2) Redistributions in binary form must reproduce the above copyright notice,
18 * this list of conditions and the following disclaimer in the documentation
19 * and/or other materials provided with the distribution.
20 *
21 * 3) Neither the name of the ORGANIZATION nor the names of its contributors may
22 * be used to endorse or promote products derived from this software without
23 * specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 *
37 ******************************************************************************/
38 
39 #include <driverlib/udma.h>
40 
41 //*****************************************************************************
42 //
43 // Handle support for DriverLib in ROM:
44 // This section will undo prototype renaming made in the header file
45 //
46 //*****************************************************************************
47 #if !defined(DOXYGEN)
48  #undef uDMAChannelAttributeEnable
49  #define uDMAChannelAttributeEnable NOROM_uDMAChannelAttributeEnable
50  #undef uDMAChannelAttributeDisable
51  #define uDMAChannelAttributeDisable NOROM_uDMAChannelAttributeDisable
52  #undef uDMAChannelAttributeGet
53  #define uDMAChannelAttributeGet NOROM_uDMAChannelAttributeGet
54  #undef uDMAChannelControlSet
55  #define uDMAChannelControlSet NOROM_uDMAChannelControlSet
56  #undef uDMAChannelTransferSet
57  #define uDMAChannelTransferSet NOROM_uDMAChannelTransferSet
58  #undef uDMAChannelScatterGatherSet
59  #define uDMAChannelScatterGatherSet NOROM_uDMAChannelScatterGatherSet
60  #undef uDMAChannelSizeGet
61  #define uDMAChannelSizeGet NOROM_uDMAChannelSizeGet
62  #undef uDMAChannelModeGet
63  #define uDMAChannelModeGet NOROM_uDMAChannelModeGet
64 #endif
65 
66 //*****************************************************************************
67 //
69 //
70 //*****************************************************************************
71 void
72 uDMAChannelAttributeEnable(uint32_t ui32Base, uint32_t ui32ChannelNum,
73  uint32_t ui32Attr)
74 {
75  //
76  // Check the arguments.
77  //
78  ASSERT(uDMABaseValid(ui32Base));
79  ASSERT(ui32ChannelNum < UDMA_NUM_CHANNELS);
82 
83  //
84  // Set the useburst bit for this channel if set in ui32Attr.
85  //
86  if(ui32Attr & UDMA_ATTR_USEBURST)
87  {
88  HWREG(ui32Base + UDMA_O_SETBURST) = 1 << ui32ChannelNum;
89  }
90 
91  //
92  // Set the alternate control select bit for this channel,
93  // if set in ui32Attr.
94  //
95  if(ui32Attr & UDMA_ATTR_ALTSELECT)
96  {
97  HWREG(ui32Base + UDMA_O_SETCHNLPRIALT) = 1 << ui32ChannelNum;
98  }
99 
100  //
101  // Set the high priority bit for this channel, if set in ui32Attr.
102  //
103  if(ui32Attr & UDMA_ATTR_HIGH_PRIORITY)
104  {
105  HWREG(ui32Base + UDMA_O_SETCHNLPRIORITY) = 1 << ui32ChannelNum;
106  }
107 
108  //
109  // Set the request mask bit for this channel, if set in ui32Attr.
110  //
111  if(ui32Attr & UDMA_ATTR_REQMASK)
112  {
113  HWREG(ui32Base + UDMA_O_SETREQMASK) = 1 << ui32ChannelNum;
114  }
115 }
116 
117 //*****************************************************************************
118 //
120 //
121 //*****************************************************************************
122 void
123 uDMAChannelAttributeDisable(uint32_t ui32Base, uint32_t ui32ChannelNum,
124  uint32_t ui32Attr)
125 {
126  //
127  // Check the arguments.
128  //
129  ASSERT(uDMABaseValid(ui32Base));
130  ASSERT(ui32ChannelNum < UDMA_NUM_CHANNELS);
133 
134  //
135  // Clear the useburst bit for this channel if set in ui32Attr.
136  //
137  if(ui32Attr & UDMA_ATTR_USEBURST)
138  {
139  HWREG(ui32Base + UDMA_O_CLEARBURST) = 1 << ui32ChannelNum;
140  }
141 
142  //
143  // Clear the alternate control select bit for this channel, if set in
144  // ululAttr.
145  //
146  if(ui32Attr & UDMA_ATTR_ALTSELECT)
147  {
148  HWREG(ui32Base + UDMA_O_CLEARCHNLPRIALT) = 1 << ui32ChannelNum;
149  }
150 
151  //
152  // Clear the high priority bit for this channel, if set in ui32Attr.
153  //
154  if(ui32Attr & UDMA_ATTR_HIGH_PRIORITY)
155  {
156  HWREG(ui32Base + UDMA_O_CLEARCHNLPRIORITY) = 1 << ui32ChannelNum;
157  }
158 
159  //
160  // Clear the request mask bit for this channel, if set in ui32Attr.
161  //
162  if(ui32Attr & UDMA_ATTR_REQMASK)
163  {
164  HWREG(ui32Base + UDMA_O_CLEARREQMASK) = 1 << ui32ChannelNum;
165  }
166 }
167 
168 //*****************************************************************************
169 //
171 //
172 //*****************************************************************************
173 uint32_t
174 uDMAChannelAttributeGet(uint32_t ui32Base, uint32_t ui32ChannelNum)
175 {
176  uint32_t ui32Attr = 0;
177 
178  //
179  // Check the arguments.
180  //
181  ASSERT(uDMABaseValid(ui32Base));
182  ASSERT(ui32ChannelNum < UDMA_NUM_CHANNELS);
183 
184  //
185  // Check to see if useburst bit is set for this channel.
186  //
187  if(HWREG(ui32Base + UDMA_O_SETBURST) & (1 << ui32ChannelNum))
188  {
189  ui32Attr |= UDMA_ATTR_USEBURST;
190  }
191 
192  //
193  // Check to see if the alternate control bit is set for this channel.
194  //
195  if(HWREG(ui32Base + UDMA_O_SETCHNLPRIALT) & (1 << ui32ChannelNum))
196  {
197  ui32Attr |= UDMA_ATTR_ALTSELECT;
198  }
199 
200  //
201  // Check to see if the high priority bit is set for this channel.
202  //
203  if(HWREG(ui32Base + UDMA_O_SETCHNLPRIORITY) & (1 << ui32ChannelNum))
204  {
205  ui32Attr |= UDMA_ATTR_HIGH_PRIORITY;
206  }
207 
208  //
209  // Check to see if the request mask bit is set for this channel.
210  //
211  if(HWREG(ui32Base + UDMA_O_SETREQMASK) & (1 << ui32ChannelNum))
212  {
213  ui32Attr |= UDMA_ATTR_REQMASK;
214  }
215 
216  //
217  // Return the configuration flags.
218  //
219  return(ui32Attr);
220 }
221 
222 //*****************************************************************************
223 //
225 //
226 //*****************************************************************************
227 void
228 uDMAChannelControlSet(uint32_t ui32Base, uint32_t ui32ChannelStructIndex,
229  uint32_t ui32Control)
230 {
231  tDMAControlTable *pControlTable;
232 
233  //
234  // Check the arguments.
235  //
236  ASSERT(uDMABaseValid(ui32Base));
237  ASSERT(ui32ChannelStructIndex < (UDMA_NUM_CHANNELS * 2));
238  ASSERT(HWREG(ui32Base + UDMA_O_CTRL) != 0);
239 
240  //
241  // Get the base address of the control table.
242  //
243  pControlTable = (tDMAControlTable *)HWREG(ui32Base + UDMA_O_CTRL);
244 
245  //
246  // Get the current control word value and mask off the fields to be
247  // changed, then OR in the new settings.
248  //
249  pControlTable[ui32ChannelStructIndex].ui32Control =
250  ((pControlTable[ui32ChannelStructIndex].ui32Control &
251  ~(UDMA_DST_INC_M |
253  UDMA_SIZE_M |
254  UDMA_ARB_M |
256  ui32Control);
257 }
258 
259 //*****************************************************************************
260 //
262 //
263 //*****************************************************************************
264 void
265 uDMAChannelTransferSet(uint32_t ui32Base, uint32_t ui32ChannelStructIndex,
266  uint32_t ui32Mode, void *pvSrcAddr, void *pvDstAddr,
267  uint32_t ui32TransferSize)
268 {
269  tDMAControlTable *pControlTable;
270  uint32_t ui32Control;
271  uint32_t ui32Inc;
272  uint32_t ui32BufferBytes;
273 
274  //
275  // Check the arguments.
276  //
277  ASSERT(uDMABaseValid(ui32Base));
278  ASSERT(ui32ChannelStructIndex < (UDMA_NUM_CHANNELS * 2));
279  ASSERT(HWREG(ui32Base + UDMA_O_CTRL) != 0);
281  ASSERT((uint32_t)pvSrcAddr >= SRAM_BASE);
282  ASSERT((uint32_t)pvDstAddr >= SRAM_BASE);
283  ASSERT((ui32TransferSize != 0) && (ui32TransferSize <= UDMA_XFER_SIZE_MAX));
284 
285  //
286  // Get the base address of the control table.
287  //
288  pControlTable = (tDMAControlTable *)HWREG(ui32Base + UDMA_O_CTRL);
289 
290  //
291  // Get the current control word value and mask off the mode and size
292  // fields.
293  //
294  ui32Control = (pControlTable[ui32ChannelStructIndex].ui32Control &
296 
297  //
298  // Adjust the mode if the alt control structure is selected.
299  //
300  if(ui32ChannelStructIndex & UDMA_ALT_SELECT)
301  {
302  if((ui32Mode == UDMA_MODE_MEM_SCATTER_GATHER) ||
303  (ui32Mode == UDMA_MODE_PER_SCATTER_GATHER))
304  {
305  ui32Mode |= UDMA_MODE_ALT_SELECT;
306  }
307  }
308 
309  //
310  // Set the transfer size and mode in the control word (but don't write the
311  // control word yet as it could kick off a transfer).
312  //
313  ui32Control |= ui32Mode | ((ui32TransferSize - 1) << UDMA_XFER_SIZE_S);
314 
315  //
316  // Get the address increment value for the source, from the control word.
317  //
318  ui32Inc = (ui32Control & UDMA_SRC_INC_M);
319 
320  //
321  // Compute the ending source address of the transfer. If the source
322  // increment is set to none, then the ending address is the same as the
323  // beginning.
324  //
325  if(ui32Inc != UDMA_SRC_INC_NONE)
326  {
327  ui32Inc = ui32Inc >> UDMA_SRC_INC_S;
328  ui32BufferBytes = ui32TransferSize << ui32Inc;
329  pvSrcAddr = (void *)((uint32_t)pvSrcAddr + ui32BufferBytes - (1 << ui32Inc));
330  }
331 
332  //
333  // Load the source ending address into the control block.
334  //
335  pControlTable[ui32ChannelStructIndex].pvSrcEndAddr = pvSrcAddr;
336 
337  //
338  // Get the address increment value for the destination, from the control
339  // word.
340  //
341  ui32Inc = ui32Control & UDMA_DST_INC_M;
342 
343  //
344  // Compute the ending destination address of the transfer. If the
345  // destination increment is set to none, then the ending address is the
346  // same as the beginning.
347  //
348  if(ui32Inc != UDMA_DST_INC_NONE)
349  {
350  //
351  // There is a special case if this is setting up a scatter-gather
352  // transfer. The destination pointer needs to point to the end of
353  // the alternate structure for this channel instead of calculating
354  // the end of the buffer in the normal way.
355  //
356  if((ui32Mode == UDMA_MODE_MEM_SCATTER_GATHER) ||
357  (ui32Mode == UDMA_MODE_PER_SCATTER_GATHER))
358  {
359  pvDstAddr =
360  (void *)&pControlTable[ui32ChannelStructIndex |
361  UDMA_ALT_SELECT].ui32Spare;
362  }
363  //
364  // Not a scatter-gather transfer, calculate end pointer normally.
365  //
366  else
367  {
368  ui32Inc = ui32Inc >> UDMA_DST_INC_S;
369  ui32BufferBytes = ui32TransferSize << ui32Inc;
370  pvDstAddr = (void *)((uint32_t)pvDstAddr + ui32BufferBytes - 1);
371  }
372  }
373 
374  //
375  // Load the destination ending address into the control block.
376  //
377  pControlTable[ui32ChannelStructIndex].pvDstEndAddr = pvDstAddr;
378 
379  //
380  // Write the new control word value.
381  //
382  pControlTable[ui32ChannelStructIndex].ui32Control = ui32Control;
383 }
384 
385 //*****************************************************************************
386 //
388 //
389 //*****************************************************************************
390 void
391 uDMAChannelScatterGatherSet(uint32_t ui32Base, uint32_t ui32ChannelNum,
392  uint32_t ui32TaskCount, void *pvTaskList,
393  uint32_t ui32IsPeriphSG)
394 {
395  tDMAControlTable *pControlTable;
396  tDMAControlTable *pTaskTable;
397 
398  //
399  // Check the parameters.
400  //
401  ASSERT(uDMABaseValid(ui32Base));
402  ASSERT(ui32ChannelNum < UDMA_NUM_CHANNELS);
403  ASSERT(HWREG(ui32Base + UDMA_O_CTRL) != 0);
404  ASSERT(pvTaskList != 0);
405  ASSERT(ui32TaskCount <= UDMA_XFER_SIZE_MAX);
406  ASSERT(ui32TaskCount != 0);
407 
408  //
409  // Get the base address of the control table.
410  //
411  pControlTable = (tDMAControlTable *)HWREG(ui32Base + UDMA_O_CTRL);
412 
413  //
414  // Get a handy pointer to the task list.
415  //
416  pTaskTable = (tDMAControlTable *)pvTaskList;
417 
418  //
419  // Compute the ending address for the source pointer. This will be the
420  // last element of the last task in the task table.
421  //
422  pControlTable[ui32ChannelNum].pvSrcEndAddr =
423  &pTaskTable[ui32TaskCount - 1].ui32Spare;
424 
425  //
426  // Compute the ending address for the destination pointer. This will be
427  // the end of the alternate structure for this channel.
428  //
429  pControlTable[ui32ChannelNum].pvDstEndAddr =
430  &pControlTable[ui32ChannelNum | UDMA_ALT_SELECT].ui32Spare;
431 
432  //
433  // Compute the control word. Most configurable items are fixed for
434  // scatter-gather. Item and increment sizes are all 32-bit and arb
435  // size must be 4. The count is the number of items in the task list
436  // times 4 (4 words per task).
437  //
438  pControlTable[ui32ChannelNum].ui32Control =
441  (((ui32TaskCount * 4) - 1) << UDMA_XFER_SIZE_S) |
442  (ui32IsPeriphSG ? UDMA_MODE_PER_SCATTER_GATHER :
444 
445  //
446  // Scatter-gather operations can leave the alt bit set. So if doing
447  // back to back scatter-gather transfers, the second attempt may not
448  // work correctly because the alt bit is set. Therefore, clear the
449  // alt bit here to ensure that it is always cleared before a new SG
450  // transfer is started.
451  //
452  HWREG(ui32Base + UDMA_O_CLEARCHNLPRIALT) = 1 << ui32ChannelNum;
453 
454 }
455 
456 //*****************************************************************************
457 //
459 //
460 //*****************************************************************************
461 uint32_t
462 uDMAChannelSizeGet(uint32_t ui32Base, uint32_t ui32ChannelStructIndex)
463 {
464  tDMAControlTable *pControlTable;
465  uint32_t ui32Control;
466 
467  //
468  // Check the arguments.
469  //
470  ASSERT(uDMABaseValid(ui32Base));
471  ASSERT(ui32ChannelStructIndex < (UDMA_NUM_CHANNELS * 2));
472  ASSERT(HWREG(ui32Base + UDMA_O_CTRL) != 0);
473 
474  //
475  // Get the base address of the control table.
476  //
477  pControlTable = (tDMAControlTable *)HWREG(ui32Base + UDMA_O_CTRL);
478 
479  //
480  // Get the current control word value and mask off all but the size field
481  // and the mode field.
482  //
483  ui32Control = (pControlTable[ui32ChannelStructIndex].ui32Control &
485 
486  //
487  // If the size field and mode field are 0 then the transfer is finished
488  // and there are no more items to transfer.
489  //
490  if(ui32Control == 0)
491  {
492  return(0);
493  }
494 
495  //
496  // Otherwise, if either the size field or more field is non-zero, then
497  // not all the items have been transferred.
498  //
499  else
500  {
501  //
502  // Shift the size field and add one, then return to user.
503  //
504  return((ui32Control >> UDMA_XFER_SIZE_S) + 1);
505  }
506 }
507 
508 //*****************************************************************************
509 //
511 //
512 //*****************************************************************************
513 uint32_t
514 uDMAChannelModeGet(uint32_t ui32Base, uint32_t ui32ChannelStructIndex)
515 {
516  tDMAControlTable *pControlTable;
517  uint32_t ui32Control;
518 
519  //
520  // Check the arguments.
521  //
522  ASSERT(uDMABaseValid(ui32Base));
523  ASSERT(ui32ChannelStructIndex < (UDMA_NUM_CHANNELS * 2));
524  ASSERT(HWREG(ui32Base + UDMA_O_CTRL) != 0);
525 
526  //
527  // Get the base address of the control table.
528  //
529  pControlTable = (tDMAControlTable *)HWREG(ui32Base + UDMA_O_CTRL);
530 
531  //
532  // Get the current control word value and mask off all but the mode field.
533  //
534  ui32Control = (pControlTable[ui32ChannelStructIndex].ui32Control &
535  UDMA_MODE_M);
536 
537  //
538  // Check if scatter/gather mode, and if so, mask off the alt bit.
539  //
540  if(((ui32Control & ~UDMA_MODE_ALT_SELECT) == UDMA_MODE_MEM_SCATTER_GATHER) ||
542  {
543  ui32Control &= ~UDMA_MODE_ALT_SELECT;
544  }
545 
546  //
547  // Return the mode to the caller.
548  //
549  return(ui32Control);
550 }
#define UDMA_ARB_4
Definition: udma.h:270
#define UDMA_NUM_CHANNELS
Definition: udma.h:207
uint32_t uDMAChannelModeGet(uint32_t ui32Base, uint32_t ui32ChannelStructIndex)
Gets the transfer mode for a uDMA channel control structure.
Definition: udma.c:514
#define UDMA_ARB_M
Definition: udma.h:279
volatile void * pvSrcEndAddr
The ending source address of the data transfer.
Definition: udma.h:105
#define UDMA_SRC_INC_M
Definition: udma.h:261
#define UDMA_DST_INC_S
Definition: udma.h:256
#define UDMA_MODE_MEM_SCATTER_GATHER
Definition: udma.h:239
#define UDMA_MODE_ALT_SELECT
Definition: udma.h:244
void uDMAChannelScatterGatherSet(uint32_t ui32Base, uint32_t ui32ChannelNum, uint32_t ui32TaskCount, void *pvTaskList, uint32_t ui32IsPeriphSG)
Configures a uDMA channel for scatter-gather mode.
Definition: udma.c:391
#define UDMA_XFER_SIZE_M
Definition: udma.h:283
#define UDMA_ATTR_HIGH_PRIORITY
Definition: udma.h:225
#define UDMA_ATTR_REQMASK
Definition: udma.h:226
#define UDMA_SRC_INC_NONE
Definition: udma.h:260
void uDMAChannelAttributeDisable(uint32_t ui32Base, uint32_t ui32ChannelNum, uint32_t ui32Attr)
Disables attributes of an uDMA channel.
Definition: udma.c:123
#define UDMA_MODE_PER_SCATTER_GATHER
Definition: udma.h:241
void uDMAChannelAttributeEnable(uint32_t ui32Base, uint32_t ui32ChannelNum, uint32_t ui32Attr)
Enables attributes of a uDMA channel.
Definition: udma.c:72
void uDMAChannelControlSet(uint32_t ui32Base, uint32_t ui32ChannelStructIndex, uint32_t ui32Control)
Sets the control parameters for a uDMA channel control structure.
Definition: udma.c:228
#define UDMA_SRC_INC_32
Definition: udma.h:259
#define UDMA_MODE_M
Definition: udma.h:243
volatile uint32_t ui32Spare
An unused location.
Definition: udma.h:108
#define UDMA_DST_INC_NONE
Definition: udma.h:254
#define UDMA_DST_INC_M
Definition: udma.h:255
#define UDMA_ATTR_USEBURST
Definition: udma.h:223
#define ASSERT(expr)
Definition: debug.h:74
#define UDMA_SIZE_32
Definition: udma.h:265
#define UDMA_XFER_SIZE_S
Definition: udma.h:284
volatile uint32_t ui32Control
The channel control mode.
Definition: udma.h:107
volatile void * pvDstEndAddr
The ending destination address of the data transfer.
Definition: udma.h:106
#define UDMA_ATTR_ALTSELECT
Definition: udma.h:224
void uDMAChannelTransferSet(uint32_t ui32Base, uint32_t ui32ChannelStructIndex, uint32_t ui32Mode, void *pvSrcAddr, void *pvDstAddr, uint32_t ui32TransferSize)
Sets the transfer parameters for a uDMA channel control structure.
Definition: udma.c:265
#define UDMA_NEXT_USEBURST
Definition: udma.h:281
#define UDMA_DST_INC_32
Definition: udma.h:253
A structure that defines an entry in the channel control table.
Definition: udma.h:103
uint32_t uDMAChannelAttributeGet(uint32_t ui32Base, uint32_t ui32ChannelNum)
Gets the enabled attributes of a uDMA channel.
Definition: udma.c:174
#define UDMA_XFER_SIZE_MAX
Definition: udma.h:282
#define UDMA_SIZE_M
Definition: udma.h:266
uint32_t uDMAChannelSizeGet(uint32_t ui32Base, uint32_t ui32ChannelStructIndex)
Gets the current transfer size for a uDMA channel control structure.
Definition: udma.c:462
#define UDMA_SRC_INC_S
Definition: udma.h:262
#define UDMA_ALT_SELECT
Definition: udma.h:319