comparison src/cs/drivers/drv_core/uart/uart.c @ 0:945cf7f506b2

src/cs: chipsetsw import from tcs211-fcmodem binary blobs and LCD demo files have been excluded, all line endings are LF only
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 25 Sep 2016 22:50:11 +0000
parents
children beff67c568cf
comparison
equal deleted inserted replaced
-1:000000000000 0:945cf7f506b2
1 /*******************************************************************************
2 *
3 * UART.C
4 *
5 * This module allows to use the UARTs of chipset 1.5 in interrupt mode for
6 * the Receive side and in polling mode for the Transmit side.
7 * The driver calls a user's function when characters are received.
8 *
9 * (C) Texas Instruments 1999
10 *
11 ******************************************************************************/
12
13 #include "l1sw.cfg"
14 #include "chipset.cfg"
15 #include "board.cfg"
16
17 #if (OP_L1_STANDALONE == 0)
18 #include "main/sys_types.h"
19 #else
20 #include "sys_types.h"
21 #endif
22
23 #include "uart/traceswitch.h"
24 #include "uart.h"
25
26 #include <string.h>
27
28 #include "memif/mem.h"
29
30 #if (BOARD != 34)
31 /*
32 * Needed to reset and restart the sleep timer in case of incoming characters.
33 */
34
35 #if (OP_L1_STANDALONE == 1)
36 #include "serialswitch_core.h"
37 #else
38 #include "uart/serialswitch.h"
39 #endif
40
41 extern SYS_BOOL uart_sleep_timer_enabled;
42 #endif
43
44 #define BUFFER_SIZE (512) /* In bytes. */
45 #define FIFO_SIZE (64) /* In bytes. */
46
47 #define STX 0x02
48 #define DLE 0x10
49
50 /*
51 * TLR is used to program the RX FIFO trigger levels. FCR[7:4] are not used.
52 */
53
54 #define RX_FIFO_TRIGGER_LEVEL (12 << 4)
55
56
57 /*
58 * 16750 addresses. Registers accessed when LCR[7] = 0.
59 */
60
61 #define RHR (0x00) /* Rx buffer register - Read access */
62 #define THR (0x00) /* Tx holding register - Write access */
63 #define IER (0x01) /* Interrupt enable register */
64
65 /*
66 * 16750 addresses. Registers accessed when LCR[7] = 1.
67 */
68
69 #define DLL (0x00) /* Divisor latch (LSB) */
70 #define DLM (0x01) /* Divisor latch (MSB) */
71
72
73 /*
74 * EFR is accessed when LCR[7:0] = 0xBF.
75 */
76
77 #define EFR (0x02) /* Enhanced feature register */
78
79
80 /*
81 * 16750 addresses. Bit 5 of the FCR register is accessed when LCR[7] = 1.
82 */
83
84 #define IIR (0x02) /* Interrupt ident. register - Read only */
85 #define FCR (0x02) /* FIFO control register - Write only */
86 #define LCR (0x03) /* Line control register */
87 #define MCR (0x04) /* Modem control register */
88 #define LSR (0x05) /* Line status register */
89 #define MSR (0x06) /* Modem status register */
90 #define TCR (0x06) /* Transmission control register */
91 #define TLR (0x07) /* Trigger level register */
92 #define MDR1 (0x08) /* Mode definition register 1 */
93 #define SCR (0x10) /* Supplementary Control register */
94 #define SSR (0x11) /* Supplementary Status register */
95
96
97 /*
98 * Supplementary control register.
99 */
100
101 #define TX_EMPTY_CTL_IT (0x08)
102 #define RX_CTS_WAKE_UP_ENABLE_BIT (4) /* Use RESET_BIT and SET_BIT macros. */
103
104 /*
105 * Enhanced feature register.
106 */
107
108 #define ENHANCED_FEATURE_BIT (4) /* Use RESET_BIT and SET_BIT macros. */
109
110 /*
111 * Mode definition register 1.
112 */
113
114 #define UART_MODE (0x00)
115 #define SIR_MODE (0x01)
116 #define UART_MODE_AUTOBAUDING (0x02) /* Reserved in UART/IrDA. */
117 #define RESET_DEFAULT_STATE (0x07)
118 #define IR_SLEEP_DISABLED (0x00)
119 #define IR_SLEEP_ENABLED (0x08)
120 #define SIR_TX_WITHOUT_ACREG2 (0x00) /* Reserved in UART/modem. */
121 #define SIR_TX_WITH_ACREG2 (0x20) /* Reserved in UART/modem. */
122 #define FRAME_LENGTH_METHOD (0x00) /* Reserved in UART/modem. */
123 #define EOT_BIT_METHOD (0x80) /* Reserved in UART/modem. */
124
125 /*
126 * Supplementary Status Register
127 */
128
129 #define TX_FIFO_FULL (0x01)
130
131
132 /*
133 * Interrupt enable register.
134 */
135
136 #define ERBI (0x01) /* Enable received data available interrupt */
137 #define ETBEI (0x02) /* Enable transmitter holding register empty interrupt */
138 #define ELSI (0x04) /* Enable receiver line status interrupt */
139 #define EDSSI (0x08) /* Enable modem status interrupt */
140 #define IER_SLEEP (0x10) /* Enable sleep mode */
141
142 /*
143 * Modem control register.
144 */
145
146 #define MDTR (0x01) /* Data terminal ready. */
147 #define MRTS (0x02) /* Request to send. */
148 #define TCR_TLR_BIT (6)
149
150 /*
151 * Line status register.
152 */
153
154 #define DR (0x01) /* Data ready */
155 #define OE (0x02) /* Overrun error */
156 #define PE (0x04) /* Parity error */
157 #define FE (0x08) /* Framing error */
158 #define BI (0x10) /* Break interrupt */
159 #define THRE (0x20) /* Transmitter holding register (FIFO empty) */
160 #define TEMT (0x40) /* Transmitter empty (FIFO and TSR both empty) */
161
162 /*
163 * Interrupt identification register.
164 * Bit 0 is set to 0 if an IT is pending.
165 * Bits 1 and 2 are used to identify the IT.
166 */
167
168 #define IIR_BITS_USED (0x07)
169 #define IT_NOT_PENDING (0x01)
170 #define RX_DATA (0x04)
171 #define TX_EMPTY (0x02)
172 #define MODEM_STATUS (0x00)
173
174 /*
175 * Line control register.
176 */
177
178 #define WLS_5 (0x00) /* Word length: 5 bits */
179 #define WLS_6 (0x01) /* Word length: 6 bits */
180 #define WLS_7 (0x02) /* Word length: 7 bits */
181 #define WLS_8 (0x03) /* Word length: 8 bits */
182 #define STB (0x04) /* Number of stop bits: 0: 1, 1: 1,5 or 2 */
183 #define PEN (0x08) /* Parity enable */
184 #define EPS (0x10) /* Even parity select */
185 #define BREAK_CONTROL (0x40) /* Enable a break condition */
186 #define DLAB (0x80) /* Divisor latch access bit */
187 #define DIV_EN_BIT (7)
188
189 /*
190 * FIFO control register.
191 */
192
193 #define FIFO_ENABLE (0x01)
194 #define RX_FIFO_RESET (0x02)
195 #define TX_FIFO_RESET (0x04)
196
197 /*
198 * These macros allow to read and write a UART register.
199 */
200
201 #define READ_UART_REGISTER(UART,REG) \
202 *((volatile SYS_UWORD8 *) ((UART)->base_address + (REG)))
203
204 #define WRITE_UART_REGISTER(UART,REG,VALUE) \
205 *((volatile SYS_UWORD8 *) ((UART)->base_address + (REG))) = (VALUE)
206
207 #define RESET_BIT(UART,REG,BIT) \
208 (WRITE_UART_REGISTER ( \
209 UART, REG, READ_UART_REGISTER (UART, REG) & ~(1 << (BIT))))
210
211 #define SET_BIT(UART,REG,BIT) \
212 (WRITE_UART_REGISTER ( \
213 UART, REG, READ_UART_REGISTER (UART, REG) | (1 << (BIT))))
214
215 /*
216 * These macros allow to enable or disable the wake-up interrupt.
217 */
218
219 #define ENABLE_WAKEUP_INTERRUPT(UART) \
220 SET_BIT(UART, SCR, RX_CTS_WAKE_UP_ENABLE_BIT);
221
222 #define DISABLE_WAKEUP_INTERRUPT(UART) \
223 RESET_BIT(UART, SCR, RX_CTS_WAKE_UP_ENABLE_BIT);
224
225
226 /*
227 * This macro allows to know if the RX buffer is full. It must be called only
228 * from the RX interrupt handler. If it is called from the application, the
229 * rx_in pointer may be updated if a RX interrupt occurs.
230 */
231
232 #define RX_BUFFER_FULL(UART) \
233 (((UART)->rx_in == (UART)->rx_out - 1) || \
234 ((UART)->rx_in == (UART)->rx_out + BUFFER_SIZE - 1))
235
236
237 /*
238 * This allows monitor the last 32 inbound buffers gotten from the RX FIFO.
239 */
240
241 //#define UART_RX_BUFFER_DUMP
242
243 #ifdef UART_RX_BUFFER_DUMP
244 struct {
245 char rx_buffer[(BUFFER_SIZE + 1) << 5];
246 char *rx_in;
247 int errors_count;
248 int wrong_interrupt_status;
249 } uart_rx_buffer_dump = {0};
250 #endif
251
252
253 typedef struct s_uart {
254
255 SYS_UWORD32 base_address;
256
257 /*
258 * Buffers management.
259 */
260
261 char rx_buffer[BUFFER_SIZE + 1];
262 char *rx_in;
263 char *rx_out;
264 void (*callback_function) (void);
265
266 /*
267 * Errors counters.
268 */
269
270 SYS_UWORD32 framing_error;
271 SYS_UWORD32 parity_error;
272 SYS_UWORD32 overrun_error;
273
274 /*
275 * Framing flags.
276 */
277
278 SYS_BOOL dle_detected;
279 SYS_BOOL inframe;
280 SYS_BOOL encapsulation_flag;
281 unsigned char frame_length;
282
283 } t_uart;
284
285 static t_uart uart_parameter[NUMBER_OF_TR_UART];
286
287 static const SYS_UWORD32 base_address[NUMBER_OF_TR_UART] =
288 {
289 MEM_UART_IRDA,
290 MEM_UART_MODEM
291 #if (CHIPSET == 12)
292 , MEM_UART_MODEM2
293 #endif
294 };
295
296
297 /*
298 * DLL (LSB) and DLH (MSB) registers values using the 13 MHz clock.
299 */
300
301 static const SYS_UWORD8 dll[] =
302 {
303 2, /* 406250 baud. */
304 7, /* 115200 baud. */
305 14, /* 57600 baud. */
306 21, /* 38400 baud. */
307 24, /* 33900 baud. */
308 28, /* 28800 baud. */
309 42, /* 19200 baud. */
310 56, /* 14400 baud. */
311 84, /* 9600 baud. */
312 169, /* 4800 baud. */
313 83, /* 2400 baud. */
314 165, /* 1200 baud. */
315 74, /* 600 baud. */
316 148, /* 300 baud. */
317 40, /* 150 baud. */
318 81 /* 75 baud. */
319 };
320
321 static const SYS_UWORD8 dlh[] =
322 {
323 0, /* 406250 baud. */
324 0, /* 115200 baud. */
325 0, /* 57600 baud. */
326 0, /* 38400 baud. */
327 0, /* 33900 baud. */
328 0, /* 28800 baud. */
329 0, /* 19200 baud. */
330 0, /* 14400 baud. */
331 0, /* 9600 baud. */
332 0, /* 4800 baud. */
333 1, /* 2400 baud. */
334 2, /* 1200 baud. */
335 5, /* 600 baud. */
336 10, /* 300 baud. */
337 21, /* 150 baud. */
338 42 /* 75 baud. */
339 };
340
341
342 /*******************************************************************************
343 *
344 * read_rx_fifo
345 *
346 * Purpose : Check the bytes written into the RX FIFO. Characters are not
347 * written in the RX buffer if it is full. The HISR is called if
348 * enough characters are received.
349 *
350 * Arguments: In : uart: pointer on UART structure.
351 * Out: none
352 *
353 * Returns : none
354 *
355 ******************************************************************************/
356
357 static void
358 read_rx_fifo (t_uart *uart)
359 {
360 volatile SYS_UWORD8 status;
361 int error_detected;
362 SYS_UWORD8 char_received;
363
364 #if (BOARD != 34)
365 /*
366 * Since new characters have been received, the sleep timer is reset then
367 * restarted preventing the system to enter deep-sleep for a new period of
368 * time.
369 */
370
371 SER_activate_timer_hisr ();
372 uart_sleep_timer_enabled = 1;
373 #endif
374
375 status = READ_UART_REGISTER (uart, LSR);
376
377 while (status & DR) { /* While RX FIFO is not empty... */
378
379 error_detected = 0;
380
381 char_received = READ_UART_REGISTER (uart, RHR);
382
383 /*
384 * Check if an error (overrun, parity, framing or break) is associated with the
385 * received data. If there is an error the byte is not copied into the
386 * RX buffer.
387 */
388
389 if (status & (OE | PE | FE | BI)) {
390
391 if (status & PE)
392 uart->parity_error++;
393
394 if (status & FE)
395 uart->framing_error++;
396
397 if (status & OE)
398 uart->overrun_error++;
399
400 error_detected = 1;
401 }
402
403 /*
404 * If there is no error the byte is copied into the RX
405 * buffer if it is not full.
406 */
407
408 if (!error_detected && !RX_BUFFER_FULL (uart)) {
409
410 *(uart->rx_in++) = char_received;
411
412 if (uart->rx_in == &(uart->rx_buffer[0]) + BUFFER_SIZE + 1)
413 uart->rx_in = &(uart->rx_buffer[0]);
414
415 #ifdef UART_RX_BUFFER_DUMP
416 *(uart_rx_buffer_dump.rx_in)++ = char_received;
417
418 if (uart_rx_buffer_dump.rx_in == uart_rx_buffer_dump.rx_buffer + sizeof (uart_rx_buffer_dump.rx_buffer))
419 uart_rx_buffer_dump.rx_in = uart_rx_buffer_dump.rx_buffer;
420 }
421 else {
422 uart_rx_buffer_dump.errors_count++;
423 #endif
424 }
425
426 status = READ_UART_REGISTER (uart, LSR);
427 }
428
429 /*
430 * Call the user's function.
431 */
432
433 if (uart->callback_function != NULL)
434 (*(uart->callback_function)) ();
435 }
436
437 /*******************************************************************************
438 *
439 * initialize_uart_sleep
440 *
441 * Purpose : Performs basic UART hardware initialization including sleep mode.
442 *
443 * Arguments: In : uart_id : UART id.
444 * Out: none
445 *
446 * Returns: none
447 *
448 * Warning: Parameters are not verified.
449 *
450 ******************************************************************************/
451
452 void
453 initialize_uart_sleep (T_tr_UartId uart_id)
454 {
455 t_uart *uart;
456 int index;
457 SYS_UWORD8 dummy;
458
459 for (index = 0; index < NUMBER_OF_TR_UART; index++)
460 uart_parameter[index].base_address = base_address[index];
461
462 uart = &(uart_parameter[uart_id]);
463
464 /*
465 * Mask all interrupts causes and disable sleep mode.
466 */
467
468 WRITE_UART_REGISTER (uart, IER, 0x00);
469
470 /*
471 * Reset UART mode configuration.
472 */
473
474 WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE);
475
476 /*
477 * LCR[7:0] = 0xBF to allow to access EFR
478 * EFR[4] = 1 to allow to program IER[4].
479 */
480
481 WRITE_UART_REGISTER (uart, LCR, 0xBF);
482 SET_BIT (uart, EFR, ENHANCED_FEATURE_BIT);
483 WRITE_UART_REGISTER (uart, LCR, 0x83);
484
485 /*
486 * Enable FIFO and reset them.
487 */
488
489 WRITE_UART_REGISTER (uart, FCR, FIFO_ENABLE |
490 RX_FIFO_RESET |
491 TX_FIFO_RESET);
492
493 /*
494 * Program the baud generator (dummy 115200).
495 */
496
497 WRITE_UART_REGISTER (uart, DLL, 0x07);
498 WRITE_UART_REGISTER (uart, DLM, 0x00);
499
500 /*
501 * LCR[7] = 0 to allow to access IER and RHR - normal mode.
502 */
503
504 RESET_BIT (uart, LCR, DIV_EN_BIT);
505
506 /*
507 * Select UART mode.
508 */
509
510 WRITE_UART_REGISTER (uart, MDR1, UART_MODE);
511
512 /*
513 * Clear Interrupt and check that Rx FIFO is empty.
514 */
515
516 dummy = READ_UART_REGISTER (uart, IIR);
517
518 while (READ_UART_REGISTER (uart, LSR) & DR)
519 dummy = READ_UART_REGISTER (uart, RHR);
520
521 #if ((CHIPSET != 5) && (CHIPSET != 6))
522 /*
523 * Enable sleep mode.
524 */
525
526 WRITE_UART_REGISTER (uart, IER, IER_SLEEP);
527 #endif
528 }
529
530
531 /*******************************************************************************
532 *
533 * UA_Init
534 *
535 * Purpose : Initializes the module and the UART.
536 *
537 * Arguments: In : uart_id : UART id.
538 * baudrate: baud rate selected.
539 * callback: user's function called characters are received.
540 * Out: none
541 *
542 * Returns: none
543 *
544 * Warning: Parameters are not verified.
545 *
546 ******************************************************************************/
547
548 void
549 UA_Init (T_tr_UartId uart_id,
550 T_tr_Baudrate baudrate,
551 void (callback_function (void)))
552 {
553 t_uart *uart;
554 int index;
555
556 #ifdef UART_RX_BUFFER_DUMP
557 uart_rx_buffer_dump.rx_in = uart_rx_buffer_dump.rx_buffer;
558 #endif
559
560 for (index = 0; index < NUMBER_OF_TR_UART; index++)
561 uart_parameter[index].base_address = base_address[index];
562
563 uart = &(uart_parameter[uart_id]);
564
565 uart->rx_in = &(uart->rx_buffer[0]);
566 uart->rx_out = &(uart->rx_buffer[0]);
567
568 uart->callback_function = callback_function;
569
570 uart->framing_error = 0;
571 uart->parity_error = 0;
572 uart->overrun_error = 0;
573
574 uart->dle_detected = 0;
575 uart->inframe = 0;
576 uart->encapsulation_flag = 0;
577 uart->frame_length = 0;
578
579 /*
580 * Mask all interrupts causes and disable sleep mode.
581 */
582
583 WRITE_UART_REGISTER (uart, IER, 0x00);
584
585 /*
586 * Reset UART mode configuration.
587 */
588
589 WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE |
590 IR_SLEEP_DISABLED |
591 SIR_TX_WITHOUT_ACREG2 |
592 FRAME_LENGTH_METHOD);
593
594 /*
595 * FIFO configuration.
596 * EFR[4] = 1 to allow to program FCR[5:4] and MCR[7:5].
597 */
598
599 WRITE_UART_REGISTER (uart, LCR, 0xBF);
600 SET_BIT (uart, EFR, ENHANCED_FEATURE_BIT);
601
602 /*
603 * Select the word length, the number of stop bits , the parity and set
604 * LCR[7] (DLAB) to allow to program FCR, DLL and DLM.
605 */
606
607 WRITE_UART_REGISTER (uart, LCR, WLS_8 | DLAB);
608
609 /*
610 * Program the trigger levels.
611 * MCR[6] must be set to 1.
612 */
613
614 SET_BIT (uart, MCR, TCR_TLR_BIT);
615 WRITE_UART_REGISTER (uart, TCR, 0x0F);
616 WRITE_UART_REGISTER (
617 uart, TLR, RX_FIFO_TRIGGER_LEVEL);
618
619 /*
620 * Program the FIFO control register. Bit 0 must be set when other FCR bits
621 * are written to or they are not programmed.
622 * FCR is a write-only register. It will not be modified.
623 */
624
625 WRITE_UART_REGISTER (uart, FCR, FIFO_ENABLE |
626 RX_FIFO_RESET | /* self cleared */
627 TX_FIFO_RESET); /* self cleared */
628
629 /*
630 * Program the baud generator.
631 */
632
633 WRITE_UART_REGISTER (uart, DLL, dll[baudrate]);
634 WRITE_UART_REGISTER (uart, DLM, dlh[baudrate]);
635
636
637 /*
638 * Reset LCR[7] (DLAB) to have access to the RBR, THR and IER registers.
639 */
640
641 WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB);
642
643
644 /*
645 * Select UART mode.
646 */
647
648 WRITE_UART_REGISTER (uart, MDR1, UART_MODE |
649 IR_SLEEP_DISABLED |
650 SIR_TX_WITHOUT_ACREG2 |
651 FRAME_LENGTH_METHOD);
652
653 #if ((CHIPSET == 5) || (CHIPSET == 6))
654 /*
655 * Unmask RX interrupt
656 */
657
658 WRITE_UART_REGISTER (uart, IER, ERBI);
659 #else
660 /*
661 * Unmask RX interrupt and allow sleep mode.
662 */
663
664 WRITE_UART_REGISTER (uart, IER, ERBI | IER_SLEEP);
665 #endif
666 }
667
668 /*******************************************************************************
669 *
670 * UA_ReadNChars
671 *
672 * Purpose : Reads N characters from the RX buffer.
673 *
674 * Arguments: In : uart_id : UART id.
675 * buffer : buffer address where the characters are
676 * copied.
677 * chars_to_read: number of characters to read.
678 * Out: none
679 *
680 * Returns : The number of characters read.
681 *
682 * Warning: Parameters are not verified.
683 *
684 ******************************************************************************/
685
686 SYS_UWORD32
687 UA_ReadNChars (T_tr_UartId uart_id,
688 char *buffer,
689 SYS_UWORD32 chars_to_read)
690 {
691 SYS_UWORD32 chars_in_rx_buffer;
692 SYS_UWORD32 chars_to_copy;
693 SYS_UWORD32 chars_written;
694 char *rx_in;
695 t_uart *uart;
696
697 uart = &(uart_parameter[uart_id]);
698
699 /*
700 * A copy of the rx_in pointer is used because it may be updated by
701 * the interrupt handler.
702 * Get the number of bytes available in the RX buffer.
703 */
704
705 rx_in = uart->rx_in;
706
707 if (uart->rx_out <= rx_in)
708 chars_in_rx_buffer = (SYS_UWORD32) (rx_in - uart->rx_out);
709 else
710 chars_in_rx_buffer = (SYS_UWORD32) (rx_in - uart->rx_out + BUFFER_SIZE + 1);
711
712 /*
713 * No more bytes than those received may be written in the output buffer.
714 */
715
716 if (chars_in_rx_buffer >= chars_to_read)
717 chars_to_copy = chars_to_read;
718 else
719 chars_to_copy = chars_in_rx_buffer;
720
721 chars_written = chars_to_copy;
722
723 /*
724 * Write the received bytes in the output buffer.
725 */
726
727 while (chars_to_copy) {
728
729 *(buffer++) = *(uart->rx_out++);
730 chars_to_copy--;
731
732 if (uart->rx_out == &(uart->rx_buffer[0]) + BUFFER_SIZE + 1)
733 uart->rx_out = &(uart->rx_buffer[0]);
734 }
735
736 return (chars_written);
737 }
738
739 /*******************************************************************************
740 *
741 * UA_ReadNBytes
742 *
743 * Purpose : Reads and destuff N bytes from the RX buffer.
744 *
745 * Arguments: In : uart_id : UART id.
746 * buffer : buffer address where the bytes are copied.
747 * chars_to_read: number of bytes to read.
748 * Out: eof_detected : indicates if an EOF has been detected. Possible
749 * values are:
750 * - 0: EOF not detected,
751 * - 1: EOF detected and no more bytes left,
752 * - 2: EOF not detected and more bytes left.
753 * Users must invoke this function one more
754 * time in order to get those remaining
755 * bytes,
756 * - 3: EOF detected and more bytes left. Users
757 * must invoke this function one more time
758 * in order to get those remaining bytes.
759 *
760 * Returns : The number of bytes read.
761 *
762 * Warning: Parameters are not verified.
763 *
764 ******************************************************************************/
765
766 SYS_UWORD32
767 UA_ReadNBytes (T_tr_UartId uart_id,
768 char *buffer_p,
769 SYS_UWORD32 bytes_to_read,
770 SYS_BOOL *eof_detected_p)
771 {
772 SYS_UWORD32 bytes_written;
773 SYS_UWORD32 bytes_in_rx_buffer;
774 SYS_UWORD32 bytes_to_process;
775 t_uart *uart_p;
776 char *rx_in_p;
777
778 bytes_written = 0;
779 uart_p = &(uart_parameter[uart_id]);
780
781 /*
782 * A copy of the rx_in pointer is used because it may be updated by
783 * the interrupt handler.
784 * Get the number of bytes available in the RX buffer.
785 */
786
787 rx_in_p = uart_p->rx_in;
788
789 if (uart_p->rx_out <= rx_in_p)
790 bytes_in_rx_buffer = (SYS_UWORD32) (rx_in_p - uart_p->rx_out);
791 else
792 bytes_in_rx_buffer = (SYS_UWORD32) (rx_in_p - uart_p->rx_out + BUFFER_SIZE + 1);
793
794 /*
795 * No more bytes than those received may be processed and then written
796 * in the output buffer.
797 */
798
799 if (bytes_in_rx_buffer > bytes_to_read) {
800 bytes_to_process = bytes_to_read;
801
802 /*
803 * More bytes left. Users must invoke this function one more time
804 * in order to get those remaining bytes.
805 */
806
807 *eof_detected_p = 2;
808 }
809 else {
810 bytes_to_process = bytes_in_rx_buffer;
811
812 /*
813 * No more bytes left.
814 */
815
816 *eof_detected_p = 0;
817 }
818
819 /*
820 * Perform the byte destuffing and then write the "valid" received bytes in
821 * the output buffer.
822 */
823
824 while ((bytes_to_process) && !(*eof_detected_p & 0x01)) {
825
826 switch (*(uart_p->rx_out)) {
827
828 /*
829 * Current byte is DLE.
830 */
831
832 case DLE:
833
834 if (!uart_p->dle_detected) {
835
836 /*
837 * No DLE previously detected =>
838 * Skip the current byte and set the flag.
839 */
840
841 uart_p->dle_detected = 1;
842 uart_p->rx_out++;
843 }
844
845 else { /* if (uart_p->dle_detected) */
846
847 if (uart_p->inframe) {
848
849 /*
850 * DLE previously detected AND currently inside of a frame =>
851 * Copy the current byte in the output buffer, reset the flag
852 * and increase the frame length.
853 */
854
855 uart_p->dle_detected = 0;
856 uart_p->frame_length++;
857 *(buffer_p++) = *(uart_p->rx_out++);
858 bytes_written++;
859 }
860
861 else { /* if (!uart_p->inframe) */
862
863 /*
864 * DLE previously detected AND currently outside of a frame =>
865 * Skip the current byte.
866 */
867
868 uart_p->rx_out++;
869 }
870 }
871
872 break; /* case DLE */
873
874 /*
875 * Current byte is STX.
876 */
877
878 case STX:
879
880 if ((!uart_p->dle_detected) && (uart_p->inframe)) {
881
882 /*
883 * No DLE previously detected AND currently inside of a frame.
884 */
885
886 if (uart_p->frame_length) {
887
888 /*
889 * Frame length is not zero (End of Frame) =>
890 * Skip the current byte and set the flags (EOF).
891 */
892
893 uart_p->inframe = 0;
894 uart_p->frame_length = 0;
895 uart_p->rx_out++;
896
897 /*
898 * More bytes left.
899 */
900
901 if ((*eof_detected_p == 0) && (bytes_to_process))
902 *eof_detected_p = 2;
903
904 /*
905 * EOF detected.
906 */
907
908 (*eof_detected_p)++;
909 }
910
911 else { /* if (!uart_p->frame_length) */
912
913 /*
914 * Frame length is zero (STX followed by another STX =
915 * Synchro lost but start of a new frame) =>
916 * Skip the current byte and keep the flag set.
917 */
918
919 uart_p->rx_out++;
920 }
921 }
922
923 else if ((!uart_p->dle_detected) && (!uart_p->inframe)) {
924
925 /*
926 * No DLE previously detected AND currently outside of a
927 * frame (Start of Frame) =>
928 * Skip the current byte and set the flag.
929 */
930
931 uart_p->inframe = 1;
932 uart_p->rx_out++;
933 }
934
935 else if ((uart_p->dle_detected) && (uart_p->inframe)) {
936
937 /*
938 * DLE previously detected AND currently inside of a frame =>
939 * Copy the current byte in the output buffer, reset the flag
940 * and increase the frame length.
941 */
942
943 uart_p->dle_detected = 0;
944 uart_p->frame_length++;
945 *(buffer_p++) = *(uart_p->rx_out++);
946 bytes_written++;
947 }
948
949 else if ((uart_p->dle_detected) && (!uart_p->inframe)) {
950
951 /*
952 * DLE previously detected AND currently outside of a frame =>
953 * Skip the current byte and reset the flag.
954 */
955
956 uart_p->dle_detected = 0;
957 uart_p->rx_out++;
958 }
959
960 break; /* case STX */
961
962 /*
963 * Current byte is neither DLE nor STX.
964 */
965
966 default:
967
968 if (uart_p->inframe) {
969
970 /*
971 * Currently inside of a frame =>
972 * Copy the current byte in the output buffer and increase
973 * the frame length.
974 */
975
976 uart_p->frame_length++;
977 *(buffer_p++) = *(uart_p->rx_out++);
978 bytes_written++;
979 }
980
981 else { /* if (!uart_p->inframe) */
982
983 /*
984 * Currently outside of a frame =>
985 * Skip the current byte.
986 */
987
988 uart_p->rx_out++;
989 }
990
991 break; /* default */
992 }
993
994 if (uart_p->rx_out == &(uart_p->rx_buffer[0]) + BUFFER_SIZE + 1)
995 uart_p->rx_out = &(uart_p->rx_buffer[0]);
996
997 bytes_to_process--;
998 }
999
1000 return (bytes_written);
1001 }
1002
1003
1004 /*******************************************************************************
1005 *
1006 * UA_WriteNChars
1007 *
1008 * Purpose : Writes N characters in the TX FIFO.
1009 *
1010 * Arguments: In : uart_id : UART id.
1011 * buffer : buffer address from which characters are
1012 * written.
1013 * bytes_to_write: number of bytes to write.
1014 * Out: none
1015 *
1016 * Returns : Number of bytes written.
1017 *
1018 * Warning: Parameters are not verified.
1019 *
1020 ******************************************************************************/
1021
1022 SYS_UWORD32
1023 UA_WriteNChars (T_tr_UartId uart_id,
1024 char *buffer,
1025 SYS_UWORD32 chars_to_write)
1026 {
1027 SYS_UWORD32 chars_in_tx_fifo;
1028 SYS_UWORD32 chars_written;
1029 t_uart *uart;
1030
1031 chars_written = 0;
1032 uart = &(uart_parameter[uart_id]);
1033
1034 #if ((CHIPSET != 5) && (CHIPSET != 6))
1035 /*
1036 * Disable sleep mode.
1037 */
1038
1039 WRITE_UART_REGISTER (
1040 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
1041 #endif
1042
1043 /*
1044 * Copy the input buffer to the TX FIFO.
1045 * Ulyssse Bug #44: TX FIFO full status bit (SSR[1]) is corrupted during
1046 * one period of Bclock => Workaround S/W.
1047 * Write in TX FIFO only if FIFO is empty instead of writing in TX FIFO
1048 * while FIFO is not full.
1049 */
1050
1051 if (READ_UART_REGISTER (uart, LSR) & THRE) {
1052
1053 chars_in_tx_fifo = 0;
1054
1055 while ((chars_written < chars_to_write) &&
1056 (chars_in_tx_fifo < FIFO_SIZE)) {
1057
1058 WRITE_UART_REGISTER (uart, THR, *(buffer++));
1059 chars_written++;
1060 chars_in_tx_fifo++;
1061 }
1062 }
1063
1064 #if ((CHIPSET != 5) && (CHIPSET != 6))
1065 /*
1066 * Re-enable sleep mode.
1067 */
1068
1069 WRITE_UART_REGISTER (
1070 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
1071 #endif
1072
1073 return (chars_written);
1074 }
1075
1076
1077 /*******************************************************************************
1078 *
1079 * UA_EncapsulateNChars
1080 *
1081 * Purpose : Writes N characters in the TX FIFO in encapsulating them with 2
1082 * STX bytes (one at the beginning and one at the end).
1083 *
1084 * Arguments: In : uart_id : UART id.
1085 * buffer : buffer address from which characters are
1086 * written.
1087 * chars_to_write: number of chars to write.
1088 * Out: none
1089 *
1090 * Returns : Number of chars written.
1091 *
1092 * Warning: Parameters are not verified.
1093 *
1094 ******************************************************************************/
1095
1096 SYS_UWORD32
1097 UA_EncapsulateNChars (T_tr_UartId uart_id,
1098 char *buffer,
1099 SYS_UWORD32 chars_to_write)
1100 {
1101 SYS_UWORD32 chars_written;
1102 SYS_UWORD32 chars_in_tx_fifo;
1103 t_uart *uart;
1104
1105 chars_written = 0;
1106 uart = &(uart_parameter[uart_id]);
1107
1108 #if ((CHIPSET != 5) && (CHIPSET != 6))
1109 /*
1110 * Disable sleep mode.
1111 */
1112
1113 WRITE_UART_REGISTER (
1114 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
1115 #endif
1116
1117 /*
1118 * Copy the input buffer to the TX FIFO.
1119 * Ulyssse Bug #44: TX FIFO full status bit (SSR[1]) is corrupted during
1120 * one period of Bclock => Workaround S/W.
1121 * Write in TX FIFO only if FIFO is empty instead of writing in TX FIFO
1122 * while FIFO is not full.
1123 */
1124
1125 if (READ_UART_REGISTER (uart, LSR) & THRE) {
1126
1127 chars_in_tx_fifo = 0;
1128
1129 /*
1130 * Check if the message has been already encapsulated.
1131 */
1132
1133 if (!uart->encapsulation_flag) {
1134 /*
1135 * Write STX in the TX FIFO and set the flag.
1136 */
1137
1138 WRITE_UART_REGISTER (uart, THR, STX);
1139 chars_in_tx_fifo++;
1140 uart->encapsulation_flag = 1;
1141 }
1142
1143 /*
1144 * Keep one char margin in the TX FIFO for the last STX.
1145 */
1146
1147 while ((chars_written < chars_to_write) &&
1148 (chars_in_tx_fifo < (FIFO_SIZE-1))) {
1149
1150 WRITE_UART_REGISTER (uart, THR, *(buffer++));
1151 chars_written++;
1152 chars_in_tx_fifo++;
1153 }
1154
1155 /*
1156 * Append STX byte at the end if the frame is complete.
1157 */
1158
1159 if (chars_written == chars_to_write) {
1160
1161 /*
1162 * Write STX in the TX FIFO and reset the flag.
1163 */
1164
1165 WRITE_UART_REGISTER (uart, THR, STX);
1166 uart->encapsulation_flag = 0;
1167 }
1168 }
1169
1170 #if ((CHIPSET != 5) && (CHIPSET != 6))
1171 /*
1172 * Re-enable sleep mode.
1173 */
1174
1175 WRITE_UART_REGISTER (
1176 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
1177 #endif
1178
1179 return (chars_written);
1180 }
1181
1182
1183 /*******************************************************************************
1184 *
1185 * UA_WriteNBytes
1186 *
1187 * Purpose : Writes N bytes in the TX FIFO in encapsulating with 2 STX bytes
1188 * at the beginning and the end of the frame, and in making byte
1189 * stuffing.
1190 *
1191 * Arguments: In : uart_id : UART id.
1192 * buffer : buffer address from which bytes are
1193 * written.
1194 * bytes_to_write: number of bytes to write.
1195 * Out: none
1196 *
1197 * Returns : Number of bytes written.
1198 *
1199 * Warning: Parameters are not verified.
1200 *
1201 ******************************************************************************/
1202
1203 SYS_UWORD32
1204 UA_WriteNBytes (T_tr_UartId uart_id,
1205 SYS_UWORD8 *buffer,
1206 SYS_UWORD32 bytes_to_write)
1207 {
1208 SYS_UWORD32 bytes_written;
1209 SYS_UWORD32 bytes_in_tx_fifo;
1210 t_uart *uart;
1211
1212 bytes_written = 0;
1213 uart = &(uart_parameter[uart_id]);
1214
1215 #if ((CHIPSET != 5) && (CHIPSET != 6))
1216 /*
1217 * Disable sleep mode.
1218 */
1219
1220 WRITE_UART_REGISTER (
1221 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
1222 #endif
1223
1224 /*
1225 * Copy the input buffer to the TX FIFO.
1226 * Ulyssse Bug #44: TX FIFO full status bit (SSR[1]) is corrupted during
1227 * one period of Bclock => Workaround S/W.
1228 * Write in TX FIFO only if FIFO is empty instead of writing in TX FIFO
1229 * while FIFO is not full.
1230 */
1231
1232 if (READ_UART_REGISTER (uart, LSR) & THRE) {
1233
1234 bytes_in_tx_fifo = 0;
1235
1236 /*
1237 * Check if the message has been already encapsulated.
1238 */
1239
1240 if (!uart->encapsulation_flag) {
1241
1242 /*
1243 * Write STX in the TX FIFO and set the flag.
1244 */
1245
1246 WRITE_UART_REGISTER (uart, THR, STX);
1247 bytes_in_tx_fifo++;
1248 uart->encapsulation_flag = 1;
1249 }
1250
1251 /*
1252 * Keep 2 chars margin in the FIFO, one for the stuffing (if necessary)
1253 * and one for the last STX.
1254 */
1255
1256 while ((bytes_written < bytes_to_write) &&
1257 (bytes_in_tx_fifo < (FIFO_SIZE-2))) {
1258
1259 /*
1260 * Check for STX or DLE in order to perform the stuffing.
1261 */
1262
1263 if ((*(buffer) == STX) || (*(buffer) == DLE)) {
1264
1265 /*
1266 * Write DLE in the TX FIFO.
1267 */
1268
1269 WRITE_UART_REGISTER (uart, THR, DLE);
1270 bytes_in_tx_fifo++;
1271 }
1272
1273 WRITE_UART_REGISTER (uart, THR, *(buffer++));
1274 bytes_written++;
1275 bytes_in_tx_fifo++;
1276 }
1277
1278 /*
1279 * Append STX byte at the end if the frame is complete.
1280 */
1281
1282 if (bytes_written == bytes_to_write) {
1283
1284 /*
1285 * Write STX in the TX FIFO and reset the flag.
1286 */
1287
1288 WRITE_UART_REGISTER (uart, THR, STX);
1289 uart->encapsulation_flag = 0;
1290 }
1291 }
1292
1293 #if ((CHIPSET != 5) && (CHIPSET != 6))
1294 /*
1295 * Re-enable sleep mode.
1296 */
1297
1298 WRITE_UART_REGISTER (
1299 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
1300 #endif
1301
1302 return (bytes_written);
1303 }
1304
1305
1306 /*******************************************************************************
1307 *
1308 * UA_WriteChar
1309 *
1310 * Purpose : Writes a character in the TX FIFO.
1311 *
1312 * Arguments: In : uart: UART id.
1313 * character
1314 * Out: none
1315 *
1316 * Returns : none
1317 *
1318 * Warning: Parameters are not verified.
1319 *
1320 ******************************************************************************/
1321
1322 void
1323 UA_WriteChar (T_tr_UartId uart_id,
1324 char character)
1325 {
1326 (void) UA_WriteNChars (uart_id, &character, 1);
1327 }
1328
1329 /*******************************************************************************
1330 *
1331 * UA_WriteString
1332 *
1333 * Purpose : Writes a null terminated string in the TX FIFO.
1334 *
1335 * Arguments: In : uart_id: UART id.
1336 * buffer : buffer address from which characters are written.
1337 * Out: none
1338 *
1339 * Returns : none
1340 *
1341 * Warning: Parameters are not verified.
1342 *
1343 ******************************************************************************/
1344
1345 void
1346 UA_WriteString (T_tr_UartId uart_id,
1347 char *buffer)
1348 {
1349 (void) UA_WriteNChars (uart_id, buffer, strlen (buffer));
1350 }
1351
1352 /*******************************************************************************
1353 *
1354 * UA_EnterSleep
1355 *
1356 * Purpose : Checks if UART is ready to enter Deep Sleep. If ready, enables
1357 * wake-up interrupt.
1358 *
1359 * Arguments: In : uart_id : UART id.
1360 * Out: none
1361 *
1362 * Returns: 0 : Deep Sleep is not possible.
1363 * >= 1 : Deep Sleep is possible.
1364 *
1365 * Warning: Parameters are not verified.
1366 *
1367 ******************************************************************************/
1368
1369 SYS_BOOL
1370 UA_EnterSleep (T_tr_UartId uart_id)
1371 {
1372 t_uart *uart;
1373 SYS_BOOL deep_sleep;
1374 volatile SYS_UWORD8 status;
1375
1376 uart = &(uart_parameter[uart_id]);
1377 deep_sleep = 0;
1378
1379 /*
1380 * Check if RX & TX FIFOs are both empty
1381 */
1382
1383 status = READ_UART_REGISTER (uart, LSR);
1384
1385 if (!(status & DR) &&
1386 (status & TEMT)) {
1387
1388 #if ((CHIPSET != 5) && (CHIPSET != 6))
1389 /*
1390 * Disable sleep mode.
1391 */
1392
1393 WRITE_UART_REGISTER (
1394 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
1395 #endif
1396
1397 /*
1398 * Mask RX interrupt.
1399 */
1400
1401 WRITE_UART_REGISTER (
1402 uart, IER, READ_UART_REGISTER (uart, IER) & ~ERBI);
1403
1404 /*
1405 * Enable the wake-up interrupt.
1406 */
1407
1408 ENABLE_WAKEUP_INTERRUPT (uart);
1409
1410 deep_sleep = 1;
1411 }
1412
1413 return (deep_sleep);
1414 }
1415
1416 /*******************************************************************************
1417 *
1418 * UA_WakeUp
1419 *
1420 * Purpose : Wakes up UART after Deep Sleep.
1421 *
1422 * Arguments: In : uart_id : UART id.
1423 * Out: none
1424 *
1425 * Returns: none
1426 *
1427 * Warning: Parameters are not verified.
1428 *
1429 ******************************************************************************/
1430
1431 void
1432 UA_WakeUp (T_tr_UartId uart_id)
1433 {
1434 t_uart *uart;
1435
1436 uart = &(uart_parameter[uart_id]);
1437
1438 /*
1439 * Disable the wake-up interrupt.
1440 */
1441
1442 DISABLE_WAKEUP_INTERRUPT (uart);
1443
1444 /*
1445 * Unmask RX interrupts.
1446 */
1447
1448 WRITE_UART_REGISTER (
1449 uart, IER, READ_UART_REGISTER (uart, IER) | ERBI);
1450
1451 #if ((CHIPSET != 5) && (CHIPSET != 6))
1452 /*
1453 * Allow sleep mode.
1454 */
1455
1456 WRITE_UART_REGISTER (
1457 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
1458 #endif
1459 }
1460
1461 /*******************************************************************************
1462 *
1463 * UA_InterruptHandler
1464 *
1465 * Purpose : Interrupt handler.
1466 *
1467 * Arguments: In : uart_id : origin of interrupt
1468 * interrupt_status: source of interrupt
1469 * Out: none
1470 *
1471 * Returns : none
1472 *
1473 ******************************************************************************/
1474
1475 void
1476 UA_InterruptHandler (T_tr_UartId uart_id,
1477 SYS_UWORD8 interrupt_status)
1478 {
1479 t_uart *uart;
1480
1481 uart = &(uart_parameter[uart_id]);
1482
1483 switch (interrupt_status) {
1484
1485 case RX_DATA:
1486
1487 read_rx_fifo (uart);
1488
1489 break;
1490
1491 default:
1492
1493 #ifdef UART_RX_BUFFER_DUMP
1494 uart_rx_buffer_dump.wrong_interrupt_status++;
1495 #endif
1496
1497 /* No Processing */
1498
1499 break;
1500 }
1501 }