core_dma.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * Copyright (c) 2022 OpenLuat & AirM2M
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. * this software and associated documentation files (the "Software"), to deal in
  6. * the Software without restriction, including without limitation the rights to
  7. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  8. * the Software, and to permit persons to whom the Software is furnished to do so,
  9. * subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in all
  12. * copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  16. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  17. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  18. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. */
  21. #include "user.h"
  22. typedef struct
  23. {
  24. const DMA_TypeDef *RegBase;
  25. const uint32_t Index;
  26. CBFuncEx_t CB;
  27. void *pData;
  28. uint8_t TxDir;
  29. }DMAChannal_struct;
  30. /************ operation definition for DMA DMA_CTL_H REGISTER ************/
  31. #define DMA_CTL_BLOCK_TS_Pos (0)
  32. #define DMA_CTL_BLOCK_TS_Mask (0x0fffU<<DMA_CTL_BLOCK_TS_Pos)
  33. /************ operation definition for DMA DMA_CTL_L REGISTER ************/
  34. #define DMA_CTL_TT_FC_Pos (20)
  35. #define DMA_CTL_TT_FC_Mask (0x07U<<DMA_CTL_TT_FC_Pos)
  36. #define DMA_CTL_TT_FC_Memory_to_Memory_Set (0x00U<<DMA_CTL_TT_FC_Pos)
  37. #define DMA_CTL_TT_FC_Memory_to_Peripheral_Set (0x01U<<DMA_CTL_TT_FC_Pos)
  38. #define DMA_CTL_TT_FC_Peripheral_to_Memory_Set (0x02U<<DMA_CTL_TT_FC_Pos)
  39. #define DMA_CTL_TT_FC_Peripheral_to_Memory_P_Set (0x04U<<DMA_CTL_TT_FC_Pos)
  40. #define DMA_CTL_TT_FC_Memory_to_Peripheral_P_Set (0x06U<<DMA_CTL_TT_FC_Pos)
  41. #define DMA_CTL_SRC_MSIZE_Pos (14)
  42. #define DMA_CTL_SRC_MSIZE_Mask (0x07U<<DMA_CTL_SRC_MSIZE_Pos)
  43. #define DMA_CTL_DEST_MSIZE_Pos (11)
  44. #define DMA_CTL_DEST_MSIZE_Mask (0x07U<<DMA_CTL_DEST_MSIZE_Pos)
  45. #define DMA_CTL_SINC_Pos (9)
  46. #define DMA_CTL_SINC_Mask (0x03U<<DMA_CTL_SINC_Pos)
  47. #define DMA_CTL_DINC_Pos (7)
  48. #define DMA_CTL_DINC_Mask (0x03U<<DMA_CTL_DINC_Pos)
  49. #define DMA_CTL_SRC_TR_WIDTH_Pos (4)
  50. #define DMA_CTL_SRC_TR_WIDTH_Mask (0x07U<<DMA_CTL_SRC_TR_WIDTH_Pos)
  51. #define DMA_CTL_DST_TR_WIDTH_Pos (1)
  52. #define DMA_CTL_DST_TR_WIDTH_Mask (0x07U<<DMA_CTL_DST_TR_WIDTH_Pos)
  53. #define DMA_CTL_INT_EN_Set ((uint32_t)0x01)
  54. /************ operation definition for DMA DMA_CFG_L REGISTER ************/
  55. #define DMA_CFG_HS_SEL_SRC_Pos (11)
  56. #define DMA_CFG_HS_SEL_SRC_Mask (0x01U<<DMA_CFG_HS_SEL_SRC_Pos)//0 HARD 1 SOFT
  57. #define DMA_CFG_HS_SEL_DST_Pos (10)
  58. #define DMA_CFG_HS_SEL_DST_Mask (0x01U<<DMA_CFG_HS_SEL_DST_Pos)
  59. /************ operation definition for DMA DMA_CFG_H REGISTER ************/
  60. #define DMA_CFG_DEST_PER_Pos (11)
  61. #define DMA_CFG_DEST_PER_Mask (0x07U<<DMA_CFG_DEST_PER_Pos)//need write current channel num
  62. #define DMA_CFG_SRC_PER_Pos (7)
  63. #define DMA_CFG_SRC_PER_Mask (0x07U<<DMA_CFG_SRC_PER_Pos)//need write current channel num
  64. /************ operation definition for DMA DMA_LLP_L REGISTER ************/
  65. #define DMAC_LLP_NEXT_LLI_MSK (0x3)
  66. static DMAChannal_struct hwDMAChannal[DMA_STREAM_QTY] = {
  67. {
  68. DMA_Channel_0,
  69. 1 << 0,
  70. },
  71. {
  72. DMA_Channel_1,
  73. 1 << 1,
  74. },
  75. {
  76. DMA_Channel_2,
  77. 1 << 2,
  78. },
  79. {
  80. DMA_Channel_3,
  81. 1 << 3,
  82. },
  83. {
  84. DMA_Channel_4,
  85. 1 << 4,
  86. },
  87. {
  88. DMA_Channel_5,
  89. 1 << 5,
  90. },
  91. {
  92. DMA_Channel_6,
  93. 1 << 6,
  94. },
  95. {
  96. DMA_Channel_7,
  97. 1 << 7,
  98. },
  99. };
  100. static uint8_t DMALock[(DMA_STREAM_QTY - 1)/8 + 1];
  101. static int32_t DMA_DummyCB(void *pData, void *pParam)
  102. {
  103. return 0;
  104. }
  105. void *DMA_TakeStream(uint8_t Stream)
  106. {
  107. if (BSP_TestBit(DMALock, Stream))
  108. {
  109. return NULL;
  110. }
  111. BSP_SetBit(DMALock, Stream, 1);
  112. return &hwDMAChannal[Stream];
  113. }
  114. int DMA_CheckStreamLock(uint8_t Stream)
  115. {
  116. return BSP_TestBit(DMALock, Stream);
  117. }
  118. void DMA_ReleaseStream(uint8_t Stream)
  119. {
  120. BSP_SetBit(DMALock, Stream, 0);
  121. }
  122. uint8_t DMA_CheckStreamBusy(uint8_t Stream)
  123. {
  124. DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
  125. uint32_t BaseIndex = hwDMAChannal[Stream].Index;
  126. if (DMA->ChEnReg_L & BaseIndex)
  127. {
  128. return 1;
  129. }
  130. return 0;
  131. }
  132. void DMA_BaseConfig(void *Config)
  133. {
  134. DMA_InitTypeDef *DMA_InitStruct = (DMA_InitTypeDef *)Config;
  135. memset(DMA_InitStruct, 0, sizeof(DMA_InitTypeDef));
  136. DMA_InitStruct->DMA_PeripheralBurstSize = DMA_BurstSize_1;
  137. DMA_InitStruct->DMA_PeripheralDataSize = DMA_DataSize_Byte;
  138. DMA_InitStruct->DMA_PeripheralInc = DMA_Inc_Nochange;
  139. DMA_InitStruct->DMA_MemoryBurstSize = DMA_BurstSize_1;
  140. DMA_InitStruct->DMA_MemoryDataSize = DMA_DataSize_Byte;
  141. DMA_InitStruct->DMA_MemoryInc = DMA_Inc_Increment;
  142. }
  143. int DMA_ConfigStream(uint8_t Stream, void *Config)
  144. {
  145. DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
  146. uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index;
  147. DMA_InitTypeDef *DMA_InitStruct = (DMA_InitTypeDef *)Config;
  148. if (DMA->ChEnReg_L & tmpChannelxBit)
  149. {
  150. return -1;
  151. }
  152. DMA->ClearTfr_L = tmpChannelxBit;
  153. DMA->ClearBlock_L = tmpChannelxBit;
  154. DMA->ClearSrcTran_L = tmpChannelxBit;
  155. DMA->ClearDstTran_L = tmpChannelxBit;
  156. DMA->ClearErr_L = tmpChannelxBit;
  157. if((DMA->RawBlock_L & tmpChannelxBit) | (DMA->RawDstTran_L & tmpChannelxBit) | (DMA->RawErr_L & tmpChannelxBit) \
  158. | (DMA->RawSrcTran_L & tmpChannelxBit) | (DMA->RawTfr_L & tmpChannelxBit) | (DMA->StatusBlock_L & tmpChannelxBit) \
  159. | (DMA->StatusDstTran_L & tmpChannelxBit) | (DMA->StatusErr_L & tmpChannelxBit) | (DMA->StatusSrcTran_L & tmpChannelxBit) \
  160. | (DMA->StatusTfr_L & tmpChannelxBit) )
  161. {
  162. return -1;
  163. }
  164. switch(DMA_InitStruct->DMA_Peripheral)
  165. {
  166. case SYSCTRL_PHER_CTRL_DMA_CHx_IF_LCD:
  167. case SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART0_TX:
  168. case SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART1_TX:
  169. case SYSCTRL_PHER_CTRL_DMA_CHx_IF_DAC:
  170. case SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI0_TX:
  171. case SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI1_TX:
  172. case SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI2_TX:
  173. case SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART2_TX:
  174. case SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART3_TX:
  175. case SYSCTRL_PHER_CTRL_DMA_CHx_IF_I2C_TX:
  176. case SYSCTRL_PHER_CTRL_DMA_CHx_IF_QSPI_TX:
  177. case SYSCTRL_PHER_CTRL_DMA_CHx_IF_HSPI_TX:
  178. hwDMA->SAR_L = DMA_InitStruct->DMA_MemoryBaseAddr;
  179. hwDMA->DAR_L = DMA_InitStruct->DMA_PeripheralBaseAddr;
  180. hwDMA->CTL_L = DMA_CTL_TT_FC_Memory_to_Peripheral_Set|
  181. (DMA_InitStruct->DMA_MemoryBurstSize << DMA_CTL_SRC_MSIZE_Pos)|
  182. (DMA_InitStruct->DMA_PeripheralBurstSize << DMA_CTL_DEST_MSIZE_Pos)|
  183. (DMA_InitStruct->DMA_MemoryInc << DMA_CTL_SINC_Pos)|
  184. (DMA_InitStruct->DMA_PeripheralInc << DMA_CTL_DINC_Pos)|
  185. (DMA_InitStruct->DMA_MemoryDataSize << DMA_CTL_SRC_TR_WIDTH_Pos)|
  186. (DMA_InitStruct->DMA_PeripheralDataSize << DMA_CTL_DST_TR_WIDTH_Pos);
  187. hwDMAChannal[Stream].TxDir = 1;
  188. // hwDMA->CFG_L = (1 << 18);
  189. hwDMA->CFG_L = 0;
  190. break;
  191. default:
  192. hwDMA->SAR_L = DMA_InitStruct->DMA_PeripheralBaseAddr;
  193. hwDMA->DAR_L = DMA_InitStruct->DMA_MemoryBaseAddr;
  194. hwDMA->CTL_L = DMA_CTL_TT_FC_Peripheral_to_Memory_Set|
  195. (DMA_InitStruct->DMA_PeripheralBurstSize << DMA_CTL_SRC_MSIZE_Pos)|
  196. (DMA_InitStruct->DMA_MemoryBurstSize << DMA_CTL_DEST_MSIZE_Pos)|
  197. (DMA_InitStruct->DMA_PeripheralInc << DMA_CTL_SINC_Pos)|
  198. (DMA_InitStruct->DMA_MemoryInc << DMA_CTL_DINC_Pos)|
  199. (DMA_InitStruct->DMA_PeripheralDataSize << DMA_CTL_SRC_TR_WIDTH_Pos)|
  200. (DMA_InitStruct->DMA_MemoryDataSize << DMA_CTL_DST_TR_WIDTH_Pos);
  201. hwDMAChannal[Stream].TxDir = 0;
  202. hwDMA->CFG_L = 0;
  203. break;
  204. }
  205. hwDMA->CFG_L |= DMA_InitStruct->DMA_Priority;
  206. hwDMA->CFG_H |= (Stream << DMA_CFG_DEST_PER_Pos) | (Stream << DMA_CFG_SRC_PER_Pos);
  207. if (Stream <= DMA1_STREAM_3)
  208. {
  209. tmpChannelxBit = (Stream - DMA1_STREAM_0) * 8;
  210. SYSCTRL->DMA_CHAN = (SYSCTRL->DMA_CHAN & ~(0x0000003f << tmpChannelxBit)) | (DMA_InitStruct->DMA_Peripheral << tmpChannelxBit);
  211. }
  212. else
  213. {
  214. tmpChannelxBit = (Stream - DMA1_STREAM_4) * 8;
  215. SYSCTRL->DMA_CHAN1 = (SYSCTRL->DMA_CHAN1 & ~(0x0000003f << tmpChannelxBit)) | (DMA_InitStruct->DMA_Peripheral << tmpChannelxBit);
  216. }
  217. return 0;
  218. }
  219. int DMA_StartStream(uint8_t Stream, const void *Data, uint32_t Len, CBFuncEx_t CB, void *pUserData, uint8_t NeedIrq)
  220. {
  221. uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index;
  222. if (DMA->ChEnReg_L & tmpChannelxBit)
  223. {
  224. return -1;
  225. }
  226. DMA_ForceStartStream(Stream, Data, Len, CB, pUserData, NeedIrq);
  227. return 0;
  228. }
  229. void DMA_ForceStartStream(uint8_t Stream, const void *Data, uint32_t Len, CBFuncEx_t CB, void *pUserData, uint8_t NeedIrq)
  230. {
  231. DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
  232. volatile uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index;
  233. DMA->ChEnReg_L = (tmpChannelxBit << 8);
  234. while(DMA->ChEnReg_L & tmpChannelxBit) {;}
  235. if (hwDMAChannal[Stream].TxDir)
  236. {
  237. hwDMA->SAR_L = (uint32_t)Data;
  238. }
  239. else
  240. {
  241. hwDMA->DAR_L = (uint32_t)Data;
  242. }
  243. hwDMA->CTL_H &= ~DMA_CTL_BLOCK_TS_Mask;
  244. hwDMA->CTL_H |= Len;
  245. tmpChannelxBit = (tmpChannelxBit << 8) + tmpChannelxBit;
  246. if (NeedIrq)
  247. {
  248. hwDMA->CTL_L |= DMA_CTL_INT_EN_Set;
  249. }
  250. else
  251. {
  252. hwDMA->CTL_L &= ~DMA_CTL_INT_EN_Set;
  253. }
  254. hwDMAChannal[Stream].pData = pUserData;
  255. if (CB)
  256. {
  257. hwDMAChannal[Stream].CB = CB;
  258. }
  259. else
  260. {
  261. hwDMAChannal[Stream].CB = DMA_DummyCB;
  262. }
  263. DMA->ChEnReg_L = tmpChannelxBit;
  264. }
  265. void DMA_ClearStreamFlag(uint8_t Stream)
  266. {
  267. DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
  268. uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index;
  269. DMA->ClearTfr_L = tmpChannelxBit;
  270. DMA->ClearBlock_L = tmpChannelxBit;
  271. DMA->ClearSrcTran_L = tmpChannelxBit;
  272. DMA->ClearDstTran_L = tmpChannelxBit;
  273. DMA->ClearErr_L = tmpChannelxBit;
  274. }
  275. void DMA_StopStream(uint8_t Stream)
  276. {
  277. DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
  278. uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index;
  279. DMA->ChEnReg_L = (tmpChannelxBit << 8);
  280. DMA->ClearTfr_L = tmpChannelxBit;
  281. DMA->ClearBlock_L = tmpChannelxBit;
  282. DMA->ClearSrcTran_L = tmpChannelxBit;
  283. DMA->ClearDstTran_L = tmpChannelxBit;
  284. DMA->ClearErr_L = tmpChannelxBit;
  285. }
  286. uint32_t DMA_GetRemainingDataLength(uint8_t Stream)
  287. {
  288. return 0;
  289. }
  290. uint32_t DMA_GetDataLength(uint8_t Stream, uint32_t FirstAddress)
  291. {
  292. DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
  293. return (hwDMA->CTL_H);
  294. }
  295. static void DMA_IrqHandle(int32_t IrqLine, void *pData)
  296. {
  297. uint32_t i;
  298. // DBG("%x", DMA->StatusTfr_L);
  299. if (DMA->StatusInt_L & (1 << 0))
  300. {
  301. for(i = 0; i < DMA_STREAM_QTY; i++)
  302. {
  303. if (DMA->StatusTfr_L & (1 << i))
  304. {
  305. DMA->ClearTfr_L = (1 << i);
  306. hwDMAChannal[i].CB(hwDMAChannal[i].pData, 0);
  307. }
  308. }
  309. }
  310. if (DMA->StatusInt_L & (1 << 4))
  311. {
  312. for(i = 0; i < DMA_STREAM_QTY; i++)
  313. {
  314. if (DMA->StatusErr_L & (1 << i))
  315. {
  316. DMA->ClearErr_L = (1 << i);
  317. hwDMAChannal[i].CB(hwDMAChannal[i].pData, 0xffffffff);
  318. }
  319. }
  320. }
  321. DMA->ClearBlock_L = 0x000000ff;
  322. DMA->ClearSrcTran_L = 0x000000ff;
  323. DMA->ClearDstTran_L = 0x000000ff;
  324. }
  325. void DMA_GlobalInit(void)
  326. {
  327. ISR_SetHandler(DMA_IRQn, DMA_IrqHandle, NULL);
  328. #ifdef __BUILD_OS__
  329. ISR_SetPriority(DMA_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 2);
  330. #else
  331. ISR_SetPriority(DMA_IRQn, 3);
  332. #endif
  333. DMA->DmaCfgReg_L = 1;
  334. DMA->ChEnReg_L = 0x0000ff00;
  335. ISR_OnOff(DMA_IRQn, 1);
  336. DMA->MaskTfr_L = 0x0000ffff;
  337. DMA->MaskErr_L = 0x0000ffff;
  338. }
  339. void DMA_PrintReg(uint8_t Stream)
  340. {
  341. DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
  342. DBG("%d, %d, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", Stream, hwDMAChannal[Stream].TxDir, hwDMA->SAR_L, hwDMA->DAR_L, hwDMA->CTL_H, hwDMA->CTL_L, hwDMA->CFG_L);
  343. }
  344. void DMA_PrintGlobalReg(void)
  345. {
  346. DBG("global 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", SYSCTRL->DMA_CHAN, SYSCTRL->DMA_CHAN1, DMA->StatusTfr_L,
  347. DMA->StatusErr_L, DMA->ChEnReg_L, DMA->DmaCfgReg_L);
  348. }