1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-14 17:13:50 +01:00

Merge pull request #21283 from carl-tud/native-gardening

cpu/native: Gardening/QoL
This commit is contained in:
benpicco 2025-03-12 17:54:07 +00:00 committed by GitHub
commit a042d66e68
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
59 changed files with 1753 additions and 1416 deletions

View File

@ -1,6 +1,4 @@
/**
* Multiple asynchronous read on file descriptors
*
/*
* Copyright (C) 2015 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>,
* Martine Lenders <mlenders@inf.fu-berlin.de>
* Kaspar Schleiser <kaspar@schleiser.de>
@ -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 <Yonezawa-T2@mail.dnp.co.jp>
*/
@ -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);
}
}
/** @} */

View File

@ -7,9 +7,9 @@
*/
/**
* @{
*
* @file
* @ingroup cpu_native
* @brief Backtrace implementation for native CPU
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/
@ -55,5 +55,3 @@ int backtrace_len(void)
return backtrace(array, BACKTRACE_SIZE + 1) - 1;
}
/** @} */

View File

@ -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 <benjamin.valentin@ml-pa.com>
* @}
*/
#include <assert.h>

271
cpu/native/cpu.c Normal file
View File

@ -0,0 +1,271 @@
/*
* Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
* 2013 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*
* 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 <ludwig.knuepfer@fu-berlin.de>
* @author Kaspar Schleiser <kaspar@schleiser.de>
*
* In-process preemptive context switching utilizes POSIX ucontexts.
* (ucontext provides for architecture independent stack handling)
*/
#include <err.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#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;
}

View File

@ -7,15 +7,10 @@
*/
/**
* @ingroup sys_fs_native
* @{
*
* @file
* @brief native integration with vfs
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
*
* @}
* @ingroup sys_fs_native
* @brief Native integration with virtual filesystem (VFS)
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
*/
#include <assert.h>
@ -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)

View File

@ -7,16 +7,15 @@
*/
/**
* @ingroup cpu_native
* @addtogroup cpu_native
* @{
*
* @file
* @brief Architecture details
*
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*
*/
/**
* @file
* @brief Architecture details
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*/
#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 */
/** @} */

View File

@ -7,13 +7,14 @@
*/
/**
* @ingroup cpu_native
* @addtogroup cpu_native
* @{
*
*/
/**
* @file
* @brief Multiple asynchronous read on file descriptors
*
* @author Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
* @brief Multiple asynchronous read on file descriptors
* @author Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
*/
#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
/**

View File

@ -7,18 +7,17 @@
*/
/**
* @ingroup cpu_native
*
* @addtogroup cpu_native
* @{
*
* @file
* @brief Implementation of fast atomic utility functions
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*/
/**
* @file
* @brief Implementation of fast atomic utility functions
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*/
#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 */
/** @} */

View File

@ -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 <m.lenders@fu-berlin.de>
* @brief Backtrace functionalitry
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/
#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
/**

View File

@ -7,15 +7,15 @@
*/
/**
* @ingroup drivers_candev_linux
* @addtogroup drivers_candev_linux
* @{
*
* @file
* @brief Default linux can config
*
* @author Vincent Dupont <vincent@otakeys.com>
*/
/**
* @file
* @brief Default linux can config
* @author Vincent Dupont <vincent@otakeys.com>
*/
#ifndef CAN_PARAMS_H
#define CAN_PARAMS_H

View File

@ -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 <hermann@otakeys.com>
* @author Aurelien Gonce <aurelien.gonce@altran.com>
* @author Vincent Dupont <vincent@otakeys.com>
*/
/**
* @file
* @brief Implementation of simulated CAN controller driver using SocketCAN on Linux
* @author Hermann Lelong <hermann@otakeys.com>
* @author Aurelien Gonce <aurelien.gonce@altran.com>
* @author Vincent Dupont <vincent@otakeys.com>
*/
#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 <stdbool.h>
# include <stdbool.h>
#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

View File

@ -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 <ludwig.knuepfer@fu-berlin.de>
*
* The native CPU uses system calls to simulate hardware access.
*
* @{
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*/
/**
* @file
* @brief Native CPU header
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*/
#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 */
/** @} */

View File

@ -1,17 +1,20 @@
/**
* Native CPU configuration
*
/*
* Copyright (C) 2013 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*
* 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 <ludwig.knuepfer@fu-berlin.de>
* @}
* @brief Native CPU configuration
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*/
#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 */
/** @} */

View File

@ -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 <alexandre.abadie@inria.fr>
*/
/**
* @file
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*/
#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
/**

View File

@ -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 <benpicco@googlemail.com>
*/
/**
* @file
* @brief Implementation of GPIO access from Linux User Space
* @author Benjamin Valentin <benpicco@googlemail.com>
*/
#ifndef GPIODEV_LINUX_H
#define GPIODEV_LINUX_H

View File

@ -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 <vincent@otakeys.com>
*/
/**
* @file
* @author Vincent Dupont <vincent@otakeys.com>
*/
#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 */
/** @} */

View File

@ -7,15 +7,15 @@
*/
/**
* @ingroup cpu_native
* @addtogroup cpu_native
* @{
*
* @file
* @brief Command-line EUI provider for native
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
*/
/**
* @file
* @brief Command-line EUI provider for native
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
*/
#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.
*/

View File

@ -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 <ludwig.knuepfer@fu-berlin.de>
*/
/**
* @file
* @brief Native CPU internal symbols
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
* @author carl-tud
*/
#ifndef NATIVE_INTERNAL_H
#define NATIVE_INTERNAL_H
#include <signal.h>
#include "util/ucontext.h"
#include <stdio.h>
#include <stdint.h>
#include <poll.h>
/* 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 <ucontext.h>
#undef _XOPEN_SOURCE
#else
#include <ucontext.h>
#endif
#elif defined(__linux__)
#ifndef _GNU_SOURCE
#define GNU_SOURCE
#include <ucontext.h>
#undef GNU_SOURCE
#else
#include <ucontext.h>
#endif
#endif /* BSD/Linux */
#include <stdbool.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <time.h>
@ -64,150 +50,287 @@
#include <sys/uio.h>
#include <dirent.h>
#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 */
/** @} */

View File

@ -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 <kaspar@schleiser.de>
* @brief Definitions for @ref netdev ethernet driver for host system's
* TAP interfaces
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#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 */
/** @} */

View File

@ -7,14 +7,14 @@
*/
/**
* @ingroup drivers_netdev
* @brief
* @addtogroup drivers_netdev
* @{
*
*/
/**
* @file
* @brief Default configuration for the netdev_tap driver
*
* @author Martine Lenders <m.lenders@fu-berlin.de>
* @brief Default configuration for the netdev_tap driver
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/
#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
/**

View File

@ -1,18 +1,21 @@
/**
* Native CPU peripheral configuration
*
/*
* Copyright (C) 2014 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*
* 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 <ludwig.knuepfer@fu-berlin.de>
*/
/**
* @addtogroup cpu_native
* @{
*/
/**
* @file
* @brief Native CPU peripheral configuration
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*/
#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
/**

View File

@ -7,15 +7,15 @@
*/
/**
* @ingroup cpu_native
* @addtogroup cpu_native
* @{
*
* @file
* @brief CPU specific definitions for internal peripheral handling
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
/**
* @file
* @brief CPU specific definitions for internal peripheral handling
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#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 <linux/gpio.h>
# include <linux/gpio.h>
/* 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

View File

@ -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 <m.lenders@fu-berlin.de>
* @brief Socket ZEP definitions
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/
#ifndef SOCKET_ZEP_H
#define SOCKET_ZEP_H

View File

@ -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 <m.lenders@fu-berlin.de>
* @brief Configuration parameters for the @ref drivers_socket_zep driver
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/
#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
/**

View File

@ -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 <frank@fhessel.de>
*/
/**
* @file
* @brief Implementation of SPI access from Linux User Space
* @author Frank Hessel <frank@fhessel.de>
*/
#ifndef SPIDEV_LINUX_H
#define SPIDEV_LINUX_H

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2013 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*
* 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 <sys/time.h>
#include <stdint.h>
#include <ifaddrs.h>
#include <stdio.h>
/**
* @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 */

View File

@ -8,15 +8,15 @@
*/
/**
* @ingroup cpu_native
* @addtogroup cpu_native
* @{
*
* @file
* @brief Implementation of the kernels thread interface
*
* @author Koen Zandberg <koen@bergzand.net>
*/
/**
* @file
* @brief Implementation of the kernels thread interface
* @author Koen Zandberg <koen@bergzand.net>
*/
#ifndef THREAD_ARCH_H
#define THREAD_ARCH_H

View File

@ -7,15 +7,15 @@
*/
/**
* @ingroup cpu_native
* @addtogroup cpu_native
* @{
*
* @file
* @brief UART implementation based on /dev/tty devices on host
*
* @author Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
*/
/**
* @file
* @brief UART implementation based on /dev/tty devices on host
* @author Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
*/
#ifndef TTY_UART_H
#define TTY_UART_H

View File

@ -0,0 +1,136 @@
/*
* Copyright (C) 2013 - 2016 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
* 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 <libucontext/libucontext.h>
#else
# include <ucontext.h>
#endif /* USE_LIBUCONTEXT */
#include <stdint.h>
#include <stdbool.h>
#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 */

View File

@ -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 <valgrind.h>
#define VALGRIND_DEBUG DEBUG
# elif defined(HAVE_VALGRIND_VALGRIND_H)
# include <valgrind/valgrind.h>
#define VALGRIND_DEBUG DEBUG
#else
# define VALGRIND_STACK_REGISTER(...) (0)
# define VALGRIND_DEBUG(...)
#endif
#ifdef __cplusplus
extern "C" {}
#endif
#endif /* UTIL_VALGRIND_H */

View File

@ -1,22 +1,17 @@
/**
* Native CPU irq.h implementation
*
/*
* Copyright (C) 2013 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*
* 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 <ludwig.knuepfer@fu-berlin.de>
*/
/* __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 <ludwig.knuepfer@fu-berlin.de>
*/
#include <err.h>
#include <signal.h>
@ -24,16 +19,7 @@
#include <string.h>
#include <unistd.h>
#ifdef HAVE_VALGRIND_H
#include <valgrind.h>
#define VALGRIND_DEBUG DEBUG
#elif defined(HAVE_VALGRIND_VALGRIND_H)
#include <valgrind/valgrind.h>
#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.");
}
/** @} */

View File

@ -7,12 +7,10 @@
*/
/**
* @{
* @brief mtd flash emulation for native
*
* @file
*
* @author Vincent Dupont <vincent@otakeys.com>
* @ingroup drivers_mtd_native
* @brief MTD flash emulation for native
* @author Vincent Dupont <vincent@otakeys.com>
*/
#include <errno.h>
@ -156,5 +154,3 @@ const mtd_desc_t native_flash_driver = {
.erase = _erase,
.init = _init,
};
/** @} */

224
cpu/native/native.S Normal file
View File

@ -0,0 +1,224 @@
/*
* Copyright (C) 2013, 2014 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
* Copyright (C) 2014 Thomas Eichinger <thomas.eichinger1@gmail.com>
*
* 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

View File

@ -1,284 +0,0 @@
/*
* Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
* 2013 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*
* 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 <ludwig.knuepfer@fu-berlin.de>
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
/* __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 <err.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#if USE_LIBUCONTEXT
#include <libucontext/libucontext.h>
#else
#include <ucontext.h>
#endif
#ifdef HAVE_VALGRIND_H
#include <valgrind.h>
#define VALGRIND_DEBUG DEBUG
#elif defined(HAVE_VALGRIND_VALGRIND_H)
#include <valgrind/valgrind.h>
#define VALGRIND_DEBUG DEBUG
#else
#define VALGRIND_STACK_REGISTER(...) (0)
#define VALGRIND_DEBUG(...)
#endif
#include <stdlib.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"
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");
}
/** @} */

View File

@ -9,13 +9,13 @@
* more details.
*/
/*
/**
* @file
* @ingroup drivers_netdev
* @{
* @brief Low-level ethernet driver for tap interfaces
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @}
*/
#include <assert.h>
#include <err.h>
#include <errno.h>
@ -28,19 +28,20 @@
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <unistd.h>
#include <signal.h>
/* needs to be included before native's declarations of ntohl etc. */
#include "byteorder.h"
#ifdef __FreeBSD__
#include <sys/socket.h>
#include <net/if.h>
#include <ifaddrs.h>
#include <net/if_dl.h>
#if defined(__FreeBSD__)
# include <sys/socket.h>
# include <net/if.h>
# include <ifaddrs.h>
# include <net/if_dl.h>
#else
#include <net/if.h>
#include <linux/if_tun.h>
#include <linux/if_ether.h>
# include <net/if.h>
# include <linux/if_tun.h>
# include <linux/if_ether.h>
#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]);

View File

@ -7,15 +7,12 @@
*/
/**
* @ingroup cpu_native
* @{
*
* @file
* @brief Crash handling functions implementation for 'native' port
*
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
* @author Kévin Roussel <Kevin.Roussel@inria.fr>
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @ingroup cpu_native
* @brief Crash handling functions implementation for 'native' port
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
* @author Kévin Roussel <Kevin.Roussel@inria.fr>
* @author Oliver Hahm <oliver.hahm@inria.fr>
*/
#include <errno.h>

View File

@ -7,16 +7,12 @@
*/
/**
* @ingroup drivers_candev_linux
* @{
*
* @file
* @brief Implementation of simulated CAN controller driver using SocketCAN on Linux
*
* @author Hermann Lelong <hermann@otakeys.com>
* @author Aurelien Gonce <aurelien.gonce@altran.com>
* @author Vincent Dupont <vincent@otakeys.com>
* @}
* @ingroup drivers_candev_linux
* @brief Implementation of simulated CAN controller driver using SocketCAN on Linux
* @author Hermann Lelong <hermann@otakeys.com>
* @author Aurelien Gonce <aurelien.gonce@altran.com>
* @author Vincent Dupont <vincent@otakeys.com>
*/
#if !defined(__linux__)

View File

@ -7,16 +7,11 @@
*/
/**
* @ingroup cpu_native
* @ingroup drivers_periph_cpuid
* @{
*
* @file
* @brief Implementation
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*
* @}
* @ingroup cpu_native
* @ingroup drivers_periph_cpuid
* @brief CPUID implementation
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#include <string.h>

View File

@ -7,15 +7,11 @@
*/
/**
* @ingroup cpu_native
* @ingroup drivers_periph_eeprom
* @{
*
* @file
* @brief Low-level EEPROM driver implementation for native
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
* @}
* @ingroup cpu_native
* @ingroup drivers_periph_eeprom
* @brief Low-level EEPROM driver implementation for native
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*/
#include <stdio.h>

View File

@ -7,15 +7,11 @@
*/
/**
* @ingroup cpu_native
* @ingroup drivers_periph_flashpage
* @{
*
* @file
* @brief Low-level flashpage driver emulation
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
* @}
* @ingroup cpu_native
* @ingroup drivers_periph_flashpage
* @brief Low-level flashpage driver emulation
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
*/
#include <assert.h>

View File

@ -7,18 +7,13 @@
*/
/**
* @ingroup cpu_native
* @ingroup drivers_periph_gpio
* @{
*
* @file
* @brief native GPIO implementation
*
* @author Benjamin Valentin <benpicco@googlemail.com>
* @ingroup cpu_native
* @ingroup drivers_periph_gpio
* @brief native GPIO implementation
* @author Benjamin Valentin <benpicco@googlemail.com>
*/
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <linux/gpio.h>
@ -314,5 +309,3 @@ void gpio_irq_disable(gpio_t pin)
}
#endif /* MODULE_PERIPH_GPIO_IRQ */
/** @} */

View File

@ -7,14 +7,11 @@
*/
/**
* @ingroup cpu_native
* @ingroup drivers_periph_gpio
* @{
*
* @file
* @brief empty GPIO implementation
*
* @author Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
* @ingroup cpu_native
* @ingroup drivers_periph_gpio
* @brief empty GPIO implementation
* @author Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
*/
#include "periph/gpio.h"
@ -97,5 +94,3 @@ __attribute__((weak)) void gpio_write(gpio_t pin, bool value) {
pin->value = value;
}
}
/** @} */

View File

@ -8,14 +8,11 @@
*/
/**
* @ingroup cpu_native
* @ingroup drivers_periph_hwrng
* @{
*
* @file
* @brief HWRNG interface implementation
*
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
* @ingroup cpu_native
* @ingroup drivers_periph_hwrng
* @brief HWRNG interface implementation
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*/
#include <string.h>
@ -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;
}
/**
* @}
*/

View File

@ -7,14 +7,11 @@
*/
/**
* @ingroup cpu_native
* @ingroup drivers_periph_pm
* @{
*
* @file
* @brief native Power Management implementation
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @ingroup cpu_native
* @ingroup drivers_periph_pm
* @brief Native Power Management implementation
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#include <err.h>
@ -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();
}
}

View File

@ -7,15 +7,11 @@
*/
/**
* @ingroup cpu_native
* @ingroup drivers_periph_pwm
* @{
*
* @file
* @brief Low-level PWM driver implementation
*
* @author Gilles DOFFE <g.doffe@gmail.com>
* @}
* @ingroup cpu_native
* @ingroup drivers_periph_pwm
* @brief Low-level PWM driver implementation
* @author Gilles DOFFE <g.doffe@gmail.com>
*/
#include <assert.h>

View File

@ -7,16 +7,11 @@
*/
/**
* @ingroup cpu_native
* @ingroup drivers_periph_qdec
* @{
*
* @file
* @brief Low-level QDEC driver implementation
*
* @author Gilles DOFFE <g.doffe@gmail.com>
*
* @}
* @ingroup cpu_native
* @ingroup drivers_periph_qdec
* @brief Low-level QDEC driver implementation
* @author Gilles DOFFE <g.doffe@gmail.com>
*/
#include <time.h>

View File

@ -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 <ludwig.knuepfer@fu-berlin.de>
* @{
*
* The implementation uses POSIX system calls to emulate a real-time
* clock based on the system clock.
*
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*
* @}
*/
@ -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;

View File

@ -7,15 +7,11 @@
*/
/**
* @ingroup cpu_native
* @ingroup drivers_spidev_linux
* @{
*
* @file
* @brief Implementation of SPI access from Linux User Space
*
* @author Frank Hessel <frank@fhessel.de>
* @}
* @ingroup cpu_native
* @ingroup drivers_spidev_linux
* @brief Implementation of SPI access from Linux User Space
* @author Frank Hessel <frank@fhessel.de>
*/
#ifdef MODULE_PERIPH_SPIDEV_LINUX

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright (C) 2013 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
* 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
@ -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 <ludwig.knuepfer@fu-berlin.de>
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @{
*
* 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 <ludwig.knuepfer@fu-berlin.de>
* @author Kaspar Schleiser <kaspar@schleiser.de>
*
* @}
*/
@ -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;

View File

@ -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 <Yonezawa-T2@mail.dnp.co.jp>
*
* @}
* @ingroup cpu_native
* @ingroup drivers_periph_uart
* @brief UART implementation based on /dev/tty devices on host
* @author Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
*/
#include <errno.h>

View File

@ -7,11 +7,9 @@
*/
/**
* @{
*
* @file
* @author Martine Lenders <m.lenders@fu-berlin.de>
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
* @author Martine Lenders <m.lenders@fu-berlin.de>
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
*/
#include <assert.h>
@ -20,6 +18,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@ -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;
}
/** @} */

View File

@ -1,31 +1,25 @@
/**
* Native CPU entry code
*
/*
* Copyright (C) 2013 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
* 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 <ludwig.knuepfer@fu-berlin.de>
* @author Martine Lenders <m.lenders@fu-berlin.de>
* @}
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
/**
* @file Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
* @brief Native CPU entry code
* @ingroup cpu_native
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/
#include <dlfcn.h>
#else
#include <dlfcn.h>
#endif
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <features.h>
#include <getopt.h>
#include <stdbool.h>
@ -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();

View File

@ -7,10 +7,8 @@
*/
/**
* @{
*
* @file
* @author Martine S. Lenders <m.lenders@fu-berlin.de>
* @author Martine S. Lenders <m.lenders@fu-berlin.de>
*/
#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);
}
/** @} */

View File

@ -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 <ludwig.knuepfer@fu-berlin.de>
*
* 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 <ludwig.knuepfer@fu-berlin.de>
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#include <dlfcn.h>
#else
#include <dlfcn.h>
#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 <dlfcn.h>
#include <err.h>
#include <errno.h>
#include <poll.h>
@ -32,7 +28,7 @@
#include <stdio.h>
#include <stdarg.h>
#ifdef MODULE_LIBC_GETTIMEOFDAY
#include <sys/time.h>
# include <sys/time.h>
#endif
#include <ifaddrs.h>
#include <sys/stat.h>
@ -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");

View File

@ -1,153 +0,0 @@
/*
* Copyright (C) 2013, 2014 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
* Copyright (C) 2014 Thomas Eichinger <thomas.eichinger1@gmail.com>
*
* 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

View File

@ -7,13 +7,10 @@
*/
/**
* @ingroup cpu_native
* @{
*
* @file
* @brief VFS wrappers for POSIX file I/O functions
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @ingroup cpu_native
* @brief VFS wrappers for POSIX file I/O functions
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#include <errno.h>
@ -145,5 +142,3 @@ int unlink(const char *path)
}
return 0;
}
/** @} */

View File

@ -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);

View File

@ -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 +=

View File

@ -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 <benjamin.valentin@ml-pa.com>
*/