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:
commit
a042d66e68
@ -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);
|
||||
}
|
||||
}
|
||||
/** @} */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -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
271
cpu/native/cpu.c
Normal 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;
|
||||
}
|
||||
@ -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)
|
||||
|
||||
@ -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 */
|
||||
/** @} */
|
||||
|
||||
@ -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
|
||||
|
||||
/**
|
||||
|
||||
@ -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 */
|
||||
/** @} */
|
||||
|
||||
@ -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
|
||||
|
||||
/**
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 */
|
||||
/** @} */
|
||||
|
||||
@ -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 */
|
||||
/** @} */
|
||||
|
||||
@ -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
|
||||
|
||||
/**
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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 */
|
||||
/** @} */
|
||||
|
||||
@ -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 */
|
||||
/** @} */
|
||||
|
||||
@ -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
|
||||
|
||||
/**
|
||||
|
||||
@ -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
|
||||
|
||||
/**
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
/**
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
118
cpu/native/include/syscalls.h
Normal file
118
cpu/native/include/syscalls.h
Normal 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 */
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
136
cpu/native/include/util/ucontext.h
Normal file
136
cpu/native/include/util/ucontext.h
Normal 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 */
|
||||
27
cpu/native/include/util/valgrind.h
Normal file
27
cpu/native/include/util/valgrind.h
Normal 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 */
|
||||
@ -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.");
|
||||
}
|
||||
/** @} */
|
||||
@ -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
224
cpu/native/native.S
Normal 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
|
||||
@ -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");
|
||||
}
|
||||
/** @} */
|
||||
@ -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]);
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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__)
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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 */
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 +=
|
||||
|
||||
@ -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>
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user