dma.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /**
  2. * @file dma.c
  3. * @author chipsea
  4. * @brief
  5. * @version 0.1
  6. * @date 2020-11-30
  7. * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd.
  8. * @note
  9. */
  10. #include <string.h>
  11. #include "clock.h"
  12. #include "pwrmgr.h"
  13. #include "error.h"
  14. #include "log.h"
  15. #include "jump_function.h"
  16. #include "dma.h"
  17. typedef struct{
  18. bool init_flg;
  19. DMA_CH_Ctx_t dma_ch_ctx[DMA_CH_NUM];
  20. }dma_ctx_t;
  21. dma_ctx_t s_dma_ctx = {
  22. .init_flg = FALSE,
  23. };
  24. static DMA_CONN_e GetSrcConn(uint32_t addr)
  25. {
  26. if(addr == (uint32_t)&(AP_SPI0->DataReg))
  27. return DMA_CONN_SPI0_Rx;
  28. if(addr == (uint32_t)&(AP_SPI1->DataReg))
  29. return DMA_CONN_SPI1_Rx;
  30. if(addr == (uint32_t)&(AP_I2C0->IC_DATA_CMD))
  31. return DMA_CONN_I2C0_Rx;
  32. if(addr == (uint32_t)&(AP_I2C1->IC_DATA_CMD))
  33. return DMA_CONN_I2C1_Rx;
  34. if(addr == (uint32_t)&(AP_UART0->RBR))
  35. return DMA_CONN_UART0_Rx;
  36. if(addr == (uint32_t)&(AP_UART1->RBR))
  37. return DMA_CONN_UART1_Rx;
  38. return DMA_CONN_MEM;
  39. }
  40. static DMA_CONN_e GetDstConn(uint32_t addr)
  41. {
  42. if(addr == (uint32_t)&(AP_SPI0->DataReg))
  43. return DMA_CONN_SPI0_Tx;
  44. if(addr == (uint32_t)&(AP_SPI1->DataReg))
  45. return DMA_CONN_SPI1_Tx;
  46. if(addr == (uint32_t)&(AP_I2C0->IC_DATA_CMD))
  47. return DMA_CONN_I2C0_Tx;
  48. if(addr == (uint32_t)&(AP_I2C1->IC_DATA_CMD))
  49. return DMA_CONN_I2C1_Tx;
  50. if(addr == (uint32_t)&(AP_UART0->THR))
  51. return DMA_CONN_UART0_Tx;
  52. if(addr == (uint32_t)&(AP_UART1->THR))
  53. return DMA_CONN_UART1_Tx;
  54. return DMA_CONN_MEM;
  55. }
  56. static void DMAWakeupHandler(void)
  57. {
  58. hal_clk_gate_enable(MOD_DMA);
  59. NVIC_SetPriority((IRQn_Type)DMAC_IRQn, IRQ_PRIO_HAL);
  60. NVIC_EnableIRQ((IRQn_Type)DMAC_IRQn);
  61. JUMP_FUNCTION(V19_IRQ_HANDLER) = (uint32_t)&HalDMAIRQHandler;
  62. AP_DMA_MISC->DmaCfgReg = DMA_DMAC_E;
  63. }
  64. int HalDMAInitChannel(HAL_DMA_t cfg)
  65. {
  66. DMA_CH_Ctx_t* pctx;
  67. DMA_CH_t ch;
  68. if(!s_dma_ctx.init_flg)
  69. return ERR_NOT_REGISTED;
  70. ch = cfg.dma_channel;
  71. if(ch >= DMA_CH_NUM)
  72. return ERR_INVALID_PARAM;
  73. pctx = &s_dma_ctx.dma_ch_ctx[ch];
  74. if(pctx ->init_ch)
  75. return ERR_INVALID_STATE;
  76. pctx->evt_handler = cfg.evt_handler;
  77. pctx->init_ch = true;
  78. return SUCCESS;
  79. }
  80. int HalDMAConfigChannel(DMA_CH_t ch, DMA_CH_CFG_t* cfg)
  81. {
  82. DMA_CH_Ctx_t* pctx;
  83. DMA_CONN_e src_conn,dst_conn;
  84. uint32_t cctrl = 0;
  85. uint32_t transf_type = DMA_TRANSFERTYPE_M2M;
  86. uint32_t transf_per = 0;
  87. uint32_t spif_protect = AP_SPIF->wr_protection;
  88. uint32_t cache_bypass = AP_PCR->CACHE_BYPASS;
  89. if(!s_dma_ctx.init_flg)
  90. {
  91. return ERR_NOT_REGISTED;
  92. }
  93. if(ch >= DMA_CH_NUM)
  94. {
  95. return ERR_INVALID_PARAM;
  96. }
  97. if(cfg->sinc >DMA_INC_NCHG || cfg->dinc >DMA_INC_NCHG)
  98. {
  99. return ERR_INVALID_PARAM;
  100. }
  101. if(cfg->src_tr_width >DMA_WIDTH_8WORD || cfg->dst_tr_width >DMA_WIDTH_8WORD)
  102. {
  103. return ERR_INVALID_PARAM;
  104. }
  105. if(cfg->src_msize >DMA_BSIZE_256 || cfg->dst_msize >DMA_BSIZE_256)
  106. {
  107. return ERR_INVALID_PARAM;
  108. }
  109. pctx = &s_dma_ctx.dma_ch_ctx[ch];
  110. if(!pctx->init_ch)
  111. return ERR_INVALID_STATE;
  112. if ((AP_DMA_MISC->ChEnReg & (DMA_DMACEnbldChns_Ch(ch))) || \
  113. (pctx->xmit_busy)){
  114. // This channel is enabled, return ERROR, need to release this channel first
  115. return ERR_BUSY;
  116. }
  117. // Reset the Interrupt status
  118. AP_DMA_INT->ClearTfr = DMA_DMACIntTfrClr_Ch(ch);
  119. // UnMask interrupt
  120. AP_DMA_INT->MaskTfr = DMA_DMACCxIntMask_E(ch);
  121. src_conn = GetSrcConn(cfg->src_addr);
  122. dst_conn = GetDstConn(cfg->dst_addr);
  123. /* Assign Linker List Item value */
  124. if(src_conn && dst_conn){
  125. transf_type = DMA_TRANSFERTYPE_P2P;
  126. transf_per = DMA_DMACCxConfig_SrcPeripheral(src_conn-1)| \
  127. DMA_DMACCxConfig_DestPeripheral(dst_conn-1);
  128. }
  129. else if(src_conn){
  130. transf_type = DMA_TRANSFERTYPE_P2M;
  131. transf_per = DMA_DMACCxConfig_SrcPeripheral(src_conn-1);
  132. }
  133. else if(dst_conn){
  134. transf_type = DMA_TRANSFERTYPE_M2P;
  135. transf_per = DMA_DMACCxConfig_DestPeripheral(dst_conn-1);
  136. }
  137. if((cfg->dst_addr > 0x11000000) && (cfg->dst_addr <= 0x11080000))
  138. {
  139. pctx->xmit_flash = DMA_DST_XIMT_IS_FLASH;
  140. if(spif_protect)
  141. {
  142. AP_SPIF->wr_protection = 0;
  143. }
  144. if(cache_bypass == 0)
  145. {
  146. AP_PCR->CACHE_BYPASS = 1;
  147. }
  148. }
  149. else
  150. {
  151. pctx->xmit_flash = DMA_DST_XIMT_NOT_FLASH;
  152. }
  153. AP_DMA_CH_CFG(ch)->SAR = cfg->src_addr;
  154. AP_DMA_CH_CFG(ch)->DAR = cfg->dst_addr;
  155. AP_DMA_CH_CFG(ch)->LLP = 0;
  156. if(DMA_GET_MAX_TRANSPORT_SIZE(ch) < cfg->transf_size)
  157. {
  158. return ERR_INVALID_PARAM;
  159. }
  160. AP_DMA_CH_CFG(ch)->CTL_H = DMA_DMACCxControl_TransferSize(cfg->transf_size);
  161. subWriteReg(&(AP_DMA_CH_CFG(ch)->CFG_H),15,7 ,transf_per);
  162. AP_DMA_CH_CFG(ch)->CFG = 0;
  163. cctrl = DMA_DMACCxConfig_TransferType(transf_type)| \
  164. DMA_DMACCxControl_SMSize(cfg->src_msize)| \
  165. DMA_DMACCxControl_DMSize(cfg->dst_msize)| \
  166. DMA_DMACCxControl_SWidth(cfg->src_tr_width)| \
  167. DMA_DMACCxControl_DWidth(cfg->dst_tr_width)| \
  168. DMA_DMACCxControl_SInc(cfg->sinc)| \
  169. DMA_DMACCxControl_DInc(cfg->dinc)| \
  170. DMA_DMAC_INT_E;
  171. AP_DMA_CH_CFG(ch)->CTL = cctrl;
  172. if(cfg->enable_int)
  173. {
  174. AP_DMA_INT->MaskTfr = DMA_DMACCxConfig_E(ch) | BIT(ch);
  175. pctx->interrupt = true;
  176. }
  177. else
  178. {
  179. AP_DMA_INT->ClearTfr = DMA_DMACIntTfrClr_Ch(ch);
  180. AP_DMA_INT->MaskTfr = DMA_DMACCxIntMask_E(ch);
  181. pctx->interrupt = false;
  182. }
  183. return SUCCESS;
  184. }
  185. int HalDMAStartChannel(DMA_CH_t ch)
  186. {
  187. DMA_CH_Ctx_t* pctx;
  188. if(!s_dma_ctx.init_flg)
  189. return ERR_NOT_REGISTED;
  190. if(ch >= DMA_CH_NUM)
  191. {
  192. return ERR_INVALID_PARAM;
  193. }
  194. pctx = &s_dma_ctx.dma_ch_ctx[ch];
  195. AP_DMA_MISC->ChEnReg = DMA_DMACCxConfig_E(ch) | BIT(ch);
  196. pctx->xmit_busy = TRUE;
  197. hal_pwrmgr_lock(MOD_DMA);
  198. return SUCCESS;
  199. }
  200. int HalDMAStopChannel(DMA_CH_t ch)
  201. {
  202. uint32_t spif_protect = AP_SPIF->wr_protection;
  203. uint32_t cache_bypass = AP_PCR->CACHE_BYPASS;
  204. DMA_CH_Ctx_t* pctx;
  205. if(!s_dma_ctx.init_flg)
  206. return ERR_NOT_REGISTED;
  207. if(ch >= DMA_CH_NUM)
  208. {
  209. return ERR_INVALID_PARAM;
  210. }
  211. pctx = &s_dma_ctx.dma_ch_ctx[ch];
  212. if(pctx->xmit_flash == DMA_DST_XIMT_IS_FLASH)
  213. {
  214. if(spif_protect)
  215. {
  216. AP_SPIF->wr_protection = 2;
  217. }
  218. if(cache_bypass == 0)
  219. {
  220. AP_PCR->CACHE_BYPASS = 0;
  221. AP_CACHE->CTRL0 = 0x01;
  222. }
  223. }
  224. // Reset the Interrupt status
  225. AP_DMA_INT->ClearTfr = DMA_DMACIntTfrClr_Ch(ch);
  226. // UnMask interrupt
  227. // AP_DMA_INT->MaskTfr = DMA_DMACCxIntMask_E(ch);
  228. AP_DMA_MISC->ChEnReg = DMA_DMACCxConfig_E(ch);
  229. pctx->xmit_busy = FALSE;
  230. hal_pwrmgr_unlock(MOD_DMA);
  231. return SUCCESS;
  232. }
  233. int HalDMAStatusControl(DMA_CH_t ch)
  234. {
  235. DMA_CH_Ctx_t* pctx;
  236. if(!s_dma_ctx.init_flg)
  237. return ERR_NOT_REGISTED;
  238. if(ch >= DMA_CH_NUM)
  239. {
  240. return ERR_INVALID_PARAM;
  241. }
  242. pctx = &s_dma_ctx.dma_ch_ctx[ch];
  243. if(pctx->interrupt == false)
  244. HalDMAWaitChannelComplete(ch);
  245. return SUCCESS;
  246. }
  247. int HalDMAWaitChannelComplete(DMA_CH_t ch)
  248. {
  249. uint32_t Temp = 0;
  250. if(!s_dma_ctx.init_flg)
  251. return ERR_NOT_REGISTED;
  252. if(ch >= DMA_CH_NUM)
  253. {
  254. return ERR_INVALID_PARAM;
  255. }
  256. while(1){
  257. Temp ++;
  258. if(AP_DMA_INT->RawTfr)
  259. {
  260. break;
  261. }
  262. }
  263. HalDMAStopChannel(ch);
  264. // LOG("wait count is %d\n",Temp);
  265. return SUCCESS;
  266. }
  267. int HalDMAInit(void)
  268. {
  269. uint8_t ret;
  270. hal_clk_gate_enable(MOD_DMA);
  271. hal_clk_reset(MOD_DMA);
  272. NVIC_SetPriority((IRQn_Type)DMAC_IRQn, IRQ_PRIO_HAL);
  273. NVIC_EnableIRQ((IRQn_Type)DMAC_IRQn);
  274. JUMP_FUNCTION(V19_IRQ_HANDLER) = (uint32_t)&HalDMAIRQHandler;
  275. ret = hal_pwrmgr_register(MOD_DMA,NULL, DMAWakeupHandler);
  276. if(ret == SUCCESS)
  277. {
  278. s_dma_ctx.init_flg = TRUE;
  279. memset(&(s_dma_ctx.dma_ch_ctx[0]), 0, sizeof(DMA_CH_Ctx_t)*DMA_CH_NUM);
  280. //dmac controller enable
  281. AP_DMA_MISC->DmaCfgReg = DMA_DMAC_E;
  282. }
  283. else
  284. {
  285. return ret;
  286. }
  287. return SUCCESS;
  288. }
  289. int HalDMADeinit(void)
  290. {
  291. //dmac controller disable
  292. AP_DMA_MISC->DmaCfgReg = DMA_DMAC_D;
  293. s_dma_ctx.init_flg = FALSE;
  294. memset(&(s_dma_ctx.dma_ch_ctx[0]), 0, sizeof(DMA_CH_Ctx_t)*DMA_CH_NUM);
  295. hal_clk_gate_disable(MOD_DMA);
  296. return SUCCESS;
  297. }
  298. void __attribute__((used)) HalDMAIRQHandler(void)
  299. {
  300. DMA_CH_t ch;
  301. for(ch = DMA_CH_0;ch < DMA_CH_NUM;ch++)
  302. {
  303. if(AP_DMA_INT->StatusTfr & BIT(ch))
  304. {
  305. HalDMAStopChannel(ch);
  306. if(s_dma_ctx.dma_ch_ctx[ch].evt_handler != NULL)
  307. {
  308. s_dma_ctx.dma_ch_ctx[ch].evt_handler(ch);
  309. }
  310. }
  311. }
  312. }