Merge pull request #14827 from keith-packard/pr/libc/picolibc
Pr/libc/picolibc
This commit is contained in:
commit
f3e1032f6e
@ -479,6 +479,14 @@ ifneq (,$(filter posix_select,$(USEMODULE)))
|
|||||||
USEMODULE += xtimer
|
USEMODULE += xtimer
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter picolibc,$(USEMODULE)))
|
||||||
|
# allow custom picolibc syscalls implementations by adding
|
||||||
|
# picolibc_syscalls_XXX to USEMODULE
|
||||||
|
ifeq (,$(filter picolibc_syscalls_%,$(USEMODULE)))
|
||||||
|
USEMODULE += picolibc_syscalls_default
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter posix_sockets,$(USEMODULE)))
|
ifneq (,$(filter posix_sockets,$(USEMODULE)))
|
||||||
USEMODULE += bitfield
|
USEMODULE += bitfield
|
||||||
USEMODULE += random
|
USEMODULE += random
|
||||||
|
|||||||
@ -176,6 +176,10 @@ struct _thread {
|
|||||||
const char *name; /**< thread's name */
|
const char *name; /**< thread's name */
|
||||||
int stack_size; /**< thread's stack size */
|
int stack_size; /**< thread's stack size */
|
||||||
#endif
|
#endif
|
||||||
|
/* enable TLS only when Picolibc is compiled with TLS enabled */
|
||||||
|
#ifdef PICOLIBC_TLS
|
||||||
|
void *tls; /**< thread local storage ptr */
|
||||||
|
#endif
|
||||||
#ifdef HAVE_THREAD_ARCH_T
|
#ifdef HAVE_THREAD_ARCH_T
|
||||||
thread_arch_t arch; /**< architecture dependent part */
|
thread_arch_t arch; /**< architecture dependent part */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -40,6 +40,10 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PICOLIBC_TLS
|
||||||
|
#include <picotls.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Needed by OpenOCD to read sched_threads */
|
/* Needed by OpenOCD to read sched_threads */
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
#define FORCE_USED_SECTION __attribute__((used)) __attribute__((section( \
|
#define FORCE_USED_SECTION __attribute__((used)) __attribute__((section( \
|
||||||
@ -148,6 +152,9 @@ int __attribute__((used)) sched_run(void)
|
|||||||
next_thread->status = STATUS_RUNNING;
|
next_thread->status = STATUS_RUNNING;
|
||||||
sched_active_pid = next_thread->pid;
|
sched_active_pid = next_thread->pid;
|
||||||
sched_active_thread = next_thread;
|
sched_active_thread = next_thread;
|
||||||
|
#ifdef PICOLIBC_TLS
|
||||||
|
_set_tls(next_thread->tls);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MODULE_MPU_STACK_GUARD
|
#ifdef MODULE_MPU_STACK_GUARD
|
||||||
mpu_configure(
|
mpu_configure(
|
||||||
|
|||||||
@ -20,6 +20,9 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#ifdef PICOLIBC_TLS
|
||||||
|
#include <picotls.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
@ -215,6 +218,13 @@ kernel_pid_t thread_create(char *stack, int stacksize, uint8_t priority,
|
|||||||
/* allocate our thread control block at the top of our stackspace */
|
/* allocate our thread control block at the top of our stackspace */
|
||||||
thread_t *thread = (thread_t *)(stack + stacksize);
|
thread_t *thread = (thread_t *)(stack + stacksize);
|
||||||
|
|
||||||
|
#ifdef PICOLIBC_TLS
|
||||||
|
stacksize -= _tls_size();
|
||||||
|
|
||||||
|
thread->tls = stack + stacksize;
|
||||||
|
_init_tls(thread->tls);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(DEVELHELP) || defined(SCHED_TEST_STACK)
|
#if defined(DEVELHELP) || defined(SCHED_TEST_STACK)
|
||||||
if (flags & THREAD_CREATE_STACKTEST) {
|
if (flags & THREAD_CREATE_STACKTEST) {
|
||||||
/* assign each int of the stack the value of it's address */
|
/* assign each int of the stack the value of it's address */
|
||||||
|
|||||||
@ -127,7 +127,7 @@ void bootloader(void)
|
|||||||
/* cpu specific setup of clocks, peripherals */
|
/* cpu specific setup of clocks, peripherals */
|
||||||
cpu_init();
|
cpu_init();
|
||||||
|
|
||||||
#ifdef MODULE_NEWLIB
|
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
|
||||||
extern void __libc_init_array(void);
|
extern void __libc_init_array(void);
|
||||||
__libc_init_array();
|
__libc_init_array();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -4,11 +4,15 @@ USEMODULE += cortexm_common
|
|||||||
# include common periph code
|
# include common periph code
|
||||||
USEMODULE += cortexm_common_periph
|
USEMODULE += cortexm_common_periph
|
||||||
|
|
||||||
# all cortex MCU's use newlib as libc
|
ifeq (1,$(PICOLIBC))
|
||||||
USEMODULE += newlib
|
# Use Picolibc when explicitly selected
|
||||||
|
USEMODULE += picolibc
|
||||||
# use the nano-specs of Newlib when available
|
else
|
||||||
USEMODULE += newlib_nano
|
# all cortex MCU's use newlib as libc
|
||||||
|
USEMODULE += newlib
|
||||||
|
# use the nano-specs of Newlib when available
|
||||||
|
USEMODULE += newlib_nano
|
||||||
|
endif
|
||||||
|
|
||||||
# Export the peripheral drivers to be linked into the final binary:
|
# Export the peripheral drivers to be linked into the final binary:
|
||||||
USEMODULE += periph
|
USEMODULE += periph
|
||||||
|
|||||||
@ -96,6 +96,42 @@ SECTIONS
|
|||||||
_efixed = .; /* End of text section */
|
_efixed = .; /* End of text section */
|
||||||
} > rom
|
} > rom
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS relocations are offsets relative to the address
|
||||||
|
* of the first TLS symbol. That means we just need to
|
||||||
|
* allocate them all together so that the TLS region
|
||||||
|
* is compact when allocated for each thread.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS initialization data is loaded into ROM so that
|
||||||
|
* each thread can get its values initialized from there
|
||||||
|
* at startup
|
||||||
|
*/
|
||||||
|
.tdata :
|
||||||
|
{
|
||||||
|
__tdata_start = .;
|
||||||
|
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||||
|
__tdata_end = .;
|
||||||
|
} > rom
|
||||||
|
__tdata_source = LOADADDR(.tdata);
|
||||||
|
__tdata_size = SIZEOF(.tdata);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS zeroed data is relocated as if it immediately followed
|
||||||
|
* the tdata values. However, the linker 'magically' erases the
|
||||||
|
* memory allocation so that no ROM is consumed by this
|
||||||
|
* section
|
||||||
|
*/
|
||||||
|
.tbss :
|
||||||
|
{
|
||||||
|
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||||
|
*(.tcommon)
|
||||||
|
__tbss_end = .;
|
||||||
|
} > rom
|
||||||
|
__tls_size = __tbss_end - __tdata_start;
|
||||||
|
__tbss_size = __tls_size - __tdata_size;
|
||||||
|
|
||||||
/* .ARM.exidx is sorted, so has to go in its own output section. */
|
/* .ARM.exidx is sorted, so has to go in its own output section. */
|
||||||
PROVIDE_HIDDEN (__exidx_start = .);
|
PROVIDE_HIDDEN (__exidx_start = .);
|
||||||
.ARM.exidx :
|
.ARM.exidx :
|
||||||
|
|||||||
@ -174,7 +174,7 @@ void reset_handler_default(void)
|
|||||||
/* initialize the board (which also initiates CPU initialization) */
|
/* initialize the board (which also initiates CPU initialization) */
|
||||||
board_init();
|
board_init();
|
||||||
|
|
||||||
#if MODULE_NEWLIB
|
#if MODULE_NEWLIB || MODULE_PICOLIBC
|
||||||
/* initialize std-c library (this must be done after board_init) */
|
/* initialize std-c library (this must be done after board_init) */
|
||||||
extern void __libc_init_array(void);
|
extern void __libc_init_array(void);
|
||||||
__libc_init_array();
|
__libc_init_array();
|
||||||
|
|||||||
@ -2,6 +2,10 @@
|
|||||||
MODULE = cpu
|
MODULE = cpu
|
||||||
|
|
||||||
# add a list of subdirectories, that should also be built
|
# add a list of subdirectories, that should also be built
|
||||||
DIRS = periph nano vendor
|
DIRS = periph vendor
|
||||||
|
|
||||||
|
ifneq (1,$(PICOLIBC))
|
||||||
|
DIRS += nano
|
||||||
|
endif
|
||||||
|
|
||||||
include $(RIOTBASE)/Makefile.base
|
include $(RIOTBASE)/Makefile.base
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
USEMODULE += newlib_nano
|
ifeq (1,$(PICOLIBC))
|
||||||
|
USEMODULE += picolibc
|
||||||
|
else
|
||||||
|
USEMODULE += newlib_nano
|
||||||
|
USEMODULE += newlib_syscalls_fe310
|
||||||
|
endif
|
||||||
|
|
||||||
USEMODULE += newlib_syscalls_fe310
|
|
||||||
USEMODULE += sifive_drivers_fe310
|
USEMODULE += sifive_drivers_fe310
|
||||||
|
|
||||||
USEMODULE += periph
|
USEMODULE += periph
|
||||||
|
|||||||
@ -24,6 +24,8 @@
|
|||||||
#include "vendor/encoding.h"
|
#include "vendor/encoding.h"
|
||||||
#include "vendor/plic_driver.h"
|
#include "vendor/plic_driver.h"
|
||||||
|
|
||||||
|
#include "stdio_uart.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configure the memory mapped flash for faster throughput
|
* Configure the memory mapped flash for faster throughput
|
||||||
* to minimize interrupt latency on an I-Cache miss and refill
|
* to minimize interrupt latency on an I-Cache miss and refill
|
||||||
@ -110,8 +112,12 @@ void cpu_init(void)
|
|||||||
/* Initialize IRQs */
|
/* Initialize IRQs */
|
||||||
irq_init();
|
irq_init();
|
||||||
|
|
||||||
|
/* Initialize stdio */
|
||||||
|
stdio_init();
|
||||||
|
#ifndef _PICOLIBC__
|
||||||
/* Initialize newlib-nano library stubs */
|
/* Initialize newlib-nano library stubs */
|
||||||
nanostubs_init();
|
nanostubs_init();
|
||||||
|
#endif /* PICOLIBC */
|
||||||
|
|
||||||
/* Initialize static peripheral */
|
/* Initialize static peripheral */
|
||||||
periph_init();
|
periph_init();
|
||||||
|
|||||||
@ -27,6 +27,7 @@ PHDRS
|
|||||||
flash PT_LOAD;
|
flash PT_LOAD;
|
||||||
ram_init PT_LOAD;
|
ram_init PT_LOAD;
|
||||||
ram PT_NULL;
|
ram PT_NULL;
|
||||||
|
tls PT_TLS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
@ -118,6 +119,42 @@ SECTIONS
|
|||||||
KEEP (*(.dtors))
|
KEEP (*(.dtors))
|
||||||
} >flash AT>flash :flash
|
} >flash AT>flash :flash
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS relocations are offsets relative to the address
|
||||||
|
* of the first TLS symbol. That means we just need to
|
||||||
|
* allocate them all together so that the TLS region
|
||||||
|
* is compact when allocated for each thread.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS initialization data is loaded into ROM so that
|
||||||
|
* each thread can get its values initialized from there
|
||||||
|
* at startup
|
||||||
|
*/
|
||||||
|
.tdata :
|
||||||
|
{
|
||||||
|
__tdata_start = .;
|
||||||
|
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||||
|
__tdata_end = .;
|
||||||
|
} >flash AT>flash :tls
|
||||||
|
__tdata_source = LOADADDR(.tdata);
|
||||||
|
__tdata_size = SIZEOF(.tdata);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS zeroed data is relocated as if it immediately followed
|
||||||
|
* the tdata values. However, the linker 'magically' erases the
|
||||||
|
* memory allocation so that no ROM is consumed by this
|
||||||
|
* section
|
||||||
|
*/
|
||||||
|
.tbss :
|
||||||
|
{
|
||||||
|
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||||
|
*(.tcommon)
|
||||||
|
__tbss_end = .;
|
||||||
|
} >flash : tls
|
||||||
|
__tls_size = __tbss_end - __tdata_start;
|
||||||
|
__tbss_size = __tls_size - __tdata_size;
|
||||||
|
|
||||||
.lalign :
|
.lalign :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
|
|||||||
@ -40,7 +40,6 @@ void nanostubs_init(void)
|
|||||||
{
|
{
|
||||||
#if defined(MODULE_STDIO_UART)
|
#if defined(MODULE_STDIO_UART)
|
||||||
/* STDIO redirected to UART, no line buffering */
|
/* STDIO redirected to UART, no line buffering */
|
||||||
stdio_init();
|
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
setvbuf(stdout, NULL, _IONBF, 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,8 +43,6 @@ _start:
|
|||||||
2:
|
2:
|
||||||
|
|
||||||
/* Call global constructors */
|
/* Call global constructors */
|
||||||
la a0, __libc_fini_array
|
|
||||||
call atexit
|
|
||||||
call __libc_init_array
|
call __libc_init_array
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -240,9 +240,9 @@ static int _cat(int argc, char **argv)
|
|||||||
printf("Usage: %s <file>\n", argv[0]);
|
printf("Usage: %s <file>\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* With newlib, low-level syscalls are plugged to RIOT vfs
|
/* With newlib or picolibc, low-level syscalls are plugged to RIOT vfs
|
||||||
* on native, open/read/write/close/... are plugged to RIOT vfs */
|
* on native, open/read/write/close/... are plugged to RIOT vfs */
|
||||||
#ifdef MODULE_NEWLIB
|
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
|
||||||
FILE *f = fopen(argv[1], "r");
|
FILE *f = fopen(argv[1], "r");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
printf("file %s does not exist\n", argv[1]);
|
printf("file %s does not exist\n", argv[1]);
|
||||||
@ -276,7 +276,7 @@ static int _tee(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE_NEWLIB
|
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
|
||||||
FILE *f = fopen(argv[1], "w+");
|
FILE *f = fopen(argv[1], "w+");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
printf("error while trying to create %s\n", argv[1]);
|
printf("error while trying to create %s\n", argv[1]);
|
||||||
|
|||||||
@ -57,6 +57,7 @@ export DOCKER_ENV_VARS += \
|
|||||||
PREFIX \
|
PREFIX \
|
||||||
QUIET \
|
QUIET \
|
||||||
WERROR \
|
WERROR \
|
||||||
|
PICOLIBC \
|
||||||
PROGRAMMER \
|
PROGRAMMER \
|
||||||
RIOT_CI_BUILD \
|
RIOT_CI_BUILD \
|
||||||
RIOT_VERSION \
|
RIOT_VERSION \
|
||||||
|
|||||||
25
makefiles/libc/picolibc.mk
Normal file
25
makefiles/libc/picolibc.mk
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
ifneq (,$(filter picolibc,$(USEMODULE)))
|
||||||
|
# Test if picolibc.specs is available
|
||||||
|
ifeq ($(shell $(LINK) -specs=picolibc.specs -E - 2>/dev/null >/dev/null </dev/null ; echo $$?),0)
|
||||||
|
USE_PICOLIBC = 1
|
||||||
|
ifeq ($(shell echo "int main(){} void _exit(int n) {(void)n;while(1);}" | LC_ALL=C $(CC) -xc - -o /dev/null -lc -specs=picolibc.specs -Wall -Wextra -pedantic 2>&1 | grep -q "use of wchar_t values across objects may fail" ; echo $$?),0)
|
||||||
|
CFLAGS += -fshort-wchar
|
||||||
|
LINKFLAGS += -Wl,--no-wchar-size-warning
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq (1,$(USE_PICOLIBC))
|
||||||
|
LINKFLAGS += -specs=picolibc.specs
|
||||||
|
# RIOT uses _sheap and _eheap for heap start and end, PicoLIBC uses
|
||||||
|
# __heap_start and __heap_end. This glues these different names together.
|
||||||
|
LINKFLAGS += -Wl,--defsym=__heap_end=_eheap
|
||||||
|
LINKFLAGS += -Wl,--defsym=__heap_start=_sheap
|
||||||
|
CFLAGS += -specs=picolibc.specs
|
||||||
|
ifeq (,$(filter printf_float scanf_float,$(USEMODULE)))
|
||||||
|
CFLAGS += -DPICOLIBC_INTEGER_PRINTF_SCANF
|
||||||
|
LINKFLAGS += -DPICOLIBC_INTEGER_PRINTF_SCANF
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
LINKFLAGS += -lc
|
||||||
@ -85,6 +85,7 @@ PSEUDOMODULES += newlib
|
|||||||
PSEUDOMODULES += newlib_gnu_source
|
PSEUDOMODULES += newlib_gnu_source
|
||||||
PSEUDOMODULES += newlib_nano
|
PSEUDOMODULES += newlib_nano
|
||||||
PSEUDOMODULES += openthread
|
PSEUDOMODULES += openthread
|
||||||
|
PSEUDOMODULES += picolibc
|
||||||
PSEUDOMODULES += pktqueue
|
PSEUDOMODULES += pktqueue
|
||||||
PSEUDOMODULES += posix_headers
|
PSEUDOMODULES += posix_headers
|
||||||
PSEUDOMODULES += printf_float
|
PSEUDOMODULES += printf_float
|
||||||
|
|||||||
@ -8,7 +8,7 @@ STDIO_MODULES = \
|
|||||||
stdio_uart \
|
stdio_uart \
|
||||||
#
|
#
|
||||||
|
|
||||||
ifneq (,$(filter newlib,$(USEMODULE)))
|
ifneq (,$(filter newlib picolibc,$(USEMODULE)))
|
||||||
ifeq (,$(filter $(STDIO_MODULES),$(USEMODULE)))
|
ifeq (,$(filter $(STDIO_MODULES),$(USEMODULE)))
|
||||||
USEMODULE += stdio_uart
|
USEMODULE += stdio_uart
|
||||||
endif
|
endif
|
||||||
|
|||||||
@ -68,10 +68,18 @@ ifneq (,$(filter newlib,$(USEMODULE)))
|
|||||||
include $(RIOTMAKE)/libc/newlib.mk
|
include $(RIOTMAKE)/libc/newlib.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter picolibc,$(USEMODULE)))
|
||||||
|
include $(RIOTMAKE)/libc/picolibc.mk
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter newlib_syscalls_default,$(USEMODULE)))
|
ifneq (,$(filter newlib_syscalls_default,$(USEMODULE)))
|
||||||
include $(RIOTBASE)/sys/newlib_syscalls_default/Makefile.include
|
include $(RIOTBASE)/sys/newlib_syscalls_default/Makefile.include
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter picolibc_syscalls_default,$(USEMODULE)))
|
||||||
|
include $(RIOTBASE)/sys/picolibc_syscalls_default/Makefile.include
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter arduino,$(USEMODULE)))
|
ifneq (,$(filter arduino,$(USEMODULE)))
|
||||||
include $(RIOTBASE)/sys/arduino/Makefile.include
|
include $(RIOTBASE)/sys/arduino/Makefile.include
|
||||||
endif
|
endif
|
||||||
|
|||||||
@ -110,7 +110,7 @@ static inline void log_write(unsigned level, const char *format, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
printf(LOG_RESET_ANSI_COLOR_CODE);
|
printf(LOG_RESET_ANSI_COLOR_CODE);
|
||||||
|
|
||||||
#ifdef MODULE_NEWLIB
|
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
|
||||||
/* no fflush on msp430 */
|
/* no fflush on msp430 */
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
1
sys/picolibc_syscalls_default/Makefile
Normal file
1
sys/picolibc_syscalls_default/Makefile
Normal file
@ -0,0 +1 @@
|
|||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
1
sys/picolibc_syscalls_default/Makefile.include
Normal file
1
sys/picolibc_syscalls_default/Makefile.include
Normal file
@ -0,0 +1 @@
|
|||||||
|
UNDEF += $(BINDIR)/picolibc_syscalls_default/syscalls.o
|
||||||
357
sys/picolibc_syscalls_default/syscalls.c
Normal file
357
sys/picolibc_syscalls_default/syscalls.c
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Koen Zandberg
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||||
|
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||||
|
* details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup sys_picolibc PicoLibc system call
|
||||||
|
* @ingroup sys
|
||||||
|
* @brief PicoLibc system call
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief PicoLibc system call implementations
|
||||||
|
*
|
||||||
|
* @author Koen Zandberg <koen@bergzand.net>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/times.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "periph/pm.h"
|
||||||
|
#include "stdio_base.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Exit a program without cleaning up files
|
||||||
|
*
|
||||||
|
* If your system doesn't provide this, it is best to avoid linking with subroutines that
|
||||||
|
* require it (exit, system).
|
||||||
|
*
|
||||||
|
* @param n the exit code, 0 for all OK, >0 for not OK
|
||||||
|
*/
|
||||||
|
void __attribute__((__noreturn__))
|
||||||
|
_exit(int n)
|
||||||
|
{
|
||||||
|
LOG_INFO("#! exit %i: powering off\n", n);
|
||||||
|
pm_off();
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send a signal to a thread
|
||||||
|
*
|
||||||
|
* @param[in] pid the pid to send to
|
||||||
|
* @param[in] sig the signal to send
|
||||||
|
*
|
||||||
|
* @return always returns -1 to signal error
|
||||||
|
*/
|
||||||
|
__attribute__ ((weak))
|
||||||
|
int kill(pid_t pid, int sig)
|
||||||
|
{
|
||||||
|
(void) pid;
|
||||||
|
(void) sig;
|
||||||
|
errno = ESRCH; /* not implemented yet */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "mutex.h"
|
||||||
|
|
||||||
|
static mutex_t picolibc_put_mutex = MUTEX_INIT;
|
||||||
|
|
||||||
|
#define PICOLIBC_STDOUT_BUFSIZE 64
|
||||||
|
|
||||||
|
static char picolibc_stdout[PICOLIBC_STDOUT_BUFSIZE];
|
||||||
|
static int picolibc_stdout_queued;
|
||||||
|
|
||||||
|
static void _picolibc_flush(void)
|
||||||
|
{
|
||||||
|
if (picolibc_stdout_queued) {
|
||||||
|
stdio_write(picolibc_stdout, picolibc_stdout_queued);
|
||||||
|
picolibc_stdout_queued = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int picolibc_put(char c, FILE *file)
|
||||||
|
{
|
||||||
|
(void)file;
|
||||||
|
mutex_lock(&picolibc_put_mutex);
|
||||||
|
picolibc_stdout[picolibc_stdout_queued++] = c;
|
||||||
|
if (picolibc_stdout_queued == PICOLIBC_STDOUT_BUFSIZE || c == '\n')
|
||||||
|
_picolibc_flush();
|
||||||
|
mutex_unlock(&picolibc_put_mutex);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int picolibc_flush(FILE *file)
|
||||||
|
{
|
||||||
|
(void)file;
|
||||||
|
mutex_lock(&picolibc_put_mutex);
|
||||||
|
_picolibc_flush();
|
||||||
|
mutex_unlock(&picolibc_put_mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int picolibc_get(FILE *file)
|
||||||
|
{
|
||||||
|
(void)file;
|
||||||
|
picolibc_flush(NULL);
|
||||||
|
char c = 0;
|
||||||
|
stdio_read(&c, 1);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE picolibc_stdio =
|
||||||
|
FDEV_SETUP_STREAM(picolibc_put, picolibc_get, picolibc_flush, _FDEV_SETUP_RW);
|
||||||
|
|
||||||
|
FILE *const __iob[] = {
|
||||||
|
&picolibc_stdio, /* stdin */
|
||||||
|
&picolibc_stdio, /* stdout */
|
||||||
|
&picolibc_stdio, /* stderr */
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <thread.h>
|
||||||
|
/**
|
||||||
|
* @brief Get the process-ID of the current thread
|
||||||
|
*
|
||||||
|
* @return the process ID of the current thread
|
||||||
|
*/
|
||||||
|
pid_t getpid(void)
|
||||||
|
{
|
||||||
|
return thread_getpid();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MODULE_VFS
|
||||||
|
#include "vfs.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Open a file
|
||||||
|
*
|
||||||
|
* This is a wrapper around @c vfs_open
|
||||||
|
*
|
||||||
|
* @param name file name to open
|
||||||
|
* @param flags flags, see man 3p open
|
||||||
|
* @param mode mode, file creation mode if the file is created when opening
|
||||||
|
*
|
||||||
|
* @return fd number (>= 0) on success
|
||||||
|
* @return -1 on error, @c errno set to a constant from errno.h to indicate the error
|
||||||
|
*/
|
||||||
|
int open(const char *name, int flags, int mode)
|
||||||
|
{
|
||||||
|
int fd = vfs_open(name, flags, mode);
|
||||||
|
if (fd < 0) {
|
||||||
|
/* vfs returns negative error codes */
|
||||||
|
errno = -fd;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read bytes from an open file
|
||||||
|
*
|
||||||
|
* This is a wrapper around @c vfs_read
|
||||||
|
*
|
||||||
|
* @param[in] fd open file descriptor obtained from @c open()
|
||||||
|
* @param[out] dest destination buffer
|
||||||
|
* @param[in] count maximum number of bytes to read
|
||||||
|
*
|
||||||
|
* @return number of bytes read on success
|
||||||
|
* @return -1 on error, @c errno set to a constant from errno.h to indicate the error
|
||||||
|
*/
|
||||||
|
_READ_WRITE_RETURN_TYPE read(int fd, void *dest, size_t count)
|
||||||
|
{
|
||||||
|
int res = vfs_read(fd, dest, count);
|
||||||
|
if (res < 0) {
|
||||||
|
/* vfs returns negative error codes */
|
||||||
|
errno = -res;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write bytes to an open file
|
||||||
|
*
|
||||||
|
* This is a wrapper around @c vfs_write
|
||||||
|
*
|
||||||
|
* @param[in] fd open file descriptor obtained from @c open()
|
||||||
|
* @param[in] src source data buffer
|
||||||
|
* @param[in] count maximum number of bytes to write
|
||||||
|
*
|
||||||
|
* @return number of bytes written on success
|
||||||
|
* @return -1 on error, @c errno set to a constant from errno.h to indicate the error
|
||||||
|
*/
|
||||||
|
_READ_WRITE_RETURN_TYPE write(int fd, const void *src, size_t count)
|
||||||
|
{
|
||||||
|
int res = vfs_write(fd, src, count);
|
||||||
|
if (res < 0) {
|
||||||
|
/* vfs returns negative error codes */
|
||||||
|
errno = -res;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Close an open file
|
||||||
|
*
|
||||||
|
* This is a wrapper around @c vfs_close
|
||||||
|
*
|
||||||
|
* If this call returns an error, the fd should still be considered invalid and
|
||||||
|
* no further attempt to use it shall be made, not even to retry @c close()
|
||||||
|
*
|
||||||
|
* @param[in] fd open file descriptor obtained from @c open()
|
||||||
|
*
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -1 on error, @c errno set to a constant from errno.h to indicate the error
|
||||||
|
*/
|
||||||
|
int close(int fd)
|
||||||
|
{
|
||||||
|
int res = vfs_close(fd);
|
||||||
|
if (res < 0) {
|
||||||
|
/* vfs returns negative error codes */
|
||||||
|
errno = -res;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current process times (not implemented).
|
||||||
|
*
|
||||||
|
* @param[out] ptms Not modified.
|
||||||
|
*
|
||||||
|
* @return -1, this function always fails. errno is set to ENOSYS.
|
||||||
|
*/
|
||||||
|
clock_t times(struct tms *ptms)
|
||||||
|
{
|
||||||
|
(void)ptms;
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Query or set options on an open file
|
||||||
|
*
|
||||||
|
* This is a wrapper around @c vfs_fcntl
|
||||||
|
*
|
||||||
|
* @param[in] fd open file descriptor obtained from @c open()
|
||||||
|
* @param[in] cmd fcntl command, see man 3p fcntl
|
||||||
|
* @param[in] arg argument to fcntl command, see man 3p fcntl
|
||||||
|
*
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -1 on error, @c errno set to a constant from errno.h to indicate the error
|
||||||
|
*/
|
||||||
|
int fcntl (int fd, int cmd, int arg)
|
||||||
|
{
|
||||||
|
int res = vfs_fcntl(fd, cmd, arg);
|
||||||
|
if (res < 0) {
|
||||||
|
/* vfs returns negative error codes */
|
||||||
|
errno = -res;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Seek to position in file
|
||||||
|
*
|
||||||
|
* This is a wrapper around @c vfs_lseek
|
||||||
|
*
|
||||||
|
* @p whence determines the function of the seek and should be set to one of
|
||||||
|
* the following values:
|
||||||
|
*
|
||||||
|
* - @c SEEK_SET: Seek to absolute offset @p off
|
||||||
|
* - @c SEEK_CUR: Seek to current location + @p off
|
||||||
|
* - @c SEEK_END: Seek to end of file + @p off
|
||||||
|
*
|
||||||
|
* @param[in] fd open file descriptor obtained from @c open()
|
||||||
|
* @param[in] off seek offset
|
||||||
|
* @param[in] whence determines the seek method, see detailed description
|
||||||
|
*
|
||||||
|
* @return the new seek location in the file on success
|
||||||
|
* @return -1 on error, @c errno set to a constant from errno.h to indicate the error
|
||||||
|
*/
|
||||||
|
off_t lseek(int fd, _off_t off, int whence)
|
||||||
|
{
|
||||||
|
int res = vfs_lseek(fd, off, whence);
|
||||||
|
if (res < 0) {
|
||||||
|
/* vfs returns negative error codes */
|
||||||
|
errno = -res;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get status of an open file
|
||||||
|
*
|
||||||
|
* This is a wrapper around @c vfs_fstat
|
||||||
|
*
|
||||||
|
* @param[in] fd open file descriptor obtained from @c open()
|
||||||
|
* @param[out] buf pointer to stat struct to fill
|
||||||
|
*
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -1 on error, @c errno set to a constant from errno.h to indicate the error
|
||||||
|
*/
|
||||||
|
int fstat(int fd, struct stat *buf)
|
||||||
|
{
|
||||||
|
int res = vfs_fstat(fd, buf);
|
||||||
|
if (res < 0) {
|
||||||
|
/* vfs returns negative error codes */
|
||||||
|
errno = -res;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Status of a file (by name)
|
||||||
|
*
|
||||||
|
* This is a wrapper around @c vfs_fstat
|
||||||
|
*
|
||||||
|
* @param[in] name path to file
|
||||||
|
* @param[out] buf pointer to stat struct to fill
|
||||||
|
*
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -1 on error, @c errno set to a constant from errno.h to indicate the error
|
||||||
|
*/
|
||||||
|
int stat(const char *name, struct stat *st)
|
||||||
|
{
|
||||||
|
int res = vfs_stat(name, st);
|
||||||
|
if (res < 0) {
|
||||||
|
/* vfs returns negative error codes */
|
||||||
|
errno = -res;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unlink (delete) a file
|
||||||
|
*
|
||||||
|
* @param[in] path path to file to be deleted
|
||||||
|
*
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -1 on error, @c errno set to a constant from errno.h to indicate the error
|
||||||
|
*/
|
||||||
|
int unlink(const char *path)
|
||||||
|
{
|
||||||
|
int res = vfs_unlink(path);
|
||||||
|
if (res < 0) {
|
||||||
|
/* vfs returns negative error codes */
|
||||||
|
errno = -res;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* MODULE_VFS */
|
||||||
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DOXYGEN
|
#ifndef DOXYGEN
|
||||||
#if defined(CPU_NATIVE) || MODULE_NEWLIB
|
#if defined(CPU_NATIVE) || MODULE_NEWLIB || MODULE_PICOLIBC
|
||||||
/* If building on native or newlib we need to use the system header instead */
|
/* If building on native or newlib we need to use the system header instead */
|
||||||
#pragma GCC system_header
|
#pragma GCC system_header
|
||||||
/* without the GCC pragma above #include_next will trigger a pedantic error */
|
/* without the GCC pragma above #include_next will trigger a pedantic error */
|
||||||
|
|||||||
@ -30,8 +30,9 @@
|
|||||||
#define SYS_SELECT_H
|
#define SYS_SELECT_H
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
/* prevent cyclic dependency with newlib's `sys/types.h` */
|
/* prevent cyclic dependency with newlib/picolibc's `sys/types.h` */
|
||||||
#if defined(MODULE_NEWLIB) && !defined(CPU_ESP32) && !defined(CPU_ESP8266)
|
#if (defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)) && \
|
||||||
|
!defined(CPU_ESP32) && !defined(CPU_ESP8266)
|
||||||
#include <sys/_timeval.h>
|
#include <sys/_timeval.h>
|
||||||
#else
|
#else
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|||||||
@ -72,7 +72,7 @@ void progress_bar_print(char *prefix, char *suffix, uint8_t value)
|
|||||||
/* show cursor */
|
/* show cursor */
|
||||||
printf("\033[?25h");
|
printf("\033[?25h");
|
||||||
|
|
||||||
#ifdef MODULE_NEWLIB
|
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,7 +82,7 @@ int _ntpdate(int argc, char **argv)
|
|||||||
puts("Error in synchronization");
|
puts("Error in synchronization");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#ifdef MODULE_NEWLIB
|
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
time_t time = (time_t)(sntp_get_unix_usec() / US_PER_SEC);
|
time_t time = (time_t)(sntp_get_unix_usec() / US_PER_SEC);
|
||||||
|
|
||||||
|
|||||||
@ -42,11 +42,11 @@
|
|||||||
#define BS '\x08' /** ASCII "Backspace" */
|
#define BS '\x08' /** ASCII "Backspace" */
|
||||||
#define DEL '\x7f' /** ASCII "Delete" */
|
#define DEL '\x7f' /** ASCII "Delete" */
|
||||||
|
|
||||||
#ifdef MODULE_NEWLIB
|
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
|
||||||
#define flush_if_needed() fflush(stdout)
|
#define flush_if_needed() fflush(stdout)
|
||||||
#else
|
#else
|
||||||
#define flush_if_needed()
|
#define flush_if_needed()
|
||||||
#endif /* MODULE_NEWLIB */
|
#endif /* MODULE_NEWLIB || MODULE_PICOLIBC */
|
||||||
|
|
||||||
#ifndef SHELL_NO_ECHO
|
#ifndef SHELL_NO_ECHO
|
||||||
#define ECHO_ON 1
|
#define ECHO_ON 1
|
||||||
|
|||||||
@ -110,7 +110,7 @@ int main(void)
|
|||||||
double false_positive_rate = (double) in / (double) lenA;
|
double false_positive_rate = (double) in / (double) lenA;
|
||||||
/* Use 'fmt/print_float' to work on all platforms (atmega)
|
/* Use 'fmt/print_float' to work on all platforms (atmega)
|
||||||
* Stdout should be flushed before to prevent garbled output. */
|
* Stdout should be flushed before to prevent garbled output. */
|
||||||
#ifdef MODULE_NEWLIB
|
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
print_float(false_positive_rate, 6);
|
print_float(false_positive_rate, 6);
|
||||||
|
|||||||
@ -325,16 +325,16 @@ static void test_fstat(void)
|
|||||||
print_test_result("test_stat__umount", vfs_umount(&_test_vfs_mount) == 0);
|
print_test_result("test_stat__umount", vfs_umount(&_test_vfs_mount) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE_NEWLIB
|
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
|
||||||
static void test_newlib(void)
|
static void test_libc(void)
|
||||||
{
|
{
|
||||||
FILE* fl;
|
FILE* fl;
|
||||||
char buf[sizeof(test_txt) + sizeof(test_txt2)];
|
char buf[sizeof(test_txt) + sizeof(test_txt2)];
|
||||||
print_test_result("test_newlib__mount", vfs_mount(&_test_vfs_mount) == 0);
|
print_test_result("test_libc__mount", vfs_mount(&_test_vfs_mount) == 0);
|
||||||
|
|
||||||
/* try to open file that doesn't exist */
|
/* try to open file that doesn't exist */
|
||||||
fl = fopen(FULL_FNAME_NXIST, "r");
|
fl = fopen(FULL_FNAME_NXIST, "r");
|
||||||
print_test_result("test_newlib__fopen", fl == NULL);
|
print_test_result("test_libc__fopen", fl == NULL);
|
||||||
if (fl) {
|
if (fl) {
|
||||||
fclose(fl);
|
fclose(fl);
|
||||||
}
|
}
|
||||||
@ -342,52 +342,52 @@ static void test_newlib(void)
|
|||||||
/* create new file write and check content */
|
/* create new file write and check content */
|
||||||
remove(FULL_FNAME2);
|
remove(FULL_FNAME2);
|
||||||
fl = fopen(FULL_FNAME2, "w+");
|
fl = fopen(FULL_FNAME2, "w+");
|
||||||
print_test_result("test_newlib__fopen_w", fl != NULL);
|
print_test_result("test_libc__fopen_w", fl != NULL);
|
||||||
if (fl) {
|
if (fl) {
|
||||||
print_test_result("test_newlib__fputs_w", fputs(test_txt, fl) >= 0);
|
print_test_result("test_libc__fputs_w", fputs(test_txt, fl) >= 0);
|
||||||
rewind(fl);
|
rewind(fl);
|
||||||
print_test_result("test_newlib__fread_w",
|
print_test_result("test_libc__fread_w",
|
||||||
fread(buf, sizeof(*buf), sizeof(buf), fl) > 0);
|
fread(buf, sizeof(*buf), sizeof(buf), fl) > 0);
|
||||||
print_test_result("test_newlib__strcmp_w", strcmp(test_txt, buf) == 0);
|
print_test_result("test_libc__strcmp_w", strcmp(test_txt, buf) == 0);
|
||||||
print_test_result("test_newlib__fclose_w", fclose(fl) == 0);
|
print_test_result("test_libc__fclose_w", fclose(fl) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cppcheck-suppress resourceLeak
|
/* cppcheck-suppress resourceLeak
|
||||||
* (reason: cppcheck <2.0 reports a false positive here) */
|
* (reason: cppcheck <2.0 reports a false positive here) */
|
||||||
fl = fopen(FULL_FNAME2, "r"); /* open file RO */
|
fl = fopen(FULL_FNAME2, "r"); /* open file RO */
|
||||||
print_test_result("test_newlib__fopen_r", fl != NULL);
|
print_test_result("test_libc__fopen_r", fl != NULL);
|
||||||
if (fl) {
|
if (fl) {
|
||||||
print_test_result("test_newlib__fclose_r", fclose(fl) == 0);
|
print_test_result("test_libc__fclose_r", fclose(fl) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove file */
|
/* remove file */
|
||||||
print_test_result("test_newlib__remove", remove(FULL_FNAME2) == 0);
|
print_test_result("test_libc__remove", remove(FULL_FNAME2) == 0);
|
||||||
|
|
||||||
/* append to non existing file */
|
/* append to non existing file */
|
||||||
fl = fopen(FULL_FNAME2, "a");
|
fl = fopen(FULL_FNAME2, "a");
|
||||||
print_test_result("test_newlib__fopen_a", fl != NULL);
|
print_test_result("test_libc__fopen_a", fl != NULL);
|
||||||
if (fl) {
|
if (fl) {
|
||||||
print_test_result("test_newlib__fputs_a", fputs(test_txt, fl) >= 0);
|
print_test_result("test_libc__fputs_a", fputs(test_txt, fl) >= 0);
|
||||||
print_test_result("test_newlib__fclose_a", fclose(fl) == 0);
|
print_test_result("test_libc__fclose_a", fclose(fl) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* append to existing file and check content */
|
/* append to existing file and check content */
|
||||||
fl = fopen(FULL_FNAME2, "a+");
|
fl = fopen(FULL_FNAME2, "a+");
|
||||||
print_test_result("test_newlib__fopen_a2", fl != NULL);
|
print_test_result("test_libc__fopen_a2", fl != NULL);
|
||||||
if (fl) {
|
if (fl) {
|
||||||
print_test_result("test_newlib__fputs_a2", fputs(test_txt2, fl) >= 0);
|
print_test_result("test_libc__fputs_a2", fputs(test_txt2, fl) >= 0);
|
||||||
rewind(fl);
|
rewind(fl);
|
||||||
print_test_result("test_newlib__fread_a2",
|
print_test_result("test_libc__fread_a2",
|
||||||
fread(buf, sizeof(*buf), sizeof(buf), fl) > 0);
|
fread(buf, sizeof(*buf), sizeof(buf), fl) > 0);
|
||||||
print_test_result("test_newlib__strcmp_a2",
|
print_test_result("test_libc__strcmp_a2",
|
||||||
strncmp(test_txt, buf, strlen(test_txt)) == 0);
|
strncmp(test_txt, buf, strlen(test_txt)) == 0);
|
||||||
print_test_result("test_newlib__strcmp_a2", strncmp(test_txt2,
|
print_test_result("test_libc__strcmp_a2", strncmp(test_txt2,
|
||||||
&buf[strlen(test_txt)], strlen(test_txt2)) == 0);
|
&buf[strlen(test_txt)], strlen(test_txt2)) == 0);
|
||||||
print_test_result("test_newlib__fclose_a2", fclose(fl) == 0);
|
print_test_result("test_libc__fclose_a2", fclose(fl) == 0);
|
||||||
}
|
}
|
||||||
print_test_result("test_newlib__remove", remove(FULL_FNAME2) == 0);
|
print_test_result("test_libc__remove", remove(FULL_FNAME2) == 0);
|
||||||
|
|
||||||
print_test_result("test_newlib__umount", vfs_umount(&_test_vfs_mount) == 0);
|
print_test_result("test_libc__umount", vfs_umount(&_test_vfs_mount) == 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -421,8 +421,8 @@ int main(void)
|
|||||||
test_mkrmdir();
|
test_mkrmdir();
|
||||||
test_create();
|
test_create();
|
||||||
test_fstat();
|
test_fstat();
|
||||||
#ifdef MODULE_NEWLIB
|
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
|
||||||
test_newlib();
|
test_libc();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
printf("Test end.\n");
|
printf("Test end.\n");
|
||||||
|
|||||||
@ -389,7 +389,7 @@ void test_entropy(uint32_t samples)
|
|||||||
/* Use 'fmt/print_float' to work on all platforms (atmega)
|
/* Use 'fmt/print_float' to work on all platforms (atmega)
|
||||||
* Stdout should be flushed before to prevent garbled output. */
|
* Stdout should be flushed before to prevent garbled output. */
|
||||||
printf("Calculated ");
|
printf("Calculated ");
|
||||||
#ifdef MODULE_NEWLIB
|
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
|
||||||
/* no fflush on msp430 */
|
/* no fflush on msp430 */
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -171,7 +171,7 @@ static void test_vfs_constfs_read_lseek(void)
|
|||||||
TEST_ASSERT_EQUAL_INT(0, res);
|
TEST_ASSERT_EQUAL_INT(0, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MODULE_NEWLIB || defined(BOARD_NATIVE)
|
#if MODULE_NEWLIB || MODULE_PICOLIBC || defined(BOARD_NATIVE)
|
||||||
static void test_vfs_constfs__posix(void)
|
static void test_vfs_constfs__posix(void)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
@ -210,7 +210,7 @@ Test *tests_vfs_mount_constfs_tests(void)
|
|||||||
new_TestFixture(test_vfs_umount__invalid_mount),
|
new_TestFixture(test_vfs_umount__invalid_mount),
|
||||||
new_TestFixture(test_vfs_constfs_open),
|
new_TestFixture(test_vfs_constfs_open),
|
||||||
new_TestFixture(test_vfs_constfs_read_lseek),
|
new_TestFixture(test_vfs_constfs_read_lseek),
|
||||||
#if MODULE_NEWLIB || defined(BOARD_NATIVE)
|
#if MODULE_NEWLIB || MODULE_PICOLIBC || defined(BOARD_NATIVE)
|
||||||
new_TestFixture(test_vfs_constfs__posix),
|
new_TestFixture(test_vfs_constfs__posix),
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user