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

src/cs: initial import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 04:39:26 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:b6a5e36de839
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 1 /* 812500 baud. */
320 };
321
322 static const SYS_UWORD8 dlh[] =
323 {
324 0, /* 406250 baud. */
325 0, /* 115200 baud. */
326 0, /* 57600 baud. */
327 0, /* 38400 baud. */
328 0, /* 33900 baud. */
329 0, /* 28800 baud. */
330 0, /* 19200 baud. */
331 0, /* 14400 baud. */
332 0, /* 9600 baud. */
333 0, /* 4800 baud. */
334 1, /* 2400 baud. */
335 2, /* 1200 baud. */
336 5, /* 600 baud. */
337 10, /* 300 baud. */
338 21, /* 150 baud. */
339 42, /* 75 baud. */
340 0 /* 812500 baud. */
341 };
342
343
344 /*******************************************************************************
345 *
346 * read_rx_fifo
347 *
348 * Purpose : Check the bytes written into the RX FIFO. Characters are not
349 * written in the RX buffer if it is full. The HISR is called if
350 * enough characters are received.
351 *
352 * Arguments: In : uart: pointer on UART structure.
353 * Out: none
354 *
355 * Returns : none
356 *
357 ******************************************************************************/
358
359 static void
360 read_rx_fifo (t_uart *uart)
361 {
362 volatile SYS_UWORD8 status;
363 int error_detected;
364 SYS_UWORD8 char_received;
365
366 #if (BOARD != 34)
367 /*
368 * Since new characters have been received, the sleep timer is reset then
369 * restarted preventing the system to enter deep-sleep for a new period of
370 * time.
371 */
372
373 SER_activate_timer_hisr ();
374 uart_sleep_timer_enabled = 1;
375 #endif
376
377 status = READ_UART_REGISTER (uart, LSR);
378
379 while (status & DR) { /* While RX FIFO is not empty... */
380
381 error_detected = 0;
382
383 char_received = READ_UART_REGISTER (uart, RHR);
384
385 /*
386 * Check if an error (overrun, parity, framing or break) is associated with the
387 * received data. If there is an error the byte is not copied into the
388 * RX buffer.
389 */
390
391 if (status & (OE | PE | FE | BI)) {
392
393 if (status & PE)
394 uart->parity_error++;
395
396 if (status & FE)
397 uart->framing_error++;
398
399 if (status & OE)
400 uart->overrun_error++;
401
402 error_detected = 1;
403 }
404
405 /*
406 * If there is no error the byte is copied into the RX
407 * buffer if it is not full.
408 */
409
410 if (!error_detected && !RX_BUFFER_FULL (uart)) {
411
412 *(uart->rx_in++) = char_received;
413
414 if (uart->rx_in == &(uart->rx_buffer[0]) + BUFFER_SIZE + 1)
415 uart->rx_in = &(uart->rx_buffer[0]);
416
417 #ifdef UART_RX_BUFFER_DUMP
418 *(uart_rx_buffer_dump.rx_in)++ = char_received;
419
420 if (uart_rx_buffer_dump.rx_in == uart_rx_buffer_dump.rx_buffer + sizeof (uart_rx_buffer_dump.rx_buffer))
421 uart_rx_buffer_dump.rx_in = uart_rx_buffer_dump.rx_buffer;
422 }
423 else {
424 uart_rx_buffer_dump.errors_count++;
425 #endif
426 }
427
428 status = READ_UART_REGISTER (uart, LSR);
429 }
430
431 /*
432 * Call the user's function.
433 */
434
435 if (uart->callback_function != NULL)
436 (*(uart->callback_function)) ();
437 }
438
439 /*******************************************************************************
440 *
441 * initialize_uart_sleep
442 *
443 * Purpose : Performs basic UART hardware initialization including sleep mode.
444 *
445 * Arguments: In : uart_id : UART id.
446 * Out: none
447 *
448 * Returns: none
449 *
450 * Warning: Parameters are not verified.
451 *
452 ******************************************************************************/
453
454 void
455 initialize_uart_sleep (T_tr_UartId uart_id)
456 {
457 t_uart *uart;
458 int index;
459 SYS_UWORD8 dummy;
460
461 for (index = 0; index < NUMBER_OF_TR_UART; index++)
462 uart_parameter[index].base_address = base_address[index];
463
464 uart = &(uart_parameter[uart_id]);
465
466 /*
467 * Mask all interrupts causes and disable sleep mode.
468 */
469
470 WRITE_UART_REGISTER (uart, IER, 0x00);
471
472 /*
473 * Reset UART mode configuration.
474 */
475
476 WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE);
477
478 /*
479 * LCR[7:0] = 0xBF to allow to access EFR
480 * EFR[4] = 1 to allow to program IER[4].
481 */
482
483 WRITE_UART_REGISTER (uart, LCR, 0xBF);
484 SET_BIT (uart, EFR, ENHANCED_FEATURE_BIT);
485 WRITE_UART_REGISTER (uart, LCR, 0x83);
486
487 /*
488 * Enable FIFO and reset them.
489 */
490
491 WRITE_UART_REGISTER (uart, FCR, FIFO_ENABLE |
492 RX_FIFO_RESET |
493 TX_FIFO_RESET);
494
495 /*
496 * Program the baud generator (dummy 115200).
497 */
498
499 WRITE_UART_REGISTER (uart, DLL, 0x07);
500 WRITE_UART_REGISTER (uart, DLM, 0x00);
501
502 /*
503 * LCR[7] = 0 to allow to access IER and RHR - normal mode.
504 */
505
506 RESET_BIT (uart, LCR, DIV_EN_BIT);
507
508 /*
509 * Select UART mode.
510 */
511
512 WRITE_UART_REGISTER (uart, MDR1, UART_MODE);
513
514 /*
515 * Clear Interrupt and check that Rx FIFO is empty.
516 */
517
518 dummy = READ_UART_REGISTER (uart, IIR);
519
520 while (READ_UART_REGISTER (uart, LSR) & DR)
521 dummy = READ_UART_REGISTER (uart, RHR);
522
523 #if ((CHIPSET != 5) && (CHIPSET != 6))
524 /*
525 * Enable sleep mode.
526 */
527
528 WRITE_UART_REGISTER (uart, IER, IER_SLEEP);
529 #endif
530 }
531
532
533 /*******************************************************************************
534 *
535 * UA_Init
536 *
537 * Purpose : Initializes the module and the UART.
538 *
539 * Arguments: In : uart_id : UART id.
540 * baudrate: baud rate selected.
541 * callback: user's function called characters are received.
542 * Out: none
543 *
544 * Returns: none
545 *
546 * Warning: Parameters are not verified.
547 *
548 ******************************************************************************/
549
550 void
551 UA_Init (T_tr_UartId uart_id,
552 T_tr_Baudrate baudrate,
553 void (callback_function (void)))
554 {
555 t_uart *uart;
556 int index;
557
558 #ifdef UART_RX_BUFFER_DUMP
559 uart_rx_buffer_dump.rx_in = uart_rx_buffer_dump.rx_buffer;
560 #endif
561
562 for (index = 0; index < NUMBER_OF_TR_UART; index++)
563 uart_parameter[index].base_address = base_address[index];
564
565 uart = &(uart_parameter[uart_id]);
566
567 uart->rx_in = &(uart->rx_buffer[0]);
568 uart->rx_out = &(uart->rx_buffer[0]);
569
570 uart->callback_function = callback_function;
571
572 uart->framing_error = 0;
573 uart->parity_error = 0;
574 uart->overrun_error = 0;
575
576 uart->dle_detected = 0;
577 uart->inframe = 0;
578 uart->encapsulation_flag = 0;
579 uart->frame_length = 0;
580
581 /*
582 * Mask all interrupts causes and disable sleep mode.
583 */
584
585 WRITE_UART_REGISTER (uart, IER, 0x00);
586
587 /*
588 * Reset UART mode configuration.
589 */
590
591 WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE |
592 IR_SLEEP_DISABLED |
593 SIR_TX_WITHOUT_ACREG2 |
594 FRAME_LENGTH_METHOD);
595
596 /*
597 * FIFO configuration.
598 * EFR[4] = 1 to allow to program FCR[5:4] and MCR[7:5].
599 */
600
601 WRITE_UART_REGISTER (uart, LCR, 0xBF);
602 SET_BIT (uart, EFR, ENHANCED_FEATURE_BIT);
603
604 /*
605 * Select the word length, the number of stop bits , the parity and set
606 * LCR[7] (DLAB) to allow to program FCR, DLL and DLM.
607 */
608
609 WRITE_UART_REGISTER (uart, LCR, WLS_8 | DLAB);
610
611 /*
612 * Program the trigger levels.
613 * MCR[6] must be set to 1.
614 */
615
616 SET_BIT (uart, MCR, TCR_TLR_BIT);
617 WRITE_UART_REGISTER (uart, TCR, 0x0F);
618 WRITE_UART_REGISTER (
619 uart, TLR, RX_FIFO_TRIGGER_LEVEL);
620
621 /*
622 * Program the FIFO control register. Bit 0 must be set when other FCR bits
623 * are written to or they are not programmed.
624 * FCR is a write-only register. It will not be modified.
625 */
626
627 WRITE_UART_REGISTER (uart, FCR, FIFO_ENABLE |
628 RX_FIFO_RESET | /* self cleared */
629 TX_FIFO_RESET); /* self cleared */
630
631 /*
632 * Program the baud generator.
633 */
634
635 WRITE_UART_REGISTER (uart, DLL, dll[baudrate]);
636 WRITE_UART_REGISTER (uart, DLM, dlh[baudrate]);
637
638
639 /*
640 * Reset LCR[7] (DLAB) to have access to the RBR, THR and IER registers.
641 */
642
643 WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB);
644
645
646 /*
647 * Select UART mode.
648 */
649
650 WRITE_UART_REGISTER (uart, MDR1, UART_MODE |
651 IR_SLEEP_DISABLED |
652 SIR_TX_WITHOUT_ACREG2 |
653 FRAME_LENGTH_METHOD);
654
655 #if ((CHIPSET == 5) || (CHIPSET == 6))
656 /*
657 * Unmask RX interrupt
658 */
659
660 WRITE_UART_REGISTER (uart, IER, ERBI);
661 #else
662 /*
663 * Unmask RX interrupt and allow sleep mode.
664 */
665
666 WRITE_UART_REGISTER (uart, IER, ERBI | IER_SLEEP);
667 #endif
668 }
669
670 /*******************************************************************************
671 *
672 * UA_ReadNChars
673 *
674 * Purpose : Reads N characters from the RX buffer.
675 *
676 * Arguments: In : uart_id : UART id.
677 * buffer : buffer address where the characters are
678 * copied.
679 * chars_to_read: number of characters to read.
680 * Out: none
681 *
682 * Returns : The number of characters read.
683 *
684 * Warning: Parameters are not verified.
685 *
686 ******************************************************************************/
687
688 SYS_UWORD32
689 UA_ReadNChars (T_tr_UartId uart_id,
690 char *buffer,
691 SYS_UWORD32 chars_to_read)
692 {
693 SYS_UWORD32 chars_in_rx_buffer;
694 SYS_UWORD32 chars_to_copy;
695 SYS_UWORD32 chars_written;
696 char *rx_in;
697 t_uart *uart;
698
699 uart = &(uart_parameter[uart_id]);
700
701 /*
702 * A copy of the rx_in pointer is used because it may be updated by
703 * the interrupt handler.
704 * Get the number of bytes available in the RX buffer.
705 */
706
707 rx_in = uart->rx_in;
708
709 if (uart->rx_out <= rx_in)
710 chars_in_rx_buffer = (SYS_UWORD32) (rx_in - uart->rx_out);
711 else
712 chars_in_rx_buffer = (SYS_UWORD32) (rx_in - uart->rx_out + BUFFER_SIZE + 1);
713
714 /*
715 * No more bytes than those received may be written in the output buffer.
716 */
717
718 if (chars_in_rx_buffer >= chars_to_read)
719 chars_to_copy = chars_to_read;
720 else
721 chars_to_copy = chars_in_rx_buffer;
722
723 chars_written = chars_to_copy;
724
725 /*
726 * Write the received bytes in the output buffer.
727 */
728
729 while (chars_to_copy) {
730
731 *(buffer++) = *(uart->rx_out++);
732 chars_to_copy--;
733
734 if (uart->rx_out == &(uart->rx_buffer[0]) + BUFFER_SIZE + 1)
735 uart->rx_out = &(uart->rx_buffer[0]);
736 }
737
738 return (chars_written);
739 }
740
741 /*******************************************************************************
742 *
743 * UA_ReadNBytes
744 *
745 * Purpose : Reads and destuff N bytes from the RX buffer.
746 *
747 * Arguments: In : uart_id : UART id.
748 * buffer : buffer address where the bytes are copied.
749 * chars_to_read: number of bytes to read.
750 * Out: eof_detected : indicates if an EOF has been detected. Possible
751 * values are:
752 * - 0: EOF not detected,
753 * - 1: EOF detected and no more bytes left,
754 * - 2: EOF not detected and more bytes left.
755 * Users must invoke this function one more
756 * time in order to get those remaining
757 * bytes,
758 * - 3: EOF detected and more bytes left. Users
759 * must invoke this function one more time
760 * in order to get those remaining bytes.
761 *
762 * Returns : The number of bytes read.
763 *
764 * Warning: Parameters are not verified.
765 *
766 ******************************************************************************/
767
768 SYS_UWORD32
769 UA_ReadNBytes (T_tr_UartId uart_id,
770 char *buffer_p,
771 SYS_UWORD32 bytes_to_read,
772 SYS_BOOL *eof_detected_p)
773 {
774 SYS_UWORD32 bytes_written;
775 SYS_UWORD32 bytes_in_rx_buffer;
776 SYS_UWORD32 bytes_to_process;
777 t_uart *uart_p;
778 char *rx_in_p;
779
780 bytes_written = 0;
781 uart_p = &(uart_parameter[uart_id]);
782
783 /*
784 * A copy of the rx_in pointer is used because it may be updated by
785 * the interrupt handler.
786 * Get the number of bytes available in the RX buffer.
787 */
788
789 rx_in_p = uart_p->rx_in;
790
791 if (uart_p->rx_out <= rx_in_p)
792 bytes_in_rx_buffer = (SYS_UWORD32) (rx_in_p - uart_p->rx_out);
793 else
794 bytes_in_rx_buffer = (SYS_UWORD32) (rx_in_p - uart_p->rx_out + BUFFER_SIZE + 1);
795
796 /*
797 * No more bytes than those received may be processed and then written
798 * in the output buffer.
799 */
800
801 if (bytes_in_rx_buffer > bytes_to_read) {
802 bytes_to_process = bytes_to_read;
803
804 /*
805 * More bytes left. Users must invoke this function one more time
806 * in order to get those remaining bytes.
807 */
808
809 *eof_detected_p = 2;
810 }
811 else {
812 bytes_to_process = bytes_in_rx_buffer;
813
814 /*
815 * No more bytes left.
816 */
817
818 *eof_detected_p = 0;
819 }
820
821 /*
822 * Perform the byte destuffing and then write the "valid" received bytes in
823 * the output buffer.
824 */
825
826 while ((bytes_to_process) && !(*eof_detected_p & 0x01)) {
827
828 switch (*(uart_p->rx_out)) {
829
830 /*
831 * Current byte is DLE.
832 */
833
834 case DLE:
835
836 if (!uart_p->dle_detected) {
837
838 /*
839 * No DLE previously detected =>
840 * Skip the current byte and set the flag.
841 */
842
843 uart_p->dle_detected = 1;
844 uart_p->rx_out++;
845 }
846
847 else { /* if (uart_p->dle_detected) */
848
849 if (uart_p->inframe) {
850
851 /*
852 * DLE previously detected AND currently inside of a frame =>
853 * Copy the current byte in the output buffer, reset the flag
854 * and increase the frame length.
855 */
856
857 uart_p->dle_detected = 0;
858 uart_p->frame_length++;
859 *(buffer_p++) = *(uart_p->rx_out++);
860 bytes_written++;
861 }
862
863 else { /* if (!uart_p->inframe) */
864
865 /*
866 * DLE previously detected AND currently outside of a frame =>
867 * Skip the current byte.
868 */
869
870 uart_p->rx_out++;
871 }
872 }
873
874 break; /* case DLE */
875
876 /*
877 * Current byte is STX.
878 */
879
880 case STX:
881
882 if ((!uart_p->dle_detected) && (uart_p->inframe)) {
883
884 /*
885 * No DLE previously detected AND currently inside of a frame.
886 */
887
888 if (uart_p->frame_length) {
889
890 /*
891 * Frame length is not zero (End of Frame) =>
892 * Skip the current byte and set the flags (EOF).
893 */
894
895 uart_p->inframe = 0;
896 uart_p->frame_length = 0;
897 uart_p->rx_out++;
898
899 /*
900 * More bytes left.
901 */
902
903 if ((*eof_detected_p == 0) && (bytes_to_process))
904 *eof_detected_p = 2;
905
906 /*
907 * EOF detected.
908 */
909
910 (*eof_detected_p)++;
911 }
912
913 else { /* if (!uart_p->frame_length) */
914
915 /*
916 * Frame length is zero (STX followed by another STX =
917 * Synchro lost but start of a new frame) =>
918 * Skip the current byte and keep the flag set.
919 */
920
921 uart_p->rx_out++;
922 }
923 }
924
925 else if ((!uart_p->dle_detected) && (!uart_p->inframe)) {
926
927 /*
928 * No DLE previously detected AND currently outside of a
929 * frame (Start of Frame) =>
930 * Skip the current byte and set the flag.
931 */
932
933 uart_p->inframe = 1;
934 uart_p->rx_out++;
935 }
936
937 else if ((uart_p->dle_detected) && (uart_p->inframe)) {
938
939 /*
940 * DLE previously detected AND currently inside of a frame =>
941 * Copy the current byte in the output buffer, reset the flag
942 * and increase the frame length.
943 */
944
945 uart_p->dle_detected = 0;
946 uart_p->frame_length++;
947 *(buffer_p++) = *(uart_p->rx_out++);
948 bytes_written++;
949 }
950
951 else if ((uart_p->dle_detected) && (!uart_p->inframe)) {
952
953 /*
954 * DLE previously detected AND currently outside of a frame =>
955 * Skip the current byte and reset the flag.
956 */
957
958 uart_p->dle_detected = 0;
959 uart_p->rx_out++;
960 }
961
962 break; /* case STX */
963
964 /*
965 * Current byte is neither DLE nor STX.
966 */
967
968 default:
969
970 if (uart_p->inframe) {
971
972 /*
973 * Currently inside of a frame =>
974 * Copy the current byte in the output buffer and increase
975 * the frame length.
976 */
977
978 uart_p->frame_length++;
979 *(buffer_p++) = *(uart_p->rx_out++);
980 bytes_written++;
981 }
982
983 else { /* if (!uart_p->inframe) */
984
985 /*
986 * Currently outside of a frame =>
987 * Skip the current byte.
988 */
989
990 uart_p->rx_out++;
991 }
992
993 break; /* default */
994 }
995
996 if (uart_p->rx_out == &(uart_p->rx_buffer[0]) + BUFFER_SIZE + 1)
997 uart_p->rx_out = &(uart_p->rx_buffer[0]);
998
999 bytes_to_process--;
1000 }
1001
1002 return (bytes_written);
1003 }
1004
1005
1006 /*******************************************************************************
1007 *
1008 * UA_WriteNChars
1009 *
1010 * Purpose : Writes N characters in the TX FIFO.
1011 *
1012 * Arguments: In : uart_id : UART id.
1013 * buffer : buffer address from which characters are
1014 * written.
1015 * bytes_to_write: number of bytes to write.
1016 * Out: none
1017 *
1018 * Returns : Number of bytes written.
1019 *
1020 * Warning: Parameters are not verified.
1021 *
1022 ******************************************************************************/
1023
1024 SYS_UWORD32
1025 UA_WriteNChars (T_tr_UartId uart_id,
1026 char *buffer,
1027 SYS_UWORD32 chars_to_write)
1028 {
1029 SYS_UWORD32 chars_in_tx_fifo;
1030 SYS_UWORD32 chars_written;
1031 t_uart *uart;
1032
1033 chars_written = 0;
1034 uart = &(uart_parameter[uart_id]);
1035
1036 #if ((CHIPSET != 5) && (CHIPSET != 6))
1037 /*
1038 * Disable sleep mode.
1039 */
1040
1041 WRITE_UART_REGISTER (
1042 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
1043 #endif
1044
1045 /*
1046 * Copy the input buffer to the TX FIFO.
1047 * Ulyssse Bug #44: TX FIFO full status bit (SSR[1]) is corrupted during
1048 * one period of Bclock => Workaround S/W.
1049 * Write in TX FIFO only if FIFO is empty instead of writing in TX FIFO
1050 * while FIFO is not full.
1051 */
1052
1053 if (READ_UART_REGISTER (uart, LSR) & THRE) {
1054
1055 chars_in_tx_fifo = 0;
1056
1057 while ((chars_written < chars_to_write) &&
1058 (chars_in_tx_fifo < FIFO_SIZE)) {
1059
1060 WRITE_UART_REGISTER (uart, THR, *(buffer++));
1061 chars_written++;
1062 chars_in_tx_fifo++;
1063 }
1064 }
1065
1066 #if ((CHIPSET != 5) && (CHIPSET != 6))
1067 /*
1068 * Re-enable sleep mode.
1069 */
1070
1071 WRITE_UART_REGISTER (
1072 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
1073 #endif
1074
1075 return (chars_written);
1076 }
1077
1078
1079 /*******************************************************************************
1080 *
1081 * UA_EncapsulateNChars
1082 *
1083 * Purpose : Writes N characters in the TX FIFO in encapsulating them with 2
1084 * STX bytes (one at the beginning and one at the end).
1085 *
1086 * Arguments: In : uart_id : UART id.
1087 * buffer : buffer address from which characters are
1088 * written.
1089 * chars_to_write: number of chars to write.
1090 * Out: none
1091 *
1092 * Returns : Number of chars written.
1093 *
1094 * Warning: Parameters are not verified.
1095 *
1096 ******************************************************************************/
1097
1098 SYS_UWORD32
1099 UA_EncapsulateNChars (T_tr_UartId uart_id,
1100 char *buffer,
1101 SYS_UWORD32 chars_to_write)
1102 {
1103 SYS_UWORD32 chars_written;
1104 SYS_UWORD32 chars_in_tx_fifo;
1105 t_uart *uart;
1106
1107 chars_written = 0;
1108 uart = &(uart_parameter[uart_id]);
1109
1110 #if ((CHIPSET != 5) && (CHIPSET != 6))
1111 /*
1112 * Disable sleep mode.
1113 */
1114
1115 WRITE_UART_REGISTER (
1116 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
1117 #endif
1118
1119 /*
1120 * Copy the input buffer to the TX FIFO.
1121 * Ulyssse Bug #44: TX FIFO full status bit (SSR[1]) is corrupted during
1122 * one period of Bclock => Workaround S/W.
1123 * Write in TX FIFO only if FIFO is empty instead of writing in TX FIFO
1124 * while FIFO is not full.
1125 */
1126
1127 if (READ_UART_REGISTER (uart, LSR) & THRE) {
1128
1129 chars_in_tx_fifo = 0;
1130
1131 /*
1132 * Check if the message has been already encapsulated.
1133 */
1134
1135 if (!uart->encapsulation_flag) {
1136 /*
1137 * Write STX in the TX FIFO and set the flag.
1138 */
1139
1140 WRITE_UART_REGISTER (uart, THR, STX);
1141 chars_in_tx_fifo++;
1142 uart->encapsulation_flag = 1;
1143 }
1144
1145 /*
1146 * Keep one char margin in the TX FIFO for the last STX.
1147 */
1148
1149 while ((chars_written < chars_to_write) &&
1150 (chars_in_tx_fifo < (FIFO_SIZE-1))) {
1151
1152 WRITE_UART_REGISTER (uart, THR, *(buffer++));
1153 chars_written++;
1154 chars_in_tx_fifo++;
1155 }
1156
1157 /*
1158 * Append STX byte at the end if the frame is complete.
1159 */
1160
1161 if (chars_written == chars_to_write) {
1162
1163 /*
1164 * Write STX in the TX FIFO and reset the flag.
1165 */
1166
1167 WRITE_UART_REGISTER (uart, THR, STX);
1168 uart->encapsulation_flag = 0;
1169 }
1170 }
1171
1172 #if ((CHIPSET != 5) && (CHIPSET != 6))
1173 /*
1174 * Re-enable sleep mode.
1175 */
1176
1177 WRITE_UART_REGISTER (
1178 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
1179 #endif
1180
1181 return (chars_written);
1182 }
1183
1184
1185 /*******************************************************************************
1186 *
1187 * UA_WriteNBytes
1188 *
1189 * Purpose : Writes N bytes in the TX FIFO in encapsulating with 2 STX bytes
1190 * at the beginning and the end of the frame, and in making byte
1191 * stuffing.
1192 *
1193 * Arguments: In : uart_id : UART id.
1194 * buffer : buffer address from which bytes are
1195 * written.
1196 * bytes_to_write: number of bytes to write.
1197 * Out: none
1198 *
1199 * Returns : Number of bytes written.
1200 *
1201 * Warning: Parameters are not verified.
1202 *
1203 ******************************************************************************/
1204
1205 SYS_UWORD32
1206 UA_WriteNBytes (T_tr_UartId uart_id,
1207 SYS_UWORD8 *buffer,
1208 SYS_UWORD32 bytes_to_write)
1209 {
1210 SYS_UWORD32 bytes_written;
1211 SYS_UWORD32 bytes_in_tx_fifo;
1212 t_uart *uart;
1213
1214 bytes_written = 0;
1215 uart = &(uart_parameter[uart_id]);
1216
1217 #if ((CHIPSET != 5) && (CHIPSET != 6))
1218 /*
1219 * Disable sleep mode.
1220 */
1221
1222 WRITE_UART_REGISTER (
1223 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
1224 #endif
1225
1226 /*
1227 * Copy the input buffer to the TX FIFO.
1228 * Ulyssse Bug #44: TX FIFO full status bit (SSR[1]) is corrupted during
1229 * one period of Bclock => Workaround S/W.
1230 * Write in TX FIFO only if FIFO is empty instead of writing in TX FIFO
1231 * while FIFO is not full.
1232 */
1233
1234 if (READ_UART_REGISTER (uart, LSR) & THRE) {
1235
1236 bytes_in_tx_fifo = 0;
1237
1238 /*
1239 * Check if the message has been already encapsulated.
1240 */
1241
1242 if (!uart->encapsulation_flag) {
1243
1244 /*
1245 * Write STX in the TX FIFO and set the flag.
1246 */
1247
1248 WRITE_UART_REGISTER (uart, THR, STX);
1249 bytes_in_tx_fifo++;
1250 uart->encapsulation_flag = 1;
1251 }
1252
1253 /*
1254 * Keep 2 chars margin in the FIFO, one for the stuffing (if necessary)
1255 * and one for the last STX.
1256 */
1257
1258 while ((bytes_written < bytes_to_write) &&
1259 (bytes_in_tx_fifo < (FIFO_SIZE-2))) {
1260
1261 /*
1262 * Check for STX or DLE in order to perform the stuffing.
1263 */
1264
1265 if ((*(buffer) == STX) || (*(buffer) == DLE)) {
1266
1267 /*
1268 * Write DLE in the TX FIFO.
1269 */
1270
1271 WRITE_UART_REGISTER (uart, THR, DLE);
1272 bytes_in_tx_fifo++;
1273 }
1274
1275 WRITE_UART_REGISTER (uart, THR, *(buffer++));
1276 bytes_written++;
1277 bytes_in_tx_fifo++;
1278 }
1279
1280 /*
1281 * Append STX byte at the end if the frame is complete.
1282 */
1283
1284 if (bytes_written == bytes_to_write) {
1285
1286 /*
1287 * Write STX in the TX FIFO and reset the flag.
1288 */
1289
1290 WRITE_UART_REGISTER (uart, THR, STX);
1291 uart->encapsulation_flag = 0;
1292 }
1293 }
1294
1295 #if ((CHIPSET != 5) && (CHIPSET != 6))
1296 /*
1297 * Re-enable sleep mode.
1298 */
1299
1300 WRITE_UART_REGISTER (
1301 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
1302 #endif
1303
1304 return (bytes_written);
1305 }
1306
1307
1308 /*******************************************************************************
1309 *
1310 * UA_WriteChar
1311 *
1312 * Purpose : Writes a character in the TX FIFO.
1313 *
1314 * Arguments: In : uart: UART id.
1315 * character
1316 * Out: none
1317 *
1318 * Returns : none
1319 *
1320 * Warning: Parameters are not verified.
1321 *
1322 ******************************************************************************/
1323
1324 void
1325 UA_WriteChar (T_tr_UartId uart_id,
1326 char character)
1327 {
1328 (void) UA_WriteNChars (uart_id, &character, 1);
1329 }
1330
1331 /*******************************************************************************
1332 *
1333 * UA_WriteString
1334 *
1335 * Purpose : Writes a null terminated string in the TX FIFO.
1336 *
1337 * Arguments: In : uart_id: UART id.
1338 * buffer : buffer address from which characters are written.
1339 * Out: none
1340 *
1341 * Returns : none
1342 *
1343 * Warning: Parameters are not verified.
1344 *
1345 ******************************************************************************/
1346
1347 void
1348 UA_WriteString (T_tr_UartId uart_id,
1349 char *buffer)
1350 {
1351 (void) UA_WriteNChars (uart_id, buffer, strlen (buffer));
1352 }
1353
1354 /*******************************************************************************
1355 *
1356 * UA_EnterSleep
1357 *
1358 * Purpose : Checks if UART is ready to enter Deep Sleep. If ready, enables
1359 * wake-up interrupt.
1360 *
1361 * Arguments: In : uart_id : UART id.
1362 * Out: none
1363 *
1364 * Returns: 0 : Deep Sleep is not possible.
1365 * >= 1 : Deep Sleep is possible.
1366 *
1367 * Warning: Parameters are not verified.
1368 *
1369 ******************************************************************************/
1370
1371 SYS_BOOL
1372 UA_EnterSleep (T_tr_UartId uart_id)
1373 {
1374 t_uart *uart;
1375 SYS_BOOL deep_sleep;
1376 volatile SYS_UWORD8 status;
1377
1378 uart = &(uart_parameter[uart_id]);
1379 deep_sleep = 0;
1380
1381 /*
1382 * Check if RX & TX FIFOs are both empty
1383 */
1384
1385 status = READ_UART_REGISTER (uart, LSR);
1386
1387 if (!(status & DR) &&
1388 (status & TEMT)) {
1389
1390 #if ((CHIPSET != 5) && (CHIPSET != 6))
1391 /*
1392 * Disable sleep mode.
1393 */
1394
1395 WRITE_UART_REGISTER (
1396 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
1397 #endif
1398
1399 /*
1400 * Mask RX interrupt.
1401 */
1402
1403 WRITE_UART_REGISTER (
1404 uart, IER, READ_UART_REGISTER (uart, IER) & ~ERBI);
1405
1406 /*
1407 * Enable the wake-up interrupt.
1408 */
1409
1410 ENABLE_WAKEUP_INTERRUPT (uart);
1411
1412 deep_sleep = 1;
1413 }
1414
1415 return (deep_sleep);
1416 }
1417
1418 /*******************************************************************************
1419 *
1420 * UA_WakeUp
1421 *
1422 * Purpose : Wakes up UART after Deep Sleep.
1423 *
1424 * Arguments: In : uart_id : UART id.
1425 * Out: none
1426 *
1427 * Returns: none
1428 *
1429 * Warning: Parameters are not verified.
1430 *
1431 ******************************************************************************/
1432
1433 void
1434 UA_WakeUp (T_tr_UartId uart_id)
1435 {
1436 t_uart *uart;
1437
1438 uart = &(uart_parameter[uart_id]);
1439
1440 /*
1441 * Disable the wake-up interrupt.
1442 */
1443
1444 DISABLE_WAKEUP_INTERRUPT (uart);
1445
1446 /*
1447 * Unmask RX interrupts.
1448 */
1449
1450 WRITE_UART_REGISTER (
1451 uart, IER, READ_UART_REGISTER (uart, IER) | ERBI);
1452
1453 #if ((CHIPSET != 5) && (CHIPSET != 6))
1454 /*
1455 * Allow sleep mode.
1456 */
1457
1458 WRITE_UART_REGISTER (
1459 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
1460 #endif
1461 }
1462
1463 /*******************************************************************************
1464 *
1465 * UA_InterruptHandler
1466 *
1467 * Purpose : Interrupt handler.
1468 *
1469 * Arguments: In : uart_id : origin of interrupt
1470 * interrupt_status: source of interrupt
1471 * Out: none
1472 *
1473 * Returns : none
1474 *
1475 ******************************************************************************/
1476
1477 void
1478 UA_InterruptHandler (T_tr_UartId uart_id,
1479 SYS_UWORD8 interrupt_status)
1480 {
1481 t_uart *uart;
1482
1483 uart = &(uart_parameter[uart_id]);
1484
1485 switch (interrupt_status) {
1486
1487 case RX_DATA:
1488
1489 read_rx_fifo (uart);
1490
1491 break;
1492
1493 default:
1494
1495 #ifdef UART_RX_BUFFER_DUMP
1496 uart_rx_buffer_dump.wrong_interrupt_status++;
1497 #endif
1498
1499 /* No Processing */
1500
1501 break;
1502 }
1503 }