Loading...
 

SW4STM32 and SW4Linux fully supports the STM32MP1 asymmetric multicore Cortex/A7+M4 MPUs

   With System Workbench for Linux, Embedded Linux on the STM32MP1 family of MPUs from ST was never as simple to build and maintain, even for newcomers in the Linux world.
And, if you install System Workbench for Linux in System Workbench for STM32 you can seamlessly develop and debug asymmetric applications running partly on Linux, partly on the Cortex-M4.
You can get more information from the ac6-tools website and download two short videos (registration required) highlighting:

System Workbench for STM32


You are viewing a reply to Retargeting getchar() function  

Retargeting getchar() function

To make stdio functions like getchar() and printf() to work with your specific peripheral, you need to create custom versions of specific interface functions that are normally defined as no-op stubs by GCC’s runtime library.

I wish there was a way that I could attach a source file to a message. I have a complete implementation that uses a custom-written USART libaray (not ST’s HAL) that could be easily adapted (I think) to use ST HAL functions. I’ll copy it here, although with comments it’s kinda long. Hope this does not bug anyone.

Note that for the _write() function implementation, I’ve added some code to translate the ‘\v’ (vertical tab) control character into a “conditional newline”. Without this code, the _write() function implementation would be a lot simpler - just an if() enclosing a call to a single-character-out function.

There’s a few other things in here that are specific to my platform and usage that I extracted this code segment from. Hopefully those things won’t be too distracting. What is shown below is a stand-alone “library” source file (which also has a very simple accompanying .h file, not shown here) that you’d just add to your source project directory.

#include "errno.h"
#include "stdio.h"
#include "sys/stat.h"
#include "sys/unistd.h"
#include "stdio_helper_gcc.h"
#include "USART.h"

#undef errno
extern int errno;

/******************************************************************************
 * void stdio_setup()
 *
 * Perform any necessary or desired setup and/or hook-up outside of that which
 * is done by the stdio library interfacing routines (e.g. _read(), _write(),
 * etc.) needed to get stdio and the target device(s) to work optimally.
 *
 * For this target, setup is limited to turning stdio I/O buffering off for the
 * default I/O channels, so I/O operations done to them are passed to the
 * target I/O on a character-by-character basis. This means, for example, that
 * when a single character is output via putchar(), it will be transmitted to
 * the debug port immediately; it will not be locally buffered until a EOL
 * character is sent.
 *
 * This routine could also (optionally) include code that initializes and
 * configures the device(s) on the target to be used for stdio.
 * This initialization is presently being done outside of this routine.
 ******************************************************************************/

void stdio_setup(void)
{
    // Initialize "default" USART if it has not been done already

    if (! USART_Initialized(USART_NUMBER))
    {
        USART_Init(USART_NUMBER, USART_BAUDRATE, USART_RX_BUFSIZE, USART_TX_BUFSIZE);
    }

    // Turn off buffers, so I/O occurs immediately
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stderr, NULL, _IONBF, 0);
}

/******************************************************************************
 * Notes concerning the functions defined below:
 *
 * These implementations replace "weak" stub implementations in GCC libc.
 * Parameters accepted and return types and values are dictated by what is
 * expected by libc and stdio, which is the only entity that should be calling
 * these routines.
 *
 * For the STM32 implementation, only I/O to the default file handles stdin,
 * stdout and stderr is supported. Input and output to the standard file handles
 * is directed to the U(S)ART designated for debug I/O.
 ******************************************************************************/

/******************************************************************************
 * int read(file, *data, len)
 *
 * Target-specific implementation of the stdio _read() function.
 * Reads data from devices on the target.
 *
 * file         File or device ID to read from
 * *data        Pointer to buffer where data read from the selected device
 *              is stored
 * len          Number of bytes to read from device
 *
 * Returns: Number of bytes read, or stdio error code
 ******************************************************************************/

int _read(int file, char *data, int len)
{
    int bytes_read;

    if (file != STDIN_FILENO)
    {
        errno = EBADF;
        return -1;
    }

    for (bytes_read = 0; bytes_read < len; bytes_read++)
    {
        *data = (char) USART_RxBlocking(USART_NUMBER);
        data++;
    }

    return bytes_read;
}

/******************************************************************************
 * int _write(file, *data, len)
 *
 * Target-specific implementation of the stdio _write() function.
 * Writes data to devices on the target.
 *
 * file         File or device ID to write to
 * *data        Pointer to buffer where data to be written is stored
 * len          Number of bytes to write to the device
 *
 * Returns: Number of bytes actually written, or stdio error code
 ******************************************************************************/

int _write(int file, char *data, int len)
{
    static unsigned int char_count;
    int bytes_written;
    char ch;

    if ((file != STDOUT_FILENO) && (file != STDERR_FILENO))
    {
        errno = EBADF;
        return -1;
    }

    for (bytes_written = 0; bytes_written < len; bytes_written++)
    {
        ch = *data;
        data++;

        // Translate the vertical tab char '\v' into a "conditional newline"
        // Sending '\v' will generate a \r\n (CR/LF) if the previous character
        // sent was printable (not a control char); i.e. Advance to a new line
        // if the cursor is not at the start of a new line.

        if (ch == '\v')
        {
            if (char_count > 0)
            {
                USART_TxBlocking(USART_NUMBER, '\r');
                USART_TxBlocking(USART_NUMBER, '\n');
                char_count = 0;
            }
        }
        else
        {
            USART_TxBlocking(USART_NUMBER, ch);
            if (ch >= ' ')
            {
                char_count++;
            }
            else if (ch == '\r')
            {
                char_count = 0;
            }
        }
    }

    return bytes_written;
}

/******************************************************************************
 * int _close(file)
 *
 * Target-specific implementation of the stdio file _close() function.
 *
 * Not used in this application.
 ******************************************************************************/

int _close(int file)
{
    return -1;
}

/******************************************************************************
 * int _lseek(file)
 *
 * Target-specific implementation of the stdio _lseek() (file seek) function.
 *
 * Not used in this application.
 ******************************************************************************/

int _lseek(int file, int ptr, int dir)
{
    return 0;
}

/******************************************************************************
 * int _fstat(file, *st)
 *
 * Target-specific implementation of the stdio _fstat (file status) function.
 *
 * Implemented minimally on this target, always returns status indicating that
 * the file/device is a "character" type.
 ******************************************************************************/

int _fstat(int file, struct stat *st)
{
    st->st_mode = S_IFCHR;
    return 0;
}

/******************************************************************************
 * int _isatty(file)
 *
 * Target-specific implementation of the stdio _isatty() function.
 *
 * Returns a nonzero value if the specified <file> is a "tty" style device; that
 * is, a display terminal or similar user-interactive device.
 *
 * For this target, it always returns a nonzero/true result for the
 * STDIN/STDOUT/STDERR devices.
 ******************************************************************************/

int _isatty(int file)
{
    if ((file == STDOUT_FILENO) ||
        (file == STDIN_FILENO) ||
        (file == STDERR_FILENO))
    {
        return 1;
    }

    errno = EBADF;
    return 0;
}