[PATCH 34.2 v2 3/6] LEON3: add console interrupt mode support

Joel Sherrill joel.sherrill at OARcorp.com
Thu Apr 19 13:26:32 UTC 2012


OK with one minor formatting nit.

Look for

Console Termios Write-Buffer Support Entry Point

There is a blank unneeded comment line.

You can resubmit or if whoever commits will fix that,
I am ok.





On 04/19/2012 08:21 AM, Daniel Hellstrom wrote:
> The comment in configure.ac is probably inherited from the LEON2
> BSP. The LEON3 console driver implements a "flush" mechanism on
> console_close() in order to solve the problem described with
> sis/LEON2.
>
> Signed-off-by: Daniel Hellstrom<daniel at gaisler.com>
> ---
>   c/src/lib/libbsp/sparc/leon3/configure.ac      |    5 +-
>   c/src/lib/libbsp/sparc/leon3/console/console.c |  172 +++++++++++++++++++++---
>   2 files changed, 154 insertions(+), 23 deletions(-)
>
> diff --git a/c/src/lib/libbsp/sparc/leon3/configure.ac b/c/src/lib/libbsp/sparc/leon3/configure.ac
> index 6d86386..3f2d445 100644
> --- a/c/src/lib/libbsp/sparc/leon3/configure.ac
> +++ b/c/src/lib/libbsp/sparc/leon3/configure.ac
> @@ -26,10 +26,7 @@ RTEMS_BSPOPTS_SET([CONSOLE_USE_INTERRUPTS],[*],[0])
>   RTEMS_BSPOPTS_HELP([CONSOLE_USE_INTERRUPTS],
>   [The leon3 console driver can operate in either polled or interrupt mode.
>   Under the simulator (especially when FAST_UART is defined), polled seems to operate
> -better.  It is common for a task to print a line (like the end of test message) and
> -then exit.  In this case, the program returns control to the simulator command line
> -before the program has even queued the output to the uart.  Thus sis has no chance
> -of getting the data out.])
> +better.])
>
>   RTEMS_BSPOPTS_SET([SIMSPARC_FAST_IDLE],[*],[])
>   RTEMS_BSPOPTS_HELP([SIMSPARC_FAST_IDLE],
> diff --git a/c/src/lib/libbsp/sparc/leon3/console/console.c b/c/src/lib/libbsp/sparc/leon3/console/console.c
> index 45ec82e..aece47a 100644
> --- a/c/src/lib/libbsp/sparc/leon3/console/console.c
> +++ b/c/src/lib/libbsp/sparc/leon3/console/console.c
> @@ -15,6 +15,17 @@
>    *  http://www.rtems.com/license/LICENSE.
>    */
>
> +/* Define CONSOLE_USE_INTERRUPTS to enable APBUART interrupt handling instead
> + * of polling mode.
> + *
> + * Note that it is not possible to use the interrupt mode of the driver
> + * together with the "old" APBUART and -u to GRMON. However the new
> + * APBUART core (from GRLIB 1.0.17-b2710) has the GRMON debug bit and can
> + * handle interrupts.
> + *
> + * NOTE: This can be defined in the make/custom/leon3.cfg file.
> + */
> +
>   #include<bsp.h>
>   #include<rtems/libio.h>
>   #include<stdlib.h>
> @@ -32,12 +43,6 @@
>   int syscon_uart_index __attribute__((weak)) = 0;
>
>   /*
> - *  Should we use a polled or interrupt drived console?
> - *
> - *  NOTE: This is defined in the custom/leon.cfg file.
> - */
> -
> -/*
>    *  apbuart_outbyte_polled
>    *
>    *  This routine transmits a character using polling.
> @@ -63,16 +68,86 @@ extern int apbuart_inbyte_nonblocking(ambapp_apb_uart *regs);
>   struct apbuart_priv {
>     ambapp_apb_uart *regs;
>     unsigned int freq_hz;
> +#if CONSOLE_USE_INTERRUPTS
> +  int irq;
> +  void *cookie;
> +  volatile int sending;
> +  char *buf;
> +#endif
>   };
>   static struct apbuart_priv apbuarts[BSP_NUMBER_OF_TERMIOS_PORTS];
>   static int uarts = 0;
>
> +#if CONSOLE_USE_INTERRUPTS
> +
> +/* Handle UART interrupts */
> +void console_isr(void *arg)
> +{
> +  struct apbuart_priv *uart = arg;
> +  unsigned int status;
> +  char data;
> +
> +  /* Get all received characters */
> +  while ((status=uart->regs->status)&  LEON_REG_UART_STATUS_DR) {
> +    /* Data has arrived, get new data */
> +    data = uart->regs->data;
> +
> +    /* Tell termios layer about new character */
> +    rtems_termios_enqueue_raw_characters(uart->cookie,&data, 1);
> +  }
> +
> +  if (status&  LEON_REG_UART_STATUS_THE) {
> +    /* Sent the one char, we disable TX interrupts */
> +    uart->regs->ctrl&= ~LEON_REG_UART_CTRL_TI;
> +
> +    /* Tell close that we sent everything */
> +    uart->sending = 0;
> +
> +    /* write_interrupt will get called from this function */
> +    rtems_termios_dequeue_characters(uart->cookie, 1);
> +  }
> +}
> +
> +/*
> + *  Console Termios Write-Buffer Support Entry Point
> + *
> + */
> +
> +int console_write_interrupt(int minor, const char *buf, int len)
> +{
> +  struct apbuart_priv *uart;
> +  unsigned int oldLevel;
> +
> +  if (minor == 0)
> +    uart =&apbuarts[syscon_uart_index];
> +  else
> +    uart =&apbuarts[minor - 1];
> +
> +  /* Remember what position in buffer */
> +
> +  rtems_interrupt_disable(oldLevel);
> +
> +  /* Enable TX interrupt */
> +  uart->regs->ctrl |= LEON_REG_UART_CTRL_TI;
> +
> +  /* start UART TX, this will result in an interrupt when done */
> +  uart->regs->data = *buf;
> +
> +  uart->sending = 1;
> +
> +  rtems_interrupt_enable(oldLevel);
> +
> +  return 0;
> +}
> +
> +#else
> +
>   /*
>    *  Console Termios Support Entry Points
>    *
>    */
>
> -ssize_t console_write_support (int minor, const char *buf, size_t len)
> +ssize_t console_write_polled(int minor, const char *buf, size_t len)
>   {
>     int nwrite = 0, port;
>
> @@ -100,6 +175,8 @@ int console_pollRead(int minor)
>     return apbuart_inbyte_nonblocking(apbuarts[port].regs);
>   }
>
> +#endif
> +
>   int console_set_attributes(int minor, const struct termios *t)
>   {
>     unsigned int scaler;
> @@ -174,6 +251,9 @@ int find_matching_apbuart(struct ambapp_dev *dev, int index, void *arg)
>
>     /* Extract needed information of one APBUART */
>     apbuarts[uarts].regs = (ambapp_apb_uart *)apb->start;
> +#if CONSOLE_USE_INTERRUPTS
> +  apbuarts[uarts].irq = apb->irq;
> +#endif
>     /* Get APBUART core frequency, it is assumed that it is the same
>      * as Bus frequency where the UART is situated
>      */
> @@ -266,35 +346,70 @@ rtems_device_driver console_open(
>   )
>   {
>     rtems_status_code sc;
> -  int port;
> +  struct apbuart_priv *uart;
> +#if CONSOLE_USE_INTERRUPTS
> +  rtems_libio_open_close_args_t *priv = arg;
>
> -  static const rtems_termios_callbacks pollCallbacks = {
> +  /* Interrupt mode routines */
> +  static const rtems_termios_callbacks Callbacks = {
> +    NULL,                        /* firstOpen */
> +    NULL,                        /* lastClose */
> +    NULL,                        /* pollRead */
> +    console_write_interrupt,     /* write */
> +    console_set_attributes,      /* setAttributes */
> +    NULL,                        /* stopRemoteTx */
> +    NULL,                        /* startRemoteTx */
> +    1                            /* outputUsesInterrupts */
> +  };
> +#else
> +  /* Polling mode routines */
> +  static const rtems_termios_callbacks Callbacks = {
>       NULL,                        /* firstOpen */
>       NULL,                        /* lastClose */
>       console_pollRead,            /* pollRead */
> -    console_write_support,       /* write */
> +    console_write_polled,        /* write */
>       console_set_attributes,      /* setAttributes */
>       NULL,                        /* stopRemoteTx */
>       NULL,                        /* startRemoteTx */
>       0                            /* outputUsesInterrupts */
>     };
> +#endif
>
>     assert(minor<= uarts);
>     if (minor>  uarts || minor == (syscon_uart_index + 1))
>       return RTEMS_INVALID_NUMBER;
>
> -  sc = rtems_termios_open (major, minor, arg,&pollCallbacks);
> +  sc = rtems_termios_open(major, minor, arg,&Callbacks);
>     if (sc != RTEMS_SUCCESSFUL)
>       return sc;
>
>     if (minor == 0)
> -    port = syscon_uart_index;
> +    uart =&apbuarts[syscon_uart_index];
>     else
> -    port = minor - 1;
> +    uart =&apbuarts[minor - 1];
> +
> +#if CONSOLE_USE_INTERRUPTS
> +  if (priv&&  priv->iop)
> +    uart->cookie = priv->iop->data1;
> +  else
> +    uart->cookie = NULL;
> +
> +  /* Register Interrupt handler */
> +  sc = rtems_interrupt_handler_install(uart->irq, "console",
> +                                       RTEMS_INTERRUPT_SHARED, console_isr,
> +                                       uart);
> +  if (sc != RTEMS_SUCCESSFUL)
> +    return sc;
>
> +  uart->sending = 0;
> +  /* Enable Receiver and transmitter and Turn on RX interrupts */
> +  uart->regs->ctrl |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE |
> +                      LEON_REG_UART_CTRL_RI;
> +#else
>     /* Initialize UART on opening */
> -  apbuarts[port]->regs->ctrl |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
> -  apbuarts[port]->regs->status = 0;
> +  uart->regs->ctrl |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
> +#endif
> +  uart->regs->status = 0;
>
>     return RTEMS_SUCCESSFUL;
>   }
> @@ -305,7 +420,26 @@ rtems_device_driver console_close(
>     void                    * arg
>   )
>   {
> -  return rtems_termios_close (arg);
> +#if CONSOLE_USE_INTERRUPTS
> +  struct apbuart_priv *uart;
> +
> +  if (minor == 0)
> +    uart =&apbuarts[syscon_uart_index];
> +  else
> +    uart =&apbuarts[minor - 1];
> +
> +  /* Turn off RX interrupts */
> +  uart->regs->ctrl&= ~(LEON_REG_UART_CTRL_RI);
> +
> +  /**** Flush device ****/
> +  while (uart->sending) {
> +    /* Wait until all data has been sent */
> +  }
> +
> +  /* uninstall ISR */
> +  rtems_interrupt_handler_remove(uart->irq, console_isr, uart);
> +#endif
> +  return rtems_termios_close(arg);
>   }
>
>   rtems_device_driver console_read(
> @@ -314,7 +448,7 @@ rtems_device_driver console_read(
>     void                    * arg
>   )
>   {
> -  return rtems_termios_read (arg);
> +  return rtems_termios_read(arg);
>   }
>
>   rtems_device_driver console_write(
> @@ -323,7 +457,7 @@ rtems_device_driver console_write(
>     void                    * arg
>   )
>   {
> -  return rtems_termios_write (arg);
> +  return rtems_termios_write(arg);
>   }
>
>   rtems_device_driver console_control(
> @@ -332,6 +466,6 @@ rtems_device_driver console_control(
>     void                    * arg
>   )
>   {
> -  return rtems_termios_ioctl (arg);
> +  return rtems_termios_ioctl(arg);
>   }
>


-- 
Joel Sherrill, Ph.D.             Director of Research&   Development
joel.sherrill at OARcorp.com        On-Line Applications Research
Ask me about RTEMS: a free RTOS  Huntsville AL 35805
     Support Available             (256) 722-9985





More information about the devel mailing list