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 
22 #include "user.h"
23 
24 #define HSPIM_CR0_CLEAR_MASK                                        ((uint32_t)~0xFFEEFFFF)
25 #define HSPIM_CR0_MODE_SELECT_CLEAR_MASK                            ((uint32_t)~0x1C00)
26 #define HSPIM_CR1_CLEAR_MASK                                        ((uint32_t)~0xFFFFF)
27 #define HSPIM_FCR_CLEAR_MASK                                        ((uint32_t)~0x3F3F3F00)
28 #define HSPIM_DCR_RECEIVE_LEVEL_CLEAR_MASK                          ((uint32_t)~0x3F80)
29 #define HSPIM_DCR_TRANSMIT_LEVEL_CLEAR_MASK                         ((uint32_t)~0x7F)
30 
31 
32 #define HSPIM_CR0_PARAM_ENABLE_POS                                  (0x18)
33 #define HSPIM_CR0_PARAM_DMA_RECEIVE_ENABLE_POS                      (0x14)
34 #define HSPIM_CR0_PARAM_DMA_TRANSMIT_ENABLE_POS                     (0x10)
35 #define HSPIM_CR0_PARAM_INTERRPUT_RX_POS                            (0x0F)
36 #define HSPIM_CR0_PARAM_INTERRPUT_TX_POS                            (0x0E)
37 #define HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS                        (0x0D)
38 #define HSPIM_CR0_PARAM_MODEL_SELECT_POS                            (0x0A)
39 #define HSPIM_CR0_PARAM_FIRST_BIT_POS                               (0x09)
40 #define HSPIM_CR0_PARAM_CPOL_POS                                    (0x08)
41 #define HSPIM_CR0_PARAM_CPHA_POS                                    (0x07)
42 #define HSPIM_CR0_PARAM_DIVIDE_ENABLE_POS                           (0x02)
43 #define HSPIM_CR0_PARAM_TRANSMIT_ENABLE_POS                         (0x01)
44 #define HSPIM_CR0_PARAM_BUSY_POS                                    (0x00)
45 
46 #define HSPIM_CR1_PARAM_BAUDRATE_POS                                (0x0A)
47 #define HSPIM_CR1_PARAM_RECEIVE_DATA_LENGTH_POS                     (0x00)
48 
49 #define HSPIM_DCR_PARAM_DMA_RECEIVE_LEVEL_POS                       (0x07)
50 #define HSPIM_DCR_PARAM_DMA_TRANSMIT_LEVEL_POS                      (0x00)
51 
52 #define HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS         (0x08)
53 #define HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS            (0x10)
54 
55 #define HSPIM_SR_PUSH_FULL_TX                               (1 << 4)
56 #define HSPIM_SR_POP_EMPTY_RX                               (1 << 10)
57 #define HSPIM_FIFO_TX_NUM                                   (64)
58 #define HSPIM_FIFO_RX_NUM                                   (64)
59 #define HSPIM_FIFO_LEVEL                                    (48)
60 
61 #define SPIM_FIFO_TX_NUM                                    (16)
62 #define SPIM_FIFO_RX_NUM                                    (16)
63 #define SPIM_FIFO_RX_LEVEL                                  (7)
64 #define SPIM_FIFO_TX_LEVEL                                  (8)
65 typedef struct
66 {
67     const volatile void *RegBase;
68     const int32_t IrqLine;
69     const uint16_t DMATxChannel;
70     const uint16_t DMARxChannel;
71     CBFuncEx_t Callback;
72     void *pParam;
73     HANDLE Sem;
74     Buffer_Struct TxBuf;
75     Buffer_Struct RxBuf;
76     uint32_t Speed;
77     uint8_t DMATxStream;
78     uint8_t DMARxStream;
79     uint8_t Is16Bit;
80     uint8_t IsOnlyTx;
81     uint8_t IsBusy;
82     uint8_t IsBlockMode;
83 }SPI_ResourceStruct;
84 
85 static SPI_ResourceStruct prvSPI[SPI_MAX] = {
86         {
87                 HSPIM,
88                 SPI5_IRQn,
89                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_HSPI_TX,
90                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_HSPI_RX,
91         },
92         {
93                 SPIM0,
94                 SPI0_IRQn,
95                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI0_TX,
96                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI0_RX,
97         },
98         {
99                 SPIM1,
100                 SPI1_IRQn,
101                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI1_TX,
102                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI1_RX,
103         },
104         {
105                 SPIM2,
106                 SPI2_IRQn,
107                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI2_TX,
108                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI2_RX,
109         },
110         {
111                 SPIS0,
112                 SPI0_IRQn,
113                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI0_TX,
114                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_SPI0_RX,
115         },
116 };
117 
HSPI_IrqHandle(int32_t IrqLine,void * pData)118 static void HSPI_IrqHandle(int32_t IrqLine, void *pData)
119 {
120     uint32_t SpiID = HSPI_ID0;
121     uint32_t RxLevel, i, TxLen;
122     HSPIM_TypeDef *SPI = HSPIM;
123     volatile uint32_t DummyData;
124     if (!prvSPI[SpiID].IsBusy)
125     {
126 
127         ISR_Clear(prvSPI[SpiID].IrqLine);
128         ISR_OnOff(prvSPI[SpiID].IrqLine, 0);
129         return;
130     }
131     if (prvSPI[SpiID].RxBuf.Data)
132     {
133         while (prvSPI[SpiID].RxBuf.Pos < prvSPI[SpiID].RxBuf.MaxLen)
134         {
135             if (SPI->SR & HSPIM_SR_POP_EMPTY_RX)
136             {
137                 break;
138             }
139             else
140             {
141                 prvSPI[SpiID].RxBuf.Data[prvSPI[SpiID].RxBuf.Pos] = SPI->RDR;
142                 prvSPI[SpiID].RxBuf.Pos++;
143             }
144         }
145     }
146     else
147     {
148         while (prvSPI[SpiID].RxBuf.Pos < prvSPI[SpiID].RxBuf.MaxLen)
149         {
150             if (SPI->SR & HSPIM_SR_POP_EMPTY_RX)
151             {
152                 break;
153             }
154             else
155             {
156                 DummyData = SPI->RDR;
157                 prvSPI[SpiID].RxBuf.Pos++;
158             }
159         }
160     }
161 
162 
163     if (prvSPI[SpiID].RxBuf.Pos >= prvSPI[SpiID].RxBuf.MaxLen)
164     {
165         SPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS);
166         prvSPI[SpiID].IsBusy = 0;
167         ISR_Clear(prvSPI[SpiID].IrqLine);
168         ISR_OnOff(prvSPI[SpiID].IrqLine, 0);
169         if ((prvSPI[SpiID].TxBuf.Pos != prvSPI[SpiID].RxBuf.Pos) || (prvSPI[SpiID].RxBuf.Pos != prvSPI[SpiID].RxBuf.MaxLen))
170         {
171             DBG("%u, %u", prvSPI[SpiID].TxBuf.Pos, prvSPI[SpiID].RxBuf.Pos);
172         }
173 #ifdef __BUILD_OS__
174         if (prvSPI[SpiID].IsBlockMode)
175         {
176             OS_MutexRelease(prvSPI[SpiID].Sem);
177         }
178 #endif
179         prvSPI[SpiID].Callback((void *)SpiID, prvSPI[SpiID].pParam);
180         return;
181     }
182 
183     if (prvSPI[SpiID].TxBuf.Pos < prvSPI[SpiID].TxBuf.MaxLen)
184     {
185         i = 0;
186         TxLen = (HSPIM_FIFO_TX_NUM - (SPI->FSR & 0x0000003f));
187         if (TxLen > (prvSPI[SpiID].TxBuf.MaxLen -prvSPI[SpiID].TxBuf.Pos))
188         {
189             TxLen = prvSPI[SpiID].TxBuf.MaxLen - prvSPI[SpiID].TxBuf.Pos;
190         }
191         while((i < TxLen))
192         {
193             SPI->WDR = prvSPI[SpiID].TxBuf.Data[prvSPI[SpiID].TxBuf.Pos + i];
194             i++;
195         }
196         prvSPI[SpiID].TxBuf.Pos += TxLen;
197         if (prvSPI[SpiID].TxBuf.Pos >= prvSPI[SpiID].TxBuf.MaxLen)
198         {
199             SPI->FCR = (63 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(0 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(63);
200             SPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS);
201             SPI->CR0 |= (5 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS);
202         }
203     }
204     else
205     {
206         SPI->FCR = (63 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(0 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(63);
207         SPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS);
208         SPI->CR0 |= (5 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS);
209     }
210 }
211 
SPI_DMADoneCB(void * pData,void * pParam)212 static int32_t SPI_DMADoneCB(void *pData, void *pParam)
213 {
214     uint32_t SpiID = (uint32_t)pData;
215     uint32_t RxLevel;
216 
217     if (prvSPI[SpiID].RxBuf.MaxLen > prvSPI[SpiID].RxBuf.Pos)
218     {
219         RxLevel = ((prvSPI[SpiID].RxBuf.MaxLen -  prvSPI[SpiID].RxBuf.Pos) > 4080)?4000:(prvSPI[SpiID].RxBuf.MaxLen -  prvSPI[SpiID].RxBuf.Pos);
220 
221         DMA_ClearStreamFlag(prvSPI[SpiID].DMATxStream);
222 
223         DMA_ClearStreamFlag(prvSPI[SpiID].DMARxStream);
224 
225         if (prvSPI[SpiID].IsOnlyTx)
226         {
227             DMA_ForceStartStream(prvSPI[SpiID].DMATxStream, &prvSPI[SpiID].TxBuf.Data[prvSPI[SpiID].TxBuf.Pos], RxLevel, SPI_DMADoneCB, (void *)SpiID, 1);
228             DMA_ForceStartStream(prvSPI[SpiID].DMARxStream, &prvSPI[SpiID].RxBuf.Data[prvSPI[SpiID].RxBuf.Pos], RxLevel, NULL, NULL, 0);
229         }
230         else
231         {
232             DMA_ForceStartStream(prvSPI[SpiID].DMATxStream, &prvSPI[SpiID].TxBuf.Data[prvSPI[SpiID].TxBuf.Pos], RxLevel, NULL, NULL, 0);
233             DMA_ForceStartStream(prvSPI[SpiID].DMARxStream, &prvSPI[SpiID].RxBuf.Data[prvSPI[SpiID].RxBuf.Pos], RxLevel, SPI_DMADoneCB, (void *)SpiID, 1);
234         }
235         prvSPI[SpiID].RxBuf.Pos += RxLevel;
236         prvSPI[SpiID].TxBuf.Pos += RxLevel;
237     }
238 
239     else
240     {
241         prvSPI[SpiID].IsBusy = 0;
242         if ((prvSPI[SpiID].TxBuf.Pos != prvSPI[SpiID].RxBuf.Pos) || (prvSPI[SpiID].RxBuf.Pos != prvSPI[SpiID].RxBuf.MaxLen))
243         {
244             DBG("%u, %u", prvSPI[SpiID].TxBuf.Pos, prvSPI[SpiID].RxBuf.Pos);
245         }
246 #ifdef __BUILD_OS__
247         if (prvSPI[SpiID].IsBlockMode)
248         {
249             OS_MutexRelease(prvSPI[SpiID].Sem);
250         }
251 #endif
252         prvSPI[SpiID].Callback((void *)SpiID, prvSPI[SpiID].pParam);
253     }
254 
255 
256 }
257 
SPI_IrqHandle(int32_t IrqLine,void * pData)258 static void SPI_IrqHandle(int32_t IrqLine, void *pData)
259 {
260     uint32_t SpiID = (uint32_t)pData;
261     volatile uint32_t DummyData;
262     uint32_t RxLevel, SR, i, TxLen;
263     SPI_TypeDef *SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase;
264     if (!prvSPI[SpiID].IsBusy)
265     {
266         SR = SPI->ICR;
267         SPI->IMR = 0;
268         SPI->SER = 0;
269         ISR_Clear(prvSPI[SpiID].IrqLine);
270         ISR_OnOff(prvSPI[SpiID].IrqLine, 0);
271         return;
272     }
273     TxLen = SPIM_FIFO_TX_NUM - SPI->TXFLR;
274 
275     SR = SPI->ICR;
276     if (prvSPI[SpiID].RxBuf.Data)
277     {
278         while(SPI->RXFLR)
279         {
280             prvSPI[SpiID].RxBuf.Data[prvSPI[SpiID].RxBuf.Pos] = SPI->DR;
281             prvSPI[SpiID].RxBuf.Pos++;
282         }
283     }
284     else
285     {
286         while(SPI->RXFLR)
287         {
288             DummyData = SPI->DR;
289             prvSPI[SpiID].RxBuf.Pos++;
290         }
291     }
292 
293     if (prvSPI[SpiID].RxBuf.Pos >= prvSPI[SpiID].RxBuf.MaxLen)
294     {
295 
296         SR = SPI->ICR;
297         SPI->IMR = 0;
298         SPI->SER = 0;
299         prvSPI[SpiID].IsBusy = 0;
300         ISR_Clear(prvSPI[SpiID].IrqLine);
301         ISR_OnOff(prvSPI[SpiID].IrqLine, 0);
302         if (prvSPI[SpiID].TxBuf.Pos != prvSPI[SpiID].RxBuf.Pos)
303         {
304             DBG("%u, %u", prvSPI[SpiID].TxBuf.Pos, prvSPI[SpiID].RxBuf.Pos);
305         }
306 #ifdef __BUILD_OS__
307         if (prvSPI[SpiID].IsBlockMode)
308         {
309             OS_MutexRelease(prvSPI[SpiID].Sem);
310         }
311 #endif
312         prvSPI[SpiID].Callback((void *)SpiID, prvSPI[SpiID].pParam);
313         return;
314     }
315 
316     if (prvSPI[SpiID].TxBuf.Pos < prvSPI[SpiID].TxBuf.MaxLen)
317     {
318         i = 0;
319         if (TxLen > (prvSPI[SpiID].TxBuf.MaxLen -prvSPI[SpiID].TxBuf.Pos))
320         {
321             TxLen = prvSPI[SpiID].TxBuf.MaxLen - prvSPI[SpiID].TxBuf.Pos;
322         }
323         while((i < TxLen))
324         {
325             SPI->DR = prvSPI[SpiID].TxBuf.Data[prvSPI[SpiID].TxBuf.Pos + i];
326             i++;
327         }
328         prvSPI[SpiID].TxBuf.Pos += i;
329     }
330     else
331     {
332 
333         if ((prvSPI[SpiID].RxBuf.MaxLen - prvSPI[SpiID].RxBuf.Pos) >= SPIM_FIFO_RX_NUM)
334         {
335             SPI->RXFTLR = (SPIM_FIFO_RX_NUM - 1);
336         }
337         else
338         {
339             SPI->RXFTLR = prvSPI[SpiID].RxBuf.MaxLen - prvSPI[SpiID].RxBuf.Pos - 1;
340         }
341         SPI->IMR = SPI_IMR_RXOIM|SPI_IMR_RXFIM;
342     }
343 }
344 
SPI_DummyCB(void * pData,void * pParam)345 static int32_t SPI_DummyCB(void *pData, void *pParam)
346 {
347     return 0;
348 }
349 
HSPI_MasterInit(uint8_t SpiID,uint8_t Mode,uint32_t Speed)350 static void HSPI_MasterInit(uint8_t SpiID, uint8_t Mode, uint32_t Speed)
351 {
352     HSPIM_TypeDef *SPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase;
353     uint32_t div = (SystemCoreClock / Speed) >> 1;
354     uint32_t ctrl = (1 << 24) | (1 << 10) | (1 << 2) | (1 << 1);
355     switch(Mode)
356     {
357     case SPI_MODE_0:
358         break;
359     case SPI_MODE_1:
360         ctrl |= (1 << HSPIM_CR0_PARAM_CPHA_POS);
361         break;
362     case SPI_MODE_2:
363         ctrl |= (1 << HSPIM_CR0_PARAM_CPOL_POS);
364         break;
365     case SPI_MODE_3:
366         ctrl |= (1 << HSPIM_CR0_PARAM_CPOL_POS)|(1 << HSPIM_CR0_PARAM_CPHA_POS);
367         break;
368     }
369     SPI->CR1 = (div << HSPIM_CR1_PARAM_BAUDRATE_POS) + 1;
370     SPI->CR0 = ctrl;
371     SPI->DCR = 30|(1 << 7);
372     prvSPI[SpiID].Speed = (SystemCoreClock >> 1) / div;
373 
374     ISR_SetHandler(prvSPI[SpiID].IrqLine, HSPI_IrqHandle, (uint32_t)SpiID);
375 #ifdef __BUILD_OS__
376     ISR_SetPriority(prvSPI[SpiID].IrqLine, IRQ_MAX_PRIORITY + 1);
377 #else
378     ISR_SetPriority(prvSPI[SpiID].IrqLine, 3);
379 #endif
380     ISR_Clear(prvSPI[SpiID].IrqLine);
381     ISR_OnOff(prvSPI[SpiID].IrqLine, 0);
382 
383 }
384 
SPI_MasterInit(uint8_t SpiID,uint8_t DataBit,uint8_t Mode,uint32_t Speed,CBFuncEx_t CB,void * pUserData)385 void SPI_MasterInit(uint8_t SpiID, uint8_t DataBit, uint8_t Mode, uint32_t Speed, CBFuncEx_t CB, void *pUserData)
386 {
387     SPI_TypeDef *SPI;
388     uint32_t ctrl;
389     uint32_t div;
390     switch(SpiID)
391     {
392     case HSPI_ID0:
393         HSPI_MasterInit(SpiID, Mode, Speed);
394         break;
395     case SPI_ID0:
396         SYSCTRL->PHER_CTRL &= ~SYSCTRL_PHER_CTRL_SPI0_SLV_EN;
397     case SPI_ID1:
398     case SPI_ID2:
399         SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase;
400         SPI->SSIENR = 0;
401         SPI->SER = 0;
402         SPI->IMR = 0;
403         SPI->DMACR = 0;
404         ctrl = DataBit - 1;
405         switch(Mode)
406         {
407         case SPI_MODE_0:
408             break;
409         case SPI_MODE_1:
410             ctrl |= SPI_CTRLR0_SCPH;
411             break;
412         case SPI_MODE_2:
413             ctrl |= SPI_CTRLR0_SCPOL;
414             break;
415         case SPI_MODE_3:
416             ctrl |= SPI_CTRLR0_SCPOL|SPI_CTRLR0_SCPH;
417             break;
418         }
419         div = (SystemCoreClock >> 2) / Speed;
420         if (div % 2) div++;
421         prvSPI[SpiID].Speed = (SystemCoreClock >> 2) / div;
422         SPI->CTRLR0 = ctrl;
423         SPI->BAUDR = div;
424         SPI->TXFTLR = 0;
425         SPI->RXFTLR = 0;
426         SPI->DMATDLR = 7;
427         SPI->DMARDLR = 0;
428         ISR_SetHandler(prvSPI[SpiID].IrqLine, SPI_IrqHandle, (uint32_t)SpiID);
429 #ifdef __BUILD_OS__
430         ISR_SetPriority(prvSPI[SpiID].IrqLine, IRQ_LOWEST_PRIORITY - 2);
431 #else
432         ISR_SetPriority(prvSPI[SpiID].IrqLine, 5);
433 #endif
434         ISR_Clear(prvSPI[SpiID].IrqLine);
435         ISR_OnOff(prvSPI[SpiID].IrqLine, 0);
436         SPI->SSIENR = 1;
437         break;
438 //  case SPI_ID3:
439 //      SYSCTRL->PHER_CTRL |= SYSCTRL_PHER_CTRL_SPI0_SLV_EN;
440 //      break;
441     default:
442         return;
443     }
444     prvSPI[SpiID].DMATxStream = 0xff;
445     prvSPI[SpiID].DMARxStream = 0xff;
446     if (CB)
447     {
448         prvSPI[SpiID].Callback = CB;
449     }
450     else
451     {
452         prvSPI[SpiID].Callback = SPI_DummyCB;
453     }
454     prvSPI[SpiID].pParam = pUserData;
455 #ifdef __BUILD_OS__
456     if (!prvSPI[SpiID].Sem)
457     {
458         prvSPI[SpiID].Sem = OS_MutexCreate();
459     }
460 #endif
461 }
462 
463 
SPI_SetTxOnlyFlag(uint8_t SpiID,uint8_t OnOff)464 void SPI_SetTxOnlyFlag(uint8_t SpiID, uint8_t OnOff)
465 {
466     prvSPI[SpiID].IsOnlyTx = OnOff;
467 }
468 
SPI_SetCallbackFun(uint8_t SpiID,CBFuncEx_t CB,void * pUserData)469 void SPI_SetCallbackFun(uint8_t SpiID, CBFuncEx_t CB, void *pUserData)
470 {
471     if (CB)
472     {
473         prvSPI[SpiID].Callback = CB;
474     }
475     else
476     {
477         prvSPI[SpiID].Callback = SPI_DummyCB;
478     }
479     prvSPI[SpiID].pParam = pUserData;
480 }
481 
482 
SPI_DMATransfer(uint8_t SpiID,uint8_t UseDMA)483 static void SPI_DMATransfer(uint8_t SpiID, uint8_t UseDMA)
484 {
485     uint32_t RxLevel;
486 
487     RxLevel = (prvSPI[SpiID].RxBuf.MaxLen > 4080)?4000:prvSPI[SpiID].RxBuf.MaxLen;
488     prvSPI[SpiID].RxBuf.Pos += RxLevel;
489     prvSPI[SpiID].TxBuf.Pos += RxLevel;
490     DMA_StopStream(prvSPI[SpiID].DMATxStream);
491     DMA_StopStream(prvSPI[SpiID].DMARxStream);
492     if (prvSPI[SpiID].IsOnlyTx)
493     {
494         DMA_ForceStartStream(prvSPI[SpiID].DMATxStream, prvSPI[SpiID].TxBuf.Data, RxLevel, SPI_DMADoneCB, (void *)SpiID, 1);
495         DMA_ForceStartStream(prvSPI[SpiID].DMARxStream, prvSPI[SpiID].RxBuf.Data, RxLevel, NULL, NULL, 0);
496     }
497     else
498     {
499         DMA_ForceStartStream(prvSPI[SpiID].DMATxStream, prvSPI[SpiID].TxBuf.Data, RxLevel, NULL, NULL, 0);
500         DMA_ForceStartStream(prvSPI[SpiID].DMARxStream, prvSPI[SpiID].RxBuf.Data, RxLevel, SPI_DMADoneCB, (void *)SpiID, 1);
501     }
502 
503 
504 }
505 
HSPI_Transfer(uint8_t SpiID,uint8_t UseDMA)506 static int32_t HSPI_Transfer(uint8_t SpiID, uint8_t UseDMA)
507 {
508     HSPIM_TypeDef *SPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase;
509     uint32_t TxLen, i;
510     if (UseDMA)
511     {
512         SPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS);
513         SPI->CR0 |= (1 << HSPIM_CR0_PARAM_DMA_TRANSMIT_ENABLE_POS)|(1 << HSPIM_CR0_PARAM_DMA_RECEIVE_ENABLE_POS);
514         SPI->FCR = (32 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(0 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(3 << 6)|(63);
515         SPI->FCR &= ~(3 << 6);
516         SPI_DMATransfer(SpiID, UseDMA);
517     }
518     else
519     {
520         SPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS);
521 //      SPI->CR0 &= ~(1 << 10);
522         SPI->CR0 &= ~((1 << HSPIM_CR0_PARAM_DMA_TRANSMIT_ENABLE_POS)|(1 << HSPIM_CR0_PARAM_DMA_RECEIVE_ENABLE_POS));
523 
524 
525 
526         if (prvSPI[SpiID].TxBuf.MaxLen <= HSPIM_FIFO_TX_NUM)
527         {
528             TxLen = prvSPI[SpiID].TxBuf.MaxLen;
529             SPI->FCR = (32 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|((TxLen - 1) << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(3 << 6)|(63);
530             SPI->CR0 |= (5 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS);
531         }
532         else
533         {
534             TxLen = HSPIM_FIFO_TX_NUM;
535             SPI->FCR = (32 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(63 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(3 << 6)|(63);
536             SPI->CR0 |= (3 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS);
537         }
538 
539         SPI->FCR &= ~(3 << 6);
540 
541         for(i = 0; i < TxLen; i++)
542         {
543             SPI->WDR = prvSPI[SpiID].TxBuf.Data[i];
544         }
545         prvSPI[SpiID].TxBuf.Pos += TxLen;
546 //      SPI->CR0 |= (1 << 10);
547         ISR_Clear(prvSPI[SpiID].IrqLine);
548         ISR_OnOff(prvSPI[SpiID].IrqLine, 1);
549         return ERROR_NONE;
550     }
551     return ERROR_NONE;
552 }
553 
SPI_Transfer(uint8_t SpiID,const uint8_t * TxData,uint8_t * RxData,uint32_t Len,uint8_t UseDMA)554 int32_t SPI_Transfer(uint8_t SpiID, const uint8_t *TxData, uint8_t *RxData, uint32_t Len, uint8_t UseDMA)
555 {
556     uint32_t SR;
557     SPI_TypeDef *SPI;
558     if (prvSPI[SpiID].IsBusy)
559     {
560         return -ERROR_DEVICE_BUSY;
561     }
562     prvSPI[SpiID].IsBusy = 1;
563 //
564     uint32_t RxLevel, i, TxLen;
565     Buffer_StaticInit(&prvSPI[SpiID].TxBuf, TxData, Len);
566     Buffer_StaticInit(&prvSPI[SpiID].RxBuf, RxData, Len);
567     switch(SpiID)
568     {
569     case HSPI_ID0:
570         ISR_Clear(prvSPI[SpiID].IrqLine);
571         ISR_OnOff(prvSPI[SpiID].IrqLine, 0);
572         return HSPI_Transfer(SpiID, UseDMA);
573     case SPI_ID0:
574         SYSCTRL->PHER_CTRL &= ~SYSCTRL_PHER_CTRL_SPI0_SLV_EN;
575     case SPI_ID1:
576     case SPI_ID2:
577         break;
578 //  case SPI_ID3:
579 //      SYSCTRL->PHER_CTRL |= SYSCTRL_PHER_CTRL_SPI0_SLV_EN;
580 //      break;
581     default:
582         return -ERROR_ID_INVALID;
583     }
584     SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase;
585     SPI->SER = 0;
586     if (UseDMA)
587     {
588 
589         SR = SPI->ICR;
590         SPI->IMR = 0;
591         SPI->DMACR = SPI_DMACR_RDMAE|SPI_DMACR_TDMAE;
592         ISR_Clear(prvSPI[SpiID].IrqLine);
593         ISR_OnOff(prvSPI[SpiID].IrqLine, 0);
594         SPI->SER = 1;
595         SPI_DMATransfer(SpiID, 1);
596 
597     }
598     else
599     {
600         ISR_OnOff(prvSPI[SpiID].IrqLine, 0);
601 
602         if (prvSPI[SpiID].RxBuf.MaxLen <= SPIM_FIFO_RX_NUM)
603         {
604             SPI->RXFTLR = prvSPI[SpiID].RxBuf.MaxLen - 1;
605             TxLen = prvSPI[SpiID].RxBuf.MaxLen;
606             SPI->IMR = SPI_IMR_RXOIM|SPI_IMR_RXFIM;
607         }
608         else
609         {
610             SPI->IMR = SPI_IMR_TXEIM;
611             SPI->RXFTLR = SPIM_FIFO_RX_LEVEL;
612             SPI->TXFTLR = SPIM_FIFO_TX_LEVEL;
613             TxLen = SPIM_FIFO_TX_NUM;
614         }
615         for(i = 0; i < TxLen; i++)
616         {
617             SPI->DR = prvSPI[SpiID].TxBuf.Data[i];
618         }
619         prvSPI[SpiID].TxBuf.Pos += TxLen;
620         ISR_Clear(prvSPI[SpiID].IrqLine);
621         ISR_OnOff(prvSPI[SpiID].IrqLine, 1);
622     }
623     SPI->SER = 1;
624 
625     return ERROR_NONE;
626 }
627 
628 
prvSPI_BlockTransfer(uint8_t SpiID,const uint8_t * TxData,uint8_t * RxData,uint32_t Len)629 static int32_t prvSPI_BlockTransfer(uint8_t SpiID, const uint8_t *TxData, uint8_t *RxData, uint32_t Len)
630 {
631     volatile uint32_t DummyData;
632     uint32_t TxLen, RxLen, i, To;
633     HSPIM_TypeDef *HSPI;
634     SPI_TypeDef *SPI;
635     prvSPI[SpiID].IsBusy = 1;
636     switch(SpiID)
637     {
638     case HSPI_ID0:
639         HSPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase;
640         ISR_OnOff(prvSPI[SpiID].IrqLine, 0);
641         HSPI->FCR = (32 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(32 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(3 << 6)|(63);
642         HSPI->FCR &= ~(3 << 6);
643         HSPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS);
644         if (Len <= HSPIM_FIFO_TX_NUM)
645         {
646             TxLen = Len;
647         }
648         else
649         {
650             TxLen = HSPIM_FIFO_TX_NUM;
651         }
652         for(i = 0; i < TxLen; i++)
653         {
654             HSPI->WDR = TxData[i];
655         }
656         if (RxData)
657         {
658             for(RxLen = 0; RxLen < Len; RxLen++)
659             {
660                 while (HSPI->SR & HSPIM_SR_POP_EMPTY_RX)
661                 {
662                     ;
663                 }
664                 RxData[RxLen] = HSPI->RDR;
665                 if (TxLen < Len)
666                 {
667                     HSPI->WDR = TxData[TxLen];
668                     TxLen++;
669                 }
670             }
671         }
672         else
673         {
674             while(TxLen < Len)
675             {
676                 while ((HSPI->FSR & 0x7f) > 16)
677                 {
678                     ;
679                 }
680                 HSPI->WDR = TxData[TxLen];
681                 TxLen++;
682             }
683             while ((HSPI->FSR & 0x7f))
684             {
685                 ;
686             }
687 //          for(RxLen = 0; RxLen < Len; RxLen++)
688 //          {
689 //              while (HSPI->SR & HSPIM_SR_POP_EMPTY_RX)
690 //              {
691 //                  ;
692 //              }
693 //              DummyData = HSPI->RDR;
694 //              if (TxLen < Len)
695 //              {
696 //                  HSPI->WDR = TxData[TxLen];
697 //                  TxLen++;
698 //              }
699 //          }
700         }
701         break;
702     case SPI_ID0:
703     case SPI_ID1:
704     case SPI_ID2:
705         SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase;
706         ISR_OnOff(prvSPI[SpiID].IrqLine, 0);
707         SPI->SER = 0;
708         if (Len <= SPIM_FIFO_TX_NUM)
709         {
710             TxLen = Len;
711         }
712         else
713         {
714             TxLen = SPIM_FIFO_TX_NUM;
715         }
716         for(i = 0; i < TxLen; i++)
717         {
718             SPI->DR = TxData[i];
719         }
720         SPI->SER = 1;
721         if (RxData)
722         {
723             for(RxLen = 0; RxLen < Len; RxLen++)
724             {
725                 while (!SPI->RXFLR)
726                 {
727                     ;
728                 }
729                 RxData[RxLen] = SPI->DR;
730                 if (TxLen < Len)
731                 {
732                     SPI->DR = TxData[TxLen];
733                     TxLen++;
734                 }
735             }
736         }
737         else
738         {
739             for(RxLen = 0; RxLen < Len; RxLen++)
740             {
741                 while (!SPI->RXFLR)
742                 {
743                     ;
744                 }
745                 DummyData = SPI->DR;
746                 if (TxLen < Len)
747                 {
748                     SPI->DR = TxData[TxLen];
749                     TxLen++;
750                 }
751             }
752         }
753         SPI->SER = 0;
754         break;
755     }
756     prvSPI[SpiID].IsBusy = 0;
757     prvSPI[SpiID].Callback((void *)SpiID, prvSPI[SpiID].pParam);
758     return 0;
759 }
760 
SPI_BlockTransfer(uint8_t SpiID,const uint8_t * TxData,uint8_t * RxData,uint32_t Len)761 int32_t SPI_BlockTransfer(uint8_t SpiID, const uint8_t *TxData, uint8_t *RxData, uint32_t Len)
762 {
763 #ifdef __BUILD_OS__
764     if ( (prvSPI[SpiID].DMARxStream == 0xff) || (prvSPI[SpiID].DMATxStream == 0xff) || OS_CheckInIrq() || ((prvSPI[SpiID].Speed >> 3) >= (Len * 100000)))
765     {
766         prvSPI[SpiID].IsBlockMode = 0;
767 #endif
768         return prvSPI_BlockTransfer(SpiID, TxData, RxData, Len);
769 #ifdef __BUILD_OS__
770     }
771     int32_t Result;
772     uint32_t Time = (Len * 1000) / (prvSPI[SpiID].Speed >> 3);
773     prvSPI[SpiID].IsBlockMode = 1;
774     if (TxData)
775     {
776         Result = SPI_Transfer(SpiID, TxData, RxData, Len, 1);
777     }
778     else
779     {
780         Result = SPI_Transfer(SpiID, RxData, RxData, Len, 1);
781     }
782     if (Result)
783     {
784         prvSPI[SpiID].IsBlockMode = 0;
785         DBG("!");
786         return Result;
787     }
788     if (OS_MutexLockWtihTime(prvSPI[SpiID].Sem, Time + 10))
789     {
790         DBG("!!!");
791         SPI_TransferStop(SpiID);
792         prvSPI[SpiID].IsBlockMode = 0;
793         return -1;
794     }
795     prvSPI[SpiID].IsBlockMode = 0;
796     return 0;
797 #endif
798 }
799 
800 
prvSPI_FlashBlockTransfer(uint8_t SpiID,const uint8_t * TxData,uint32_t WLen,uint8_t * RxData,uint32_t RLen)801 static int32_t prvSPI_FlashBlockTransfer(uint8_t SpiID, const uint8_t *TxData, uint32_t WLen, uint8_t *RxData, uint32_t RLen)
802 {
803     volatile uint32_t DummyData;
804     uint32_t TxLen, RxLen, i;
805     HSPIM_TypeDef *HSPI;
806     SPI_TypeDef *SPI;
807     prvSPI[SpiID].IsBusy = 1;
808     switch(SpiID)
809     {
810     case HSPI_ID0:
811         HSPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase;
812 
813         HSPI->FCR = (32 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(32 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(3 << 6)|(63);
814         HSPI->FCR &= ~(3 << 6);
815         HSPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS);
816         if (WLen <= HSPIM_FIFO_TX_NUM)
817         {
818             TxLen = WLen;
819         }
820         else
821         {
822             TxLen = HSPIM_FIFO_TX_NUM;
823         }
824         for(i = 0; i < TxLen; i++)
825         {
826             HSPI->WDR = TxData[i];
827         }
828         for(RxLen = 0; RxLen < WLen; RxLen++)
829         {
830             while (HSPI->SR & HSPIM_SR_POP_EMPTY_RX)
831             {
832                 ;
833             }
834             DummyData = HSPI->RDR;
835             if (TxLen < WLen)
836             {
837                 HSPI->WDR = TxData[TxLen];
838                 TxLen++;
839             }
840         }
841         if (RLen <= HSPIM_FIFO_TX_NUM)
842         {
843             TxLen = RLen;
844         }
845         else
846         {
847             TxLen = HSPIM_FIFO_TX_NUM;
848         }
849         for(i = 0; i < TxLen; i++)
850         {
851             HSPI->WDR = TxData[i];
852         }
853         for(RxLen = 0; RxLen < RLen; RxLen++)
854         {
855             while (HSPI->SR & HSPIM_SR_POP_EMPTY_RX)
856             {
857                 ;
858             }
859             RxData[RxLen] = HSPI->RDR;
860             if (TxLen < RLen)
861             {
862                 HSPI->WDR = 0xff;
863                 TxLen++;
864             }
865         }
866 
867         break;
868     case SPI_ID0:
869     case SPI_ID1:
870     case SPI_ID2:
871         SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase;
872         ISR_OnOff(prvSPI[SpiID].IrqLine, 0);
873         SPI->SER = 0;
874         if (WLen <= SPIM_FIFO_TX_NUM)
875         {
876             TxLen = WLen;
877         }
878         else
879         {
880             TxLen = SPIM_FIFO_TX_NUM;
881         }
882         for(i = 0; i < TxLen; i++)
883         {
884             SPI->DR = TxData[i];
885         }
886         SPI->SER = 1;
887         for(RxLen = 0; RxLen < WLen; RxLen++)
888         {
889             while (!SPI->RXFLR)
890             {
891                 ;
892             }
893             DummyData = SPI->DR;
894             if (TxLen < WLen)
895             {
896                 SPI->DR = TxData[TxLen];
897                 TxLen++;
898             }
899         }
900         if (RLen <= SPIM_FIFO_TX_NUM)
901         {
902             TxLen = RLen;
903         }
904         else
905         {
906             TxLen = SPIM_FIFO_TX_NUM;
907         }
908         for(i = 0; i < TxLen; i++)
909         {
910             SPI->DR = TxData[i];
911         }
912 
913         for(RxLen = 0; RxLen < RLen; RxLen++)
914         {
915             while (!SPI->RXFLR)
916             {
917                 ;
918             }
919             RxData[RxLen] = SPI->DR;
920             if (TxLen < RLen)
921             {
922                 SPI->DR = 0xff;
923                 TxLen++;
924             }
925         }
926         SPI->SER = 0;
927         break;
928     }
929     prvSPI[SpiID].IsBusy = 0;
930     prvSPI[SpiID].Callback((void *)SpiID, prvSPI[SpiID].pParam);
931     return 0;
932 }
933 
SPI_FlashBlockTransfer(uint8_t SpiID,const uint8_t * TxData,uint32_t WLen,uint8_t * RxData,uint32_t RLen)934 int32_t SPI_FlashBlockTransfer(uint8_t SpiID, const uint8_t *TxData, uint32_t WLen, uint8_t *RxData, uint32_t RLen)
935 {
936 #ifdef __BUILD_OS__
937     if ( (prvSPI[SpiID].DMARxStream == 0xff) || (prvSPI[SpiID].DMATxStream == 0xff) || OS_CheckInIrq() || ((prvSPI[SpiID].Speed >> 3) >= ((WLen + RLen) * 100000)))
938     {
939         prvSPI[SpiID].IsBlockMode = 0;
940 #endif
941         return prvSPI_FlashBlockTransfer(SpiID, TxData, WLen, RxData, RLen);
942 #ifdef __BUILD_OS__
943     }
944     int32_t Result;
945     uint32_t Time = ((WLen + RLen) * 1000) / (prvSPI[SpiID].Speed >> 3);
946     uint8_t *Temp = malloc(WLen + RLen);
947     memcpy(Temp, TxData, WLen);
948     prvSPI[SpiID].IsBlockMode = 1;
949 
950     if (TxData)
951     {
952         Result = SPI_Transfer(SpiID, Temp, Temp, WLen + RLen, 1);
953     }
954     else
955     {
956         Result = SPI_Transfer(SpiID, Temp, Temp, WLen + RLen, 1);
957     }
958     if (Result)
959     {
960         prvSPI[SpiID].IsBlockMode = 0;
961         free(Temp);
962         return Result;
963     }
964     if (OS_MutexLockWtihTime(prvSPI[SpiID].Sem, Time + 10))
965     {
966         free(Temp);
967         DBG("!!!");
968         DMA_StopStream(prvSPI[SpiID].DMATxStream);
969         DMA_StopStream(prvSPI[SpiID].DMARxStream);
970         SPI_TransferStop(SpiID);
971         prvSPI[SpiID].IsBlockMode = 0;
972         return -1;
973     }
974     memcpy(RxData, Temp + WLen, RLen);
975     prvSPI[SpiID].IsBlockMode = 0;
976     free(Temp);
977     return 0;
978 #endif
979 }
980 
981 
SPI_DMATxInit(uint8_t SpiID,uint8_t Stream,uint32_t Channel)982 void SPI_DMATxInit(uint8_t SpiID, uint8_t Stream, uint32_t Channel)
983 {
984     SPI_TypeDef *SPI;
985     HSPIM_TypeDef *HSPI;
986     DMA_InitTypeDef DMA_InitStruct;
987     DMA_BaseConfig(&DMA_InitStruct);
988     DMA_InitStruct.DMA_Peripheral = prvSPI[SpiID].DMATxChannel;
989     DMA_InitStruct.DMA_Priority = DMA_Priority_3;
990     prvSPI[SpiID].DMATxStream = Stream;
991     switch(SpiID)
992     {
993     case HSPI_ID0:
994         HSPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase;
995         if (prvSPI[SpiID].IsOnlyTx)
996         {
997             DMA_InitStruct.DMA_Priority = DMA_Priority_0;
998         }
999         DMA_InitStruct.DMA_PeripheralBurstSize = DMA_BurstSize_32;
1000         DMA_InitStruct.DMA_MemoryBurstSize = DMA_BurstSize_32;
1001         DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&HSPI->WDR;
1002         break;
1003     case SPI_ID0:
1004     case SPI_ID1:
1005     case SPI_ID2:
1006         SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase;
1007         DMA_InitStruct.DMA_PeripheralBurstSize = DMA_BurstSize_8;
1008         DMA_InitStruct.DMA_MemoryBurstSize = DMA_BurstSize_8;
1009         DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&SPI->DR;
1010         break;
1011 //  case SPI_ID3:
1012 //      SYSCTRL->PHER_CTRL |= SYSCTRL_PHER_CTRL_SPI0_SLV_EN;
1013 //      break;
1014     default:
1015         return;
1016     }
1017     DMA_ConfigStream(Stream, &DMA_InitStruct);
1018 }
SPI_DMARxInit(uint8_t SpiID,uint8_t Stream,uint32_t Channel)1019 void SPI_DMARxInit(uint8_t SpiID, uint8_t Stream, uint32_t Channel)
1020 {
1021     SPI_TypeDef *SPI;
1022     HSPIM_TypeDef *HSPI;
1023     DMA_InitTypeDef DMA_InitStruct;
1024     DMA_BaseConfig(&DMA_InitStruct);
1025     DMA_InitStruct.DMA_Peripheral = prvSPI[SpiID].DMARxChannel;
1026     DMA_InitStruct.DMA_Priority = DMA_Priority_2;
1027     prvSPI[SpiID].DMARxStream = Stream;
1028     switch(SpiID)
1029     {
1030     case HSPI_ID0:
1031         HSPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase;
1032         DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&HSPI->RDR;
1033         break;
1034     case SPI_ID0:
1035     case SPI_ID1:
1036     case SPI_ID2:
1037         SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase;
1038         DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&SPI->DR;
1039         break;
1040 //  case SPI_ID3:
1041 //      SYSCTRL->PHER_CTRL |= SYSCTRL_PHER_CTRL_SPI0_SLV_EN;
1042 //      break;
1043     default:
1044         return;
1045     }
1046     DMA_ConfigStream(Stream, &DMA_InitStruct);
1047 }
1048 
SPI_TransferStop(uint8_t SpiID)1049 void SPI_TransferStop(uint8_t SpiID)
1050 {
1051     uint16_t Data;
1052     ISR_Clear(prvSPI[SpiID].IrqLine);
1053     ISR_OnOff(prvSPI[SpiID].IrqLine, 0);
1054     SPI_TypeDef *SPI;
1055     HSPIM_TypeDef *HSPI;
1056     uint32_t TxLen, i;
1057     DMA_StopStream(prvSPI[SpiID].DMATxStream);
1058     DMA_StopStream(prvSPI[SpiID].DMARxStream);
1059     switch(SpiID)
1060     {
1061     case HSPI_ID0:
1062         HSPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase;
1063         HSPI->CR0 &= ~(7 << HSPIM_CR0_PARAM_INTERRPUT_ENABLE_POS);
1064         HSPI->FCR = (32 << HSPIM_FCR_PARAM_TRANSIMIT_FIFO_EMPTY_THRESHOULD_POS)|(32 << HSPIM_FCR_PARAM_RECEIVE_FIFO_FULL_THRESHOULD_POS)|(3 << 6)|(63);
1065         HSPI->FCR &= ~(3 << 6);
1066         break;
1067     case SPI_ID0:
1068         SYSCTRL->PHER_CTRL &= ~SYSCTRL_PHER_CTRL_SPI0_SLV_EN;
1069     case SPI_ID1:
1070     case SPI_ID2:
1071         SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase;
1072         while(SPI->TXFLR){;}
1073         while(SPI->RXFLR){Data = SPI->DR;}
1074         SPI->SER = 0;
1075         break;
1076 //  case SPI_ID3:
1077 //      SYSCTRL->PHER_CTRL |= SYSCTRL_PHER_CTRL_SPI0_SLV_EN;
1078 //      break;
1079     default:
1080         return ;
1081     }
1082 
1083     prvSPI[SpiID].IsBusy = 0;
1084 
1085 }
1086 
SPI_IsTransferBusy(uint8_t SpiID)1087 uint8_t SPI_IsTransferBusy(uint8_t SpiID)
1088 {
1089     return prvSPI[SpiID].IsBusy;
1090 }
1091 
SPI_SetNewConfig(uint8_t SpiID,uint32_t Speed,uint8_t NewMode)1092 void SPI_SetNewConfig(uint8_t SpiID, uint32_t Speed, uint8_t NewMode)
1093 {
1094     HSPIM_TypeDef *HSPI;
1095     SPI_TypeDef *SPI;
1096     uint32_t div;
1097     if (prvSPI[SpiID].IsBusy) return;
1098 
1099     switch(SpiID)
1100     {
1101     case HSPI_ID0:
1102         HSPI = (HSPIM_TypeDef *)prvSPI[SpiID].RegBase;
1103         div = (SystemCoreClock / Speed) >> 1;
1104         HSPI->CR1 = (div << HSPIM_CR1_PARAM_BAUDRATE_POS) + 1;
1105         prvSPI[SpiID].Speed = (SystemCoreClock >> 1) / div;
1106         HSPI->CR0 &= ~((1 << HSPIM_CR0_PARAM_CPOL_POS)|(1 << HSPIM_CR0_PARAM_CPHA_POS));
1107         switch(NewMode)
1108         {
1109         case SPI_MODE_0:
1110 
1111             break;
1112         case SPI_MODE_1:
1113             HSPI->CR0 |= (1 << HSPIM_CR0_PARAM_CPHA_POS);
1114             break;
1115         case SPI_MODE_2:
1116             HSPI->CR0 |= (1 << HSPIM_CR0_PARAM_CPOL_POS);
1117             break;
1118         case SPI_MODE_3:
1119             HSPI->CR0 |= (1 << HSPIM_CR0_PARAM_CPOL_POS)|(1 << HSPIM_CR0_PARAM_CPHA_POS);
1120             break;
1121         }
1122         break;
1123     case SPI_ID0:
1124     case SPI_ID1:
1125     case SPI_ID2:
1126         SPI = (SPI_TypeDef *)prvSPI[SpiID].RegBase;
1127         SPI->SSIENR = 0;
1128         div = (SystemCoreClock >> 2) / Speed;
1129         if (div % 2) div++;
1130         prvSPI[SpiID].Speed = (SystemCoreClock >> 2) / div;
1131         SPI->BAUDR = div;
1132         SPI->CTRLR0 &= ~(SPI_CTRLR0_SCPOL|SPI_CTRLR0_SCPH);
1133         switch(NewMode)
1134         {
1135         case SPI_MODE_0:
1136             break;
1137         case SPI_MODE_1:
1138             SPI->CTRLR0 |= SPI_CTRLR0_SCPH;
1139             break;
1140         case SPI_MODE_2:
1141             SPI->CTRLR0 |= SPI_CTRLR0_SCPOL;
1142             break;
1143         case SPI_MODE_3:
1144             SPI->CTRLR0 |= SPI_CTRLR0_SCPOL|SPI_CTRLR0_SCPH;
1145             break;
1146         }
1147         SPI->SSIENR = 1;
1148         break;
1149     }
1150 }
1151