stm32f2_dma.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*
  2. * Copyright (C) 2010 by Ulrich Prinz (uprinz2@netscape.net)
  3. * Copyright (C) 2010 by Nikolaj Zamotaev. All rights reserved.
  4. * Copyright (C) 2012 by Uwe Bonnes(bon@elektron.ikp.physik.tu-darmstadt.de)
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. 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. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
  23. * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. *
  34. */
  35. /*
  36. * \verbatim
  37. * $Id$
  38. * \endverbatim
  39. */
  40. /* Both F2 and F4 have 8 DMA streams with 8 requests per stream
  41. Only DMA2 can do Memory to memory transfers
  42. DMA/Controller(D), Stream(S) and Request(R) are encoded in one byte
  43. Byte 7 6 5 4 3 2 1 0
  44. D S2 S1 S0 0 R2 R1 R0
  45. */
  46. #include <cfg/arch.h>
  47. #include <arch/cm3.h>
  48. #include <dev/irqreg.h>
  49. #include <dev/gpio.h>
  50. #include <arch/cm3/stm/stm32xxxx.h>
  51. #include <arch/cm3/stm/stm32_dma.h>
  52. #define CH2NR(ch) ((ch & 0x70)>>4)
  53. #define CH2STREAM(base, ch) (base + 0x10 + ( CH2NR(ch) * 0x18))
  54. /*
  55. * \brief DMA Transfer Setup Function.
  56. *
  57. * This function sets up a DMA transfer. This function automatically
  58. * detects the transfer direction and if sources or targets are memory
  59. * or peripherals and sets up the right flags.
  60. *
  61. * \param channel One of the available channes of the STM32. If used
  62. * with peripherals, check to use the correct channel for the
  63. * desired peripheral unit.
  64. * \param dst Destination where to send the data to. Can be memory or peripheral.
  65. * \param src Source to take the data from. Can be memory or peripheral.
  66. * \param flags Option flags for priority and autoincrement of memory or peripheral.
  67. *
  68. */
  69. void DMA_Setup( uint8_t ch, void* dst, void* src, uint16_t length, uint32_t flags)
  70. {
  71. uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
  72. uint32_t stream_base = CH2STREAM(dma_base, ch);
  73. uint32_t cc = flags & ~(DMA_SxCR_CHSEL||DMA_SxCR_DIR|DMA_SxCR_EN);
  74. uint32_t cp;
  75. uint32_t cm;
  76. /* Clear all stream related flags */
  77. DMA_ClearFlag( ch, DMA_TEIF| DMA_HTIF| DMA_TCIF);
  78. cc |= (ch & 0x7)<<_BI32(DMA_SxCR_CHSEL_0);
  79. /* if DMA stream running, Stop DMA stream */
  80. if (CM3BBGET(stream_base, DMA_Stream_TypeDef,
  81. CR, _BI32(DMA_SxCR_EN)))
  82. {
  83. /* Disable stream */
  84. CM3BBCLR(stream_base, DMA_Stream_TypeDef, CR, _BI32(DMA_SxCR_EN));
  85. while(CM3BBGET(stream_base, DMA_Stream_TypeDef,
  86. CR, _BI32(DMA_SxCR_EN)));
  87. }
  88. /* Detect transfer type and set Registers accordingly */
  89. if ((uint32_t)src & PERIPH_BASE) {
  90. /* Peripheral to Memory */
  91. cp=(uint32_t)src;
  92. cm=(uint32_t)dst;
  93. }
  94. else if ((uint32_t)dst & PERIPH_BASE) {
  95. /* Memory to Peripheral */
  96. cc |= DMA_SxCR_DIR_0;
  97. cp=(uint32_t)dst;
  98. cm=(uint32_t)src;
  99. }
  100. else {
  101. /* Memory to Memory Transfer */
  102. cc |= DMA_SxCR_DIR_1;
  103. cp =(uint32_t)dst;
  104. cm =(uint32_t)dst;
  105. }
  106. CM3REG(stream_base, DMA_Stream_TypeDef, CR)=cc;
  107. CM3REG(stream_base, DMA_Stream_TypeDef, NDTR)=length;
  108. CM3REG(stream_base, DMA_Stream_TypeDef, PAR)=cp;
  109. CM3REG(stream_base, DMA_Stream_TypeDef, M0AR)=cm;
  110. };
  111. /*
  112. * \brief Enable DMA Transfer.
  113. */
  114. void DMA_Enable(uint8_t ch)
  115. {
  116. uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
  117. uint32_t stream_base = CH2STREAM(dma_base, ch);
  118. CM3BBSET(stream_base, DMA_Stream_TypeDef, CR, _BI32(DMA_SxCR_EN));
  119. }
  120. /*
  121. * \brief Disable DMA Transfer.
  122. */
  123. void DMA_Disable(uint8_t ch)
  124. {
  125. uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
  126. uint32_t stream_base = CH2STREAM(dma_base, ch);
  127. CM3BBCLR(stream_base, DMA_Stream_TypeDef, CR, _BI32(DMA_SxCR_EN));
  128. }
  129. /*!
  130. * \brief DMA System Initialization
  131. *
  132. * Register all DMA interrupt handlers.
  133. * Both DMA controllers are initialized separate
  134. */
  135. #if 0
  136. void DMA_Init(uint8_t ch)
  137. {
  138. uint8_t stream_nr = CH2NR(ch);
  139. uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
  140. if (ch < 0x80)
  141. {
  142. if (!(CM3BBGET(RCC_BASE, RCC_TypeDef, AHB1ENR,
  143. _BI32(RCC_AHB1ENR_DMA1EN ))))
  144. {
  145. /* Enable DMA1 Clock */
  146. CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA1EN ));
  147. /* Reset DMA1 */
  148. CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA1RST));
  149. CM3BBCLR(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA1RST));
  150. return;
  151. }
  152. }
  153. else if (!(CM3BBGET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA2EN ))))
  154. {
  155. /* Enable DMA2 Clock */
  156. CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA2EN ));
  157. /* Reset DMA2 */
  158. CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA2RST));
  159. CM3BBCLR(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA2RST));
  160. return;
  161. }
  162. switch (stream_nr)
  163. {
  164. case 0: CM3REG(dma_base, DMA_TypeDef, LIFCR) &= ~(DMA_LIFCR_CFEIF0|DMA_LIFCR_CDMEIF0|DMA_LIFCR_CTEIF0 |DMA_LIFCR_CHTIF0 |DMA_LIFCR_CTCIF0);
  165. break;
  166. case 1: CM3REG(dma_base, DMA_TypeDef, LIFCR) &= ~(DMA_LIFCR_CFEIF1|DMA_LIFCR_CDMEIF1|DMA_LIFCR_CTEIF1 |DMA_LIFCR_CHTIF1 |DMA_LIFCR_CTCIF1);
  167. break;
  168. case 2: CM3REG(dma_base, DMA_TypeDef, LIFCR) &= ~(DMA_LIFCR_CFEIF2|DMA_LIFCR_CDMEIF2|DMA_LIFCR_CTEIF2 |DMA_LIFCR_CHTIF2 |DMA_LIFCR_CTCIF2);
  169. break;
  170. case 3: CM3REG(dma_base, DMA_TypeDef, LIFCR) &= ~(DMA_LIFCR_CFEIF3|DMA_LIFCR_CDMEIF3|DMA_LIFCR_CTEIF3 |DMA_LIFCR_CHTIF3 |DMA_LIFCR_CTCIF3);
  171. break;
  172. case 4: CM3REG(dma_base, DMA_TypeDef, HIFCR) &= ~(DMA_HIFCR_CFEIF4|DMA_HIFCR_CDMEIF4|DMA_HIFCR_CTEIF4 |DMA_HIFCR_CHTIF4 |DMA_HIFCR_CTCIF4);
  173. break;
  174. case 5: CM3REG(dma_base, DMA_TypeDef, HIFCR) &= ~(DMA_HIFCR_CFEIF4|DMA_HIFCR_CDMEIF4|DMA_HIFCR_CTEIF4 |DMA_HIFCR_CHTIF4 |DMA_HIFCR_CTCIF4);
  175. break;
  176. case 6: CM3REG(dma_base, DMA_TypeDef, HIFCR) &= ~(DMA_HIFCR_CFEIF4|DMA_HIFCR_CDMEIF4|DMA_HIFCR_CTEIF4 |DMA_HIFCR_CHTIF4 |DMA_HIFCR_CTCIF4);
  177. break;
  178. case 7: CM3REG(dma_base, DMA_TypeDef, HIFCR) &= ~(DMA_HIFCR_CFEIF4|DMA_HIFCR_CDMEIF4|DMA_HIFCR_CTEIF4 |DMA_HIFCR_CHTIF4 |DMA_HIFCR_CTCIF4);
  179. break;
  180. }
  181. #else
  182. void DMA_Init(void)
  183. {
  184. if (!CM3BBGET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA1EN ))) {
  185. /* Enable DMA1 Clock */
  186. CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA1EN ));
  187. /* Reset DMA1 */
  188. CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA1RST));
  189. CM3BBCLR(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA1RST));
  190. }
  191. if (!CM3BBGET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA2EN ))) {
  192. /* Enable DMA2 Clock */
  193. CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1ENR, _BI32(RCC_AHB1ENR_DMA2EN ));
  194. /* Reset DMA2 */
  195. CM3BBSET(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA2RST));
  196. CM3BBCLR(RCC_BASE, RCC_TypeDef, AHB1RSTR, _BI32(RCC_AHB1RSTR_DMA2RST));
  197. }
  198. return;
  199. }
  200. #endif
  201. /*!
  202. * \brief Control DMA channel interrupt masks
  203. *
  204. * Setup interrupt mask on given channel. Channel numbers are
  205. * from 0..n while documentation numbers them from 1..n.
  206. * For that please use the defines DMAx_Cn.
  207. *
  208. * \param ch Channel number to set interrupt mask.
  209. * \param mask Mask to set on the designated channel interrupts.
  210. * \param ena Enable (1) or Disable (0) the bits in the mask.
  211. *
  212. * On F2/F4, Interrupt enable bits and interrupt clear flags don't correspond!
  213. * The Clear flags are arranged with sffereing spacing!
  214. */
  215. void DMA_IrqMask( uint8_t ch, uint32_t mask, uint8_t ena)
  216. {
  217. uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
  218. uint32_t stream_base = CH2STREAM(dma_base, ch);
  219. uint32_t en_dis_msk = 0, clr_msk = DMA_LIFCR_CFEIF0|DMA_LIFCR_CDMEIF0;
  220. if (mask & DMA_TCIF)
  221. {
  222. en_dis_msk |= DMA_SxCR_TCIE;
  223. clr_msk |= DMA_LIFCR_CTCIF0;
  224. }
  225. if (mask & DMA_HTIF)
  226. {
  227. en_dis_msk |= DMA_SxCR_HTIE;
  228. clr_msk |= DMA_LIFCR_CHTIF0;
  229. }
  230. if (mask & DMA_TEIF)
  231. {
  232. en_dis_msk |= DMA_SxCR_TEIE;
  233. clr_msk |= DMA_LIFCR_CTEIF0;
  234. }
  235. if (ena)
  236. CM3REG(stream_base, DMA_Stream_TypeDef, CR) |= en_dis_msk;
  237. else
  238. CM3REG(stream_base, DMA_Stream_TypeDef, CR) &= ~en_dis_msk;
  239. switch (CH2NR(ch))
  240. {
  241. case 0: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk; break;
  242. case 1: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk<<6; break;
  243. case 2: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk<<16; break;
  244. case 3: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk<<22; break;
  245. case 4: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk; break;
  246. case 5: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk<<6; break;
  247. case 6: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk<<16; break;
  248. case 7: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk<<22; break;
  249. }
  250. };
  251. /*!
  252. * \brief Clear DMA channel flags.
  253. *
  254. * \param ch Channel number.
  255. * \param flags Mask of flags to clear.
  256. */
  257. void DMA_ClearFlag( uint8_t ch, uint32_t flags)
  258. {
  259. uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
  260. uint32_t clr_msk = DMA_LIFCR_CFEIF0|DMA_LIFCR_CDMEIF0|DMA_LIFCR_CTEIF0;
  261. if (flags & DMA_TCIF) clr_msk |= DMA_LIFCR_CTCIF0;
  262. if (flags & DMA_HTIF) clr_msk |= DMA_LIFCR_CHTIF0;
  263. if (flags & DMA_TEIF) clr_msk |= DMA_LIFCR_CTEIF0;
  264. switch (CH2NR(ch))
  265. {
  266. case 0: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk; break;
  267. case 1: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk<<6; break;
  268. case 2: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk<<16; break;
  269. case 3: CM3REG(dma_base, DMA_TypeDef, LIFCR) |= clr_msk<<22; break;
  270. case 4: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk; break;
  271. case 5: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk<<6; break;
  272. case 6: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk<<16; break;
  273. case 7: CM3REG(dma_base, DMA_TypeDef, HIFCR) |= clr_msk<<22; break;
  274. }
  275. }
  276. /*!
  277. * \brief Get DMA channel flags.
  278. *
  279. * Get interrupt / status flags of given channel.
  280. *
  281. * \param ch Channel number to set interrupt mask.
  282. *
  283. * \return flags Mask of flags to clear.
  284. */
  285. uint32_t DMA_GetFlag( uint8_t ch)
  286. {
  287. uint32_t dma_base = (ch& 0x80)?DMA2_BASE:DMA1_BASE;
  288. uint32_t flags = 0, ret = 0;
  289. switch (CH2NR(ch))
  290. {
  291. case 0: flags = (CM3REG(dma_base, DMA_TypeDef, LISR) ) & 0x3d; break;
  292. case 1: flags = (CM3REG(dma_base, DMA_TypeDef, LISR)>> 6) & 0x3d; break;
  293. case 2: flags = (CM3REG(dma_base, DMA_TypeDef, LISR)>>16) & 0x3d; break;
  294. case 3: flags = (CM3REG(dma_base, DMA_TypeDef, LISR)>>22) & 0x3d; break;
  295. case 4: flags = (CM3REG(dma_base, DMA_TypeDef, HISR) ) & 0x3d; break;
  296. case 5: flags = (CM3REG(dma_base, DMA_TypeDef, HISR)>> 6) & 0x3d; break;
  297. case 6: flags = (CM3REG(dma_base, DMA_TypeDef, HISR)>>16) & 0x3d; break;
  298. case 7: flags = (CM3REG(dma_base, DMA_TypeDef, HISR)>>22) & 0x3d; break;
  299. }
  300. if (flags & DMA_LISR_TCIF0) ret |= DMA_TCIF;
  301. if (flags & DMA_LISR_HTIF0) ret |= DMA_HTIF;
  302. if (flags & DMA_LISR_TEIF0) ret |= DMA_TEIF;
  303. return ret;
  304. }