Embedded Studio Library IO

From SEGGER Wiki
Revision as of 14:17, 26 January 2022 by DavidP (talk | contribs)
Jump to: navigation, search

The debugger and the Runtime Library of Embedded Studio support different mechanisms for debug input and output. The mechanism to be used in a project can easily be selected in the project options at Library -> Library I/O and does not require any additional file or configuration.

Library I/O Mechanisms

There are different mechanisms for different application requirements.

RTT

Use SEGGER Real-Time Transfer (RTT), which enables super fast output without halting the system. The target application writes the output string to a buffer in RAM. The J-Link reads the buffer while the target is running.

Suitable for applications with real-time requirements.

Available on all Cortex-M based systems.

SWO

The target application writes the output string to the ITM stimulus ports. The J-Link reads the SWO pin while the target is running.

Suitable for applications with real-time requirements.

Available on all Cortex-M based systems with a SWO pin.

SEMIHOST

Halt the target CPU for I/O operations. On halt, the debugger reads and executes the operation command and parameters.

Available on all targets (Cortex-M, Cortex-A, Cortex-R, RISC-V)

SEMIHOST host-formatted

With host formatting printf output is processed by the debugger instead of on the target. The debugger reads the format string and the parameters from the target and feeds it to its formatter to be printed. No code for formatting is required on the target, saving 1 - 3 kiloBytes of ROM.

Recommended for minimum size.

None

No I/O mechanism implemented. Use user-supplied I/O mechanisms, such as output on a UART.

User-supplied I/O

Note: This section applies to Embedded Studio V6.10 and later.

When no standard I/O mechanism is implemented, the user can supply an implementation of the low-level routines to do output and optionally input.

The functions to be implemented are:

 int __SEGGER_RTL_X_file_stat(__SEGGER_RTL_FILE *stream);                                // Get file status.               >= 0: OK. < 0: Invalid file stream.
 int __SEGGER_RTL_X_file_bufsize(__SEGGER_RTL_FILE *stream);                             // Get stream buffer size.        == 1: Unbuffered I/O. > 1: Size of buffer.
 int __SEGGER_RTL_X_file_read(__SEGGER_RTL_FILE * stream, char * s, unsigned len);       // Read data from file stream.    >= 0: OK. < 0: Failed to read.
 int __SEGGER_RTL_X_file_write(__SEGGER_RTL_FILE *stream, const char *s, unsigned len);  // Write data to file stream.     >= 0: OK. < 0: Error.
 int __SEGGER_RTL_X_file_unget(__SEGGER_RTL_FILE *stream, int c);                        // Push character back to stream. >= 0: OK. < 0: Error.


The default implementations are:

 int __SEGGER_RTL_X_file_stat(__SEGGER_RTL_FILE *stream) {
   return 0;  // Assume only stdout/stdin/stderr is used and always valid.
 }
 int __SEGGER_RTL_X_file_bufsize(__SEGGER_RTL_FILE *stream) {
   return 1; // 1 for unbuffered I/O. Otherwise 80.
 }
 int __SEGGER_RTL_X_file_read(__SEGGER_RTL_FILE * stream, char * s, unsigned len) {
   return EOF; // Read not implemented
 }
 int __SEGGER_RTL_X_file_write(__SEGGER_RTL_FILE *stream, const char *s, unsigned len) {
   while (len > 0) {
     UART_SendByte(*s++); // Output any stream to UART.
     --len;
   }
   return 0;
 }
 int __SEGGER_RTL_X_file_unget(__SEGGER_RTL_FILE *stream, int c) {
   return EOF; // Unget not implemented.
 }

A Embedded Studio project for the emPower board that exposes I/O of a UART port can be downloaded here: (FIXME)

A minimal implementation of the I/O functions could look like the below:


 /*********************************************************************
 *                   (c) SEGGER Microcontroller GmbH                  *
 *                        The Embedded Experts                        *
 *                           www.segger.com                           *
 **********************************************************************
 
 -------------------------- END-OF-HEADER -----------------------------
 Purpose : Implementation of low-level functions for I/O with the
           SEGGER Runtime Library
           using a UART (SEGGER's BSP UART module)
 */
 
 /*********************************************************************
 *
 *       #include section
 *
 **********************************************************************
 */
 
 #include "__SEGGER_RTL_Int.h"
 #include "stdio.h"
 #include "BSP_UART.h"
 
 /*********************************************************************
 *
 *       Prototypes
 *
 **********************************************************************
 */
 void RTL_UART_Init(unsigned int Unit, unsigned long Baudrate, unsigned char NumDataBits, unsigned char Parity, unsigned char NumStopBits);
 
 /*********************************************************************
 *
 *       Local types
 *
 **********************************************************************
 */
 
 struct __SEGGER_RTL_FILE_impl {         // NOTE: Provides implementation for FILE
   int stub; // only needed so impl has size != 0.
 };
 
 /*********************************************************************
 *
 *       Static data
 *
 **********************************************************************
 */
 
 static FILE __SEGGER_RTL_stdin_file  = { 0 };  // stdin reads from UART
 static FILE __SEGGER_RTL_stdout_file = { 0 };  // stdout writes to UART
 static FILE __SEGGER_RTL_stderr_file = { 0 };  // stderr writes to UART
 
 static unsigned int _UART_Port    = 0;
 static int          _stdin_ungot  = EOF;
 
 /*********************************************************************
 *
 *       Public data
 *
 **********************************************************************
 */
 
 FILE *stdin  = &__SEGGER_RTL_stdin_file;  // NOTE: Provide implementation of stdin for RTL.
 FILE *stdout = &__SEGGER_RTL_stdout_file; // NOTE: Provide implementation of stdout for RTL.
 FILE *stderr = &__SEGGER_RTL_stderr_file; // NOTE: Provide implementation of stderr for RTL.
 
 /*********************************************************************
 *
 *       Static code
 *
 **********************************************************************
 */
 
 /*********************************************************************
 *
 *       _stdin_getc()
 *
 *  Function description
 *    Get character from standard input.
 *
 *  Return value
 *    Character received.
 *
 *  Additional information
 *    This function never fails to deliver a character.
 */
 static char _stdin_getc(void) {
   unsigned char c;
 
   if (_stdin_ungot != EOF) {
     c = _stdin_ungot;
     _stdin_ungot = EOF;
   } else {
     BSP_UART_ReadBlocking(_UART_Port, &c, sizeof(c));
   }
   return c;
 }
 
 /*********************************************************************
 *
 *       Public code
 *
 **********************************************************************
 */
 
 /*********************************************************************
 *
 *       RTL_UART_Init()
 *
 *  Function description
 *    Initialize RTL to use given UART for stdio.
 *
 *  Parameters
 *    Unit       : UART unit number (typically zero-based).
 *    Baudrate   : Baud rate to configure [Hz].
 *    NumDataBits: Number of data bits to use.
 *    Parity     : One of the following values:
 *                   * BSP_UART_PARITY_NONE
 *                   * BSP_UART_PARITY_ODD
 *                   * BSP_UART_PARITY_EVEN
 *    NumStopBits: Number of stop bits to use.
 *
 *  Additional description
 *    Parameters are same as for BSP_UART_Init().
 *    This also sets appropriate RX and TX interrupt handlers.
 */
 void RTL_UART_Init(unsigned int Unit, unsigned long Baudrate, unsigned char NumDataBits, unsigned char Parity, unsigned char NumStopBits) {
   _UART_Port = Unit;
   BSP_UART_Init(_UART_Port, Baudrate, NumDataBits, Parity, NumStopBits);
 }
 
 /*********************************************************************
 *
 *       __SEGGER_RTL_X_file_stat()
 *
 *  Function description
 *    Get file status.
 *
 *  Parameters
 *    stream - Pointer to file.
 *
 *  Additional information
 *    Low-overhead test to determine if stream is valid.  If stream
 *    is a valid pointer and the stream is open, this function must
 *    succeed.  If stream is a valid pointer and the stream is closed,
 *    this function must fail.
 *
 *    The implementation may optionally determine whether stream is
 *    a valid pointer: this may not always be possible and is not
 *    required, but may assist debugging when clients provide wild
 *    pointers.
 *
 *  Return value
 *    <  0 - Failure, stream is not a valid file.
 *    >= 0 - Success, stream is a valid file.
 */
 int __SEGGER_RTL_X_file_stat(FILE *stream) {
   if (stream == stdin || stream == stdout || stream == stderr) {
     return 0;       // NOTE: stdin, stdout, and stderr are assumed to be valid.
   } else {
     return EOF;
   }
 }
 
 /*********************************************************************
 *
 *       __SEGGER_RTL_X_file_bufsize()
 *
 *  Function description
 *    Get stream buffer size.
 *
 *  Parameters
 *    stream - Pointer to file.
 *
 *  Additional information
 *    Returns the number of characters to use for buffered I/O on
 *    the file stream.  The I/O buffer is allocated on the stack
 *    for the duration of the I/O call, therefore this value should
 *    not be set arbitrarily large.
 *
 *    For unbuffered I/O, return 1.
 *
 *  Return value
 *    Nonzero number of characters to use for buffered I/O; for
 *    unbuffered I/O, return 1.
 */
 int __SEGGER_RTL_X_file_bufsize(FILE *stream) {
   (void)stream;
   return 1;
 }
 
 /*********************************************************************
 *
 *       __SEGGER_RTL_X_file_read()
 *
 *  Function description
 *    Read data from file.
 *
 *  Parameters
 *    stream - Pointer to file to read from.
 *    s      - Pointer to object that receives the input.
 *    len    - Number of characters to read from file.
 *
 *  Return value
 *    >= 0 - Success, amount of data read.
 *    <  0 - Failure.
 *
 *  Additional information
 *    Reading from any stream other than stdin results in an error.
 */
 int __SEGGER_RTL_X_file_read(FILE *stream, char *s, unsigned len) {
   int c;
 
   if (stream == stdin) {
     c = 0;
     while (len > 0) {
       *s = _stdin_getc();
       ++s;
       ++c;
       --len;
     }
   } else {
     c = EOF;
   }
   return c;
 }
 
 /*********************************************************************
 *
 *       __SEGGER_RTL_X_file_write()
 *
 *  Function description
 *    Write data to file.
 *
 *  Parameters
 *    stream - Pointer to file to write to.
 *    s      - Pointer to object to write to file.
 *    len    - Number of characters to write to the file.
 *
 *  Return value
 *    >= 0 - Success.
 *    <  0 - Failure.
 *
 *  Additional information
 *    this version is NOT reentrant!
 *    stdout and stderr are directed to UART;
 *    writing to any stream other than stdout or stderr results in an error
 */
 int __SEGGER_RTL_X_file_write(FILE *stream, const char *s, unsigned len) {
   if ((stream == stdout) || (stream == stderr)) {
     BSP_UART_WriteBlocking(_UART_Port, (const unsigned char*) s, len);
     return len;
   } else {
     return EOF;
   }
 }
 
 /*********************************************************************
 *
 *       __SEGGER_RTL_X_file_unget()
 *
 *  Function description
 *    Push character back to stream.
 *
 *  Parameters
 *    stream - Pointer to file to push back to.
 *    c      - Character to push back.
 *
 *  Return value
 *    >= 0 - Success.
 *    <  0 - Failure.
 *
 *  Additional information
 *    Push-back is only supported for standard input, and
 *    only a single-character pushback buffer is implemented.
 */
 int __SEGGER_RTL_X_file_unget(FILE *stream, int c) {
   if (stream == stdin) {
     if (c != EOF && _stdin_ungot == EOF) {
       _stdin_ungot = c;
     } else {
       c = EOF;
     }
   } else {
     c = EOF;
   }
   return c;
 }
 
 /*************************** End of file ****************************/