diff --git a/cpu/native/async_read.c b/cpu/native/async_read.c index 5aed77739e..58a0e0881d 100644 --- a/cpu/native/async_read.c +++ b/cpu/native/async_read.c @@ -1,6 +1,4 @@ -/** - * Multiple asynchronous read on file descriptors - * +/* * Copyright (C) 2015 Ludwig Knüpfer , * Martine Lenders * Kaspar Schleiser @@ -10,10 +8,12 @@ * 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. - * - * @ingroup cpu_native - * @{ + */ + +/** * @file + * @brief Multiple asynchronous read on file descriptors + * @ingroup cpu_native * @author Takuo Yonezawa */ @@ -45,11 +45,11 @@ static void _async_io_isr(void) { } void native_async_read_setup(void) { - register_interrupt(SIGIO, _async_io_isr); + native_register_interrupt(SIGIO, _async_io_isr); } void native_async_read_cleanup(void) { - unregister_interrupt(SIGIO); + native_unregister_interrupt(SIGIO); for (int i = 0; i < _next_index; i++) { real_close(_fds[i].fd); @@ -115,12 +115,12 @@ void native_async_read_remove_handler(int fd) return; } - unregister_interrupt(SIGIO); + native_unregister_interrupt(SIGIO); for (; i < (unsigned)_next_index - 1; i++) { _fds[i] = _fds[i + 1]; } _next_index--; - register_interrupt(SIGIO, _async_io_isr); + native_register_interrupt(SIGIO, _async_io_isr); _fds[_next_index] = (struct pollfd){ 0 }; } @@ -179,4 +179,3 @@ static void _sigio_child(int index) sigwait(&sigmask, &sig); } } -/** @} */ diff --git a/cpu/native/backtrace/backtrace.c b/cpu/native/backtrace/backtrace.c index f17157f1cf..cb38361293 100644 --- a/cpu/native/backtrace/backtrace.c +++ b/cpu/native/backtrace/backtrace.c @@ -7,9 +7,9 @@ */ /** - * @{ - * * @file + * @ingroup cpu_native + * @brief Backtrace implementation for native CPU * @author Martine Lenders */ @@ -55,5 +55,3 @@ int backtrace_len(void) return backtrace(array, BACKTRACE_SIZE + 1) - 1; } - -/** @} */ diff --git a/cpu/native/cli_eui_provider/eui_provider.c b/cpu/native/cli_eui_provider/eui_provider.c index b187b19743..1ed2723117 100644 --- a/cpu/native/cli_eui_provider/eui_provider.c +++ b/cpu/native/cli_eui_provider/eui_provider.c @@ -1,17 +1,16 @@ -/** - * Native CPU EUI provider - * +/* * Copyright (C) 2020 Benjamin Valentin * * 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. - * - * @ingroup cpu_native - * @{ + */ + +/** * @file + * @ingroup cpu_native + * @brief Native CPU EUI provider * @author Benjamin Valentin - * @} */ #include diff --git a/cpu/native/cpu.c b/cpu/native/cpu.c new file mode 100644 index 0000000000..032b67cc3f --- /dev/null +++ b/cpu/native/cpu.c @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2016 Kaspar Schleiser + * 2013 Ludwig Knüpfer + * + * 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. + */ + +/** + * @file + * @brief Native CPU kernel_intern.h and sched.h implementation + * @author Ludwig Knüpfer + * @author Kaspar Schleiser + * + * In-process preemptive context switching utilizes POSIX ucontexts. + * (ucontext provides for architecture independent stack handling) + */ + +#include +#include +#include +#include +#include +#include + +#include "util/valgrind.h" + +#include "cpu.h" +#include "cpu_conf.h" +#include "irq.h" +#include "sched.h" +#include "test_utils/expect.h" + +#ifdef MODULE_NETDEV_TAP +#include "netdev_tap.h" +extern netdev_tap_t netdev_tap; +#endif + +#include "native_internal.h" + +#define ENABLE_DEBUG 0 +#include "debug.h" +#define DEBUG_CPU(...) DEBUG("[native] CPU: " __VA_ARGS__) + +static ucontext_t _end_context; + +/** + * TODO: implement + */ +void thread_print_stack(void) +{ + DEBUG_CPU("thread_print_stack\n"); + return; +} + +/* This function calculates the ISR_usage */ +int thread_isr_stack_usage(void) +{ + /* TODO */ + return -1; +} + +void native_breakpoint(void) +{ + raise(SIGTRAP); +} + +/* ========================================= */ +/* ISR -> user switch function */ + +void _isr_switch_to_user(void) { + DEBUG_CPU("... ISR: switching to user thread, calling setcontext(PID %" PRIkernel_pid ")\n\n", thread_getpid()); + + ucontext_t *context = _native_user_context(); + _native_interrupts_enabled = true; + + /* Get PC/LR. This is where we will resume execution on the userspace thread. */ + _native_user_fptr = (uintptr_t)_context_get_fptr(context); + + /* Now we want to go to _native_isr_leave before resuming execution at _native_user_fptr. */ + _context_set_fptr(context, (uintptr_t)_native_isr_leave); + + if (setcontext(context) == -1) { + err(EXIT_FAILURE, "_isr_schedule_and_switch: setcontext"); + } + errx(EXIT_FAILURE, "2 this should have never been reached!!"); +} + +/* ========================================= */ + +void _isr_context_switch_exit(void) +{ + DEBUG_CPU("_isr_schedule_and_switch\n"); + /* Schedule thread job if no active thread */ + if (((sched_context_switch_request == 1) || (thread_get_active() == NULL)) + && IS_USED(MODULE_CORE_THREAD)) { + /* Schedule active thread */ + sched_run(); + } + + /* Switch to active userspace thread */ + _isr_switch_to_user(); +} + +/* ^ + * | + * | + * cpu_switch_context_exit continues + * in ISR context in _isr_context_switch_exit + */ + +void cpu_switch_context_exit(void) +{ +# ifdef NATIVE_AUTO_EXIT + if (sched_num_threads <= 1) { + extern unsigned _native_retval; + DEBUG_CPU("cpu_switch_context_exit: last task has ended. exiting.\n"); + real_exit(_native_retval); + } +# endif + + if (_native_in_isr == 0) { + /* Disable interrupts while switching */ + irq_disable(); + _native_in_isr = 1; + + _native_isr_context_make(_isr_context_switch_exit); + if (setcontext(_native_isr_context) == -1) { + err(EXIT_FAILURE, "cpu_switch_context_exit: setcontext"); + } + errx(EXIT_FAILURE, "1 this should have never been reached!!"); + } + else { + _isr_context_switch_exit(); + } + errx(EXIT_FAILURE, "3 this should have never been reached!!"); +} + +/* ========================================= */ + + +void _isr_thread_yield(void) +{ + DEBUG_CPU("... ISR: switched to ISR context, scheduling\n"); + + if (_native_pending_signals > 0) { + DEBUG_CPU("... ISR: pending signals, handling signals\n\n"); + _native_call_sig_handlers_and_switch(); + } + + if (!IS_USED(MODULE_CORE_THREAD)) { + return; + } + + /* Set active thread */ + sched_run(); + + /* Switch to active userspace thread */ + _isr_switch_to_user(); +} + +/* ^ + * | + * | + * thread_yield_higher continues + * in ISR context in _isr_thread_yield + */ + +void thread_yield_higher(void) +{ + sched_context_switch_request = 1; + + if (_native_in_isr == 0 && _native_interrupts_enabled) { + DEBUG_CPU("yielding higher priority thread, switching to ISR context ...\n"); + + _native_in_isr = 1; + irq_disable(); + + /* Create the ISR context, will execute isr_thread_yield */ + _native_isr_context_make(_isr_thread_yield); + if (swapcontext(_native_user_context(), _native_isr_context) == -1) { + err(EXIT_FAILURE, "thread_yield_higher: swapcontext"); + } + irq_enable(); + } +} + +/* ========================================= */ + +void native_cpu_init(void) +{ + if (getcontext(&_end_context) == -1) { + err(EXIT_FAILURE, "native_cpu_init: getcontext"); + } + + /* The _end_context allows RIOT to execute code after a thread task func returns. + * This works as follows (explanation based on libplatform) + * - In thread_stack_init, we call makecontext with the thread task func + * and uc_link = _end_context. + * - makecontext modifies the ucontext so that _ctx_start (in the libc/libplatform impl) + * is called when setcontext is executed. The thread task func resides in a register. + * - When the thread is started using setcontext, _ctx_start branches and links to the + * the task func. After the task func returns, _ctx_start would normally call exit. + * However, if _end_context is set, it calls setcontext on th bespoke _end_context. + */ + _end_context.uc_stack.ss_sp = malloc(SIGSTKSZ); + expect(_end_context.uc_stack.ss_sp != NULL); + _end_context.uc_stack.ss_size = SIGSTKSZ; + _end_context.uc_stack.ss_flags = 0; + makecontext(&_end_context, sched_task_exit, 0); + + (void)VALGRIND_STACK_REGISTER(_end_context.uc_stack.ss_sp, + (char *)_end_context.uc_stack.ss_sp + _end_context.uc_stack.ss_size); + VALGRIND_DEBUG("VALGRIND_STACK_REGISTER(%p, %p)\n", + (void*)_end_context.uc_stack.ss_sp, + (void*)((char *)_end_context.uc_stack.ss_sp + _end_context.uc_stack.ss_size)); + + DEBUG_CPU("RIOT native cpu initialized.\n"); +} + +/* ========================================= */ + +static inline void *align_stack(uintptr_t start, int *stacksize) +{ + const size_t alignment = sizeof(uintptr_t); + const uintptr_t align_mask = alignment - 1; + size_t unalignment = (start & align_mask) + ? (alignment - (start & align_mask)) : 0; + start += unalignment; + *stacksize -= unalignment; + *stacksize &= ~align_mask; + return (void *)start; +} + +char *thread_stack_init(thread_task_func_t task_func, void *arg, void *stack_start, int stacksize) +{ + ucontext_t *p; + + stack_start = align_stack((uintptr_t)stack_start, &stacksize); + + (void) VALGRIND_STACK_REGISTER(stack_start, (char *)stack_start + stacksize); + VALGRIND_DEBUG("VALGRIND_STACK_REGISTER(%p, %p)\n", + stack_start, (void*)((char *)stack_start + stacksize)); + + DEBUG_CPU("thread_stack_init\n"); + + /* Use intermediate cast to uintptr_t to silence -Wcast-align. The stack + * is aligned to word size above. */ + p = (ucontext_t *)(uintptr_t)((uint8_t *)stack_start + (stacksize - sizeof(ucontext_t))); + /* Stack guards might be in the way. */ + memset(p, 0, sizeof(ucontext_t)); + stacksize -= sizeof(ucontext_t); + + if (getcontext(p) == -1) { + err(EXIT_FAILURE, "thread_stack_init: getcontext"); + } + + p->uc_stack.ss_sp = stack_start; + p->uc_stack.ss_size = stacksize; + p->uc_stack.ss_flags = 0; + p->uc_link = &_end_context; + + if (sigemptyset(&(p->uc_sigmask)) == -1) { + err(EXIT_FAILURE, "thread_stack_init: sigemptyset"); + } + + makecontext64(p, (void (*)(void))task_func, arg); + + return (char *) p; +} diff --git a/cpu/native/fs/native_fs.c b/cpu/native/fs/native_fs.c index 8d8bcba700..015a65ec30 100644 --- a/cpu/native/fs/native_fs.c +++ b/cpu/native/fs/native_fs.c @@ -7,15 +7,10 @@ */ /** - * @ingroup sys_fs_native - * @{ - * * @file - * @brief native integration with vfs - * - * @author Benjamin Valentin - * - * @} + * @ingroup sys_fs_native + * @brief Native integration with virtual filesystem (VFS) + * @author Benjamin Valentin */ #include @@ -35,7 +30,7 @@ * @brief Assign each native instance a sub-sirectory based on `_native_id` */ #ifndef CONFIG_NATIVE_ISOLATE_FS -#define CONFIG_NATIVE_ISOLATE_FS 0 +# define CONFIG_NATIVE_ISOLATE_FS 0 #endif /* Not using static inline functions here because they are also assigned to. */ @@ -58,14 +53,14 @@ static void _do_prefix(vfs_mount_t *mountp, const char *name, char *buffer, size res = snprintf(buffer, len, "%s%s", fs_desc->hostpath, name); } -#ifdef NDEBUG +# ifdef NDEBUG if (res > len) { puts("fs_native: path larger than PATH_MAX"); exit(ENOBUFS); } -#else +# else assert(res <= len); -#endif +# endif } static char *_prefix_path(vfs_mount_t *mountp, const char *name) diff --git a/cpu/native/include/architecture_arch.h b/cpu/native/include/architecture_arch.h index 604dd08b39..18f9a08700 100644 --- a/cpu/native/include/architecture_arch.h +++ b/cpu/native/include/architecture_arch.h @@ -7,16 +7,15 @@ */ /** - * @ingroup cpu_native + * @addtogroup cpu_native * @{ - * - * @file - * @brief Architecture details - * - * @author Marian Buschsieweke - * */ +/** + * @file + * @brief Architecture details + * @author Marian Buschsieweke + */ #ifndef ARCHITECTURE_ARCH_H #define ARCHITECTURE_ARCH_H @@ -33,17 +32,17 @@ void native_breakpoint(void); /* Doc is provided centrally in architecture.h, hide this from Doxygen */ #ifndef DOXYGEN -#if (__SIZEOF_POINTER__ == 8) -#define ARCHITECTURE_WORD_BITS (64U) -#else -#define ARCHITECTURE_WORD_BITS (32U) -#endif -#define ARCHITECTURE_BREAKPOINT(v) native_breakpoint() +# if (__SIZEOF_POINTER__ == 8) +# define ARCHITECTURE_WORD_BITS (64U) +# else +# define ARCHITECTURE_WORD_BITS (32U) +# endif +# define ARCHITECTURE_BREAKPOINT(v) native_breakpoint() #endif /* DOXYGEN */ #ifdef __cplusplus } #endif -/** @} */ #endif /* ARCHITECTURE_ARCH_H */ +/** @} */ diff --git a/cpu/native/include/async_read.h b/cpu/native/include/async_read.h index 3f36ab1af5..4793b5bd32 100644 --- a/cpu/native/include/async_read.h +++ b/cpu/native/include/async_read.h @@ -7,13 +7,14 @@ */ /** - * @ingroup cpu_native + * @addtogroup cpu_native * @{ - * + */ + +/** * @file - * @brief Multiple asynchronous read on file descriptors - * - * @author Takuo Yonezawa + * @brief Multiple asynchronous read on file descriptors + * @author Takuo Yonezawa */ #ifndef ASYNC_READ_H #define ASYNC_READ_H @@ -29,7 +30,7 @@ extern "C" { * @brief Maximum number of file descriptors */ #ifndef ASYNC_READ_NUMOF -#define ASYNC_READ_NUMOF 2 +# define ASYNC_READ_NUMOF 2 #endif /** diff --git a/cpu/native/include/atomic_utils_arch.h b/cpu/native/include/atomic_utils_arch.h index eda75e6449..32c52c9620 100644 --- a/cpu/native/include/atomic_utils_arch.h +++ b/cpu/native/include/atomic_utils_arch.h @@ -7,18 +7,17 @@ */ /** - * @ingroup cpu_native - * + * @addtogroup cpu_native * @{ - * - * @file - * @brief Implementation of fast atomic utility functions - * @author Marian Buschsieweke */ +/** + * @file + * @brief Implementation of fast atomic utility functions + * @author Marian Buschsieweke + */ #ifndef ATOMIC_UTILS_ARCH_H #define ATOMIC_UTILS_ARCH_H -#ifndef DOXYGEN #include "periph_cpu.h" @@ -26,6 +25,8 @@ extern "C" { #endif +#ifndef DOXYGEN + /* clang provides no built-in atomic access to regular variables */ #ifndef __clang__ @@ -66,11 +67,11 @@ static inline void atomic_store_u32(volatile uint32_t *dest, uint32_t val) } #endif /* __clang__ */ +#endif /* DOXYGEN */ #ifdef __cplusplus } #endif -#endif /* DOXYGEN */ #endif /* ATOMIC_UTILS_ARCH_H */ /** @} */ diff --git a/cpu/native/include/backtrace.h b/cpu/native/include/backtrace.h index 2174607080..89e3f7bbb3 100644 --- a/cpu/native/include/backtrace.h +++ b/cpu/native/include/backtrace.h @@ -7,19 +7,19 @@ */ /** - * @defgroup backtrace Stack backtrace (only under native) - * @ingroup core_util - * @brief Backtrace functionalitry + * @defgroup backtrace Stack backtrace (only under native) + * @ingroup core_util + * @brief Backtrace functionalitry + * @{ * * If you call the @ref backtrace_print() function a stack backtrace of all return * addresses up to @ref BACKTRACE_SIZE will be printed from the point of execution. - * - * @{ - * + */ + +/** * @file - * @brief - * - * @author Martine Lenders + * @brief Backtrace functionalitry + * @author Martine Lenders */ #ifndef BACKTRACE_H #define BACKTRACE_H @@ -32,7 +32,7 @@ extern "C" { * @brief Maximum number of return addresses to print */ #ifndef BACKTRACE_SIZE -#define BACKTRACE_SIZE (4U) +# define BACKTRACE_SIZE (4U) #endif /** diff --git a/cpu/native/include/can_params.h b/cpu/native/include/can_params.h index 36e69962ea..16d83249af 100644 --- a/cpu/native/include/can_params.h +++ b/cpu/native/include/can_params.h @@ -7,15 +7,15 @@ */ /** - * @ingroup drivers_candev_linux + * @addtogroup drivers_candev_linux * @{ - * - * @file - * @brief Default linux can config - * - * @author Vincent Dupont */ +/** + * @file + * @brief Default linux can config + * @author Vincent Dupont + */ #ifndef CAN_PARAMS_H #define CAN_PARAMS_H diff --git a/cpu/native/include/candev_linux.h b/cpu/native/include/candev_linux.h index c911c9bee8..d5c082273f 100644 --- a/cpu/native/include/candev_linux.h +++ b/cpu/native/include/candev_linux.h @@ -7,19 +7,19 @@ */ /** - * @defgroup drivers_candev_linux SocketCAN driver - * @ingroup drivers_can - * @brief Implementation of simulated CAN controller driver using SocketCAN on Linux + * @defgroup drivers_candev_linux SocketCAN driver + * @ingroup drivers_can + * @brief Implementation of simulated CAN controller driver using SocketCAN on Linux * @{ - * - * @file - * @brief Implementation of simulated CAN controller driver using SocketCAN on Linux - * - * @author Hermann Lelong - * @author Aurelien Gonce - * @author Vincent Dupont */ +/** + * @file + * @brief Implementation of simulated CAN controller driver using SocketCAN on Linux + * @author Hermann Lelong + * @author Aurelien Gonce + * @author Vincent Dupont + */ #ifndef CANDEV_LINUX_H #define CANDEV_LINUX_H @@ -29,48 +29,42 @@ extern "C" { #if defined(__linux__) /* SocketCAN is supported only on Linux */ || defined(DOXYGEN) -#include +# include -#include "can/device.h" -#include "can/candev.h" -#include "mutex.h" +# include "can/device.h" +# include "can/candev.h" +# include "mutex.h" /** - * Maximum size of an interface name + * @brief Maximum size of an interface name */ -#define CAN_MAX_SIZE_INTERFACE_NAME (5) +# define CAN_MAX_SIZE_INTERFACE_NAME (5) /** - * Linux candev configuration + * @brief Linux candev configuration */ typedef struct candev_conf { /** local interface name */ char interface_name[CAN_MAX_SIZE_INTERFACE_NAME + 1]; } can_conf_t; -/** CAN device configuration type can_conf_t is redefined by native CAN */ -#define HAVE_CAN_CONF_T +/** @brief CAN device configuration type can_conf_t is redefined by native CAN */ +# define HAVE_CAN_CONF_T -#ifndef CANDEV_LINUX_MAX_FILTERS_RX -/** - * Max number of rx filters which can be set - */ -#define CANDEV_LINUX_MAX_FILTERS_RX (16) -#endif +# if !defined(CANDEV_LINUX_MAX_FILTERS_RX) || defined(DOXYGEN) +/** @brief Max number of rx filters which can be set */ +# define CANDEV_LINUX_MAX_FILTERS_RX (16) +# endif -#ifndef CANDEV_LINUX_DEFAULT_BITRATE -/** - * Default bitrate setup - */ -#define CANDEV_LINUX_DEFAULT_BITRATE (500000) -#endif +# if !defined(CANDEV_LINUX_DEFAULT_BITRATE) || defined(DOXYGEN) +/** @brief Default bitrate setup */ +# define CANDEV_LINUX_DEFAULT_BITRATE (500000) +# endif -#ifndef CANDEV_LINUX_DEFAULT_SPT -/** - * Default sampling point setup - */ -#define CANDEV_LINUX_DEFAULT_SPT (875) -#endif +# if !defined(CANDEV_LINUX_DEFAULT_SPT) || defined(DOXYGEN) +/** @brief Default sampling point setup*/ +# define CANDEV_LINUX_DEFAULT_SPT (875) +# endif /** * @brief The candev_linux struct @@ -83,8 +77,8 @@ typedef struct candev_linux { struct can_filter filters[CANDEV_LINUX_MAX_FILTERS_RX]; } can_t; -/** CAN device type can_t is redefined by native CAN */ -#define HAVE_CAN_T +/** @brief CAN device type can_t is redefined by native CAN */ +# define HAVE_CAN_T /** * @brief Array containing socketCAN device names diff --git a/cpu/native/include/cpu.h b/cpu/native/include/cpu.h index 20a8f6310b..5eb3830d07 100644 --- a/cpu/native/include/cpu.h +++ b/cpu/native/include/cpu.h @@ -7,16 +7,21 @@ */ /** - * @ingroup cpu - * @defgroup cpu_native Native - * @brief Native CPU specific code - * @details The native CPU uses system calls to simulate hardware access. - * @ingroup cpu - * @brief CPU abstraction for the native port + * @defgroup cpu_native Native CPU + * @ingroup cpu + * @brief CPU implementation for running RIOT on a Linux and BSD + * @author Ludwig Knüpfer + * + * The native CPU uses system calls to simulate hardware access. + * * @{ - * @author Ludwig Knüpfer */ +/** + * @file + * @brief Native CPU header + * @author Ludwig Knüpfer + */ #ifndef CPU_H #define CPU_H @@ -28,6 +33,11 @@ extern "C" { #endif +/* MARK: - Basics */ +/** + * @name + * @{ + */ /** * @brief The CPU supports unaligned memory access. * Even if the underlying architecture does not support it, the kernel will take care of it. @@ -44,10 +54,11 @@ __attribute__((always_inline)) static inline uintptr_t cpu_get_caller_pc(void) * it is the return address of the user of this function */ return (uintptr_t)__builtin_return_address(0); } +/** @} */ #ifdef __cplusplus } #endif -/** @} */ #endif /* CPU_H */ +/** @} */ diff --git a/cpu/native/include/cpu_conf.h b/cpu/native/include/cpu_conf.h index 88d37cbb94..84906bbe1d 100644 --- a/cpu/native/include/cpu_conf.h +++ b/cpu/native/include/cpu_conf.h @@ -1,17 +1,20 @@ -/** - * Native CPU configuration - * +/* * Copyright (C) 2013 Ludwig Knüpfer * * 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. - * - * @ingroup cpu_native + */ + +/** + * @addtogroup cpu_native * @{ + */ + +/** * @file - * @author Ludwig Knüpfer - * @} + * @brief Native CPU configuration + * @author Ludwig Knüpfer */ #ifndef CPU_CONF_H #define CPU_CONF_H @@ -20,39 +23,63 @@ extern "C" { #endif +/* MARK: - CPU-specific default stack sizes */ /** - * @brief CPU specific default stack sizes + * @brief CPU-specific default stack sizes * - * TODO: tighten stack sizes + * @todo TODO: tighten stack sizes * * @{ */ -#ifndef THREAD_STACKSIZE_DEFAULT -#if (__SIZEOF_POINTER__ == 8) -#define THREAD_STACKSIZE_DEFAULT (16384) -#else -#define THREAD_STACKSIZE_DEFAULT (8192) +#if !defined(THREAD_STACKSIZE_DEFAULT) || defined(DOXYGEN) +/** + * @brief Default size of a thread stack + */ +# if (__SIZEOF_POINTER__ == 8) +# define THREAD_STACKSIZE_DEFAULT (16384) +# else +# define THREAD_STACKSIZE_DEFAULT (8192) +# endif #endif +/** + * @brief Default size of idle thread stack + */ +#if !defined(THREAD_STACKSIZE_IDLE) || defined(DOXYGEN) +# define THREAD_STACKSIZE_IDLE (THREAD_STACKSIZE_DEFAULT) #endif -#ifndef THREAD_STACKSIZE_IDLE -#define THREAD_STACKSIZE_IDLE (THREAD_STACKSIZE_DEFAULT) +/** + * @brief Extra stack buffer capacity needed for `printf` + */ +#if !defined(THREAD_EXTRA_STACKSIZE_PRINTF) || defined(DOXYGEN) +# define THREAD_EXTRA_STACKSIZE_PRINTF (4096) #endif -#ifndef THREAD_EXTRA_STACKSIZE_PRINTF -#define THREAD_EXTRA_STACKSIZE_PRINTF (4096) -#endif -#ifndef THREAD_EXTRA_STACKSIZE_PRINTF_FLOAT -#define THREAD_EXTRA_STACKSIZE_PRINTF_FLOAT (4096) +/** + * @brief Extra stack buffer capacity needed for `printf` in floating-point operations + */ +#if !defined(THREAD_EXTRA_STACKSIZE_PRINTF_FLOAT) || defined(DOXYGEN) +# define THREAD_EXTRA_STACKSIZE_PRINTF_FLOAT (4096) #endif /* for core/include/thread.h */ -#ifndef THREAD_STACKSIZE_MINIMUM -#define THREAD_STACKSIZE_MINIMUM (THREAD_STACKSIZE_DEFAULT) +/** + * @brief Minimum thread size + */ +#if !defined(THREAD_STACKSIZE_MINIMUM) || defined(DOXYGEN) +# define THREAD_STACKSIZE_MINIMUM (THREAD_STACKSIZE_DEFAULT) #endif /* native internal */ -#ifndef ISR_STACKSIZE -#define ISR_STACKSIZE (THREAD_STACKSIZE_DEFAULT) +/** + * @brief Size of stack used in ISR context + */ +#if !defined(ISR_STACKSIZE) || defined(DOXYGEN) +# define ISR_STACKSIZE (THREAD_STACKSIZE_DEFAULT) #endif /** @} */ +/* MARK: - Networking constants */ +/** + * @name Networking constants + * @{ + */ /** * @brief Native internal Ethernet protocol number */ @@ -62,30 +89,64 @@ extern "C" { # undef CONFIG_GNRC_PKTBUF_SIZE # define CONFIG_GNRC_PKTBUF_SIZE (2048) #endif +/** @} */ +/* MARK: - Native flash emulation */ /** - * @brief Native Flash emulation - * Use unusual parameters to trigger edge cases + * @name Native flash emulation + * Use unusual parameters to trigger edge cases * @{ */ -#ifndef FLASHPAGE_SIZE -#define FLASHPAGE_SIZE (512) -#endif -#ifndef FLASHPAGE_NUMOF -#define FLASHPAGE_NUMOF (32) -#endif -#ifndef FLASHPAGE_WRITE_BLOCK_ALIGNMENT -#define FLASHPAGE_WRITE_BLOCK_ALIGNMENT (8) -#endif -#ifndef FLASHPAGE_WRITE_BLOCK_SIZE -#define FLASHPAGE_WRITE_BLOCK_SIZE (16) -#endif -#ifndef FLASHPAGE_ERASE_STATE -#define FLASHPAGE_ERASE_STATE (0x0) +/** + * @brief Size of a single emulated flash page + */ +#if !defined(FLASHPAGE_SIZE) || defined(DOXYGEN) +# define FLASHPAGE_SIZE (512) #endif +/** + * @brief Total number of emulated flash pages + */ +#if !defined(FLASHPAGE_NUMOF) || defined(DOXYGEN) +# define FLASHPAGE_NUMOF (32) +#endif + +/** + * @brief Flashpage alignment + * + * The address passed to @ref flashpage_write must be a multiple of this constant. + */ +#if !defined(FLASHPAGE_WRITE_BLOCK_ALIGNMENT) || defined(DOXYGEN) +# define FLASHPAGE_WRITE_BLOCK_ALIGNMENT (8) +#endif +/** + * @brief Flashpage block size + * + * When writing to flash, the data size must be a multiple of this constant. + * + * @see @ref flashpage_write + */ +#if !defined(FLASHPAGE_WRITE_BLOCK_SIZE) || defined(DOXYGEN) +# define FLASHPAGE_WRITE_BLOCK_SIZE (16) +#endif + +/** + * @brief Value of bytes in erased flash + * + * The flash is set to this constant when you call @ref flashpage_erase. + */ +#if !defined(FLASHPAGE_ERASE_STATE) || defined(DOXYGEN) +# define FLASHPAGE_ERASE_STATE (0x0) +#endif + +/** + * @brief Emulated flash buffer + */ extern char _native_flash[FLASHPAGE_SIZE * FLASHPAGE_NUMOF]; +/** + * @brief Base buffer pointer to emulated flash + */ #define CPU_FLASH_BASE ((uintptr_t)_native_flash) /** @} */ @@ -94,3 +155,4 @@ extern char _native_flash[FLASHPAGE_SIZE * FLASHPAGE_NUMOF]; #endif #endif /* CPU_CONF_H */ +/** @} */ diff --git a/cpu/native/include/eeprom_native.h b/cpu/native/include/eeprom_native.h index eb1238029a..ee4acce576 100644 --- a/cpu/native/include/eeprom_native.h +++ b/cpu/native/include/eeprom_native.h @@ -7,17 +7,16 @@ */ /** - * @defgroup drivers_eeprom_native Native extra API for EEPROM - * @ingroup cpu_native - * @brief Implementation of EEPROM buffer persistence in file. - * + * @defgroup drivers_eeprom_native Native extra API for EEPROM + * @ingroup cpu_native + * @brief Implementation of EEPROM buffer persistence in file. * @{ - * - * @file - * - * @author Alexandre Abadie */ +/** + * @file + * @author Alexandre Abadie + */ #ifndef EEPROM_NATIVE_H #define EEPROM_NATIVE_H @@ -27,8 +26,11 @@ extern "C" { #endif -#ifndef EEPROM_FILEPATH_MAX_LEN -#define EEPROM_FILEPATH_MAX_LEN (128U) /**< Maximum path len to store the EEPROM filepath */ +#if !defined(EEPROM_FILEPATH_MAX_LEN) || defined(DOXYGEN) +/** + * @brief Maximum path len to store the EEPROM filepath + */ +# define EEPROM_FILEPATH_MAX_LEN (128U) #endif /** diff --git a/cpu/native/include/gpiodev_linux.h b/cpu/native/include/gpiodev_linux.h index 456bdf659c..f65c119908 100644 --- a/cpu/native/include/gpiodev_linux.h +++ b/cpu/native/include/gpiodev_linux.h @@ -7,9 +7,10 @@ */ /** - * @defgroup drivers_gpio_linux Linux User Mode GPIO Driver - * @ingroup cpu_native - * @brief Implementation of GPIO access from Linux User Space + * @defgroup drivers_gpio_linux Linux User Mode GPIO Driver + * @ingroup cpu_native + * @brief Implementation of GPIO access from Linux User Space + * @{ * * This module allows to connect a RIOT application that runs on a Linux host to * the physical GPIO pins of that host. To do so, the application has to be @@ -34,15 +35,13 @@ * port would be PIN(0,1) and so on. * * Please refer to your board's documentation for the mapping of the pins. - * - * @{ - * - * @file - * @brief Implementation of GPIO access from Linux User Space - * - * @author Benjamin Valentin */ +/** + * @file + * @brief Implementation of GPIO access from Linux User Space + * @author Benjamin Valentin + */ #ifndef GPIODEV_LINUX_H #define GPIODEV_LINUX_H diff --git a/cpu/native/include/mtd_native.h b/cpu/native/include/mtd_native.h index 7ba16cbeb4..0eee280176 100644 --- a/cpu/native/include/mtd_native.h +++ b/cpu/native/include/mtd_native.h @@ -7,16 +7,16 @@ */ /** - * @ingroup drivers_mtd + * @addtogroup drivers_mtd * @defgroup drivers_mtd_native Native MTD + * @brief MTD flash emulation for native * @{ - * @brief mtd flash emulation for native - * - * @file - * - * @author Vincent Dupont */ +/** + * @file + * @author Vincent Dupont + */ #ifndef MTD_NATIVE_H #define MTD_NATIVE_H @@ -42,5 +42,4 @@ extern const mtd_desc_t native_flash_driver; #endif #endif /* MTD_NATIVE_H */ - /** @} */ diff --git a/cpu/native/include/native_cli_eui_provider.h b/cpu/native/include/native_cli_eui_provider.h index 0ed57a7a22..a019c73986 100644 --- a/cpu/native/include/native_cli_eui_provider.h +++ b/cpu/native/include/native_cli_eui_provider.h @@ -7,15 +7,15 @@ */ /** - * @ingroup cpu_native + * @addtogroup cpu_native * @{ - * - * @file - * @brief Command-line EUI provider for native - * - * @author Benjamin Valentin */ +/** + * @file + * @brief Command-line EUI provider for native + * @author Benjamin Valentin + */ #ifndef NATIVE_CLI_EUI_PROVIDER_H #define NATIVE_CLI_EUI_PROVIDER_H @@ -26,17 +26,17 @@ extern "C" { #endif /** - * @name parse a string as an EUI-64 and add it to the list of EUI-64s + * @brief parse a string as an EUI-64 and add it to the list of EUI-64s * - * @param s[in] EUI-64 as hexadecimal string representation + * @param[in] s EUI-64 as hexadecimal string representation */ void native_cli_add_eui64(const char *s); /** - * @name Get a command-line provided EUI-64 + * @brief Get a command-line provided EUI-64 * * @param index index of ZEP device - * @param addr[out] user supplied EUI-64 + * @param[out] addr user supplied EUI-64 * * @return 0 on success, negatvie if no more EUIs are available. */ diff --git a/cpu/native/include/native_internal.h b/cpu/native/include/native_internal.h index 91744bab50..16e64e276a 100644 --- a/cpu/native/include/native_internal.h +++ b/cpu/native/include/native_internal.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2013, 2014 Ludwig Knüpfer + * Copyright (C) 2025 carl-tud * * 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 @@ -7,54 +8,39 @@ */ /** - * Native CPU internal declarations - */ - -/** - * @defgroup cpu_native_stdio STDIO for native - * @ingroup sys_stdio - * @brief Standard input/output backend for native + * @defgroup cpu_native_stdio STDIO for native + * @ingroup sys_stdio + * @brief Standard input/output backend for native + * @{ * * This will hook up RIOT's stdio to the host's stdio fds. It is the default * stdio implementation of the board `native`. * - * @see cpu_native + * @see @ref cpu_native + + * @} */ /** - * @ingroup cpu_native + * @addtogroup cpu_native * @{ - * @author Ludwig Knüpfer */ +/** + * @file + * @brief Native CPU internal symbols + * @author Ludwig Knüpfer + * @author carl-tud + */ #ifndef NATIVE_INTERNAL_H #define NATIVE_INTERNAL_H -#include +#include "util/ucontext.h" #include #include #include -/* enable signal handler register access on different platforms - * check here for more: - * http://sourceforge.net/p/predef/wiki/OperatingSystems/ - */ -#ifdef __FreeBSD__ -#ifndef _XOPEN_SOURCE -#define _XOPEN_SOURCE -#include -#undef _XOPEN_SOURCE -#else -#include -#endif -#elif defined(__linux__) -#ifndef _GNU_SOURCE -#define GNU_SOURCE -#include -#undef GNU_SOURCE -#else -#include -#endif -#endif /* BSD/Linux */ + +#include #include #include #include @@ -64,150 +50,287 @@ #include #include +#include "cpu_conf.h" +#include "thread.h" +#include "sched.h" + #ifdef __cplusplus extern "C" { #endif +#include "syscalls.h" + +/* MARK: - Internal native CPU API */ /** - * Prototype for native's internal callbacks + * @name Internal native CPU API + * @{ + */ + +/** + * @brief Prototype for native's internal callbacks */ typedef void (*_native_callback_t)(void); /** - * @cond INTERNAL - * internal functions + * @brief Initializes native CPU */ void native_cpu_init(void); +/** @} */ + +/* MARK: - Native Signal Handling */ +/** + * @name Native Signal Handling + * @{ + */ + +/** + * @brief A boolean variable indicating whether interrupts are currently permissible + * @private + */ +extern volatile bool _native_interrupts_enabled; + +/** + * @brief Pipe yielding signals + * @private + * + * The internal signal handler writes into the write end of this pipe + */ +extern int _signal_pipe_fd[2]; + +/** + * @brief Number of currently pending signals + * @private + */ +extern volatile int _native_pending_signals; + +/** + * @brief Registers signal handlers for the native CPU + */ void native_interrupt_init(void); -void native_irq_handler(void); +/** + * @brief Register interrupt handler handler for interrupt signal + * + * @param sig Signal number + * @param handler Signal action function + * + * @returns 0 on success, negative number otherwise. + */ +int native_register_interrupt(int sig, _native_callback_t handler); + +/** + * @brief Unregister interrupt handler for interrupt signal + * + * @param sig Signal number + * + * @returns 0 on success, negative number otherwise. + */ +int native_unregister_interrupt(int sig); + +/** + * @brief Calls signal handlers for pending signal, then exits ISR context and performs context switch + * @pre Intended to be called from **ISR context** + * @private + * + * The context switch back to userspace is performed using @ref `cpu_switch_context_exit`. + * + * @note While it would have been possible to separate this method's functionality into two functions, `setcontext` requires us to have a single function. + */ +void _native_call_sig_handlers_and_switch(void); + +/** + * @brief Switches to ISR context, then enables IRQ and returns to userspace + * + * @note This function is implemented in assembly. + */ extern void _native_sig_leave_tramp(void); -extern void _native_sig_leave_handler(void); +/** @} */ + +/* MARK: - System Calls */ +/** + * @name System Calls + * + * We wrap system calls and syscall-invoking library calls to ensure **no context switches occur during a system call**. + * @{ + */ +/** + * @brief Number of currently pending system calls + * @private + */ +extern volatile int _native_pending_syscalls; + +/** + * @brief Increment spending system call counter + */ +static inline void _native_pending_syscalls_up(void) { + _native_pending_syscalls += 1; +} + +/** + * @brief Decrements pending system call counter + */ +static inline void _native_pending_syscalls_down(void) { + _native_pending_syscalls -= 1; +} + +/** + * @brief Executes post-syscall logic + * @private + * + * Decrements internal pending syscall counter. + * + * If there are other pending system calls and when not already in an ISR context, this function switches to the ISR context and + * calls signals handlers. This is done through @ref `_native_call_sig_handlers_and_switch`. Returns to userspace + * thereafter. + */ void _native_syscall_leave(void); + +/** + * @brief Executes pre-syscall logic + * @private + * + * Increments internal pending syscall counter. + */ void _native_syscall_enter(void); + +/** + * @brief Registers system calls. + * + * Wraps syscall functions from the standard library. + */ void _native_init_syscalls(void); +/** @} */ + +/* MARK: - Native Context Switching */ +/** + * @name Native Context Switching + * @{ + */ /** - * external functions regularly wrapped in native for direct use + * @brief Points to instruction in userspace where RIOT left off and switched to ISR context */ -extern ssize_t (*real_read)(int fd, void *buf, size_t count); -extern ssize_t (*real_write)(int fd, const void *buf, size_t count); -extern off_t (*real_lseek)(int fd, off_t offset, int whence); -extern off_t (*real_fstat)(int fd, struct stat *statbuf); -extern int (*real_statvfs)(const char *restrict path, struct statvfs *restrict buf); -extern int (*real_fsync)(int fd); -extern size_t (*real_fread)(void *ptr, size_t size, size_t nmemb, FILE *stream); -extern void (*real_clearerr)(FILE *stream); -extern __attribute__((noreturn)) void (*real_exit)(int status); -extern void (*real_free)(void *ptr); -extern void* (*real_calloc)(size_t nmemb, size_t size); -extern void* (*real_malloc)(size_t size); -extern void* (*real_realloc)(void *ptr, size_t size); -extern void (*real_freeaddrinfo)(struct addrinfo *res); -extern void (*real_freeifaddrs)(struct ifaddrs *ifa); -extern void (*real_srandom)(unsigned int seed); -/* The ... is a hack to save includes: */ -extern int (*real_accept)(int socket, ...); -/* The ... is a hack to save includes: */ -extern int (*real_bind)(int socket, ...); -extern int (*real_connect)(int socket, ...); -extern ssize_t (*real_recv)(int sockfd, void *buf, size_t len, int flags); -extern int (*real_chdir)(const char *path); -extern int (*real_close)(int); -extern int (*real_fcntl)(int, int, ...); -/* The ... is a hack to save includes: */ -extern int (*real_creat)(const char *path, ...); -extern int (*real_dup2)(int, int); -extern int (*real_execve)(const char *, char *const[], char *const[]); -extern int (*real_feof)(FILE *stream); -extern int (*real_ferror)(FILE *stream); -extern int (*real_fork)(void); -/* The ... is a hack to save includes: */ -extern int (*real_getaddrinfo)(const char *node, ...); -extern int (*real_getifaddrs)(struct ifaddrs **ifap); -extern int (*real_getpid)(void); -extern int (*real_gettimeofday)(struct timeval *t, ...); -extern int (*real_ioctl)(int fildes, unsigned long request, ...); -extern int (*real_listen)(int socket, int backlog); -extern int (*real_open)(const char *path, int oflag, ...); -extern int (*real_mkdir)(const char *pathname, mode_t mode); -extern int (*real_rmdir)(const char *pathname); -extern DIR *(*real_opendir)(const char *name); -extern struct dirent *(*real_readdir)(DIR *dirp); -extern int (*real_closedir)(DIR *dirp); -extern int (*real_pause)(void); -extern int (*real_pipe)(int[2]); -/* The ... is a hack to save includes: */ -extern int (*real_select)(int nfds, ...); -extern int (*real_poll)(struct pollfd *nfds, ...); -extern int (*real_setitimer)(int which, const struct itimerval - *__restrict value, struct itimerval *__restrict ovalue); -extern int (*real_setsid)(void); -extern int (*real_setsockopt)(int socket, ...); -extern int (*real_socket)(int domain, int type, int protocol); -extern int (*real_printf)(const char *format, ...); -extern int (*real_unlink)(const char *); -extern int (*real_rename)(const char *, const char *); -extern long int (*real_random)(void); -extern const char* (*real_gai_strerror)(int errcode); -extern FILE* (*real_fopen)(const char *path, const char *mode); -extern int (*real_fclose)(FILE *stream); -extern int (*real_fseek)(FILE *stream, long offset, int whence); -extern long (*real_ftell)(FILE *stream); -extern int (*real_fputc)(int c, FILE *stream); -extern int (*real_fgetc)(FILE *stream); -extern mode_t (*real_umask)(mode_t cmask); -extern ssize_t (*real_writev)(int fildes, const struct iovec *iov, int iovcnt); -extern ssize_t (*real_send)(int sockfd, const void *buf, size_t len, int flags); +extern volatile uintptr_t _native_user_fptr; /** - * data structures + * @brief A boolean variable indicating whether program execution currently takes place in an ISR context */ -extern volatile int native_interrupts_enabled; -extern volatile uintptr_t _native_saved_eip; -extern int _sig_pipefd[2]; -extern volatile int _native_sigpend; extern volatile int _native_in_isr; -extern volatile int _native_in_syscall; -extern char __isr_stack[]; -extern const size_t __isr_stack_size; -extern ucontext_t native_isr_context; -extern ucontext_t end_context; -extern ucontext_t *_native_cur_ctx, *_native_isr_ctx; +/** + * @brief Stack used in ISR context + */ +extern char _isr_stack[THREAD_STACKSIZE_DEFAULT]; +/** + * @brief ISR context + */ +extern ucontext_t *_native_isr_context; + +/** + * @brief Resets internal `in_ISR` barrier switch and resumes execution on the currently scheduled thread + * @pre Intended to be executed in userspace + * @private + * + * @note This function is implemented in assembly to preserve registers. See `native.S` + */ +extern void _native_isr_leave(void); + +/** + * @brief Makes ISR context so that execution continues at `func` when the context is applied + * + * @param func Function executed when `_native_isr_context` is applied + */ +static inline void _native_isr_context_make(void (*func)(void)) { + _native_isr_context->uc_stack.ss_sp = _isr_stack; + _native_isr_context->uc_stack.ss_size = sizeof(_isr_stack); + _native_isr_context->uc_stack.ss_flags = 0; + + /* Create the ISR context, will execute _isr_schedule_and_switch */ + makecontext(_native_isr_context, func, 0); +} + +/** + * @brief Retrieves user context + * @returns `ucontext_t` + */ +static inline ucontext_t* _native_user_context(void) { + /* Use intermediate cast to uintptr_t to silence -Wcast-align. + * stacks are manually word aligned in thread_static_init() */ + return (ucontext_t *)(uintptr_t)thread_get_active()->sp; +} +/** @} */ + +/* MARK: - Native Process State */ +/** + * @name Native Process State + * @{ + */ +/** + * @brief Program name + * @private + */ extern const char *_progname; + +/** + * @brief Program argument values + * @private + */ extern char **_native_argv; + +/** + * @brief Process Identifier + * @private + */ extern pid_t _native_pid; + +/** + * @brief Process Identifier / CPUID ??? + * @private + */ extern pid_t _native_id; -extern unsigned _native_rng_seed; -extern int _native_rng_mode; /**< 0 = /dev/random, 1 = random(3) */ -extern const char *_native_unix_socket_path; +/** + * @brief Random number generator seed value + * @private + */ +extern unsigned int _native_rng_seed; + +/** + * @brief Random number generator mode + * @private + * + * - `0`: Use `/dev/random` + * - `1`: Use `random(3)` + */ +extern int _native_rng_mode; +/** @} */ + +/* MARK: - Native Read/Write Methods */ +/** + * @name Native Read/Write Methods + * @{ + */ +/** + * @brief Reads file, populates given buffer + */ ssize_t _native_read(int fd, void *buf, size_t count); + +/** + * @brief Writes given data into file + */ ssize_t _native_write(int fd, const void *buf, size_t count); + +/** + * @brief Performs a vectored write operation + */ ssize_t _native_writev(int fildes, const struct iovec *iov, int iovcnt); - -/** - * @endcond - */ - -/** - * register interrupt handler handler for interrupt sig - */ -int register_interrupt(int sig, _native_callback_t handler); - -/** - * unregister interrupt handler for interrupt sig - */ -int unregister_interrupt(int sig); +/** @} */ #ifdef __cplusplus } #endif -#include "sched.h" - -/** @} */ #endif /* NATIVE_INTERNAL_H */ +/** @} */ diff --git a/cpu/native/include/netdev_tap.h b/cpu/native/include/netdev_tap.h index 197cb89d9e..ef24280887 100644 --- a/cpu/native/include/netdev_tap.h +++ b/cpu/native/include/netdev_tap.h @@ -7,15 +7,15 @@ */ /** - * @ingroup drivers_netdev - * @brief Low-level ethernet driver for native tap interfaces + * @addtogroup drivers_netdev * @{ - * + */ + +/** * @file - * @brief Definitions for @ref netdev ethernet driver for host system's - * TAP interfaces - * - * @author Kaspar Schleiser + * @brief Definitions for @ref netdev ethernet driver for host system's + * TAP interfaces + * @author Kaspar Schleiser */ #ifndef NETDEV_TAP_H #define NETDEV_TAP_H @@ -32,6 +32,11 @@ extern "C" { #include "net/if.h" +/* MARK: - Low-level ethernet driver for native tap interfaces */ +/** + * @name Low-level ethernet driver for native tap interfaces + * @{ + */ /** * @brief tap interface state */ @@ -63,9 +68,11 @@ typedef struct { * If initialized manually, pass a unique identifier instead. */ void netdev_tap_setup(netdev_tap_t *dev, const netdev_tap_params_t *params, int index); +/** @} */ #ifdef __cplusplus } #endif -/** @} */ + #endif /* NETDEV_TAP_H */ +/** @} */ diff --git a/cpu/native/include/netdev_tap_params.h b/cpu/native/include/netdev_tap_params.h index a588ab921b..766a714647 100644 --- a/cpu/native/include/netdev_tap_params.h +++ b/cpu/native/include/netdev_tap_params.h @@ -7,14 +7,14 @@ */ /** - * @ingroup drivers_netdev - * @brief + * @addtogroup drivers_netdev * @{ - * + */ + +/** * @file - * @brief Default configuration for the netdev_tap driver - * - * @author Martine Lenders + * @brief Default configuration for the netdev_tap driver + * @author Martine Lenders */ #ifndef NETDEV_TAP_PARAMS_H #define NETDEV_TAP_PARAMS_H @@ -31,8 +31,8 @@ extern "C" { * @note This was decided to only be configurable on compile-time to be * more similar to actual boards */ -#ifndef NETDEV_TAP_MAX -#define NETDEV_TAP_MAX (1) +#if !defined(NETDEV_TAP_MAX) || defined(DOXYGEN) +# define NETDEV_TAP_MAX (1) #endif /** diff --git a/cpu/native/include/periph_conf.h b/cpu/native/include/periph_conf.h index 0df89b2c53..cf8aa132ce 100644 --- a/cpu/native/include/periph_conf.h +++ b/cpu/native/include/periph_conf.h @@ -1,18 +1,21 @@ -/** - * Native CPU peripheral configuration - * +/* * Copyright (C) 2014 Ludwig Knüpfer * * 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. - * - * @ingroup cpu_native - * @{ - * @file - * @author Ludwig Knüpfer */ +/** + * @addtogroup cpu_native + * @{ + */ + +/** + * @file + * @brief Native CPU peripheral configuration + * @author Ludwig Knüpfer + */ #ifndef PERIPH_CONF_H #define PERIPH_CONF_H @@ -23,70 +26,68 @@ extern "C" { #endif /** - * @brief System core clock in Hz + * @brief System core clock in Hz * * 1GHz is an arbitrary value used for compatibility with other platforms. */ -#ifndef CLOCK_CORECLOCK -#define CLOCK_CORECLOCK GHZ(1) +#if !defined(CLOCK_CORECLOCK) || defined(DOXYGEN) +# define CLOCK_CORECLOCK GHZ(1) #endif /** - * @name hardware timer clock skew avoidance - * @{ + * @brief Hardware timer clock skew avoidance */ #define NATIVE_TIMER_MIN_RES 200 -/** @} */ /** - * @name Random Number Generator configuration - * @{ + * @brief Random Number Generator configuration */ #define RANDOM_NUMOF (1U) -/** @} */ +/* MARK: - Timer peripheral configuration */ /** * @name Timer peripheral configuration * @{ */ #define TIMER_NUMOF (1U) #define TIMER_CHANNEL_NUMOF (1U) /**< Number of timer channels */ +/** @} */ +/* MARK: - xtimer configuration */ /** - * @brief xtimer configuration - */ -/* timer_set_absolute() has a high margin for possible underflow if set with + * @name `xtimer` configuration + * @{ + * + * @ref timer_set_absolute has a high margin for possible underflow if set with * value not far in the future. To prevent this, we set high backoff values * here. */ #define XTIMER_BACKOFF 200 #define XTIMER_ISR_BACKOFF 200 - /** @} */ /** * @brief UART configuration - * @{ */ -#ifndef UART_NUMOF -#define UART_NUMOF (1U) +#if !defined(UART_NUMOF) || defined(DOXYGEN) +# define UART_NUMOF (1U) #endif -/** @} */ /** * @brief PWM configuration */ -#ifndef PWM_NUMOF -#define PWM_NUMOF (8U) +#if !defined(PWM_NUMOF) || defined(DOXYGEN) +# define PWM_NUMOF (8U) #endif /** * @brief QDEC configuration */ -#ifndef QDEC_NUMOF -#define QDEC_NUMOF (8U) +#if !defined(QDEC_NUMOF) || defined(DOXYGEN) +# define QDEC_NUMOF (8U) #endif +/* MARK: - SPI configuration (Linux host only) */ /** * @name SPI configuration (Linux host only) * @{ @@ -101,7 +102,7 @@ extern "C" { * * Can be overridden during compile time with a `-DSPI_NUMOF=n` flag. */ -#define SPI_NUMOF (1U) +# define SPI_NUMOF (1U) #endif #if !defined(SPI_MAXCS) || defined(DOXYGEN) @@ -111,7 +112,7 @@ extern "C" { * Allows up to SPI_MAXCS hardware cable select lines per SPI device. The n-th * hardware select line can be used with the SPI_HWCS macro. */ -#define SPI_MAXCS (4U) +# define SPI_MAXCS (4U) #endif /** diff --git a/cpu/native/include/periph_cpu.h b/cpu/native/include/periph_cpu.h index 94d70693eb..f77e627233 100644 --- a/cpu/native/include/periph_cpu.h +++ b/cpu/native/include/periph_cpu.h @@ -7,15 +7,15 @@ */ /** - * @ingroup cpu_native + * @addtogroup cpu_native * @{ - * - * @file - * @brief CPU specific definitions for internal peripheral handling - * - * @author Hauke Petersen */ +/** + * @file + * @brief CPU specific definitions for internal peripheral handling + * @author Hauke Petersen + */ #ifndef PERIPH_CPU_H #define PERIPH_CPU_H @@ -28,15 +28,15 @@ extern "C" { /** * @brief Length of the CPU_ID in octets */ -#ifndef CPUID_LEN -#define CPUID_LEN (4U) +#if !defined(CPUID_LEN) || defined(DOXYGEN) +# define CPUID_LEN (4U) #endif /** - * @name Power mode configuration + * @brief Power mode configuration */ -#ifndef PM_NUM_MODES -#define PM_NUM_MODES (1U) +#if !defined(PM_NUM_MODES) || defined(DOXYGEN) +# define PM_NUM_MODES (1U) #endif /** @@ -46,30 +46,39 @@ extern "C" { /* GPIO configuration only if the module is available (=Linux) */ #if defined(MODULE_PERIPH_GPIO_LINUX) || defined(DOXYGEN) -#include +# include +/* MARK: - GPIO Configuration */ /** * @name GPIO Configuration * @{ */ - /** * @brief The offset between Port and Pin */ -#define GPIO_PORT_SHIFT (24) +# define GPIO_PORT_SHIFT (24) /** * @brief Define a custom GPIO_PIN macro for native */ -#define GPIO_PIN(port, pin) (gpio_t)((port << GPIO_PORT_SHIFT) | pin) +# define GPIO_PIN(port, pin) (gpio_t)((port << GPIO_PORT_SHIFT) | pin) -#define HAVE_GPIO_MODE_T -#ifndef GPIOHANDLE_REQUEST_PULL_DOWN -#define GPIOHANDLE_REQUEST_PULL_DOWN (0xFF) -#endif -#ifndef GPIOHANDLE_REQUEST_PULL_UP -#define GPIOHANDLE_REQUEST_PULL_UP (0xFF) -#endif +/** + * @brief Macro indicating whether GPIO modes are available on the native CPU + */ +# define HAVE_GPIO_MODE_T +/** + * @brief Pull-down + */ +# if !defined(GPIOHANDLE_REQUEST_PULL_DOWN) || defined(DOXYGEN) +# define GPIOHANDLE_REQUEST_PULL_DOWN (0xFF) +# endif +/** + * @brief Pull-up + */ +# if !defined(GPIOHANDLE_REQUEST_PULL_UP) || defined(DOXYGEN) +# define GPIOHANDLE_REQUEST_PULL_UP (0xFF) +# endif /** * @brief Available pin modes @@ -88,21 +97,27 @@ typedef enum { GPIO_OD_PU = GPIOHANDLE_REQUEST_OPEN_DRAIN | GPIOHANDLE_REQUEST_PULL_UP } gpio_mode_t; -#define HAVE_GPIO_FLANK_T +/** + * @brief A macro indicating whether the native CPU supports GPIO edge behavior + */ +# define HAVE_GPIO_FLANK_T + +/** + * @brief An enum for the type of flank that emit interrupts + */ typedef enum { GPIO_FALLING = GPIOEVENT_EVENT_FALLING_EDGE, /**< emit interrupt on falling flank */ GPIO_RISING = GPIOEVENT_EVENT_RISING_EDGE, /**< emit interrupt on rising flank */ GPIO_BOTH = GPIO_FALLING | GPIO_RISING /**< emit interrupt on both flanks */ } gpio_flank_t; - /** @} */ + #elif defined(MODULE_PERIPH_GPIO_MOCK) /** * @brief Mocked GPIO * * Mocked GPIO representation for simulation. - * @{ */ typedef struct { int value; /**< current value */ @@ -111,24 +126,23 @@ typedef struct { void (*cb)(void *arg); /**< ISR */ void *arg; /**< ISR arg */ } gpio_mock_t; -/** @} */ -#define GPIO_UNDEF 0 +# define GPIO_UNDEF 0 -#ifndef GPIO_PORT_MAX -#define GPIO_PORT_MAX (16) -#endif +# if !defined(GPIO_PORT_MAX) || defined(DOXYGEN) +# define GPIO_PORT_MAX (16) +# endif -#ifndef GPIO_PIN_MAX -#define GPIO_PIN_MAX (32) -#endif +# if !defined(GPIO_PIN_MAX) || defined(DOXYGEN) +# define GPIO_PIN_MAX (32) +# endif /** * @brief Mocked GPIO array */ extern gpio_mock_t gpio_mock[GPIO_PORT_MAX][GPIO_PIN_MAX]; -#define HAVE_GPIO_T +# define HAVE_GPIO_T /** * @brief Pointer on a mocked GPIO */ @@ -138,7 +152,7 @@ typedef gpio_mock_t* gpio_t; * @brief Define a custom GPIO_PIN macro for native mocked GPIO framework. * Get the mocked GPIO object from mocked GPIO array. */ -#define GPIO_PIN(port, pin) \ +# define GPIO_PIN(port, pin) \ (((port >= 0) && (pin >= 0) && (port < GPIO_PORT_MAX) && (pin < GPIO_PIN_MAX)) \ ? &gpio_mock[port][pin] \ : GPIO_UNDEF) @@ -150,8 +164,9 @@ typedef gpio_mock_t* gpio_t; */ #define PERIPH_TIMER_PROVIDES_SET +/* MARK: - Power management configuration*/ /** - * @name Power management configuration + * @name Power management configuration * @{ */ #define PROVIDES_PM_OFF @@ -164,35 +179,34 @@ typedef gpio_mock_t* gpio_t; * spi.h. */ #if defined(MODULE_PERIPH_SPIDEV_LINUX) || defined(DOXYGEN) - +/* MARK: - SPI Configuration */ /** * @name SPI Configuration + * @{ */ - /** * @brief Use the common `transfer_byte` SPI function */ -#define PERIPH_SPI_NEEDS_TRANSFER_BYTE +# define PERIPH_SPI_NEEDS_TRANSFER_BYTE /** * @brief Use the common `transfer_reg` SPI function */ -#define PERIPH_SPI_NEEDS_TRANSFER_REG +# define PERIPH_SPI_NEEDS_TRANSFER_REG /** * @brief Use the common `transfer_regs` SPI function */ -#define PERIPH_SPI_NEEDS_TRANSFER_REGS +# define PERIPH_SPI_NEEDS_TRANSFER_REGS -#ifndef DOXYGEN +# ifndef DOXYGEN /** * @brief Use a custom clock speed type */ -#define HAVE_SPI_CLK_T +# define HAVE_SPI_CLK_T /** * @brief SPI clock speed values * * The Linux userspace driver takes values in Hertz, which values are available * can only be determined at runtime. - * @{ */ typedef enum { SPI_CLK_100KHZ = (100000U), @@ -201,21 +215,19 @@ typedef enum { SPI_CLK_5MHZ = (5000000U), SPI_CLK_10MHZ = (10000000U) } spi_clk_t; +# endif /* ndef DOXYGEN */ /** @} */ -#endif /* ndef DOXYGEN */ #endif /* MODULE_PERIPH_SPI | DOXYGEN */ /** - * @name EEPROM configuration - * @{ + * @brief EEPROM configuration */ -#ifndef EEPROM_SIZE -#define EEPROM_SIZE (1024U) /* 1kB */ +#if !defined(EEPROM_SIZE) || defined(DOXYGEN) +# define EEPROM_SIZE (1024U) /* 1kB */ #endif -/** @} */ #ifdef MODULE_PERIPH_CAN -#include "candev_linux.h" +# include "candev_linux.h" #endif #ifdef __cplusplus diff --git a/cpu/native/include/socket_zep.h b/cpu/native/include/socket_zep.h index ac2a7edd2a..eda624b7ca 100644 --- a/cpu/native/include/socket_zep.h +++ b/cpu/native/include/socket_zep.h @@ -7,9 +7,10 @@ */ /** - * @defgroup drivers_socket_zep Socket-based ZEP - * @ingroup drivers_netdev - * @brief UDP socket-based IEEE 802.15.4 device over ZEP + * @defgroup drivers_socket_zep Socket-based ZEP + * @ingroup drivers_netdev + * @brief UDP socket-based IEEE 802.15.4 device over ZEP + * @{ * * @see @ref net_zep for protocol definitions * @@ -46,12 +47,12 @@ * | 0 | 0 | 0 | 0 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * - * @{ - * + */ + +/** * @file - * @brief Socket ZEP definitions - * - * @author Martine Lenders + * @brief Socket ZEP definitions + * @author Martine Lenders */ #ifndef SOCKET_ZEP_H #define SOCKET_ZEP_H diff --git a/cpu/native/include/socket_zep_params.h b/cpu/native/include/socket_zep_params.h index 7e9a1fe2bd..8736ce548f 100644 --- a/cpu/native/include/socket_zep_params.h +++ b/cpu/native/include/socket_zep_params.h @@ -7,13 +7,14 @@ */ /** - * @ingroup drivers_socket_zep + * @addtogroup drivers_socket_zep * @{ - * + */ + +/** * @file - * @brief Configuration parameters for the @ref drivers_socket_zep driver - * - * @author Martine Lenders + * @brief Configuration parameters for the @ref drivers_socket_zep driver + * @author Martine Lenders */ #ifndef SOCKET_ZEP_PARAMS_H #define SOCKET_ZEP_PARAMS_H @@ -30,8 +31,8 @@ extern "C" { * @note This was decided to only be confiruable on compile-time to be * more similar to actual boards */ -#ifndef SOCKET_ZEP_MAX -#define SOCKET_ZEP_MAX (1) +#if !defined(SOCKET_ZEP_MAX) || defined(DOXYGEN) +# define SOCKET_ZEP_MAX (1) #endif /** diff --git a/cpu/native/include/spidev_linux.h b/cpu/native/include/spidev_linux.h index 2914a311d6..0849302103 100644 --- a/cpu/native/include/spidev_linux.h +++ b/cpu/native/include/spidev_linux.h @@ -7,9 +7,10 @@ */ /** - * @defgroup drivers_spidev_linux Linux User Mode SPI Driver - * @ingroup cpu_native - * @brief Implementation of SPI access from Linux User Space + * @defgroup drivers_spidev_linux Linux User Mode SPI Driver + * @ingroup cpu_native + * @brief Implementation of SPI access from Linux User Space + * @{ * * This module allows to connect a RIOT application that runs on a Linux host to * the physical SPI bus(ses) of that host. To do so, the application has to be @@ -50,15 +51,13 @@ * select the file descriptor with the lowest HWCS id for that bus, but the * actual CS line will not be pulled low (if the hardware supports this). This * would (in principle) allow to control CS manually. - * - * @{ - * - * @file - * @brief Implementation of SPI access from Linux User Space - * - * @author Frank Hessel */ +/** + * @file + * @brief Implementation of SPI access from Linux User Space + * @author Frank Hessel + */ #ifndef SPIDEV_LINUX_H #define SPIDEV_LINUX_H diff --git a/cpu/native/include/syscalls.h b/cpu/native/include/syscalls.h new file mode 100644 index 0000000000..3a9f3c720f --- /dev/null +++ b/cpu/native/include/syscalls.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2013 Ludwig Knüpfer + * + * 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. + */ + +#ifndef SYSCALLS_H +#define SYSCALLS_H + +#include +#include +#include +#include + +/** + * @addtogroup cpu_native + * @{ + */ + +#ifndef DOXYGEN +# if NATIVE_SYSCALLS_DEFINITION +# define __SPECIFIER +# else +# define __SPECIFIER extern +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* MARK: - System call wrappers */ +/** @cond */ +/** + * @name System call wrappers + * + * Internally, these function pointers are assigned their implementation in the standard library. + * We wrap system calls and syscall-invoking library calls to ensure **no context switches occur during a system call**. + * @{ + */ +__SPECIFIER ssize_t (*real_read)(int fd, void *buf, size_t count); +__SPECIFIER ssize_t (*real_write)(int fd, const void *buf, size_t count); +__SPECIFIER size_t (*real_fread)(void *ptr, size_t size, size_t nmemb, FILE *stream); +__SPECIFIER ssize_t (*real_recv)(int sockfd, void *buf, size_t len, int flags); +__SPECIFIER void (*real_clearerr)(FILE *stream); +__SPECIFIER __attribute__((noreturn)) void (*real_exit)(int status); +__SPECIFIER void (*real_free)(void *ptr); +__SPECIFIER void* (*real_malloc)(size_t size); +__SPECIFIER void* (*real_calloc)(size_t nmemb, size_t size); +__SPECIFIER void* (*real_realloc)(void *ptr, size_t size); +__SPECIFIER void (*real_freeaddrinfo)(struct addrinfo *res); +__SPECIFIER void (*real_freeifaddrs)(struct ifaddrs *ifa); +__SPECIFIER void (*real_srandom)(unsigned int seed); +__SPECIFIER int (*real_accept)(int socket, ...); +__SPECIFIER int (*real_bind)(int socket, ...); +__SPECIFIER int (*real_connect)(int socket, ...); +__SPECIFIER int (*real_printf)(const char *format, ...); +__SPECIFIER int (*real_getaddrinfo)(const char *node, ...); +__SPECIFIER int (*real_getifaddrs)(struct ifaddrs **ifap); +__SPECIFIER int (*real_gettimeofday)(struct timeval *t, ...); +__SPECIFIER int (*real_getpid)(void); +__SPECIFIER int (*real_chdir)(const char *path); +__SPECIFIER int (*real_close)(int); +__SPECIFIER int (*real_fcntl)(int, int, ...); +__SPECIFIER int (*real_creat)(const char *path, ...); +__SPECIFIER int (*real_dup2)(int, int); +__SPECIFIER int (*real_execve)(const char *, char *const[], char *const[]); +__SPECIFIER int (*real_fork)(void); +__SPECIFIER int (*real_feof)(FILE *stream); +__SPECIFIER int (*real_ferror)(FILE *stream); +__SPECIFIER int (*real_listen)(int socket, int backlog); +__SPECIFIER int (*real_ioctl)(int fildes, unsigned long request, ...); +__SPECIFIER int (*real_open)(const char *path, int oflag, ...); +__SPECIFIER int (*real_pause)(void); +__SPECIFIER int (*real_pipe)(int[2]); +__SPECIFIER int (*real_select)(int nfds, ...); +__SPECIFIER int (*real_poll)(struct pollfd *fds, ...); +__SPECIFIER int (*real_setsid)(void); +__SPECIFIER int (*real_setsockopt)(int socket, ...); +__SPECIFIER int (*real_socket)(int domain, int type, int protocol); +__SPECIFIER int (*real_unlink)(const char *); +__SPECIFIER long int (*real_random)(void); +__SPECIFIER const char* (*real_gai_strerror)(int errcode); +__SPECIFIER FILE* (*real_fopen)(const char *path, const char *mode); +__SPECIFIER int (*real_fclose)(FILE *stream); +__SPECIFIER int (*real_fseek)(FILE *stream, long offset, int whence); +__SPECIFIER long (*real_ftell)(FILE *stream); +__SPECIFIER int (*real_fputc)(int c, FILE *stream); +__SPECIFIER int (*real_fgetc)(FILE *stream); +__SPECIFIER mode_t (*real_umask)(mode_t cmask); +__SPECIFIER ssize_t (*real_writev)(int fildes, const struct iovec *iov, int iovcnt); +__SPECIFIER ssize_t (*real_send)(int sockfd, const void *buf, size_t len, int flags); +__SPECIFIER off_t (*real_lseek)(int fd, off_t offset, int whence); +__SPECIFIER off_t (*real_fstat)(int fd, struct stat *statbuf); +__SPECIFIER int (*real_fsync)(int fd); +__SPECIFIER int (*real_mkdir)(const char *pathname, mode_t mode); +__SPECIFIER int (*real_rmdir)(const char *pathname); +__SPECIFIER DIR *(*real_opendir)(const char *name); +__SPECIFIER struct dirent *(*real_readdir)(DIR *dirp); +__SPECIFIER int (*real_closedir)(DIR *dirp); +__SPECIFIER int (*real_rename)(const char *, const char *); +__SPECIFIER int (*real_statvfs)(const char *restrict path, struct statvfs *restrict buf); +/** @}*/ +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#if !defined(DOXYGEN) +# undef __SPECIFIER +#endif + +/** @} */ + +#endif /* SYSCALLS_H */ diff --git a/cpu/native/include/thread_arch.h b/cpu/native/include/thread_arch.h index d1ae2867b3..83ab0385e6 100644 --- a/cpu/native/include/thread_arch.h +++ b/cpu/native/include/thread_arch.h @@ -8,15 +8,15 @@ */ /** - * @ingroup cpu_native + * @addtogroup cpu_native * @{ - * - * @file - * @brief Implementation of the kernels thread interface - * - * @author Koen Zandberg */ +/** + * @file + * @brief Implementation of the kernels thread interface + * @author Koen Zandberg + */ #ifndef THREAD_ARCH_H #define THREAD_ARCH_H diff --git a/cpu/native/include/tty_uart.h b/cpu/native/include/tty_uart.h index aaac459a72..62871721cf 100644 --- a/cpu/native/include/tty_uart.h +++ b/cpu/native/include/tty_uart.h @@ -7,15 +7,15 @@ */ /** - * @ingroup cpu_native + * @addtogroup cpu_native * @{ - * - * @file - * @brief UART implementation based on /dev/tty devices on host - * - * @author Takuo Yonezawa */ +/** + * @file + * @brief UART implementation based on /dev/tty devices on host + * @author Takuo Yonezawa + */ #ifndef TTY_UART_H #define TTY_UART_H diff --git a/cpu/native/include/util/ucontext.h b/cpu/native/include/util/ucontext.h new file mode 100644 index 0000000000..1e11e8b846 --- /dev/null +++ b/cpu/native/include/util/ucontext.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2013 - 2016 Ludwig Knüpfer + * Copyright (C) 2025 carl-tud + * + * 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. + */ + +#ifndef UTIL_UCONTEXT_H +#define UTIL_UCONTEXT_H + +#if USE_LIBUCONTEXT +# include +#else +# include +#endif /* USE_LIBUCONTEXT */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup cpu_native + * @{ + */ + +/* MARK: - Context accessors */ +/** + * @name Context accessors + * @{ + */ + +/** + * @brief Retrieves function pointer generated during calls to `makecontext`/`setcontext`/`swapcontext` + * @param context `ucontext_t` + * @returns Function pointer (does not need to be start of a function, points to instruction) + */ +static inline uintptr_t _context_get_fptr(ucontext_t *context) { +# if defined(__FreeBSD__) /* FreeBSD */ + return (uintptr_t)((struct sigcontext *)context)->sc_eip; +# elif defined(__linux__) /* Linux */ +# if defined(__arm__) + return (uintptr_t)((ucontext_t *)context)->uc_mcontext.arm_pc; +# elif defined(__x86_64__) + return (uintptr_t)((ucontext_t *)context)->uc_mcontext.gregs[REG_RIP]; +# elif defined(__i386__) + return (uintptr_t)((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP]; +# else +# error "Unsupported Linux architecture" +# endif +# else +# error "Operating system unsupported" +# endif +} + +/** + * @brief Retrieves function pointer generated during calls to `makecontext`/`setcontext`/`swapcontext` + * @param context `ucontext_t` + * @param func Function pointer + */ +static inline void _context_set_fptr(ucontext_t *context, uintptr_t func) { +# if defined(__FreeBSD__) /* FreeBSD */ + ((struct sigcontext *)context)->sc_eip = (unsigned int)func; +# elif defined(__linux__) /* Linux */ +# if defined(__arm__) + ((ucontext_t *)context)->uc_mcontext.arm_lr = func; + ((ucontext_t *)context)->uc_mcontext.arm_pc = func; +# elif defined(__x86_64__) + ((ucontext_t *)context)->uc_mcontext.gregs[REG_RIP] = (greg_t)func; +# elif defined(__i386__) + ((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP] = func; +# else +# error "Unsupported Linux architecture" +# endif +# else +# error "Operating system unsupported" +# endif +} +/** @} */ + +/* MARK: - 64-bit support for makecontext */ +/** + * @name 64-bit support for makecontext + * @{ + */ +#if defined(__LP64__) || defined(DOXYGEN) +/** + * @brief Invokes thread task function + * + * This function fixes the otherwise necessary cast from `void*` to `int` of the thread + * task function pointer. We pass the task func and its argument in registers. + * See @ref makecontext64. + */ +extern void _start_task_func64(void); +#endif + +/** + * @brief Like `makecontext`, allows 64-bit wide function argument on 64-bit platforms + * @param context `ucontext_t` + * @param func Function to be executed when context is applied + * @param arg Function argument, previously limited to `int` width, can now be up to 64 bits wide on 64-bit platforms + * + * Internally, we circumvent the 32-bit `int` limitation by passing the parameter in a register. This is done using + * a custom function defined in `native.S` + */ +static inline void makecontext64(ucontext_t *context, void (*func)(void), void* arg) { +# if defined(__LP64__) + /* makecontext accepts int arguments. In RIOT, we use void* for the optional argument. + * To not truncate the argument pointer, we pass it in a register to _start_task_func64. */ + makecontext(context, (void (*)(void))_start_task_func64, 0); + +# if defined(__x86_64__) +# if defined(__linux__) + context->uc_mcontext.gregs[REG_R14] = (greg_t)func; + context->uc_mcontext.gregs[REG_R15] = (greg_t)arg; +# endif +# endif + +# else + /* On 32-bit platforms, the width of an int is enough to fit a pointer. */ + makecontext(context, (void (*)(void))func, 1, arg); +# endif +} +/** @} */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* UTIL_UCONTEXT_H */ diff --git a/cpu/native/include/util/valgrind.h b/cpu/native/include/util/valgrind.h new file mode 100644 index 0000000000..f5323aec48 --- /dev/null +++ b/cpu/native/include/util/valgrind.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2025 carl-tud + * + * 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. + */ + +#ifndef UTIL_VALGRIND_H +#define UTIL_VALGRIND_H + +#ifdef HAVE_VALGRIND_H +# include +#define VALGRIND_DEBUG DEBUG +# elif defined(HAVE_VALGRIND_VALGRIND_H) +# include +#define VALGRIND_DEBUG DEBUG +#else +# define VALGRIND_STACK_REGISTER(...) (0) +# define VALGRIND_DEBUG(...) +#endif + +#ifdef __cplusplus +extern "C" {} +#endif + +#endif /* UTIL_VALGRIND_H */ diff --git a/cpu/native/irq_cpu.c b/cpu/native/irq.c similarity index 58% rename from cpu/native/irq_cpu.c rename to cpu/native/irq.c index c5e404115a..ab5e250ccc 100644 --- a/cpu/native/irq_cpu.c +++ b/cpu/native/irq.c @@ -1,22 +1,17 @@ -/** - * Native CPU irq.h implementation - * +/* * Copyright (C) 2013 Ludwig Knüpfer * * 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. - * - * @ingroup cpu_native - * @{ - * @file - * @author Ludwig Knüpfer */ -/* __USE_GNU for gregs[REG_EIP] access under glibc - * _GNU_SOURCE for REG_EIP and strsignal() under musl */ -#define __USE_GNU -#define _GNU_SOURCE +/** + * @file + * @brief Native CPU irq.h implementation + * @ingroup cpu_native + * @author Ludwig Knüpfer + */ #include #include @@ -24,16 +19,7 @@ #include #include -#ifdef HAVE_VALGRIND_H -#include -#define VALGRIND_DEBUG DEBUG -#elif defined(HAVE_VALGRIND_VALGRIND_H) -#include -#define VALGRIND_DEBUG DEBUG -#else -#define VALGRIND_STACK_REGISTER(...) (0) -#define VALGRIND_DEBUG(...) -#endif +#include "util/valgrind.h" #include "irq.h" #include "cpu.h" @@ -44,32 +30,40 @@ #define ENABLE_DEBUG 0 #include "debug.h" +#define DEBUG_IRQ(...) DEBUG("[native] IRQ: " __VA_ARGS__) -volatile int native_interrupts_enabled = 0; +volatile bool _native_interrupts_enabled = false; volatile int _native_in_isr; -volatile int _native_in_syscall; +volatile int _native_pending_syscalls; -static sigset_t _native_sig_set, _native_sig_set_dint; +char _isr_stack[THREAD_STACKSIZE_DEFAULT]; +static ucontext_t _native_isr_context_storage; +ucontext_t *_native_isr_context = &_native_isr_context_storage; +ucontext_t *_native_current_context = NULL; -char __isr_stack[THREAD_STACKSIZE_DEFAULT]; -const size_t __isr_stack_size = sizeof(__isr_stack); -ucontext_t native_isr_context; -ucontext_t *_native_cur_ctx, *_native_isr_ctx; +volatile uintptr_t _native_user_fptr; -volatile uintptr_t _native_saved_eip; -volatile int _native_sigpend; -int _sig_pipefd[2]; +static sigset_t _native_sig_set; +static sigset_t _native_sig_set_dint; +volatile int _native_pending_signals; +int _signal_pipe_fd[2]; -static _native_callback_t native_irq_handlers[255]; +static _native_callback_t _native_irq_handlers[255]; + +static inline void _set_sigmask(ucontext_t *ctx) +{ + ctx->uc_sigmask = _native_sig_set_dint; + _native_interrupts_enabled = false; +} void *thread_isr_stack_pointer(void) { - return native_isr_context.uc_stack.ss_sp; + return _native_isr_context->uc_stack.ss_sp; } void *thread_isr_stack_start(void) { - return __isr_stack; + return _isr_stack; } void print_thread_sigmask(ucontext_t *cp) @@ -81,7 +75,7 @@ void print_thread_sigmask(ucontext_t *cp) } for (int i = 1; i < (NSIG); i++) { - if (native_irq_handlers[i] != NULL) { + if (_native_irq_handlers[i] != NULL) { printf("%s: %s\n", strsignal(i), (sigismember(&_native_sig_set, i) ? "blocked" : "unblocked") @@ -130,7 +124,7 @@ void native_print_signals(void) } for (int i = 1; i < (NSIG); i++) { - if (native_irq_handlers[i] != NULL || i == SIGUSR1) { + if (_native_irq_handlers[i] != NULL || i == SIGUSR1) { printf("%s: %s in active thread\n", strsignal(i), (sigismember(&_native_sig_set, i) ? "blocked" : "unblocked") @@ -155,20 +149,20 @@ unsigned irq_disable(void) unsigned int prev_state; _native_syscall_enter(); - DEBUG("irq_disable()\n"); + DEBUG_IRQ("irq_disable(): _native_in_isr == %i\n", _native_in_isr); if (_native_in_isr == 1) { - DEBUG("irq_disable + _native_in_isr\n"); + DEBUG_IRQ("irq_disable + _native_in_isr\n"); } if (sigprocmask(SIG_SETMASK, &_native_sig_set_dint, NULL) == -1) { err(EXIT_FAILURE, "irq_disable: sigprocmask"); } - prev_state = native_interrupts_enabled; - native_interrupts_enabled = 0; + prev_state = _native_interrupts_enabled; + _native_interrupts_enabled = false; - DEBUG("irq_disable(): return\n"); + DEBUG_IRQ("irq_disable(): return\n"); _native_syscall_leave(); return prev_state; @@ -182,22 +176,22 @@ unsigned irq_enable(void) unsigned int prev_state; if (_native_in_isr == 1) { -#ifdef DEVELHELP +# ifdef DEVELHELP real_write(STDERR_FILENO, "irq_enable + _native_in_isr\n", 27); -#else - DEBUG("irq_enable + _native_in_isr\n"); -#endif +# else + DEBUG_IRQ("irq_enable + _native_in_isr\n"); +# endif } _native_syscall_enter(); - DEBUG("irq_enable()\n"); + DEBUG_IRQ("irq_enable()\n"); /* Mark the IRQ as enabled first since sigprocmask could call the handler * before returning to userspace. */ - prev_state = native_interrupts_enabled; - native_interrupts_enabled = 1; + prev_state = _native_interrupts_enabled; + _native_interrupts_enabled = true; if (sigprocmask(SIG_SETMASK, &_native_sig_set, NULL) == -1) { err(EXIT_FAILURE, "irq_enable: sigprocmask"); @@ -206,18 +200,18 @@ unsigned irq_enable(void) _native_syscall_leave(); if (_native_in_isr == 0 && sched_context_switch_request) { - DEBUG("irq_enable() deferred thread_yield_higher()\n"); + DEBUG_IRQ("irq_enable() deferred thread_yield_higher()\n"); thread_yield_higher(); } - DEBUG("irq_enable(): return\n"); + DEBUG_IRQ("irq_enable(): return\n"); return prev_state; } void irq_restore(unsigned state) { - DEBUG("irq_restore()\n"); + DEBUG_IRQ("irq_restore()\n"); if (state == 1) { irq_enable(); @@ -231,16 +225,16 @@ void irq_restore(unsigned state) bool irq_is_enabled(void) { - return native_interrupts_enabled; + return _native_interrupts_enabled; } bool irq_is_in(void) { - DEBUG("irq_is_in: %i\n", _native_in_isr); + DEBUG_IRQ("irq_is_in: %i\n", _native_in_isr); return _native_in_isr; } -int _native_popsig(void) +static int _native_pop_sig(void) { int nread, nleft, i; int sig = 0; @@ -248,132 +242,97 @@ int _native_popsig(void) nleft = sizeof(int); i = 0; - while ((nleft > 0) && ((nread = real_read(_sig_pipefd[0], ((uint8_t*)&sig) + i, nleft)) != -1)) { + while ((nleft > 0) && ((nread = real_read(_signal_pipe_fd[0], ((uint8_t*)&sig) + i, nleft)) != -1)) { i += nread; nleft -= nread; } if (nread == -1) { - err(EXIT_FAILURE, "_native_popsig: real_read"); + err(EXIT_FAILURE, "_native_pop_sig: real_read"); } return sig; } -/** - * call signal handlers, - * restore user context - */ -void native_irq_handler(void) +void _native_call_sig_handlers_and_switch(void) { - DEBUG("\n\n\t\tnative_irq_handler\n\n"); + DEBUG_IRQ("\n\n\t\tcall sig handlers + switch\n\n"); - while (_native_sigpend > 0) { - int sig = _native_popsig(); - _native_sigpend--; + while (_native_pending_signals > 0) { + int sig = _native_pop_sig(); + _native_pending_signals--; - if (native_irq_handlers[sig] != NULL) { - DEBUG("native_irq_handler: calling interrupt handler for %i\n", sig); - native_irq_handlers[sig](); + if (_native_irq_handlers[sig]) { + DEBUG_IRQ("call sig handlers + switch: calling interrupt handler for %i\n", sig); + _native_irq_handlers[sig](); } else if (sig == SIGUSR1) { - warnx("native_irq_handler: ignoring SIGUSR1"); + warnx("call sig handlers + switch: ignoring SIGUSR1"); } else { errx(EXIT_FAILURE, "XXX: no handler for signal %i\nXXX: this should not have happened!\n", sig); } } - DEBUG("native_irq_handler: return\n"); + DEBUG_IRQ("call sig handlers + switch: return\n"); + + /* Leave ISR context */ cpu_switch_context_exit(); } -void isr_set_sigmask(ucontext_t *ctx) -{ - ctx->uc_sigmask = _native_sig_set_dint; - native_interrupts_enabled = 0; -} - -/** - * save signal, return to _native_sig_leave_tramp if possible - */ -void native_isr_entry(int sig, siginfo_t *info, void *context) +void native_signal_action(int sig, siginfo_t *info, void *context) { (void) info; /* unused at the moment */ - //printf("\n\033[33m\n\t\tnative_isr_entry(%i)\n\n\033[0m", sig); /* save the signal */ - if (real_write(_sig_pipefd[1], &sig, sizeof(int)) == -1) { - err(EXIT_FAILURE, "native_isr_entry: real_write()"); + if (real_write(_signal_pipe_fd[1], &sig, sizeof(int)) == -1) { + err(EXIT_FAILURE, "native_signal_action: real_write()"); } - _native_sigpend++; - //real_write(STDOUT_FILENO, "sigpend\n", 8); + _native_pending_signals++; if (context == NULL) { - errx(EXIT_FAILURE, "native_isr_entry: context is null - unhandled"); + errx(EXIT_FAILURE, "native_signal_action: context is null - unhandled"); } if (thread_get_active() == NULL) { _native_in_isr++; - warnx("native_isr_entry: thread_get_active() is null - unhandled"); + warnx("native_signal_action: thread_get_active() is null - unhandled"); _native_in_isr--; return; } /* XXX: Workaround safety check - whenever this happens it really * indicates a bug in irq_disable */ - if (native_interrupts_enabled == 0) { - //printf("interrupts are off, but I caught a signal.\n"); + if (!_native_interrupts_enabled) { return; } if (_native_in_isr != 0) { - //real_write(STDOUT_FILENO, "interrupts in ISR!!\n", 20); return; } - if (_native_in_syscall != 0) { - DEBUG("\n\n\t\tnative_isr_entry: return to syscall\n\n"); + if (_native_pending_syscalls != 0) { + DEBUG_IRQ("\n\n\t\tnative_signal_action: return to syscall\n\n"); return; } - native_isr_context.uc_stack.ss_sp = __isr_stack; - native_isr_context.uc_stack.ss_size = sizeof(__isr_stack); - native_isr_context.uc_stack.ss_flags = 0; - makecontext(&native_isr_context, native_irq_handler, 0); - /* Use intermediate cast to uintptr_t to silence -Wcast-align. - * stacks are manually word aligned in thread_stack_init() */ - _native_cur_ctx = (ucontext_t *)(uintptr_t)thread_get_active()->sp; + /* We will switch to the ISR context with ISR stack */ + _native_isr_context_make(_native_call_sig_handlers_and_switch); - DEBUG("\n\n\t\tnative_isr_entry: return to _native_sig_leave_tramp\n\n"); + /* Current user thread context */ + _native_current_context = _native_user_context(); + + DEBUG_IRQ("\n\n\t\tnative_signal_action: return to _native_sig_leave_tramp\n\n"); /* disable interrupts in context */ - isr_set_sigmask((ucontext_t *)context); + _set_sigmask((ucontext_t *)context); _native_in_isr = 1; -#if defined(__FreeBSD__) - _native_saved_eip = ((struct sigcontext *)context)->sc_eip; - ((struct sigcontext *)context)->sc_eip = (unsigned int)&_native_sig_leave_tramp; -#else /* Linux */ -#if defined(__arm__) - _native_saved_eip = ((ucontext_t *)context)->uc_mcontext.arm_pc; - ((ucontext_t *)context)->uc_mcontext.arm_pc = (unsigned int)&_native_sig_leave_tramp; -#else /* Linux/x86 */ - #ifdef __x86_64__ - _native_saved_eip = ((ucontext_t *)context)->uc_mcontext.gregs[REG_RIP]; - ((ucontext_t *)context)->uc_mcontext.gregs[REG_RIP] = (uintptr_t)&_native_sig_leave_tramp; - #else - //printf("\n\033[31mEIP:\t%p\ngo switching\n\n\033[0m", (void*)((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP]); - _native_saved_eip = ((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP]; - ((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP] = (unsigned int)&_native_sig_leave_tramp; - #endif -#endif -#endif + + /* Get PC/LR. This is where we will resume execution on the userspace thread. */ + _native_user_fptr = (uintptr_t)_context_get_fptr((ucontext_t *)context); + + /* Now we want to go to _native_sig_leave_tramp before resuming execution at _native_user_fptr. */ + _context_set_fptr(context, (uintptr_t)_native_sig_leave_tramp); } -/** - * Add or remove handler for signal - * - * To be called with interrupts disabled - * - */ -void set_signal_handler(int sig, bool add) +static void _set_signal_handler(int sig, bool add) { struct sigaction sa; int ret; @@ -403,7 +362,7 @@ void set_signal_handler(int sig, bool add) if (add) { sa.sa_flags |= SA_SIGINFO; /* sa.sa_sigaction is used */ - sa.sa_sigaction = native_isr_entry; + sa.sa_sigaction = native_signal_action; } else { sa.sa_handler = SIG_IGN; @@ -416,37 +375,30 @@ void set_signal_handler(int sig, bool add) _native_syscall_leave(); } -/** - * register signal/interrupt handler for signal sig - * - * TODO: use appropriate data structure for signal - * handlers. - */ -int register_interrupt(int sig, _native_callback_t handler) +/* TODO: use appropriate data structure for signal handlers. */ +int native_register_interrupt(int sig, _native_callback_t handler) { - DEBUG("register_interrupt\n"); + DEBUG_IRQ("native_register_interrupt\n"); unsigned state = irq_disable(); - native_irq_handlers[sig] = handler; - set_signal_handler(sig, true); + _native_irq_handlers[sig] = handler; + _set_signal_handler(sig, true); irq_restore(state); return 0; } -/** - * empty signal mask - */ -int unregister_interrupt(int sig) +int native_unregister_interrupt(int sig) { - DEBUG("unregister_interrupt\n"); + /* empty signal mask */ + DEBUG_IRQ("native_unregister_interrupt\n"); unsigned state = irq_disable(); - set_signal_handler(sig, false); - native_irq_handlers[sig] = NULL; + _set_signal_handler(sig, false); + _native_irq_handlers[sig] = NULL; irq_restore(state); @@ -462,28 +414,21 @@ static void native_shutdown(int sig, siginfo_t *info, void *context) pm_off(); } -/** - * register internal signal handler, - * initialize local variables - * - * TODO: see register_interrupt - */ void native_interrupt_init(void) { + /* register internal signal handler, initialize local variables + * TODO: see native_register_interrupt */ struct sigaction sa; - DEBUG("native_interrupt_init\n"); + DEBUG_IRQ("native_interrupt_init\n"); (void) VALGRIND_STACK_REGISTER(__isr_stack, __isr_stack + sizeof(__isr_stack)); VALGRIND_DEBUG("VALGRIND_STACK_REGISTER(%p, %p)\n", (void *)__isr_stack, (void*)(__isr_stack + sizeof(__isr_stack))); - _native_sigpend = 0; + _native_pending_signals = 0; + memset(_native_irq_handlers, 0, sizeof(_native_irq_handlers)); - for (int i = 0; i < 255; i++) { - native_irq_handlers[i] = NULL; - } - - sa.sa_sigaction = native_isr_entry; + sa.sa_sigaction = native_signal_action; if (sigfillset(&sa.sa_mask) == -1) { err(EXIT_FAILURE, "native_interrupt_init: sigfillset"); @@ -515,14 +460,11 @@ void native_interrupt_init(void) err(EXIT_FAILURE, "native_interrupt_init: sigaction"); } - if (getcontext(&native_isr_context) == -1) { + if (getcontext(_native_isr_context) == -1) { err(EXIT_FAILURE, "native_interrupt_init: getcontext"); } - native_isr_context.uc_stack.ss_sp = __isr_stack; - native_isr_context.uc_stack.ss_size = sizeof(__isr_stack); - native_isr_context.uc_stack.ss_flags = 0; - _native_isr_ctx = &native_isr_context; + _native_isr_context_make(_native_call_sig_handlers_and_switch); static stack_t sigstk; sigstk.ss_sp = malloc(SIGSTKSZ); @@ -534,16 +476,14 @@ void native_interrupt_init(void) err(EXIT_FAILURE, "native_interrupt_init: sigaltstack"); } - makecontext(&native_isr_context, native_irq_handler, 0); + _native_pending_syscalls = 0; - _native_in_syscall = 0; - - if (real_pipe(_sig_pipefd) == -1) { + if (real_pipe(_signal_pipe_fd) == -1) { err(EXIT_FAILURE, "native_interrupt_init: pipe"); } /* allow for ctrl+c to shut down gracefully always */ - //register_interrupt(SIGINT, native_shutdown); + //native_register_interrupt(SIGINT, native_shutdown); sa.sa_sigaction = native_shutdown; if (sigdelset(&_native_sig_set, SIGINT) == -1) { err(EXIT_FAILURE, "native_interrupt_init: sigdelset"); @@ -557,4 +497,3 @@ void native_interrupt_init(void) puts("RIOT native interrupts/signals initialized."); } -/** @} */ diff --git a/cpu/native/mtd/mtd_native.c b/cpu/native/mtd/mtd_native.c index 672cdad3a5..11db5d0a4a 100644 --- a/cpu/native/mtd/mtd_native.c +++ b/cpu/native/mtd/mtd_native.c @@ -7,12 +7,10 @@ */ /** - * @{ - * @brief mtd flash emulation for native - * * @file - * - * @author Vincent Dupont + * @ingroup drivers_mtd_native + * @brief MTD flash emulation for native + * @author Vincent Dupont */ #include @@ -156,5 +154,3 @@ const mtd_desc_t native_flash_driver = { .erase = _erase, .init = _init, }; - -/** @} */ diff --git a/cpu/native/native.S b/cpu/native/native.S new file mode 100644 index 0000000000..ec17bf9d45 --- /dev/null +++ b/cpu/native/native.S @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2013, 2014 Ludwig Knüpfer + * Copyright (C) 2014 Thomas Eichinger + * + * 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. + */ + +/** + * @brief Generates platform-dependent symbol name + */ +#define SYMBOL(name) name + +/** + * @brief Defines new global symbol + */ +.macro GLOBAL_SYMBOL name + .globl SYMBOL(\name) + SYMBOL(\name): +.endm + +/** + * @brief Loads address immediate and then memory contents into register + * @param register Register to load memory contents in + * @param symbol Symbol whose memory contents to load + */ +.macro LOADMEM register, symbol + ldr \register, =\symbol + ldr \register, [\register] +.endm + +/** + * @brief Write register contents into memory + * @param value Register containing value to write + * @param register Helper register to use for loading address + * @param symbol Symbol pointing to memory location to write to + */ +.macro STOREMEM value, register, symbol + ldr \register, =\symbol + str \value, [\register] +.endm + +.text + +#if defined(__arm__) + +GLOBAL_SYMBOL _native_sig_leave_tramp + /* save _native_user_fptr and registers */ + stmdb sp!, {r0} + LOADMEM r0, SYMBOL(_native_user_fptr) + stmdb sp!, {r0-r12} + stmdb sp!, {lr} + + /* exchange r0 and _native_user_fptr */ + ldr r0, [sp,#56] + ldr r1, [sp,#4 ] + str r0, [sp,#4 ] + str r1, [sp,#56] + + /* call swapcontext(_native_current_context, _native_isr_context) */ + LOADMEM r0, SYMBOL(_native_current_context) + LOADMEM r1, SYMBOL(_native_isr_context) + bl SYMBOL(swapcontext) + + /* reeanble interrupts */ + bl SYMBOL(irq_enable) + + /* _native_in_isr = 0 */ + eor r0, r0, r0 + STOREMEM r0, r1, SYMBOL(_native_in_isr) + + /* restore registers, jump to (saved) _native_user_fptr */ + ldmia sp!, {lr} + ldmia sp!, {r0-r12} + ldmia sp!, {pc} + +GLOBAL_SYMBOL _native_isr_leave + stmdb sp!, {r0} + LOADMEM r0, SYMBOL(_native_user_fptr) + stmdb sp!, {r0-r12} + stmdb sp!, {lr} + + /* exchange r0 and _native_user_fptr */ + ldr r0, [sp,#56] + ldr r1, [sp,#4 ] + str r0, [sp,#4 ] + str r1, [sp,#56] + + /* _native_in_isr = 0 */ + eor r0, r0, r0 + STOREMEM r0, r1, SYMBOL(_native_in_isr) + ldmia sp!, {lr} + ldmia sp!, {r0-r12} + ldmia sp!, {pc} + +#elif defined(__x86_64__) + +GLOBAL_SYMBOL _native_sig_leave_tramp + /* Push (relative) return address onto stack */ + pushq SYMBOL(_native_user_fptr)(%rip) + /* Push RFLAGS register onto stack */ + pushfq + /* Preserve general-purpose registers */ + pushq %rax + pushq %rcx + pushq %rdx + pushq %rbx + pushq %rbp + pushq %rsi + pushq %rdi + pushq %r8 + pushq %r9 + pushq %r10 + pushq %r11 + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + + /* Push swapcontext arguments onto stack (relative) */ + mov SYMBOL(_native_isr_context)(%rip), %rsi + mov SYMBOL(_native_current_context)(%rip), %rdi + /* call swapcontext(_native_current_context (RDI), _native_isr_context (RSI)) */ + call SYMBOL(swapcontext) + + /* reeanble interrupts */ + call SYMBOL(irq_enable) + + /* _native_in_isr = 0 */ + movl $0x0, SYMBOL(_native_in_isr)(%rip) + + /* Restore general-purpose registers */ + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %r11 + popq %r10 + popq %r9 + popq %r8 + popq %rdi + popq %rsi + popq %rbp + popq %rbx + popq %rdx + popq %rcx + popq %rax + /* Restore RFLAGS register*/ + popfq + + /* Pop and jump to _native_user_fptr */ + ret + +GLOBAL_SYMBOL _native_isr_leave + /* Push (relative) return address onto stack */ + pushq SYMBOL(_native_user_fptr)(%rip) + + /* _native_in_isr = 0 */ + movl $0x0, SYMBOL(_native_in_isr)(%rip) + + /* Pop and jump to _native_user_fptr */ + ret + +GLOBAL_SYMBOL _start_task_func64 + /* Use r14 and r15 as scratch registers. */ + /* r8, r9 / r12 are used by glibc / libplatform on arm64 */ + /* This is the 64-bit function argument. RIOT threads can only receive one argument. */ + /* System V ABI says: first argument in RDI. + * See: https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf + * > %rdi - used to pass 1st argument to functions */ + mov %r15, %rdi + /* Call user thread func. */ + jmp *%r14 + +#elif defined(__i386__) + +GLOBAL_SYMBOL _native_sig_leave_tramp + /* Push return address onto stack */ + pushl SYMBOL(_native_user_fptr) + /* Push eflags register onto stack */ + pushfl + /* Push all general-purpose registers */ + pushal + + /* Push swapcontext arguments onto stack */ + pushl SYMBOL(_native_isr_context) + pushl SYMBOL(_native_current_context) + /* call swapcontext(_native_current_context, _native_isr_context) */ + call SYMBOL(swapcontext) + /* Remove swapcontext arguments from stack */ + addl $8, %esp + + /* reeanble interrupts */ + call SYMBOL(irq_enable) + + /* _native_in_isr = 0 */ + movl $0x0, SYMBOL(_native_in_isr) + + /* Pop all general-purpose registers */ + popal + /* Pop eflags register */ + popfl + + /* Pop and jump to _native_user_fptr */ + ret + +GLOBAL_SYMBOL _native_isr_leave + /* Push return address onto stack */ + pushl SYMBOL(_native_user_fptr) + + /* _native_in_isr = 0 */ + movl $0x0, SYMBOL(_native_in_isr) + + /* Pop and jump to _native_user_fptr*/ + ret + +#else +# error "Unsupported architecture" +#endif + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/cpu/native/native_cpu.c b/cpu/native/native_cpu.c deleted file mode 100644 index c2c1a39ca4..0000000000 --- a/cpu/native/native_cpu.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (C) 2016 Kaspar Schleiser - * 2013 Ludwig Knüpfer - * - * 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. - */ - -/** - * @ingroup cpu_native - * @{ - * - * @file - * @brief Native CPU kernel_intern.h and sched.h implementation - * - * in-process preemptive context switching utilizes POSIX ucontexts. - * (ucontext provides for architecture independent stack handling) - * - * @author Ludwig Knüpfer - * @author Kaspar Schleiser - */ - -/* __USE_GNU for gregs[REG_EIP] access under glibc - * _GNU_SOURCE for REG_EIP and strsignal() under musl */ -#define __USE_GNU -#define _GNU_SOURCE - -#include -#include -#include -#include -#include - -#if USE_LIBUCONTEXT -#include -#else -#include -#endif - -#ifdef HAVE_VALGRIND_H -#include -#define VALGRIND_DEBUG DEBUG -#elif defined(HAVE_VALGRIND_VALGRIND_H) -#include -#define VALGRIND_DEBUG DEBUG -#else -#define VALGRIND_STACK_REGISTER(...) (0) -#define VALGRIND_DEBUG(...) -#endif - -#include - -#include "cpu.h" -#include "cpu_conf.h" -#include "irq.h" -#include "sched.h" -#include "test_utils/expect.h" - -#ifdef MODULE_NETDEV_TAP -#include "netdev_tap.h" -extern netdev_tap_t netdev_tap; -#endif - -#include "native_internal.h" - -#define ENABLE_DEBUG 0 -#include "debug.h" - -ucontext_t end_context; - -/** - * make the new context assign `_native_in_isr = 0` before resuming - */ -static void _native_mod_ctx_leave_sigh(ucontext_t *ctx) -{ -#if defined(__FreeBSD__) - _native_saved_eip = ((struct sigcontext *)ctx)->sc_eip; - ((struct sigcontext *)ctx)->sc_eip = (unsigned int)&_native_sig_leave_handler; -#else /* Linux */ -#if defined(__arm__) - _native_saved_eip = ((ucontext_t *)ctx)->uc_mcontext.arm_pc; - ((ucontext_t *)ctx)->uc_mcontext.arm_pc = (unsigned int)&_native_sig_leave_handler; -#else /* Linux/x86 */ - #ifdef __x86_64__ - _native_saved_eip = ctx->uc_mcontext.gregs[REG_RIP]; - ctx->uc_mcontext.gregs[REG_RIP] = (unsigned long)&_native_sig_leave_handler; - #else - _native_saved_eip = ctx->uc_mcontext.gregs[REG_EIP]; - ctx->uc_mcontext.gregs[REG_EIP] = (unsigned int)&_native_sig_leave_handler; - #endif -#endif -#endif -} - -/** - * TODO: implement - */ -void thread_print_stack(void) -{ - DEBUG("thread_print_stack\n"); - return; -} - -/* This function calculates the ISR_usage */ -int thread_isr_stack_usage(void) -{ - /* TODO */ - return -1; -} - -void native_breakpoint(void) -{ - raise(SIGTRAP); -} - -static inline void *align_stack(uintptr_t start, int *stacksize) -{ - const size_t alignment = sizeof(uintptr_t); - const uintptr_t align_mask = alignment - 1; - size_t unalignment = (start & align_mask) - ? (alignment - (start & align_mask)) : 0; - start += unalignment; - *stacksize -= unalignment; - *stacksize &= ~align_mask; - return (void *)start; -} - -char *thread_stack_init(thread_task_func_t task_func, void *arg, void *stack_start, int stacksize) -{ - ucontext_t *p; - - stack_start = align_stack((uintptr_t)stack_start, &stacksize); - - (void) VALGRIND_STACK_REGISTER(stack_start, (char *)stack_start + stacksize); - VALGRIND_DEBUG("VALGRIND_STACK_REGISTER(%p, %p)\n", - stack_start, (void*)((char *)stack_start + stacksize)); - - DEBUG("thread_stack_init\n"); - - /* Use intermediate cast to uintptr_t to silence -Wcast-align. The stack - * is aligned to word size above. */ - p = (ucontext_t *)(uintptr_t)((uint8_t *)stack_start + (stacksize - sizeof(ucontext_t))); - stacksize -= sizeof(ucontext_t); - - if (getcontext(p) == -1) { - err(EXIT_FAILURE, "thread_stack_init: getcontext"); - } - - p->uc_stack.ss_sp = stack_start; - p->uc_stack.ss_size = stacksize; - p->uc_stack.ss_flags = 0; - p->uc_link = &end_context; - - if (sigemptyset(&(p->uc_sigmask)) == -1) { - err(EXIT_FAILURE, "thread_stack_init: sigemptyset"); - } - - makecontext(p, (void (*)(void)) task_func, 1, arg); - - return (char *) p; -} - -void isr_cpu_switch_context_exit(void) -{ - ucontext_t *ctx; - - DEBUG("isr_cpu_switch_context_exit\n"); - if (((sched_context_switch_request == 1) || (thread_get_active() == NULL)) - && IS_USED(MODULE_CORE_THREAD)) { - sched_run(); - } - - DEBUG("isr_cpu_switch_context_exit: calling setcontext(%" PRIkernel_pid ")\n\n", thread_getpid()); - /* Use intermediate cast to uintptr_t to silence -Wcast-align. - * stacks are manually word aligned in thread_static_init() */ - ctx = (ucontext_t *)(uintptr_t)(thread_get_active()->sp); - - native_interrupts_enabled = 1; - _native_mod_ctx_leave_sigh(ctx); - - if (setcontext(ctx) == -1) { - err(EXIT_FAILURE, "isr_cpu_switch_context_exit: setcontext"); - } - errx(EXIT_FAILURE, "2 this should have never been reached!!"); -} - -void cpu_switch_context_exit(void) -{ -#ifdef NATIVE_AUTO_EXIT - if (sched_num_threads <= 1) { - extern unsigned _native_retval; - DEBUG("cpu_switch_context_exit: last task has ended. exiting.\n"); - real_exit(_native_retval); - } -#endif - - if (_native_in_isr == 0) { - irq_disable(); - _native_in_isr = 1; - native_isr_context.uc_stack.ss_sp = __isr_stack; - native_isr_context.uc_stack.ss_size = __isr_stack_size; - native_isr_context.uc_stack.ss_flags = 0; - makecontext(&native_isr_context, isr_cpu_switch_context_exit, 0); - if (setcontext(&native_isr_context) == -1) { - err(EXIT_FAILURE, "cpu_switch_context_exit: setcontext"); - } - errx(EXIT_FAILURE, "1 this should have never been reached!!"); - } - else { - isr_cpu_switch_context_exit(); - } - errx(EXIT_FAILURE, "3 this should have never been reached!!"); -} - -void isr_thread_yield(void) -{ - DEBUG("isr_thread_yield\n"); - - if (_native_sigpend > 0) { - DEBUG("isr_thread_yield(): handling signals\n\n"); - native_irq_handler(); - } - - if (!IS_USED(MODULE_CORE_THREAD)) { - return; - } - sched_run(); - - /* Use intermediate cast to uintptr_t to silence -Wcast-align. - * stacks are manually word aligned in thread_static_init() */ - ucontext_t *ctx = (ucontext_t *)(uintptr_t)(thread_get_active()->sp); - DEBUG("isr_thread_yield: switching to(%" PRIkernel_pid ")\n\n", - thread_getpid()); - - native_interrupts_enabled = 1; - _native_mod_ctx_leave_sigh(ctx); - - if (setcontext(ctx) == -1) { - err(EXIT_FAILURE, "isr_thread_yield: setcontext"); - } -} - -void thread_yield_higher(void) -{ - sched_context_switch_request = 1; - - if (_native_in_isr == 0 && native_interrupts_enabled) { - /* Use intermediate cast to uintptr_t to silence -Wcast-align. - * stacks are manually word aligned in thread_static_init() */ - ucontext_t *ctx = (ucontext_t *)(uintptr_t)(thread_get_active()->sp); - _native_in_isr = 1; - irq_disable(); - native_isr_context.uc_stack.ss_sp = __isr_stack; - native_isr_context.uc_stack.ss_size = __isr_stack_size; - native_isr_context.uc_stack.ss_flags = 0; - makecontext(&native_isr_context, isr_thread_yield, 0); - if (swapcontext(ctx, &native_isr_context) == -1) { - err(EXIT_FAILURE, "thread_yield_higher: swapcontext"); - } - irq_enable(); - } -} - -void native_cpu_init(void) -{ - if (getcontext(&end_context) == -1) { - err(EXIT_FAILURE, "native_cpu_init: getcontext"); - } - - end_context.uc_stack.ss_sp = malloc(SIGSTKSZ); - expect(end_context.uc_stack.ss_sp != NULL); - end_context.uc_stack.ss_size = SIGSTKSZ; - end_context.uc_stack.ss_flags = 0; - makecontext(&end_context, sched_task_exit, 0); - (void)VALGRIND_STACK_REGISTER(end_context.uc_stack.ss_sp, - (char *)end_context.uc_stack.ss_sp + end_context.uc_stack.ss_size); - VALGRIND_DEBUG("VALGRIND_STACK_REGISTER(%p, %p)\n", - (void*)end_context.uc_stack.ss_sp, - (void*)((char *)end_context.uc_stack.ss_sp + end_context.uc_stack.ss_size)); - - DEBUG("RIOT native cpu initialized.\n"); -} -/** @} */ diff --git a/cpu/native/netdev_tap/netdev_tap.c b/cpu/native/netdev_tap/netdev_tap.c index 444ac0f2c0..8ddf7fc77a 100644 --- a/cpu/native/netdev_tap/netdev_tap.c +++ b/cpu/native/netdev_tap/netdev_tap.c @@ -9,13 +9,13 @@ * more details. */ -/* +/** + * @file * @ingroup drivers_netdev - * @{ * @brief Low-level ethernet driver for tap interfaces * @author Kaspar Schleiser - * @} */ + #include #include #include @@ -28,19 +28,20 @@ #include #include #include +#include /* needs to be included before native's declarations of ntohl etc. */ #include "byteorder.h" -#ifdef __FreeBSD__ -#include -#include -#include -#include +#if defined(__FreeBSD__) +# include +# include +# include +# include #else -#include -#include -#include +# include +# include +# include #endif #include "native_internal.h" @@ -209,14 +210,14 @@ static void _continue_reading(netdev_tap_t *dev) FD_ZERO(&rfds); FD_SET(dev->tap_fd, &rfds); - _native_in_syscall++; /* no switching here */ + _native_pending_syscalls_up(); /* no switching here */ if (real_select(dev->tap_fd + 1, &rfds, NULL, NULL, &t) == 1) { int sig = SIGIO; - extern int _sig_pipefd[2]; + extern int _signal_pipe_fd[2]; extern ssize_t (*real_write)(int fd, const void * buf, size_t count); - real_write(_sig_pipefd[1], &sig, sizeof(int)); - _native_sigpend++; + real_write(_signal_pipe_fd[1], &sig, sizeof(int)); + _native_pending_signals++; DEBUG("netdev_tap: sigpend++\n"); } else { @@ -224,7 +225,7 @@ static void _continue_reading(netdev_tap_t *dev) native_async_read_continue(dev->tap_fd); } - _native_in_syscall--; + _native_pending_syscalls_down(); } static int _recv(netdev_t *netdev, void *buf, size_t len, void *info) @@ -342,20 +343,20 @@ static int _init(netdev_t *netdev) } char *name = dev->tap_name; -#ifdef __FreeBSD__ +# ifdef __FreeBSD__ char clonedev[255] = "/dev/"; /* XXX bad size */ strncpy(clonedev + 5, name, 250); -#else /* Linux */ +# else /* Linux */ struct ifreq ifr; const char *clonedev = "/dev/net/tun"; -#endif +# endif /* initialize device descriptor */ dev->promiscuous = 0; /* implicitly create the tap interface */ if ((dev->tap_fd = real_open(clonedev, O_RDWR | O_NONBLOCK)) == -1) { err(EXIT_FAILURE, "open(%s)", clonedev); } -#if __FreeBSD__ /* FreeBSD */ +# if __FreeBSD__ /* FreeBSD */ struct ifaddrs *iflist; if (real_getifaddrs(&iflist) == 0) { for (struct ifaddrs *cur = iflist; cur; cur = cur->ifa_next) { @@ -367,12 +368,12 @@ static int _init(netdev_t *netdev) } real_freeifaddrs(iflist); } -#else /* Linux */ +# else /* Linux */ memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strncpy(ifr.ifr_name, name, IFNAMSIZ); if (real_ioctl(dev->tap_fd, TUNSETIFF, (void *)&ifr) == -1) { - _native_in_syscall++; + _native_pending_syscalls_up(); warn("ioctl TUNSETIFF"); warnx("probably the tap interface (%s) does not exist or is already in use", name); real_exit(EXIT_FAILURE); @@ -382,7 +383,7 @@ static int _init(netdev_t *netdev) memset(&ifr, 0, sizeof(ifr)); snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", name); if (real_ioctl(dev->tap_fd, SIOCGIFHWADDR, &ifr) == -1) { - _native_in_syscall++; + _native_pending_syscalls_up(); warn("ioctl SIOCGIFHWADDR"); if (real_close(dev->tap_fd) == -1) { warn("close"); @@ -393,7 +394,7 @@ static int _init(netdev_t *netdev) /* change mac addr so it differs from what the host is using */ dev->addr[5]++; -#endif +# endif DEBUG("gnrc_tapnet_init(): dev->addr = %02x:%02x:%02x:%02x:%02x:%02x\n", dev->addr[0], dev->addr[1], dev->addr[2], dev->addr[3], dev->addr[4], dev->addr[5]); diff --git a/cpu/native/panic.c b/cpu/native/panic.c index 127df9f005..6d1be76732 100644 --- a/cpu/native/panic.c +++ b/cpu/native/panic.c @@ -7,15 +7,12 @@ */ /** - * @ingroup cpu_native - * @{ - * * @file - * @brief Crash handling functions implementation for 'native' port - * - * @author Ludwig Knüpfer - * @author Kévin Roussel - * @author Oliver Hahm + * @ingroup cpu_native + * @brief Crash handling functions implementation for 'native' port + * @author Ludwig Knüpfer + * @author Kévin Roussel + * @author Oliver Hahm */ #include diff --git a/cpu/native/periph/can.c b/cpu/native/periph/can.c index aa1565dc3c..a5fd61b2c9 100644 --- a/cpu/native/periph/can.c +++ b/cpu/native/periph/can.c @@ -7,16 +7,12 @@ */ /** - * @ingroup drivers_candev_linux - * @{ - * * @file - * @brief Implementation of simulated CAN controller driver using SocketCAN on Linux - * - * @author Hermann Lelong - * @author Aurelien Gonce - * @author Vincent Dupont - * @} + * @ingroup drivers_candev_linux + * @brief Implementation of simulated CAN controller driver using SocketCAN on Linux + * @author Hermann Lelong + * @author Aurelien Gonce + * @author Vincent Dupont */ #if !defined(__linux__) diff --git a/cpu/native/periph/cpuid.c b/cpu/native/periph/cpuid.c index 8f315f544d..1eebe4494c 100644 --- a/cpu/native/periph/cpuid.c +++ b/cpu/native/periph/cpuid.c @@ -7,16 +7,11 @@ */ /** - * @ingroup cpu_native - * @ingroup drivers_periph_cpuid - * @{ - * * @file - * @brief Implementation - * - * @author Martine Lenders - * - * @} + * @ingroup cpu_native + * @ingroup drivers_periph_cpuid + * @brief CPUID implementation + * @author Martine Lenders */ #include diff --git a/cpu/native/periph/eeprom.c b/cpu/native/periph/eeprom.c index 797db72f86..ea9f7cb6df 100644 --- a/cpu/native/periph/eeprom.c +++ b/cpu/native/periph/eeprom.c @@ -7,15 +7,11 @@ */ /** - * @ingroup cpu_native - * @ingroup drivers_periph_eeprom - * @{ - * * @file - * @brief Low-level EEPROM driver implementation for native - * - * @author Alexandre Abadie - * @} + * @ingroup cpu_native + * @ingroup drivers_periph_eeprom + * @brief Low-level EEPROM driver implementation for native + * @author Alexandre Abadie */ #include diff --git a/cpu/native/periph/flashpage.c b/cpu/native/periph/flashpage.c index 8da0c26a8e..3fb8200091 100644 --- a/cpu/native/periph/flashpage.c +++ b/cpu/native/periph/flashpage.c @@ -7,15 +7,11 @@ */ /** - * @ingroup cpu_native - * @ingroup drivers_periph_flashpage - * @{ - * * @file - * @brief Low-level flashpage driver emulation - * - * @author Benjamin Valentin - * @} + * @ingroup cpu_native + * @ingroup drivers_periph_flashpage + * @brief Low-level flashpage driver emulation + * @author Benjamin Valentin */ #include diff --git a/cpu/native/periph/gpio_linux.c b/cpu/native/periph/gpio_linux.c index 2b32790e99..024a8ac4c9 100644 --- a/cpu/native/periph/gpio_linux.c +++ b/cpu/native/periph/gpio_linux.c @@ -7,18 +7,13 @@ */ /** - * @ingroup cpu_native - * @ingroup drivers_periph_gpio - * @{ - * * @file - * @brief native GPIO implementation - * - * @author Benjamin Valentin + * @ingroup cpu_native + * @ingroup drivers_periph_gpio + * @brief native GPIO implementation + * @author Benjamin Valentin */ -#define _GNU_SOURCE - #include #include #include @@ -314,5 +309,3 @@ void gpio_irq_disable(gpio_t pin) } #endif /* MODULE_PERIPH_GPIO_IRQ */ - -/** @} */ diff --git a/cpu/native/periph/gpio_mock.c b/cpu/native/periph/gpio_mock.c index 3094be3144..ecaf7555dd 100644 --- a/cpu/native/periph/gpio_mock.c +++ b/cpu/native/periph/gpio_mock.c @@ -7,14 +7,11 @@ */ /** - * @ingroup cpu_native - * @ingroup drivers_periph_gpio - * @{ - * * @file - * @brief empty GPIO implementation - * - * @author Takuo Yonezawa + * @ingroup cpu_native + * @ingroup drivers_periph_gpio + * @brief empty GPIO implementation + * @author Takuo Yonezawa */ #include "periph/gpio.h" @@ -97,5 +94,3 @@ __attribute__((weak)) void gpio_write(gpio_t pin, bool value) { pin->value = value; } } - -/** @} */ diff --git a/cpu/native/periph/hwrng.c b/cpu/native/periph/hwrng.c index f9971cebbf..f4301b3c2e 100644 --- a/cpu/native/periph/hwrng.c +++ b/cpu/native/periph/hwrng.c @@ -8,14 +8,11 @@ */ /** - * @ingroup cpu_native - * @ingroup drivers_periph_hwrng - * @{ - * * @file - * @brief HWRNG interface implementation - * - * @author Ludwig Knüpfer + * @ingroup cpu_native + * @ingroup drivers_periph_hwrng + * @brief HWRNG interface implementation + * @author Ludwig Knüpfer */ #include @@ -35,9 +32,7 @@ static int initialized = 0; static int dev_random = -1; -/********************************************************************** - * internal API declaration - **********************************************************************/ +/* MARK: - Internal API declaration */ /** * seed host random module with @ref _native_rng_seed @@ -47,9 +42,7 @@ void _native_rng_init_hq(void); unsigned _native_rng_read_det(uint8_t *buf, unsigned num); unsigned _native_rng_read_hq(uint8_t *buf, unsigned num); -/********************************************************************** - * public API implementation - **********************************************************************/ +/* MARK: - Public API implementation */ void hwrng_init(void) { @@ -94,9 +87,7 @@ void hwrng_read(void *buf, unsigned int num) } } -/********************************************************************** - * internal API implementation - **********************************************************************/ +/* MARK: - Internal API implementation */ void _native_rng_init_det(void) { @@ -152,7 +143,3 @@ unsigned _native_rng_read_hq(uint8_t *buf, unsigned num) return offset; } - -/** - * @} - */ diff --git a/cpu/native/periph/pm.c b/cpu/native/periph/pm.c index a1215163ef..7fda4515b0 100644 --- a/cpu/native/periph/pm.c +++ b/cpu/native/periph/pm.c @@ -7,14 +7,11 @@ */ /** - * @ingroup cpu_native - * @ingroup drivers_periph_pm - * @{ - * * @file - * @brief native Power Management implementation - * - * @author Kaspar Schleiser + * @ingroup cpu_native + * @ingroup drivers_periph_pm + * @brief Native Power Management implementation + * @author Kaspar Schleiser */ #include @@ -40,12 +37,12 @@ unsigned _native_retval = EXIT_SUCCESS; static void _native_sleep(void) { - _native_in_syscall++; /* no switching here */ + _native_pending_syscalls_up(); /* no switching here */ real_pause(); - _native_in_syscall--; + _native_pending_syscalls_down(); - if (_native_sigpend > 0) { - _native_in_syscall++; + if (_native_pending_signals > 0) { + _native_pending_syscalls_up(); _native_syscall_leave(); } } diff --git a/cpu/native/periph/pwm.c b/cpu/native/periph/pwm.c index f4b0af0c12..cb92aecf9d 100644 --- a/cpu/native/periph/pwm.c +++ b/cpu/native/periph/pwm.c @@ -7,15 +7,11 @@ */ /** - * @ingroup cpu_native - * @ingroup drivers_periph_pwm - * @{ - * * @file - * @brief Low-level PWM driver implementation - * - * @author Gilles DOFFE - * @} + * @ingroup cpu_native + * @ingroup drivers_periph_pwm + * @brief Low-level PWM driver implementation + * @author Gilles DOFFE */ #include diff --git a/cpu/native/periph/qdec.c b/cpu/native/periph/qdec.c index c3a3b8aa91..47c6d29c10 100644 --- a/cpu/native/periph/qdec.c +++ b/cpu/native/periph/qdec.c @@ -7,16 +7,11 @@ */ /** - * @ingroup cpu_native - * @ingroup drivers_periph_qdec - * @{ - * * @file - * @brief Low-level QDEC driver implementation - * - * @author Gilles DOFFE - * - * @} + * @ingroup cpu_native + * @ingroup drivers_periph_qdec + * @brief Low-level QDEC driver implementation + * @author Gilles DOFFE */ #include diff --git a/cpu/native/periph/rtc.c b/cpu/native/periph/rtc.c index 088e465332..aa4bcd1b74 100644 --- a/cpu/native/periph/rtc.c +++ b/cpu/native/periph/rtc.c @@ -7,18 +7,16 @@ */ /** - * @ingroup cpu_native - * @ingroup drivers_periph_rtc - * @{ - * * @file - * @brief Native CPU periph/rtc.h implementation + * @ingroup cpu_native + * @ingroup drivers_periph_rtc + * @brief Native CPU periph/rtc.h implementation + * @author Ludwig Knüpfer + * @{ * * The implementation uses POSIX system calls to emulate a real-time * clock based on the system clock. * - * @author Ludwig Knüpfer - * * @} */ @@ -42,7 +40,7 @@ * @brief Time source of the native RTC */ #ifndef NATIVE_RTC_SOURCE -#define NATIVE_RTC_SOURCE CLOCK_REALTIME +# define NATIVE_RTC_SOURCE CLOCK_REALTIME #endif static int _native_rtc_initialized = 0; diff --git a/cpu/native/periph/spidev_linux.c b/cpu/native/periph/spidev_linux.c index f5f0d29082..e204e46c21 100644 --- a/cpu/native/periph/spidev_linux.c +++ b/cpu/native/periph/spidev_linux.c @@ -7,15 +7,11 @@ */ /** - * @ingroup cpu_native - * @ingroup drivers_spidev_linux - * @{ - * * @file - * @brief Implementation of SPI access from Linux User Space - * - * @author Frank Hessel - * @} + * @ingroup cpu_native + * @ingroup drivers_spidev_linux + * @brief Implementation of SPI access from Linux User Space + * @author Frank Hessel */ #ifdef MODULE_PERIPH_SPIDEV_LINUX diff --git a/cpu/native/periph/timer.c b/cpu/native/periph/timer.c index 7a80baa2e3..507aa63830 100644 --- a/cpu/native/periph/timer.c +++ b/cpu/native/periph/timer.c @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2013 Ludwig Knüpfer * 2015 Kaspar Schleiser * @@ -8,12 +8,13 @@ */ /** - * @ingroup cpu_native - * @ingroup drivers_periph_timer - * @{ - * * @file - * @brief Native CPU periph/timer.h implementation + * @ingroup cpu_native + * @ingroup drivers_periph_timer + * @brief Native CPU periph/timer.h implementation + * @author Ludwig Knüpfer + * @author Kaspar Schleiser + * @{ * * Uses POSIX realtime clock and POSIX itimer to mimic hardware. * This is done with the timer_settime(3), timer_create(3) interfaces, which are @@ -22,9 +23,6 @@ * This is based on native's hwtimer implementation by Ludwig Knüpfer. * I removed the multiplexing, as ztimer does the same. (kaspar) * - * @author Ludwig Knüpfer - * @author Kaspar Schleiser - * * @} */ @@ -121,7 +119,7 @@ int timer_init(tim_t dev, uint32_t freq, timer_cb_t cb, void *arg) return -1; } - if (register_interrupt(SIGALRM, native_isr_timer) != 0) { + if (native_register_interrupt(SIGALRM, native_isr_timer) != 0) { DEBUG_PUTS("Failed to register SIGALRM handler"); timer_delete(itimer_monotonic); return -1; diff --git a/cpu/native/periph/uart.c b/cpu/native/periph/uart.c index c3bd7ea0bc..a1b2994409 100644 --- a/cpu/native/periph/uart.c +++ b/cpu/native/periph/uart.c @@ -7,16 +7,11 @@ */ /** - * @ingroup cpu_native - * @ingroup drivers_periph_uart - * @{ - * * @file - * @brief UART implementation based on /dev/tty devices on host - * - * @author Takuo Yonezawa - * - * @} + * @ingroup cpu_native + * @ingroup drivers_periph_uart + * @brief UART implementation based on /dev/tty devices on host + * @author Takuo Yonezawa */ #include diff --git a/cpu/native/socket_zep/socket_zep.c b/cpu/native/socket_zep/socket_zep.c index ea5617de5a..512dfe5d5d 100644 --- a/cpu/native/socket_zep/socket_zep.c +++ b/cpu/native/socket_zep/socket_zep.c @@ -7,11 +7,9 @@ */ /** - * @{ - * * @file - * @author Martine Lenders - * @author Benjamin Valentin + * @author Martine Lenders + * @author Benjamin Valentin */ #include @@ -20,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -88,19 +87,19 @@ static void _continue_reading(socket_zep_t *dev) FD_ZERO(&rfds); FD_SET(dev->sock_fd, &rfds); - _native_in_syscall++; /* no switching here */ + _native_pending_syscalls_up(); /* no switching here */ if (real_select(dev->sock_fd + 1, &rfds, NULL, NULL, &t) == 1) { int sig = SIGIO; - extern int _sig_pipefd[2]; - real_write(_sig_pipefd[1], &sig, sizeof(sig)); - _native_sigpend++; + extern int _signal_pipe_fd[2]; + real_write(_signal_pipe_fd[1], &sig, sizeof(sig)); + _native_pending_signals++; } else { native_async_read_continue(dev->sock_fd); } - _native_in_syscall--; + _native_pending_syscalls_down(); } static inline bool _dst_not_me(socket_zep_t *dev, const void *buf) @@ -640,5 +639,3 @@ void socket_zep_hal_setup(socket_zep_t *dev, ieee802154_dev_t *hal) hal->driver = &socket_zep_rf_ops; hal->priv = dev; } - -/** @} */ diff --git a/cpu/native/startup.c b/cpu/native/startup.c index 5ee0515ff4..fc1c2bb700 100644 --- a/cpu/native/startup.c +++ b/cpu/native/startup.c @@ -1,31 +1,25 @@ -/** - * Native CPU entry code - * +/* * Copyright (C) 2013 Ludwig Knüpfer * 2017 Freie Universität Berlin * * 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. - * - * @ingroup cpu_native - * @{ - * @file - * @author Ludwig Knüpfer - * @author Martine Lenders - * @} */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE +/** + * @file Ludwig Knüpfer + * @brief Native CPU entry code + * @ingroup cpu_native + * @author Martine Lenders + */ + #include -#else -#include -#endif #include #include #include #include +#include #include #include #include @@ -47,6 +41,7 @@ #define ENABLE_DEBUG 0 #include "debug.h" +#define DEBUG_STARTUP(...) DEBUG("[native] startup: " __VA_ARGS__) typedef enum { _STDIOTYPE_STDIO = 0, /**< leave intact */ @@ -62,7 +57,6 @@ pid_t _native_pid; pid_t _native_id; unsigned _native_rng_seed = 0; int _native_rng_mode = 0; -const char *_native_unix_socket_path = NULL; #ifdef MODULE_NETDEV_TAP #include "netdev_tap_params.h" @@ -120,9 +114,11 @@ static const char short_opts[] = ":hi:s:deEoc:" ""; #if __GLIBC__ -static const bool _is_glibc = true; +/* glibc and Apple's libSystem pass argc, argv, and envp to init_fini handlers */ +# define _HAVE_INIT_FINIT_PROGRAM_ARGUMENTS 1 #else -static const bool _is_glibc = false; +/* otherwise, not guaranteed */ +# define _HAVE_INIT_FINIT_PROGRAM_ARGUMENTS 0 #endif static const struct option long_opts[] = { @@ -475,7 +471,7 @@ __attribute__((constructor)) static void startup(int argc, char **argv, char **e /* Passing argc, argv, and envp to init_fini handlers is a glibc * extension. If we are not running glibc, we parse /proc/self/cmdline * to populate argc and argv by hand */ - if (!_is_glibc) { + if (!_HAVE_INIT_FINIT_PROGRAM_ARGUMENTS) { const size_t bufsize = 4096; const size_t argc_max = 32; size_t cmdlen = 0; @@ -513,6 +509,11 @@ __attribute__((constructor)) static void startup(int argc, char **argv, char **e } expect((size_t)argc < argc_max); argv = realloc(argv, sizeof(char *) * (argc + 1)); + } else { + /* must be */ + assert(argc > 0); + assert(argv); + assert(argv[0]); } _native_argv = argv; @@ -689,24 +690,24 @@ __attribute__((constructor)) static void startup(int argc, char **argv, char **e */ init_func_t *init_array_ptr = &__init_array_start; DEBUG("__init_array_start: %p\n", (void *)init_array_ptr); - while (init_array_ptr != &__init_array_end) { + while (init_array_ptr < &__init_array_end) { /* Skip everything which has already been run */ if ((*init_array_ptr) == startup) { /* Found ourselves, move on to calling the rest of the constructors */ - DEBUG("%18p - myself\n", (void *)init_array_ptr); + DEBUG_STARTUP("%18p - myself\n", (void *)init_array_ptr); ++init_array_ptr; break; } - DEBUG("%18p - skip\n", (void *)init_array_ptr); + DEBUG_STARTUP("%18p - skip\n", (void *)init_array_ptr); ++init_array_ptr; } - while (init_array_ptr != &__init_array_end) { + while (init_array_ptr < &__init_array_end) { /* call all remaining constructors */ - DEBUG("%18p - call\n", (void *)init_array_ptr); + DEBUG_STARTUP("%18p - call\n", (void *)init_array_ptr); (*init_array_ptr)(argc, argv, envp); ++init_array_ptr; } - DEBUG("done, __init_array_end: %p\n", (void *)init_array_ptr); + DEBUG_STARTUP("done, __init_array_end: %p\n", (void *)init_array_ptr); native_cpu_init(); native_interrupt_init(); @@ -727,7 +728,7 @@ __attribute__((constructor)) static void startup(int argc, char **argv, char **e periph_init(); board_init(); - register_interrupt(SIGUSR1, _reset_handler); + native_register_interrupt(SIGUSR1, _reset_handler); puts("RIOT native hardware initialization complete.\n"); irq_enable(); diff --git a/cpu/native/stdio_native/stdio_native.c b/cpu/native/stdio_native/stdio_native.c index e79bec4eba..8902b02feb 100644 --- a/cpu/native/stdio_native/stdio_native.c +++ b/cpu/native/stdio_native/stdio_native.c @@ -7,10 +7,8 @@ */ /** - * @{ - * * @file - * @author Martine S. Lenders + * @author Martine S. Lenders */ #include "kernel_defines.h" @@ -31,5 +29,3 @@ ssize_t stdio_write(const void* buffer, size_t len) { return real_write(STDOUT_FILENO, buffer, len); } - -/** @} */ diff --git a/cpu/native/syscalls.c b/cpu/native/syscalls.c index 76a13e9f81..222162b4a7 100644 --- a/cpu/native/syscalls.c +++ b/cpu/native/syscalls.c @@ -1,28 +1,24 @@ -/** - * Native CPU syscall managing - * - * Wrap system calls and system call invoking library calls to make - * sure no context switches happen during a system call. - * +/* * Copyright (C) 2013 Ludwig Knüpfer * * 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. - * - * @ingroup cpu_native - * @{ - * @file - * @author Ludwig Knüpfer */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#include -#else -#include -#endif +/** + * @file + * @ingroup cpu_native + * @brief Native CPU syscall managing + * @{ + * + * Wrap system calls and system call invoking library calls to make + * sure no context switches happen during a system call. + * + * @} + */ +#include #include #include #include @@ -32,7 +28,7 @@ #include #include #ifdef MODULE_LIBC_GETTIMEOFDAY -#include +# include #endif #include #include @@ -40,114 +36,55 @@ #include "cpu.h" #include "irq.h" #ifdef MODULE_LIBC_GETTIMEOFDAY -#include "time_units.h" -#include "ztimer64.h" +# include "time_units.h" +# include "ztimer64.h" #endif + #include "stdio_base.h" #include "kernel_defines.h" +/* This header defines the system call function pointers */ +#define NATIVE_SYSCALLS_DEFINITION 1 #include "native_internal.h" #define ENABLE_DEBUG 0 #include "debug.h" -ssize_t (*real_read)(int fd, void *buf, size_t count); -ssize_t (*real_write)(int fd, const void *buf, size_t count); -size_t (*real_fread)(void *ptr, size_t size, size_t nmemb, FILE *stream); -ssize_t (*real_recv)(int sockfd, void *buf, size_t len, int flags); -void (*real_clearerr)(FILE *stream); -__attribute__((noreturn)) void (*real_exit)(int status); -void (*real_free)(void *ptr); -void* (*real_malloc)(size_t size); -void* (*real_calloc)(size_t nmemb, size_t size); -void* (*real_realloc)(void *ptr, size_t size); -void (*real_freeaddrinfo)(struct addrinfo *res); -void (*real_freeifaddrs)(struct ifaddrs *ifa); -void (*real_srandom)(unsigned int seed); -int (*real_accept)(int socket, ...); -int (*real_bind)(int socket, ...); -int (*real_connect)(int socket, ...); -int (*real_printf)(const char *format, ...); -int (*real_getaddrinfo)(const char *node, ...); -int (*real_getifaddrs)(struct ifaddrs **ifap); -int (*real_gettimeofday)(struct timeval *t, ...); -int (*real_getpid)(void); -int (*real_chdir)(const char *path); -int (*real_close)(int); -int (*real_fcntl)(int, int, ...); -int (*real_creat)(const char *path, ...); -int (*real_dup2)(int, int); -int (*real_execve)(const char *, char *const[], char *const[]); -int (*real_fork)(void); -int (*real_feof)(FILE *stream); -int (*real_ferror)(FILE *stream); -int (*real_listen)(int socket, int backlog); -int (*real_ioctl)(int fildes, unsigned long request, ...); -int (*real_open)(const char *path, int oflag, ...); -int (*real_pause)(void); -int (*real_pipe)(int[2]); -int (*real_select)(int nfds, ...); -int (*real_poll)(struct pollfd *fds, ...); -int (*real_setsid)(void); -int (*real_setsockopt)(int socket, ...); -int (*real_socket)(int domain, int type, int protocol); -int (*real_unlink)(const char *); -long int (*real_random)(void); -const char* (*real_gai_strerror)(int errcode); -FILE* (*real_fopen)(const char *path, const char *mode); -int (*real_fclose)(FILE *stream); -int (*real_fseek)(FILE *stream, long offset, int whence); -long (*real_ftell)(FILE *stream); -int (*real_fputc)(int c, FILE *stream); -int (*real_fgetc)(FILE *stream); -mode_t (*real_umask)(mode_t cmask); -ssize_t (*real_writev)(int fildes, const struct iovec *iov, int iovcnt); -ssize_t (*real_send)(int sockfd, const void *buf, size_t len, int flags); -off_t (*real_lseek)(int fd, off_t offset, int whence); -off_t (*real_fstat)(int fd, struct stat *statbuf); -int (*real_fsync)(int fd); -int (*real_mkdir)(const char *pathname, mode_t mode); -int (*real_rmdir)(const char *pathname); -DIR *(*real_opendir)(const char *name); -struct dirent *(*real_readdir)(DIR *dirp); -int (*real_closedir)(DIR *dirp); -int (*real_rename)(const char *, const char *); -int (*real_statvfs)(const char *restrict path, struct statvfs *restrict buf); +#define _DEBUG_PREFIX "[native] syscalls: " +#define DEBUG_SYSCALLS(...) DEBUG(_DEBUG_PREFIX __VA_ARGS__) + +#define _SYSCALL_ENTER_MESSAGE _DEBUG_PREFIX "> _native_pending_syscalls\n" +#define _SYSCALL_LEAVE_MESSAGE _DEBUG_PREFIX "< _native_pending_syscalls\n" void _native_syscall_enter(void) { - _native_in_syscall++; + _native_pending_syscalls_up(); if (IS_ACTIVE(ENABLE_DEBUG)) { - real_write(STDERR_FILENO, "> _native_in_syscall\n", 21); + real_write(STDERR_FILENO, _SYSCALL_ENTER_MESSAGE, sizeof(_SYSCALL_ENTER_MESSAGE) - 1); } } void _native_syscall_leave(void) { if (IS_ACTIVE(ENABLE_DEBUG)) { - real_write(STDERR_FILENO, "< _native_in_syscall\n", 21); + real_write(STDERR_FILENO, _SYSCALL_LEAVE_MESSAGE, sizeof(_SYSCALL_LEAVE_MESSAGE) - 1); } - _native_in_syscall--; + _native_pending_syscalls_down(); if ( - (_native_sigpend > 0) + (_native_pending_signals > 0) && (_native_in_isr == 0) - && (_native_in_syscall == 0) - && (native_interrupts_enabled == 1) + && (_native_pending_syscalls == 0) + && (_native_interrupts_enabled) && (thread_get_active() != NULL) ) { _native_in_isr = 1; - /* Use intermediate cast to uintptr_t to silence -Wcast-align. - * stacks are manually word aligned in thread_static_init() */ - _native_cur_ctx = (ucontext_t *)(uintptr_t)thread_get_active()->sp; - native_isr_context.uc_stack.ss_sp = __isr_stack; - native_isr_context.uc_stack.ss_size = __isr_stack_size; - native_isr_context.uc_stack.ss_flags = 0; - native_interrupts_enabled = 0; - makecontext(&native_isr_context, native_irq_handler, 0); - if (swapcontext(_native_cur_ctx, &native_isr_context) == -1) { + _native_interrupts_enabled = false; + + _native_isr_context_make(_native_call_sig_handlers_and_switch); + if (swapcontext(_native_user_context(), _native_isr_context) == -1) { err(EXIT_FAILURE, "_native_syscall_leave: swapcontext"); } } @@ -509,9 +446,6 @@ int _gettimeofday(struct timeval *tp, void *restrict tzp) } #endif -/** - * set up native internal syscall symbols - */ void _native_init_syscalls(void) { *(void **)(&real_read) = dlsym(RTLD_NEXT, "read"); diff --git a/cpu/native/tramp.S b/cpu/native/tramp.S deleted file mode 100644 index 85c7c60dc0..0000000000 --- a/cpu/native/tramp.S +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2013, 2014 Ludwig Knüpfer - * Copyright (C) 2014 Thomas Eichinger - * - * 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. - */ - -.text - -#ifdef __arm__ - -.globl _native_sig_leave_tramp -_native_sig_leave_tramp: - /* save _native_saved_eip and registers */ - stmdb sp!, {r0} - ldr r0, =_native_saved_eip - ldr r0, [r0] - stmdb sp!, {r0-r12} - stmdb sp!, {lr} - - /* exchange r0 and _native_saved_eip */ - ldr r0, [sp,#56] - ldr r1, [sp,#4 ] - str r0, [sp,#4 ] - str r1, [sp,#56] - - /* call swapcontext ( _native_cur_ctx, _native_isr_ctx ) */ - ldr r2, =_native_cur_ctx - ldr r0, [r2] - ldr r2, =_native_isr_ctx - ldr r1, [r2] - bl swapcontext - - /* reeanble interrupts */ - bl irq_enable - - /* _native_in_isr = 0 */ - eor r0, r0, r0 - ldr r2, =_native_in_isr - str r0, [r2] - - /* restore registers, jump to (saved) _native_saved_eip */ - ldmia sp!, {lr} - ldmia sp!, {r0-r12} - ldmia sp!, {pc} - -.globl _native_sig_leave_handler -_native_sig_leave_handler: - stmdb sp!, {r0} - ldr r0, =_native_saved_eip - ldr r0, [r0] - stmdb sp!, {r0-r12} - stmdb sp!, {lr} - /* exchange r0 and _native_saved_eip */ - ldr r0, [sp,#56] - ldr r1, [sp,#4 ] - str r0, [sp,#4 ] - str r1, [sp,#56] - /* _native_in_isr = 0 */ - eor r0, r0, r0 - ldr r1, =_native_in_isr - str r0, [r1] - ldmia sp!, {lr} - ldmia sp!, {r0-r12} - ldmia sp!, {pc} - -#else -.globl _native_sig_leave_tramp - -#ifdef __x86_64__ -_native_sig_leave_tramp: - pushq _native_saved_eip(%rip) - pushfq - - pushq %rax - pushq %rcx - pushq %rdx - pushq %rbx - pushq %rbp - pushq %rsi - pushq %rdi - pushq %r8 - pushq %r9 - pushq %r10 - pushq %r11 - pushq %r12 - pushq %r13 - pushq %r14 - pushq %r15 - - mov _native_isr_ctx(%rip), %rsi - mov _native_cur_ctx(%rip), %rdi - - call swapcontext - - call irq_enable - - movl $0x0, _native_in_isr(%rip) - popq %r15 - popq %r14 - popq %r13 - popq %r12 - popq %r11 - popq %r10 - popq %r9 - popq %r8 - popq %rdi - popq %rsi - popq %rbp - popq %rbx - popq %rdx - popq %rcx - popq %rax - - popfq - ret -#else -_native_sig_leave_tramp: - pushl _native_saved_eip - pushfl - pushal - - pushl _native_isr_ctx - pushl _native_cur_ctx - call swapcontext - addl $8, %esp - - call irq_enable - - movl $0x0, _native_in_isr - popal - popfl - - ret -#endif - -.globl _native_sig_leave_handler -_native_sig_leave_handler: -#ifdef __x86_64__ - pushq _native_saved_eip(%rip) - movl $0x0, _native_in_isr(%rip) -#else - pushl _native_saved_eip - movl $0x0, _native_in_isr -#endif - ret -#endif - -#if defined(__linux__) && defined(__ELF__) -.section .note.GNU-stack,"",%progbits -#endif diff --git a/cpu/native/vfs/native_vfs.c b/cpu/native/vfs/native_vfs.c index 2d701c8a9e..8d4adf6a72 100644 --- a/cpu/native/vfs/native_vfs.c +++ b/cpu/native/vfs/native_vfs.c @@ -7,13 +7,10 @@ */ /** - * @ingroup cpu_native - * @{ - * * @file - * @brief VFS wrappers for POSIX file I/O functions - * - * @author Kaspar Schleiser + * @ingroup cpu_native + * @brief VFS wrappers for POSIX file I/O functions + * @author Kaspar Schleiser */ #include @@ -145,5 +142,3 @@ int unlink(const char *path) } return 0; } - -/** @} */ diff --git a/drivers/pcd8544/pcd8544.c b/drivers/pcd8544/pcd8544.c index b477a288cd..981eb6afc2 100644 --- a/drivers/pcd8544/pcd8544.c +++ b/drivers/pcd8544/pcd8544.c @@ -30,7 +30,7 @@ #define ASCII_MIN 0x20 /**< start of ASCII table */ #define ASCII_MAX 0x7e /**< end of ASCII table */ -#define CHAR_WIDTH (6U) /**< pixel width of a single character */ +#define CHAR_PIXEL_WIDTH (6U) /**< pixel width of a single character */ #define SPI_CLK (SPI_CLK_1MHZ) #define SPI_MODE (SPI_MODE_0) @@ -328,10 +328,10 @@ void pcd8544_write_c(const pcd8544_t *dev, uint8_t x, uint8_t y, char c) } /* set position */ lock(dev); - _set_x(dev, x * CHAR_WIDTH); + _set_x(dev, x * CHAR_PIXEL_WIDTH); _set_y(dev, y); /* write char */ - for (unsigned i = 0; i < CHAR_WIDTH - 1; i++) { + for (unsigned i = 0; i < CHAR_PIXEL_WIDTH - 1; i++) { _write(dev, MODE_DTA, _ascii[c - ASCII_MIN][i]); } _write(dev, MODE_DTA, 0x00); diff --git a/makefiles/arch/native.inc.mk b/makefiles/arch/native.inc.mk index bb1ef3a88d..1e1804199c 100644 --- a/makefiles/arch/native.inc.mk +++ b/makefiles/arch/native.inc.mk @@ -57,6 +57,12 @@ ifeq ($(OS),Darwin) CFLAGS += -Wno-deprecated-declarations endif +ifneq ($(filter $(OS),Darwin FreeBSD),) + CFLAGS += -D_XOPEN_SOURCE +else + CFLAGS += -D_GNU_SOURCE +endif + # unwanted (CXXUWFLAGS) and extra (CXXEXFLAGS) flags for c++ CXXUWFLAGS += CXXEXFLAGS += diff --git a/sys/include/fs/native_fs.h b/sys/include/fs/native_fs.h index 1a521990fc..5abfd90922 100644 --- a/sys/include/fs/native_fs.h +++ b/sys/include/fs/native_fs.h @@ -7,14 +7,14 @@ */ /** - * @defgroup sys_fs_native native fs integration - * @ingroup cpu_native - * @brief Access to the host fs from RIOT native + * @defgroup sys_fs_native Native FS Integration + * @ingroup cpu_native + * @brief Access to the host filesystem from RIOT native * * @{ * * @file - * @brief native integration with vfs + * @brief Native integration with virtual filesystem (VFS) * * @author Benjamin Valentin */