1 /*
2  * Copyright (C) 2017-2019 Alibaba Group Holding Limited
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2020-08-20     zx.chen      CSI Source File for usart Driver
9  */
10 
11 #include <csi_config.h>
12 #include <stdbool.h>
13 #include <string.h>
14 #include <drv_irq.h>
15 #include <drv_usart.h>
16 #include <ck_usart.h>
17 #include <soc.h>
18 #include <csi_core.h>
19 
20 #define ERR_USART(errno) (CSI_DRV_ERRNO_USART_BASE | errno)
21 
22 /*
23  * setting config may be accessed when the USART is not
24  * busy(USR[0]=0) and the DLAB bit(LCR[7]) is set.
25  */
26 
27 #define WAIT_USART_IDLE(addr)\
28     do {                       \
29         int32_t timecount = 0;  \
30         while ((addr->USR & USR_UART_BUSY) && (timecount < UART_BUSY_TIMEOUT)) {\
31             timecount++;\
32         }\
33         if (timecount >= UART_BUSY_TIMEOUT) {\
34             return ERR_USART(DRV_ERROR_TIMEOUT);\
35         }                                   \
36     } while(0)
37 
38 #define USART_NULL_PARAM_CHK(para) HANDLE_PARAM_CHK(para, ERR_USART(DRV_ERROR_PARAMETER))
39 
40 typedef struct
41 {
42     uint32_t base;
43     uint32_t irq;
44     usart_event_cb_t cb_event;           ///< Event callback
45     uint32_t rx_total_num;
46     uint32_t tx_total_num;
47     uint8_t *rx_buf;
48     uint8_t *tx_buf;
49     volatile uint32_t rx_cnt;
50     volatile uint32_t tx_cnt;
51     volatile uint32_t tx_busy;
52     volatile uint32_t rx_busy;
53     uint32_t last_tx_num;
54     uint32_t last_rx_num;
55     int32_t idx;
56 } ck_usart_priv_t;
57 
58 extern int32_t target_usart_init(int32_t idx, uint32_t *base, uint32_t *irq, void **handler);
59 
60 static ck_usart_priv_t usart_instance[CONFIG_USART_NUM];
61 
62 static const usart_capabilities_t usart_capabilities =
63 {
64     .asynchronous = 1,          /* supports USART (Asynchronous) mode */
65     .synchronous_master = 0,    /* supports Synchronous Master mode */
66     .synchronous_slave = 0,     /* supports Synchronous Slave mode */
67     .single_wire = 0,           /* supports USART Single-wire mode */
68     .event_tx_complete = 1,     /* Transmit completed event */
69     .event_rx_timeout = 0,      /* Signal receive character timeout event */
70 };
71 
72 /**
73   \brief       set the bautrate of usart.
74   \param[in]   addr  usart base to operate.
75   \return      error code
76 */
csi_usart_config_baudrate(usart_handle_t handle,uint32_t baud)77 int32_t csi_usart_config_baudrate(usart_handle_t handle, uint32_t baud)
78 {
79     USART_NULL_PARAM_CHK(handle);
80     ck_usart_priv_t *usart_priv = handle;
81     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
82 
83 
84     WAIT_USART_IDLE(addr);
85 
86     /* baudrate=(seriak clock freq)/(16*divisor); algorithm :rounding*/
87     uint32_t divisor = ((drv_get_usart_freq(usart_priv->idx)  * 10) / baud) >> 4;
88 
89     if ((divisor % 10) >= 5)
90     {
91         divisor = (divisor / 10) + 1;
92     } else
93     {
94         divisor = divisor / 10;
95     }
96 
97     addr->LCR |= LCR_SET_DLAB;
98     /* DLL and DLH is lower 8-bits and higher 8-bits of divisor.*/
99     addr->DLL = divisor & 0xff;
100     addr->DLH = (divisor >> 8) & 0xff;
101     /*
102      * The DLAB must be cleared after the baudrate is setted
103      * to access other registers.
104      */
105     addr->LCR &= (~LCR_SET_DLAB);
106 
107     return 0;
108 }
109 
110 /**
111   \brief       config usart mode.
112   \param[in]   handle  usart handle to operate.
113   \param[in]   mode    \ref usart_mode_e
114   \return      error code
115 */
csi_usart_config_mode(usart_handle_t handle,usart_mode_e mode)116 int32_t csi_usart_config_mode(usart_handle_t handle, usart_mode_e mode)
117 {
118     USART_NULL_PARAM_CHK(handle);
119 
120     if (mode == USART_MODE_ASYNCHRONOUS)
121     {
122         return 0;
123     }
124 
125     return ERR_USART(USART_ERROR_MODE);
126 }
127 
128 /**
129   \brief       config usart parity.
130   \param[in]   handle  usart handle to operate.
131   \param[in]   parity    \ref usart_parity_e
132   \return      error code
133 */
csi_usart_config_parity(usart_handle_t handle,usart_parity_e parity)134 int32_t csi_usart_config_parity(usart_handle_t handle, usart_parity_e parity)
135 {
136     USART_NULL_PARAM_CHK(handle);
137     ck_usart_priv_t *usart_priv = handle;
138     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
139 
140     WAIT_USART_IDLE(addr);
141 
142     switch (parity)
143     {
144         case USART_PARITY_NONE:
145             /*CLear the PEN bit(LCR[3]) to disable parity.*/
146             addr->LCR &= (~LCR_PARITY_ENABLE);
147             break;
148 
149         case USART_PARITY_ODD:
150             /* Set PEN and clear EPS(LCR[4]) to set the ODD parity. */
151             addr->LCR |= LCR_PARITY_ENABLE;
152             addr->LCR &= LCR_PARITY_ODD;
153             break;
154 
155         case USART_PARITY_EVEN:
156             /* Set PEN and EPS(LCR[4]) to set the EVEN parity.*/
157             addr->LCR |= LCR_PARITY_ENABLE;
158             addr->LCR |= LCR_PARITY_EVEN;
159             break;
160 
161         default:
162             return ERR_USART(USART_ERROR_PARITY);
163     }
164 
165     return 0;
166 }
167 
168 /**
169   \brief       config usart stop bit number.
170   \param[in]   handle  usart handle to operate.
171   \param[in]   stopbits  \ref usart_stop_bits_e
172   \return      error code
173 */
csi_usart_config_stopbits(usart_handle_t handle,usart_stop_bits_e stopbit)174 int32_t csi_usart_config_stopbits(usart_handle_t handle, usart_stop_bits_e stopbit)
175 {
176     USART_NULL_PARAM_CHK(handle);
177     ck_usart_priv_t *usart_priv = handle;
178     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
179 
180     WAIT_USART_IDLE(addr);
181 
182     switch (stopbit)
183     {
184         case USART_STOP_BITS_1:
185             /* Clear the STOP bit to set 1 stop bit*/
186             addr->LCR &= LCR_STOP_BIT1;
187             break;
188 
189         case USART_STOP_BITS_2:
190             /*
191             * If the STOP bit is set "1",we'd gotten 1.5 stop
192             * bits when DLS(LCR[1:0]) is zero, else 2 stop bits.
193             */
194             addr->LCR |= LCR_STOP_BIT2;
195             break;
196 
197         default:
198             return ERR_USART(USART_ERROR_STOP_BITS);
199     }
200 
201     return 0;
202 }
203 
204 /**
205   \brief       config usart data length.
206   \param[in]   handle  usart handle to operate.
207   \param[in]   databits      \ref usart_data_bits_e
208   \return      error code
209 */
csi_usart_config_databits(usart_handle_t handle,usart_data_bits_e databits)210 int32_t csi_usart_config_databits(usart_handle_t handle, usart_data_bits_e databits)
211 {
212     USART_NULL_PARAM_CHK(handle);
213     ck_usart_priv_t *usart_priv = handle;
214     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
215 
216     WAIT_USART_IDLE(addr);
217     /* The word size decides by the DLS bits(LCR[1:0]), and the
218      * corresponding relationship between them is:
219      *   DLS   word size
220      *       00 -- 5 bits
221      *       01 -- 6 bits
222      *       10 -- 7 bits
223      *       11 -- 8 bits
224      */
225 
226     switch (databits)
227     {
228         case USART_DATA_BITS_5:
229             addr->LCR &= LCR_WORD_SIZE_5;
230             break;
231 
232         case USART_DATA_BITS_6:
233             addr->LCR &= 0xfd;
234             addr->LCR |= LCR_WORD_SIZE_6;
235             break;
236 
237         case USART_DATA_BITS_7:
238             addr->LCR &= 0xfe;
239             addr->LCR |= LCR_WORD_SIZE_7;
240             break;
241 
242         case USART_DATA_BITS_8:
243             addr->LCR |= LCR_WORD_SIZE_8;
244             break;
245 
246         default:
247             return ERR_USART(USART_ERROR_DATA_BITS);
248     }
249 
250     return 0;
251 }
252 
253 
ck_usart_set_int_flag(usart_handle_t handle,uint32_t flag)254 int32_t ck_usart_set_int_flag(usart_handle_t handle,uint32_t flag)
255 {
256     ck_usart_priv_t *usart_priv = handle;
257     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
258 
259     addr->IER |= flag;
260 
261     return 0;
262 }
263 
ck_usart_clr_int_flag(usart_handle_t handle,uint32_t flag)264 int32_t ck_usart_clr_int_flag(usart_handle_t handle,uint32_t flag)
265 {
266     ck_usart_priv_t *usart_priv = handle;
267     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
268 
269     addr->IER &= ~flag;
270 
271     return 0;
272 }
273 
274 
275 /**
276   \brief       get character in query mode.
277   \param[in]   instance  usart instance to operate.
278   \param[in]   the pointer to the recieve charater.
279   \return      error code
280 */
csi_usart_getchar(usart_handle_t handle,uint8_t * ch)281 int32_t csi_usart_getchar(usart_handle_t handle, uint8_t *ch)
282 {
283     USART_NULL_PARAM_CHK(handle);
284     USART_NULL_PARAM_CHK(ch);
285 
286     ck_usart_priv_t *usart_priv = handle;
287     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
288 
289     while (!(addr->LSR & LSR_DATA_READY));
290 
291     *ch = addr->RBR;
292 
293     return 0;
294 }
295 
296 
297 /**
298   \brief       get character in query mode.
299   \param[in]   instance  usart instance to operate.
300   \param[in]   the pointer to the recieve charater.
301   \return      error code
302 */
csi_uart_getchar(usart_handle_t handle)303 int csi_uart_getchar(usart_handle_t handle)
304 {
305     volatile int ch;
306     USART_NULL_PARAM_CHK(handle);
307 
308     ck_usart_priv_t *usart_priv = handle;
309     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
310 
311     ch = -1;
312 
313     if (addr->LSR & LSR_DATA_READY)
314     {
315         ch = addr->RBR & 0xff;
316     }
317 
318     return ch;
319 }
320 
321 
322 /**
323   \brief       transmit character in query mode.
324   \param[in]   instance  usart instance to operate.
325   \param[in]   ch  the input charater
326   \return      error code
327 */
csi_usart_putchar(usart_handle_t handle,uint8_t ch)328 int32_t csi_usart_putchar(usart_handle_t handle, uint8_t ch)
329 {
330     USART_NULL_PARAM_CHK(handle);
331     ck_usart_priv_t *usart_priv = handle;
332     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
333     uint32_t timecount = 0;
334 
335     while ((!(addr->LSR & DW_LSR_TRANS_EMPTY)))
336     {
337         timecount++;
338 
339         if (timecount >= UART_BUSY_TIMEOUT)
340         {
341             return ERR_USART(DRV_ERROR_TIMEOUT);
342         }
343     }
344 
345     addr->THR = ch;
346 
347     return 0;
348 
349 }
350 
351 /**
352   \brief       interrupt service function for transmitter holding register empty.
353   \param[in]   usart_priv usart private to operate.
354 */
ck_usart_intr_threshold_empty(int32_t idx,ck_usart_priv_t * usart_priv)355 void ck_usart_intr_threshold_empty(int32_t idx, ck_usart_priv_t *usart_priv)
356 {
357     if (usart_priv->tx_total_num == 0)
358     {
359         return;
360     }
361 
362     volatile int i = 500;
363     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
364 
365     if (usart_priv->tx_cnt >= usart_priv->tx_total_num)
366     {
367         addr->IER &= (~IER_THRE_INT_ENABLE);
368         usart_priv->last_tx_num = usart_priv->tx_total_num;
369 
370         /* fix hardware bug */
371         while (addr->USR & USR_UART_BUSY);
372 
373         i = 500;
374 
375         while (i--);
376 
377         usart_priv->tx_cnt = 0;
378         usart_priv->tx_busy = 0;
379         usart_priv->tx_buf = NULL;
380         usart_priv->tx_total_num = 0;
381 
382         if (usart_priv->cb_event)
383         {
384             usart_priv->cb_event(idx, USART_EVENT_SEND_COMPLETE);
385         }
386     } else
387     {
388         /* fix hardware bug */
389         while (addr->USR & USR_UART_BUSY);
390 
391         i = 500;
392 
393         while (i--);
394 
395         addr->THR = *((uint8_t *)usart_priv->tx_buf);
396         usart_priv->tx_cnt++;
397         usart_priv->tx_buf++;
398     }
399 }
400 
401 /**
402   \brief        interrupt service function for receiver data available.
403   \param[in]   usart_priv usart private to operate.
404 */
ck_usart_intr_recv_data(int32_t idx,ck_usart_priv_t * usart_priv)405 static void ck_usart_intr_recv_data(int32_t idx, ck_usart_priv_t *usart_priv)
406 {
407     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
408     uint8_t data = addr->RBR;
409 
410     *((uint8_t *)usart_priv->rx_buf) = data;
411     usart_priv->rx_cnt++;
412     usart_priv->rx_buf++;
413 
414     if (usart_priv->rx_cnt >= usart_priv->rx_total_num)
415     {
416         usart_priv->last_rx_num = usart_priv->rx_total_num;
417         usart_priv->rx_cnt = 0;
418         usart_priv->rx_buf = NULL;
419         usart_priv->rx_busy = 0;
420         usart_priv->rx_total_num = 0;
421 
422         if (usart_priv->cb_event)
423         {
424             usart_priv->cb_event(idx, USART_EVENT_RECEIVE_COMPLETE);
425         }
426     }
427 
428 }
429 
430 /**
431   \brief        interrupt service function for receiver line.
432   \param[in]   usart_priv usart private to operate.
433 */
ck_usart_intr_recv_line(int32_t idx,ck_usart_priv_t * usart_priv)434 static void ck_usart_intr_recv_line(int32_t idx, ck_usart_priv_t *usart_priv)
435 {
436     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
437     uint32_t lsr_stat = addr->LSR;
438 
439     addr->IER &= (~IER_THRE_INT_ENABLE);
440 
441     uint32_t timecount = 0;
442 
443     while (addr->LSR & 0x1)
444     {
445         addr->RBR;
446         timecount++;
447 
448         if (timecount >= UART_BUSY_TIMEOUT)
449         {
450             if (usart_priv->cb_event)
451             {
452                 usart_priv->cb_event(idx, USART_EVENT_RX_TIMEOUT);
453             }
454 
455             return;
456         }
457     }
458 
459     /** Break Interrupt bit. This is used to indicate the detection of a
460       * break sequence on the serial input data.
461       */
462     if (lsr_stat & DW_LSR_BI)
463     {
464         if (usart_priv->cb_event)
465         {
466             usart_priv->cb_event(idx, USART_EVENT_RX_BREAK);
467         }
468 
469         return;
470     }
471 
472     /** Framing Error bit. This is used to indicate the occurrence of a
473       * framing error in the receiver. A framing error occurs when the receiver
474       * does not detect a valid STOP bit in the received data.
475       */
476     if (lsr_stat & DW_LSR_FE)
477     {
478         if (usart_priv->cb_event)
479         {
480             usart_priv->cb_event(idx, USART_EVENT_RX_FRAMING_ERROR);
481         }
482 
483         return;
484     }
485 
486     /** Framing Error bit. This is used to indicate the occurrence of a
487       * framing error in the receiver. A framing error occurs when the
488       * receiver does not detect a valid STOP bit in the received data.
489       */
490     if (lsr_stat & DW_LSR_PE)
491     {
492         if (usart_priv->cb_event)
493         {
494             usart_priv->cb_event(idx, USART_EVENT_RX_PARITY_ERROR);
495         }
496 
497         return;
498     }
499 
500     /** Overrun error bit. This is used to indicate the occurrence of an overrun error.
501       * This occurs if a new data character was received before the previous data was read.
502       */
503     if (lsr_stat & DW_LSR_OE)
504     {
505         if (usart_priv->cb_event)
506         {
507             usart_priv->cb_event(idx, USART_EVENT_RX_OVERFLOW);
508         }
509 
510         return;
511     }
512 }
513 /**
514   \brief        interrupt service function for character timeout.
515   \param[in]   usart_priv usart private to operate.
516 */
ck_usart_intr_char_timeout(int32_t idx,ck_usart_priv_t * usart_priv)517 static void ck_usart_intr_char_timeout(int32_t idx, ck_usart_priv_t *usart_priv)
518 {
519     if ((usart_priv->rx_total_num != 0) && (usart_priv->rx_buf != NULL))
520     {
521         ck_usart_intr_recv_data(idx, usart_priv);
522         return;
523     }
524 
525     if (usart_priv->cb_event)
526     {
527         usart_priv->cb_event(idx, USART_EVENT_RECEIVED);
528     } else
529     {
530         ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
531 
532         uint32_t timecount = 0;
533 
534         while (addr->LSR & 0x1)
535         {
536             addr->RBR;
537             timecount++;
538 
539             if (timecount >= UART_BUSY_TIMEOUT)
540             {
541                 if (usart_priv->cb_event)
542                 {
543                     usart_priv->cb_event(idx, USART_EVENT_RX_TIMEOUT);
544                 }
545 
546                 return;
547             }
548         }
549     }
550 }
551 
552 /**
553   \brief       the interrupt service function.
554   \param[in]   index of usart instance.
555 */
ck_usart_irqhandler(int32_t idx)556 void ck_usart_irqhandler(int32_t idx)
557 {
558     ck_usart_priv_t *usart_priv = &usart_instance[idx];
559     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
560 
561     uint8_t intr_state = addr->IIR & 0xf;
562 
563     switch (intr_state)
564     {
565         case DW_IIR_THR_EMPTY:       /* interrupt source:transmitter holding register empty */
566             ck_usart_intr_threshold_empty(idx, usart_priv);
567             break;
568 
569         case DW_IIR_RECV_DATA:       /* interrupt source:receiver data available or receiver fifo trigger level reached */
570             ck_usart_intr_char_timeout(idx, usart_priv);
571             //ck_usart_intr_recv_data(idx, usart_priv);
572             break;
573 
574         case DW_IIR_RECV_LINE:
575             ck_usart_intr_recv_line(idx, usart_priv);
576             break;
577 
578         case DW_IIR_CHAR_TIMEOUT:
579             ck_usart_intr_char_timeout(idx, usart_priv);
580             break;
581 
582         default:
583             break;
584     }
585 }
586 
587 /**
588   \brief       Get driver capabilities.
589   \param[in]   idx usart index
590   \return      \ref usart_capabilities_t
591 */
csi_usart_get_capabilities(int32_t idx)592 usart_capabilities_t csi_usart_get_capabilities(int32_t idx)
593 {
594     if (idx < 0 || idx >= CONFIG_USART_NUM)
595     {
596         usart_capabilities_t ret;
597         memset(&ret, 0, sizeof(usart_capabilities_t));
598         return ret;
599     }
600 
601     return usart_capabilities;
602 }
603 
604 /**
605   \brief       Initialize USART Interface. 1. Initializes the resources needed for the USART interface 2.registers event callback function
606   \param[in]   idx usart index
607   \param[in]   cb_event  Pointer to \ref usart_event_cb_t
608   \return      return usart handle if success
609 */
csi_usart_initialize(int32_t idx,usart_event_cb_t cb_event)610 usart_handle_t csi_usart_initialize(int32_t idx, usart_event_cb_t cb_event)
611 {
612     uint32_t base = 0u;
613     uint32_t irq = 0u;
614     void *handler;
615 
616     int32_t ret = target_usart_init(idx, &base, &irq, &handler);
617 
618     if (ret < 0 || ret >= CONFIG_USART_NUM)
619     {
620         return NULL;
621     }
622 
623     ck_usart_priv_t *usart_priv = &usart_instance[idx];
624     usart_priv->base = base;
625     usart_priv->irq = irq;
626     usart_priv->cb_event = cb_event;
627     usart_priv->idx = idx;
628     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
629 
630     /* enable received data available */
631     addr->IER = IER_RDA_INT_ENABLE | IIR_RECV_LINE_ENABLE;
632     drv_irq_register(usart_priv->irq, handler);
633     drv_irq_enable(usart_priv->irq);
634 
635     return usart_priv;
636 }
637 
638 /**
639   \brief       De-initialize UART Interface. stops operation and releases the software resources used by the interface
640   \param[in]   handle  usart handle to operate.
641   \return      error code
642 */
csi_usart_uninitialize(usart_handle_t handle)643 int32_t csi_usart_uninitialize(usart_handle_t handle)
644 {
645     USART_NULL_PARAM_CHK(handle);
646 
647     ck_usart_priv_t *usart_priv = handle;
648 
649     drv_irq_disable(usart_priv->irq);
650     drv_irq_unregister(usart_priv->irq);
651     usart_priv->cb_event   = NULL;
652 
653     return 0;
654 }
655 
656 /**
657   \brief       config usart mode.
658   \param[in]   handle  usart handle to operate.
659   \param[in]   baud      baud rate
660   \param[in]   mode      \ref usart_mode_e
661   \param[in]   parity    \ref usart_parity_e
662   \param[in]   stopbits  \ref usart_stop_bits_e
663   \param[in]   bits      \ref usart_data_bits_e
664   \return      error code
665 */
csi_usart_config(usart_handle_t handle,uint32_t baud,usart_mode_e mode,usart_parity_e parity,usart_stop_bits_e stopbits,usart_data_bits_e bits)666 int32_t csi_usart_config(usart_handle_t handle,
667                          uint32_t baud,
668                          usart_mode_e mode,
669                          usart_parity_e parity,
670                          usart_stop_bits_e stopbits,
671                          usart_data_bits_e bits)
672 {
673     int32_t ret;
674 
675     /* control the data_bit of the usart*/
676     ret = csi_usart_config_baudrate(handle, baud);
677 
678     if (ret < 0)
679     {
680         return ret;
681     }
682 
683     /* control mode of the usart*/
684     ret = csi_usart_config_mode(handle, mode);
685 
686     if (ret < 0)
687     {
688         return ret;
689     }
690 
691     /* control the parity of the usart*/
692     ret = csi_usart_config_parity(handle, parity);
693 
694     if (ret < 0)
695     {
696         return ret;
697     }
698 
699     /* control the stopbit of the usart*/
700     ret = csi_usart_config_stopbits(handle, stopbits);
701 
702     if (ret < 0)
703     {
704         return ret;
705     }
706 
707     ret = csi_usart_config_databits(handle, bits);
708 
709     if (ret < 0)
710     {
711         return ret;
712     }
713 
714     return 0;
715 }
716 
717 
718 /**
719   \brief       Start sending data to UART transmitter,(received data is ignored).
720                The function is non-blocking,UART_EVENT_TRANSFER_COMPLETE is signaled when transfer completes.
721                csi_usart_get_status can indicates if transmission is still in progress or pending
722   \param[in]   handle  usart handle to operate.
723   \param[in]   data  Pointer to buffer with data to send to UART transmitter. data_type is : uint8_t for 1..8 data bits, uint16_t for 9..16 data bits,uint32_t for 17..32 data bits,
724   \param[in]   num   Number of data items to send
725   \return      error code
726 */
csi_usart_send(usart_handle_t handle,const void * data,uint32_t num)727 int32_t csi_usart_send(usart_handle_t handle, const void *data, uint32_t num)
728 {
729     USART_NULL_PARAM_CHK(handle);
730     USART_NULL_PARAM_CHK(data);
731 
732     if (num == 0)
733     {
734         return ERR_USART(DRV_ERROR_PARAMETER);
735     }
736 
737     ck_usart_priv_t *usart_priv = handle;
738 
739     usart_priv->tx_buf = (uint8_t *)data;
740     usart_priv->tx_total_num = num;
741     usart_priv->tx_cnt = 0;
742     usart_priv->tx_busy = 1;
743     usart_priv->last_tx_num = 0;
744 
745     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
746     ck_usart_intr_threshold_empty(usart_priv->idx, usart_priv);
747     /* enable the interrupt*/
748     addr->IER |= IER_THRE_INT_ENABLE;
749     return 0;
750 }
751 
752 /**
753   \brief       Abort Send data to UART transmitter
754   \param[in]   handle  usart handle to operate.
755   \return      error code
756 */
csi_usart_abort_send(usart_handle_t handle)757 int32_t csi_usart_abort_send(usart_handle_t handle)
758 {
759     USART_NULL_PARAM_CHK(handle);
760     ck_usart_priv_t *usart_priv = handle;
761 
762     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
763     addr->IER &= (~IER_THRE_INT_ENABLE);
764 
765     usart_priv->tx_cnt = usart_priv->tx_total_num;
766     usart_priv->tx_cnt = 0;
767     usart_priv->tx_busy = 0;
768     usart_priv->tx_buf = NULL;
769     usart_priv->tx_total_num = 0;
770     return 0;
771 }
772 
773 /**
774   \brief       Start receiving data from UART receiver.transmits the default value as specified by csi_usart_set_default_tx_value
775   \param[in]   handle  usart handle to operate.
776   \param[out]  data  Pointer to buffer for data to receive from UART receiver
777   \param[in]   num   Number of data items to receive
778   \return      error code
779 */
csi_usart_receive(usart_handle_t handle,void * data,uint32_t num)780 int32_t csi_usart_receive(usart_handle_t handle, void *data, uint32_t num)
781 {
782     USART_NULL_PARAM_CHK(handle);
783     USART_NULL_PARAM_CHK(data);
784 
785     ck_usart_priv_t *usart_priv = handle;
786 
787     usart_priv->rx_buf = (uint8_t *)data;   // Save receive buffer usart
788     usart_priv->rx_total_num = num;         // Save number of data to be received
789     usart_priv->rx_cnt = 0;
790     usart_priv->rx_busy = 1;
791     usart_priv->last_rx_num = 0;
792 
793     return 0;
794 
795 }
796 
797 /**
798   \brief       query data from UART receiver FIFO.
799   \param[in]   handle  usart handle to operate.
800   \param[out]  data  Pointer to buffer for data to receive from UART receiver
801   \param[in]   num   Number of data items to receive
802   \return      receive fifo data num
803 */
csi_usart_receive_query(usart_handle_t handle,void * data,uint32_t num)804 int32_t csi_usart_receive_query(usart_handle_t handle, void *data, uint32_t num)
805 {
806     USART_NULL_PARAM_CHK(handle);
807     USART_NULL_PARAM_CHK(data);
808 
809     ck_usart_priv_t *usart_priv = handle;
810     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
811     int32_t recv_num = 0;
812     uint8_t *dest = (uint8_t *)data;
813 
814     while (addr->LSR & 0x1)
815     {
816         *dest++ = addr->RBR;
817         recv_num++;
818 
819         if (recv_num >= num)
820         {
821             break;
822         }
823     }
824 
825     return recv_num;
826 
827 }
828 
829 /**
830   \brief       Abort Receive data from UART receiver
831   \param[in]   handle  usart handle to operate.
832   \return      error code
833 */
csi_usart_abort_receive(usart_handle_t handle)834 int32_t csi_usart_abort_receive(usart_handle_t handle)
835 {
836     USART_NULL_PARAM_CHK(handle);
837     ck_usart_priv_t *usart_priv = handle;
838 
839     usart_priv->rx_cnt = usart_priv->rx_total_num;
840     return 0;
841 }
842 
843 /**
844   \brief       Start sending/receiving data to/from UART transmitter/receiver.
845   \param[in]   handle  usart handle to operate.
846   \param[in]   data_out  Pointer to buffer with data to send to USART transmitter
847   \param[out]  data_in   Pointer to buffer for data to receive from USART receiver
848   \param[in]   num       Number of data items to transfer
849   \return      error code
850 */
csi_usart_transfer(usart_handle_t handle,const void * data_out,void * data_in,uint32_t num)851 int32_t csi_usart_transfer(usart_handle_t handle, const void *data_out, void *data_in, uint32_t num)
852 {
853     USART_NULL_PARAM_CHK(handle);
854     return ERR_USART(DRV_ERROR_UNSUPPORTED);
855 }
856 
857 /**
858   \brief       abort sending/receiving data to/from USART transmitter/receiver.
859   \param[in]   handle  usart handle to operate.
860   \return      error code
861 */
csi_usart_abort_transfer(usart_handle_t handle)862 int32_t csi_usart_abort_transfer(usart_handle_t handle)
863 {
864     USART_NULL_PARAM_CHK(handle);
865     return ERR_USART(DRV_ERROR_UNSUPPORTED);
866 }
867 
868 /**
869   \brief       Get USART status.
870   \param[in]   handle  usart handle to operate.
871   \return      USART status \ref usart_status_t
872 */
csi_usart_get_status(usart_handle_t handle)873 usart_status_t csi_usart_get_status(usart_handle_t handle)
874 {
875     usart_status_t usart_status;
876 
877     memset(&usart_status, 0, sizeof(usart_status_t));
878 
879     if (handle == NULL)
880     {
881         return usart_status;
882     }
883 
884     ck_usart_priv_t *usart_priv = handle;
885     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
886     uint32_t line_status_reg    = addr->LSR;
887 
888     usart_status.tx_busy = usart_priv->tx_busy;
889     usart_status.rx_busy = usart_priv->rx_busy;
890 
891     if (line_status_reg & DW_LSR_BI)
892     {
893         usart_status.rx_break = 1;
894     }
895 
896     if (line_status_reg & DW_LSR_FE)
897     {
898         usart_status.rx_framing_error = 1;
899     }
900 
901     if (line_status_reg & DW_LSR_PE)
902     {
903         usart_status.rx_parity_error = 1;
904     }
905 
906     usart_status.tx_enable  = 1;
907     usart_status.rx_enable  = 1;
908 
909     return usart_status;
910 }
911 
912 /**
913   \brief       control the transmit.
914   \param[in]   handle  usart handle to operate.
915   \param[in]   1 - enable the transmitter. 0 - disable the transmitter
916   \return      error code
917 */
csi_usart_control_tx(usart_handle_t handle,uint32_t enable)918 int32_t csi_usart_control_tx(usart_handle_t handle, uint32_t enable)
919 {
920     USART_NULL_PARAM_CHK(handle);
921     return 0;
922 }
923 
924 /**
925   \brief       control the receive.
926   \param[in]   handle  usart handle to operate.
927   \param[in]   1 - enable the receiver. 0 - disable the receiver
928   \return      error code
929 */
csi_usart_control_rx(usart_handle_t handle,uint32_t enable)930 int32_t csi_usart_control_rx(usart_handle_t handle, uint32_t enable)
931 {
932     USART_NULL_PARAM_CHK(handle);
933     return 0;
934 }
935 
936 /**
937   \brief       control the break.
938   \param[in]   handle  usart handle to operate.
939   \param[in]   1- Enable continuous Break transmission,0 - disable continuous Break transmission
940   \return      error code
941 */
csi_usart_control_break(usart_handle_t handle,uint32_t enable)942 int32_t csi_usart_control_break(usart_handle_t handle, uint32_t enable)
943 {
944     USART_NULL_PARAM_CHK(handle);
945     return ERR_USART(DRV_ERROR_UNSUPPORTED);
946 }
947 
948 /**
949   \brief       flush receive/send data.
950   \param[in]   handle usart handle to operate.
951   \param[in]   type \ref usart_flush_type_e.
952   \return      error code
953 */
csi_usart_flush(usart_handle_t handle,usart_flush_type_e type)954 int32_t csi_usart_flush(usart_handle_t handle, usart_flush_type_e type)
955 {
956     USART_NULL_PARAM_CHK(handle);
957 
958     ck_usart_priv_t *usart_priv = handle;
959     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
960 
961     uint32_t timecount = 0;
962 
963     if (type == USART_FLUSH_WRITE) {
964         while ((!(addr->LSR & DW_LSR_TEMT)))
965         {
966             timecount++;
967 
968             if (timecount >= UART_BUSY_TIMEOUT)
969             {
970                 return ERR_USART(DRV_ERROR_TIMEOUT);
971             }
972         }
973     } else if (type == USART_FLUSH_READ)
974     {
975         while (addr->LSR & 0x1) {
976             timecount++;
977 
978             if (timecount >= UART_BUSY_TIMEOUT)
979             {
980                 return ERR_USART(DRV_ERROR_TIMEOUT);
981             }
982         }
983     } else
984     {
985         return ERR_USART(DRV_ERROR_PARAMETER);
986     }
987 
988     return 0;
989 }
990 
991 /**
992   \brief       set interrupt mode.
993   \param[in]   handle usart handle to operate.
994   \param[in]   type \ref usart_intr_type_e.
995   \param[in]   flag 0-OFF, 1-ON.
996   \return      error code
997 */
csi_usart_set_interrupt(usart_handle_t handle,usart_intr_type_e type,int32_t flag)998 int32_t csi_usart_set_interrupt(usart_handle_t handle, usart_intr_type_e type, int32_t flag)
999 {
1000     USART_NULL_PARAM_CHK(handle);
1001 
1002     ck_usart_priv_t *usart_priv = handle;
1003     ck_usart_reg_t *addr = (ck_usart_reg_t *)(usart_priv->base);
1004 
1005     switch (type)
1006     {
1007         case USART_INTR_WRITE:
1008             if (flag == 0)
1009             {
1010                 addr->IER &= ~IER_THRE_INT_ENABLE;
1011             } else if (flag == 1)
1012             {
1013                 addr->IER |= IER_THRE_INT_ENABLE;
1014             } else
1015             {
1016                 return ERR_USART(DRV_ERROR_PARAMETER);
1017             }
1018 
1019             break;
1020 
1021         case USART_INTR_READ:
1022             if (flag == 0)
1023             {
1024                 addr->IER &= ~IER_RDA_INT_ENABLE;
1025             } else if (flag == 1)
1026             {
1027                 addr->IER |= IER_RDA_INT_ENABLE;
1028             } else
1029             {
1030                 return ERR_USART(DRV_ERROR_PARAMETER);
1031             }
1032 
1033             break;
1034 
1035         default:
1036             return ERR_USART(DRV_ERROR_PARAMETER);
1037 
1038     }
1039 
1040     return 0;
1041 }
1042 
1043 /**
1044   \brief       Get usart send data count.
1045   \param[in]   handle  usart handle to operate.
1046   \return      number of currently transmitted data bytes
1047 */
csi_usart_get_tx_count(usart_handle_t handle)1048 uint32_t csi_usart_get_tx_count(usart_handle_t handle)
1049 {
1050     USART_NULL_PARAM_CHK(handle);
1051 
1052     ck_usart_priv_t *usart_priv = handle;
1053 
1054     if (usart_priv->tx_busy)
1055     {
1056         return usart_priv->tx_cnt;
1057     } else
1058     {
1059         return usart_priv->last_tx_num;
1060     }
1061 }
1062 
1063 /**
1064   \brief       Get usart receive data count.
1065   \param[in]   handle  usart handle to operate.
1066   \return      number of currently received data bytes
1067 */
csi_usart_get_rx_count(usart_handle_t handle)1068 uint32_t csi_usart_get_rx_count(usart_handle_t handle)
1069 {
1070     USART_NULL_PARAM_CHK(handle);
1071     ck_usart_priv_t *usart_priv = handle;
1072 
1073     if (usart_priv->rx_busy)
1074     {
1075         return usart_priv->rx_cnt;
1076     } else
1077     {
1078         return usart_priv->last_rx_num;
1079     }
1080 }
1081 
1082 /**
1083   \brief       control usart power.
1084   \param[in]   handle  usart handle to operate.
1085   \param[in]   state   power state.\ref csi_power_stat_e.
1086   \return      error code
1087 */
csi_usart_power_control(usart_handle_t handle,csi_power_stat_e state)1088 int32_t csi_usart_power_control(usart_handle_t handle, csi_power_stat_e state)
1089 {
1090     USART_NULL_PARAM_CHK(handle);
1091     return ERR_USART(DRV_ERROR_UNSUPPORTED);
1092 }
1093 
1094 /**
1095   \brief       config usart flow control type.
1096   \param[in]   handle  usart handle to operate.
1097   \param[in]   flowctrl_type   flow control type.\ref usart_flowctrl_type_e.
1098   \return      error code
1099 */
csi_usart_config_flowctrl(usart_handle_t handle,usart_flowctrl_type_e flowctrl_type)1100 int32_t csi_usart_config_flowctrl(usart_handle_t handle,
1101                                   usart_flowctrl_type_e flowctrl_type)
1102 {
1103     USART_NULL_PARAM_CHK(handle);
1104 
1105     switch (flowctrl_type)
1106     {
1107         case USART_FLOWCTRL_CTS:
1108             return ERR_USART(DRV_ERROR_UNSUPPORTED);
1109 
1110         case USART_FLOWCTRL_RTS:
1111             return ERR_USART(DRV_ERROR_UNSUPPORTED);
1112 
1113         case USART_FLOWCTRL_CTS_RTS:
1114             return ERR_USART(DRV_ERROR_UNSUPPORTED);
1115             break;
1116 
1117         case USART_FLOWCTRL_NONE:
1118             return ERR_USART(DRV_ERROR_UNSUPPORTED);
1119             break;
1120 
1121         default:
1122             return ERR_USART(DRV_ERROR_UNSUPPORTED);
1123     }
1124 
1125     return 0;
1126 }
1127 
1128 
1129 /**
1130   \brief       config usart clock Polarity and Phase.
1131   \param[in]   handle  usart handle to operate.
1132   \param[in]   cpol    Clock Polarity.\ref usart_cpol_e.
1133   \param[in]   cpha    Clock Phase.\ref usart_cpha_e.
1134   \return      error code
1135 */
csi_usart_config_clock(usart_handle_t handle,usart_cpol_e cpol,usart_cpha_e cpha)1136 int32_t csi_usart_config_clock(usart_handle_t handle, usart_cpol_e cpol, usart_cpha_e cpha)
1137 {
1138     USART_NULL_PARAM_CHK(handle);
1139     return ERR_USART(DRV_ERROR_UNSUPPORTED);
1140 }
1141 
1142