From 1aa47857a0b51c6304976491c711d75a731f8cb8 Mon Sep 17 00:00:00 2001 From: Florian La Roche Date: Wed, 13 Aug 2025 16:45:54 +0200 Subject: [PATCH] Various Qemu Cortex M3 ports now support picolibc (#1364) * Various Qemu Cortex M3 ports now support picolibc Allow various Qemu Cortex M3 ports to compile against picolibc. Also support "-flto" to work correctly. Tested with picolibc in current Debian 13. Just use "PICOLIBC=1 make" to switch over from default newlib. Signed-off-by: Florian La Roche * Add ffreestanding Signed-off-by: Ubuntu * Fix formatting check Signed-off-by: Ubuntu --------- Signed-off-by: Florian La Roche Signed-off-by: Ubuntu Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Ubuntu --- .../FreeRTOS_Plus_TCP_Echo_Qemu_mps2/Makefile | 21 ++++++++++----- .../main_networking.c | 9 +++++-- .../mps2_m3.ld | 2 ++ .../syscalls.c | 23 ++++++++++++++++ .../build/gcc/Makefile | 19 ++++++++------ .../build/gcc/startup_gcc.c | 2 +- FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/main.c | 23 +++++++++++++++- .../Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/Makefile | 26 +++++++++---------- .../scripts/mps2_m3.ld | 3 ++- .../CORTEX_MPU_M3_MPS2_QEMU_GCC/syscall.c | 2 +- 10 files changed, 96 insertions(+), 34 deletions(-) diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/Makefile b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/Makefile index eb248d9a5..93d73435e 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/Makefile +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/Makefile @@ -51,31 +51,38 @@ SOURCE_FILES += ${FREERTOS_TCP}/source/portable/BufferManagement/BufferAllocatio SOURCE_FILES += ${FREERTOS_TCP}/source/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c SOURCE_FILES += ${FREERTOS_TCP}/source/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c -DEFINES := -DHEAP3 -CPPFLAGS += $(DEFINES) +CPPFLAGS += -DHEAP3 +ifeq ($(PICOLIBC), 1) + CFLAGS += --specs=picolibc.specs -DPICOLIBC_INTEGER_PRINTF_SCANF --oslib=semihost +endif CFLAGS += -mthumb -mcpu=cortex-m3 ifeq ($(DEBUG), 1) CFLAGS += -g3 -Og -ffunction-sections -fdata-sections else CFLAGS += -Os -ffunction-sections -fdata-sections endif -CFLAGS += -MMD +#CFLAGS += -flto CFLAGS += -Wall -Wextra -Wshadow #CFLAGS += -Wpedantic -fanalyzer -#CFLAGS += -flto +CFLAGS += -MMD CFLAGS += $(INCLUDE_DIRS) LDFLAGS = -T mps2_m3.ld LDFLAGS += -Xlinker -Map=${BUILD_DIR}/output.map LDFLAGS += -Xlinker --gc-sections -LDFLAGS += -nostartfiles -specs=nano.specs -specs=nosys.specs -specs=rdimon.specs +#LDFLAGS += -Xlinker --print-gc-sections +ifeq ($(PICOLIBC), 1) + LDFLAGS += -nostartfiles +else + LDFLAGS += -nostartfiles -specs=nano.specs -specs=nosys.specs -specs=rdimon.specs +endif OBJ_FILES := $(SOURCE_FILES:%.c=$(BUILD_DIR)/%.o) .PHONY: clean -$(BUILD_DIR)/$(BIN) : $(OBJ_FILES) +$(BUILD_DIR)/$(BIN): $(OBJ_FILES) $(CC) $(CFLAGS) $(LDFLAGS) $+ -o $(@) $(SIZE) $(@) @@ -88,7 +95,7 @@ $(BUILD_DIR)/$(BIN) : $(OBJ_FILES) INCLUDES := $(SOURCE_FILES:%.c=$(BUILD_DIR)/%.d) -include $(INCLUDES) -${BUILD_DIR}/%.o : %.c Makefile +${BUILD_DIR}/%.o: %.c Makefile -mkdir -p $(@D) $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/main_networking.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/main_networking.c index b1b560011..72cc96647 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/main_networking.c +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/main_networking.c @@ -142,7 +142,10 @@ static UBaseType_t ulNextRand; void main_tcp_echo_client_tasks( void ) { BaseType_t xReturn; - const uint32_t ulLongTime_ms = pdMS_TO_TICKS( 1000UL ); + + #ifndef __PICOLIBC__ + const uint32_t ulLongTime_ms = pdMS_TO_TICKS( 1000UL ); + #endif /* * Instructions for using this project are provided on: @@ -203,7 +206,9 @@ void main_tcp_echo_client_tasks( void ) * really applicable to the Linux simulator port). */ for( ; ; ) { - usleep( ulLongTime_ms * 1000 ); + #ifndef __PICOLIBC__ + usleep( ulLongTime_ms * 1000 ); + #endif } } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/mps2_m3.ld b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/mps2_m3.ld index 97089f3c4..eb75ce03e 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/mps2_m3.ld +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/mps2_m3.ld @@ -124,8 +124,10 @@ SECTIONS PROVIDE ( end = . ); PROVIDE ( _end = . ); _heap_bottom = .; + __heap_start = .; . = . + _Min_Heap_Size; _heap_top = .; + __heap_end = .; . = . + _Min_Stack_Size; . = ALIGN(8); } >RAM diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/syscalls.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/syscalls.c index f50ff62dc..92bbabbaf 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/syscalls.c +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/syscalls.c @@ -30,6 +30,7 @@ extern "C" { #include void uart_init( void ); +#ifndef __PICOLIBC__ __attribute__( ( used ) ) int _fstat( int file ); int _read( int file, char * buf, @@ -39,6 +40,7 @@ int _write( int file, int len ); void * _sbrk( int incr ); +#endif typedef struct UART_t { @@ -55,10 +57,12 @@ typedef struct UART_t #define UART_CTRL_TX_EN ( 1 << 0 ) +#ifndef __PICOLIBC__ extern unsigned long _heap_bottom; extern unsigned long _heap_top; static char * heap_end = ( char * ) &_heap_bottom; +#endif /** * @brief initializes the UART emulated hardware @@ -69,6 +73,24 @@ void uart_init( void ) UART0_ADDR->CTRL = UART_CTRL_TX_EN; } +#ifdef __PICOLIBC__ + +#include + +int +_uart_putc(char c, FILE *file) +{ + ( void ) file; + + UART_DR( UART0_ADDR ) = c; + return (unsigned char) c; +} + +static FILE __stdio = FDEV_SETUP_STREAM(_uart_putc, NULL, NULL, _FDEV_SETUP_WRITE); +__attribute__( ( used ) ) FILE *const stdout = &__stdio; + +#else + /** * @brief not used anywhere in the code * @todo implement if necessary @@ -138,6 +160,7 @@ void * _sbrk( int incr ) return prev_heap_end; } +#endif #ifdef __cplusplus } diff --git a/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/build/gcc/Makefile b/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/build/gcc/Makefile index 57df4e48f..b238f8ffa 100644 --- a/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/build/gcc/Makefile +++ b/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/build/gcc/Makefile @@ -9,20 +9,23 @@ LD = arm-none-eabi-gcc SIZE = arm-none-eabi-size MAKE = make -CFLAGS += -ffreestanding -mthumb -mcpu=cortex-m3 -CFLAGS += -Wall -Wextra -Wshadow -Wno-unused-value +ifeq ($(PICOLIBC), 1) + CFLAGS += --specs=picolibc.specs -DPICOLIBC_INTEGER_PRINTF_SCANF +endif +CFLAGS += -mthumb -mcpu=cortex-m3 -ffreestanding CFLAGS += -g3 -Os -ffunction-sections -fdata-sections -CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" -MT $@ -#CFLAGS += -std=c99 -#CFLAGS += -Wpedantic -fanalyzer #CFLAGS += -flto +CFLAGS += -Wall -Wextra -Wshadow -Wno-unused-value +CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" -MT $@ CFLAGS += $(INCLUDE_DIRS) LDFLAGS = -T ./mps2_m3.ld LDFLAGS += -Xlinker -Map=$(OUTPUT_DIR)/RTOSDemo.map LDFLAGS += -Xlinker --gc-sections -LDFLAGS += -nostartfiles -LDFLAGS += -specs=nano.specs -specs=nosys.specs # -specs=rdimon.specs +#LDFLAGS += -Xlinker --print-gc-sections +ifneq ($(PICOLIBC), 1) + LDFLAGS += -nostartfiles -specs=nano.specs -specs=nosys.specs # -specs=rdimon.specs +endif # # Kernel build. @@ -99,7 +102,7 @@ VPATH += $(TRACERECORDER_DIR) VPATH += $(TRACERECORDER_DIR)/kernelports/FreeRTOS VPATH += $(TRACERECORDER_DIR)/streamports/RingBuffer INCLUDE_DIRS += -I$(TRACERECORDER_CFG_DIR) -INCLUDE_DIRS += -I$(TRACERECORDER_DIR)/include +INCLUDE_DIRS += -I$(TRACERECORDER_DIR)/include INCLUDE_DIRS += -I$(TRACERECORDER_DIR)/kernelports/FreeRTOS/include INCLUDE_DIRS += -I$(TRACERECORDER_DIR)/streamports/RingBuffer/include SOURCE_FILES += (TRACERECORDER_DIR)/kernelports/FreeRTOS/trcKernelPort.c diff --git a/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/build/gcc/startup_gcc.c b/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/build/gcc/startup_gcc.c index e4894b8e6..3b1f2769b 100644 --- a/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/build/gcc/startup_gcc.c +++ b/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/build/gcc/startup_gcc.c @@ -79,7 +79,7 @@ const uint32_t* isr_vector[] __attribute__((section(".isr_vector"), used)) = void Reset_Handler( void ) { - main(); + (void) main(); } /* Variables used to store the value of registers at the time a hardfault diff --git a/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/main.c b/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/main.c index 3dbfbd48d..ae15d2f0a 100644 --- a/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/main.c +++ b/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/main.c @@ -103,7 +103,7 @@ static void prvUARTInit( void ); /*-----------------------------------------------------------*/ -void main( void ) +int main( void ) { /* See https://www.freertos.org/freertos-on-qemu-mps2-an385-model.html for * instructions. */ @@ -141,6 +141,7 @@ void main( void ) main_full(); } #endif + return 0; } /*-----------------------------------------------------------*/ @@ -313,6 +314,25 @@ static void prvUARTInit( void ) } /*-----------------------------------------------------------*/ +#ifdef __PICOLIBC__ +int +_uart_putc(char c, FILE *file) +{ + ( void ) file; + + while( ( UART0_STATE & TX_BUFFER_MASK ) != 0 ) + { + } + + UART0_DATA = c; + return (unsigned char) c; +} + +static FILE __stdio = FDEV_SETUP_STREAM(_uart_putc, NULL, NULL, _FDEV_SETUP_WRITE); +__attribute__( ( used ) ) FILE *const stdout = &__stdio; +#else +/*-----------------------------------------------------------*/ + int __write( int iFile, char * pcString, int iStringLength ) @@ -351,3 +371,4 @@ void * malloc( size_t size ) { } } +#endif diff --git a/FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/Makefile b/FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/Makefile index 82c018698..2322a1c48 100644 --- a/FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/Makefile +++ b/FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/Makefile @@ -35,29 +35,29 @@ INCLUDE_DIRS += -I$(FREERTOS_DIR)/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/C INCLUDE_DIRS += -I$(KERNEL_DIR)/include INCLUDE_DIRS += -I$(KERNEL_DIR)/portable/GCC/ARM_CM3_MPU -DEFINES := -DHEAP4 -CPPFLAGS += $(DEFINES) +CPPFLAGS += -DHEAP4 +ifeq ($(PICOLIBC), 1) + CFLAGS += --specs=picolibc.specs -DPICOLIBC_INTEGER_PRINTF_SCANF +endif CFLAGS += -mthumb -mcpu=cortex-m3 +ifeq ($(DEBUG), 1) + CFLAGS += -g3 -Og -ffunction-sections -fdata-sections -save-temps=obj +else + CFLAGS += -Os -ffunction-sections -fdata-sections +endif +#CFLAGS += -flto CFLAGS += -Wall -Wextra -Wshadow -Wno-unused-parameter -#CFLAGS += -Wpedantic -fanalyzer CFLAGS += $(INCLUDE_DIRS) LDFLAGS = -T ./scripts/mps2_m3.ld LDFLAGS += -Xlinker -Map=${BUILD_DIR}/output.map LDFLAGS += -Xlinker --gc-sections -LDFLAGS += -nostartfiles -nostdlib -nolibc -nodefaultlibs +#LDFLAGS += -Xlinker --print-gc-sections +#LDFLAGS += -nostartfiles -nostdlib -nolibc -nodefaultlibs +LDFLAGS += -nostdlib -ifeq ($(DEBUG), 1) - CFLAGS += -g3 -Og -ffunction-sections -fdata-sections -save-temps=obj -else - CFLAGS += -Os -ffunction-sections -fdata-sections -endif -ifeq ($(PICOLIBC), 1) - CFLAGS += --specs=picolibc.specs -DPICOLIBC_INTEGER_PRINTF_SCANF - LDFLAGS += --specs=picolibc.specs -DPICOLIBC_INTEGER_PRINTF_SCANF -endif OBJ_FILES := $(SOURCE_FILES:%.c=$(BUILD_DIR)/%.o) diff --git a/FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/scripts/mps2_m3.ld b/FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/scripts/mps2_m3.ld index 6d92fd34c..0d7477b55 100644 --- a/FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/scripts/mps2_m3.ld +++ b/FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/scripts/mps2_m3.ld @@ -66,7 +66,8 @@ SECTIONS *(privileged_functions) . = ALIGN(4); FILL(0xDEAD); - /* Ensure that un-privileged code is placed after the region reserved 4 * for privileged kernel code. */ + /* Ensure that un-privileged code is placed after the region reserved + * for privileged kernel code. */ /* Note that dot (.) actually refers to the byte offset from the start * of the current section (.privileged_functions in this case). As a * result, setting dot (.) to a value sets the size of the section. */ diff --git a/FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/syscall.c b/FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/syscall.c index 7ed16af05..9dde591db 100644 --- a/FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/syscall.c +++ b/FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC/syscall.c @@ -76,7 +76,7 @@ _uart_putc(char c, FILE *file) static FILE __stdio = FDEV_SETUP_STREAM(_uart_putc, NULL, NULL, _FDEV_SETUP_WRITE); -FILE *const stdout = &__stdio; +__attribute__( ( used ) ) FILE *const stdout = &__stdio; #else