printf through uart

The way I got printf (and all other console-oriented stdio functions) to work was by creating custom implementations of the low-level I/O functions like _read() and _write().
The GCC C library makes calls to the following functions to perform low-level I/O :
int _read(int file, char *data, int len) int _write(int file, char *data, int len) int _close(int file) int _lseek(int file, int ptr, int dir) int _fstat(int file, struct stat *st) int _isatty(int file)
int _read(int file, char *data, int len)
int _write(int file, char *data, int len)
int _close(int file)
int _lseek(int file, int ptr, int dir)
int _fstat(int file, struct stat *st)
int _isatty(int file)
These functions are implemented witihin the GCC C library as stub routines with “weak” linkage. If a declaration of any of the above functions appears in your own code, your substitute routine will override the declaration in the library and be used instead of the default (non-functional) routine.
I have copied my implementations of these functions below. You will need to substitute the calls to UART_TxBlocking() and UART_RxBlocking() with calls to whatever functions you have created that do U(S)ART I/O.
#ifdef __GCC__ #include <errno.h> #include <stdio.h> #include <sys/stat.h> #include <sys/unistd.h> #include "stdio_helper_gcc.h" #include "UART.h" #undef errno extern int errno; /****************************************************************************** * ******************************************************************************/ void stdio_setup(int no_init) { if (! no_init) { UART_Init(0); } // Turn off buffers, so I/O occurs immediately setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); } /****************************************************************************** * ******************************************************************************/ 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) UART_RxBlocking(); data++; } return bytes_read; } /****************************************************************************** * ******************************************************************************/ int _write(int file, char *data, int len) { int bytes_written; if ((file != STDOUT_FILENO) && (file != STDERR_FILENO)) { errno = EBADF; return -1; } for (bytes_written = 0; bytes_written < len; bytes_written++) { UART_TxBlocking(*data); data++; } return bytes_written; } /****************************************************************************** * ******************************************************************************/ int _close(int file) { return -1; } /****************************************************************************** * ******************************************************************************/ int _lseek(int file, int ptr, int dir) { return 0; } /****************************************************************************** * ******************************************************************************/ int _fstat(int file, struct stat *st) { st->st_mode = S_IFCHR; return 0; } /****************************************************************************** * ******************************************************************************/ int _isatty(int file) { if ((file == STDOUT_FILENO) || (file == STDIN_FILENO) || (file == STDERR_FILENO)) { return 1; } errno = EBADF; return 0; } #endif
#ifdef __GCC__
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#include "stdio_helper_gcc.h"
#include "UART.h"
#undef errno
extern int errno;
/******************************************************************************
*
******************************************************************************/
void stdio_setup(int no_init)
{
if (! no_init)
{
UART_Init(0);
}
// Turn off buffers, so I/O occurs immediately
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
}
/******************************************************************************
*
******************************************************************************/
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) UART_RxBlocking();
data++;
}
return bytes_read;
}
/******************************************************************************
*
******************************************************************************/
int _write(int file, char *data, int len)
{
int bytes_written;
if ((file != STDOUT_FILENO) && (file != STDERR_FILENO))
{
errno = EBADF;
return -1;
}
for (bytes_written = 0; bytes_written < len; bytes_written++)
{
UART_TxBlocking(*data);
data++;
}
return bytes_written;
}
/******************************************************************************
*
******************************************************************************/
int _close(int file)
{
return -1;
}
/******************************************************************************
*
******************************************************************************/
int _lseek(int file, int ptr, int dir)
{
return 0;
}
/******************************************************************************
*
******************************************************************************/
int _fstat(int file, struct stat *st)
{
st->st_mode = S_IFCHR;
return 0;
}
/******************************************************************************
*
******************************************************************************/
int _isatty(int file)
{
if ((file == STDOUT_FILENO) ||
(file == STDIN_FILENO) ||
(file == STDERR_FILENO))
{
return 1;
}
errno = EBADF;
return 0;
}
#endif