em_dma.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  1. /***************************************************************************//**
  2. * @file
  3. * @brief Direct memory access (DMA) module peripheral API
  4. * @author Energy Micro AS
  5. * @version 3.0.0
  6. *******************************************************************************
  7. * @section License
  8. * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
  9. *******************************************************************************
  10. *
  11. * Permission is granted to anyone to use this software for any purpose,
  12. * including commercial applications, and to alter it and redistribute it
  13. * freely, subject to the following restrictions:
  14. *
  15. * 1. The origin of this software must not be misrepresented; you must not
  16. * claim that you wrote the original software.
  17. * 2. Altered source versions must be plainly marked as such, and must not be
  18. * misrepresented as being the original software.
  19. * 3. This notice may not be removed or altered from any source distribution.
  20. *
  21. * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
  22. * obligation to support this Software. Energy Micro AS is providing the
  23. * Software "AS IS", with no express or implied warranties of any kind,
  24. * including, but not limited to, any implied warranties of merchantability
  25. * or fitness for any particular purpose or warranties against infringement
  26. * of any proprietary rights of a third party.
  27. *
  28. * Energy Micro AS will not be liable for any consequential, incidental, or
  29. * special damages, or any other relief, or for any claim by any third party,
  30. * arising from your use of this Software.
  31. *
  32. ******************************************************************************/
  33. #include "em_dma.h"
  34. #include "em_cmu.h"
  35. #include "em_assert.h"
  36. #include "em_bitband.h"
  37. /***************************************************************************//**
  38. * @addtogroup EM_Library
  39. * @{
  40. ******************************************************************************/
  41. /***************************************************************************//**
  42. * @addtogroup DMA
  43. * @brief Direct Memory Access (DMA) Peripheral API
  44. * @details
  45. * These DMA access functions provide basic support for the following
  46. * types of DMA cycles:
  47. *
  48. * @li @b Basic, used for transferring data between memory and peripherals.
  49. * @li @b Auto-request, used for transferring data between memory locations.
  50. * @li @b Ping-pong, used for for continuous transfer of data between memory
  51. * and peripherals, automatically toggling between primary and alternate
  52. * descriptors.
  53. * @li @b Memory @b scatter-gather, used for transferring a number of buffers
  54. * between memory locations.
  55. * @li @b Peripheral @b scatter-gather, used for transferring a number of
  56. * buffers between memory and peripherals.
  57. *
  58. * A basic understanding of the DMA controller is assumed. Please refer to
  59. * the EFM32 reference manual for further details.
  60. *
  61. * The term 'descriptor' is used as a synonym to the 'channel control data
  62. * structure' term.
  63. *
  64. * In order to use the DMA controller, the initialization function must have
  65. * been executed once (normally during system init):
  66. * @verbatim
  67. * DMA_Init();
  68. * @endverbatim
  69. *
  70. * Then, normally a user of a DMA channel configures the channel:
  71. * @verbatim
  72. * DMA_CfgChannel();
  73. * @endverbatim
  74. *
  75. * The channel configuration only has to be done once, if reusing the channel
  76. * for the same purpose later.
  77. *
  78. * In order to set up a DMA cycle, the primary and/or alternate descriptor
  79. * has to be set up as indicated below.
  80. *
  81. * For basic or auto-request cycles, use once on either primary or alternate
  82. * descriptor:
  83. * @verbatim
  84. * DMA_CfgDescr();
  85. * @endverbatim
  86. *
  87. * For ping-pong cycles, configure both primary or alternate descriptors:
  88. * @verbatim
  89. * DMA_CfgDescr(); // Primary descriptor config
  90. * DMA_CfgDescr(); // Alternate descriptor config
  91. * @endverbatim
  92. *
  93. * For scatter-gather cycles, the alternate descriptor array must be programmed:
  94. * @verbatim
  95. * // 'n' is the number of scattered buffers
  96. * // 'descr' points to the start of the alternate descriptor array
  97. *
  98. * // Fill in 'cfg'
  99. * DMA_CfgDescrScatterGather(descr, 0, cfg);
  100. * // Fill in 'cfg'
  101. * DMA_CfgDescrScatterGather(descr, 1, cfg);
  102. * :
  103. * // Fill in 'cfg'
  104. * DMA_CfgDescrScatterGather(descr, n - 1, cfg);
  105. * @endverbatim
  106. *
  107. * In many cases, the descriptor configuration only has to be done once, if
  108. * re-using the channel for the same type of DMA cycles later.
  109. *
  110. * In order to activate the DMA cycle, use the respective DMA_Activate...()
  111. * function.
  112. *
  113. * For ping-pong DMA cycles, use DMA_RefreshPingPong() from the callback to
  114. * prepare the completed descriptor for reuse. Notice that the refresh must
  115. * be done prior to the other active descriptor completes, otherwise the
  116. * ping-pong DMA cycle will halt.
  117. * @{
  118. ******************************************************************************/
  119. /*******************************************************************************
  120. ************************** LOCAL FUNCTIONS ********************************
  121. ******************************************************************************/
  122. /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
  123. /***************************************************************************//**
  124. * @brief
  125. * Prepare descriptor for DMA cycle.
  126. *
  127. * @details
  128. * This function prepares the last pieces of configuration required to start a
  129. * DMA cycle. Since the DMA controller itself modifies some parts of the
  130. * descriptor during use, those parts need to be refreshed if reusing a
  131. * descriptor configuration.
  132. *
  133. * @note
  134. * If using this function on a descriptor already activated and in use by the
  135. * DMA controller, the behaviour is undefined.
  136. *
  137. * @param[in] channel
  138. * DMA channel to prepare for DMA cycle.
  139. *
  140. * @param[in] cycleCtrl
  141. * DMA cycle type to prepare for.
  142. *
  143. * @param[in] primary
  144. * @li true - prepare primary descriptor
  145. * @li false - prepare alternate descriptor
  146. *
  147. * @param[in] useBurst
  148. * The burst feature is only used on peripherals supporting DMA bursts.
  149. * Bursts must not be used if the total length (as given by nMinus1) is
  150. * less than the arbitration rate configured for the descriptor. Please
  151. * refer to the reference manual for further details on burst usage.
  152. *
  153. * @param[in] dst
  154. * Address to start location to transfer data to. If NULL, leave setting in
  155. * descriptor as is.
  156. *
  157. * @param[in] src
  158. * Address to start location to transfer data from. If NULL, leave setting in
  159. * descriptor as is.
  160. *
  161. * @param[in] nMinus1
  162. * Number of elements (minus 1) to transfer (<= 1023).
  163. ******************************************************************************/
  164. static void DMA_Prepare(unsigned int channel,
  165. DMA_CycleCtrl_TypeDef cycleCtrl,
  166. bool primary,
  167. bool useBurst,
  168. void *dst,
  169. void *src,
  170. unsigned int nMinus1)
  171. {
  172. DMA_DESCRIPTOR_TypeDef *descr;
  173. DMA_DESCRIPTOR_TypeDef *primDescr;
  174. DMA_CB_TypeDef *cb;
  175. uint32_t inc;
  176. uint32_t chBit;
  177. uint32_t tmp;
  178. primDescr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE)) + channel;
  179. /* Find descriptor to configure */
  180. if (primary)
  181. {
  182. descr = primDescr;
  183. }
  184. else
  185. {
  186. descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE)) + channel;
  187. }
  188. /* If callback defined, update info on whether callback is issued */
  189. /* for primary or alternate descriptor. Mainly needed for ping-pong */
  190. /* cycles. */
  191. cb = (DMA_CB_TypeDef *)(primDescr->USER);
  192. if (cb)
  193. {
  194. cb->primary = (uint8_t)primary;
  195. }
  196. if (src)
  197. {
  198. inc = (descr->CTRL & _DMA_CTRL_SRC_INC_MASK) >> _DMA_CTRL_SRC_INC_SHIFT;
  199. if (inc == _DMA_CTRL_SRC_INC_NONE)
  200. {
  201. descr->SRCEND = src;
  202. }
  203. else
  204. {
  205. descr->SRCEND = (void *)((uint32_t)src + (nMinus1 << inc));
  206. }
  207. }
  208. if (dst)
  209. {
  210. inc = (descr->CTRL & _DMA_CTRL_DST_INC_MASK) >> _DMA_CTRL_DST_INC_SHIFT;
  211. if (inc == _DMA_CTRL_DST_INC_NONE)
  212. {
  213. descr->DSTEND = dst;
  214. }
  215. else
  216. {
  217. descr->DSTEND = (void *)((uint32_t)dst + (nMinus1 << inc));
  218. }
  219. }
  220. chBit = 1 << channel;
  221. if (useBurst)
  222. {
  223. DMA->CHUSEBURSTS = chBit;
  224. }
  225. else
  226. {
  227. DMA->CHUSEBURSTC = chBit;
  228. }
  229. if (primary)
  230. {
  231. DMA->CHALTC = chBit;
  232. }
  233. else
  234. {
  235. DMA->CHALTS = chBit;
  236. }
  237. /* Set cycle control */
  238. tmp = descr->CTRL & ~(_DMA_CTRL_CYCLE_CTRL_MASK | _DMA_CTRL_N_MINUS_1_MASK);
  239. tmp |= nMinus1 << _DMA_CTRL_N_MINUS_1_SHIFT;
  240. tmp |= (uint32_t)cycleCtrl << _DMA_CTRL_CYCLE_CTRL_SHIFT;
  241. descr->CTRL = tmp;
  242. }
  243. /** @endcond */
  244. /*******************************************************************************
  245. ************************ INTERRUPT FUNCTIONS ******************************
  246. ******************************************************************************/
  247. /***************************************************************************//**
  248. * @brief
  249. * Interrupt handler for DMA cycle completion handling.
  250. *
  251. * @details
  252. * Clears any pending flags and calls registered callback (if any).
  253. *
  254. * If using the default interrupt vector table setup provided, this function
  255. * is automatically placed in the IRQ table due to weak linking. If taking
  256. * control over the interrupt vector table in some other way, this interrupt
  257. * handler must be installed in order to be able to support callback actions.
  258. ******************************************************************************/
  259. void DMA_IRQHandler(void)
  260. {
  261. DMA_DESCRIPTOR_TypeDef *descr = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE);
  262. int channel;
  263. DMA_CB_TypeDef *cb;
  264. uint32_t pending;
  265. uint32_t pendingPrio;
  266. uint32_t prio;
  267. uint32_t primaryCpy;
  268. int i;
  269. /* Get all pending interrupts */
  270. pending = DMA->IF;
  271. /* Check for bus error */
  272. if (pending & DMA_IF_ERR)
  273. {
  274. /* Loop here to enable the debugger to see what has happened */
  275. while (1)
  276. ;
  277. }
  278. /* Process all pending channel interrupts. First process channels */
  279. /* defined with high priority, then those with default priority. */
  280. prio = DMA->CHPRIS;
  281. pendingPrio = pending & prio;
  282. for (i = 0; i < 2; i++)
  283. {
  284. channel = 0;
  285. /* Process pending interrupts within high/default priority group */
  286. /* honouring priority within group. */
  287. while (pendingPrio)
  288. {
  289. if (pendingPrio & 1)
  290. {
  291. /* Clear pending interrupt prior to invoking callback, in case it */
  292. /* sets up another DMA cycle. */
  293. DMA->IFC = 1 << channel;
  294. /* Normally, no point in enabling interrupt without callback, but */
  295. /* check if callback is defined anyway. Callback info is always */
  296. /* located in primary descriptor. */
  297. cb = (DMA_CB_TypeDef *)(descr[channel].USER);
  298. if (cb)
  299. {
  300. /* Toggle next-descriptor indicator always prior to invoking */
  301. /* callback (in case callback reconfigurs something) */
  302. primaryCpy = cb->primary;
  303. cb->primary ^= 1;
  304. if (cb->cbFunc)
  305. {
  306. cb->cbFunc(channel, (bool)primaryCpy, cb->userPtr);
  307. }
  308. }
  309. }
  310. pendingPrio >>= 1;
  311. channel++;
  312. }
  313. /* On second iteration, process default priority channels */
  314. pendingPrio = pending & ~prio;
  315. }
  316. }
  317. /*******************************************************************************
  318. ************************** GLOBAL FUNCTIONS *******************************
  319. ******************************************************************************/
  320. /***************************************************************************//**
  321. * @brief
  322. * Activate DMA auto-request cycle (used for memory-memory transfers).
  323. *
  324. * @details
  325. * Prior to activating the DMA cycle, the channel and descriptor to be used
  326. * must have been properly configured.
  327. *
  328. * @note
  329. * If using this function on a channel already activated and in use by the
  330. * DMA controller, the behaviour is undefined.
  331. *
  332. * @param[in] channel
  333. * DMA channel to activate DMA cycle for.
  334. *
  335. * @param[in] primary
  336. * @li true - activate using primary descriptor
  337. * @li false - activate using alternate descriptor
  338. *
  339. * @param[in] dst
  340. * Address to start location to transfer data to. If NULL, leave setting in
  341. * descriptor as is from a previous activation.
  342. *
  343. * @param[in] src
  344. * Address to start location to transfer data from. If NULL, leave setting in
  345. * descriptor as is from a previous activation.
  346. *
  347. * @param[in] nMinus1
  348. * Number of DMA transfer elements (minus 1) to transfer (<= 1023). The
  349. * size of the DMA transfer element (1, 2 or 4 bytes) is configured with
  350. * DMA_CfgDescr().
  351. ******************************************************************************/
  352. void DMA_ActivateAuto(unsigned int channel,
  353. bool primary,
  354. void *dst,
  355. void *src,
  356. unsigned int nMinus1)
  357. {
  358. uint32_t chBit;
  359. EFM_ASSERT(channel < DMA_CHAN_COUNT);
  360. EFM_ASSERT(nMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
  361. DMA_Prepare(channel,
  362. dmaCycleCtrlAuto,
  363. primary,
  364. false,
  365. dst,
  366. src,
  367. nMinus1);
  368. chBit = 1 << channel;
  369. DMA->CHENS = chBit; /* Enable channel */
  370. DMA->CHSWREQ = chBit; /* Activate with SW request */
  371. }
  372. /***************************************************************************//**
  373. * @brief
  374. * Activate DMA basic cycle (used for memory-peripheral transfers).
  375. *
  376. * @details
  377. * Prior to activating the DMA cycle, the channel and descriptor to be used
  378. * must have been properly configured.
  379. *
  380. * @note
  381. * If using this function on a channel already activated and in use by the
  382. * DMA controller, the behaviour is undefined.
  383. *
  384. * @param[in] channel
  385. * DMA channel to activate DMA cycle for.
  386. *
  387. * @param[in] primary
  388. * @li true - activate using primary descriptor
  389. * @li false - activate using alternate descriptor
  390. *
  391. * @param[in] useBurst
  392. * The burst feature is only used on peripherals supporting DMA bursts.
  393. * Bursts must not be used if the total length (as given by nMinus1) is
  394. * less than the arbitration rate configured for the descriptor. Please
  395. * refer to the reference manual for further details on burst usage.
  396. *
  397. * @param[in] dst
  398. * Address to start location to transfer data to. If NULL, leave setting in
  399. * descriptor as is from a previous activation.
  400. *
  401. * @param[in] src
  402. * Address to start location to transfer data from. If NULL, leave setting in
  403. * descriptor as is from a previous activation.
  404. *
  405. * @param[in] nMinus1
  406. * Number of DMA transfer elements (minus 1) to transfer (<= 1023). The
  407. * size of the DMA transfer element (1, 2 or 4 bytes) is configured with
  408. * DMA_CfgDescr().
  409. ******************************************************************************/
  410. void DMA_ActivateBasic(unsigned int channel,
  411. bool primary,
  412. bool useBurst,
  413. void *dst,
  414. void *src,
  415. unsigned int nMinus1)
  416. {
  417. EFM_ASSERT(channel < DMA_CHAN_COUNT);
  418. EFM_ASSERT(nMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
  419. DMA_Prepare(channel,
  420. dmaCycleCtrlBasic,
  421. primary,
  422. useBurst,
  423. dst,
  424. src,
  425. nMinus1);
  426. /* Enable channel, request signal is provided by peripheral device */
  427. DMA->CHENS = 1 << channel;
  428. }
  429. /***************************************************************************//**
  430. * @brief
  431. * Activate DMA ping-pong cycle (used for memory-peripheral transfers).
  432. *
  433. * @details
  434. * Prior to activating the DMA cycle, the channel and both descriptors must
  435. * have been properly configured. The primary descriptor is always the first
  436. * descriptor to be used by the DMA controller.
  437. *
  438. * @note
  439. * If using this function on a channel already activated and in use by the
  440. * DMA controller, the behaviour is undefined.
  441. *
  442. * @param[in] channel
  443. * DMA channel to activate DMA cycle for.
  444. *
  445. * @param[in] useBurst
  446. * The burst feature is only used on peripherals supporting DMA bursts.
  447. * Bursts must not be used if the total length (as given by nMinus1) is
  448. * less than the arbitration rate configured for the descriptors. Please
  449. * refer to the reference manual for further details on burst usage. Notice
  450. * that this setting is used for both the primary and alternate descriptors.
  451. *
  452. * @param[in] primDst
  453. * Address to start location to transfer data to, for primary descriptor.
  454. * If NULL, leave setting in descriptor as is from a previous activation.
  455. *
  456. * @param[in] primSrc
  457. * Address to start location to transfer data from, for primary descriptor.
  458. * If NULL, leave setting in descriptor as is from a previous activation.
  459. *
  460. * @param[in] primNMinus1
  461. * Number of DMA transfer elements (minus 1) to transfer (<= 1023), for
  462. * primary descriptor. The size of the DMA transfer element (1, 2 or 4 bytes)
  463. * is configured with DMA_CfgDescr().
  464. *
  465. * @param[in] altDst
  466. * Address to start location to transfer data to, for alternate descriptor.
  467. * If NULL, leave setting in descriptor as is from a previous activation.
  468. *
  469. * @param[in] altSrc
  470. * Address to start location to transfer data from, for alternate descriptor.
  471. * If NULL, leave setting in descriptor as is from a previous activation.
  472. *
  473. * @param[in] altNMinus1
  474. * Number of DMA transfer elements (minus 1) to transfer (<= 1023), for
  475. * alternate descriptor. The size of the DMA transfer element (1, 2 or 4 bytes)
  476. * is configured with DMA_CfgDescr().
  477. ******************************************************************************/
  478. void DMA_ActivatePingPong(unsigned int channel,
  479. bool useBurst,
  480. void *primDst,
  481. void *primSrc,
  482. unsigned int primNMinus1,
  483. void *altDst,
  484. void *altSrc,
  485. unsigned int altNMinus1)
  486. {
  487. EFM_ASSERT(channel < DMA_CHAN_COUNT);
  488. EFM_ASSERT(primNMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
  489. EFM_ASSERT(altNMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
  490. /* Prepare alternate descriptor first */
  491. DMA_Prepare(channel,
  492. dmaCycleCtrlPingPong,
  493. false,
  494. useBurst,
  495. altDst,
  496. altSrc,
  497. altNMinus1);
  498. /* Prepare primary descriptor last in order to start cycle using it */
  499. DMA_Prepare(channel,
  500. dmaCycleCtrlPingPong,
  501. true,
  502. useBurst,
  503. primDst,
  504. primSrc,
  505. primNMinus1);
  506. /* Enable channel, request signal is provided by peripheral device */
  507. DMA->CHENS = 1 << channel;
  508. }
  509. /***************************************************************************//**
  510. * @brief
  511. * Activate DMA scatter-gather cycle (used for either memory-peripheral
  512. * or memory-memory transfers).
  513. *
  514. * @details
  515. * Prior to activating the DMA cycle, the array with alternate descriptors
  516. * must have been properly configured. This function can be reused without
  517. * reconfiguring the alternate descriptors, as long as @p count is the same.
  518. *
  519. * @note
  520. * If using this function on a channel already activated and in use by the
  521. * DMA controller, the behaviour is undefined.
  522. *
  523. * @param[in] channel
  524. * DMA channel to activate DMA cycle for.
  525. *
  526. * @param[in] useBurst
  527. * The burst feature is only used on peripherals supporting DMA bursts
  528. * (and thus this parameter is ignored for memory scatter-gather cycles).
  529. * This parameter determines if bursts should be enabled during DMA transfers
  530. * using the alternate descriptors. Bursts must not be used if the total
  531. * length (as given by nMinus1 for the alternate descriptor) is
  532. * less than the arbitration rate configured for the descriptor. Please
  533. * refer to the reference manual for further details on burst usage.
  534. *
  535. * @param[in,out] altDescr
  536. * Pointer to start of array with prepared alternate descriptors. The last
  537. * descriptor will have its cycle control type reprogrammed to basic type.
  538. *
  539. * @param[in] count
  540. * Number of alternate descriptors in @p altDescr array. Maximum number of
  541. * alternate descriptors is 256.
  542. ******************************************************************************/
  543. void DMA_ActivateScatterGather(unsigned int channel,
  544. bool useBurst,
  545. DMA_DESCRIPTOR_TypeDef *altDescr,
  546. unsigned int count)
  547. {
  548. DMA_DESCRIPTOR_TypeDef *descr;
  549. DMA_CB_TypeDef *cb;
  550. uint32_t cycleCtrl;
  551. uint32_t chBit;
  552. EFM_ASSERT(channel < DMA_CHAN_COUNT);
  553. EFM_ASSERT(altDescr);
  554. EFM_ASSERT(count && (count <= 256));
  555. /* We have to configure the primary descriptor properly in order to */
  556. /* transfer one complete alternate descriptor from the alternate */
  557. /* descriptor table into the actual alternate descriptor. */
  558. descr = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE) + channel;
  559. /* Set source end address to point to alternate descriptor array */
  560. descr->SRCEND = (uint32_t *)altDescr + (count * 4) - 1;
  561. /* The destination end address in the primary descriptor MUST point */
  562. /* to the corresponding alternate descriptor in scatter-gather mode. */
  563. descr->DSTEND = (uint32_t *)((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE) +
  564. channel + 1) - 1;
  565. /* The user field of the descriptor is used for callback configuration, */
  566. /* and already configured when channel is configured. Do not modify it. */
  567. /* Determine from alternate configuration whether this is a memory or */
  568. /* peripheral scatter-gather, by looking at the first alternate descriptor. */
  569. cycleCtrl = altDescr->CTRL & _DMA_CTRL_CYCLE_CTRL_MASK;
  570. cycleCtrl &= ~(1 << _DMA_CTRL_CYCLE_CTRL_SHIFT);
  571. EFM_ASSERT((cycleCtrl == dmaCycleCtrlMemScatterGather) ||
  572. (cycleCtrl == dmaCycleCtrlPerScatterGather));
  573. /* Set last alternate descriptor to basic or auto-request cycle type in */
  574. /* order to have dma_done signal asserted when complete. Otherwise interrupt */
  575. /* will not be triggered when done. */
  576. altDescr[count - 1].CTRL &= ~_DMA_CTRL_CYCLE_CTRL_MASK;
  577. if (cycleCtrl == dmaCycleCtrlMemScatterGather)
  578. {
  579. altDescr[count - 1].CTRL |= (uint32_t)dmaCycleCtrlAuto << _DMA_CTRL_CYCLE_CTRL_SHIFT;
  580. }
  581. else
  582. {
  583. altDescr[count - 1].CTRL |= (uint32_t)dmaCycleCtrlBasic << _DMA_CTRL_CYCLE_CTRL_SHIFT;
  584. }
  585. /* If callback defined, update info on whether callback is issued for */
  586. /* primary or alternate descriptor. Not really useful for scatter-gather, */
  587. /* but do for consistency. Always set to alternate, since that is the last */
  588. /* descriptor actually used. */
  589. cb = (DMA_CB_TypeDef *)(descr->USER);
  590. if (cb)
  591. {
  592. cb->primary = false;
  593. }
  594. /* Configure primary descriptor control word */
  595. descr->CTRL =
  596. ((uint32_t)dmaDataInc4 << _DMA_CTRL_DST_INC_SHIFT) |
  597. ((uint32_t)dmaDataSize4 << _DMA_CTRL_DST_SIZE_SHIFT) |
  598. ((uint32_t)dmaDataInc4 << _DMA_CTRL_SRC_INC_SHIFT) |
  599. ((uint32_t)dmaDataSize4 << _DMA_CTRL_SRC_SIZE_SHIFT) |
  600. /* Use same protection scheme as for alternate descriptors */
  601. (altDescr->CTRL & _DMA_CTRL_SRC_PROT_CTRL_MASK) |
  602. ((uint32_t)dmaArbitrate4 << _DMA_CTRL_R_POWER_SHIFT) |
  603. (((count * 4) - 1) << _DMA_CTRL_N_MINUS_1_SHIFT) |
  604. (((uint32_t)useBurst & 1) << _DMA_CTRL_NEXT_USEBURST_SHIFT) |
  605. cycleCtrl;
  606. chBit = 1 << channel;
  607. /* Start with primary descriptor */
  608. DMA->CHALTC = chBit;
  609. /* Enable channel */
  610. DMA->CHENS = chBit;
  611. /* Send request if memory scatter-gather, otherwise request signal is */
  612. /* provided by peripheral. */
  613. if (cycleCtrl == dmaCycleCtrlMemScatterGather)
  614. {
  615. DMA->CHSWREQ = chBit;
  616. }
  617. }
  618. /***************************************************************************//**
  619. * @brief
  620. * Configure a DMA channel.
  621. *
  622. * @details
  623. * Configure miscellaneous issues for a DMA channel. This function is typically
  624. * used once to setup a channel for a certain type of use.
  625. *
  626. * @note
  627. * If using this function on a channel already in use by the DMA controller,
  628. * the behaviour is undefined.
  629. *
  630. * @param[in] channel
  631. * DMA channel to configure.
  632. *
  633. * @param[in] cfg
  634. * Configuration to use.
  635. ******************************************************************************/
  636. void DMA_CfgChannel(unsigned int channel, DMA_CfgChannel_TypeDef *cfg)
  637. {
  638. DMA_DESCRIPTOR_TypeDef *descr;
  639. EFM_ASSERT(channel < DMA_CHAN_COUNT);
  640. EFM_ASSERT(cfg);
  641. /* Always keep callback configuration reference in primary descriptor */
  642. descr = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE);
  643. descr[channel].USER = (uint32_t)(cfg->cb);
  644. /* Set to specified priority for channel */
  645. if (cfg->highPri)
  646. {
  647. DMA->CHPRIS = 1 << channel;
  648. }
  649. else
  650. {
  651. DMA->CHPRIC = 1 << channel;
  652. }
  653. /* Set DMA signal source select */
  654. DMA->CH[channel].CTRL = cfg->select;
  655. /* Enable/disable interrupt as specified */
  656. if (cfg->enableInt)
  657. {
  658. DMA->IFC = (1 << channel);
  659. BITBAND_Peripheral(&(DMA->IEN), channel, 1);
  660. }
  661. else
  662. {
  663. BITBAND_Peripheral(&(DMA->IEN), channel, 0);
  664. }
  665. }
  666. /***************************************************************************//**
  667. * @brief
  668. * Configure DMA descriptor for auto-request, basic or ping-pong DMA cycles.
  669. *
  670. * @details
  671. * This function is used for configuration of a descriptor for the following
  672. * DMA cycle types:
  673. *
  674. * @li auto-request - used for memory/memory transfer
  675. * @li basic - used for a peripheral/memory transfer
  676. * @li ping-pong - used for a ping-pong based peripheral/memory transfer
  677. * style providing time to refresh one descriptor while the other is
  678. * in use.
  679. *
  680. * The DMA cycle is not activated, please see DMA_ActivateAuto(),
  681. * DMA_ActivateBasic() or DMA_ActivatePingPong() to activate the DMA cycle.
  682. * In many cases, the configuration only has to be done once, and all
  683. * subsequent cycles may be activated with the activate function.
  684. *
  685. * For ping-pong DMA cycles, this function must be used both on the primary
  686. * and the alternate descriptor prior to activating the DMA cycle.
  687. *
  688. * Notice that the DMA channel must also be configured, see DMA_CfgChannel().
  689. *
  690. * @note
  691. * If using this function on a descriptor already activated and in use by
  692. * the DMA controller, the behaviour is undefined.
  693. *
  694. * @param[in] channel
  695. * DMA channel to configure for.
  696. *
  697. * @param[in] primary
  698. * @li true - configure primary descriptor
  699. * @li false - configure alternate descriptor
  700. *
  701. * @param[in] cfg
  702. * Configuration to use.
  703. ******************************************************************************/
  704. void DMA_CfgDescr(unsigned int channel,
  705. bool primary,
  706. DMA_CfgDescr_TypeDef *cfg)
  707. {
  708. DMA_DESCRIPTOR_TypeDef *descr;
  709. EFM_ASSERT(channel < DMA_CHAN_COUNT);
  710. EFM_ASSERT(cfg);
  711. /* Find descriptor to configure */
  712. if (primary)
  713. {
  714. descr = (DMA_DESCRIPTOR_TypeDef *)DMA->CTRLBASE;
  715. }
  716. else
  717. {
  718. descr = (DMA_DESCRIPTOR_TypeDef *)DMA->ALTCTRLBASE;
  719. }
  720. descr += channel;
  721. /* Prepare the descriptor */
  722. /* Source/destination end addresses set when started */
  723. descr->CTRL =
  724. (cfg->dstInc << _DMA_CTRL_DST_INC_SHIFT) |
  725. (cfg->size << _DMA_CTRL_DST_SIZE_SHIFT) |
  726. (cfg->srcInc << _DMA_CTRL_SRC_INC_SHIFT) |
  727. (cfg->size << _DMA_CTRL_SRC_SIZE_SHIFT) |
  728. ((uint32_t)(cfg->hprot) << _DMA_CTRL_SRC_PROT_CTRL_SHIFT) |
  729. (cfg->arbRate << _DMA_CTRL_R_POWER_SHIFT) |
  730. (0 << _DMA_CTRL_N_MINUS_1_SHIFT) | /* Set when activated */
  731. (0 << _DMA_CTRL_NEXT_USEBURST_SHIFT) | /* Set when activated */
  732. DMA_CTRL_CYCLE_CTRL_INVALID; /* Set when activated */
  733. }
  734. #if defined(_EFM32_GIANT_FAMILY)
  735. /***************************************************************************//**
  736. * @brief Configure DMA channel for Loop mode or 2D transfer.
  737. *
  738. * @details
  739. * For 2D transfer, set cfg->enable to "false", and only configure nMinus1
  740. * to same width as channel descriptor.
  741. *
  742. * @param[in] channel
  743. * DMA channel to configure for.
  744. *
  745. * @param[in] cfg
  746. * Configuration to use.
  747. ******************************************************************************/
  748. void DMA_CfgLoop(unsigned int channel, DMA_CfgLoop_TypeDef *cfg)
  749. {
  750. EFM_ASSERT(channel <= 1);
  751. EFM_ASSERT(cfg->nMinus1 <= 1023);
  752. /* Configure LOOP setting */
  753. switch( channel )
  754. {
  755. case 0:
  756. DMA->LOOP0 = (cfg->enable << _DMA_LOOP0_EN_SHIFT|
  757. cfg->nMinus1 << _DMA_LOOP0_WIDTH_SHIFT);
  758. break;
  759. case 1:
  760. DMA->LOOP1 = (cfg->enable << _DMA_LOOP1_EN_SHIFT|
  761. cfg->nMinus1 << _DMA_LOOP1_WIDTH_SHIFT);
  762. break;
  763. }
  764. }
  765. /***************************************************************************//**
  766. * @brief Configure DMA channel 2D transfer properties.
  767. *
  768. * @param[in] channel
  769. * DMA channel to configure for.
  770. *
  771. * @param[in] cfg
  772. * Configuration to use.
  773. ******************************************************************************/
  774. void DMA_CfgRect(unsigned int channel, DMA_CfgRect_TypeDef *cfg)
  775. {
  776. EFM_ASSERT(channel == 0);
  777. EFM_ASSERT(cfg->dstStride <= 2047);
  778. EFM_ASSERT(cfg->srcStride <= 2047);
  779. EFM_ASSERT(cfg->height <= 1023);
  780. /* Configure rectangular/2D copy */
  781. DMA->RECT0 = (cfg->dstStride << _DMA_RECT0_DSTSTRIDE_SHIFT|
  782. cfg->srcStride << _DMA_RECT0_SRCSTRIDE_SHIFT|
  783. cfg->height << _DMA_RECT0_HEIGHT_SHIFT);
  784. }
  785. #endif
  786. /***************************************************************************//**
  787. * @brief
  788. * Configure an alternate DMA descriptor for use with scatter-gather DMA
  789. * cycles.
  790. *
  791. * @details
  792. * In scatter-gather mode, the alternate descriptors are located in one
  793. * contiguous memory area. Each of the alternate descriptor must be fully
  794. * configured prior to starting the scatter-gather DMA cycle.
  795. *
  796. * The DMA cycle is not activated by this function, please see
  797. * DMA_ActivateScatterGather() to activate the DMA cycle. In some cases, the
  798. * alternate configuration only has to be done once, and all subsequent
  799. * transfers may be activated with the activate function.
  800. *
  801. * Notice that the DMA channel must also be configured, see DMA_CfgChannel().
  802. *
  803. * @param[in] descr
  804. * Points to start of memory area holding the alternate descriptors.
  805. *
  806. * @param[in] indx
  807. * Alternate descriptor index number to configure (numbered from 0).
  808. *
  809. * @param[in] cfg
  810. * Configuration to use.
  811. ******************************************************************************/
  812. void DMA_CfgDescrScatterGather(DMA_DESCRIPTOR_TypeDef *descr,
  813. unsigned int indx,
  814. DMA_CfgDescrSGAlt_TypeDef *cfg)
  815. {
  816. uint32_t cycleCtrl;
  817. EFM_ASSERT(descr);
  818. EFM_ASSERT(cfg);
  819. /* Point to selected entry in alternate descriptor table */
  820. descr += indx;
  821. if (cfg->srcInc == dmaDataIncNone)
  822. {
  823. descr->SRCEND = cfg->src;
  824. }
  825. else
  826. {
  827. descr->SRCEND = (void *)((uint32_t)(cfg->src) + ((uint32_t)(cfg->nMinus1) << cfg->srcInc));
  828. }
  829. if (cfg->dstInc == dmaDataIncNone)
  830. {
  831. descr->DSTEND = cfg->dst;
  832. }
  833. else
  834. {
  835. descr->DSTEND = (void *)((uint32_t)(cfg->dst) + ((uint32_t)(cfg->nMinus1) << cfg->dstInc));
  836. }
  837. /* User definable part not used */
  838. descr->USER = 0;
  839. if (cfg->peripheral)
  840. {
  841. cycleCtrl = (uint32_t)dmaCycleCtrlPerScatterGather + 1;
  842. }
  843. else
  844. {
  845. cycleCtrl = (uint32_t)dmaCycleCtrlMemScatterGather + 1;
  846. }
  847. descr->CTRL =
  848. (cfg->dstInc << _DMA_CTRL_DST_INC_SHIFT) |
  849. (cfg->size << _DMA_CTRL_DST_SIZE_SHIFT) |
  850. (cfg->srcInc << _DMA_CTRL_SRC_INC_SHIFT) |
  851. (cfg->size << _DMA_CTRL_SRC_SIZE_SHIFT) |
  852. ((uint32_t)(cfg->hprot) << _DMA_CTRL_SRC_PROT_CTRL_SHIFT) |
  853. (cfg->arbRate << _DMA_CTRL_R_POWER_SHIFT) |
  854. ((uint32_t)(cfg->nMinus1) << _DMA_CTRL_N_MINUS_1_SHIFT) |
  855. /* Never set next useburst bit, since the descriptor used after the */
  856. /* alternate descriptor is the primary descriptor which operates on */
  857. /* memory. If the alternate descriptors need to have useBurst set, this */
  858. /* done when setting up the primary descriptor, ie when activating. */
  859. (0 << _DMA_CTRL_NEXT_USEBURST_SHIFT) |
  860. (cycleCtrl << _DMA_CTRL_CYCLE_CTRL_SHIFT);
  861. }
  862. /***************************************************************************//**
  863. * @brief
  864. * Check if DMA channel is enabled.
  865. *
  866. * @details
  867. * The DMA channel is disabled when the DMA controller has finished a DMA
  868. * cycle.
  869. *
  870. * @param[in] channel
  871. * DMA channel to check.
  872. *
  873. * @return
  874. * true if channel is enabled, false if not.
  875. ******************************************************************************/
  876. bool DMA_ChannelEnabled(unsigned int channel)
  877. {
  878. EFM_ASSERT(channel < DMA_CHAN_COUNT);
  879. return (bool)((DMA->CHENS >> channel) & 1);
  880. }
  881. /***************************************************************************//**
  882. * @brief
  883. * Initializes DMA controller.
  884. *
  885. * @details
  886. * This function will reset and prepare the DMA controller for use. Although
  887. * it may be used several times, it is normally only used during system
  888. * init. If reused during normal operation, notice that any ongoing DMA
  889. * transfers will be aborted. When completed, the DMA controller is in
  890. * an enabled state.
  891. *
  892. * @note
  893. * Must be invoked before using the DMA controller.
  894. *
  895. * @param[in] init
  896. * Pointer to a structure containing DMA init information.
  897. ******************************************************************************/
  898. void DMA_Init(DMA_Init_TypeDef *init)
  899. {
  900. EFM_ASSERT(init);
  901. /* Make sure control block is properly aligned */
  902. EFM_ASSERT(!((uint32_t)(init->controlBlock) & (256 - 1)));
  903. /* Make sure DMA clock is enabled prior to accessing DMA module */
  904. CMU_ClockEnable(cmuClock_DMA, true);
  905. /* Make sure DMA controller is set to a known reset state */
  906. DMA_Reset();
  907. /* Clear/enable DMA interrupts */
  908. NVIC_ClearPendingIRQ(DMA_IRQn);
  909. NVIC_EnableIRQ(DMA_IRQn);
  910. /* Enable bus error interrupt */
  911. DMA->IEN = DMA_IEN_ERR;
  912. /* Set pointer to control block, notice that this ptr must have been */
  913. /* properly aligned, according to requirements defined in the reference */
  914. /* manual. */
  915. DMA->CTRLBASE = (uint32_t)(init->controlBlock);
  916. /* Configure and enable the DMA controller */
  917. DMA->CONFIG = ((uint32_t)(init->hprot) << _DMA_CONFIG_CHPROT_SHIFT) | DMA_CONFIG_EN;
  918. }
  919. /***************************************************************************//**
  920. * @brief
  921. * Refresh a descriptor used in a DMA ping-pong cycle.
  922. *
  923. * @details
  924. * During a ping-pong DMA cycle, the DMA controller automatically alternates
  925. * between primary and alternate descriptors, when completing use of a
  926. * descriptor. While the other descriptor is in use by the DMA controller,
  927. * the SW should refresh the completed descriptor. This is typically done from
  928. * the callback defined for the ping-pong cycle.
  929. *
  930. * @param[in] channel
  931. * DMA channel to refresh ping-pong descriptor for.
  932. *
  933. * @param[in] primary
  934. * @li true - refresh primary descriptor
  935. * @li false - refresh alternate descriptor
  936. *
  937. * @param[in] useBurst
  938. * The burst feature is only used on peripherals supporting DMA bursts.
  939. * Bursts must not be used if the total length (as given by nMinus1) is
  940. * less than the arbitration rate configured for the descriptor. Please
  941. * refer to the reference manual for further details on burst usage.
  942. *
  943. * @param[in] dst
  944. * Address to start location to transfer data to. If NULL, leave setting in
  945. * descriptor as is.
  946. *
  947. * @param[in] src
  948. * Address to start location to transfer data from. If NULL, leave setting in
  949. * descriptor as is.
  950. *
  951. * @param[in] nMinus1
  952. * Number of DMA transfer elements (minus 1) to transfer (<= 1023). The
  953. * size of the DMA transfer element (1, 2 or 4 bytes) is configured with
  954. * DMA_CfgDescr().
  955. *
  956. * @param[in] stop
  957. * Indicate that the DMA ping-pong cycle shall stop @b after completing use
  958. * of this descriptor.
  959. ******************************************************************************/
  960. void DMA_RefreshPingPong(unsigned int channel,
  961. bool primary,
  962. bool useBurst,
  963. void *dst,
  964. void *src,
  965. unsigned int nMinus1,
  966. bool stop)
  967. {
  968. DMA_CycleCtrl_TypeDef cycleCtrl;
  969. DMA_DESCRIPTOR_TypeDef *descr;
  970. uint32_t inc;
  971. uint32_t chBit;
  972. uint32_t tmp;
  973. EFM_ASSERT(channel < DMA_CHAN_COUNT);
  974. EFM_ASSERT(nMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
  975. /* The ping-pong DMA cycle may be stopped by issuing a basic cycle type */
  976. if (stop)
  977. {
  978. cycleCtrl = dmaCycleCtrlBasic;
  979. }
  980. else
  981. {
  982. cycleCtrl = dmaCycleCtrlPingPong;
  983. }
  984. /* Find descriptor to configure */
  985. if (primary)
  986. {
  987. descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE)) + channel;
  988. }
  989. else
  990. {
  991. descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE)) + channel;
  992. }
  993. if (src)
  994. {
  995. inc = (descr->CTRL & _DMA_CTRL_SRC_INC_MASK) >> _DMA_CTRL_SRC_INC_SHIFT;
  996. if (inc == _DMA_CTRL_SRC_INC_NONE)
  997. {
  998. descr->SRCEND = src;
  999. }
  1000. else
  1001. {
  1002. descr->SRCEND = (void *)((uint32_t)src + (nMinus1 << inc));
  1003. }
  1004. }
  1005. if (dst)
  1006. {
  1007. inc = (descr->CTRL & _DMA_CTRL_DST_INC_MASK) >> _DMA_CTRL_DST_INC_SHIFT;
  1008. if (inc == _DMA_CTRL_DST_INC_NONE)
  1009. {
  1010. descr->DSTEND = dst;
  1011. }
  1012. else
  1013. {
  1014. descr->DSTEND = (void *)((uint32_t)dst + (nMinus1 << inc));
  1015. }
  1016. }
  1017. chBit = 1 << channel;
  1018. if (useBurst)
  1019. {
  1020. DMA->CHUSEBURSTS = chBit;
  1021. }
  1022. else
  1023. {
  1024. DMA->CHUSEBURSTC = chBit;
  1025. }
  1026. /* Set cycle control */
  1027. tmp = descr->CTRL & ~(_DMA_CTRL_CYCLE_CTRL_MASK | _DMA_CTRL_N_MINUS_1_MASK);
  1028. tmp |= nMinus1 << _DMA_CTRL_N_MINUS_1_SHIFT;
  1029. tmp |= cycleCtrl << _DMA_CTRL_CYCLE_CTRL_SHIFT;
  1030. descr->CTRL = tmp;
  1031. }
  1032. /***************************************************************************//**
  1033. * @brief
  1034. * Reset the DMA controller.
  1035. *
  1036. * @details
  1037. * This functions will disable the DMA controller and set it to a reset
  1038. * state.
  1039. *
  1040. * @note
  1041. * Notice that any ongoing transfers will be aborted.
  1042. ******************************************************************************/
  1043. void DMA_Reset(void)
  1044. {
  1045. int i;
  1046. /* Disable DMA interrupts */
  1047. NVIC_DisableIRQ(DMA_IRQn);
  1048. /* Put the DMA controller into a known state, first disabling it. */
  1049. DMA->CONFIG = _DMA_CONFIG_RESETVALUE;
  1050. DMA->CHUSEBURSTC = _DMA_CHUSEBURSTC_MASK;
  1051. DMA->CHREQMASKC = _DMA_CHREQMASKC_MASK;
  1052. DMA->CHENC = _DMA_CHENC_MASK;
  1053. DMA->CHALTC = _DMA_CHALTC_MASK;
  1054. DMA->CHPRIC = _DMA_CHPRIC_MASK;
  1055. DMA->ERRORC = DMA_ERRORC_ERRORC;
  1056. DMA->IEN = _DMA_IEN_RESETVALUE;
  1057. DMA->IFC = _DMA_IFC_MASK;
  1058. /* Clear channel control flags */
  1059. for (i = 0; i < DMA_CHAN_COUNT; i++)
  1060. {
  1061. DMA->CH[i].CTRL = _DMA_CH_CTRL_RESETVALUE;
  1062. }
  1063. }
  1064. /** @} (end addtogroup DMA) */
  1065. /** @} (end addtogroup EM_Library) */