📄 syscalls.c
字号:
/* Support files for GNU libc. Files in the system namespace go here. Files in the C namespace (ie those that do not start with an underscore) go in .c. */#include <_ansi.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/fcntl.h>#include <stdio.h>#include <time.h>#include <sys/time.h>#include <sys/times.h>#include <errno.h>#include <reent.h>#include <unistd.h>#include "swi.h"#include "Board.h"/* Forward prototypes. */int _system _PARAMS ((const char *));int _rename _PARAMS ((const char *, const char *));int isatty _PARAMS ((int));clock_t _times _PARAMS ((struct tms *));int _gettimeofday _PARAMS ((struct timeval *, struct timezone *));void _raise _PARAMS ((void));int _unlink _PARAMS ((void));int _link _PARAMS ((void));int _stat _PARAMS ((const char *, struct stat *));int _fstat _PARAMS ((int, struct stat *));caddr_t _sbrk _PARAMS ((int));int _getpid _PARAMS ((int));int _kill _PARAMS ((int, int));void _exit _PARAMS ((int));int _close _PARAMS ((int));int _swiclose _PARAMS ((int));int _open _PARAMS ((const char *, int, ...));int _swiopen _PARAMS ((const char *, int));int _write _PARAMS ((int, char *, int));int _swiwrite _PARAMS ((int, char *, int));int _lseek _PARAMS ((int, int, int));int _swilseek _PARAMS ((int, int, int));int _read _PARAMS ((int, char *, int));int _swiread _PARAMS ((int, char *, int));void initialise_monitor_handles _PARAMS ((void));static int wrap _PARAMS ((int));static int error _PARAMS ((int));static int get_errno _PARAMS ((void));static int remap_handle _PARAMS ((int));static int do_AngelSWI _PARAMS ((int, void *));static int findslot _PARAMS ((int));/* Register name faking - works in collusion with the linker. */register char * stack_ptr asm ("sp");/* following is copied from libc/stdio/local.h to check std streams */extern void _EXFUN(__sinit,(struct _reent *));#define CHECK_INIT(ptr) \ do \ { \ if ((ptr) && !(ptr)->__sdidinit) \ __sinit (ptr); \ } \ while (0)/* Adjust our internal handles to stay away from std* handles. */#define FILE_HANDLE_OFFSET (0x20)static int monitor_stdin;static int monitor_stdout;static int monitor_stderr;/* Struct used to keep track of the file position, just so we can implement fseek(fh,x,SEEK_CUR). */typedef struct{ int handle; int pos;}poslog;#define MAX_OPEN_FILES 20static poslog openfiles [MAX_OPEN_FILES];static intfindslot (int fh){ int i; for (i = 0; i < MAX_OPEN_FILES; i ++) if (openfiles[i].handle == fh) break; return i;}#ifdef ARM_RDI_MONITORstatic inline intdo_AngelSWI (int reason, void * arg){ int value; asm volatile ("mov r0, %1; mov r1, %2; swi %a3; mov %0, r0" : "=r" (value) /* Outputs */ : "r" (reason), "r" (arg), "i" (AngelSWI) /* Inputs */ : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc" /* Clobbers r0 and r1, and lr if in supervisor mode */); /* Accordingly to page 13-77 of ARM DUI 0040D other registers can also be clobbered. Some memory positions may also be changed by a system call, so they should not be kept in registers. Note: we are assuming the manual is right and Angel is respecting the APCS. */ return value;}#endif /* ARM_RDI_MONITOR *//* Function to convert std(in|out|err) handles to internal versions. */static intremap_handle (int fh){ CHECK_INIT(_REENT); if (fh == STDIN_FILENO) return monitor_stdin; if (fh == STDOUT_FILENO) return monitor_stdout; if (fh == STDERR_FILENO) return monitor_stderr; return fh - FILE_HANDLE_OFFSET;}voidinitialise_monitor_handles (void){ int i; #ifdef ARM_RDI_MONITOR int volatile block[3]; block[0] = (int) ":tt"; block[2] = 3; /* length of filename */ block[1] = 0; /* mode "r" */ monitor_stdin = do_AngelSWI (AngelSWI_Reason_Open, (void *) block); block[0] = (int) ":tt"; block[2] = 3; /* length of filename */ block[1] = 4; /* mode "w" */ monitor_stdout = monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);#else int fh; const char * name; name = ":tt"; asm ("mov r0,%2; mov r1, #0; swi %a1; mov %0, r0" : "=r"(fh) : "i" (SWI_Open),"r"(name) : "r0","r1"); monitor_stdin = fh; name = ":tt"; asm ("mov r0,%2; mov r1, #4; swi %a1; mov %0, r0" : "=r"(fh) : "i" (SWI_Open),"r"(name) : "r0","r1"); monitor_stdout = monitor_stderr = fh;#endif for (i = 0; i < MAX_OPEN_FILES; i ++) openfiles[i].handle = -1; openfiles[0].handle = monitor_stdin; openfiles[0].pos = 0; openfiles[1].handle = monitor_stdout; openfiles[1].pos = 0;}static intget_errno (void){#ifdef ARM_RDI_MONITOR return do_AngelSWI (AngelSWI_Reason_Errno, NULL);#else asm ("swi %a0" :: "i" (SWI_GetErrno));#endif}static interror (int result){ errno = get_errno (); return result;}static intwrap (int result){ if (result == -1) return error (-1); return result;}/* Returns # chars not! written. */int_swiread (int file, char * ptr, int len){ int fh = remap_handle (file);#ifdef ARM_RDI_MONITOR int block[3]; block[0] = fh; block[1] = (int) ptr; block[2] = len; return do_AngelSWI (AngelSWI_Reason_Read, block);#else asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0" : /* No outputs */ : "i"(SWI_Read), "r"(fh), "r"(ptr), "r"(len) : "r0","r1","r2");#endif}int_read (int file, char * ptr, int len){/* This overrides the default _read function in libc and just dumps the output to the serial port. Added by Adam Pierce. */ int i, j; volatile AT91PS_USART pUart = AT91C_BASE_US0; for(i = 0; i < len; i++) { // Loop until a byte is received.// for(j = 0; 0 == (pUart->US_CSR & AT91C_US_RXRDY); j++)// {// if(j >= 8000000)// return len; // Timeout.// } // Wait for a byte to appear on the port. while(0 == (pUart->US_CSR & AT91C_US_RXRDY)) ; // Read the byte.
ptr[i] = (char)pUart->US_RHR; // Local echo. pUart->US_THR = ptr[i]; } return len;
/* int slot = findslot (remap_handle (file)); int x = _swiread (file, ptr, len); if (x < 0) return error (-1); if (slot != MAX_OPEN_FILES) openfiles [slot].pos += len - x; // x == len is not an error, at least if we want feof() to work. return len - x;*/}int_swilseek (int file, int ptr, int dir){ int res; int fh = remap_handle (file); int slot = findslot (fh);#ifdef ARM_RDI_MONITOR int block[2];#endif if (dir == SEEK_CUR) { if (slot == MAX_OPEN_FILES) return -1; ptr = openfiles[slot].pos + ptr; dir = SEEK_SET; } #ifdef ARM_RDI_MONITOR if (dir == SEEK_END) { block[0] = fh; ptr += do_AngelSWI (AngelSWI_Reason_FLen, block); } /* This code only does absolute seeks. */ block[0] = remap_handle (file); block[1] = ptr; res = do_AngelSWI (AngelSWI_Reason_Seek, block);#else if (dir == SEEK_END) { asm ("mov r0, %2; swi %a1; mov %0, r0" : "=r" (res) : "i" (SWI_Flen), "r" (fh) : "r0"); ptr += res; } /* This code only does absolute seeks. */ asm ("mov r0, %2; mov r1, %3; swi %a1; mov %0, r0" : "=r" (res) : "i" (SWI_Seek), "r" (fh), "r" (ptr) : "r0", "r1");#endif if (slot != MAX_OPEN_FILES && res == 0) openfiles[slot].pos = ptr; /* This is expected to return the position in the file. */ return res == 0 ? ptr : -1;}int_lseek (int file, int ptr, int dir){ return wrap (_swilseek (file, ptr, dir));}/* Returns #chars not! written. */int_swiwrite ( int file, char * ptr, int len){ int fh = remap_handle (file);#ifdef ARM_RDI_MONITOR int block[3]; block[0] = fh; block[1] = (int) ptr; block[2] = len; return do_AngelSWI (AngelSWI_Reason_Write, block);#else asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0" : /* No outputs */ : "i"(SWI_Write), "r"(fh), "r"(ptr), "r"(len) : "r0","r1","r2");#endif}int_write (int file, char * ptr, int len){/* This overrides the default _write function in libc and just dumps the output to the serial port. Added by Adam Pierce. */ int i; volatile AT91PS_USART pUart = AT91C_BASE_US0; for(i = 0; i < len; i++) { while(0 == (pUart->US_CSR & AT91C_US_TXRDY)) ; pUart->US_THR = ptr[i]; } return len;
/* int slot = findslot (remap_handle (file)); int x = _swiwrite (file, ptr,len); if (x == -1 || x == len) return error (-1); if (slot != MAX_OPEN_FILES) openfiles[slot].pos += len - x; return len - x;*/}extern int strlen (const char *);int_swiopen (const char * path, int flags){ int aflags = 0, fh;#ifdef ARM_RDI_MONITOR int block[3];#endif int i = findslot (-1); if (i == MAX_OPEN_FILES) return -1; /* The flags are Unix-style, so we need to convert them. */#ifdef O_BINARY if (flags & O_BINARY) aflags |= 1;#endif if (flags & O_RDWR) aflags |= 2; if (flags & O_CREAT) aflags |= 4; if (flags & O_TRUNC) aflags |= 4; if (flags & O_APPEND) { aflags &= ~4; /* Can't ask for w AND a; means just 'a'. */ aflags |= 8; } #ifdef ARM_RDI_MONITOR block[0] = (int) path; block[2] = strlen (path); block[1] = aflags; fh = do_AngelSWI (AngelSWI_Reason_Open, block); #else asm ("mov r0,%2; mov r1, %3; swi %a1; mov %0, r0" : "=r"(fh) : "i" (SWI_Open),"r"(path),"r"(aflags) : "r0","r1");#endif if (fh >= 0) { openfiles[i].handle = fh; openfiles[i].pos = 0; } return fh >= 0 ? fh + FILE_HANDLE_OFFSET : error (fh);}int_open (const char * path, int flags, ...){ return wrap (_swiopen (path, flags));}int_swiclose (int file){ int myhan = remap_handle (file); int slot = findslot (myhan); if (slot != MAX_OPEN_FILES) openfiles[slot].handle = -1;#ifdef ARM_RDI_MONITOR return do_AngelSWI (AngelSWI_Reason_Close, & myhan);#else asm ("mov r0, %1; swi %a0" :: "i" (SWI_Close),"r"(myhan):"r0");#endif}int_close (int file){ return wrap (_swiclose (file));}void_exit (int n){ /* FIXME: return code is thrown away. */ #ifdef ARM_RDI_MONITOR do_AngelSWI (AngelSWI_Reason_ReportException, (void *) ADP_Stopped_ApplicationExit);#else asm ("swi %a0" :: "i" (SWI_Exit));#endif n = n;}int_kill (int n, int m){#ifdef ARM_RDI_MONITOR return do_AngelSWI (AngelSWI_Reason_ReportException, (void *) ADP_Stopped_ApplicationExit);#else asm ("swi %a0" :: "i" (SWI_Exit));#endif n = n; m = m;}int_getpid (int n){ return 1; n = n;}caddr_t_sbrk (int incr){ extern char end asm ("end"); /* Defined by the linker. */ static char * heap_end; char * prev_heap_end; if (heap_end == NULL) heap_end = & end; prev_heap_end = heap_end; if (heap_end + incr > stack_ptr) { /* Some of the libstdc++-v3 tests rely upon detecting out of memory errors, so do not abort here. */#if 0 extern void abort (void); _write (1, "_sbrk: Heap and stack collision\n", 32); abort ();#else errno = ENOMEM; return (caddr_t) -1;#endif } heap_end += incr; return (caddr_t) prev_heap_end;}extern void memset (struct stat *, int, unsigned int);int_fstat (int file, struct stat * st){ memset (st, 0, sizeof (* st)); st->st_mode = S_IFCHR; st->st_blksize = 1024; return 0; file = file;}int _stat (const char *fname, struct stat *st){ int file; /* The best we can do is try to open the file readonly. If it exists, then we can guess a few things about it. */ if ((file = _open (fname, O_RDONLY)) < 0) return -1; memset (st, 0, sizeof (* st)); st->st_mode = S_IFREG | S_IREAD; st->st_blksize = 1024; _swiclose (file); /* Not interested in the error. */ return 0;}int_link (void){ return -1;}int_unlink (void){ return -1;}void_raise (void){ return;}int_gettimeofday (struct timeval * tp, struct timezone * tzp){ if (tp) { /* Ask the host for the seconds since the Unix epoch. */#ifdef ARM_RDI_MONITOR tp->tv_sec = do_AngelSWI (AngelSWI_Reason_Time,NULL);#else { int value; asm ("swi %a1; mov %0, r0" : "=r" (value): "i" (SWI_Time) : "r0"); tp->tv_sec = value; }#endif tp->tv_usec = 0; } /* Return fixed data for the timezone. */ if (tzp) { tzp->tz_minuteswest = 0; tzp->tz_dsttime = 0; } return 0;}/* Return a clock that ticks at 100Hz. */clock_t _times (struct tms * tp){ clock_t timeval;#ifdef ARM_RDI_MONITOR timeval = do_AngelSWI (AngelSWI_Reason_Clock,NULL);#else asm ("swi %a1; mov %0, r0" : "=r" (timeval): "i" (SWI_Clock) : "r0");#endif if (tp) { tp->tms_utime = timeval; /* user time */ tp->tms_stime = 0; /* system time */ tp->tms_cutime = 0; /* user time, children */ tp->tms_cstime = 0; /* system time, children */ } return timeval;};intisatty (int fd){ return 1; fd = fd;}int_system (const char *s){ if (s == NULL) return 0; errno = ENOSYS; return -1;}int_rename (const char * oldpath, const char * newpath){ errno = ENOSYS; return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -