Changeset 1e744ef in rtems


Ignore:
Timestamp:
Nov 26, 2013, 7:47:37 AM (6 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
6fe6d017
Parents:
022851a
git-author:
Sebastian Huber <sebastian.huber@…> (11/26/13 07:47:37)
git-committer:
Sebastian Huber <sebastian.huber@…> (02/04/14 13:54:26)
Message:

bsp/leon3: Fix interrupt-driven console driver

File:
1 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/sparc/leon3/console/console.c

    r022851a r1e744ef  
    8686
    8787/* Handle UART interrupts */
    88 void console_isr(void *arg)
     88static void leon3_console_isr(void *arg)
    8989{
    9090  struct apbuart_priv *uart = arg;
     
    101101  }
    102102
    103   if (status & LEON_REG_UART_STATUS_THE) {
    104     /* Sent the one char, we disable TX interrupts */
    105     uart->regs->ctrl &= ~LEON_REG_UART_CTRL_TI;
    106 
    107     /* Tell close that we sent everything */
    108     uart->sending = 0;
    109 
     103  if (
     104    (status & LEON_REG_UART_STATUS_THE)
     105      && (uart->regs->ctrl & LEON_REG_UART_CTRL_TI) != 0
     106  ) {
    110107    /* write_interrupt will get called from this function */
    111108    rtems_termios_dequeue_characters(uart->cookie, 1);
     
    117114 *
    118115 */
    119 int console_write_interrupt(int minor, const char *buf, int len)
    120 {
     116static int leon3_console_write_support(int minor, const char *buf, size_t len)
     117{
     118  struct apbuart_priv *uart;
     119  int sending;
     120
     121  if (minor == 0)
     122    uart = &apbuarts[syscon_uart_index];
     123  else
     124    uart = &apbuarts[minor - 1];
     125
    121126  if (len > 0) {
    122     struct apbuart_priv *uart;
    123 
    124     if (minor == 0)
    125       uart = &apbuarts[syscon_uart_index];
    126     else
    127       uart = &apbuarts[minor - 1];
    128 
    129     /* Remember what position in buffer */
    130 
    131     /* Enable TX interrupt */
     127    /* Enable TX interrupt (interrupt is edge-triggered) */
    132128    uart->regs->ctrl |= LEON_REG_UART_CTRL_TI;
    133129
     
    135131    uart->regs->data = *buf;
    136132
    137     uart->sending = 1;
    138   }
     133    sending = 1;
     134  } else {
     135    /* No more to send, disable TX interrupts */
     136    uart->regs->ctrl &= ~LEON_REG_UART_CTRL_TI;
     137
     138    /* Tell close that we sent everything */
     139    sending = 0;
     140  }
     141
     142  uart->sending = sending;
    139143
    140144  return 0;
     
    212216  else
    213217    uart = &apbuarts[minor - 1];
     218
     219  /*
     220   * FIXME: This read-modify-write sequence is broken since interrupts may
     221   * interfere.
     222   */
    214223
    215224  /* Read out current value */
     
    352361}
    353362
     363#if CONSOLE_USE_INTERRUPTS
     364static struct rtems_termios_tty *leon3_console_get_tty(
     365  rtems_libio_open_close_args_t *args
     366)
     367{
     368  return args->iop->data1;
     369}
     370#endif
     371
     372static int leon3_console_first_open(int major, int minor, void *arg)
     373{
     374  struct apbuart_priv *uart;
     375  rtems_status_code sc;
     376
     377  if (minor == 0)
     378    uart = &apbuarts[syscon_uart_index];
     379  else
     380    uart = &apbuarts[minor - 1];
     381
     382#if CONSOLE_USE_INTERRUPTS
     383  uart->cookie = leon3_console_get_tty(arg);
     384
     385  /* Register Interrupt handler */
     386  sc = rtems_interrupt_handler_install(uart->irq, "console",
     387                                       RTEMS_INTERRUPT_SHARED,
     388                                       leon3_console_isr,
     389                                       uart);
     390  if (sc != RTEMS_SUCCESSFUL)
     391    return -1;
     392
     393  uart->sending = 0;
     394  /* Enable Receiver and transmitter and Turn on RX interrupts */
     395  uart->regs->ctrl |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE |
     396                      LEON_REG_UART_CTRL_RI;
     397#else
     398  /* Initialize UART on opening */
     399  uart->regs->ctrl |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
     400#endif
     401  uart->regs->status = 0;
     402
     403  return 0;
     404}
     405
     406#if CONSOLE_USE_INTERRUPTS
     407static int leon3_console_last_close(int major, int minor, void *arg)
     408{
     409  struct rtems_termios_tty *tty = leon3_console_get_tty(arg);
     410  struct apbuart_priv *uart;
     411  rtems_interrupt_level level;
     412
     413  if (minor == 0)
     414    uart = &apbuarts[syscon_uart_index];
     415  else
     416    uart = &apbuarts[minor - 1];
     417
     418  /* Turn off RX interrupts */
     419  rtems_termios_interrupt_lock_acquire(tty, level);
     420  uart->regs->ctrl &= ~(LEON_REG_UART_CTRL_RI);
     421  rtems_termios_interrupt_lock_release(tty, level);
     422
     423  /**** Flush device ****/
     424  while (uart->sending) {
     425    /* Wait until all data has been sent */
     426  }
     427
     428  /* uninstall ISR */
     429  rtems_interrupt_handler_remove(uart->irq, leon3_console_isr, uart);
     430
     431  return 0;
     432}
     433#endif
     434
    354435rtems_device_driver console_open(
    355436  rtems_device_major_number major,
     
    358439)
    359440{
    360   rtems_status_code sc;
    361   struct apbuart_priv *uart;
    362 #if CONSOLE_USE_INTERRUPTS
    363   rtems_libio_open_close_args_t *priv = arg;
    364 
     441#if CONSOLE_USE_INTERRUPTS
    365442  /* Interrupt mode routines */
    366443  static const rtems_termios_callbacks Callbacks = {
    367     NULL,                        /* firstOpen */
    368     NULL,                        /* lastClose */
     444    leon3_console_first_open,    /* firstOpen */
     445    leon3_console_last_close,    /* lastClose */
    369446    NULL,                        /* pollRead */
    370     console_write_interrupt,    /* write */
     447    leon3_console_write_support, /* write */
    371448    console_set_attributes,      /* setAttributes */
    372449    NULL,                        /* stopRemoteTx */
     
    377454  /* Polling mode routines */
    378455  static const rtems_termios_callbacks Callbacks = {
    379     NULL,                        /* firstOpen */
     456    leon3_console_first_open,    /* firstOpen */
    380457    NULL,                        /* lastClose */
    381458    console_pollRead,            /* pollRead */
     
    392469    return RTEMS_INVALID_NUMBER;
    393470
    394   sc = rtems_termios_open(major, minor, arg, &Callbacks);
    395   if (sc != RTEMS_SUCCESSFUL)
    396     return sc;
    397 
    398   if (minor == 0)
    399     uart = &apbuarts[syscon_uart_index];
    400   else
    401     uart = &apbuarts[minor - 1];
    402 
    403 #if CONSOLE_USE_INTERRUPTS
    404   if (priv && priv->iop)
    405     uart->cookie = priv->iop->data1;
    406   else
    407     uart->cookie = NULL;
    408 
    409   /* Register Interrupt handler */
    410   sc = rtems_interrupt_handler_install(uart->irq, "console",
    411                                        RTEMS_INTERRUPT_SHARED, console_isr,
    412                                        uart);
    413   if (sc != RTEMS_SUCCESSFUL)
    414     return sc;
    415 
    416   uart->sending = 0;
    417   /* Enable Receiver and transmitter and Turn on RX interrupts */
    418   uart->regs->ctrl |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE |
    419                       LEON_REG_UART_CTRL_RI;
    420 #else
    421   /* Initialize UART on opening */
    422   uart->regs->ctrl |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
    423 #endif
    424   uart->regs->status = 0;
    425 
    426   return RTEMS_SUCCESSFUL;
     471  return rtems_termios_open(major, minor, arg, &Callbacks);
    427472}
    428473
     
    433478)
    434479{
    435 #if CONSOLE_USE_INTERRUPTS
    436   struct apbuart_priv *uart;
    437 
    438   if (minor == 0)
    439     uart = &apbuarts[syscon_uart_index];
    440   else
    441     uart = &apbuarts[minor - 1];
    442 
    443   /* Turn off RX interrupts */
    444   uart->regs->ctrl &= ~(LEON_REG_UART_CTRL_RI);
    445 
    446   /**** Flush device ****/
    447   while (uart->sending) {
    448     /* Wait until all data has been sent */
    449   }
    450 
    451   /* uninstall ISR */
    452   rtems_interrupt_handler_remove(uart->irq, console_isr, uart);
    453 #endif
    454480  return rtems_termios_close(arg);
    455481}
Note: See TracChangeset for help on using the changeset viewer.