comparison nuc-fw/serial/uart.c @ 116:22c8199e08af

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