/*************************************************************************** * Copyright (C) 2020 by Silvano Seva IU2KWO * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, see * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include "../drivers/usb_vcom.h" void pthread_mutex_unlock(){} void pthread_mutex_lock() {} void pthread_mutex_destroy() {} int pthread_setcancelstate(int state, int *oldstate) { (void) state; (void) oldstate; return 0; } #ifdef __cplusplus extern "C" { #endif // // C atexit support, for thread safety and code size optimizations // =============================================================== /** * Function called by atexit(), on_exit() and __cxa_atexit() to register * C functions/C++ destructors to be run at program termintion. * It is called in this way: * atexit(): __register_exitproc(__et_atexit, fn, 0, 0) * on_exit(): __register_exitproc(__et_onexit, fn, arg, 0) * __cxa_atexit(): __register_exitproc(__et_cxa, fn, arg, d) * \param type to understand if the function was called by atexit, on_exit, ... * \param fn pointer to function to be called * \param arg 0 in case of atexit, function argument in case of on_exit, * "this" parameter for C++ destructors registered with __cxa_atexit * \param d __dso_handle used to selectively call C++ destructors of a shared * library loaded dynamically, unused since Miosix does not support shared libs * \return 0 on success */ int __register_exitproc(int type, void (*fn)(void), void *arg, void *d) { (void) type; (void) fn; (void) arg; (void) d; return 0; } /** * Called by exit() to call functions registered through atexit() * \param code the exit code, for example with exit(1), code==1 * \param d __dso_handle, see __register_exitproc */ void __call_exitprocs(int code, void *d) { (void) code; (void) d; } /** * \internal * Required by C++ standard library. * See http://lists.debian.org/debian-gcc/2003/07/msg00057.html */ void *__dso_handle=(void*) &__dso_handle; // // C/C++ system calls, to support malloc, printf, fopen, etc. // ========================================================== /** * \internal * _exit, lock system in infinite loop until reboot */ void _exit(int status) { (void) status; for(;;) ; } /** * \internal * _sbrk_r, allocates memory dynamically */ void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr) { (void) ptr; //This is the absolute start of the heap extern char _end asm("_end"); //defined in the linker script //This is the absolute end of the heap extern char _heap_end asm("_heap_end"); //defined in the linker script //This holds the current end of the heap (static) static char *curHeapEnd=NULL; //This holds the previous end of the heap char *prevHeapEnd; //Check if it's first time called if(curHeapEnd==NULL) curHeapEnd=&_end; prevHeapEnd=curHeapEnd; if((curHeapEnd+incr)>&_heap_end) { return (void*)(-1); } curHeapEnd+=incr; return (void*)(prevHeapEnd); } /** * \internal * __malloc_lock, called by malloc to ensure no context switch happens during * memory allocation. Since this environment is not a multithreaded one, this * function is left empty. Allocating memory inside interrupts is anyway * forbidden. */ void __malloc_lock() {} /** * \internal * __malloc_unlock, called by malloc after performing operations on the heap */ void __malloc_unlock() {} /** * \internal * __getreent(), return the reentrancy structure of the current thread. * Used by newlib to make the C standard library thread safe. * Not a multithreaded environment, we return global reentrancy data. */ struct _reent *__getreent() { return _GLOBAL_REENT; } /** * \internal * _open_r, open a file. Actually unimpemented */ int _open_r(struct _reent *ptr, const char *name, int flags, int mode) { (void) ptr; (void) name; (void) flags; (void) mode; return -1; } /** * \internal * _close_r, close a file. Actually unimpemented */ int _close_r(struct _reent *ptr, int fd) { (void) ptr; (void) fd; return -1; } /** * \internal * _write_r, write to a file. */ int _write_r(struct _reent *ptr, int fd, const void *buf, size_t cnt) { if(fd == STDOUT_FILENO || fd == STDERR_FILENO) { vcom_writeBlock(buf, cnt); return cnt; } /* If fd is not stdout or stderr */ ptr->_errno = EBADF; return -1; } /** * \internal * _read_r, read from a file. */ int _read_r(struct _reent *ptr, int fd, void *buf, size_t cnt) { if(fd == STDIN_FILENO) { for(;;) { ssize_t r = vcom_readBlock(buf, cnt); if((r < 0) || (r == (ssize_t)(cnt))) return r; } } else /* If fd is not stdin */ ptr->_errno = EBADF; return -1; } int _read(int fd, void *buf, size_t cnt) { return _read_r(__getreent(), fd, buf, cnt); } /** * \internal * _lseek_r, move file pointer. Actually unimpemented */ off_t _lseek_r(struct _reent *ptr, int fd, off_t pos, int whence) { (void) ptr; (void) fd; (void) pos; (void) whence; return -1; } off_t _lseek(int fd, off_t pos, int whence) { (void) fd; (void) pos; (void) whence; return -1; } /** * \internal * _fstat_r, return file info. Actually unimpemented */ int _fstat_r(struct _reent *ptr, int fd, struct stat *pstat) { (void) ptr; (void) fd; (void) pstat; return -1; } int _fstat(int fd, struct stat *pstat) { (void) fd; (void) pstat; return -1; } /** * \internal * _stat_r, collect data about a file. Actually unimpemented */ int _stat_r(struct _reent *ptr, const char *file, struct stat *pstat) { (void) ptr; (void) file; (void) pstat; return -1; } /** * \internal * isatty, returns 1 if fd is associated with a terminal. * Always return 1 because read and write are implemented only in * terms of serial communication */ int _isatty_r(struct _reent *ptr, int fd) { (void) ptr; (void) fd; return 1; } int isatty(int fd) { (void) fd; return 1; } int _isatty(int fd) { (void) fd; return 1; } /** * \internal * _mkdir, create a directory. Actually unimpemented */ int mkdir(const char *path, mode_t mode) { (void) path; (void) mode; return -1; } /** * \internal * _link_r: create hardlinks. Actually unimpemented */ int _link_r(struct _reent *ptr, const char *f_old, const char *f_new) { (void) ptr; (void) f_old; (void) f_new; return -1; } /** * \internal * _unlink_r, remove a file. Actually unimpemented */ int _unlink_r(struct _reent *ptr, const char *file) { (void) ptr; (void) file; return -1; } /** * \internal * _times_r, return elapsed time. Actually unimpemented */ clock_t _times_r(struct _reent *ptr, struct tms *tim) { (void) ptr; (void) tim; return -1; } /** * \internal * it looks like abort() calls _kill instead of exit, this implementation * calls _exit() so that calling abort() really terminates the program */ int _kill_r(struct _reent* ptr, int pid, int sig) { (void) ptr; (void) sig; if(pid == 0) _exit(1); else return -1; } int _kill(int pid, int sig) { return _kill_r(0, pid, sig); } /** * \internal * _getpid_r. Not a multiprocess system, return always 0 */ int _getpid_r(struct _reent* ptr) { (void) ptr; return 0; } int _getpid() { return 0; } /** * \internal * _wait_r, unimpemented because processes are not supported. */ int _wait_r(struct _reent *ptr, int *status) { (void) ptr; (void) status; return -1; } int _fork_r(struct _reent *ptr) { (void) ptr; return -1; } #ifdef __cplusplus } #endif