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 typedef struct
25 {
26     const UART_TypeDef *RegBase;
27     const int IrqLine;
28     const uint16_t DMATxChannel;
29     const uint16_t DMARxChannel;
30     CBFuncEx_t Callback;
31     Buffer_Struct TxBuf;
32     Buffer_Struct RxBuf;
33     uint32_t LastError;
34     uint8_t RxCacheMode;
35     uint8_t DMATxStream;
36     uint8_t DMARxStream;
37 }Uart_ResourceStruct;
38 
39 static Uart_ResourceStruct prvUart[UART_MAX] = {
40         {
41                 UART0,
42                 UART0_IRQn,
43                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART0_TX,
44                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART0_RX,
45         },
46         {
47                 UART1,
48                 UART1_IRQn,
49                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART1_TX,
50                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART1_RX,
51         },
52         {
53                 UART2,
54                 UART2_IRQn,
55                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART2_TX,
56                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART2_RX,
57         },
58         {
59                 UART3,
60                 UART3_IRQn,
61                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART3_TX,
62                 SYSCTRL_PHER_CTRL_DMA_CHx_IF_UART3_RX,
63         },
64 };
65 
prvUart_DummyCB(void * pData,void * pParam)66 static int32_t prvUart_DummyCB(void *pData, void *pParam)
67 {
68     return 0;
69 }
70 static void prvUart_IrqHandle(int32_t IrqLine, void *pData);
71 
72 
prvUart_DMAIrqCB(void * pData,void * pParam)73 static int32_t prvUart_DMAIrqCB(void *pData, void *pParam)
74 {
75     uint8_t UartID = (uint32_t)pData;
76     prvUart[UartID].Callback(pData, pParam);
77 }
78 
prvUart_FIFOInit(UART_TypeDef * UARTx,UART_FIFOInitTypeDef * UART_FIFOInitStruct)79 static void prvUart_FIFOInit(UART_TypeDef *UARTx, UART_FIFOInitTypeDef *UART_FIFOInitStruct)
80 {
81     /**************************  FIFO Tx Interrupt Config ******************************/
82     if (DISABLE != UART_FIFOInitStruct->FIFO_TX_TriggerIntEnable)
83     {
84         UARTx->OFFSET_4.IER |= UART_IER_PTIME;
85     }
86     else
87     {
88         UARTx->OFFSET_4.IER &= ~UART_IER_PTIME;
89     }
90 
91     /**************************  FIFO Config ******************************/
92     /* FCR Write Only So Here we Use FCR Shadow Register SDMAM(WR) */
93     if (UARTx->SFE | UART_SFE_SFE)
94     {
95         UARTx->SFE &= ~UART_SFE_SFE;
96     }
97 
98     if (UART_FIFO_DMA_Mode_0 == UART_FIFOInitStruct->FIFO_DMA_Mode)
99     {
100         UARTx->SDMAM &= ~UART_SDMAM_SDMAM;
101     }
102     else if(UART_FIFO_DMA_Mode_1 == UART_FIFOInitStruct->FIFO_DMA_Mode)
103     {
104         UARTx->SDMAM |= UART_SDMAM_SDMAM;
105     }
106 
107     /* FCR Write Only So Here we Use FCR Shadow Register SRT and STET(WR) */
108     UARTx->SRT = UART_FIFOInitStruct->FIFO_RX_Trigger;
109     UARTx->STET = UART_FIFOInitStruct->FIFO_TX_Trigger;
110 
111     if (DISABLE != UART_FIFOInitStruct->FIFO_Enable)
112     {
113         UARTx->SFE |= UART_SFE_SFE;
114     }
115     else
116     {
117         UARTx->SFE &= ~UART_SFE_SFE;
118     }
119 }
120 
121 
Uart_GlobalInit(void)122 void Uart_GlobalInit(void)
123 {
124     int i, j;
125     for(i = 0; i < UART_MAX; i++)
126     {
127         memset(&prvUart[i].RxBuf, 0, sizeof(Buffer_Struct));
128         prvUart[i].RxCacheMode = 0;
129     }
130 }
131 
Uart_BaseInit(uint8_t UartID,uint32_t BaudRate,uint8_t IsRxCacheEnable,uint8_t DataBits,uint8_t Parity,uint8_t StopBits,CBFuncEx_t CB)132 void Uart_BaseInit(uint8_t UartID, uint32_t BaudRate, uint8_t IsRxCacheEnable, uint8_t DataBits, uint8_t Parity, uint8_t StopBits, CBFuncEx_t CB)
133 {
134     uint32_t tmpBaudRateDiv, LCR;
135     UART_FIFOInitTypeDef UART_FIFOInitStruct;
136     UART_TypeDef* Uart = prvUart[UartID].RegBase;
137     SYSCTRL->SOFT_RST1 = (1 << UartID);
138     while(SYSCTRL->SOFT_RST1 & (1 << UartID)){;}
139     UART_FIFOInitStruct.FIFO_Enable = ENABLE;
140     UART_FIFOInitStruct.FIFO_DMA_Mode = UART_FIFO_DMA_Mode_1;
141     UART_FIFOInitStruct.FIFO_RX_Trigger = UART_FIFO_RX_Trigger_1_2_Full;
142     UART_FIFOInitStruct.FIFO_TX_Trigger = UART_FIFO_TX_Trigger_1_4_Full;
143     UART_FIFOInitStruct.FIFO_TX_TriggerIntEnable = ENABLE;
144 
145     ISR_SetHandler(prvUart[UartID].IrqLine, prvUart_IrqHandle, (void *)UartID);
146 #ifdef __BUILD_OS__
147     ISR_SetPriority(prvUart[UartID].IrqLine, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 2);
148 #else
149     ISR_SetPriority(prvUart[UartID].IrqLine, 5);
150 #endif
151     if (CB)
152     {
153         prvUart[UartID].Callback = CB;
154     }
155     else
156     {
157         prvUart[UartID].Callback = prvUart_DummyCB;
158     }
159 //  UART_Init(Uart, &UART_InitStruct);
160     Uart->LCR |= UART_LCR_DLAB;
161 
162     // baud rate = (serial clock freq) / (16 * divisor).
163     tmpBaudRateDiv = (SystemCoreClock >> 6) / BaudRate;
164     Uart->OFFSET_0.DLL = (tmpBaudRateDiv & 0x00FF);
165     Uart->OFFSET_4.DLH = ((tmpBaudRateDiv >> 8) & 0x00FF);
166 
167     /* LCR = 0 */
168     Uart->LCR &= ~UART_LCR_DLAB;
169     LCR = UART_WordLength_5b + DataBits - UART_DATA_BIT5;
170     switch(Parity)
171     {
172     case UART_STOP_BIT1:
173         LCR |= UART_StopBits_1;
174         break;
175     case UART_STOP_BIT1_5:
176         LCR |= UART_StopBits_1_5;
177         break;
178     case UART_STOP_BIT2:
179         LCR |= UART_StopBits_2;
180         break;
181     }
182     switch(Parity)
183     {
184     case UART_PARITY_NONE:
185         LCR |= UART_Parity_No;
186         break;
187     case UART_PARITY_ODD:
188         LCR |= UART_Parity_Odd;
189         break;
190     case UART_PARITY_EVEN:
191         LCR |= UART_Parity_Even;
192         break;
193     }
194     Uart->LCR = LCR;
195     prvUart_FIFOInit(Uart, &UART_FIFOInitStruct);
196     ISR_OnOff(prvUart[UartID].IrqLine, 0);
197     Uart->SFE |= UART_SFE_SFE;
198     Uart->OFFSET_4.IER = UART_IER_ELSI;
199     prvUart[UartID].RxCacheMode = IsRxCacheEnable;
200 }
201 
202 
Uart_SetCb(uint8_t UartID,CBFuncEx_t CB)203 void Uart_SetCb(uint8_t UartID, CBFuncEx_t CB)
204 {
205     if (CB)
206     {
207         prvUart[UartID].Callback = CB;
208     }
209     else
210     {
211         prvUart[UartID].Callback = prvUart_DummyCB;
212     }
213 }
214 
Uart_DeInit(uint8_t UartID)215 void Uart_DeInit(uint8_t UartID)
216 {
217     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
218     Uart->OFFSET_4.IER = 0;
219     Uart_BufferTxStop(UartID);
220     ISR_OnOff(prvUart[UartID].IrqLine, 0);
221     ISR_Clear(prvUart[UartID].IrqLine);
222     /* LCR = 1 */
223     Uart->LCR |= UART_LCR_DLAB;
224     Uart->OFFSET_0.DLL = 0;
225     Uart->OFFSET_4.DLH = 0;
226 
227     /* LCR = 0 */
228     Uart->LCR &= ~UART_LCR_DLAB;
229 
230 
231 }
232 
Uart_DMATxInit(uint8_t UartID,uint8_t Stream,uint32_t Channel)233 int Uart_DMATxInit(uint8_t UartID, uint8_t Stream, uint32_t Channel)
234 {
235     DMA_InitTypeDef DMA_InitStruct;
236     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
237     DMA_BaseConfig(&DMA_InitStruct);
238     DMA_InitStruct.DMA_Peripheral = prvUart[UartID].DMATxChannel;
239     DMA_InitStruct.DMA_PeripheralBurstSize = DMA_BurstSize_8;
240     DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&Uart->OFFSET_0.THR;
241     DMA_InitStruct.DMA_Priority = DMA_Priority_3;
242     DMA_InitStruct.DMA_MemoryBurstSize = DMA_BurstSize_8;
243     prvUart[UartID].DMATxStream = Stream;
244     return DMA_ConfigStream(Stream, &DMA_InitStruct);
245 }
246 
Uart_DMARxInit(uint8_t UartID,uint8_t Stream,uint32_t Channel)247 int Uart_DMARxInit(uint8_t UartID, uint8_t Stream, uint32_t Channel)
248 {
249     DMA_InitTypeDef DMA_InitStruct;
250     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
251     DMA_BaseConfig(&DMA_InitStruct);
252     DMA_InitStruct.DMA_Peripheral = prvUart[UartID].DMARxChannel;
253     DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&Uart->OFFSET_0.RBR;
254     DMA_InitStruct.DMA_Priority = DMA_Priority_3;
255     prvUart[UartID].DMARxStream = Stream;
256     return DMA_ConfigStream(Stream, &DMA_InitStruct);
257 }
258 
Uart_BlockTx(uint8_t UartID,uint8_t * Data,uint32_t Len)259 void Uart_BlockTx(uint8_t UartID, uint8_t *Data, uint32_t Len)
260 {
261     uint32_t i = 0;
262     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
263     Uart->OFFSET_4.IER &= ~(UART_IER_PTIME|UART_IER_ETBEI);
264     while(i < Len)
265     {
266         while (Uart->USR & UART_STATUS_TX_FIFO_NOT_FULL)
267         {
268             Uart->OFFSET_0.THR = Data[i];
269             i++;
270         }
271     }
272 }
273 
Uart_NoBlockTx(uint8_t UartID,uint8_t Data)274 void Uart_NoBlockTx(uint8_t UartID, uint8_t Data)
275 {
276     uint32_t i = 0;
277     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
278     while (!(Uart->USR & UART_STATUS_TX_FIFO_NOT_FULL))
279     {
280 
281     }
282     Uart->OFFSET_0.THR = Data;
283 }
284 
Uart_EnableRxIrq(uint8_t UartID)285 void Uart_EnableRxIrq(uint8_t UartID)
286 {
287     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
288     Uart->SRT = UART_FIFO_RX_Trigger_1_2_Full;
289     Uart->OFFSET_4.IER |= UART_IT_RX_RECVD|UART_IER_ELSI;
290     ISR_OnOff(prvUart[UartID].IrqLine, 1);
291 }
292 
Uart_EnableTxDoneIrq(uint8_t UartID)293 void Uart_EnableTxDoneIrq(uint8_t UartID)
294 {
295 
296 
297 }
298 
Uart_DMATx(uint8_t UartID,uint8_t Stream,const uint8_t * Data,uint32_t Len)299 void Uart_DMATx(uint8_t UartID, uint8_t Stream, const uint8_t *Data, uint32_t Len)
300 {
301     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
302     Uart->OFFSET_4.IER &= ~(UART_IER_PTIME|UART_IER_ETBEI);
303     DMA_ClearStreamFlag(Stream);
304     DMA_ForceStartStream(Stream, Data, Len, prvUart_DMAIrqCB, (uint32_t)UartID, 1);
305     Uart->OFFSET_4.IER |= UART_IER_PTIME|UART_IER_ETBEI;
306     ISR_OnOff(prvUart[UartID].IrqLine, 1);
307 }
308 
Uart_DMARx(uint8_t UartID,uint8_t Stream,uint8_t * Data,uint32_t Len)309 void Uart_DMARx(uint8_t UartID, uint8_t Stream, uint8_t *Data, uint32_t Len)
310 {
311     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
312     Uart->OFFSET_4.IER |= UART_IT_RX_RECVD;
313     Uart->SRT = UART_FIFO_RX_Trigger_1_4_Full;
314     ISR_OnOff(prvUart[UartID].IrqLine, 1);
315     DMA_ClearStreamFlag(Stream);
316     DMA_ForceStartStream(Stream, Data, Len, prvUart_DMAIrqCB, (uint32_t)UartID, 1);
317 }
318 
319 
Uart_BufferTx(uint8_t UartID,const uint8_t * Data,uint32_t Len)320 int32_t Uart_BufferTx(uint8_t UartID, const uint8_t *Data, uint32_t Len)
321 {
322     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
323 
324     ISR_OnOff(prvUart[UartID].IrqLine, 0);
325 #ifdef __BUILD_OS__
326     if (Data && Len)
327     {
328         OS_BufferWrite(&prvUart[UartID].TxCacheBuf, Data, Len);
329     }
330 #endif
331     if (prvUart[UartID].TxBuf.Data || prvUart[UartID].TxBuf.MaxLen)
332     {
333         ISR_OnOff(prvUart[UartID].IrqLine, 1);
334         return 0;
335     }
336     Uart->OFFSET_4.IER &= ~(UART_IER_PTIME|UART_IER_ETBEI);
337 #ifdef __BUILD_OS__
338     // 把缓存的Tx指针交给发送的Tx指针,缓存的Tx指针重新建立一个
339     Buffer_StaticInit(&prvUart[UartID].TxBuf, prvUart[UartID].TxCacheBuf.Data, prvUart[UartID].TxCacheBuf.Pos);
340 #else
341     Buffer_StaticInit(&prvUart[UartID].TxBuf, Data, Len);
342 #endif
343     while ((prvUart[UartID].TxBuf.Pos < prvUart[UartID].TxBuf.MaxLen) && (Uart->USR & UART_STATUS_TX_FIFO_NOT_FULL))
344     {
345         Uart->OFFSET_0.THR = prvUart[UartID].TxBuf.Data[prvUart[UartID].TxBuf.Pos];
346         prvUart[UartID].TxBuf.Pos++;
347     }
348     if (prvUart[UartID].TxBuf.Pos >= prvUart[UartID].TxBuf.MaxLen)
349     {
350         // 只有少量数据,只靠FIFO就能填充满,就不需要重新分配内存
351         memset(&prvUart[UartID].TxBuf, 0, sizeof(prvUart[UartID].TxBuf));
352 #ifdef __BUILD_OS__
353         prvUart[UartID].TxCacheBuf.Pos = 0;
354 #endif
355         ISR_OnOff(prvUart[UartID].IrqLine, 1);
356         Uart->OFFSET_4.IER |= UART_IER_ETBEI|UART_IER_ELSI;
357         return 0;
358     }
359     else
360     {
361         // 数据多,暂时发不完,就需要为缓存重新分配内存
362 #ifdef __BUILD_OS__
363         OS_InitBuffer(&prvUart[UartID].TxCacheBuf, TX_BUF_INIT);
364 #endif
365         ISR_OnOff(prvUart[UartID].IrqLine, 1);
366         Uart->OFFSET_4.IER |= UART_IER_PTIME|UART_IER_ETBEI|UART_IER_ELSI;
367         return 1;
368     }
369 }
370 
371 
Uart_BufferTxStop(uint8_t UartID)372 void Uart_BufferTxStop(uint8_t UartID)
373 {
374     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
375     Uart->OFFSET_4.IER &= ~(UART_IER_PTIME|UART_IER_ETBEI);
376     ISR_OnOff(prvUart[UartID].IrqLine, 0);
377     memset(&prvUart[UartID].TxBuf, 0, sizeof(Buffer_Struct));
378     ISR_OnOff(prvUart[UartID].IrqLine, 1);
379 }
380 
381 
prvUart_FifoRead(uint8_t UartID,uint8_t * Data,uint8_t Len)382 static uint32_t prvUart_FifoRead(uint8_t UartID, uint8_t *Data, uint8_t Len)
383 {
384     uint32_t i = 0;
385     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
386 
387     while (Uart->USR & UART_STATUS_RX_FIFO_NOT_EMPTY && (--Len))
388     {
389         Data[i] = Uart->OFFSET_0.RBR;
390         i++;
391     }
392     return i;
393 
394 }
395 
Uart_FifoRead(uint8_t UartID,uint8_t * Data)396 uint32_t Uart_FifoRead(uint8_t UartID, uint8_t *Data)
397 {
398     uint32_t i = 0;
399     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
400 
401     while (Uart->USR & UART_STATUS_RX_FIFO_NOT_EMPTY)
402     {
403         Data[i] = Uart->OFFSET_0.RBR;
404         i++;
405     }
406     return i;
407 
408 }
409 
Uart_ReadByte(uint8_t UartID,uint8_t * Data)410 int Uart_ReadByte(uint8_t UartID, uint8_t *Data)
411 {
412     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
413     if (Uart->USR & UART_STATUS_RX_FIFO_NOT_EMPTY)
414     {
415         *Data = Uart->OFFSET_0.RBR;
416         return 0;
417     }
418     else
419     {
420         return -1;
421     }
422 }
423 
Uart_RxBufferCB(uint8_t UartID,CBFuncEx_t CB)424 void Uart_RxBufferCB(uint8_t UartID, CBFuncEx_t CB)
425 {
426 #ifdef __BUILD_OS__
427     uint32_t ReadLen;
428     if (!prvUart[UartID].RxCacheMode)
429     {
430         return ;
431     }
432     ISR_OnOff(prvUart[UartID].IrqLine, 0);
433     if (!CB(prvUart[UartID].RxBuf.Data, (void *)prvUart[UartID].RxBuf.Pos))
434     {
435         prvUart[UartID].RxBuf.Pos = 0;
436         if (prvUart[UartID].RxBuf.MaxLen > RX_BUF_HIGH)
437         {
438             OS_ReInitBuffer(&prvUart[UartID].RxBuf, RX_BUF_INIT);
439         }
440     }
441     ISR_OnOff(prvUart[UartID].IrqLine, 1);
442 #endif
443 }
444 
Uart_RxBufferRead(uint8_t UartID,uint8_t * Data,uint32_t Len)445 uint32_t Uart_RxBufferRead(uint8_t UartID, uint8_t *Data, uint32_t Len)
446 {
447 #ifdef __BUILD_OS__
448     uint32_t ReadLen;
449     if (!prvUart[UartID].RxCacheMode)
450     {
451         return 0;
452     }
453     ISR_OnOff(prvUart[UartID].IrqLine, 0);
454     if (!Len)
455     {
456         ReadLen = prvUart[UartID].RxBuf.Pos;
457         ISR_OnOff(prvUart[UartID].IrqLine, 1);
458         return ReadLen;
459     }
460     ReadLen = (prvUart[UartID].RxBuf.Pos < Len)?prvUart[UartID].RxBuf.Pos:Len;
461     memcpy(Data, prvUart[UartID].RxBuf.Data, ReadLen);
462     OS_BufferRemove(&prvUart[UartID].RxBuf, ReadLen);
463     if (!prvUart[UartID].RxBuf.Pos && prvUart[UartID].RxBuf.MaxLen > RX_BUF_HIGH)
464     {
465         OS_ReInitBuffer(&prvUart[UartID].RxBuf, RX_BUF_INIT);
466     }
467     ISR_OnOff(prvUart[UartID].IrqLine, 1);
468     return ReadLen;
469 #else
470     return 0;
471 #endif
472 }
473 
Uart_RxBufferClear(uint8_t UartID)474 void Uart_RxBufferClear(uint8_t UartID)
475 {
476     uint32_t ReadLen;
477     if (!prvUart[UartID].RxCacheMode)
478     {
479         return ;
480     }
481     ISR_OnOff(prvUart[UartID].IrqLine, 0);
482     prvUart[UartID].RxBuf.Pos = 0;
483     ISR_OnOff(prvUart[UartID].IrqLine, 1);
484 }
485 
prvUart_Tx(uint8_t UartID,UART_TypeDef * Uart)486 static void prvUart_Tx(uint8_t UartID, UART_TypeDef* Uart)
487 {
488     if (prvUart[UartID].TxBuf.Data)
489     {
490         while ((prvUart[UartID].TxBuf.Pos < prvUart[UartID].TxBuf.MaxLen) && (Uart->USR & UART_STATUS_TX_FIFO_NOT_FULL))
491         {
492             Uart->OFFSET_0.THR = prvUart[UartID].TxBuf.Data[prvUart[UartID].TxBuf.Pos];
493             prvUart[UartID].TxBuf.Pos++;
494         }
495         if (prvUart[UartID].TxBuf.Pos >= prvUart[UartID].TxBuf.MaxLen)
496         {
497 #ifdef __BUILD_OS__
498             OS_DeInitBuffer(&prvUart[UartID].TxBuf);
499             Uart_BufferTx(UartID, NULL, 0);
500 #else
501             memset(&prvUart[UartID].TxBuf, 0, sizeof(prvUart[UartID].TxBuf));
502 #endif
503         }
504     }
505 #ifdef __BUILD_OS__
506     else if (prvUart[UartID].TxCacheBuf.Pos)
507     {
508         Uart_BufferTx(UartID, NULL, 0);
509     }
510 
511     if (!prvUart[UartID].TxBuf.Data && !prvUart[UartID].TxCacheBuf.Pos)
512 #else
513     if (!prvUart[UartID].TxBuf.Data)
514 #endif
515     {
516         if (Uart->OFFSET_4.IER & UART_IER_PTIME)
517         {
518             Uart->OFFSET_4.IER &= ~UART_IER_PTIME;
519             prvUart[UartID].Callback((uint32_t)UartID, (void *)UART_CB_TX_BUFFER_DONE);
520         }
521         else
522         {
523             Uart->OFFSET_4.IER &= ~UART_IER_ETBEI;
524             prvUart[UartID].Callback((uint32_t)UartID, (void *)UART_CB_TX_ALL_DONE);
525         }
526     }
527 }
528 
prvUart_IrqHandle(int32_t IrqLine,void * pData)529 static void prvUart_IrqHandle(int32_t IrqLine, void *pData)
530 {
531     uint8_t UartID = (uint32_t)pData;
532     UART_TypeDef* Uart = (UART_TypeDef*)prvUart[UartID].RegBase;
533     uint32_t reg_value, read_len;
534     switch(Uart->OFFSET_8.IIR & 0x0f)
535     {
536     case UART_IT_ID_RX_RECVD:
537         {
538             prvUart[UartID].Callback((uint32_t)UartID, (void *)UART_CB_RX_NEW);
539         }
540         break;
541     case UART_IT_ID_TX_EMPTY:
542         {
543 
544             prvUart_Tx(UartID, Uart);
545 
546         }
547         break;
548     case UART_IT_ID_MODEM_STATUS:
549         {
550             reg_value = Uart->MSR;
551         }
552         break;
553     case UART_IT_ID_LINE_STATUS:
554         {
555             reg_value = Uart->LSR;
556             if (reg_value & UART_LSR_TEMT)
557             {
558                 prvUart_Tx(UartID, Uart);
559             }
560             if (reg_value & (UART_LSR_PFE|UART_LSR_BI|UART_LSR_FE|UART_LSR_PE|UART_LSR_OE))
561             {
562                 prvUart[UartID].LastError = reg_value;
563                 prvUart[UartID].Callback((uint32_t)UartID, (void *)UART_CB_ERROR);
564             }
565         }
566         break;
567     case UART_IT_ID_BUSY_DETECT:
568         {
569             reg_value = Uart->USR;
570         }
571         break;
572     case UART_IT_ID_CHAR_TIMEOUT:
573         prvUart[UartID].Callback((uint32_t)UartID, (void *)UART_CB_RX_TIMEOUT);
574         break;
575     default:
576         break;
577     }
578 }
Uart_ChangeBR(uint8_t UartID,uint32_t BaudRate)579 void Uart_ChangeBR(uint8_t UartID, uint32_t BaudRate)
580 {
581     UART_TypeDef* Uart = prvUart[UartID].RegBase;
582     Uart->LCR |= UART_LCR_DLAB;
583 
584     // baud rate = (serial clock freq) / (16 * divisor).
585     uint32_t tmpBaudRateDiv = (SystemCoreClock >> 6) / BaudRate;
586     Uart->OFFSET_0.DLL = (tmpBaudRateDiv & 0x00FF);
587     Uart->OFFSET_4.DLH = ((tmpBaudRateDiv >> 8) & 0x00FF);
588 
589     /* LCR = 0 */
590     Uart->LCR &= ~UART_LCR_DLAB;
591 }
592 
Uart_GetLastError(uint8_t UartID)593 uint32_t Uart_GetLastError(uint8_t UartID)
594 {
595     return prvUart[UartID].LastError;
596 }
597 
Uart_IrqOnOff(uint8_t UartID,uint8_t OnOff)598 void Uart_IrqOnOff(uint8_t UartID, uint8_t OnOff)
599 {
600     ISR_OnOff(prvUart[UartID].IrqLine, OnOff);
601 }
602