This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Stubs


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) {
}



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]