/* See LICENSE of license details. */ #include #include #include #include #include #include #include #include #include #undef errno extern int errno; /* Key stub function for uart io via printf/scanf and heap management */ #undef putchar int putchar(int dat) { if (dat == '\n') { usart_write(SOC_DEBUG_UART, '\r'); } usart_write(SOC_DEBUG_UART, dat); return dat; } __WEAK ssize_t _write(int fd, const void* ptr, size_t len) { if (!isatty(fd)) { return -1; } const uint8_t* writebuf = (const uint8_t*)ptr; for (size_t i = 0; i < len; i++) { putchar((int)writebuf[i]); } return len; } // #define UART_AUTO_ECHO #undef getchar int getchar(void) { int dat; dat = (int)usart_read(SOC_DEBUG_UART); #ifdef UART_AUTO_ECHO usart_write(SOC_DEBUG_UART, (uint8_t)dat); #endif return dat; } __WEAK ssize_t _read(int fd, void* ptr, size_t len) { if (fd != STDIN_FILENO) { return -1; } ssize_t cnt = 0; uint8_t* readbuf = (uint8_t*)ptr; for (cnt = 0; cnt < len; cnt ++) { readbuf[cnt] = getchar(); /* Return partial buffer if we get EOL */ if (readbuf[cnt] == '\n') { return cnt; } } return cnt; } __WEAK void* _sbrk(ptrdiff_t incr) { extern char __heap_start[]; extern char __heap_end[]; static char* curbrk = __heap_start; if ((curbrk + incr < __heap_start) || (curbrk + incr > __heap_end)) { return (void*)(-1); } curbrk += incr; return (void*)(curbrk - incr); } /* Other newlib stub functions, see https://sourceware.org/newlib/libc.html#Stubs */ int errno; __WEAK void* __dso_handle = NULL; /* version of environ for no OS. */ char *__env[1] = { 0 }; char **environ = __env; /* Get resolution of clock. */ __WEAK int clock_getres(clockid_t clock_id, struct timespec* res) { res->tv_sec = 0; res->tv_nsec = 1000000000 / SystemCoreClock; return 0; } __WEAK int _gettimeofday(struct timeval* tp, void* tzp) { uint64_t cycles; cycles = __get_rv_cycle(); tp->tv_sec = cycles / SystemCoreClock; tp->tv_usec = (cycles % SystemCoreClock) * 1000000 / SystemCoreClock; return 0; } __WEAK int _isatty(int fd) { return 1; } __WEAK int _stat(char* file, struct stat* st) { st->st_mode = S_IFCHR; return 0; } __WEAK int _fstat(int file, struct stat* st) { if ((STDOUT_FILENO == file) || (STDERR_FILENO == file)) { st->st_mode = S_IFCHR; return 0; } else { errno = EBADF; return -1; } } __WEAK int _chown(const char *path, uid_t owner, gid_t group) { errno = ENOSYS; return -1; } __WEAK int _open(const char* name, int flags, int mode) { errno = ENOSYS; return -1; } __WEAK int _lseek(int file, int offset, int whence) { return 0; } __WEAK int _link(char* path1, char* path2) { errno = EMLINK; return -1; } __WEAK int _getpid(void) { return 1; } __WEAK int _close(int fd) { errno = EBADF; return -1; } __WEAK int _unlink(const char* path) { return -1; } __WEAK int _fork(void) { errno = ENOSYS; return -1; } __WEAK int _symlink(const char *path1, const char *path2) { errno = ENOSYS; return -1; } /* Supply a definition of errno if one not already provided. */ __WEAK int _execve(char* name, char** argv, char** env) { errno = ENOMEM; return -1; } __WEAK int _readlink(const char *path, char *buf, size_t bufsize) { errno = ENOSYS; return -1; } __WEAK int _kill(int pid, int sig) { errno = EINVAL; return -1; } __WEAK void _exit(int fd) { while (1) { __WFI(); } } __WEAK int _wait(int* status) { errno = ECHILD; return -1; } extern int _gettimeofday(struct timeval* tp, void* tzp); __WEAK clock_t _times(struct tms* buf) { static struct timeval t0; struct timeval t; long long utime; /* When called for the first time, initialize t0. */ if (t0.tv_sec == 0 && t0.tv_usec == 0) { _gettimeofday(&t0, 0); } _gettimeofday(&t, 0); utime = (t.tv_sec - t0.tv_sec) * 1000000 + (t.tv_usec - t0.tv_usec); buf->tms_utime = utime * CLOCKS_PER_SEC / 1000000; buf->tms_stime = buf->tms_cstime = buf->tms_cutime = 0; return buf->tms_utime; } /* Set CLOCK to value TP. */ __WEAK int clock_settime(clockid_t clock_id, const struct timespec* tp) { return -1; } /* Get current value of CLOCK and store it in tp. */ __WEAK int clock_gettime(clockid_t clock_id, struct timespec* tp) { struct timeval tv; int retval = -1; retval = _gettimeofday(&tv, NULL); if (retval == 0) { (tp)->tv_sec = (&tv)->tv_sec; (tp)->tv_nsec = (&tv)->tv_usec * 1000; } return retval; }