gd32f3x0_dma.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /*!
  2. \file gd32f3x0_dma.c
  3. \brief DMA driver
  4. */
  5. /*
  6. Copyright (C) 2017 GigaDevice
  7. 2017-06-06, V1.0.0, firmware for GD32F3x0
  8. */
  9. #include "gd32f3x0_dma.h"
  10. /*!
  11. \brief deinitialize DMA a channel registers
  12. \param[in] channelx: specify which DMA channel is deinitialized
  13. \arg DMA_CHx(x=0..6)
  14. \param[out] none
  15. \retval none
  16. */
  17. void dma_deinit(dma_channel_enum channelx)
  18. {
  19. /* disable DMA a channel */
  20. DMA_CHCTL(channelx) &= ~DMA_CHXCTL_CHEN;
  21. /* reset DMA channel registers */
  22. DMA_CHCTL(channelx) = DMA_CHCTL_RESET_VALUE;
  23. DMA_CHCNT(channelx) = DMA_CHCNT_RESET_VALUE;
  24. DMA_CHPADDR(channelx) = DMA_CHPADDR_RESET_VALUE;
  25. DMA_CHMADDR(channelx) = DMA_CHMADDR_RESET_VALUE;
  26. DMA_INTC |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx);
  27. }
  28. /*!
  29. \brief initialize DMA channel
  30. \param[in] channelx: specify which DMA channel is initialized
  31. \arg DMA_CHx(x=0..6)
  32. \param[in] init_struct: the data needed to initialize DMA channel
  33. periph_addr: peripheral base address
  34. periph_width: DMA_PERIPHERAL_WIDTH_8BIT,DMA_PERIPHERAL_WIDTH_16BIT,DMA_PERIPHERAL_WIDTH_32BIT
  35. periph_inc: DMA_PERIPH_INCREASE_ENABLE,DMA_PERIPH_INCREASE_DISABLE
  36. memory_addr: memory base address
  37. memory_width: DMA_MEMORY_WIDTH_8BIT,DMA_MEMORY_WIDTH_16BIT,DMA_MEMORY_WIDTH_32BIT
  38. memory_inc: DMA_MEMORY_INCREASE_ENABLE,DMA_MEMORY_INCREASE_DISABLE
  39. direction: DMA_PERIPHERAL_TO_MEMORY,DMA_MEMORY_TO_PERIPHERAL
  40. number: the number of remaining data to be transferred by the DMA
  41. priority: DMA_PRIORITY_LOW,DMA_PRIORITY_MEDIUM,DMA_PRIORITY_HIGH,DMA_PRIORITY_ULTRA_HIGH
  42. \param[out] none
  43. \retval none
  44. */
  45. void dma_init(dma_channel_enum channelx, dma_parameter_struct init_struct)
  46. {
  47. uint32_t ctl;
  48. dma_channel_disable(channelx);
  49. /* configure peripheral base address */
  50. DMA_CHPADDR(channelx) = init_struct.periph_addr;
  51. /* configure memory base address */
  52. DMA_CHMADDR(channelx) = init_struct.memory_addr;
  53. /* configure the number of remaining data to be transferred */
  54. DMA_CHCNT(channelx) = init_struct.number;
  55. /* configure peripheral transfer width,memory transfer width,channel priotity */
  56. ctl = DMA_CHCTL(channelx);
  57. ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO);
  58. ctl |= (init_struct.periph_width | init_struct.memory_width | init_struct.priority);
  59. DMA_CHCTL(channelx) = ctl;
  60. /* configure peripheral increasing mode */
  61. if(DMA_PERIPH_INCREASE_ENABLE == init_struct.periph_inc){
  62. DMA_CHCTL(channelx) |= DMA_CHXCTL_PNAGA;
  63. }else{
  64. DMA_CHCTL(channelx) &= ~DMA_CHXCTL_PNAGA;
  65. }
  66. /* configure memory increasing mode */
  67. if(DMA_MEMORY_INCREASE_ENABLE == init_struct.memory_inc){
  68. DMA_CHCTL(channelx) |= DMA_CHXCTL_MNAGA;
  69. }else{
  70. DMA_CHCTL(channelx) &= ~DMA_CHXCTL_MNAGA;
  71. }
  72. /* configure the direction of data transfer */
  73. if(DMA_PERIPHERAL_TO_MEMORY == init_struct.direction){
  74. DMA_CHCTL(channelx) &= ~DMA_CHXCTL_DIR;
  75. }else{
  76. DMA_CHCTL(channelx) |= DMA_CHXCTL_DIR;
  77. }
  78. }
  79. /*!
  80. \brief enable DMA circulation mode
  81. \param[in] channelx: specify which DMA channel
  82. \arg DMA_CHx(x=0..6)
  83. \param[out] none
  84. \retval none
  85. */
  86. void dma_circulation_enable(dma_channel_enum channelx)
  87. {
  88. DMA_CHCTL(channelx) |= DMA_CHXCTL_CMEN;
  89. }
  90. /*!
  91. \brief disable DMA circulation mode
  92. \param[in] channelx: specify which DMA channel
  93. \arg DMA_CHx(x=0..6)
  94. \param[out] none
  95. \retval none
  96. */
  97. void dma_circulation_disable(dma_channel_enum channelx)
  98. {
  99. DMA_CHCTL(channelx) &= ~DMA_CHXCTL_CMEN;
  100. }
  101. /*!
  102. \brief enable memory to memory mode
  103. \param[in] channelx: specify which DMA channel
  104. \arg DMA_CHx(x=0..6)
  105. \param[out] none
  106. \retval none
  107. */
  108. void dma_memory_to_memory_enable(dma_channel_enum channelx)
  109. {
  110. DMA_CHCTL(channelx) |= DMA_CHXCTL_M2M;
  111. }
  112. /*!
  113. \brief disable memory to memory mode
  114. \param[in] channelx: specify which DMA channel
  115. \arg DMA_CHx(x=0..6)
  116. \param[out] none
  117. \retval none
  118. */
  119. void dma_memory_to_memory_disable(dma_channel_enum channelx)
  120. {
  121. DMA_CHCTL(channelx) &= ~DMA_CHXCTL_M2M;
  122. }
  123. /*!
  124. \brief enable DMA channel
  125. \param[in] channelx: specify which DMA channel
  126. \arg DMA_CHx(x=0..6)
  127. \param[out] none
  128. \retval none
  129. */
  130. void dma_channel_enable(dma_channel_enum channelx)
  131. {
  132. DMA_CHCTL(channelx) |= DMA_CHXCTL_CHEN;
  133. }
  134. /*!
  135. \brief disable DMA channel
  136. \param[in] channelx: specify which DMA channel
  137. \arg DMA_CHx(x=0..6)
  138. \param[out] none
  139. \retval none
  140. */
  141. void dma_channel_disable(dma_channel_enum channelx)
  142. {
  143. DMA_CHCTL(channelx) &= ~DMA_CHXCTL_CHEN;
  144. }
  145. /*!
  146. \brief set DMA peripheral base address
  147. \param[in] channelx: specify which DMA channel to set peripheral base address
  148. \arg DMA_CHx(x=0..6)
  149. \param[in] address: peripheral base address
  150. \param[out] none
  151. \retval none
  152. */
  153. void dma_periph_address_config(dma_channel_enum channelx, uint32_t address)
  154. {
  155. DMA_CHPADDR(channelx) = address;
  156. }
  157. /*!
  158. \brief set DMA memory base address
  159. \param[in] channelx: specify which DMA channel to set memory base address
  160. \arg DMA_CHx(x=0..6)
  161. \param[in] address: memory base address
  162. \param[out] none
  163. \retval none
  164. */
  165. void dma_memory_address_config(dma_channel_enum channelx, uint32_t address)
  166. {
  167. DMA_CHMADDR(channelx) = address;
  168. }
  169. /*!
  170. \brief set the number of remaining data to be transferred by the DMA
  171. \param[in] channelx: specify which DMA channel to set number
  172. \arg DMA_CHx(x=0..6)
  173. \param[in] number: the number of remaining data to be transferred by the DMA
  174. \param[out] none
  175. \retval none
  176. */
  177. void dma_transfer_number_config(dma_channel_enum channelx, uint32_t number)
  178. {
  179. DMA_CHCNT(channelx) = (number & DMA_CHANNEL_CNT_MASK);
  180. }
  181. /*!
  182. \brief get the number of remaining data to be transferred by the DMA
  183. \param[in] channelx: specify which DMA channel to set number
  184. \arg DMA_CHx(x=0..6)
  185. \param[out] none
  186. \retval the number of remaining data to be transferred by the DMA
  187. */
  188. uint32_t dma_transfer_number_get(dma_channel_enum channelx)
  189. {
  190. return (uint32_t)DMA_CHCNT(channelx);
  191. }
  192. /*!
  193. \brief configure priority level of DMA channel
  194. \param[in] channelx: specify which DMA channel
  195. \arg DMA_CHx(x=0..6)
  196. \param[in] priority: priority level of this channel
  197. \arg DMA_PRIORITY_LOW: low priority
  198. \arg DMA_PRIORITY_MEDIUM: medium priority
  199. \arg DMA_PRIORITY_HIGH: high priority
  200. \arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority
  201. \param[out] none
  202. \retval none
  203. */
  204. void dma_priority_config(dma_channel_enum channelx, uint32_t priority)
  205. {
  206. uint32_t ctl;
  207. /* acquire DMA_CHxCTL register */
  208. ctl = DMA_CHCTL(channelx);
  209. /* assign regiser */
  210. ctl &= ~DMA_CHXCTL_PRIO;
  211. ctl |= priority;
  212. DMA_CHCTL(channelx) = ctl;
  213. }
  214. /*!
  215. \brief configure transfer data size of memory
  216. \param[in] channelx: specify which DMA channel
  217. \arg DMA_CHx(x=0..6)
  218. \param[in] mwidth: transfer data size of memory
  219. \arg DMA_MEMORY_WIDTH_8BIT: transfer data size of memory is 8-bit
  220. \arg DMA_MEMORY_WIDTH_16BIT: transfer data size of memory is 16-bit
  221. \arg DMA_MEMORY_WIDTH_32BIT: transfer data size of memory is 32-bit
  222. \param[out] none
  223. \retval none
  224. */
  225. void dma_memory_width_config(dma_channel_enum channelx, uint32_t mwidth)
  226. {
  227. uint32_t ctl;
  228. /* acquire DMA_CHxCTL register */
  229. ctl = DMA_CHCTL(channelx);
  230. /* assign regiser */
  231. ctl &= ~DMA_CHXCTL_MWIDTH;
  232. ctl |= mwidth;
  233. DMA_CHCTL(channelx) = ctl;
  234. }
  235. /*!
  236. \brief configure transfer data size of peripheral
  237. \param[in] channelx: specify which DMA channel
  238. \arg DMA_CHx(x=0..6)
  239. \param[in] pwidth: transfer data size of peripheral
  240. \arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data size of peripheral is 8-bit
  241. \arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data size of peripheral is 16-bit
  242. \arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data size of peripheral is 32-bit
  243. \param[out] none
  244. \retval none
  245. */
  246. void dma_periph_width_config(dma_channel_enum channelx, uint32_t pwidth)
  247. {
  248. uint32_t ctl;
  249. /* acquire DMA_CHxCTL register */
  250. ctl = DMA_CHCTL(channelx);
  251. /* assign regiser */
  252. ctl &= ~DMA_CHXCTL_PWIDTH;
  253. ctl |= pwidth;
  254. DMA_CHCTL(channelx) = ctl;
  255. }
  256. /*!
  257. \brief enable next address increasement algorithm of memory
  258. \param[in] channelx: specify which DMA channel
  259. \arg DMA_CHx(x=0..6)
  260. \param[out] none
  261. \retval none
  262. */
  263. void dma_memory_increase_enable(dma_channel_enum channelx)
  264. {
  265. DMA_CHCTL(channelx) |= DMA_CHXCTL_MNAGA;
  266. }
  267. /*!
  268. \brief disable next address increasement algorithm of memory
  269. \param[in] channelx: specify which DMA channel
  270. \arg DMA_CHx(x=0..6)
  271. \param[out] none
  272. \retval none
  273. */
  274. void dma_memory_increase_disable(dma_channel_enum channelx)
  275. {
  276. DMA_CHCTL(channelx) &= ~DMA_CHXCTL_MNAGA;
  277. }
  278. /*!
  279. \brief enable next address increasement algorithm of peripheral
  280. \param[in] channelx: specify which DMA channel
  281. \arg DMA_CHx(x=0..6)
  282. \param[out] none
  283. \retval none
  284. */
  285. void dma_periph_increase_enable(dma_channel_enum channelx)
  286. {
  287. DMA_CHCTL(channelx) |= DMA_CHXCTL_PNAGA;
  288. }
  289. /*!
  290. \brief disable next address increasement algorithm of peripheral
  291. \param[in] channelx: specify which DMA channel
  292. \arg DMA_CHx(x=0..6)
  293. \param[out] none
  294. \retval none
  295. */
  296. void dma_periph_increase_disable(dma_channel_enum channelx)
  297. {
  298. DMA_CHCTL(channelx) &= ~DMA_CHXCTL_PNAGA;
  299. }
  300. /*!
  301. \brief configure the direction of data transfer on the channel
  302. \param[in] channelx: specify which DMA channel
  303. \arg DMA_CHx(x=0..6)
  304. \param[in] direction: specify the direction of data transfer
  305. \arg DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory
  306. \arg DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral
  307. \param[out] none
  308. \retval none
  309. */
  310. void dma_transfer_direction_config(dma_channel_enum channelx, uint32_t direction)
  311. {
  312. if(DMA_PERIPHERAL_TO_MEMORY == direction){
  313. DMA_CHCTL(channelx) &= ~DMA_CHXCTL_DIR;
  314. } else {
  315. DMA_CHCTL(channelx) |= DMA_CHXCTL_DIR;
  316. }
  317. }
  318. /*!
  319. \brief check DMA flag is set or not
  320. \param[in] channelx: specify which DMA channel to get flag
  321. \arg DMA_CHx(x=0..6)
  322. \param[in] flag: specify get which flag
  323. only one parameter can be selected which is shown as below:
  324. \arg DMA_FLAG_G: global interrupt flag of channel
  325. \arg DMA_FLAG_FTF: full transfer finish flag of channel
  326. \arg DMA_FLAG_HTF: half transfer finish flag of channel
  327. \arg DMA_FLAG_ERR: error flag of channel
  328. \param[out] none
  329. \retval FlagStatus: SET or RESET
  330. */
  331. FlagStatus dma_flag_get(dma_channel_enum channelx, uint32_t flag)
  332. {
  333. FlagStatus reval;
  334. if(RESET != (DMA_INTF & DMA_FLAG_ADD(flag, channelx))){
  335. reval = SET;
  336. }else{
  337. reval = RESET;
  338. }
  339. return reval;
  340. }
  341. /*!
  342. \brief clear DMA a channel flag
  343. \param[in] channelx: specify which DMA channel to clear flag
  344. \arg DMA_CHx(x=0..6)
  345. \param[in] flag: specify get which flag
  346. \arg DMA_FLAG_G: global interrupt flag of channel
  347. \arg DMA_FLAG_FTF: full transfer finish flag of channel
  348. \arg DMA_FLAG_HTF: half transfer finish flag of channel
  349. \arg DMA_FLAG_ERR: error flag of channel
  350. \param[out] none
  351. \retval none
  352. */
  353. void dma_flag_clear(dma_channel_enum channelx, uint32_t flag)
  354. {
  355. DMA_INTC |= DMA_FLAG_ADD(flag, channelx);
  356. }
  357. /*!
  358. \brief check DMA flag and interrupt enable bit is set or not
  359. \param[in] channelx: specify which DMA channel to get flag
  360. \arg DMA_CHx(x=0..6)
  361. \param[in] flag: specify get which flag
  362. only one parameter can be selected which is shown as below:
  363. \arg DMA_INT_FLAG_FTF: transfer finish flag of channel
  364. \arg DMA_INT_FLAG_HTF: half transfer finish flag of channel
  365. \arg DMA_INT_FLAG_ERR: error flag of channel
  366. \param[out] none
  367. \retval FlagStatus: SET or RESET
  368. */
  369. FlagStatus dma_interrupt_flag_get(dma_channel_enum channelx, uint32_t flag)
  370. {
  371. uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
  372. switch(flag){
  373. case DMA_INT_FLAG_FTF:
  374. interrupt_flag = DMA_INTF & DMA_FLAG_ADD(flag, channelx);
  375. interrupt_enable = DMA_CHCTL(channelx) & DMA_CHXCTL_FTFIE;
  376. break;
  377. case DMA_INT_FLAG_HTF:
  378. interrupt_flag = DMA_INTF & DMA_FLAG_ADD(flag, channelx);
  379. interrupt_enable = DMA_CHCTL(channelx) & DMA_CHXCTL_HTFIE;
  380. break;
  381. case DMA_INT_FLAG_ERR:
  382. interrupt_flag = DMA_INTF & DMA_FLAG_ADD(flag, channelx);
  383. interrupt_enable = DMA_CHCTL(channelx) & DMA_CHXCTL_ERRIE;
  384. break;
  385. default:
  386. break;
  387. }
  388. if(interrupt_flag && interrupt_enable){
  389. return SET;
  390. }else{
  391. return RESET;
  392. }
  393. }
  394. /*!
  395. \brief clear DMA a channel flag
  396. \param[in] channelx: specify which DMA channel to clear flag
  397. \arg DMA_CHx(x=0..6)
  398. \param[in] flag: specify get which flag
  399. \arg DMA_INT_FLAG_G: global interrupt flag of channel
  400. \arg DMA_INT_FLAG_FTF: transfer finish flag of channel
  401. \arg DMA_INT_FLAG_HTF: half transfer finish flag of channel
  402. \arg DMA_INT_FLAG_ERR: error flag of channel
  403. \param[out] none
  404. \retval none
  405. */
  406. void dma_interrupt_flag_clear(dma_channel_enum channelx, uint32_t flag)
  407. {
  408. DMA_INTC |= DMA_FLAG_ADD(flag,channelx);
  409. }
  410. /*!
  411. \brief enable DMA interrupt
  412. \param[in] channelx: specify which DMA channel
  413. \arg DMA_CHx(x=0..6)
  414. \param[in] source: specify which interrupt to enbale
  415. \arg DMA_INT_ERR: channel error interrupt
  416. \arg DMA_INT_HTF: channel transfer half finish interrupt
  417. \arg DMA_INT_FTF: channel transfer finish interrupt
  418. \param[out] none
  419. \retval none
  420. */
  421. void dma_interrupt_enable(dma_channel_enum channelx, uint32_t source)
  422. {
  423. DMA_CHCTL(channelx) |= source;
  424. }
  425. /*!
  426. \brief disable DMA interrupt
  427. \param[in] channelx: specify which DMA channel
  428. \arg DMA_CHx(x=0..6)
  429. \param[in] source: specify which interrupt to disbale
  430. \arg DMA_INT_ERR: channel error interrupt
  431. \arg DMA_INT_HTF: channel transfer half finish interrupt
  432. \arg DMA_INT_FTF: channel transfer finish interrupt
  433. \param[out] none
  434. \retval none
  435. */
  436. void dma_interrupt_disable(dma_channel_enum channelx, uint32_t source)
  437. {
  438. DMA_CHCTL(channelx) &= ~source;
  439. }