[PATCH 28] LEON3: cleanup console UART indexing handling

Daniel Hellstrom daniel at gaisler.com
Thu Apr 5 15:23:18 UTC 2012


The UART indexing was rather a mess when MP was enabled. The changes
introduces two weak variables syscon_uart_index and debug_uart_index
so that the user can override the default system debug console (printk)
and system console UART (/dev/console).

The two weak variables is updated on boot to reflect the "real" UART
index.

MINOR    DEVICE-FS-NAME       UART
0        /dev/console         Default /dev/console_a, user selectable
1        /dev/console_a       APBUART[0]   (missing by default)
2        /dev/console_b       APBUART[1]
...

/dev/console_a is by default renamed /dev/console and assigned minor=0,
but user can select /dev/console_['a'+N] to be renamed to /dev/console
by setting syscon_uart_index=N.

On a MP system the console renamed to /dev/console is selected by CPU
index (LEON3_Cpu_Index). /dev/console_['a' + LEON3_Cpu_Index] is
renamed unless overrided. Resource sharing is performed by the user,
one should not open/access a console that another OS instance uses.

This patch also moves the initialization of the UART to the open()
call, note that before APBUART[0] was always enabled as debug uart
even on MP systems. The debug UART is initialized at boot time.

Signed-off-by: Daniel Hellstrom <daniel at gaisler.com>
---
 c/src/lib/libbsp/sparc/leon3/console/console.c   |  114 ++++++++++++++-------
 c/src/lib/libbsp/sparc/leon3/console/debugputs.c |   73 ++++++++++-----
 2 files changed, 126 insertions(+), 61 deletions(-)

diff --git a/c/src/lib/libbsp/sparc/leon3/console/console.c b/c/src/lib/libbsp/sparc/leon3/console/console.c
index fee8721..a07fb15 100644
--- a/c/src/lib/libbsp/sparc/leon3/console/console.c
+++ b/c/src/lib/libbsp/sparc/leon3/console/console.c
@@ -24,6 +24,15 @@
 #include <rtems/bspIo.h>
 #include <amba.h>
 
+/* Let user override which on-chip APBUART will be debug UART
+ * 0 = Default APBUART. On MP system CPU0=APBUART0, CPU1=APBUART1...
+ * 1 = APBUART[0]
+ * 2 = APBUART[1]
+ * 3 = APBUART[2]
+ * ...
+ */
+int syscon_uart_index __attribute__((weak)) = 0;
+
 /*
  *  Should we use a polled or interrupt drived console?
  *
@@ -44,12 +53,12 @@ void console_outbyte_polled(
 /* body is in debugputs.c */
 
 /*
- *  console_inbyte_nonblocking
+ *  apbuart_inbyte_nonblocking
  *
  *  This routine polls for a character.
  */
 
-int console_inbyte_nonblocking( int port );
+int apbuart_inbyte_nonblocking(int port);
 
 /* body is in debugputs.c */
 
@@ -61,15 +70,31 @@ int console_inbyte_nonblocking( int port );
 
 ssize_t console_write_support (int minor, const char *buf, size_t len)
 {
-  int nwrite = 0;
+  int nwrite = 0, port;
+
+  if (minor == 0)
+    port = syscon_uart_index;
+  else
+    port = minor - 1;
 
   while (nwrite < len) {
-    console_outbyte_polled( minor, *buf++ );
+    console_outbyte_polled(port, *buf++);
     nwrite++;
   }
   return nwrite;
 }
 
+int console_inbyte_nonblocking(int minor)
+{
+  int port;
+
+  if (minor == 0)
+    port = syscon_uart_index;
+  else
+    port = minor - 1;
+
+  return apbuart_inbyte_nonblocking(port);
+}
 
 /*
  *  Console Device Driver Entry Points
@@ -85,45 +110,47 @@ rtems_device_driver console_initialize(
 )
 {
   rtems_status_code status;
-  int i, uart0;
+  int i;
   char console_name[16];
 
   rtems_termios_initialize();
 
-  /* default console to zero and override if multiprocessing */
-  uart0 = 0;
-  #if defined(RTEMS_MULTIPROCESSING)
-    if (rtems_configuration_get_user_multiprocessing_table() != NULL)
-      uart0 =  LEON3_Cpu_Index;
-  #endif
+  /* Update syscon_uart_index to index used as /dev/console
+   * Let user select System console by setting syscon_uart_index. If the
+   * BSP is to provide the default UART (syscon_uart_index==0):
+   *   non-MP: APBUART[0] is system console
+   *   MP: LEON CPU index select UART
+   */
+  if (syscon_uart_index == 0) {
+#if defined(RTEMS_MULTIPROCESSING)
+    syscon_uart_index = LEON3_Cpu_Index;
+#else
+    syscon_uart_index = 0;
+#endif
+  } else {
+    syscon_uart_index = syscon_uart_index - 1; /* User selected sys-console */
+  }
 
-  /*  Register Device Names */
-  if (uarts && (uart0 < uarts)) {
+  /*  Register Device Names
+   *
+   *  0 /dev/console   - APBUART[USER-SELECTED, DEFAULT=APBUART[0]]
+   *  1 /dev/console_a - APBUART[0] (by default not present because is console)
+   *  2 /dev/console_b - APBUART[1]
+   *  ...
+   *
+   * On a MP system one should not open UARTs that other OS instances use.
+   */
+  if (syscon_uart_index < uarts) {
     status = rtems_io_register_name( "/dev/console", major, 0 );
     if (status != RTEMS_SUCCESSFUL)
       rtems_fatal_error_occurred(status);
-
-    strcpy(console_name,"/dev/console_a");
-    for (i = uart0+1; i < uarts; i++) {
-      console_name[13]++;
-      status = rtems_io_register_name( console_name, major, i);
-    }
   }
-
-  /*
-   *  Initialize Hardware if ONLY CPU or first CPU in MP system
-   */
-
-  #if defined(RTEMS_MULTIPROCESSING)
-    if (rtems_configuration_get_user_multiprocessing_table()->node == 1)
-  #endif
-  {
-    for (i = uart0; i < uarts; i++)
-    {
-      LEON3_Console_Uart[i]->ctrl |=
-        LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
-      LEON3_Console_Uart[i]->status = 0;
-    }
+  strcpy(console_name,"/dev/console_a");
+  for (i = 0; i < uarts; i++) {
+    if (i == syscon_uart_index)
+      continue; /* skip UART that is registered as /dev/console */
+    console_name[13] = 'a' + i;
+    status = rtems_io_register_name( console_name, major, i+1);
   }
 
   return RTEMS_SUCCESSFUL;
@@ -136,6 +163,7 @@ rtems_device_driver console_open(
 )
 {
   rtems_status_code sc;
+  int port;
 
   static const rtems_termios_callbacks pollCallbacks = {
     NULL,                        /* firstOpen */
@@ -148,13 +176,23 @@ rtems_device_driver console_open(
     0                            /* outputUsesInterrupts */
   };
 
-
-  assert( minor <= LEON3_APBUARTS );
-  if ( minor > LEON3_APBUARTS )
+  assert(minor <= uarts);
+  if (minor > uarts || minor == (syscon_uart_index + 1))
     return RTEMS_INVALID_NUMBER;
 
   sc = rtems_termios_open (major, minor, arg, &pollCallbacks);
-
+  if (sc != RTEMS_SUCCESSFUL)
+    return sc;
+
+  if (minor == 0)
+    port = syscon_uart_index;
+  else
+    port = minor - 1;
+
+  /* Initialize UART on opening */
+  LEON3_Console_Uart[port]->ctrl |= LEON_REG_UART_CTRL_RE |
+                                     LEON_REG_UART_CTRL_TE;
+  LEON3_Console_Uart[port]->status = 0;
 
   return RTEMS_SUCCESSFUL;
 }
diff --git a/c/src/lib/libbsp/sparc/leon3/console/debugputs.c b/c/src/lib/libbsp/sparc/leon3/console/debugputs.c
index 2cd0d13..cf3f280 100644
--- a/c/src/lib/libbsp/sparc/leon3/console/debugputs.c
+++ b/c/src/lib/libbsp/sparc/leon3/console/debugputs.c
@@ -7,8 +7,8 @@
  *  On-Line Applications Research Corporation (OAR).
  *
  *  Modified for LEON3 BSP.
- *  COPYRIGHT (c) 2004.
- *  Gaisler Research.
+ *  COPYRIGHT (c) 2011.
+ *  Aeroflex Gaisler.
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -29,6 +29,15 @@ extern int uarts;
 
 static int isinit = 0;
 
+/* Let user override which on-chip APBUART will be debug UART
+ * 0 = Default APBUART. On MP system CPU0=APBUART0, CPU1=APBUART1...
+ * 1 = APBUART[0]
+ * 2 = APBUART[1]
+ * 3 = APBUART[2]
+ * ...
+ */
+int debug_uart_index __attribute__((weak)) = 0;
+
 /*
  *  Scan for UARTS in configuration
  */
@@ -47,11 +56,27 @@ int scan_uarts(void)
       LEON3_Console_Uart[i] = (volatile LEON3_UART_Regs_Map *)apbuarts[i].start;
     }
 
-    /* initialize uart 0 if present for printk */
-    if ( uarts ) {
-      LEON3_Console_Uart[0]->ctrl |=
-        LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
-      LEON3_Console_Uart[0]->status = 0;
+    /* Update debug_uart_index to index used as debug console.
+     * Let user select Debug console by setting debug_uart_index. If the
+     * BSP is to provide the default UART (debug_uart_index==0):
+     *   non-MP: APBUART[0] is debug console
+     *   MP: LEON CPU index select UART
+     */
+    if (debug_uart_index == 0) {
+#if defined(RTEMS_MULTIPROCESSING)
+      debug_uart_index = LEON3_Cpu_Index;
+#else
+      debug_uart_index = 0;
+#endif
+    } else {
+      debug_uart_index = debug_uart_index - 1; /* User selected dbg-console */
+    }
+
+    /* initialize debug uart if present for printk */
+    if (debug_uart_index < uarts) {
+      LEON3_Console_Uart[debug_uart_index]->ctrl |= LEON_REG_UART_CTRL_RE |
+                                                    LEON_REG_UART_CTRL_TE;
+      LEON3_Console_Uart[debug_uart_index]->status = 0;
     }
     isinit = 1;
   }
@@ -70,10 +95,10 @@ void console_outbyte_polled(
 )
 {
   if ((port >= 0) && (port < uarts)) {
-    int u = LEON3_Cpu_Index+port;
-    while ( (LEON3_Console_Uart[u]->status & LEON_REG_UART_STATUS_THE) == 0 );
-    LEON3_Console_Uart[u]->data = (unsigned int) ch;
-  }
+    return;
+
+  while ( (LEON3_Console_Uart[port]->status & LEON_REG_UART_STATUS_THE) == 0 );
+  LEON3_Console_Uart[port]->data = (unsigned int) ch;
 }
 
 /*
@@ -81,26 +106,27 @@ void console_outbyte_polled(
  *
  *  This routine polls for a character.
  */
-int console_inbyte_nonblocking( int port )
+int apbuart_inbyte_nonblocking(int port)
 {
   if ((port >= 0) && (port < uarts)) {
-    int u = LEON3_Cpu_Index+port;
-    if (LEON3_Console_Uart[u]->status & LEON_REG_UART_STATUS_ERR)
-      LEON3_Console_Uart[u]->status = ~LEON_REG_UART_STATUS_ERR;
-
-    if ((LEON3_Console_Uart[u]->status & LEON_REG_UART_STATUS_DR) == 0)
-      return -1;
-    return (int) LEON3_Console_Uart[u]->data;
-  } else {
     assert( 0 );
+    return -1;
   }
-  return -1;
+
+  /* Clear errors */
+  if (LEON3_Console_Uart[port]->status & LEON_REG_UART_STATUS_ERR)
+    LEON3_Console_Uart[port]->status = ~LEON_REG_UART_STATUS_ERR;
+
+  if ((LEON3_Console_Uart[port]->status & LEON_REG_UART_STATUS_DR) == 0)
+    return -1;
+  else
+    return (int) LEON3_Console_Uart[port]->data;
 }
 
 /* putchar/getchar for printk */
 static void bsp_out_char(char c)
 {
-  console_outbyte_polled(0, c);
+  console_outbyte_polled(debug_uart_index, c);
 }
 
 /*
@@ -115,7 +141,8 @@ static int bsp_in_char(void)
 {
   int tmp;
 
-  while ((tmp = console_inbyte_nonblocking(0)) < 0);
+  while ((tmp = apbuart_inbyte_nonblocking(debug_uart_index)) < 0)
+    ;
   return tmp;
 }
 
-- 
1.7.0.4




More information about the devel mailing list