1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #14827 from keith-packard/pr/libc/picolibc

Pr/libc/picolibc
This commit is contained in:
benpicco 2020-08-24 18:06:56 +02:00 committed by GitHub
commit f3e1032f6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 566 additions and 54 deletions

View File

@ -479,6 +479,14 @@ ifneq (,$(filter posix_select,$(USEMODULE)))
USEMODULE += xtimer
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)))
USEMODULE += bitfield
USEMODULE += random

View File

@ -176,6 +176,10 @@ struct _thread {
const char *name; /**< thread's name */
int stack_size; /**< thread's stack size */
#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
thread_arch_t arch; /**< architecture dependent part */
#endif

View File

@ -40,6 +40,10 @@
#include <inttypes.h>
#endif
#ifdef PICOLIBC_TLS
#include <picotls.h>
#endif
/* Needed by OpenOCD to read sched_threads */
#if defined(__APPLE__) && defined(__MACH__)
#define FORCE_USED_SECTION __attribute__((used)) __attribute__((section( \
@ -148,6 +152,9 @@ int __attribute__((used)) sched_run(void)
next_thread->status = STATUS_RUNNING;
sched_active_pid = next_thread->pid;
sched_active_thread = next_thread;
#ifdef PICOLIBC_TLS
_set_tls(next_thread->tls);
#endif
#ifdef MODULE_MPU_STACK_GUARD
mpu_configure(

View File

@ -20,6 +20,9 @@
#include <errno.h>
#include <stdio.h>
#ifdef PICOLIBC_TLS
#include <picotls.h>
#endif
#include "assert.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 */
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 (flags & THREAD_CREATE_STACKTEST) {
/* assign each int of the stack the value of it's address */

View File

@ -127,7 +127,7 @@ void bootloader(void)
/* cpu specific setup of clocks, peripherals */
cpu_init();
#ifdef MODULE_NEWLIB
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
extern void __libc_init_array(void);
__libc_init_array();
#endif

View File

@ -4,11 +4,15 @@ USEMODULE += cortexm_common
# include common periph code
USEMODULE += cortexm_common_periph
# all cortex MCU's use newlib as libc
USEMODULE += newlib
# use the nano-specs of Newlib when available
USEMODULE += newlib_nano
ifeq (1,$(PICOLIBC))
# Use Picolibc when explicitly selected
USEMODULE += picolibc
else
# 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:
USEMODULE += periph

View File

@ -96,6 +96,42 @@ SECTIONS
_efixed = .; /* End of text section */
} > 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. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :

View File

@ -174,7 +174,7 @@ void reset_handler_default(void)
/* initialize the board (which also initiates CPU initialization) */
board_init();
#if MODULE_NEWLIB
#if MODULE_NEWLIB || MODULE_PICOLIBC
/* initialize std-c library (this must be done after board_init) */
extern void __libc_init_array(void);
__libc_init_array();

View File

@ -2,6 +2,10 @@
MODULE = cpu
# 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

View File

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

View File

@ -24,6 +24,8 @@
#include "vendor/encoding.h"
#include "vendor/plic_driver.h"
#include "stdio_uart.h"
/*
* Configure the memory mapped flash for faster throughput
* to minimize interrupt latency on an I-Cache miss and refill
@ -110,8 +112,12 @@ void cpu_init(void)
/* Initialize IRQs */
irq_init();
/* Initialize stdio */
stdio_init();
#ifndef _PICOLIBC__
/* Initialize newlib-nano library stubs */
nanostubs_init();
#endif /* PICOLIBC */
/* Initialize static peripheral */
periph_init();

View File

@ -27,6 +27,7 @@ PHDRS
flash PT_LOAD;
ram_init PT_LOAD;
ram PT_NULL;
tls PT_TLS;
}
SECTIONS
@ -118,6 +119,42 @@ SECTIONS
KEEP (*(.dtors))
} >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 :
{
. = ALIGN(4);

View File

@ -40,7 +40,6 @@ void nanostubs_init(void)
{
#if defined(MODULE_STDIO_UART)
/* STDIO redirected to UART, no line buffering */
stdio_init();
setvbuf(stdout, NULL, _IONBF, 0);
#endif
}

View File

@ -43,8 +43,6 @@ _start:
2:
/* Call global constructors */
la a0, __libc_fini_array
call atexit
call __libc_init_array

View File

@ -240,9 +240,9 @@ static int _cat(int argc, char **argv)
printf("Usage: %s <file>\n", argv[0]);
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 */
#ifdef MODULE_NEWLIB
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
FILE *f = fopen(argv[1], "r");
if (f == NULL) {
printf("file %s does not exist\n", argv[1]);
@ -276,7 +276,7 @@ static int _tee(int argc, char **argv)
return 1;
}
#ifdef MODULE_NEWLIB
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
FILE *f = fopen(argv[1], "w+");
if (f == NULL) {
printf("error while trying to create %s\n", argv[1]);

View File

@ -57,6 +57,7 @@ export DOCKER_ENV_VARS += \
PREFIX \
QUIET \
WERROR \
PICOLIBC \
PROGRAMMER \
RIOT_CI_BUILD \
RIOT_VERSION \

View 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

View File

@ -85,6 +85,7 @@ PSEUDOMODULES += newlib
PSEUDOMODULES += newlib_gnu_source
PSEUDOMODULES += newlib_nano
PSEUDOMODULES += openthread
PSEUDOMODULES += picolibc
PSEUDOMODULES += pktqueue
PSEUDOMODULES += posix_headers
PSEUDOMODULES += printf_float

View File

@ -8,7 +8,7 @@ STDIO_MODULES = \
stdio_uart \
#
ifneq (,$(filter newlib,$(USEMODULE)))
ifneq (,$(filter newlib picolibc,$(USEMODULE)))
ifeq (,$(filter $(STDIO_MODULES),$(USEMODULE)))
USEMODULE += stdio_uart
endif

View File

@ -68,10 +68,18 @@ ifneq (,$(filter newlib,$(USEMODULE)))
include $(RIOTMAKE)/libc/newlib.mk
endif
ifneq (,$(filter picolibc,$(USEMODULE)))
include $(RIOTMAKE)/libc/picolibc.mk
endif
ifneq (,$(filter newlib_syscalls_default,$(USEMODULE)))
include $(RIOTBASE)/sys/newlib_syscalls_default/Makefile.include
endif
ifneq (,$(filter picolibc_syscalls_default,$(USEMODULE)))
include $(RIOTBASE)/sys/picolibc_syscalls_default/Makefile.include
endif
ifneq (,$(filter arduino,$(USEMODULE)))
include $(RIOTBASE)/sys/arduino/Makefile.include
endif

View File

@ -110,7 +110,7 @@ static inline void log_write(unsigned level, const char *format, ...)
va_end(args);
printf(LOG_RESET_ANSI_COLOR_CODE);
#ifdef MODULE_NEWLIB
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
/* no fflush on msp430 */
fflush(stdout);
#endif

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1 @@
UNDEF += $(BINDIR)/picolibc_syscalls_default/syscalls.o

View 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 */

View File

@ -16,7 +16,7 @@
*/
#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 */
#pragma GCC system_header
/* without the GCC pragma above #include_next will trigger a pedantic error */

View File

@ -30,8 +30,9 @@
#define SYS_SELECT_H
#include <string.h>
/* prevent cyclic dependency with newlib's `sys/types.h` */
#if defined(MODULE_NEWLIB) && !defined(CPU_ESP32) && !defined(CPU_ESP8266)
/* prevent cyclic dependency with newlib/picolibc's `sys/types.h` */
#if (defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)) && \
!defined(CPU_ESP32) && !defined(CPU_ESP8266)
#include <sys/_timeval.h>
#else
#include <sys/time.h>

View File

@ -72,7 +72,7 @@ void progress_bar_print(char *prefix, char *suffix, uint8_t value)
/* show cursor */
printf("\033[?25h");
#ifdef MODULE_NEWLIB
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
fflush(stdout);
#endif
}

View File

@ -82,7 +82,7 @@ int _ntpdate(int argc, char **argv)
puts("Error in synchronization");
return 1;
}
#ifdef MODULE_NEWLIB
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
struct tm *tm;
time_t time = (time_t)(sntp_get_unix_usec() / US_PER_SEC);

View File

@ -42,11 +42,11 @@
#define BS '\x08' /** ASCII "Backspace" */
#define DEL '\x7f' /** ASCII "Delete" */
#ifdef MODULE_NEWLIB
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
#define flush_if_needed() fflush(stdout)
#else
#define flush_if_needed()
#endif /* MODULE_NEWLIB */
#endif /* MODULE_NEWLIB || MODULE_PICOLIBC */
#ifndef SHELL_NO_ECHO
#define ECHO_ON 1

View File

@ -110,7 +110,7 @@ int main(void)
double false_positive_rate = (double) in / (double) lenA;
/* Use 'fmt/print_float' to work on all platforms (atmega)
* Stdout should be flushed before to prevent garbled output. */
#ifdef MODULE_NEWLIB
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
fflush(stdout);
#endif
print_float(false_positive_rate, 6);

View File

@ -325,16 +325,16 @@ static void test_fstat(void)
print_test_result("test_stat__umount", vfs_umount(&_test_vfs_mount) == 0);
}
#ifdef MODULE_NEWLIB
static void test_newlib(void)
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
static void test_libc(void)
{
FILE* fl;
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 */
fl = fopen(FULL_FNAME_NXIST, "r");
print_test_result("test_newlib__fopen", fl == NULL);
print_test_result("test_libc__fopen", fl == NULL);
if (fl) {
fclose(fl);
}
@ -342,52 +342,52 @@ static void test_newlib(void)
/* create new file write and check content */
remove(FULL_FNAME2);
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) {
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);
print_test_result("test_newlib__fread_w",
print_test_result("test_libc__fread_w",
fread(buf, sizeof(*buf), sizeof(buf), fl) > 0);
print_test_result("test_newlib__strcmp_w", strcmp(test_txt, buf) == 0);
print_test_result("test_newlib__fclose_w", fclose(fl) == 0);
print_test_result("test_libc__strcmp_w", strcmp(test_txt, buf) == 0);
print_test_result("test_libc__fclose_w", fclose(fl) == 0);
}
/* cppcheck-suppress resourceLeak
* (reason: cppcheck <2.0 reports a false positive here) */
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) {
print_test_result("test_newlib__fclose_r", fclose(fl) == 0);
print_test_result("test_libc__fclose_r", fclose(fl) == 0);
}
/* 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 */
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) {
print_test_result("test_newlib__fputs_a", fputs(test_txt, fl) >= 0);
print_test_result("test_newlib__fclose_a", fclose(fl) == 0);
print_test_result("test_libc__fputs_a", fputs(test_txt, fl) >= 0);
print_test_result("test_libc__fclose_a", fclose(fl) == 0);
}
/* append to existing file and check content */
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) {
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);
print_test_result("test_newlib__fread_a2",
print_test_result("test_libc__fread_a2",
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);
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);
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
@ -421,8 +421,8 @@ int main(void)
test_mkrmdir();
test_create();
test_fstat();
#ifdef MODULE_NEWLIB
test_newlib();
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
test_libc();
#endif
printf("Test end.\n");

View File

@ -389,7 +389,7 @@ void test_entropy(uint32_t samples)
/* Use 'fmt/print_float' to work on all platforms (atmega)
* Stdout should be flushed before to prevent garbled output. */
printf("Calculated ");
#ifdef MODULE_NEWLIB
#if defined(MODULE_NEWLIB) || defined(MODULE_PICOLIBC)
/* no fflush on msp430 */
fflush(stdout);
#endif

View File

@ -171,7 +171,7 @@ static void test_vfs_constfs_read_lseek(void)
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)
{
int res;
@ -210,7 +210,7 @@ Test *tests_vfs_mount_constfs_tests(void)
new_TestFixture(test_vfs_umount__invalid_mount),
new_TestFixture(test_vfs_constfs_open),
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),
#endif
};