[PATCH] Add a simple task console driver

Sebastian Huber sebastian.huber at embedded-brains.de
Tue Mar 6 07:09:49 UTC 2018


Close #3320.
---
 cpukit/include/rtems/confdefs.h            |  22 ++-
 cpukit/include/rtems/console.h             |  13 +-
 cpukit/libcsupport/Makefile.am             |   2 +
 cpukit/libcsupport/src/consolesimple.c     |  26 +---
 cpukit/libcsupport/src/consolesimple.h     |  19 +++
 cpukit/libcsupport/src/consolesimpleread.c |  44 ++++++
 cpukit/libcsupport/src/consolesimpletask.c | 218 +++++++++++++++++++++++++++++
 testsuites/ada/sptests/sp20/config.h       |   4 +-
 testsuites/ada/support/init.c              |   1 +
 testsuites/sptests/sp20/init.c             |  19 +--
 testsuites/sptests/sp20/system.h           |   2 +-
 11 files changed, 319 insertions(+), 51 deletions(-)
 create mode 100644 cpukit/libcsupport/src/consolesimple.h
 create mode 100644 cpukit/libcsupport/src/consolesimpleread.c
 create mode 100644 cpukit/libcsupport/src/consolesimpletask.c

diff --git a/cpukit/include/rtems/confdefs.h b/cpukit/include/rtems/confdefs.h
index be937ab6c0..04b9708aca 100755
--- a/cpukit/include/rtems/confdefs.h
+++ b/cpukit/include/rtems/confdefs.h
@@ -1529,9 +1529,13 @@ extern rtems_initialization_tasks_table Initialization_tasks[];
 #define NULL_DRIVER_TABLE_ENTRY \
  { NULL, NULL, NULL, NULL, NULL, NULL }
 
-#if defined(CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER) && \
-  defined(CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER)
-#error "CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER and CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER are mutually exclusive"
+#if (defined(CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER) && \
+    defined(CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER)) || \
+  (defined(CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER) && \
+    defined(CONFIGURE_APPLICATION_NEEDS_SIMPLE_TASK_CONSOLE_DRIVER)) || \
+  (defined(CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER) && \
+    defined(CONFIGURE_APPLICATION_NEEDS_SIMPLE_TASK_CONSOLE_DRIVER))
+#error "CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER, CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER, and CONFIGURE_APPLICATION_NEEDS_SIMPLE_TASK_CONSOLE_DRIVER are mutually exclusive"
 #endif
 
 #ifdef CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
@@ -1550,6 +1554,18 @@ extern rtems_initialization_tasks_table Initialization_tasks[];
   #endif
 #endif
 
+#ifdef CONFIGURE_APPLICATION_NEEDS_SIMPLE_TASK_CONSOLE_DRIVER
+  #include <rtems/console.h>
+
+  #ifdef CONFIGURE_INIT
+    RTEMS_SYSINIT_ITEM(
+      _Console_simple_task_Initialize,
+      RTEMS_SYSINIT_DEVICE_DRIVERS,
+      RTEMS_SYSINIT_ORDER_SECOND
+    );
+  #endif
+#endif
+
 #ifdef CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
   #include <rtems/clockdrv.h>
 #endif
diff --git a/cpukit/include/rtems/console.h b/cpukit/include/rtems/console.h
index f9a7de186c..522e6fef41 100644
--- a/cpukit/include/rtems/console.h
+++ b/cpukit/include/rtems/console.h
@@ -150,12 +150,19 @@ rtems_device_driver console_control(
 /**
  * @brief Initializes a simple console device.
  *
- * This device writes via rtems_putc() and reads via getchark().  The Termios
- * framework is not used.  There is no support to change device settings, e.g.
- * baud, stop bits, parity, etc.
+ * See CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER documentation in the
+ * "RTEMS Classic API Guide".
  */
 void _Console_simple_Initialize( void );
 
+/**
+ * @brief Initializes a simple task console device.
+ *
+ * See CONFIGURE_APPLICATION_NEEDS_SIMPLE_TASK_CONSOLE_DRIVER documentation in
+ * the "RTEMS Classic API Guide".
+ */
+void _Console_simple_task_Initialize( void );
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/libcsupport/Makefile.am b/cpukit/libcsupport/Makefile.am
index 253c2c9924..586085916c 100644
--- a/cpukit/libcsupport/Makefile.am
+++ b/cpukit/libcsupport/Makefile.am
@@ -116,6 +116,8 @@ libcsupport_a_SOURCES = src/gxx_wrappers.c src/getchark.c src/printk.c \
     $(BSD_LIBC_C_FILES) $(BASE_FS_C_FILES) $(MALLOC_C_FILES) \
     $(ERROR_C_FILES) $(ASSOCIATION_C_FILES)
 libcsupport_a_SOURCES += src/consolesimple.c
+libcsupport_a_SOURCES += src/consolesimpleread.c
+libcsupport_a_SOURCES += src/consolesimpletask.c
 libcsupport_a_SOURCES += src/printertask.c
 libcsupport_a_SOURCES += src/printerfprintfputc.c
 
diff --git a/cpukit/libcsupport/src/consolesimple.c b/cpukit/libcsupport/src/consolesimple.c
index 5aa0f98528..94aa40c9fd 100644
--- a/cpukit/libcsupport/src/consolesimple.c
+++ b/cpukit/libcsupport/src/consolesimple.c
@@ -16,31 +16,7 @@
 #include <rtems/bspIo.h>
 #include <rtems/imfs.h>
 
-static ssize_t _Console_simple_Read(
-  rtems_libio_t *iop,
-  void          *buffer,
-  size_t         count
-)
-{
-  char    *buf;
-  ssize_t  i;
-  ssize_t  n;
-
-  buf = buffer;
-  n = (ssize_t) count;
-
-  for ( i = 0; i < n; ++i ) {
-    int c;
-
-    do {
-      c = getchark();
-    } while (c == -1);
-
-    buf[ i ] = (char) c;
-  }
-
-  return n;
-}
+#include "consolesimple.h"
 
 static ssize_t _Console_simple_Write(
   rtems_libio_t *iop,
diff --git a/cpukit/libcsupport/src/consolesimple.h b/cpukit/libcsupport/src/consolesimple.h
new file mode 100644
index 0000000000..82f5cd9cd3
--- /dev/null
+++ b/cpukit/libcsupport/src/consolesimple.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+ssize_t _Console_simple_Read(
+  rtems_libio_t *iop,
+  void          *buffer,
+  size_t         count
+);
diff --git a/cpukit/libcsupport/src/consolesimpleread.c b/cpukit/libcsupport/src/consolesimpleread.c
new file mode 100644
index 0000000000..a796e4380f
--- /dev/null
+++ b/cpukit/libcsupport/src/consolesimpleread.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/bspIo.h>
+#include <rtems/libio.h>
+
+#include "consolesimple.h"
+
+ssize_t _Console_simple_Read(
+  rtems_libio_t *iop,
+  void          *buffer,
+  size_t         count
+)
+{
+  char    *buf;
+  ssize_t  i;
+  ssize_t  n;
+
+  buf = buffer;
+  n = (ssize_t) count;
+
+  for ( i = 0; i < n; ++i ) {
+    int c;
+
+    do {
+      c = getchark();
+    } while (c == -1);
+
+    buf[ i ] = (char) c;
+  }
+
+  return n;
+}
diff --git a/cpukit/libcsupport/src/consolesimpletask.c b/cpukit/libcsupport/src/consolesimpletask.c
new file mode 100644
index 0000000000..29bab8cb86
--- /dev/null
+++ b/cpukit/libcsupport/src/consolesimpletask.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/console.h>
+#include <rtems/bspIo.h>
+#include <rtems/imfs.h>
+#include <rtems/thread.h>
+
+#include "consolesimple.h"
+
+#define CONSOLE_SIMPLE_TASK_BUFFER_SIZE 2048
+
+#define CONSOLE_SIMPLE_TASK_MAX_JUNK_SIZE 80
+
+typedef struct {
+  RTEMS_INTERRUPT_LOCK_MEMBER( buf_lock )
+  rtems_mutex output_mutex;
+  rtems_id task;
+  size_t head;
+  size_t tail;
+  char buf[ CONSOLE_SIMPLE_TASK_BUFFER_SIZE ];
+} Console_simple_task_Control;
+
+static Console_simple_task_Control _Console_simple_task_Instance;
+
+static size_t _Console_simple_task_Capacity(
+  const Console_simple_task_Control *cons
+)
+{
+  return ( cons->tail - cons->head - 1 ) % CONSOLE_SIMPLE_TASK_BUFFER_SIZE;
+}
+
+static size_t _Console_simple_task_Available(
+  const Console_simple_task_Control *cons
+)
+{
+  return ( cons->head - cons->tail ) % CONSOLE_SIMPLE_TASK_BUFFER_SIZE;
+}
+
+static ssize_t _Console_simple_task_Write(
+  rtems_libio_t *iop,
+  const void    *buffer,
+  size_t         count
+)
+{
+  Console_simple_task_Control *cons;
+  const char                  *buf;
+  size_t                       todo;
+
+  cons = IMFS_generic_get_context_by_iop( iop );
+  buf = buffer;
+  todo = count;
+
+  while ( todo > 0 ) {
+    rtems_interrupt_lock_context lock_context;
+    size_t                       junk;
+    size_t                       head;
+    size_t                       i;
+
+    rtems_interrupt_lock_acquire( &cons->buf_lock, &lock_context );
+
+    junk = _Console_simple_task_Capacity( cons );
+
+    if ( junk > todo ) {
+      junk = todo;
+    }
+
+    if ( junk > CONSOLE_SIMPLE_TASK_MAX_JUNK_SIZE ) {
+      junk = CONSOLE_SIMPLE_TASK_MAX_JUNK_SIZE;
+    }
+
+    head = cons->head;
+
+    for ( i = 0; i < junk; ++i ) {
+      cons->buf[ head ] = *buf;
+      head = ( head + 1 ) % CONSOLE_SIMPLE_TASK_BUFFER_SIZE;
+      --todo;
+      ++buf;
+    }
+
+    cons->head = head;
+
+    rtems_interrupt_lock_release( &cons->buf_lock, &lock_context );
+
+    if ( junk == 0 ) {
+      break;
+    }
+  }
+
+  rtems_event_system_send( cons->task, RTEMS_EVENT_SYSTEM_SERVER );
+
+  return (ssize_t) ( count - todo );
+}
+
+static void _Console_simple_task_Put_chars( Console_simple_task_Control *cons )
+{
+  rtems_interrupt_lock_context lock_context;
+  size_t                       available;
+  size_t                       tail;
+  size_t                       i;
+
+  rtems_mutex_lock( &cons->output_mutex );
+
+  rtems_interrupt_lock_acquire( &cons->buf_lock, &lock_context );
+
+  available = _Console_simple_task_Available( cons );
+  tail = cons->tail;
+
+  rtems_interrupt_lock_release( &cons->buf_lock, &lock_context );
+
+  for ( i = 0; i < available; ++i) {
+    rtems_putc( cons->buf[ tail ] );
+    tail = ( tail + 1 ) % CONSOLE_SIMPLE_TASK_BUFFER_SIZE;
+  }
+
+  rtems_interrupt_lock_acquire( &cons->buf_lock, &lock_context );
+
+  cons->tail = tail;
+
+  rtems_interrupt_lock_release( &cons->buf_lock, &lock_context );
+
+  rtems_mutex_unlock( &cons->output_mutex );
+}
+
+static int _Console_simple_task_Fsync( rtems_libio_t *iop )
+{
+  Console_simple_task_Control *cons;
+
+  cons = IMFS_generic_get_context_by_iop( iop );
+  _Console_simple_task_Put_chars( cons );
+}
+
+static const rtems_filesystem_file_handlers_r _Console_simple_task_Handlers = {
+  .open_h = rtems_filesystem_default_open,
+  .close_h = rtems_filesystem_default_close,
+  .read_h = _Console_simple_Read,
+  .write_h = _Console_simple_task_Write,
+  .ioctl_h = rtems_filesystem_default_ioctl,
+  .lseek_h = rtems_filesystem_default_lseek,
+  .fstat_h = IMFS_stat,
+  .ftruncate_h = rtems_filesystem_default_ftruncate,
+  .fsync_h = _Console_simple_task_Fsync,
+  .fdatasync_h = _Console_simple_task_Fsync,
+  .fcntl_h = rtems_filesystem_default_fcntl,
+  .readv_h = rtems_filesystem_default_readv,
+  .writev_h = rtems_filesystem_default_writev,
+  .mmap_h = rtems_filesystem_default_mmap
+};
+
+static const IMFS_node_control
+_Console_simple_task_Node_control = IMFS_GENERIC_INITIALIZER(
+  &_Console_simple_task_Handlers,
+  IMFS_node_initialize_generic,
+  IMFS_node_destroy_default
+);
+
+static void _Console_simple_task_Task( rtems_task_argument arg )
+{
+  Console_simple_task_Control *cons;
+
+  cons = (Console_simple_task_Control *) arg;
+
+  while ( true ) {
+    rtems_event_set events;
+
+    rtems_event_system_receive(
+      RTEMS_EVENT_SYSTEM_SERVER,
+      RTEMS_WAIT | RTEMS_EVENT_ALL,
+      RTEMS_NO_TIMEOUT,
+      &events
+    );
+
+    _Console_simple_task_Put_chars( cons );
+  }
+}
+
+void _Console_simple_task_Initialize( void )
+{
+  Console_simple_task_Control *cons;
+
+  cons = &_Console_simple_task_Instance;
+
+  rtems_interrupt_lock_initialize( &cons->buf_lock, "Console" );
+  rtems_mutex_init( &cons->output_mutex, "Console" );
+
+  IMFS_make_generic_node(
+    CONSOLE_DEVICE_NAME,
+    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
+    &_Console_simple_task_Node_control,
+    cons
+  );
+
+  rtems_task_create(
+    rtems_build_name('C', 'O', 'N', 'S'),
+    RTEMS_MAXIMUM_PRIORITY - 1,
+    RTEMS_MINIMUM_STACK_SIZE,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    RTEMS_DEFAULT_MODES,
+    &cons->task
+  );
+
+  rtems_task_start(
+    cons->task,
+    _Console_simple_task_Task,
+    (rtems_task_argument) cons
+  );
+}
diff --git a/testsuites/ada/sptests/sp20/config.h b/testsuites/ada/sptests/sp20/config.h
index f509a8163d..55990e2218 100644
--- a/testsuites/ada/sptests/sp20/config.h
+++ b/testsuites/ada/sptests/sp20/config.h
@@ -13,10 +13,10 @@
 
 /* configuration information */
 
-#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_TASK_CONSOLE_DRIVER
 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
 
-#define CONFIGURE_MAXIMUM_TASKS               7
+#define CONFIGURE_MAXIMUM_TASKS               8
 
 #define ADA_TEST_NAME "ADA SP 20"
 #define CONFIGURE_MAXIMUM_PERIODS             10
diff --git a/testsuites/ada/support/init.c b/testsuites/ada/support/init.c
index 413e52e1eb..c9a2327360 100644
--- a/testsuites/ada/support/init.c
+++ b/testsuites/ada/support/init.c
@@ -64,6 +64,7 @@ void ada_test_begin(void)
 
 void ada_test_end(void)
 {
+  fsync(STDOUT_FILENO);
   rtems_test_end(rtems_test_name);
 }
 
diff --git a/testsuites/sptests/sp20/init.c b/testsuites/sptests/sp20/init.c
index 65d32c9967..cace8c945d 100644
--- a/testsuites/sptests/sp20/init.c
+++ b/testsuites/sptests/sp20/init.c
@@ -28,18 +28,10 @@
 
 const char rtems_test_name[] = "SP 20";
 
-#define BUFFER_COUNT 16
-
-#define BUFFER_SIZE 512
-
-static rtems_printer_task_context printer_task;
-
-static long buffers[ BUFFER_COUNT ][ BUFFER_SIZE / sizeof(long) ];
-
 void end_of_test( void )
 {
   TEST_END();
-  rtems_printer_task_drain( &printer_task );
+  fsync(STDOUT_FILENO);
   rtems_test_exit( 0 );
 }
 
@@ -51,14 +43,7 @@ rtems_task Init(
   uint32_t          index;
   rtems_status_code status;
 
-  rtems_printer_task_set_priority( &printer_task, 254 );
-  rtems_printer_task_set_file_descriptor( &printer_task, 1 );
-  rtems_printer_task_set_buffer_table( &printer_task, &buffers[ 0 ][ 0 ] );
-  rtems_printer_task_set_buffer_count( &printer_task, BUFFER_COUNT );
-  rtems_printer_task_set_buffer_size( &printer_task, BUFFER_SIZE );
-  error = rtems_print_printer_task( &rtems_test_printer, &printer_task );
-  rtems_test_assert( error == 0 );
-
+  rtems_print_printer_fprintf(&rtems_test_printer, stdout);
   TEST_BEGIN();
 
   Task_name[ 1 ] =  rtems_build_name( 'T', 'A', '1', ' ' );
diff --git a/testsuites/sptests/sp20/system.h b/testsuites/sptests/sp20/system.h
index 6c5f679d72..26e837a45b 100644
--- a/testsuites/sptests/sp20/system.h
+++ b/testsuites/sptests/sp20/system.h
@@ -33,7 +33,7 @@ void Get_all_counters( void );
 
 /* configuration information */
 
-#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_TASK_CONSOLE_DRIVER
 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
 
 #define CONFIGURE_MICROSECONDS_PER_TICK 100000
-- 
2.12.3



More information about the devel mailing list