Add a simple task console driver

Close #3320.
This commit is contained in:
Sebastian Huber
2018-02-21 12:40:18 +01:00
parent 4899759f73
commit 337a186909
11 changed files with 319 additions and 51 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2018 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@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
);

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2017 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@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;
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2018 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@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
);
}

View File

@@ -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

View File

@@ -64,6 +64,7 @@ void ada_test_begin(void)
void ada_test_end(void)
{
fsync(STDOUT_FILENO);
rtems_test_end(rtems_test_name);
}

View File

@@ -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', ' ' );

View File

@@ -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