cmem7_dma.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /**
  2. *****************************************************************************
  3. * @file cmem7_dma.c
  4. *
  5. * @brief CMEM7 DMA source file
  6. *
  7. *
  8. * @version V1.0
  9. * @date 3. September 2013
  10. *
  11. * @note
  12. *
  13. *****************************************************************************
  14. * @attention
  15. *
  16. * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  17. * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  18. * TIME. AS A RESULT, CAPITAL-MICRO SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
  19. * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  20. * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  21. * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  22. *
  23. * <h2><center>&copy; COPYRIGHT 2013 Capital-micro </center></h2>
  24. *****************************************************************************
  25. */
  26. #include "cmem7_dma.h"
  27. typedef struct {
  28. union {
  29. uint32_t CTL_LOW;
  30. struct {
  31. uint32_t INT_EN : 1;
  32. uint32_t DST_TR_WIDTH: 3;
  33. uint32_t SRC_TR_WIDTH: 3;
  34. uint32_t DINC : 2;
  35. uint32_t SINC : 2;
  36. uint32_t DEST_MSIZE : 3;
  37. uint32_t SRC_MSIZE : 3;
  38. uint32_t SRC_GATHER_EN: 1;
  39. uint32_t DST_SCATTER_EN: 1;
  40. uint32_t : 1;
  41. uint32_t TT_FC : 3;
  42. uint32_t DMS : 2;
  43. uint32_t SMS : 2;
  44. uint32_t LLP_DST_EN : 1;
  45. uint32_t LLP_SRC_EN : 1;
  46. } CTL_LOW_b;
  47. } INNER;
  48. } INNER_CTL_LOW;
  49. typedef struct {
  50. union {
  51. uint32_t CTL_HI;
  52. struct {
  53. uint32_t BLOCK_TS : 12;
  54. uint32_t DONE : 1;
  55. } CTL_HI_b;
  56. } INNER;
  57. } INNER_CTL_HIGH;
  58. typedef struct {
  59. uint32_t srcAddr;
  60. uint32_t dstAddr;
  61. uint32_t nextBlock;
  62. INNER_CTL_LOW low;
  63. INNER_CTL_HIGH high;
  64. } INNER_BLOCK_DESC;
  65. #define DMA_MAX_CHANNEL_NUM 8
  66. #define DMA_TR_WIDTH_8_BIT 0
  67. #define DMA_TR_WIDTH_16_BIT 1
  68. #define DMA_TR_WIDTH_32_BIT 2
  69. #define DMA_TR_WIDTH_64_BIT 3
  70. #define DMA_TR_WIDTH_128_BIT 4
  71. #define DMA_TR_WIDTH_256_BIT 5
  72. #define DMA_INC_INCREMENT 0
  73. #define DMA_INC_DECREMENT 1
  74. #define DMA_INC_NO_CHANGE 2
  75. #define DMA_LOCK_DMA_TRANSFER 0
  76. #define DMA_LOCK_DMA_BLOCK_TRANSFER 1
  77. #define DMA_LOCK_DMA_BLOCK_TRANSACTION 2
  78. void DMA_Init() {
  79. DMA->DMA_EN_b.EN = TRUE;
  80. // only open channel 0
  81. DMA->CH_EN = (0xFF << DMA_MAX_CHANNEL_NUM) | 0x0;
  82. DMA_ClearInt(DMA_Int_All);
  83. DMA_EnableInt(DMA_Int_All, FALSE);
  84. DMA->SAR0 = 0x0;
  85. DMA->DAR0 = 0x0;
  86. DMA->CTL_HI0_b.BLOCK_TS = 0;
  87. DMA->CTL_LOW0_b.INT_EN = FALSE;
  88. DMA->CTL_LOW0_b.DST_TR_WIDTH = DMA_TR_WIDTH_32_BIT;
  89. DMA->CTL_LOW0_b.SRC_TR_WIDTH = DMA_TR_WIDTH_32_BIT;
  90. DMA->CTL_LOW0_b.DINC = DMA_INC_INCREMENT;
  91. DMA->CTL_LOW0_b.SINC = DMA_INC_INCREMENT;
  92. DMA->CTL_LOW0_b.DEST_MSIZE = 0;
  93. DMA->CTL_LOW0_b.SRC_MSIZE = 0;
  94. DMA->CTL_LOW0_b.SRC_GATHER_EN = FALSE;
  95. DMA->CTL_LOW0_b.DST_SCATTER_EN = FALSE;
  96. DMA->CTL_LOW0_b.TT_FC = 0;
  97. DMA->CTL_LOW0_b.DMS = 0;
  98. DMA->CTL_LOW0_b.SMS = 0;
  99. DMA->CTL_LOW0_b.LLP_DST_EN = FALSE;
  100. DMA->CTL_LOW0_b.LLP_SRC_EN = FALSE;
  101. DMA->LLP0_b.LOC = 0;
  102. DMA->LLP0_b.LMS = 0;
  103. DMA->SGR0_b.SGC = 0x1;
  104. DMA->SGR0_b.SGI = 0x0;
  105. DMA->DSR0_b.DSC = 0x0;
  106. DMA->DSR0_b.DSI = 0x0;
  107. DMA->SSTATAR0 = 0x0;
  108. DMA->DSTATAR0 = 0x0;
  109. DMA->CFG_HI0 = 0x0;
  110. DMA->CFG_LOW0_b.CH_PRIOR = 0;
  111. DMA->CFG_LOW0_b.CH_SUSP = 0;
  112. DMA->CFG_LOW0_b.HS_SEL_DST = 0;
  113. DMA->CFG_LOW0_b.LOCK_B_L = 0;
  114. DMA->CFG_LOW0_b.HS_SEL_SRC = 0;
  115. DMA->CFG_LOW0_b.LOCK_CH_L = DMA_LOCK_DMA_TRANSFER;
  116. DMA->CFG_LOW0_b.LOCK_B_L = DMA_LOCK_DMA_TRANSFER;
  117. DMA->CFG_LOW0_b.LOCK_CH = TRUE;
  118. DMA->CFG_LOW0_b.LOCK_B = TRUE;
  119. DMA->CFG_LOW0_b.DST_HS_POL = 0;
  120. DMA->CFG_LOW0_b.SRC_HS_POL = 0;
  121. DMA->CFG_LOW0_b.RELOAD_SRC = FALSE;
  122. DMA->CFG_LOW0_b.RELOAD_DST = FALSE;
  123. }
  124. void DMA_EnableInt(uint32_t Int, BOOL enable) {
  125. assert_param(IS_DMA_INT(Int));
  126. if (enable) {
  127. if (Int & DMA_Int_TfrComplete) {
  128. DMA->INT_EN_TFR = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x1;
  129. }
  130. if (Int & DMA_Int_Err) {
  131. DMA->INT_EN_ERR = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x1;
  132. }
  133. } else {
  134. if (Int & DMA_Int_TfrComplete) {
  135. DMA->INT_EN_TFR = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x0;
  136. }
  137. if (Int & DMA_Int_Err) {
  138. DMA->INT_EN_ERR = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x0;
  139. }
  140. }
  141. }
  142. BOOL DMA_GetIntStatus(uint32_t Int) {
  143. assert_param(IS_DMA_INT(Int));
  144. if (Int & DMA_Int_TfrComplete) {
  145. if (DMA->INT_TFR) {
  146. return TRUE;
  147. }
  148. }
  149. if (Int & DMA_Int_Err) {
  150. if (DMA->INT_ERR) {
  151. return TRUE;
  152. }
  153. }
  154. return FALSE;
  155. }
  156. void DMA_ClearInt(uint32_t Int) {
  157. assert_param(IS_DMA_INT(Int));
  158. if (Int & DMA_Int_TfrComplete) {
  159. DMA->INT_CLEAR_TFR = 0x1;
  160. }
  161. if (Int & DMA_Int_Err) {
  162. DMA->INT_CLEAR_ERR = 0x1;
  163. }
  164. }
  165. BOOL DMA_IsBusy() {
  166. return (DMA->CH_EN_b.EN) ? TRUE : FALSE;
  167. }
  168. BOOL DMA_Transfer(BLOCK_DESC *blockList) {
  169. BLOCK_DESC *p;
  170. if (!blockList) {
  171. return FALSE;
  172. }
  173. if (DMA_IsBusy()) {
  174. return FALSE;
  175. }
  176. p = blockList;
  177. while (p) {
  178. BOOL llp = FALSE;
  179. INNER_BLOCK_DESC *inner = (INNER_BLOCK_DESC *)p;
  180. if (p->nextBlock) {
  181. llp = TRUE;
  182. }
  183. inner->high.INNER.CTL_HI = 0;
  184. inner->high.INNER.CTL_HI_b.BLOCK_TS = (p->number >> DMA_TR_WIDTH_32_BIT);
  185. inner->high.INNER.CTL_HI_b.DONE = 0;
  186. inner->nextBlock = p->nextBlock;
  187. inner->low.INNER.CTL_LOW = 0;
  188. inner->low.INNER.CTL_LOW_b.INT_EN = TRUE;
  189. inner->low.INNER.CTL_LOW_b.DST_TR_WIDTH = DMA_TR_WIDTH_32_BIT;
  190. inner->low.INNER.CTL_LOW_b.SRC_TR_WIDTH = DMA_TR_WIDTH_32_BIT;
  191. inner->low.INNER.CTL_LOW_b.DINC = DMA_INC_INCREMENT;
  192. inner->low.INNER.CTL_LOW_b.SINC = DMA_INC_INCREMENT;
  193. inner->low.INNER.CTL_LOW_b.DEST_MSIZE = 0;
  194. inner->low.INNER.CTL_LOW_b.SRC_MSIZE = 0;
  195. inner->low.INNER.CTL_LOW_b.SRC_GATHER_EN = FALSE;
  196. inner->low.INNER.CTL_LOW_b.DST_SCATTER_EN = FALSE;
  197. inner->low.INNER.CTL_LOW_b.TT_FC = 0;
  198. inner->low.INNER.CTL_LOW_b.DMS = 0;
  199. inner->low.INNER.CTL_LOW_b.SMS = 0;
  200. inner->low.INNER.CTL_LOW_b.LLP_DST_EN = llp;
  201. inner->low.INNER.CTL_LOW_b.LLP_SRC_EN = llp;
  202. if ((uint32_t)inner == (uint32_t)blockList) {
  203. // copy to DMA
  204. DMA->SAR0 = llp ? 0x0 : inner->srcAddr ;
  205. DMA->DAR0 = llp ? 0x0 : inner->dstAddr ;
  206. DMA->CTL_HI0 = llp ? 0x0 : inner->high.INNER.CTL_HI;
  207. DMA->CTL_LOW0 = inner->low.INNER.CTL_LOW;
  208. DMA->LLP0 = llp ? (uint32_t)inner : 0x0;
  209. }
  210. p = (BLOCK_DESC *)inner->nextBlock;
  211. }
  212. // open channel 0
  213. DMA->CH_EN = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x1;
  214. return TRUE;
  215. }