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