stm32f1_dma.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * Copyright (C) 2010 by Ulrich Prinz (uprinz2@netscape.net)
  3. * Copyright (C) 2010 by Nikolaj Zamotaev. 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. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the copyright holders nor the names of
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  22. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  24. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  25. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  26. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  28. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. *
  31. * For additional information see http://www.ethernut.de/
  32. *
  33. */
  34. /*
  35. * \verbatim
  36. * $Id: stm32f1_dma.c 5548 2014-01-15 16:21:10Z u_bonnes $
  37. * \endverbatim
  38. */
  39. #include <cfg/arch.h>
  40. #include <arch/cm3.h>
  41. #include <dev/irqreg.h>
  42. #include <arch/cm3/stm/stm32xxxx.h>
  43. #include <arch/cm3/stm/stm32_dma.h>
  44. /*!
  45. * \brief Table to align channels and interrupts for simpler access
  46. */
  47. const DMATAB DmaTab[] = {
  48. { DMA1_BASE, 0, DMA1_Channel1 },
  49. { DMA1_BASE, 4, DMA1_Channel2 },
  50. { DMA1_BASE, 8, DMA1_Channel3 },
  51. { DMA1_BASE, 12, DMA1_Channel4 },
  52. { DMA1_BASE, 16, DMA1_Channel5 },
  53. { DMA1_BASE, 20, DMA1_Channel6 },
  54. { DMA1_BASE, 24, DMA1_Channel7 },
  55. #if defined(STM32F10X_HD) || defined(STM32F10X_XL)
  56. { DMA2_BASE, 0, DMA2_Channel1 },
  57. { DMA2_BASE, 4, DMA2_Channel2 },
  58. { DMA2_BASE, 8, DMA2_Channel3 },
  59. /* These chips have one IRQ for ch. 4 & 5 */
  60. { DMA2_BASE, 12, DMA2_Channel4 },
  61. { DMA2_BASE, 16, DMA2_Channel4 },
  62. #endif
  63. #if defined(HW_DMA2_STM32F1)
  64. { DMA2_BASE, 0, DMA2_Channel1 },
  65. { DMA2_BASE, 4, DMA2_Channel2 },
  66. { DMA2_BASE, 8, DMA2_Channel3 },
  67. { DMA2_BASE, 12, DMA2_Channel4 },
  68. { DMA2_BASE, 16, DMA2_Channel5 },
  69. #endif
  70. };
  71. const uint8_t DMACount = sizeof(DmaTab)/sizeof(DMATAB);
  72. /*
  73. * Tricky but simple, small and fast
  74. */
  75. const DMATAB *DmaTab1 = &DmaTab[0];
  76. #ifdef STM_HAS_DMA2
  77. const DMATAB *DmaTab2 = &DmaTab[STM_HAS_DMA1];
  78. #endif
  79. /*
  80. * \brief DMA Transfer Setup Function.
  81. *
  82. * This function sets up a DMA transfer. This function automatically
  83. * detects the transfer direction and if sources or targets are memory
  84. * or peripherals and sets up the right flags.
  85. *
  86. * \param channel One of the available channels of the STM32. If used
  87. * with peripherals, check to use the correct channel for the
  88. * desired peripheral unit.
  89. * \param dst Destination where to send the data to. Can be memory or peripheral.
  90. * \param src Source to take the data from. Can be memory or peripheral.
  91. * \param flags Option flags for priority and autoincrement of memory or peripheral.
  92. *
  93. */
  94. void DMA_Setup( uint8_t ch, void* dst, void* src, uint16_t length, uint32_t flags)
  95. {
  96. DMA_Channel_TypeDef* channel = DmaTab[ch].dma_ch;
  97. uint32_t cc = flags & ~(DMA_CCR_MEM2MEM|DMA_CCR_DIR|DMA_CCR_EN);
  98. uint32_t cp;
  99. uint32_t cm;
  100. /* Stop DMA channel */
  101. channel->CCR = cc;
  102. /* Detect transfer type and set Registers accordingly */
  103. if ((uint32_t)src & PERIPH_BASE) {
  104. /* Peripheral to Memory */
  105. cp=(uint32_t)src;
  106. cm=(uint32_t)dst;
  107. }
  108. else if ((uint32_t)dst & PERIPH_BASE) {
  109. /* Memory to Peripheral */
  110. cc |= DMA_CCR_DIR;
  111. cp=(uint32_t)dst;
  112. cm=(uint32_t)src;
  113. }
  114. else {
  115. /* Memory to Memory Transfer */
  116. cc |= DMA_CCR_MEM2MEM | DMA_CCR_DIR;
  117. cp =(uint32_t)dst;
  118. cm =(uint32_t)dst;
  119. }
  120. channel->CCR=cc;
  121. channel->CNDTR=length;
  122. channel->CPAR=cp;
  123. channel->CMAR=cm;
  124. };
  125. /*
  126. * \brief Enable DMA Transfer.
  127. */
  128. void DMA_Enable(uint8_t ch)
  129. {
  130. DMA_Channel_TypeDef *channel = (DMA_Channel_TypeDef*)DmaTab[ch].dma_ch;
  131. channel->CCR |= DMA_CCR_EN;
  132. }
  133. /*
  134. * \brief Disable DMA Transfer.
  135. */
  136. void DMA_Disable(uint8_t ch)
  137. {
  138. DMA_Channel_TypeDef *channel = (DMA_Channel_TypeDef*)DmaTab[ch].dma_ch;
  139. channel->CCR &= ~DMA_CCR_EN;
  140. }
  141. /*!
  142. * \brief DMA System Initialization
  143. *
  144. * Register all DMA interrupt handlers.
  145. */
  146. void DMA_Init(void)
  147. {
  148. uint8_t i;
  149. DMA_Channel_TypeDef *channel;
  150. if ((RCC->AHBENR & RCC_AHBENR_DMA1EN ) == 0) {
  151. /* Enable DMA clocks */
  152. RCC->AHBENR |= RCC_AHBENR_DMA1EN;
  153. /* Clear pending interrupts in DMA 1 ISR */
  154. DMA1->IFCR = 0xFFFFFFFF;
  155. /* Clear interrupt related flags in channels */
  156. for(i=0; i<STM_HAS_DMA1; i++) {
  157. channel = (DMA_Channel_TypeDef*)DmaTab1[i].dma_ch;
  158. channel->CCR = 0;
  159. DMA_ClearFlag(i,0xf);
  160. }
  161. }
  162. /* FIXME: The ST defined headers don't define RCC_AHBENR_DMA2EN for XL
  163. * devices, but RM0008 says that XL devices have DMA2
  164. * Assume no DMA2 for XL devices for now
  165. */
  166. #if defined(STM_HAS_DMA2) && defined(RCC_AHBENR_DMA2EN)
  167. if ((RCC->AHBENR & RCC_AHBENR_DMA2EN ) == 0) {
  168. RCC->AHBENR |= RCC_AHBENR_DMA2EN;
  169. /* Clear pending interrupts in DMA 2 ISR */
  170. DMA2->IFCR = 0xFFFFFFFF;
  171. /* Clear interrupt related flags in channels */
  172. for(i=0;i<STM_HAS_DMA2;i++) {
  173. channel = (DMA_Channel_TypeDef*)DmaTab2[i].dma_ch;
  174. channel->CCR = 0;
  175. DMA_ClearFlag(i,0xf);
  176. }
  177. }
  178. #endif
  179. }
  180. /*!
  181. * \brief Control DMA channel interrupt masks
  182. *
  183. * Setup interrupt mask on given channel. Channel numbers are
  184. * from 0..n while documentation numbers them from 1..n.
  185. * For that please use the defines DMAx_Cn.
  186. *
  187. * \param ch Channel number to set interrupt mask.
  188. * \param mask Mask to set on the designated channel interrupts.
  189. * \param ena Enable (1) or Disable (0) the bits in the mask.
  190. */
  191. void DMA_IrqMask( uint8_t ch, uint32_t mask, uint8_t ena)
  192. {
  193. DMA_Channel_TypeDef *channel = (DMA_Channel_TypeDef*)DmaTab[ch].dma_ch;
  194. uint32_t ccr = channel->CCR;
  195. DMA_TypeDef *dma = (DMA_TypeDef*)DmaTab[ch].dma;
  196. uint32_t msk = mask & DMA_FLAGMASK;
  197. if( ena) {
  198. /* Enable some/all of the DMA channels interrupts */
  199. ccr |= msk;
  200. }
  201. else {
  202. /* Disable some/all of the DMA channels interrupts */
  203. ccr &= ~msk;
  204. }
  205. /* Set channel configuration */
  206. channel->CCR = ccr;
  207. /* Clear already pending flags */
  208. dma->IFCR = (mask << (DmaTab[ch].fofs));
  209. };
  210. /*!
  211. * \brief Clear DMA channel flags.
  212. *
  213. * Setup interrupt mask on given channel. Channel numbers are
  214. * from 0..n while documentation numbers them from 1..n.
  215. * For that please use the defines DMAx_Cn.
  216. *
  217. * \param ch Channel number.
  218. * \param flags Mask of flags to clear.
  219. */
  220. void DMA_ClearFlag( uint8_t ch, uint32_t flags)
  221. {
  222. volatile DMA_TypeDef *dma = (DMA_TypeDef*)DmaTab[ch].dma;
  223. uint32_t msk = (flags&DMA_FLAGMASK)<<DmaTab[ch].fofs;
  224. dma->IFCR = msk;
  225. }
  226. /*!
  227. * \brief Get DMA channel flags.
  228. *
  229. * Get interrupt / status flags of given channel.
  230. *
  231. * \param ch Channel number to set interrupt mask.
  232. *
  233. * \return flags Mask of flags to clear.
  234. */
  235. uint32_t DMA_GetFlag( uint8_t ch)
  236. {
  237. volatile DMA_TypeDef *dma = (DMA_TypeDef*)DmaTab[ch].dma;
  238. uint32_t flags = (dma->ISR>>DmaTab[ch].fofs)&DMA_FLAGMASK;
  239. return flags;
  240. }