source: rtems/c/src/lib/libbsp/arm/shared/comm/uart.c @ 82dcbc8

4.115
Last change on this file since 82dcbc8 was f05b2ac, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/21/04 at 16:01:48

Remove duplicate white lines.

  • Property mode set to 100644
File size: 11.0 KB
Line 
1/*
2 * This software is Copyright (C) 1998 by T.sqware - all rights limited
3 * It is provided in to the public domain "as is", can be freely modified
4 * as far as this copyight notice is kept unchanged, but does not imply
5 * an endorsement by T.sqware of the product in which it is included.
6 *
7 *  COPYRIGHT (c) 2000 Canon Research France SA.
8 *  Emmanuel Raguet, mailto:raguet@crf.canon.fr
9 *
10 * The license and distribution terms for this file may be
11 * found in found in the file LICENSE in this distribution or at
12 * http://www.rtems.com/license/LICENSE.
13 *
14 *  $Id$
15 */
16
17#include <bsp.h>
18#include <irq.h>
19#include <registers.h>
20#include <uart.h>
21#include <rtems/libio.h>
22#include <assert.h>
23
24/*
25 * Basic 16552 driver
26 */
27
28struct uart_data
29{
30  int hwFlow;
31  int baud;
32};
33
34static struct uart_data uart_data[2];
35
36/*
37 * Macros to read/wirte register of uart, if configuration is
38 * different just rewrite these macros
39 */
40
41static inline unsigned char
42uread(int uart, unsigned int reg)
43{
44  register unsigned char val;
45
46  val = Regs[reg];
47
48  return val;
49}
50
51static inline void
52uwrite(int uart, int reg, unsigned int val)
53{
54
55  Regs[reg] = val;
56
57}
58
59#ifdef UARTDEBUG
60    static void
61uartError(int uart)
62{
63  unsigned char uartStatus, dummy;
64
65  uartStatus = uread(uart, LSR);
66  dummy = uread(uart, RBR);
67
68  if (uartStatus & OE)
69    printk("********* Over run Error **********\n");
70  if (uartStatus & PE)
71    printk("********* Parity Error   **********\n");
72  if (uartStatus & FE)
73    printk("********* Framing Error  **********\n");
74  if (uartStatus & BI)
75    printk("********* Parity Error   **********\n");
76  if (uartStatus & ERFIFO)
77    printk("********* Error receive Fifo **********\n");
78
79}
80#else
81inline void uartError(int uart)
82{
83  unsigned char uartStatus;
84
85  uartStatus = uread(uart, LSR);
86  uartStatus = uread(uart, RBR);
87}
88#endif
89
90/*
91 * Uart initialization, it is hardcoded to 8 bit, no parity,
92 * one stop bit, FIFO, things to be changed
93 * are baud rate and nad hw flow control,
94 * and longest rx fifo setting
95 */
96void
97BSP_uart_init(int uart, int baud, int hwFlow)
98{
99  unsigned char tmp;
100
101  /* Sanity check */
102  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
103
104  switch(baud)
105    {
106    case 50:
107    case 75:
108    case 110:
109    case 134:
110    case 300:
111    case 600:
112    case 1200:
113    case 2400:
114    case 9600:
115    case 19200:
116    case 38400:
117    case 57600:
118    case 115200:
119      break;
120    default:
121      assert(0);
122      return;
123    }
124
125  /* Enable UART block */
126  uwrite(uart, CNT, UART_ENABLE | PAD_ENABLE);
127
128  /* Set DLAB bit to 1 */
129  uwrite(uart, LCR, DLAB);
130
131  /* Set baud rate */
132  uwrite(uart, DLL,  (BSPBaseBaud/baud) & 0xff);
133  uwrite(uart, DLM,  ((BSPBaseBaud/baud) >> 8) & 0xff);
134
135  /* 8-bit, no parity , 1 stop */
136  uwrite(uart, LCR, CHR_8_BITS);
137
138  /* Enable FIFO */
139  uwrite(uart, FCR, FIFO_EN | XMIT_RESET | RCV_RESET | RECEIVE_FIFO_TRIGGER12);
140
141  /* Disable Interrupts */
142  uwrite(uart, IER, 0);
143
144  /* Read status to clear them */
145  tmp = uread(uart, LSR);
146  tmp = uread(uart, RBR);
147
148  /* Remember state */
149  uart_data[uart].hwFlow     = hwFlow;
150  uart_data[uart].baud       = baud;
151  return;
152}
153
154/*
155 * Set baud
156 */
157void
158BSP_uart_set_baud(int uart, int baud)
159{
160  unsigned char  ier;
161
162  /* Sanity check */
163  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
164
165  /*
166   * This function may be called whenever TERMIOS parameters
167   * are changed, so we have to make sure that baud change is
168   * indeed required
169   */
170
171  if(baud == uart_data[uart].baud)
172    {
173      return;
174    }
175
176  ier = uread(uart, IER);
177
178  BSP_uart_init(uart, baud, uart_data[uart].hwFlow);
179
180  uwrite(uart, IER, ier);
181
182  return;
183}
184
185/*
186 * Enable/disable interrupts
187 */
188void
189BSP_uart_intr_ctrl(int uart, int cmd)
190{
191
192  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
193
194  switch(cmd)
195    {
196    case BSP_UART_INTR_CTRL_DISABLE:
197      uwrite(uart, IER, INTERRUPT_DISABLE);
198      break;
199    case BSP_UART_INTR_CTRL_ENABLE:
200      uwrite(uart, IER,
201             (RECEIVE_ENABLE  |
202              TRANSMIT_ENABLE |
203              RECEIVER_LINE_ST_ENABLE
204              )
205             );
206      break;
207    case BSP_UART_INTR_CTRL_TERMIOS:
208      uwrite(uart, IER,
209             (RECEIVE_ENABLE  |
210              RECEIVER_LINE_ST_ENABLE
211              )
212             );
213      break;
214    case BSP_UART_INTR_CTRL_GDB:
215      uwrite(uart, IER, RECEIVE_ENABLE);
216      break;
217    default:
218      assert(0);
219      break;
220    }
221
222  return;
223}
224
225/*
226 * Status function, -1 if error
227 * detected, 0 if no received chars available,
228 * 1 if received char available, 2 if break
229 * is detected, it will eat break and error
230 * chars. It ignores overruns - we cannot do
231 * anything about - it execpt count statistics
232 * and we are not counting it.
233 */
234int
235BSP_uart_polled_status(int uart)
236{
237  unsigned char val;
238
239  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
240
241  val = uread(uart, LSR);
242
243  if(val & BI)
244    {
245      /* BREAK found, eat character */
246      uread(uart, RBR);
247      return BSP_UART_STATUS_BREAK;
248    }
249
250  if((val & (DR | OE | FE)) ==  1)
251    {
252      /* No error, character present */
253      return BSP_UART_STATUS_CHAR;
254    }
255
256  if((val & (DR | OE | FE)) == 0)
257    {
258      /* Nothing */
259      return BSP_UART_STATUS_NOCHAR;
260    }
261
262  /*
263   * Framing or parity error
264   * eat character
265   */
266  uread(uart, RBR);
267
268  return BSP_UART_STATUS_ERROR;
269}
270
271/*
272 * Polled mode write function
273 */
274void
275BSP_uart_polled_write(int uart, int val)
276{
277  unsigned char val1;
278
279  /* Sanity check */
280  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
281
282  for(;;)
283    {
284      if((val1=uread(uart, LSR)) & THRE)
285        {
286          break;
287        }
288    }
289
290  uwrite(uart, THR, val & 0xff);
291
292  return;
293}
294
295void
296BSP_output_char_via_serial(int val)
297{
298  BSP_uart_polled_write(BSPConsolePort, val);
299  if (val == '\n') BSP_uart_polled_write(BSPConsolePort,'\r');
300}
301
302/*
303 * Polled mode read function
304 */
305int
306BSP_uart_polled_read(int uart)
307{
308  unsigned char val;
309
310  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
311
312  for(;;)
313    {
314      if(uread(uart, LSR) & DR)
315        {
316          break;
317        }
318    }
319
320  val = uread(uart, RBR);
321
322  return (int)(val & 0xff);
323}
324
325unsigned
326BSP_poll_char_via_serial()
327{
328        return BSP_uart_polled_read(BSPConsolePort);
329}
330
331/* ================ Termios support  =================*/
332
333static volatile int  termios_stopped_com1        = 0;
334static volatile int  termios_tx_active_com1      = 0;
335static void*         termios_ttyp_com1           = NULL;
336static char          termios_tx_hold_com1        = 0;
337static volatile char termios_tx_hold_valid_com1  = 0;
338
339static volatile int  termios_stopped_com2        = 0;
340static volatile int  termios_tx_active_com2      = 0;
341static void*         termios_ttyp_com2           = NULL;
342static char          termios_tx_hold_com2        = 0;
343static volatile char termios_tx_hold_valid_com2  = 0;
344
345/*
346 * Set channel parameters
347 */
348void
349BSP_uart_termios_set(int uart, void *ttyp)
350{
351  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
352
353  if(uart == BSP_UART_COM1)
354    {
355      termios_stopped_com1 = 0;
356      termios_tx_active_com1      = 0;
357      termios_ttyp_com1           = ttyp;
358      termios_tx_hold_com1        = 0;
359      termios_tx_hold_valid_com1  = 0;
360    }
361  else
362    {
363      termios_stopped_com2 = 0;
364      termios_tx_active_com2      = 0;
365      termios_ttyp_com2           = ttyp;
366      termios_tx_hold_com2        = 0;
367      termios_tx_hold_valid_com2  = 0;
368    }
369
370  return;
371}
372
373int
374BSP_uart_termios_write_com1(int minor, const char *buf, int len)
375{
376  assert(buf != NULL);
377
378  if(len <= 0)
379    {
380      return 0;
381    }
382
383  /* If there TX buffer is busy - something is royally screwed up */
384  assert((uread(BSP_UART_COM1, LSR) & THRE) != 0);
385
386  if(termios_stopped_com1)
387    {
388      /* CTS low */
389      termios_tx_hold_com1       = *buf;
390      termios_tx_hold_valid_com1 = 1;
391      return 0;
392    }
393
394  /* Write character */
395  uwrite(BSP_UART_COM1, THR, *buf & 0xff);
396
397  /* Enable interrupts if necessary */
398  if(!termios_tx_active_com1)
399    {
400      termios_tx_active_com1 = 1;
401      uwrite(BSP_UART_COM1, IER,
402             (RECEIVE_ENABLE  |
403              TRANSMIT_ENABLE |
404              RECEIVER_LINE_ST_ENABLE
405             )
406            );
407    }
408
409  return 0;
410}
411
412int
413BSP_uart_termios_write_com2(int minor, const char *buf, int len)
414{
415  assert(buf != NULL);
416
417  if(len <= 0)
418    {
419      return 0;
420    }
421
422  /* If there TX buffer is busy - something is royally screwed up */
423  assert((uread(BSP_UART_COM2, LSR) & THRE) != 0);
424
425  if(termios_stopped_com2)
426    {
427      /* CTS low */
428      termios_tx_hold_com2       = *buf;
429      termios_tx_hold_valid_com2 = 1;
430      return 0;
431    }
432
433  /* Write character */
434
435  uwrite(BSP_UART_COM2, THR, *buf & 0xff);
436
437  /* Enable interrupts if necessary */
438  if(!termios_tx_active_com2)
439    {
440      termios_tx_active_com2 = 1;
441      uwrite(BSP_UART_COM2, IER,
442             (RECEIVE_ENABLE  |
443              TRANSMIT_ENABLE |
444              RECEIVER_LINE_ST_ENABLE
445             )
446            );
447    }
448
449  return 0;
450}
451
452void
453BSP_uart_termios_isr_com1(void)
454{
455  unsigned char buf[40];
456  int      off, ret, vect;
457
458  off = 0;
459
460  for(;;)
461    {
462      vect = uread(BSP_UART_COM1, IIR) & 0xf;
463
464      switch(vect)
465        {
466        case NO_MORE_INTR :
467          /* No more interrupts */
468          if(off != 0)
469            {
470              /* Update rx buffer */
471              rtems_termios_enqueue_raw_characters(termios_ttyp_com1,
472                                                   (char *)buf,
473                                                   off);
474            }
475          return;
476        case TRANSMITTER_HODING_REGISTER_EMPTY :
477          /*
478           * TX holding empty: we have to disable these interrupts
479           * if there is nothing more to send.
480           */
481
482          ret = rtems_termios_dequeue_characters(termios_ttyp_com1, 1);
483
484          /* If nothing else to send disable interrupts */
485          if(ret == 0)
486            {
487              uwrite(BSP_UART_COM1, IER,
488                     (RECEIVE_ENABLE  |
489                      RECEIVER_LINE_ST_ENABLE
490                     )
491                    );
492              termios_tx_active_com1 = 0;
493            }
494          break;
495        case RECEIVER_DATA_AVAIL :
496        case CHARACTER_TIMEOUT_INDICATION:
497          /* RX data ready */
498          assert(off < sizeof(buf));
499          buf[off++] = uread(BSP_UART_COM1, RBR);
500          break;
501        case RECEIVER_ERROR:
502          /* RX error: eat character */
503           uartError(BSP_UART_COM1);
504          break;
505        default:
506          /* Should not happen */
507          assert(0);
508          return;
509        }
510    }
511}
512
513void
514BSP_uart_termios_isr_com2()
515{
516  unsigned char buf[40];
517  int      off, ret, vect;
518
519  off = 0;
520
521  for(;;)
522    {
523      vect = uread(BSP_UART_COM2, IIR) & 0xf;
524
525      switch(vect)
526        {
527        case NO_MORE_INTR :
528          /* No more interrupts */
529          if(off != 0)
530            {
531              /* Update rx buffer */
532              rtems_termios_enqueue_raw_characters(termios_ttyp_com2,
533                                                   (char *)buf,
534                                                   off);
535            }
536          return;
537        case TRANSMITTER_HODING_REGISTER_EMPTY :
538          /*
539           * TX holding empty: we have to disable these interrupts
540           * if there is nothing more to send.
541           */
542
543          ret = rtems_termios_dequeue_characters(termios_ttyp_com2, 1);
544
545          /* If nothing else to send disable interrupts */
546          if(ret == 0)
547            {
548              uwrite(BSP_UART_COM2, IER,
549                     (RECEIVE_ENABLE  |
550                      RECEIVER_LINE_ST_ENABLE
551                     )
552                    );
553              termios_tx_active_com2 = 0;
554            }
555          break;
556        case RECEIVER_DATA_AVAIL :
557        case CHARACTER_TIMEOUT_INDICATION:
558          /* RX data ready */
559          assert(off < sizeof(buf));
560          buf[off++] = uread(BSP_UART_COM2, RBR);
561          break;
562        case RECEIVER_ERROR:
563          /* RX error: eat character */
564           uartError(BSP_UART_COM2);
565          break;
566        default:
567          /* Should not happen */
568          assert(0);
569          return;
570        }
571    }
572}
Note: See TracBrowser for help on using the repository browser.