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