source: rtems/c/src/lib/libbsp/arm/shared/comm/uart.c @ 08330bf

4.104.114.84.95
Last change on this file since 08330bf was 08330bf, checked in by Joel Sherrill <joel.sherrill@…>, on 07/27/00 at 01:04:11

Port of RTEMS to the ARM processor family by Eric Valette
<valette@…> and Emmanuel Raguet <raguet@…>
of Canon CRF - Communication Dept. This port includes a
basic BSP that is sufficient to link hello world.

  • Property mode set to 100644
File size: 11.1 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.OARcorp.com/rtems/license.html.
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/*
227 * Status function, -1 if error
228 * detected, 0 if no received chars available,
229 * 1 if received char available, 2 if break
230 * is detected, it will eat break and error
231 * chars. It ignores overruns - we cannot do
232 * anything about - it execpt count statistics
233 * and we are not counting it.
234 */
235int
236BSP_uart_polled_status(int uart)
237{
238  unsigned char val;
239
240  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
241
242  val = uread(uart, LSR);
243
244  if(val & BI)
245    {
246      /* BREAK found, eat character */
247      uread(uart, RBR);
248      return BSP_UART_STATUS_BREAK;
249    }
250
251  if((val & (DR | OE | FE)) ==  1)
252    {
253      /* No error, character present */
254      return BSP_UART_STATUS_CHAR;
255    }
256
257  if((val & (DR | OE | FE)) == 0)
258    {
259      /* Nothing */
260      return BSP_UART_STATUS_NOCHAR;
261    }
262
263  /*
264   * Framing or parity error
265   * eat character
266   */
267  uread(uart, RBR);
268 
269  return BSP_UART_STATUS_ERROR;
270}
271
272
273/*
274 * Polled mode write function
275 */
276void
277BSP_uart_polled_write(int uart, int val)
278{
279  unsigned char val1;
280 
281  /* Sanity check */
282  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
283 
284  for(;;)
285    {
286      if((val1=uread(uart, LSR)) & THRE)
287        {
288          break;
289        }
290    }
291
292  uwrite(uart, THR, val & 0xff);
293     
294  return;
295}
296
297void
298BSP_output_char_via_serial(int val)
299{
300  BSP_uart_polled_write(BSPConsolePort, val);
301  if (val == '\n') BSP_uart_polled_write(BSPConsolePort,'\r');
302}
303
304/*
305 * Polled mode read function
306 */
307int
308BSP_uart_polled_read(int uart)
309{
310  unsigned char val;
311
312  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
313 
314  for(;;)
315    {
316      if(uread(uart, LSR) & DR)
317        {
318          break;
319        }
320    }
321 
322  val = uread(uart, RBR);
323
324  return (int)(val & 0xff);
325}
326
327unsigned
328BSP_poll_char_via_serial()
329{
330        return BSP_uart_polled_read(BSPConsolePort);
331}
332
333
334/* ================ Termios support  =================*/
335
336static volatile int  termios_stopped_com1        = 0;
337static volatile int  termios_tx_active_com1      = 0;
338static void*         termios_ttyp_com1           = NULL;
339static char          termios_tx_hold_com1        = 0;
340static volatile char termios_tx_hold_valid_com1  = 0;
341
342static volatile int  termios_stopped_com2        = 0;
343static volatile int  termios_tx_active_com2      = 0;
344static void*         termios_ttyp_com2           = NULL;
345static char          termios_tx_hold_com2        = 0;
346static volatile char termios_tx_hold_valid_com2  = 0;
347
348/*
349 * Set channel parameters
350 */
351void
352BSP_uart_termios_set(int uart, void *ttyp)
353{
354  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
355 
356  if(uart == BSP_UART_COM1)
357    {
358      termios_stopped_com1 = 0;
359      termios_tx_active_com1      = 0;
360      termios_ttyp_com1           = ttyp;
361      termios_tx_hold_com1        = 0;
362      termios_tx_hold_valid_com1  = 0;
363    }
364  else
365    {
366      termios_stopped_com2 = 0;
367      termios_tx_active_com2      = 0;
368      termios_ttyp_com2           = ttyp;
369      termios_tx_hold_com2        = 0;
370      termios_tx_hold_valid_com2  = 0;
371    }
372
373  return;
374}
375
376int
377BSP_uart_termios_write_com1(int minor, const char *buf, int len)
378{
379  assert(buf != NULL);
380
381  if(len <= 0)
382    {
383      return 0;
384    }
385
386  /* If there TX buffer is busy - something is royally screwed up */
387  assert((uread(BSP_UART_COM1, LSR) & THRE) != 0);
388
389  if(termios_stopped_com1)
390    {
391      /* CTS low */
392      termios_tx_hold_com1       = *buf;
393      termios_tx_hold_valid_com1 = 1;
394      return 0;
395    }
396
397  /* Write character */
398  uwrite(BSP_UART_COM1, THR, *buf & 0xff);
399
400  /* Enable interrupts if necessary */
401  if(!termios_tx_active_com1)
402    {
403      termios_tx_active_com1 = 1;
404      uwrite(BSP_UART_COM1, IER,
405             (RECEIVE_ENABLE  |
406              TRANSMIT_ENABLE |
407              RECEIVER_LINE_ST_ENABLE
408             )
409            );
410    }
411
412  return 0;
413}
414
415int
416BSP_uart_termios_write_com2(int minor, const char *buf, int len)
417{
418  assert(buf != NULL);
419
420  if(len <= 0)
421    {
422      return 0;
423    }
424
425
426  /* If there TX buffer is busy - something is royally screwed up */
427  assert((uread(BSP_UART_COM2, LSR) & THRE) != 0);
428
429  if(termios_stopped_com2)
430    {
431      /* CTS low */
432      termios_tx_hold_com2       = *buf;
433      termios_tx_hold_valid_com2 = 1;
434      return 0;
435    }
436
437  /* Write character */
438
439  uwrite(BSP_UART_COM2, THR, *buf & 0xff);
440
441  /* Enable interrupts if necessary */
442  if(!termios_tx_active_com2)
443    {
444      termios_tx_active_com2 = 1;
445      uwrite(BSP_UART_COM2, IER,
446             (RECEIVE_ENABLE  |
447              TRANSMIT_ENABLE |
448              RECEIVER_LINE_ST_ENABLE
449             )
450            );
451    }
452
453  return 0;
454}
455
456
457void
458BSP_uart_termios_isr_com1(void)
459{
460  unsigned char buf[40];
461  int      off, ret, vect;
462
463  off = 0;
464
465  for(;;)
466    {
467      vect = uread(BSP_UART_COM1, IIR) & 0xf;
468     
469      switch(vect)
470        {
471        case NO_MORE_INTR :
472          /* No more interrupts */
473          if(off != 0)
474            {
475              /* Update rx buffer */
476              rtems_termios_enqueue_raw_characters(termios_ttyp_com1,
477                                                   (char *)buf,
478                                                   off);
479            }
480          return;
481        case TRANSMITTER_HODING_REGISTER_EMPTY :
482          /*
483           * TX holding empty: we have to disable these interrupts
484           * if there is nothing more to send.
485           */
486
487          ret = rtems_termios_dequeue_characters(termios_ttyp_com1, 1);
488
489          /* If nothing else to send disable interrupts */
490          if(ret == 0)
491            {
492              uwrite(BSP_UART_COM1, IER,
493                     (RECEIVE_ENABLE  |
494                      RECEIVER_LINE_ST_ENABLE
495                     )
496                    );
497              termios_tx_active_com1 = 0;
498            }
499          break;
500        case RECEIVER_DATA_AVAIL :
501        case CHARACTER_TIMEOUT_INDICATION:
502          /* RX data ready */
503          assert(off < sizeof(buf));
504          buf[off++] = uread(BSP_UART_COM1, RBR);
505          break;
506        case RECEIVER_ERROR:
507          /* RX error: eat character */
508           uartError(BSP_UART_COM1);
509          break;
510        default:
511          /* Should not happen */
512          assert(0);
513          return;
514        }
515    }
516}
517         
518void
519BSP_uart_termios_isr_com2()
520{
521  unsigned char buf[40];
522  int      off, ret, vect;
523
524  off = 0;
525
526  for(;;)
527    {
528      vect = uread(BSP_UART_COM2, IIR) & 0xf;
529     
530      switch(vect)
531        {
532        case NO_MORE_INTR :
533          /* No more interrupts */
534          if(off != 0)
535            {
536              /* Update rx buffer */
537              rtems_termios_enqueue_raw_characters(termios_ttyp_com2,
538                                                   (char *)buf,
539                                                   off);
540            }
541          return;
542        case TRANSMITTER_HODING_REGISTER_EMPTY :
543          /*
544           * TX holding empty: we have to disable these interrupts
545           * if there is nothing more to send.
546           */
547
548          ret = rtems_termios_dequeue_characters(termios_ttyp_com2, 1);
549
550          /* If nothing else to send disable interrupts */
551          if(ret == 0)
552            {
553              uwrite(BSP_UART_COM2, IER,
554                     (RECEIVE_ENABLE  |
555                      RECEIVER_LINE_ST_ENABLE
556                     )
557                    );
558              termios_tx_active_com2 = 0;
559            }
560          break;
561        case RECEIVER_DATA_AVAIL :
562        case CHARACTER_TIMEOUT_INDICATION:
563          /* RX data ready */
564          assert(off < sizeof(buf));
565          buf[off++] = uread(BSP_UART_COM2, RBR);
566          break;
567        case RECEIVER_ERROR:
568          /* RX error: eat character */
569           uartError(BSP_UART_COM2);
570          break;
571        default:
572          /* Should not happen */
573          assert(0);
574          return;
575        }
576    }
577}
Note: See TracBrowser for help on using the repository browser.