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 "core_irq.h"
22 #include "user.h"
23 typedef struct
24 {
25 DMA_TypeDef *RegBase;
26 const uint32_t Index;
27 CBFuncEx_t CB;
28 void *pData;
29 uint8_t TxDir;
30 }DMAChannal_struct;
31
32 /************ operation definition for DMA DMA_CTL_H REGISTER ************/
33 #define DMA_CTL_BLOCK_TS_Pos (0)
34 #define DMA_CTL_BLOCK_TS_Mask (0x0fffU<<DMA_CTL_BLOCK_TS_Pos)
35
36 /************ operation definition for DMA DMA_CTL_L REGISTER ************/
37 #define DMA_CTL_TT_FC_Pos (20)
38 #define DMA_CTL_TT_FC_Mask (0x07U<<DMA_CTL_TT_FC_Pos)
39
40 #define DMA_CTL_TT_FC_Memory_to_Memory_Set (0x00U<<DMA_CTL_TT_FC_Pos)
41 #define DMA_CTL_TT_FC_Memory_to_Peripheral_Set (0x01U<<DMA_CTL_TT_FC_Pos)
42 #define DMA_CTL_TT_FC_Peripheral_to_Memory_Set (0x02U<<DMA_CTL_TT_FC_Pos)
43 #define DMA_CTL_TT_FC_Peripheral_to_Memory_P_Set (0x04U<<DMA_CTL_TT_FC_Pos)
44 #define DMA_CTL_TT_FC_Memory_to_Peripheral_P_Set (0x06U<<DMA_CTL_TT_FC_Pos)
45
46 #define DMA_CTL_SRC_MSIZE_Pos (14)
47 #define DMA_CTL_SRC_MSIZE_Mask (0x07U<<DMA_CTL_SRC_MSIZE_Pos)
48
49 #define DMA_CTL_DEST_MSIZE_Pos (11)
50 #define DMA_CTL_DEST_MSIZE_Mask (0x07U<<DMA_CTL_DEST_MSIZE_Pos)
51
52 #define DMA_CTL_SINC_Pos (9)
53 #define DMA_CTL_SINC_Mask (0x03U<<DMA_CTL_SINC_Pos)
54
55 #define DMA_CTL_DINC_Pos (7)
56 #define DMA_CTL_DINC_Mask (0x03U<<DMA_CTL_DINC_Pos)
57
58 #define DMA_CTL_SRC_TR_WIDTH_Pos (4)
59 #define DMA_CTL_SRC_TR_WIDTH_Mask (0x07U<<DMA_CTL_SRC_TR_WIDTH_Pos)
60
61 #define DMA_CTL_DST_TR_WIDTH_Pos (1)
62 #define DMA_CTL_DST_TR_WIDTH_Mask (0x07U<<DMA_CTL_DST_TR_WIDTH_Pos)
63
64 #define DMA_CTL_INT_EN_Set ((uint32_t)0x01)
65
66 /************ operation definition for DMA DMA_CFG_L REGISTER ************/
67 #define DMA_CFG_HS_SEL_SRC_Pos (11)
68 #define DMA_CFG_HS_SEL_SRC_Mask (0x01U<<DMA_CFG_HS_SEL_SRC_Pos)/*0 HARD 1 SOFT*/
69
70 #define DMA_CFG_HS_SEL_DST_Pos (10)
71 #define DMA_CFG_HS_SEL_DST_Mask (0x01U<<DMA_CFG_HS_SEL_DST_Pos)
72
73 /************ operation definition for DMA DMA_CFG_H REGISTER ************/
74 #define DMA_CFG_DEST_PER_Pos (11)
75 #define DMA_CFG_DEST_PER_Mask (0x07U<<DMA_CFG_DEST_PER_Pos)/*need write current channel num*/
76
77 #define DMA_CFG_SRC_PER_Pos (7)
78 #define DMA_CFG_SRC_PER_Mask (0x07U<<DMA_CFG_SRC_PER_Pos)/*need write current channel num*/
79
80 /************ operation definition for DMA DMA_LLP_L REGISTER ************/
81 #define DMAC_LLP_NEXT_LLI_MSK (0x3)
82
83 static DMAChannal_struct hwDMAChannal[DMA_STREAM_QTY] = {
84 {
85 DMA_Channel_0,
86 1 << 0,
87 },
88 {
89 DMA_Channel_1,
90 1 << 1,
91 },
92 {
93 DMA_Channel_2,
94 1 << 2,
95 },
96 {
97 DMA_Channel_3,
98 1 << 3,
99 },
100 {
101 DMA_Channel_4,
102 1 << 4,
103 },
104 {
105 DMA_Channel_5,
106 1 << 5,
107 },
108 {
109 DMA_Channel_6,
110 1 << 6,
111 },
112 {
113 DMA_Channel_7,
114 1 << 7,
115 },
116 };
117
118 static uint8_t DMALock[(DMA_STREAM_QTY - 1)/8 + 1];
119
DMA_DummyCB(void * pData,void * pParam)120 static int32_t DMA_DummyCB(void *pData, void *pParam)
121 {
122 return 0;
123 }
124
DMA_TakeStream(uint8_t Stream)125 void *DMA_TakeStream(uint8_t Stream)
126 {
127 if (BSP_TestBit(DMALock, Stream))
128 {
129 return NULL;
130 }
131 BSP_SetBit(DMALock, Stream, 1);
132 return &hwDMAChannal[Stream];
133 }
134
DMA_CheckStreamLock(uint8_t Stream)135 int DMA_CheckStreamLock(uint8_t Stream)
136 {
137 return BSP_TestBit(DMALock, Stream);
138 }
139
DMA_ReleaseStream(uint8_t Stream)140 void DMA_ReleaseStream(uint8_t Stream)
141 {
142 BSP_SetBit(DMALock, Stream, 0);
143 }
144
DMA_CheckStreamBusy(uint8_t Stream)145 uint8_t DMA_CheckStreamBusy(uint8_t Stream)
146 {
147 DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
148 uint32_t BaseIndex = hwDMAChannal[Stream].Index;
149 if (DMA->ChEnReg_L & BaseIndex)
150 {
151 return 1;
152 }
153
154 return 0;
155 }
156
DMA_BaseConfig(void * Config)157 void DMA_BaseConfig(void *Config)
158 {
159 DMA_InitTypeDef *DMA_InitStruct = (DMA_InitTypeDef *)Config;
160 memset(DMA_InitStruct, 0, sizeof(DMA_InitTypeDef));
161 DMA_InitStruct->DMA_PeripheralBurstSize = DMA_BurstSize_1;
162 DMA_InitStruct->DMA_PeripheralDataSize = DMA_DataSize_Byte;
163 DMA_InitStruct->DMA_PeripheralInc = DMA_Inc_Nochange;
164 DMA_InitStruct->DMA_MemoryBurstSize = DMA_BurstSize_1;
165 DMA_InitStruct->DMA_MemoryDataSize = DMA_DataSize_Byte;
166 DMA_InitStruct->DMA_MemoryInc = DMA_Inc_Increment;
167 }
168
DMA_ConfigStream(uint8_t Stream,void * Config)169 int DMA_ConfigStream(uint8_t Stream, void *Config)
170 {
171 DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
172 uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index;
173 DMA_InitTypeDef *DMA_InitStruct = (DMA_InitTypeDef *)Config;
174 if (DMA->ChEnReg_L & tmpChannelxBit)
175 {
176 return -1;
177 }
178 DMA->ClearTfr_L = tmpChannelxBit;
179 DMA->ClearBlock_L = tmpChannelxBit;
180 DMA->ClearSrcTran_L = tmpChannelxBit;
181 DMA->ClearDstTran_L = tmpChannelxBit;
182 DMA->ClearErr_L = tmpChannelxBit;
183 if((DMA->RawBlock_L & tmpChannelxBit) | (DMA->RawDstTran_L & tmpChannelxBit) | (DMA->RawErr_L & tmpChannelxBit) \
184 | (DMA->RawSrcTran_L & tmpChannelxBit) | (DMA->RawTfr_L & tmpChannelxBit) | (DMA->StatusBlock_L & tmpChannelxBit) \
185 | (DMA->StatusDstTran_L & tmpChannelxBit) | (DMA->StatusErr_L & tmpChannelxBit) | (DMA->StatusSrcTran_L & tmpChannelxBit) \
186 | (DMA->StatusTfr_L & tmpChannelxBit) )
187 {
188 return -1;
189 }
190 switch(DMA_InitStruct->DMA_Peripheral)
191 {
192 case SYSCTRL_PHER_CTRL_DMA_CHx_IF_LCD:
193 case SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART0_TX:
194 case SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART1_TX:
195 case SYSCTRL_PHER_CTRL_DMA_CHx_IF_DAC:
196 case SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI0_TX:
197 case SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI1_TX:
198 case SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI2_TX:
199 case SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART2_TX:
200 case SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART3_TX:
201 case SYSCTRL_PHER_CTRL_DMA_CHx_IF_I2C_TX:
202 case SYSCTRL_PHER_CTRL_DMA_CHx_IF_QSPI_TX:
203 case SYSCTRL_PHER_CTRL_DMA_CHx_IF_HSPI_TX:
204 hwDMA->SAR_L = DMA_InitStruct->DMA_MemoryBaseAddr;
205 hwDMA->DAR_L = DMA_InitStruct->DMA_PeripheralBaseAddr;
206 hwDMA->CTL_L = DMA_CTL_TT_FC_Memory_to_Peripheral_Set|
207 (DMA_InitStruct->DMA_MemoryBurstSize << DMA_CTL_SRC_MSIZE_Pos)|
208 (DMA_InitStruct->DMA_PeripheralBurstSize << DMA_CTL_DEST_MSIZE_Pos)|
209 (DMA_InitStruct->DMA_MemoryInc << DMA_CTL_SINC_Pos)|
210 (DMA_InitStruct->DMA_PeripheralInc << DMA_CTL_DINC_Pos)|
211 (DMA_InitStruct->DMA_MemoryDataSize << DMA_CTL_SRC_TR_WIDTH_Pos)|
212 (DMA_InitStruct->DMA_PeripheralDataSize << DMA_CTL_DST_TR_WIDTH_Pos);
213
214 hwDMAChannal[Stream].TxDir = 1;
215 /* hwDMA->CFG_L = (1 << 18); */
216 hwDMA->CFG_L = 0;
217 break;
218 default:
219 hwDMA->SAR_L = DMA_InitStruct->DMA_PeripheralBaseAddr;
220 hwDMA->DAR_L = DMA_InitStruct->DMA_MemoryBaseAddr;
221 hwDMA->CTL_L = DMA_CTL_TT_FC_Peripheral_to_Memory_Set|
222 (DMA_InitStruct->DMA_PeripheralBurstSize << DMA_CTL_SRC_MSIZE_Pos)|
223 (DMA_InitStruct->DMA_MemoryBurstSize << DMA_CTL_DEST_MSIZE_Pos)|
224 (DMA_InitStruct->DMA_PeripheralInc << DMA_CTL_SINC_Pos)|
225 (DMA_InitStruct->DMA_MemoryInc << DMA_CTL_DINC_Pos)|
226 (DMA_InitStruct->DMA_PeripheralDataSize << DMA_CTL_SRC_TR_WIDTH_Pos)|
227 (DMA_InitStruct->DMA_MemoryDataSize << DMA_CTL_DST_TR_WIDTH_Pos);
228 hwDMAChannal[Stream].TxDir = 0;
229 hwDMA->CFG_L = 0;
230 break;
231 }
232 hwDMA->CFG_L |= DMA_InitStruct->DMA_Priority;
233 hwDMA->CFG_H |= (Stream << DMA_CFG_DEST_PER_Pos) | (Stream << DMA_CFG_SRC_PER_Pos);
234
235 if (Stream <= DMA1_STREAM_3)
236 {
237 tmpChannelxBit = (Stream - DMA1_STREAM_0) * 8;
238 SYSCTRL->DMA_CHAN = (SYSCTRL->DMA_CHAN & ~(0x0000003f << tmpChannelxBit)) | (DMA_InitStruct->DMA_Peripheral << tmpChannelxBit);
239 }
240 else
241 {
242 tmpChannelxBit = (Stream - DMA1_STREAM_4) * 8;
243 SYSCTRL->DMA_CHAN1 = (SYSCTRL->DMA_CHAN1 & ~(0x0000003f << tmpChannelxBit)) | (DMA_InitStruct->DMA_Peripheral << tmpChannelxBit);
244 }
245 return 0;
246 }
247
DMA_StartStream(uint8_t Stream,const void * Data,uint32_t Len,CBFuncEx_t CB,void * pUserData,uint8_t NeedIrq)248 int DMA_StartStream(uint8_t Stream, const void *Data, uint32_t Len, CBFuncEx_t CB, void *pUserData, uint8_t NeedIrq)
249 {
250 uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index;
251 if (DMA->ChEnReg_L & tmpChannelxBit)
252 {
253 return -1;
254 }
255 DMA_ForceStartStream(Stream, Data, Len, CB, pUserData, NeedIrq);
256 return 0;
257 }
258
DMA_ForceStartStream(uint8_t Stream,const void * Data,uint32_t Len,CBFuncEx_t CB,void * pUserData,uint8_t NeedIrq)259 void DMA_ForceStartStream(uint8_t Stream, const void *Data, uint32_t Len, CBFuncEx_t CB, void *pUserData, uint8_t NeedIrq)
260 {
261 DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
262 volatile uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index;
263 DMA->ChEnReg_L = (tmpChannelxBit << 8);
264 while(DMA->ChEnReg_L & tmpChannelxBit) {;}
265
266 if (hwDMAChannal[Stream].TxDir)
267 {
268 hwDMA->SAR_L = (uint32_t)Data;
269 }
270 else
271 {
272 hwDMA->DAR_L = (uint32_t)Data;
273 }
274 hwDMA->CTL_H &= ~DMA_CTL_BLOCK_TS_Mask;
275 hwDMA->CTL_H |= Len;
276
277 tmpChannelxBit = (tmpChannelxBit << 8) + tmpChannelxBit;
278 if (NeedIrq)
279 {
280 hwDMA->CTL_L |= DMA_CTL_INT_EN_Set;
281 }
282 else
283 {
284 hwDMA->CTL_L &= ~DMA_CTL_INT_EN_Set;
285 }
286 hwDMAChannal[Stream].pData = pUserData;
287 if (CB)
288 {
289 hwDMAChannal[Stream].CB = CB;
290 }
291 else
292 {
293 hwDMAChannal[Stream].CB = DMA_DummyCB;
294 }
295 DMA->ChEnReg_L = tmpChannelxBit;
296 }
297
DMA_ClearStreamFlag(uint8_t Stream)298 void DMA_ClearStreamFlag(uint8_t Stream)
299 {
300 DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
301 uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index;
302 DMA->ClearTfr_L = tmpChannelxBit;
303 DMA->ClearBlock_L = tmpChannelxBit;
304 DMA->ClearSrcTran_L = tmpChannelxBit;
305 DMA->ClearDstTran_L = tmpChannelxBit;
306 DMA->ClearErr_L = tmpChannelxBit;
307 }
308
DMA_StopStream(uint8_t Stream)309 void DMA_StopStream(uint8_t Stream)
310 {
311 if (Stream >= DMA_STREAM_QTY) return;
312 DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
313 uint32_t tmpChannelxBit = hwDMAChannal[Stream].Index;
314 DMA->ChEnReg_L = (tmpChannelxBit << 8);
315 DMA->ClearTfr_L = tmpChannelxBit;
316 DMA->ClearBlock_L = tmpChannelxBit;
317 DMA->ClearSrcTran_L = tmpChannelxBit;
318 DMA->ClearDstTran_L = tmpChannelxBit;
319 DMA->ClearErr_L = tmpChannelxBit;
320 }
321
DMA_GetRemainingDataLength(uint8_t Stream)322 uint32_t DMA_GetRemainingDataLength(uint8_t Stream)
323 {
324 return 0;
325 }
326
DMA_GetDataLength(uint8_t Stream,uint32_t FirstAddress)327 uint32_t DMA_GetDataLength(uint8_t Stream, uint32_t FirstAddress)
328 {
329 DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
330 return (hwDMA->CTL_H);
331 }
332
DMA_IrqHandle(int32_t IrqLine,void * pData)333 static void DMA_IrqHandle(int32_t IrqLine, void *pData)
334 {
335 uint32_t i;
336 /* DBG("%x", DMA->StatusTfr_L); */
337 if (DMA->StatusInt_L & (1 << 0))
338 {
339 for(i = 0; i < DMA_STREAM_QTY; i++)
340 {
341 if (DMA->StatusTfr_L & (1 << i))
342 {
343 DMA->ClearTfr_L = (1 << i);
344 hwDMAChannal[i].CB(hwDMAChannal[i].pData, 0);
345 }
346 }
347 }
348 if (DMA->StatusInt_L & (1 << 4))
349 {
350 for(i = 0; i < DMA_STREAM_QTY; i++)
351 {
352 if (DMA->StatusErr_L & (1 << i))
353 {
354 DMA->ClearErr_L = (1 << i);
355 hwDMAChannal[i].CB(hwDMAChannal[i].pData, (void *)0xffffffff);
356 }
357 }
358 }
359 DMA->ClearBlock_L = 0x000000ff;
360 DMA->ClearSrcTran_L = 0x000000ff;
361 DMA->ClearDstTran_L = 0x000000ff;
362 }
363
DMA_GlobalInit(void)364 void DMA_GlobalInit(void)
365 {
366 ISR_SetHandler(DMA_IRQn, DMA_IrqHandle, NULL);
367 #ifdef __BUILD_OS__
368 ISR_SetPriority(DMA_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 2);
369 #else
370 ISR_SetPriority(DMA_IRQn, 3);
371 #endif
372 DMA->DmaCfgReg_L = 1;
373 DMA->ChEnReg_L = 0x0000ff00;
374 ISR_OnOff(DMA_IRQn, 1);
375 DMA->MaskTfr_L = 0x0000ffff;
376 DMA->MaskErr_L = 0x0000ffff;
377 }
378
DMA_PrintReg(uint8_t Stream)379 void DMA_PrintReg(uint8_t Stream)
380 {
381 DMA_TypeDef *hwDMA = hwDMAChannal[Stream].RegBase;
382 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);
383 }
384
DMA_PrintGlobalReg(void)385 void DMA_PrintGlobalReg(void)
386 {
387 DBG("global 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", SYSCTRL->DMA_CHAN, SYSCTRL->DMA_CHAN1, DMA->StatusTfr_L,
388 DMA->StatusErr_L, DMA->ChEnReg_L, DMA->DmaCfgReg_L);
389 }
390