Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:08

0001 /**
0002  * @file
0003  *
0004  * @brief Driver for serial ports on the ERC32.
0005  */
0006 
0007 /*
0008  * Copyright (c) 2010 Tiemen Schut <T.Schut@sron.nl>
0009  *
0010  * The license and distribution terms for this file may be
0011  * found in the file LICENSE in this distribution or at
0012  * http://www.rtems.org/license/LICENSE.
0013  */
0014 
0015 #include <unistd.h>
0016 #include <termios.h>
0017 #include <stdlib.h>
0018 
0019 #include <rtems.h>
0020 #include <rtems/libio.h>
0021 #include <rtems/console.h>
0022 #include <rtems/termiostypes.h>
0023 
0024 #include <libchip/serial.h>
0025 #include <libchip/sersupp.h>
0026 
0027 #include <bsp.h>
0028 #include <bspopts.h>
0029 
0030 #define CONSOLE_BUF_SIZE (16)
0031 
0032 #define CONSOLE_UART_A_TRAP  ERC32_TRAP_TYPE(ERC32_INTERRUPT_UART_A_RX_TX)
0033 #define CONSOLE_UART_B_TRAP  ERC32_TRAP_TYPE(ERC32_INTERRUPT_UART_B_RX_TX)
0034 
0035 static uint8_t erc32_console_get_register(uintptr_t addr, uint8_t i)
0036 {
0037   volatile uint32_t *reg = (volatile uint32_t *)addr;
0038   return (uint8_t) reg [i];
0039 }
0040 
0041 static void erc32_console_set_register(uintptr_t addr, uint8_t i, uint8_t val)
0042 {
0043   volatile uint32_t *reg = (volatile uint32_t *)addr;
0044   reg [i] = val;
0045 }
0046 
0047 static int erc32_console_first_open(int major, int minor, void *arg);
0048 
0049 #if (CONSOLE_USE_INTERRUPTS)
0050   static ssize_t erc32_console_write_support_int(
0051     int minor, const char *buf, size_t len);
0052 #else
0053   int console_inbyte_nonblocking( int port );
0054   static ssize_t erc32_console_write_support_polled(
0055       int minor, const char *buf, size_t len);
0056 #endif
0057 static void erc32_console_initialize(int minor);
0058 
0059 #if (CONSOLE_USE_INTERRUPTS)
0060   const console_fns erc32_fns = {
0061     libchip_serial_default_probe,           /* deviceProbe */
0062     erc32_console_first_open,               /* deviceFirstOpen */
0063     NULL,                                   /* deviceLastClose */
0064     NULL,                                   /* deviceRead */
0065     erc32_console_write_support_int,        /* deviceWrite */
0066     erc32_console_initialize,               /* deviceInitialize */
0067     NULL,                                   /* deviceWritePolled */
0068     NULL,                                   /* deviceSetAttributes */
0069     true                                    /* deviceOutputUsesInterrupts */
0070   };
0071 #else
0072   const console_fns erc32_fns = {
0073     libchip_serial_default_probe,           /* deviceProbe */
0074     erc32_console_first_open,               /* deviceFirstOpen */
0075     NULL,                                   /* deviceLastClose */
0076     console_inbyte_nonblocking,             /* deviceRead */
0077     erc32_console_write_support_polled,     /* deviceWrite */
0078     erc32_console_initialize,               /* deviceInitialize */
0079     NULL,                                   /* deviceWritePolled */
0080     NULL,                                   /* deviceSetAttributes */
0081     false                                   /* deviceOutputUsesInterrupts */
0082   };
0083 #endif
0084 
0085 console_tbl Console_Configuration_Ports [] = {
0086   {
0087     .sDeviceName = "/dev/console_a",
0088     .deviceType = SERIAL_CUSTOM,
0089     .pDeviceFns = &erc32_fns,
0090     .deviceProbe = NULL,
0091     .pDeviceFlow = NULL,
0092     .ulMargin = 16,
0093     .ulHysteresis = 8,
0094     .pDeviceParams = (void *) -1,  /* could be baud rate */
0095     .ulCtrlPort1 = 0,
0096     .ulCtrlPort2 = 0,
0097     .ulDataPort = 0,
0098     .getRegister = erc32_console_get_register,
0099     .setRegister = erc32_console_set_register,
0100     .getData = NULL,
0101     .setData = NULL,
0102     .ulClock = 16,
0103     .ulIntVector = ERC32_INTERRUPT_UART_A_RX_TX
0104   },
0105   {
0106     .sDeviceName = "/dev/console_b",
0107     .deviceType = SERIAL_CUSTOM,
0108     .pDeviceFns = &erc32_fns,
0109     .deviceProbe = NULL,
0110     .pDeviceFlow = NULL,
0111     .ulMargin = 16,
0112     .ulHysteresis = 8,
0113     .pDeviceParams = (void *) -1,  /* could be baud rate */
0114     .ulCtrlPort1 = 0,
0115     .ulCtrlPort2 = 0,
0116     .ulDataPort = 0,
0117     .getRegister = erc32_console_get_register,
0118     .setRegister = erc32_console_set_register,
0119     .getData = NULL,
0120     .setData = NULL,
0121     .ulClock = 16,
0122     .ulIntVector = ERC32_INTERRUPT_UART_B_RX_TX
0123   },
0124 };
0125 
0126 /* always exactly two uarts for erc32 */
0127 #define ERC32_UART_COUNT (2)
0128 
0129 unsigned long Console_Configuration_Count = ERC32_UART_COUNT;
0130 
0131 static int erc32_console_first_open(int major, int minor, void *arg)
0132 {
0133   /* Check minor number */
0134   if (minor < 0 || minor > 1) {
0135     return -1;
0136   }
0137   
0138   rtems_libio_open_close_args_t *oca = arg;
0139   struct rtems_termios_tty *tty = oca->iop->data1;
0140   console_tbl *ct = Console_Port_Tbl [minor];
0141   console_data *cd = &Console_Port_Data [minor];
0142   
0143   cd->termios_data = tty;
0144   rtems_termios_set_initial_baud(tty, (int32_t)ct->pDeviceParams);
0145   
0146   return 0;
0147 }
0148 
0149 #if (CONSOLE_USE_INTERRUPTS)
0150 static ssize_t erc32_console_write_support_int(
0151     int minor, const char *buf, size_t len)
0152 {
0153   if (len > 0) {
0154     console_data *cd = &Console_Port_Data[minor];
0155     int k = 0;
0156 
0157     if (minor == 0) { /* uart a */
0158       for (k = 0;
0159            k < len && (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA);
0160            k ++) {
0161         ERC32_MEC.UART_Channel_A = (unsigned char)buf[k];
0162       }
0163       ERC32_Force_interrupt(ERC32_INTERRUPT_UART_A_RX_TX);
0164     } else { /* uart b */
0165       for (k = 0;
0166            k < len && (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB);
0167            k ++) {
0168         ERC32_MEC.UART_Channel_B = (unsigned char)buf[k];
0169       }
0170       ERC32_Force_interrupt(ERC32_INTERRUPT_UART_B_RX_TX);
0171     }
0172 
0173     cd->pDeviceContext = (void *)k;
0174     cd->bActive = true;
0175   }
0176 
0177   return 0;
0178 }
0179 
0180 static void erc32_console_isr_error(
0181   rtems_vector_number vector
0182 )
0183 {
0184   int UStat;
0185 
0186   UStat = ERC32_MEC.UART_Status;
0187 
0188   if (UStat & ERC32_MEC_UART_STATUS_ERRA) {
0189     ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRA;
0190     ERC32_MEC.Control = ERC32_MEC.Control;
0191   }
0192 
0193   if (UStat & ERC32_MEC_UART_STATUS_ERRB) {
0194     ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB;
0195     ERC32_MEC.Control = ERC32_MEC.Control;
0196   }
0197 
0198   ERC32_Clear_interrupt( ERC32_INTERRUPT_UART_ERROR );
0199 }
0200 
0201 static void erc32_console_isr_a(
0202   rtems_vector_number vector
0203 )
0204 {
0205   console_data *cd = &Console_Port_Data[0];
0206 
0207   /* check for error */
0208   if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_ERRA) {
0209     ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRA;
0210     ERC32_MEC.Control = ERC32_MEC.Control;
0211   }
0212 
0213   do {
0214     int chars_to_dequeue = (int)cd->pDeviceContext;
0215     int rv = 0;
0216     int i = 0;
0217     char buf[CONSOLE_BUF_SIZE];
0218         
0219     /* enqueue received chars */
0220     while (i < CONSOLE_BUF_SIZE) {
0221       if (!(ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRA))
0222         break;
0223       buf[i] = ERC32_MEC.UART_Channel_A;
0224       ++i;
0225     }
0226     if ( i ) 
0227       rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i);
0228 
0229     /* dequeue transmitted chars */
0230     if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA) {
0231       rv = rtems_termios_dequeue_characters(
0232          cd->termios_data, chars_to_dequeue);
0233       if ( !rv ) {
0234         cd->pDeviceContext = 0;
0235         cd->bActive = false;
0236       }
0237       ERC32_Clear_interrupt (ERC32_INTERRUPT_UART_A_RX_TX);
0238     }
0239   } while (ERC32_Is_interrupt_pending (ERC32_INTERRUPT_UART_A_RX_TX));
0240 }
0241 
0242 static void erc32_console_isr_b(
0243   rtems_vector_number vector
0244 )
0245 {
0246   console_data *cd = &Console_Port_Data[1];
0247 
0248   /* check for error */
0249   if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_ERRB) {
0250       ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB;
0251       ERC32_MEC.Control = ERC32_MEC.Control;
0252   }
0253 
0254   do {
0255     int chars_to_dequeue = (int)cd->pDeviceContext;
0256     int rv = 0;
0257     int i = 0;
0258     char buf[CONSOLE_BUF_SIZE];
0259         
0260     /* enqueue received chars */
0261     while (i < CONSOLE_BUF_SIZE) {
0262       if (!(ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRB))
0263         break;
0264       buf[i] = ERC32_MEC.UART_Channel_B;
0265       ++i;
0266     }
0267     if ( i )
0268       rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i);
0269 
0270     /* dequeue transmitted chars */
0271     if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB) {
0272       rv = rtems_termios_dequeue_characters(
0273          cd->termios_data, chars_to_dequeue);
0274       if ( !rv ) {
0275         cd->pDeviceContext = 0;
0276         cd->bActive = false;
0277       }
0278       ERC32_Clear_interrupt (ERC32_INTERRUPT_UART_B_RX_TX);
0279     }
0280   } while (ERC32_Is_interrupt_pending (ERC32_INTERRUPT_UART_B_RX_TX));
0281 }
0282 #else
0283 
0284 extern void console_outbyte_polled( int  port, unsigned char ch );
0285 
0286 static ssize_t erc32_console_write_support_polled(
0287   int         minor,
0288   const char *buf,
0289   size_t      len
0290 )
0291 {
0292   int nwrite = 0;
0293 
0294   while (nwrite < len) {
0295     console_outbyte_polled( minor, *buf++ );
0296     nwrite++;
0297   }
0298   return nwrite;
0299 }
0300 
0301 #endif
0302 
0303 
0304 /*
0305  *  Console Device Driver Entry Points
0306  *
0307  */
0308 
0309 static void erc32_console_initialize(
0310     int minor
0311 )
0312 {
0313   console_data *cd = &Console_Port_Data [minor];
0314 
0315   cd->bActive = false;
0316   cd->pDeviceContext = 0;
0317 
0318  /*
0319   * Initialize the Termios infrastructure.  If Termios has already
0320   * been initialized by another device driver, then this call will
0321   * have no effect.
0322   */
0323   rtems_termios_initialize();
0324 
0325  /*
0326   *  Initialize Hardware
0327   */
0328   #if (CONSOLE_USE_INTERRUPTS)
0329     set_vector(erc32_console_isr_a, CONSOLE_UART_A_TRAP, 1);
0330     set_vector(erc32_console_isr_b, CONSOLE_UART_B_TRAP, 1);
0331     set_vector(erc32_console_isr_error, CONSOLE_UART_ERROR_TRAP, 1);
0332   #endif
0333 
0334    /* Clear any previous error flags */
0335    ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRA;
0336    ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB;
0337 }