diff --git a/sys/picolibc_syscalls_default/Makefile b/sys/picolibc_syscalls_default/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/sys/picolibc_syscalls_default/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/picolibc_syscalls_default/Makefile.include b/sys/picolibc_syscalls_default/Makefile.include new file mode 100644 index 0000000000..d14f2c9f79 --- /dev/null +++ b/sys/picolibc_syscalls_default/Makefile.include @@ -0,0 +1 @@ +UNDEF += $(BINDIR)/picolibc_syscalls_default/syscalls.o diff --git a/sys/picolibc_syscalls_default/syscalls.c b/sys/picolibc_syscalls_default/syscalls.c new file mode 100644 index 0000000000..a17be9b0b8 --- /dev/null +++ b/sys/picolibc_syscalls_default/syscalls.c @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2019 Koen Zandberg + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @defgroup sys_picolibc PicoLibc system call + * @ingroup sys + * @brief PicoLibc system call + * @{ + * + * @file + * @brief PicoLibc system call implementations + * + * @author Koen Zandberg + * + * @} + */ + +#include +#include +#include + +#include "log.h" +#include "periph/pm.h" +#include "stdio_base.h" + +uint8_t sbrk[1]; + +/** + * @brief Exit a program without cleaning up files + * + * If your system doesn't provide this, it is best to avoid linking with subroutines that + * require it (exit, system). + * + * @param n the exit code, 0 for all OK, >0 for not OK + */ +void __attribute__((__noreturn__)) +_exit(int n) +{ + LOG_INFO("#! exit %i: powering off\n", n); + pm_off(); + while(1); +} + +/** + * @brief Send a signal to a thread + * + * @param[in] pid the pid to send to + * @param[in] sig the signal to send + * + * @return always returns -1 to signal error + */ +__attribute__ ((weak)) +int kill(pid_t pid, int sig) +{ + (void) pid; + (void) sig; + errno = ESRCH; /* not implemented yet */ + return -1; +} + +/* File descriptor pointers */ +int picolibc_get(FILE *file) +{ + (void)file; + char c = 0; + stdio_read(&c, 1); + return c; +} + +int picolibc_put(char c, FILE *file) +{ + (void)file; + stdio_write(&c, 1); + return 1; +} +FILE picolibc_stdio = + FDEV_SETUP_STREAM(picolibc_put, picolibc_get, NULL, _FDEV_SETUP_RW); + +FILE *const __iob[] = { + &picolibc_stdio, /* stdin */ + &picolibc_stdio, /* stdout */ + &picolibc_stdio, /* stderr */ +}; + +#include +/** + * @brief Get the process-ID of the current thread + * + * @return the process ID of the current thread + */ +pid_t getpid(void) +{ + return thread_getpid(); +} + +#if MODULE_VFS +#include "vfs.h" + +/** + * @brief Open a file + * + * This is a wrapper around @c vfs_open + * + * @param name file name to open + * @param flags flags, see man 3p open + * @param mode mode, file creation mode if the file is created when opening + * + * @return fd number (>= 0) on success + * @return -1 on error, @c errno set to a constant from errno.h to indicate the error + */ +int open(const char *name, int flags, int mode) +{ + int fd = vfs_open(name, flags, mode); + if (fd < 0) { + /* vfs returns negative error codes */ + errno = -fd; + return -1; + } + return fd; +} + +/** + * @brief Read bytes from an open file + * + * This is a wrapper around @c vfs_read + * + * @param[in] fd open file descriptor obtained from @c open() + * @param[out] dest destination buffer + * @param[in] count maximum number of bytes to read + * + * @return number of bytes read on success + * @return -1 on error, @c errno set to a constant from errno.h to indicate the error + */ +_READ_WRITE_RETURN_TYPE read(int fd, void *dest, size_t count) +{ + int res = vfs_read(fd, dest, count); + if (res < 0) { + /* vfs returns negative error codes */ + errno = -res; + return -1; + } + return res; +} + +/** + * @brief Write bytes to an open file + * + * This is a wrapper around @c vfs_write + * + * @param[in] fd open file descriptor obtained from @c open() + * @param[in] src source data buffer + * @param[in] count maximum number of bytes to write + * + * @return number of bytes written on success + * @return -1 on error, @c errno set to a constant from errno.h to indicate the error + */ +_READ_WRITE_RETURN_TYPE write(int fd, const void *src, size_t count) +{ + int res = vfs_write(fd, src, count); + if (res < 0) { + /* vfs returns negative error codes */ + errno = -res; + return -1; + } + return res; +} + +/** + * @brief Close an open file + * + * This is a wrapper around @c vfs_close + * + * If this call returns an error, the fd should still be considered invalid and + * no further attempt to use it shall be made, not even to retry @c close() + * + * @param[in] fd open file descriptor obtained from @c open() + * + * @return 0 on success + * @return -1 on error, @c errno set to a constant from errno.h to indicate the error + */ +int close(int fd) +{ + int res = vfs_close(fd); + if (res < 0) { + /* vfs returns negative error codes */ + errno = -res; + return -1; + } + return res; +} + +/** + * Current process times (not implemented). + * + * @param[out] ptms Not modified. + * + * @return -1, this function always fails. errno is set to ENOSYS. + */ +clock_t times(struct tms *ptms) +{ + (void)ptms; + errno = ENOSYS; + + return (-1); +} + +/** + * @brief Query or set options on an open file + * + * This is a wrapper around @c vfs_fcntl + * + * @param[in] fd open file descriptor obtained from @c open() + * @param[in] cmd fcntl command, see man 3p fcntl + * @param[in] arg argument to fcntl command, see man 3p fcntl + * + * @return 0 on success + * @return -1 on error, @c errno set to a constant from errno.h to indicate the error + */ +int fcntl (int fd, int cmd, int arg) +{ + int res = vfs_fcntl(fd, cmd, arg); + if (res < 0) { + /* vfs returns negative error codes */ + errno = -res; + return -1; + } + return res; +} + +/** + * @brief Seek to position in file + * + * This is a wrapper around @c vfs_lseek + * + * @p whence determines the function of the seek and should be set to one of + * the following values: + * + * - @c SEEK_SET: Seek to absolute offset @p off + * - @c SEEK_CUR: Seek to current location + @p off + * - @c SEEK_END: Seek to end of file + @p off + * + * @param[in] fd open file descriptor obtained from @c open() + * @param[in] off seek offset + * @param[in] whence determines the seek method, see detailed description + * + * @return the new seek location in the file on success + * @return -1 on error, @c errno set to a constant from errno.h to indicate the error + */ +off_t lseek(int fd, _off_t off, int whence) +{ + int res = vfs_lseek(fd, off, whence); + if (res < 0) { + /* vfs returns negative error codes */ + errno = -res; + return -1; + } + return res; +} + +/** + * @brief Get status of an open file + * + * This is a wrapper around @c vfs_fstat + * + * @param[in] fd open file descriptor obtained from @c open() + * @param[out] buf pointer to stat struct to fill + * + * @return 0 on success + * @return -1 on error, @c errno set to a constant from errno.h to indicate the error + */ +int fstat(int fd, struct stat *buf) +{ + int res = vfs_fstat(fd, buf); + if (res < 0) { + /* vfs returns negative error codes */ + errno = -res; + return -1; + } + return 0; +} + +/** + * @brief Status of a file (by name) + * + * This is a wrapper around @c vfs_fstat + * + * @param[in] name path to file + * @param[out] buf pointer to stat struct to fill + * + * @return 0 on success + * @return -1 on error, @c errno set to a constant from errno.h to indicate the error + */ +int stat(const char *name, struct stat *st) +{ + int res = vfs_stat(name, st); + if (res < 0) { + /* vfs returns negative error codes */ + errno = -res; + return -1; + } + return 0; +} + +/** + * @brief Unlink (delete) a file + * + * @param[in] path path to file to be deleted + * + * @return 0 on success + * @return -1 on error, @c errno set to a constant from errno.h to indicate the error + */ +int unlink(const char *path) +{ + int res = vfs_unlink(path); + if (res < 0) { + /* vfs returns negative error codes */ + errno = -res; + return -1; + } + return 0; +} + +#endif /* MODULE_VFS */