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