Make the kernel I/O output character device processing configurable through an option set parameter. Add RTEMS_IO_NO_OUTPUT and RTEMS_IO_DRAIN options. The goal of this API change is to enable draining the kernel output device in the system termination process before a reset is issued. A use case for using RTEMS_NO_WAIT is the polled processing of an input and output stream from and to the I/O device. --- v2:
* Do not use EARS. * Rename RTEMS_FLUSH in RTEMS_IO_DRAIN. * Rename RTEMS_NO_OUTPUT in RTEMS_IO_NO_TRANSMISSION. * Add example adoption for sparc/leon3. bsps/sparc/leon3/console/printk_support.c | 54 +++++++++++++++++++--- cpukit/include/rtems/bspIo.h | 55 ++++++++++++++++++++++- cpukit/include/rtems/rtems/options.h | 22 ++++++++- cpukit/libcsupport/src/rtems_putc.c | 4 +- testsuites/validation/tc-io-put-char.c | 8 +++- testsuites/validation/tr-io-kernel.c | 4 +- 6 files changed, 132 insertions(+), 15 deletions(-) diff --git a/bsps/sparc/leon3/console/printk_support.c b/bsps/sparc/leon3/console/printk_support.c index fd23a5033f..adfd653060 100644 --- a/bsps/sparc/leon3/console/printk_support.c +++ b/bsps/sparc/leon3/console/printk_support.c @@ -43,6 +43,7 @@ #include <bsp/leon3.h> #include <rtems/bspIo.h> #include <rtems/sysinit.h> +#include <rtems/dev/io.h> #include <grlib/apbuart.h> #include <grlib/io.h> @@ -56,6 +57,11 @@ apbuart *leon3_debug_uart = NULL; static void bsp_debug_uart_init(void); +static bool apbuart_can_transmit(apbuart *regs) +{ + return (grlib_load_32(®s->status) & APBUART_STATUS_TE) != 0; +} + static void apbuart_enable_receive_and_transmit(apbuart *regs) { uint32_t ctrl; @@ -66,10 +72,38 @@ static void apbuart_enable_receive_and_transmit(apbuart *regs) grlib_store_32(®s->status, 0); } -static void bsp_debug_uart_output_char(char c) +static rtems_status_code bsp_debug_uart_output_char( + char c, + rtems_option option_set +) { - apbuart_outbyte_polled(leon3_debug_uart, c); - apbuart_outbyte_wait(leon3_debug_uart); + apbuart *regs = leon3_debug_uart; + rtems_status_code status = RTEMS_SUCCESSFUL; + + while (true) { + if (apbuart_can_transmit(regs)) { + if ((option_set & RTEMS_IO_NO_TRANSMISSION) == 0) { + grlib_store_32(®s->data, (uint8_t) c); + } + + break; + } + + if ((option_set & RTEMS_NO_WAIT) != 0) { + status = RTEMS_UNSATISFIED; + break; + } + + _IO_Relax(); + } + + if ((option_set & RTEMS_IO_DRAIN) != 0) { + while (!apbuart_can_transmit(regs)) { + _IO_Relax(); + } + } + + return status; } static int bsp_debug_uart_poll_char(void) @@ -77,10 +111,13 @@ static int bsp_debug_uart_poll_char(void) return apbuart_inbyte_nonblocking(leon3_debug_uart); } -static void bsp_debug_uart_pre_init_out(char c) +static rtems_status_code bsp_debug_uart_pre_init_out( + char c, + rtems_option option_set +) { bsp_debug_uart_init(); - (*BSP_output_char)(c); + return (*BSP_output_char)(c, option_set); } #if defined(LEON3_APBUART_BASE) @@ -94,9 +131,14 @@ static void bsp_debug_uart_init(void) #else /* !LEON3_APBUART_BASE */ -static void bsp_debug_uart_discard(char c) +static rtems_status_code bsp_debug_uart_discard( + char c, + rtems_option option_set +) { (void) c; + (void) option_set; + return RTEMS_SUCCESSFUL; } /* Initialize the BSP system debug console layer. It will scan AMBA Plu&Play diff --git a/cpukit/include/rtems/bspIo.h b/cpukit/include/rtems/bspIo.h index 31580cd800..7848704992 100644 --- a/cpukit/include/rtems/bspIo.h +++ b/cpukit/include/rtems/bspIo.h @@ -10,7 +10,7 @@ */ /* - * Copyright (C) 2020, 2021 embedded brains GmbH & Co. KG + * Copyright (C) 2020, 2024 embedded brains GmbH & Co. KG * Copyright (C) 2015 On-Line Applications Research Corporation (OAR) * * Redistribution and use in source and binary forms, with or without @@ -58,6 +58,8 @@ #define _RTEMS_BSPIO_H #include <stdarg.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/status.h> #include <rtems/score/basedefs.h> #ifdef __cplusplus @@ -89,8 +91,48 @@ extern "C" { * @ingroup RTEMSAPIKernelCharIO * * @brief Polled character output functions shall have this type. + * + * @param out is the character to transmit. + * + * @param option_set is the option set. + * + * The behaviour of polled character output functions can be controlled by the + * three options #RTEMS_NO_WAIT, #RTEMS_IO_NO_TRANSMISSION, and #RTEMS_IO_DRAIN + * specified in the ``option_set`` parameter. + * + * If the #RTEMS_NO_WAIT option is set in the ``option_set`` parameter and the + * device cannot immediately accept a character for transmission, then the + * character in ``out`` shall not be transmitted by the device, optionally the + * device shall be drained, and ::RTEMS_UNSATISFIED shall be returned. + * + * If the #RTEMS_IO_NO_TRANSMISSION option is set in the ``option_set`` + * parameter, the character in the ``out`` parameter shall not be transmitted + * by the device. + * + * If the #RTEMS_NO_WAIT and #RTEMS_IO_NO_TRANSMISSION options are cleared in + * the ``option_set`` parameter, then the character in the ``out`` parameter + * shall transmitted by the device. + * + * If the #RTEMS_NO_WAIT option is set and the #RTEMS_IO_NO_TRANSMISSION option + * is cleared in the ``option_set`` parameter, and the device can immediately + * accept a character for transmission, then the character in ``out`` shall be + * transmitted by the device. + * + * If the #RTEMS_IO_DRAIN option is set in the ``option_set`` parameter, then + * the device shall be drained before the function returns. Draining the + * device should ensure that all characters in transmission are visible to + * external consumers. For example, the device transmit FIFO and transmit shift + * register should be empty. + * + * @retval ::RTEMS_SUCCESSFUL The requested operation was successful. + * + * @retval ::RTEMS_UNSATISFIED The device is was not immediately ready to + * transmit a character. */ -typedef void ( *BSP_output_char_function_type )( char ); +typedef rtems_status_code ( *BSP_output_char_function_type )( + char out, + rtems_option option_set +); /* Generated from spec:/rtems/io/if/bsp-output-char */ @@ -333,6 +375,15 @@ int rtems_printk_printer( void *unused, const char *fmt, va_list ap ); * @ingroup RTEMSAPIKernelCharIO * * @brief Polled character input functions shall have this type. + * + * If a character is available in the device, then a polled character input + * function shall return the least recently received character available in the + * device as an unsigned character, otherwise it shall return minus one. + * + * @retval -1 There was no received character available in the device. + * + * @return Returns the least recently received character available in the + * device as an unsigned character. */ typedef int (* BSP_polling_getchar_function_type )( void ); diff --git a/cpukit/include/rtems/rtems/options.h b/cpukit/include/rtems/rtems/options.h index 44a8d6ccb8..ca6d32639c 100644 --- a/cpukit/include/rtems/rtems/options.h +++ b/cpukit/include/rtems/rtems/options.h @@ -9,7 +9,7 @@ */ /* - * Copyright (C) 2020 embedded brains GmbH & Co. KG + * Copyright (C) 2020, 2024 embedded brains GmbH & Co. KG * Copyright (C) 1989, 2008 On-Line Applications Research Corporation (OAR) * * Redistribution and use in source and binary forms, with or without @@ -103,6 +103,26 @@ extern "C" { */ #define RTEMS_EVENT_ANY 0x00000002 +/* Generated from spec:/rtems/option/if/io-drain */ + +/** + * @ingroup RTEMSAPIClassicOptions + * + * @brief This option constant indicates that an output device shall be + * drained. + */ +#define RTEMS_IO_DRAIN 0x00000008 + +/* Generated from spec:/rtems/option/if/io-no-transmission */ + +/** + * @ingroup RTEMSAPIClassicOptions + * + * @brief This option constant indicates that nothing shall be transmitted by a + * device. + */ +#define RTEMS_IO_NO_TRANSMISSION 0x00000004 + /* Generated from spec:/rtems/option/if/no-wait */ /** diff --git a/cpukit/libcsupport/src/rtems_putc.c b/cpukit/libcsupport/src/rtems_putc.c index a9e84c0043..73bd6f1fb1 100644 --- a/cpukit/libcsupport/src/rtems_putc.c +++ b/cpukit/libcsupport/src/rtems_putc.c @@ -46,8 +46,8 @@ void rtems_putc( char c ) output_char = BSP_output_char; if ( c == '\n' ) { - ( *output_char )( '\r' ); + (void) ( *output_char )( '\r', RTEMS_DEFAULT_OPTIONS ); } - ( *output_char )( c ); + (void) ( *output_char )( c, RTEMS_DEFAULT_OPTIONS ); } diff --git a/testsuites/validation/tc-io-put-char.c b/testsuites/validation/tc-io-put-char.c index 671eed9835..7df8d7f3f2 100644 --- a/testsuites/validation/tc-io-put-char.c +++ b/testsuites/validation/tc-io-put-char.c @@ -159,16 +159,20 @@ static void Output( int value ) ++ctx->output_count; } -static void WrongOutput( char c ) +static rtems_status_code WrongOutput( char c, rtems_option option_set ) { (void) c; + (void) option_set; Output( -1 ); + return RTEMS_SUCCESSFUL; } -static void OutputChar( char c ) +static rtems_status_code OutputChar( char c, rtems_option option_set ) { + (void) option_set; BSP_output_char = WrongOutput; Output( (unsigned char) c ); + return RTEMS_SUCCESSFUL; } static void RtemsIoReqPutChar_Pre_Char_Prepare( diff --git a/testsuites/validation/tr-io-kernel.c b/testsuites/validation/tr-io-kernel.c index bbebfe5a26..99969776b6 100644 --- a/testsuites/validation/tr-io-kernel.c +++ b/testsuites/validation/tr-io-kernel.c @@ -83,9 +83,9 @@ static void RtemsIoValKernel_Action_0( void ) { T_report_hash_sha256_update( 'X' ); - ( *BSP_output_char )( 'X' ); + (void) ( *BSP_output_char )( 'X', RTEMS_DEFAULT_OPTIONS ); T_report_hash_sha256_update( '\n' ); - ( *BSP_output_char )( '\n' ); + (void) ( *BSP_output_char )( '\n', RTEMS_DEFAULT_OPTIONS ); } /** -- 2.35.3 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel