Stubs

Simon Pettersson simonpe@kth.se
Mon May 11 16:44:00 GMT 2009


Thanks for the reply Qiang,

According to the docs, open is not called for stdin,stdout and stderr.  
Anyway, I have narrowed down the problem and noticed that _read is  
called once (i run it in a while(1) loop).
The thing is that most of the time it will read 0 (zero) bytes since I  
am not sending anything to the UART, will newlib set some flag in its  
internal FILE struct for this file that makes it invalid to read from  
it, hence not invoking _read?

Simon

10 maj 2009 kl. 11.44 skrev Qiang Wang:

> hi,
> I have ported the newlib recently.
> I thing it is not the read or write problems.
> It may come from open.
> Have you opened the stdin, stdout, stderr correctly?
>
> wangqiang
>
>
> 2009/5/10 Simon Pettersson <simonpe@kth.se>:
>> I am using the Keil MCB2300 STK with an NXP LPC2378 cpu with the
>> arm-none-eabi toolkit from Code Sourcery.
>>
>> I started implementing the newlib stubs but ran into some problems.  
>> I wanted
>> the LCD row 0 to act as stdio and row 1 as stderr, moreover I  
>> wanted all
>> four USART to act as files.
>>
>> I can write to USART0 and USART1 with the following code but when I  
>> try to
>> read from them with fread my _read stub behaves weird. Essentially  
>> _read
>> never gets called, it seems like the fread returns 0 before  
>> invoking it.
>>
>> There is also a similar problem with printf(), here my _write stub  
>> never
>> gets called but _isatty does.
>>
>> I cannot find any documentation of what have to be done in the  
>> stubs for
>> newlibs implementations to work reliably, I hope someone can point  
>> me to
>> these documents.
>>
>> Please provide any input you might think is helpful as I have been  
>> stuck
>> with these problems for a long time now.
>>
>> Simon Pettersson
>>
>> Code attachment (please note that this code is nowhere complete, I  
>> just try
>> to get the basic stuff woring at the moment):
>>
>> #include <sys/types.h>
>> #include <sys/times.h>
>> #include "io.h"
>> #include "uart.h"
>>
>> // A pointer to a list of environment variables and their values.
>> char *__env[1] = { 0 };
>> char **environ = __env;
>>
>> // linker script sets heap start and end
>> extern unsigned int _HEAP_START;
>> extern unsigned int _HEAP_END;
>> static caddr_t heap = NULL;
>>
>> // low level bulk memory allocator - used by malloc
>> caddr_t _sbrk ( int increment ) {
>>        caddr_t prevHeap;
>>        caddr_t nextHeap;
>>        if (heap == NULL) {
>>                // first allocation
>>                heap = (caddr_t)&_HEAP_START;
>>        }
>>        prevHeap = heap;// Always return data aligned on a 8 byte  
>> boundary
>>        nextHeap = (caddr_t)(((unsigned int)(heap + increment) + 7)  
>> & ~7);
>>
>>        // get current stack pointer
>>        register caddr_t stackPtr asm ("sp");
>>
>>        // Check enough space and there is no collision with stack  
>> coming the
>> other way
>>
>>        // if stack is above start of heap
>>        if ( (((caddr_t)&_HEAP_START < stackPtr) && (nextHeap >  
>> stackPtr)) ||
>> (nextHeap >= (caddr_t)&_HEAP_END)) {
>>                return NULL; // error - no more memory
>>        } else {
>>                heap = nextHeap;
>>                return (caddr_t) prevHeap;
>>        }
>> }
>>
>> // Close a file
>> int _close(int file) {
>>        if(file == UART0_FILENO) {
>>                UARTClose(0);
>>                return 1;
>>        }
>>        if(file == UART1_FILENO) {
>>                UARTClose(1);
>>                return 1;
>>        }
>>        return -1;
>> }
>>
>> // Transfer control to a new process.
>> #include <errno.h>
>> #undef errno
>> extern int errno;
>> int _execve(char *name, char **argv, char **env) {
>>        errno = ENOMEM;
>>        return -1;
>> }
>>
>> // Create a new process.
>> #include <errno.h>
>> #undef errno
>> extern int errno;
>> int _fork() {
>>        errno=EAGAIN;
>>        return -1;
>> }
>>
>> // Status of an open file.
>> #include <sys/stat.h>
>> int _fstat(int file, struct stat *st) {
>>        st->st_mode = S_IFCHR;
>>        return 0;
>> }
>>
>> // Process ID
>> int _getpid() {
>>        return 1;
>> }
>>
>> // Query whether output stream is a terminal.
>> int _isatty(int file) {
>>        return 1;
>> }
>>
>> // Send a signal.
>> #include <errno.h>
>> #undef errno
>> extern int errno;
>> int _kill(int pid, int sig) {
>>        errno=EINVAL;
>>        return -1;
>> }
>>
>> // Establish a new name for an existing file.
>> #include <errno.h>
>> #undef errno
>> extern int errno;
>> int _link(char *old, char *new) {
>>        errno = EMLINK;
>>        return -1;
>> }
>>
>> // Set position in a file
>> int _lseek(int file, int ptr, int dir) {
>>        return 0;
>> }
>>
>> // Open a file
>> int _open(const char *name, int flags, int mode) {
>>        if(strcmp(name,"uart0") == 0) {
>>                if(UARTInitialized(0) || UARTInit(0,9600))
>>                        return UART0_FILENO;
>>        }
>>        if(strcmp(name,"uart1") == 0) {
>>                if(UARTInitialized(1) || UARTInit(1,9600))
>>                        return UART1_FILENO;
>>        }
>>        return -1;
>> }
>>
>> // Status of a file (by name).
>> int _stat(const char *file, struct stat *st) {
>>        st->st_mode = S_IFCHR;
>>        return 0;
>> }
>>
>> // Timing information for current process.
>> int _times(struct tms *buf) {
>>        return -1;
>> }
>>
>> // Remove a file's directory entry.
>> #include <errno.h>
>> #undef errno
>> extern int errno;
>> int _ulink(char *name) {
>>        errno=ENOENT;
>>        return -1;
>> }
>>
>> // Wait for a child process.
>> #include <errno.h>
>> #undef errno
>> extern int errno;
>> int _wait(int *status) {
>>        errno = ECHILD;
>>        return -1;
>> }
>>
>> // Read from a file
>> int _read(int file, char *ptr, int len){
>>        if(file == UART0_FILENO) {
>>                if(len > UART0Count) len = UART0Count;
>>                memcpy(ptr,UART0Buffer,len);
>>                UART0Count -= len;
>>                memcpy(UART0Buffer,UART0Buffer+len,UART0Count-len);
>>                return len;
>>        }
>>        if(file == UART1_FILENO) {
>>                if(len > UART1Count) len = UART1Count;
>>                memcpy(ptr,UART1Buffer,len);
>>                UART1Count -= len;
>>                memcpy(UART1Buffer,UART1Buffer+len,UART1Count-len);
>>                return len;
>>        }
>>        return 0;
>> }
>>
>> // Write a character to a file.
>> /*
>> `libc' subroutines will use this system routine for output to all  
>> files,
>> including stdout---so if you need to generate any output, for  
>> example to a
>> serial port for
>> debugging, you should make your minimal write capable of doing this.
>>
>> The following minimal implementation is an incomplete example; it  
>> relies on
>> a writechar
>> subroutine (not shown; typically, you must write this in assembler  
>> from
>> examples provided
>> by your hardware manufacturer) to actually perform the output.
>> */
>> int _write(int file, char *ptr, int len){
>>        if(file == UART0_FILENO) {
>>                UARTSend(0,ptr,len);
>>                return len;
>>        }
>>        if(file == UART1_FILENO) {
>>                UARTSend(1,ptr,len);
>>                return len;
>>        }
>> }
>>
>> #include <errno.h>
>> #undef errno
>> extern int errno;
>> __attribute__((noreturn)) void _exit(int status) {
>> }
>>



More information about the Newlib mailing list