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