gd32f4xx_dma.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. /*!
  2. \file gd32f4xx_dma.c
  3. \brief DMA driver
  4. \version 2016-08-15, V1.0.0, firmware for GD32F4xx
  5. \version 2018-12-12, V2.0.0, firmware for GD32F4xx
  6. \version 2020-09-30, V2.1.0, firmware for GD32F4xx
  7. */
  8. /*
  9. Copyright (c) 2020, GigaDevice Semiconductor Inc.
  10. Redistribution and use in source and binary forms, with or without modification,
  11. are permitted provided that the following conditions are met:
  12. 1. Redistributions of source code must retain the above copyright notice, this
  13. list of conditions and the following disclaimer.
  14. 2. Redistributions in binary form must reproduce the above copyright notice,
  15. this list of conditions and the following disclaimer in the documentation
  16. and/or other materials provided with the distribution.
  17. 3. Neither the name of the copyright holder nor the names of its contributors
  18. may be used to endorse or promote products derived from this software without
  19. specific prior written permission.
  20. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  22. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  23. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  24. INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  27. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  29. OF SUCH DAMAGE.
  30. */
  31. #include "gd32f4xx_dma.h"
  32. /* DMA register bit offset */
  33. #define CHXCTL_PERIEN_OFFSET ((uint32_t)25U)
  34. /*!
  35. \brief deinitialize DMA a channel registers
  36. \param[in] dma_periph: DMAx(x=0,1)
  37. \arg DMAx(x=0,1)
  38. \param[in] channelx: specify which DMA channel is deinitialized
  39. \arg DMA_CHx(x=0..7)
  40. \param[out] none
  41. \retval none
  42. */
  43. void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx)
  44. {
  45. /* disable DMA a channel */
  46. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_CHEN;
  47. /* reset DMA channel registers */
  48. DMA_CHCTL(dma_periph,channelx) = DMA_CHCTL_RESET_VALUE;
  49. DMA_CHCNT(dma_periph,channelx) = DMA_CHCNT_RESET_VALUE;
  50. DMA_CHPADDR(dma_periph,channelx) = DMA_CHPADDR_RESET_VALUE;
  51. DMA_CHM0ADDR(dma_periph,channelx) = DMA_CHMADDR_RESET_VALUE;
  52. DMA_CHM1ADDR(dma_periph,channelx) = DMA_CHMADDR_RESET_VALUE;
  53. DMA_CHFCTL(dma_periph,channelx) = DMA_CHFCTL_RESET_VALUE;
  54. if(channelx < DMA_CH4){
  55. DMA_INTC0(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE,channelx);
  56. }else{
  57. channelx -= (dma_channel_enum)4;
  58. DMA_INTC1(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE,channelx);
  59. }
  60. }
  61. /*!
  62. \brief initialize the DMA single data mode parameters struct with the default values
  63. \param[in] init_struct: the initialization data needed to initialize DMA channel
  64. \param[out] none
  65. \retval none
  66. */
  67. void dma_single_data_para_struct_init(dma_single_data_parameter_struct* init_struct)
  68. {
  69. /* set the DMA struct with the default values */
  70. init_struct->periph_addr = 0U;
  71. init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE;
  72. init_struct->memory0_addr = 0U;
  73. init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE;
  74. init_struct->periph_memory_width = 0U;
  75. init_struct->circular_mode = DMA_CIRCULAR_MODE_DISABLE;
  76. init_struct->direction = DMA_PERIPH_TO_MEMORY;
  77. init_struct->number = 0U;
  78. init_struct->priority = DMA_PRIORITY_LOW;
  79. }
  80. /*!
  81. \brief initialize the DMA multi data mode parameters struct with the default values
  82. \param[in] init_struct: the initialization data needed to initialize DMA channel
  83. \param[out] none
  84. \retval none
  85. */
  86. void dma_multi_data_para_struct_init(dma_multi_data_parameter_struct* init_struct)
  87. {
  88. /* set the DMA struct with the default values */
  89. init_struct->periph_addr = 0U;
  90. init_struct->periph_width = 0U;
  91. init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE;
  92. init_struct->memory0_addr = 0U;
  93. init_struct->memory_width = 0U;
  94. init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE;
  95. init_struct->memory_burst_width = 0U;
  96. init_struct->periph_burst_width = 0U;
  97. init_struct->circular_mode = DMA_CIRCULAR_MODE_DISABLE;
  98. init_struct->direction = DMA_PERIPH_TO_MEMORY;
  99. init_struct->number = 0U;
  100. init_struct->priority = DMA_PRIORITY_LOW;
  101. }
  102. /*!
  103. \brief initialize DMA single data mode
  104. \param[in] dma_periph: DMAx(x=0,1)
  105. \arg DMAx(x=0,1)
  106. \param[in] channelx: specify which DMA channel is initialized
  107. \arg DMA_CHx(x=0..7)
  108. \param[in] init_struct: the data needed to initialize DMA single data mode
  109. periph_addr: peripheral base address
  110. periph_inc: DMA_PERIPH_INCREASE_ENABLE,DMA_PERIPH_INCREASE_DISABLE,DMA_PERIPH_INCREASE_FIX
  111. memory0_addr: memory base address
  112. memory_inc: DMA_MEMORY_INCREASE_ENABLE,DMA_MEMORY_INCREASE_DISABLE
  113. periph_memory_width: DMA_PERIPH_WIDTH_8BIT,DMA_PERIPH_WIDTH_16BIT,DMA_PERIPH_WIDTH_32BIT
  114. circular_mode: DMA_CIRCULAR_MODE_ENABLE,DMA_CIRCULAR_MODE_DISABLE
  115. direction: DMA_PERIPH_TO_MEMORY,DMA_MEMORY_TO_PERIPH,DMA_MEMORY_TO_MEMORY
  116. number: the number of remaining data to be transferred by the DMA
  117. priority: DMA_PRIORITY_LOW,DMA_PRIORITY_MEDIUM,DMA_PRIORITY_HIGH,DMA_PRIORITY_ULTRA_HIGH
  118. \param[out] none
  119. \retval none
  120. */
  121. void dma_single_data_mode_init(uint32_t dma_periph, dma_channel_enum channelx, dma_single_data_parameter_struct* init_struct)
  122. {
  123. uint32_t ctl;
  124. /* select single data mode */
  125. DMA_CHFCTL(dma_periph,channelx) &= ~DMA_CHXFCTL_MDMEN;
  126. /* configure peripheral base address */
  127. DMA_CHPADDR(dma_periph,channelx) = init_struct->periph_addr;
  128. /* configure memory base address */
  129. DMA_CHM0ADDR(dma_periph,channelx) = init_struct->memory0_addr;
  130. /* configure the number of remaining data to be transferred */
  131. DMA_CHCNT(dma_periph,channelx) = init_struct->number;
  132. /* configure peripheral and memory transfer width,channel priotity,transfer mode */
  133. ctl = DMA_CHCTL(dma_periph,channelx);
  134. ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO | DMA_CHXCTL_TM);
  135. ctl |= (init_struct->periph_memory_width | (init_struct->periph_memory_width << 2) | init_struct->priority | init_struct->direction);
  136. DMA_CHCTL(dma_periph,channelx) = ctl;
  137. /* configure peripheral increasing mode */
  138. if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){
  139. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PNAGA;
  140. }else if(DMA_PERIPH_INCREASE_DISABLE == init_struct->periph_inc){
  141. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_PNAGA;
  142. }else{
  143. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PAIF;
  144. }
  145. /* configure memory increasing mode */
  146. if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){
  147. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_MNAGA;
  148. }else{
  149. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_MNAGA;
  150. }
  151. /* configure DMA circular mode */
  152. if(DMA_CIRCULAR_MODE_ENABLE == init_struct->circular_mode){
  153. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_CMEN;
  154. }else{
  155. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_CMEN;
  156. }
  157. }
  158. /*!
  159. \brief initialize DMA multi data mode
  160. \param[in] dma_periph: DMAx(x=0,1)
  161. \arg DMAx(x=0,1)
  162. \param[in] channelx: specify which DMA channel is initialized
  163. \arg DMA_CHx(x=0..7)
  164. \param[in] dma_multi_data_parameter_struct: the data needed to initialize DMA multi data mode
  165. periph_addr: peripheral base address
  166. periph_width: DMA_PERIPH_WIDTH_8BIT,DMA_PERIPH_WIDTH_16BIT,DMA_PERIPH_WIDTH_32BIT
  167. periph_inc: DMA_PERIPH_INCREASE_ENABLE,DMA_PERIPH_INCREASE_DISABLE,DMA_PERIPH_INCREASE_FIX
  168. memory0_addr: memory0 base address
  169. memory_width: DMA_MEMORY_WIDTH_8BIT,DMA_MEMORY_WIDTH_16BIT,DMA_MEMORY_WIDTH_32BIT
  170. memory_inc: DMA_MEMORY_INCREASE_ENABLE,DMA_MEMORY_INCREASE_DISABLE
  171. memory_burst_width: DMA_MEMORY_BURST_SINGLE,DMA_MEMORY_BURST_4_BEAT,DMA_MEMORY_BURST_8_BEAT,DMA_MEMORY_BURST_16_BEAT
  172. periph_burst_width: DMA_PERIPH_BURST_SINGLE,DMA_PERIPH_BURST_4_BEAT,DMA_PERIPH_BURST_8_BEAT,DMA_PERIPH_BURST_16_BEAT
  173. critical_value: DMA_FIFO_1_WORD,DMA_FIFO_2_WORD,DMA_FIFO_3_WORD,DMA_FIFO_4_WORD
  174. circular_mode: DMA_CIRCULAR_MODE_ENABLE,DMA_CIRCULAR_MODE_DISABLE
  175. direction: DMA_PERIPH_TO_MEMORY,DMA_MEMORY_TO_PERIPH,DMA_MEMORY_TO_MEMORY
  176. number: the number of remaining data to be transferred by the DMA
  177. priority: DMA_PRIORITY_LOW,DMA_PRIORITY_MEDIUM,DMA_PRIORITY_HIGH,DMA_PRIORITY_ULTRA_HIGH
  178. \param[out] none
  179. \retval none
  180. */
  181. void dma_multi_data_mode_init(uint32_t dma_periph, dma_channel_enum channelx, dma_multi_data_parameter_struct* init_struct)
  182. {
  183. uint32_t ctl;
  184. /* select multi data mode and configure FIFO critical value */
  185. DMA_CHFCTL(dma_periph,channelx) |= (DMA_CHXFCTL_MDMEN | init_struct->critical_value);
  186. /* configure peripheral base address */
  187. DMA_CHPADDR(dma_periph,channelx) = init_struct->periph_addr;
  188. /* configure memory base address */
  189. DMA_CHM0ADDR(dma_periph,channelx) = init_struct->memory0_addr;
  190. /* configure the number of remaining data to be transferred */
  191. DMA_CHCNT(dma_periph,channelx) = init_struct->number;
  192. /* configure peripheral and memory transfer width,channel priotity,transfer mode,peripheral and memory burst transfer width */
  193. ctl = DMA_CHCTL(dma_periph,channelx);
  194. ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO | DMA_CHXCTL_TM | DMA_CHXCTL_PBURST | DMA_CHXCTL_MBURST);
  195. ctl |= (init_struct->periph_width | (init_struct->memory_width ) | init_struct->priority | init_struct->direction | init_struct->memory_burst_width | init_struct->periph_burst_width);
  196. DMA_CHCTL(dma_periph,channelx) = ctl;
  197. /* configure peripheral increasing mode */
  198. if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){
  199. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PNAGA;
  200. }else if(DMA_PERIPH_INCREASE_DISABLE == init_struct->periph_inc){
  201. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_PNAGA;
  202. }else{
  203. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PAIF;
  204. }
  205. /* configure memory increasing mode */
  206. if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){
  207. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_MNAGA;
  208. }else{
  209. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_MNAGA;
  210. }
  211. /* configure DMA circular mode */
  212. if(DMA_CIRCULAR_MODE_ENABLE == init_struct->circular_mode){
  213. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_CMEN;
  214. }else{
  215. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_CMEN;
  216. }
  217. }
  218. /*!
  219. \brief set DMA peripheral base address
  220. \param[in] dma_periph: DMAx(x=0,1)
  221. \arg DMAx(x=0,1)
  222. \param[in] channelx: specify which DMA channel to set peripheral base address
  223. \arg DMA_CHx(x=0..7)
  224. \param[in] address: peripheral base address
  225. \param[out] none
  226. \retval none
  227. */
  228. void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
  229. {
  230. DMA_CHPADDR(dma_periph,channelx) = address;
  231. }
  232. /*!
  233. \brief set DMA Memory0 base address
  234. \param[in] dma_periph: DMAx(x=0,1)
  235. \arg DMAx(x=0,1)
  236. \param[in] channelx: specify which DMA channel to set Memory base address
  237. \arg DMA_CHx(x=0..7)
  238. \param[in] memory_flag: DMA_MEMORY_x(x=0,1)
  239. \param[in] address: Memory base address
  240. \param[out] none
  241. \retval none
  242. */
  243. void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t memory_flag, uint32_t address)
  244. {
  245. if(memory_flag){
  246. DMA_CHM1ADDR(dma_periph,channelx) = address;
  247. }else{
  248. DMA_CHM0ADDR(dma_periph,channelx) = address;
  249. }
  250. }
  251. /*!
  252. \brief set the number of remaining data to be transferred by the DMA
  253. \param[in] dma_periph: DMAx(x=0,1)
  254. \arg DMAx(x=0,1)
  255. \param[in] channelx: specify which DMA channel to set number
  256. \arg DMA_CHx(x=0..7)
  257. \param[in] number: the number of remaining data to be transferred by the DMA
  258. \param[out] none
  259. \retval none
  260. */
  261. void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number)
  262. {
  263. DMA_CHCNT(dma_periph,channelx) = number;
  264. }
  265. /*!
  266. \brief get the number of remaining data to be transferred by the DMA
  267. \param[in] dma_periph: DMAx(x=0,1)
  268. \arg DMAx(x=0,1)
  269. \param[in] channelx: specify which DMA channel to set number
  270. \arg DMA_CHx(x=0..7)
  271. \param[out] none
  272. \retval uint32_t: the number of remaining data to be transferred by the DMA
  273. */
  274. uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx)
  275. {
  276. return (uint32_t)DMA_CHCNT(dma_periph,channelx);
  277. }
  278. /*!
  279. \brief configure priority level of DMA channel
  280. \param[in] dma_periph: DMAx(x=0,1)
  281. \arg DMAx(x=0,1)
  282. \param[in] channelx: specify which DMA channel
  283. \arg DMA_CHx(x=0..7)
  284. \param[in] priority: priority Level of this channel
  285. only one parameter can be selected which is shown as below:
  286. \arg DMA_PRIORITY_LOW: low priority
  287. \arg DMA_PRIORITY_MEDIUM: medium priority
  288. \arg DMA_PRIORITY_HIGH: high priority
  289. \arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority
  290. \param[out] none
  291. \retval none
  292. */
  293. void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority)
  294. {
  295. uint32_t ctl;
  296. /* acquire DMA_CHxCTL register */
  297. ctl = DMA_CHCTL(dma_periph,channelx);
  298. /* assign regiser */
  299. ctl &= ~DMA_CHXCTL_PRIO;
  300. ctl |= priority;
  301. DMA_CHCTL(dma_periph,channelx) = ctl;
  302. }
  303. /*!
  304. \brief configure transfer burst beats of memory
  305. \param[in] dma_periph: DMAx(x=0,1)
  306. \arg DMAx(x=0,1)
  307. \param[in] channelx: specify which DMA channel
  308. \arg DMA_CHx(x=0..7)
  309. \param[in] mbeat: transfer burst beats
  310. \arg DMA_MEMORY_BURST_SINGLE: memory transfer single burst
  311. \arg DMA_MEMORY_BURST_4_BEAT: memory transfer 4-beat burst
  312. \arg DMA_MEMORY_BURST_8_BEAT: memory transfer 8-beat burst
  313. \arg DMA_MEMORY_BURST_16_BEAT: memory transfer 16-beat burst
  314. \param[out] none
  315. \retval none
  316. */
  317. void dma_memory_burst_beats_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t mbeat)
  318. {
  319. uint32_t ctl;
  320. /* acquire DMA_CHxCTL register */
  321. ctl = DMA_CHCTL(dma_periph,channelx);
  322. /* assign regiser */
  323. ctl &= ~DMA_CHXCTL_MBURST;
  324. ctl |= mbeat;
  325. DMA_CHCTL(dma_periph,channelx) = ctl;
  326. }
  327. /*!
  328. \brief configure transfer burst beats of peripheral
  329. \param[in] dma_periph: DMAx(x=0,1)
  330. \arg DMAx(x=0,1)
  331. \param[in] channelx: specify which DMA channel
  332. \arg DMA_CHx(x=0..7)
  333. \param[in] pbeat: transfer burst beats
  334. only one parameter can be selected which is shown as below:
  335. \arg DMA_PERIPH_BURST_SINGLE: peripheral transfer single burst
  336. \arg DMA_PERIPH_BURST_4_BEAT: peripheral transfer 4-beat burst
  337. \arg DMA_PERIPH_BURST_8_BEAT: peripheral transfer 8-beat burst
  338. \arg DMA_PERIPH_BURST_16_BEAT: peripheral transfer 16-beat burst
  339. \param[out] none
  340. \retval none
  341. */
  342. void dma_periph_burst_beats_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t pbeat)
  343. {
  344. uint32_t ctl;
  345. /* acquire DMA_CHxCTL register */
  346. ctl = DMA_CHCTL(dma_periph,channelx);
  347. /* assign regiser */
  348. ctl &= ~DMA_CHXCTL_PBURST;
  349. ctl |= pbeat;
  350. DMA_CHCTL(dma_periph,channelx) = ctl;
  351. }
  352. /*!
  353. \brief configure transfer data size of memory
  354. \param[in] dma_periph: DMAx(x=0,1)
  355. \arg DMAx(x=0,1)
  356. \param[in] channelx: specify which DMA channel
  357. \arg DMA_CHx(x=0..7)
  358. \param[in] msize: transfer data size of memory
  359. only one parameter can be selected which is shown as below:
  360. \arg DMA_MEMORY_WIDTH_8BIT: transfer data size of memory is 8-bit
  361. \arg DMA_MEMORY_WIDTH_16BIT: transfer data size of memory is 16-bit
  362. \arg DMA_MEMORY_WIDTH_32BIT: transfer data size of memory is 32-bit
  363. \param[out] none
  364. \retval none
  365. */
  366. void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t msize)
  367. {
  368. uint32_t ctl;
  369. /* acquire DMA_CHxCTL register */
  370. ctl = DMA_CHCTL(dma_periph,channelx);
  371. /* assign regiser */
  372. ctl &= ~DMA_CHXCTL_MWIDTH;
  373. ctl |= msize;
  374. DMA_CHCTL(dma_periph,channelx) = ctl;
  375. }
  376. /*!
  377. \brief configure transfer data size of peripheral
  378. \param[in] dma_periph: DMAx(x=0,1)
  379. \arg DMAx(x=0,1)
  380. \param[in] channelx: specify which DMA channel
  381. \arg DMA_CHx(x=0..7)
  382. \param[in] msize: transfer data size of peripheral
  383. only one parameter can be selected which is shown as below:
  384. \arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data size of peripheral is 8-bit
  385. \arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data size of peripheral is 16-bit
  386. \arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data size of peripheral is 32-bit
  387. \param[out] none
  388. \retval none
  389. */
  390. void dma_periph_width_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t psize)
  391. {
  392. uint32_t ctl;
  393. /* acquire DMA_CHxCTL register */
  394. ctl = DMA_CHCTL(dma_periph,channelx);
  395. /* assign regiser */
  396. ctl &= ~DMA_CHXCTL_PWIDTH;
  397. ctl |= psize;
  398. DMA_CHCTL(dma_periph,channelx) = ctl;
  399. }
  400. /*!
  401. \brief configure memory address generation generation_algorithm
  402. \param[in] dma_periph: DMAx(x=0,1)
  403. \arg DMAx(x=0,1)
  404. \param[in] channelx: specify which DMA channel
  405. \arg DMA_CHx(x=0..7)
  406. \param[in] generation_algorithm: the address generation algorithm
  407. only one parameter can be selected which is shown as below:
  408. \arg DMA_MEMORY_INCREASE_ENABLE: next address of memory is increasing address mode
  409. \arg DMA_MEMORY_INCREASE_DISABLE: next address of memory is fixed address mode
  410. \param[out] none
  411. \retval none
  412. */
  413. void dma_memory_address_generation_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t generation_algorithm)
  414. {
  415. if(DMA_MEMORY_INCREASE_ENABLE == generation_algorithm){
  416. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_MNAGA;
  417. }else{
  418. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_MNAGA;
  419. }
  420. }
  421. /*!
  422. \brief configure peripheral address generation_algorithm
  423. \param[in] dma_periph: DMAx(x=0,1)
  424. \arg DMAx(x=0,1)
  425. \param[in] channelx: specify which DMA channel
  426. \arg DMA_CHx(x=0..7)
  427. \param[in] generation_algorithm: the address generation algorithm
  428. only one parameter can be selected which is shown as below:
  429. \arg DMA_PERIPH_INCREASE_ENABLE: next address of peripheral is increasing address mode
  430. \arg DMA_PERIPH_INCREASE_DISABLE: next address of peripheral is fixed address mode
  431. \arg DMA_PERIPH_INCREASE_FIX: increasing steps of peripheral address is fixed
  432. \param[out] none
  433. \retval none
  434. */
  435. void dma_peripheral_address_generation_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t generation_algorithm)
  436. {
  437. if(DMA_PERIPH_INCREASE_ENABLE == generation_algorithm){
  438. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PNAGA;
  439. }else if(DMA_PERIPH_INCREASE_DISABLE == generation_algorithm){
  440. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_PNAGA;
  441. }else{
  442. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PNAGA;
  443. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_PAIF;
  444. }
  445. }
  446. /*!
  447. \brief enable DMA circulation mode
  448. \param[in] dma_periph: DMAx(x=0,1)
  449. \arg DMAx(x=0,1)
  450. \param[in] channelx: specify which DMA channel
  451. \arg DMA_CHx(x=0..7)
  452. \param[out] none
  453. \retval none
  454. */
  455. void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx)
  456. {
  457. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_CMEN;
  458. }
  459. /*!
  460. \brief disable DMA circulation mode
  461. \param[in] dma_periph: DMAx(x=0,1)
  462. \arg DMAx(x=0,1)
  463. \param[in] channelx: specify which DMA channel
  464. \arg DMA_CHx(x=0..7)
  465. \param[out] none
  466. \retval none
  467. */
  468. void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx)
  469. {
  470. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_CMEN;
  471. }
  472. /*!
  473. \brief enable DMA channel
  474. \param[in] dma_periph: DMAx(x=0,1)
  475. \arg DMAx(x=0,1)
  476. \param[in] channelx: specify which DMA channel
  477. \arg DMA_CHx(x=0..7)
  478. \param[out] none
  479. \retval none
  480. */
  481. void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx)
  482. {
  483. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_CHEN;
  484. }
  485. /*!
  486. \brief disable DMA channel
  487. \param[in] dma_periph: DMAx(x=0,1)
  488. \arg DMAx(x=0,1)
  489. \param[in] channelx: specify which DMA channel
  490. \arg DMA_CHx(x=0..7)
  491. \param[out] none
  492. \retval none
  493. */
  494. void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx)
  495. {
  496. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_CHEN;
  497. }
  498. /*!
  499. \brief configure the direction of data transfer on the channel
  500. \param[in] dma_periph: DMAx(x=0,1)
  501. \arg DMAx(x=0,1)
  502. \param[in] channelx: specify which DMA channel
  503. \arg DMA_CHx(x=0..7)
  504. \param[in] direction: specify the direction of data transfer
  505. only one parameter can be selected which is shown as below:
  506. \arg DMA_PERIPH_TO_MEMORY: read from peripheral and write to memory
  507. \arg DMA_MEMORY_TO_PERIPH: read from memory and write to peripheral
  508. \arg DMA_MEMORY_TO_MEMORY: read from memory and write to memory
  509. \param[out] none
  510. \retval none
  511. */
  512. void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction)
  513. {
  514. uint32_t ctl;
  515. /* acquire DMA_CHxCTL register */
  516. ctl = DMA_CHCTL(dma_periph,channelx);
  517. /* assign regiser */
  518. ctl &= ~DMA_CHXCTL_TM;
  519. ctl |= direction;
  520. DMA_CHCTL(dma_periph,channelx) = ctl;
  521. }
  522. /*!
  523. \brief DMA switch buffer mode config
  524. \param[in] dma_periph: DMAx(x=0,1)
  525. \arg DMAx(x=0,1)
  526. \param[in] channelx: specify which DMA channel
  527. \arg DMA_CHx(x=0..7)
  528. \param[in] memory1_addr: memory1 base address
  529. \param[in] memory_select: DMA_MEMORY_0 or DMA_MEMORY_1
  530. \param[out] none
  531. \retval none
  532. */
  533. void dma_switch_buffer_mode_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t memory1_addr, uint32_t memory_select)
  534. {
  535. /* configure memory1 base address */
  536. DMA_CHM1ADDR(dma_periph,channelx) = memory1_addr;
  537. if(DMA_MEMORY_0 == memory_select){
  538. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_MBS;
  539. }else{
  540. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_MBS;
  541. }
  542. }
  543. /*!
  544. \brief DMA using memory get
  545. \param[in] dma_periph: DMAx(x=0,1)
  546. \arg DMAx(x=0,1)
  547. \param[in] channelx: specify which DMA channel
  548. \arg DMA_CHx(x=0..7)
  549. \param[out] none
  550. \retval the using memory
  551. */
  552. uint32_t dma_using_memory_get(uint32_t dma_periph, dma_channel_enum channelx)
  553. {
  554. if((DMA_CHCTL(dma_periph,channelx)) & DMA_CHXCTL_MBS){
  555. return DMA_MEMORY_1;
  556. }else{
  557. return DMA_MEMORY_0;
  558. }
  559. }
  560. /*!
  561. \brief DMA channel peripheral select
  562. \param[in] dma_periph: DMAx(x=0,1)
  563. \arg DMAx(x=0,1)
  564. \param[in] channelx: specify which DMA channel
  565. \arg DMA_CHx(x=0..7)
  566. \param[in] sub_periph: specify DMA channel peripheral
  567. \arg DMA_SUBPERIx(x=0..7)
  568. \param[out] none
  569. \retval none
  570. */
  571. void dma_channel_subperipheral_select(uint32_t dma_periph, dma_channel_enum channelx, dma_subperipheral_enum sub_periph)
  572. {
  573. uint32_t ctl;
  574. /* acquire DMA_CHxCTL register */
  575. ctl = DMA_CHCTL(dma_periph,channelx);
  576. /* assign regiser */
  577. ctl &= ~DMA_CHXCTL_PERIEN;
  578. ctl |= ((uint32_t)sub_periph << CHXCTL_PERIEN_OFFSET);
  579. DMA_CHCTL(dma_periph,channelx) = ctl;
  580. }
  581. /*!
  582. \brief DMA flow controller configure
  583. \param[in] dma_periph: DMAx(x=0,1)
  584. \arg DMAx(x=0,1)
  585. \param[in] channelx: specify which DMA channel
  586. \arg DMA_CHx(x=0..7)
  587. \param[in] controller: specify DMA flow controler
  588. only one parameter can be selected which is shown as below:
  589. \arg DMA_FLOW_CONTROLLER_DMA: DMA is the flow controller
  590. \arg DMA_FLOW_CONTROLLER_PERI: peripheral is the flow controller
  591. \param[out] none
  592. \retval none
  593. */
  594. void dma_flow_controller_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t controller)
  595. {
  596. if(DMA_FLOW_CONTROLLER_DMA == controller){
  597. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_TFCS;
  598. }else{
  599. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_TFCS;
  600. }
  601. }
  602. /*!
  603. \brief DMA switch buffer mode enable
  604. \param[in] dma_periph: DMAx(x=0,1)
  605. \arg DMAx(x=0,1)
  606. \param[in] channelx: specify which DMA channel
  607. \arg DMA_CHx(x=0..7)
  608. \param[in] newvalue: ENABLE or DISABLE
  609. \param[out] none
  610. \retval none
  611. */
  612. void dma_switch_buffer_mode_enable(uint32_t dma_periph, dma_channel_enum channelx, ControlStatus newvalue)
  613. {
  614. if(ENABLE == newvalue){
  615. /* switch buffer mode enable */
  616. DMA_CHCTL(dma_periph,channelx) |= DMA_CHXCTL_SBMEN;
  617. }else{
  618. /* switch buffer mode disable */
  619. DMA_CHCTL(dma_periph,channelx) &= ~DMA_CHXCTL_SBMEN;
  620. }
  621. }
  622. /*!
  623. \brief DMA FIFO status get
  624. \param[in] dma_periph: DMAx(x=0,1)
  625. \arg DMAx(x=0,1)
  626. \param[in] channelx: specify which DMA channel
  627. \arg DMA_CHx(x=0..7)
  628. \param[out] none
  629. \retval the using memory
  630. */
  631. uint32_t dma_fifo_status_get(uint32_t dma_periph, dma_channel_enum channelx)
  632. {
  633. return (DMA_CHFCTL(dma_periph,channelx) & DMA_CHXFCTL_FCNT);
  634. }
  635. /*!
  636. \brief get DMA flag is set or not
  637. \param[in] dma_periph: DMAx(x=0,1)
  638. \arg DMAx(x=0,1)
  639. \param[in] channelx: specify which DMA channel to get flag
  640. \arg DMA_CHx(x=0..7)
  641. \param[in] flag: specify get which flag
  642. only one parameter can be selected which is shown as below:
  643. \arg DMA_FLAG_FEE: FIFO error and exception flag
  644. \arg DMA_FLAG_SDE: single data mode exception flag
  645. \arg DMA_FLAG_TAE: transfer access error flag
  646. \arg DMA_FLAG_HTF: half transfer finish flag
  647. \arg DMA_FLAG_FTF: full transger finish flag
  648. \param[out] none
  649. \retval FlagStatus: SET or RESET
  650. */
  651. FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
  652. {
  653. if(channelx < DMA_CH4){
  654. if(DMA_INTF0(dma_periph) & DMA_FLAG_ADD(flag,channelx)){
  655. return SET;
  656. }else{
  657. return RESET;
  658. }
  659. }else{
  660. channelx -= (dma_channel_enum)4;
  661. if(DMA_INTF1(dma_periph) & DMA_FLAG_ADD(flag,channelx)){
  662. return SET;
  663. }else{
  664. return RESET;
  665. }
  666. }
  667. }
  668. /*!
  669. \brief clear DMA a channel flag
  670. \param[in] dma_periph: DMAx(x=0,1)
  671. \arg DMAx(x=0,1)
  672. \param[in] channelx: specify which DMA channel to get flag
  673. \arg DMA_CHx(x=0..7)
  674. \param[in] flag: specify get which flag
  675. only one parameter can be selected which is shown as below:
  676. \arg DMA_FLAG_FEE: FIFO error and exception flag
  677. \arg DMA_FLAG_SDE: single data mode exception flag
  678. \arg DMA_FLAG_TAE: transfer access error flag
  679. \arg DMA_FLAG_HTF: half transfer finish flag
  680. \arg DMA_FLAG_FTF: full transger finish flag
  681. \param[out] none
  682. \retval none
  683. */
  684. void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
  685. {
  686. if(channelx < DMA_CH4){
  687. DMA_INTC0(dma_periph) |= DMA_FLAG_ADD(flag,channelx);
  688. }else{
  689. channelx -= (dma_channel_enum)4;
  690. DMA_INTC1(dma_periph) |= DMA_FLAG_ADD(flag,channelx);
  691. }
  692. }
  693. /*!
  694. \brief get DMA interrupt flag is set or not
  695. \param[in] dma_periph: DMAx(x=0,1)
  696. \arg DMAx(x=0,1)
  697. \param[in] channelx: specify which DMA channel to get interrupt flag
  698. \arg DMA_CHx(x=0..7)
  699. \param[in] interrupt: specify get which flag
  700. only one parameter can be selected which is shown as below:
  701. \arg DMA_INT_FLAG_FEE: FIFO error and exception flag
  702. \arg DMA_INT_FLAG_SDE: single data mode exception flag
  703. \arg DMA_INT_FLAG_TAE: transfer access error flag
  704. \arg DMA_INT_FLAG_HTF: half transfer finish flag
  705. \arg DMA_INT_FLAG_FTF: full transger finish flag
  706. \param[out] none
  707. \retval FlagStatus: SET or RESET
  708. */
  709. FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t interrupt)
  710. {
  711. uint32_t interrupt_enable = 0U,interrupt_flag = 0U;
  712. dma_channel_enum channel_flag_offset = channelx;
  713. if(channelx < DMA_CH4){
  714. switch(interrupt){
  715. case DMA_INTF_FEEIF:
  716. interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt,channelx);
  717. interrupt_enable = DMA_CHFCTL(dma_periph,channelx) & DMA_CHXFCTL_FEEIE;
  718. break;
  719. case DMA_INTF_SDEIF:
  720. interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt,channelx);
  721. interrupt_enable = DMA_CHCTL(dma_periph,channelx) & DMA_CHXCTL_SDEIE;
  722. break;
  723. case DMA_INTF_TAEIF:
  724. interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt,channelx);
  725. interrupt_enable = DMA_CHCTL(dma_periph,channelx) & DMA_CHXCTL_TAEIE;
  726. break;
  727. case DMA_INTF_HTFIF:
  728. interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt,channelx);
  729. interrupt_enable = DMA_CHCTL(dma_periph,channelx) & DMA_CHXCTL_HTFIE;
  730. break;
  731. case DMA_INTF_FTFIF:
  732. interrupt_flag = (DMA_INTF0(dma_periph) & DMA_FLAG_ADD(interrupt,channelx));
  733. interrupt_enable = (DMA_CHCTL(dma_periph,channelx) & DMA_CHXCTL_FTFIE);
  734. break;
  735. default:
  736. break;
  737. }
  738. }else{
  739. channel_flag_offset -= (dma_channel_enum)4;
  740. switch(interrupt){
  741. case DMA_INTF_FEEIF:
  742. interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt,channel_flag_offset);
  743. interrupt_enable = DMA_CHFCTL(dma_periph,channelx) & DMA_CHXFCTL_FEEIE;
  744. break;
  745. case DMA_INTF_SDEIF:
  746. interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt,channel_flag_offset);
  747. interrupt_enable = DMA_CHCTL(dma_periph,channelx) & DMA_CHXCTL_SDEIE;
  748. break;
  749. case DMA_INTF_TAEIF:
  750. interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt,channel_flag_offset);
  751. interrupt_enable = DMA_CHCTL(dma_periph,channelx) & DMA_CHXCTL_TAEIE;
  752. break;
  753. case DMA_INTF_HTFIF:
  754. interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt,channel_flag_offset);
  755. interrupt_enable = DMA_CHCTL(dma_periph,channelx) & DMA_CHXCTL_HTFIE;
  756. break;
  757. case DMA_INTF_FTFIF:
  758. interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(interrupt,channel_flag_offset);
  759. interrupt_enable = DMA_CHCTL(dma_periph,channelx) & DMA_CHXCTL_FTFIE;
  760. break;
  761. default:
  762. break;
  763. }
  764. }
  765. if(interrupt_flag && interrupt_enable){
  766. return SET;
  767. }else{
  768. return RESET;
  769. }
  770. }
  771. /*!
  772. \brief clear DMA a channel interrupt flag
  773. \param[in] dma_periph: DMAx(x=0,1)
  774. \arg DMAx(x=0,1)
  775. \param[in] channelx: specify which DMA channel to clear interrupt flag
  776. \arg DMA_CHx(x=0..7)
  777. \param[in] interrupt: specify get which flag
  778. only one parameter can be selected which is shown as below:
  779. \arg DMA_INT_FLAG_FEE: FIFO error and exception flag
  780. \arg DMA_INT_FLAG_SDE: single data mode exception flag
  781. \arg DMA_INT_FLAG_TAE: transfer access error flag
  782. \arg DMA_INT_FLAG_HTF: half transfer finish flag
  783. \arg DMA_INT_FLAG_FTF: full transger finish flag
  784. \param[out] none
  785. \retval none
  786. */
  787. void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t interrupt)
  788. {
  789. if(channelx < DMA_CH4){
  790. DMA_INTC0(dma_periph) |= DMA_FLAG_ADD(interrupt,channelx);
  791. }else{
  792. channelx -= (dma_channel_enum)4;
  793. DMA_INTC1(dma_periph) |= DMA_FLAG_ADD(interrupt,channelx);
  794. }
  795. }
  796. /*!
  797. \brief enable DMA interrupt
  798. \param[in] dma_periph: DMAx(x=0,1)
  799. \arg DMAx(x=0,1)
  800. \param[in] channelx: specify which DMA channel
  801. \arg DMA_CHx(x=0..7)
  802. \param[in] source: specify which interrupt to enbale
  803. one or more parameters can be selected which are shown as below:
  804. \arg DMA_CHXCTL_SDEIE: single data mode exception interrupt enable
  805. \arg DMA_CHXCTL_TAEIE: tranfer access error interrupt enable
  806. \arg DMA_CHXCTL_HTFIE: half transfer finish interrupt enable
  807. \arg DMA_CHXCTL_FTFIE: full transfer finish interrupt enable
  808. \arg DMA_CHXFCTL_FEEIE: FIFO exception interrupt enable
  809. \param[out] none
  810. \retval none
  811. */
  812. void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
  813. {
  814. if(DMA_CHXFCTL_FEEIE != source){
  815. DMA_CHCTL(dma_periph,channelx) |= source;
  816. }else{
  817. DMA_CHFCTL(dma_periph,channelx) |= source;
  818. }
  819. }
  820. /*!
  821. \brief disable DMA interrupt
  822. \param[in] dma_periph: DMAx(x=0,1)
  823. \arg DMAx(x=0,1)
  824. \param[in] channelx: specify which DMA channel
  825. \arg DMA_CHx(x=0..7)
  826. \param[in] source: specify which interrupt to disbale
  827. one or more parameters can be selected which are shown as below:
  828. \arg DMA_CHXCTL_SDEIE: single data mode exception interrupt enable
  829. \arg DMA_CHXCTL_TAEIE: tranfer access error interrupt enable
  830. \arg DMA_CHXCTL_HTFIE: half transfer finish interrupt enable
  831. \arg DMA_CHXCTL_FTFIE: full transfer finish interrupt enable
  832. \arg DMA_CHXFCTL_FEEIE: FIFO exception interrupt enable
  833. \param[out] none
  834. \retval none
  835. */
  836. void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
  837. {
  838. if(DMA_CHXFCTL_FEEIE != source){
  839. DMA_CHCTL(dma_periph,channelx) &= ~source;
  840. }else{
  841. DMA_CHFCTL(dma_periph,channelx) &= ~source;
  842. }
  843. }