Difference between revisions of "Embedded Studio Library IO"

From SEGGER Wiki
Jump to: navigation, search
(RTT)
Line 26: Line 26:
 
SEGGER Embedded Studio provides RTT <code>printf();</code> functionality automatically.
 
SEGGER Embedded Studio provides RTT <code>printf();</code> functionality automatically.
   
To use the full RTT API, the RTT Target Package needs to be added to the Embedded Studio project: [https://wiki.segger.com/Embedded_Studio/ RTT in Embedded Studio]
+
To use the full RTT API, the RTT Target Package needs to be added to the Embedded Studio project: [https://wiki.segger.com/RTT_in_Embedded_Studio RTT in Embedded Studio]
   
 
=== SWO ===
 
=== SWO ===

Revision as of 15:43, 1 March 2022

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.

Note: Embedded Studio versions prior to V6 included two versions of the runtime library: The legacy "Embedded Studio Runtime Library" and the "SEGGER Runtime Library". This article is about the SEGGER Runtime Library, which is used by Embedded Studio V6 and most projects created with Embedded Stduio V5.50 or later.

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.

Note: Older projects might include SEGGER_RTT_Syscalls_SES.c or a similar file to override printf(). When using the SEGGER Runtime Library, this file should be removed from the project, or its content should be encapsulated with #if !defined(__SEGGER_RTL_VERSION) ... #endif

SEGGER Embedded Studio provides RTT printf(); functionality automatically.

To use the full RTT API, the RTT Target Package needs to be added to the Embedded Studio project: RTT in Embedded Studio

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.12 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.

A Embedded Studio project for the emPower board that exposes I/O of a UART port can be downloaded here: File:RTL-UART-IO.zip

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 ****************************/