From e02804355d9d79e2c5ecc9b2da1326f3f4449314 Mon Sep 17 00:00:00 2001 From: Terraneo Federico <fede.tft@miosix.org> Date: Tue, 14 Jan 2025 00:40:30 +0100 Subject: [PATCH] Sharing common code between armv6m and armv7m to support processes --- .../armv6m/interfaces-impl/userspace_impl.h | 155 +--------------- .../armv7m/interfaces-impl/userspace_impl.h | 167 +----------------- .../cortexMx_userspace.cpp} | 0 miosix/arch/cpu/common/cortexMx_userspace.h | 166 +++++++++++++++++ miosix/config/Makefile.inc | 23 +-- 5 files changed, 180 insertions(+), 331 deletions(-) rename miosix/arch/cpu/{armv7m/interfaces-impl/userspace.cpp => common/cortexMx_userspace.cpp} (100%) create mode 100644 miosix/arch/cpu/common/cortexMx_userspace.h diff --git a/miosix/arch/cpu/armv6m/interfaces-impl/userspace_impl.h b/miosix/arch/cpu/armv6m/interfaces-impl/userspace_impl.h index b0fcfcd8..909798a7 100644 --- a/miosix/arch/cpu/armv6m/interfaces-impl/userspace_impl.h +++ b/miosix/arch/cpu/armv6m/interfaces-impl/userspace_impl.h @@ -1,154 +1 @@ -/*************************************************************************** - * Copyright (C) 2018-2024 by Terraneo Federico * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * As a special exception, if other files instantiate templates or use * - * macros or inline functions from this file, or you compile this file * - * and link it with other works to produce a work based on this file, * - * this file does not by itself cause the resulting work to be covered * - * by the GNU General Public License. However the source code for this * - * file must still be made available in accordance with the GNU General * - * Public License. This exception does not invalidate any other reasons * - * why a work based on this file might be covered by the GNU General * - * Public License. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see <http://www.gnu.org/licenses/> * - ***************************************************************************/ - -#pragma once - -#include "config/miosix_settings.h" -#include "interfaces/arch_registers.h" -#include <cassert> - -namespace miosix { - -#ifdef WITH_PROCESSES - -inline void portableSwitchToUserspace() -{ - asm volatile("movs r3, #1\n\t" - "svc 0" - :::"r3"); -} - -namespace { -/* - * ARM syscall parameter mapping - * Syscall id is r3, saved at registers[3] - * - * Parameter 1 is r0, saved at registers[0] - * Parameter 2 is r1, saved at registers[1] - * Parameter 3 is r2, saved at registers[2] - * Parameter 4 is r12, saved at registers[4] - */ -constexpr unsigned int armSyscallMapping[]={0,1,2,4}; -} - -// -// class SyscallParameters -// - -inline SyscallParameters::SyscallParameters(unsigned int *context) : - registers(reinterpret_cast<unsigned int*>(context[0])) {} - -inline int SyscallParameters::getSyscallId() const -{ - return registers[3]; -} - -inline unsigned int SyscallParameters::getParameter(unsigned int index) const -{ - assert(index<4); - return registers[armSyscallMapping[index]]; -} - -inline void SyscallParameters::setParameter(unsigned int index, unsigned int value) -{ - assert(index<4); - registers[armSyscallMapping[index]]=value; -} - -namespace fault { -/** - * \internal - * Possible kind of faults that the ARM Cortex CPUs can report. - * They are used to print debug information if a process causes a fault. - * This is a regular enum enclosed in a namespace instead of an enum class - * as due to the need to loosely couple fault types for different architectures - * the arch-independent code uses int to store generic fault types. - */ -enum FaultType -{ - NONE=0, //Not a fault - STACKOVERFLOW=1, //Stack overflow - MP=2, //Process attempted data access outside its memory - MP_NOADDR=3, //Process attempted data access outside its memory (missing addr) - MP_XN=4, //Process attempted code access outside its memory - UF_DIVZERO=5, //Process attempted to divide by zero - UF_UNALIGNED=6, //Process attempted unaligned memory access - UF_COPROC=7, //Process attempted a coprocessor access - UF_EXCRET=8, //Process attempted an exception return - UF_EPSR=9, //Process attempted to access the EPSR - UF_UNDEF=10, //Process attempted to execute an invalid instruction - UF_UNEXP=11, //Unexpected usage fault - HARDFAULT=12, //Hardfault (for example process executed a BKPT instruction) - BF=13, //Busfault - BF_NOADDR=14, //Busfault (missing addr) -}; - -} //namespace fault - -// -// class MPUConfiguration -// - -inline void MPUConfiguration::IRQenable() -{ - #if __MPU_PRESENT==1 - MPU->RBAR=regValues[0]; - MPU->RASR=regValues[1]; - MPU->RBAR=regValues[2]; - MPU->RASR=regValues[3]; - __set_CONTROL(3); - #endif //__MPU_PRESENT==1 -} - -inline void MPUConfiguration::IRQdisable() -{ - #if __MPU_PRESENT==1 - __set_CONTROL(2); - #endif //__MPU_PRESENT==1 -} - -#endif //WITH_PROCESSES - -inline void IRQenableMPUatBoot() -{ - #if __MPU_PRESENT==1 - MPU->CTRL=MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk; - #endif //__MPU_PRESENT==1 -} - -/** - * \internal - * Convert a memory region size to a bit pattern that can be written in the MPU - * registers. - * On some architectures the MPU is also used to set cacheability regions in the - * address space, thus this function is useful also when processes are disabled - * \param size in bytes >32 - * \return a value that can be written to MPU->RASR to represent that size - */ -unsigned int sizeToMpu(unsigned int size); - -} //namespace miosix +#include "../../common/cortexMx_userspace.h" diff --git a/miosix/arch/cpu/armv7m/interfaces-impl/userspace_impl.h b/miosix/arch/cpu/armv7m/interfaces-impl/userspace_impl.h index 3f79c961..909798a7 100644 --- a/miosix/arch/cpu/armv7m/interfaces-impl/userspace_impl.h +++ b/miosix/arch/cpu/armv7m/interfaces-impl/userspace_impl.h @@ -1,166 +1 @@ -/*************************************************************************** - * Copyright (C) 2018-2024 by Terraneo Federico * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * As a special exception, if other files instantiate templates or use * - * macros or inline functions from this file, or you compile this file * - * and link it with other works to produce a work based on this file, * - * this file does not by itself cause the resulting work to be covered * - * by the GNU General Public License. However the source code for this * - * file must still be made available in accordance with the GNU General * - * Public License. This exception does not invalidate any other reasons * - * why a work based on this file might be covered by the GNU General * - * Public License. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see <http://www.gnu.org/licenses/> * - ***************************************************************************/ - -#pragma once - -#include "config/miosix_settings.h" -#include "interfaces/arch_registers.h" -#include "interfaces/cpu_const.h" -#include <cassert> - -namespace miosix { - -#ifdef WITH_PROCESSES - -inline void portableSwitchToUserspace() -{ - asm volatile("movs r3, #1\n\t" - "svc 0" - :::"r3"); -} - -namespace { -/* - * ARM syscall parameter mapping - * Syscall id is r3, saved at registers[3] - * - * Parameter 1 is r0, saved at registers[0] - * Parameter 2 is r1, saved at registers[1] - * Parameter 3 is r2, saved at registers[2] - * Parameter 4 is r12, saved at registers[4] - */ -constexpr unsigned int armSyscallMapping[]={0,1,2,4}; -} - -// -// class SyscallParameters -// - -inline SyscallParameters::SyscallParameters(unsigned int *context) : - registers(reinterpret_cast<unsigned int*>(context[STACK_OFFSET_IN_CTXSAVE])) {} - -inline int SyscallParameters::getSyscallId() const -{ - return registers[3]; -} - -inline unsigned int SyscallParameters::getParameter(unsigned int index) const -{ - assert(index<4); - return registers[armSyscallMapping[index]]; -} - -inline void SyscallParameters::setParameter(unsigned int index, unsigned int value) -{ - assert(index<4); - registers[armSyscallMapping[index]]=value; -} - -namespace fault { -/** - * \internal - * Possible kind of faults that the ARM Cortex CPUs can report. - * They are used to print debug information if a process causes a fault. - * This is a regular enum enclosed in a namespace instead of an enum class - * as due to the need to loosely couple fault types for different architectures - * the arch-independent code uses int to store generic fault types. - */ -enum FaultType -{ - NONE=0, //Not a fault - STACKOVERFLOW=1, //Stack overflow - MP=2, //Process attempted data access outside its memory - MP_NOADDR=3, //Process attempted data access outside its memory (missing addr) - MP_XN=4, //Process attempted code access outside its memory - MP_STACK=5, //Process had invalid SP while entering IRQ - UF_DIVZERO=6, //Process attempted to divide by zero - UF_UNALIGNED=7, //Process attempted unaligned memory access - UF_COPROC=8, //Process attempted a coprocessor access - UF_EXCRET=9, //Process attempted an exception return - UF_EPSR=10, //Process attempted to access the EPSR - UF_UNDEF=11, //Process attempted to execute an invalid instruction - UF_UNEXP=12, //Unexpected usage fault - HARDFAULT=13, //Hardfault (for example process executed a BKPT instruction) - BF=14, //Busfault - BF_NOADDR=15 //Busfault (missing addr) -}; - -} //namespace fault - -// -// class MPUConfiguration -// - -inline void MPUConfiguration::IRQenable() -{ - #if __MPU_PRESENT==1 - MPU->RBAR=regValues[0]; - MPU->RASR=regValues[1]; - MPU->RBAR=regValues[2]; - MPU->RASR=regValues[3]; - // Set bit 0 of CONTROL register to switch thread mode to unprivileged. When - // we'll return from the interrupt the MPU will check the access permissions - // for unprivileged processes which only allow access to regions 6 and 7 - __set_CONTROL(3); - #endif //__MPU_PRESENT==1 -} - -inline void MPUConfiguration::IRQdisable() -{ - #if __MPU_PRESENT==1 - // Clear bit 0 of CONTROL register to switch thread mode to privileged. When - // we'll return from the interrupt the MPU will check the access permissions - // for privileged processes which includes the default memory map as we set - // MPU_CTRL_PRIVDEFENA at boot plus additional regions to set constraints - // such as cacheability. Thus we never truly disable the MPU. - __set_CONTROL(2); - #endif //__MPU_PRESENT==1 -} - -#endif //WITH_PROCESSES - -inline void IRQenableMPUatBoot() -{ - #if __MPU_PRESENT==1 - MPU->CTRL = MPU_CTRL_HFNMIENA_Msk - | MPU_CTRL_PRIVDEFENA_Msk - | MPU_CTRL_ENABLE_Msk; - #endif //__MPU_PRESENT==1 -} - -/** - * \internal - * Convert a memory region size to a bit pattern that can be written in the MPU - * registers. - * On some architectures the MPU is also used to set cacheability regions in the - * address space, thus this function is useful also when processes are disabled - * \param size in bytes >32 - * \return a value that can be written to MPU->RASR to represent that size - */ -unsigned int sizeToMpu(unsigned int size); - -} //namespace miosix +#include "../../common/cortexMx_userspace.h" diff --git a/miosix/arch/cpu/armv7m/interfaces-impl/userspace.cpp b/miosix/arch/cpu/common/cortexMx_userspace.cpp similarity index 100% rename from miosix/arch/cpu/armv7m/interfaces-impl/userspace.cpp rename to miosix/arch/cpu/common/cortexMx_userspace.cpp diff --git a/miosix/arch/cpu/common/cortexMx_userspace.h b/miosix/arch/cpu/common/cortexMx_userspace.h new file mode 100644 index 00000000..3f79c961 --- /dev/null +++ b/miosix/arch/cpu/common/cortexMx_userspace.h @@ -0,0 +1,166 @@ +/*************************************************************************** + * Copyright (C) 2018-2024 by Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * As a special exception, if other files instantiate templates or use * + * macros or inline functions from this file, or you compile this file * + * and link it with other works to produce a work based on this file, * + * this file does not by itself cause the resulting work to be covered * + * by the GNU General Public License. However the source code for this * + * file must still be made available in accordance with the GNU General * + * Public License. This exception does not invalidate any other reasons * + * why a work based on this file might be covered by the GNU General * + * Public License. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#pragma once + +#include "config/miosix_settings.h" +#include "interfaces/arch_registers.h" +#include "interfaces/cpu_const.h" +#include <cassert> + +namespace miosix { + +#ifdef WITH_PROCESSES + +inline void portableSwitchToUserspace() +{ + asm volatile("movs r3, #1\n\t" + "svc 0" + :::"r3"); +} + +namespace { +/* + * ARM syscall parameter mapping + * Syscall id is r3, saved at registers[3] + * + * Parameter 1 is r0, saved at registers[0] + * Parameter 2 is r1, saved at registers[1] + * Parameter 3 is r2, saved at registers[2] + * Parameter 4 is r12, saved at registers[4] + */ +constexpr unsigned int armSyscallMapping[]={0,1,2,4}; +} + +// +// class SyscallParameters +// + +inline SyscallParameters::SyscallParameters(unsigned int *context) : + registers(reinterpret_cast<unsigned int*>(context[STACK_OFFSET_IN_CTXSAVE])) {} + +inline int SyscallParameters::getSyscallId() const +{ + return registers[3]; +} + +inline unsigned int SyscallParameters::getParameter(unsigned int index) const +{ + assert(index<4); + return registers[armSyscallMapping[index]]; +} + +inline void SyscallParameters::setParameter(unsigned int index, unsigned int value) +{ + assert(index<4); + registers[armSyscallMapping[index]]=value; +} + +namespace fault { +/** + * \internal + * Possible kind of faults that the ARM Cortex CPUs can report. + * They are used to print debug information if a process causes a fault. + * This is a regular enum enclosed in a namespace instead of an enum class + * as due to the need to loosely couple fault types for different architectures + * the arch-independent code uses int to store generic fault types. + */ +enum FaultType +{ + NONE=0, //Not a fault + STACKOVERFLOW=1, //Stack overflow + MP=2, //Process attempted data access outside its memory + MP_NOADDR=3, //Process attempted data access outside its memory (missing addr) + MP_XN=4, //Process attempted code access outside its memory + MP_STACK=5, //Process had invalid SP while entering IRQ + UF_DIVZERO=6, //Process attempted to divide by zero + UF_UNALIGNED=7, //Process attempted unaligned memory access + UF_COPROC=8, //Process attempted a coprocessor access + UF_EXCRET=9, //Process attempted an exception return + UF_EPSR=10, //Process attempted to access the EPSR + UF_UNDEF=11, //Process attempted to execute an invalid instruction + UF_UNEXP=12, //Unexpected usage fault + HARDFAULT=13, //Hardfault (for example process executed a BKPT instruction) + BF=14, //Busfault + BF_NOADDR=15 //Busfault (missing addr) +}; + +} //namespace fault + +// +// class MPUConfiguration +// + +inline void MPUConfiguration::IRQenable() +{ + #if __MPU_PRESENT==1 + MPU->RBAR=regValues[0]; + MPU->RASR=regValues[1]; + MPU->RBAR=regValues[2]; + MPU->RASR=regValues[3]; + // Set bit 0 of CONTROL register to switch thread mode to unprivileged. When + // we'll return from the interrupt the MPU will check the access permissions + // for unprivileged processes which only allow access to regions 6 and 7 + __set_CONTROL(3); + #endif //__MPU_PRESENT==1 +} + +inline void MPUConfiguration::IRQdisable() +{ + #if __MPU_PRESENT==1 + // Clear bit 0 of CONTROL register to switch thread mode to privileged. When + // we'll return from the interrupt the MPU will check the access permissions + // for privileged processes which includes the default memory map as we set + // MPU_CTRL_PRIVDEFENA at boot plus additional regions to set constraints + // such as cacheability. Thus we never truly disable the MPU. + __set_CONTROL(2); + #endif //__MPU_PRESENT==1 +} + +#endif //WITH_PROCESSES + +inline void IRQenableMPUatBoot() +{ + #if __MPU_PRESENT==1 + MPU->CTRL = MPU_CTRL_HFNMIENA_Msk + | MPU_CTRL_PRIVDEFENA_Msk + | MPU_CTRL_ENABLE_Msk; + #endif //__MPU_PRESENT==1 +} + +/** + * \internal + * Convert a memory region size to a bit pattern that can be written in the MPU + * registers. + * On some architectures the MPU is also used to set cacheability regions in the + * address space, thus this function is useful also when processes are disabled + * \param size in bytes >32 + * \return a value that can be written to MPU->RASR to represent that size + */ +unsigned int sizeToMpu(unsigned int size); + +} //namespace miosix diff --git a/miosix/config/Makefile.inc b/miosix/config/Makefile.inc index c10843b4..b90c1742 100644 --- a/miosix/config/Makefile.inc +++ b/miosix/config/Makefile.inc @@ -1521,7 +1521,7 @@ else ifeq ($(ARCH),cortexM3_stm32f1) ARCH_SRC += \ arch/cpu/armv7m/interfaces-impl/cpu.cpp \ arch/cpu/common/cortexMx_interrupts.cpp \ - arch/cpu/armv7m/interfaces-impl/userspace.cpp \ + arch/cpu/common/cortexMx_userspace.cpp \ arch/common/os_timer/stm32_16bit_os_timer.cpp \ arch/common/os_timer/stm32_rtc_os_timer.cpp \ arch/common/sleep/cortexMx_sleep.cpp \ @@ -1990,7 +1990,7 @@ else ifeq ($(ARCH),cortexM4_stm32f4) ARCH_SRC += \ arch/cpu/armv7m/interfaces-impl/cpu.cpp \ arch/cpu/common/cortexMx_interrupts.cpp \ - arch/cpu/armv7m/interfaces-impl/userspace.cpp \ + arch/cpu/common/cortexMx_userspace.cpp \ arch/common/os_timer/stm32_32bit_os_timer.cpp \ arch/common/sleep/cortexMx_sleep.cpp \ arch/common/drivers/stm32_gpio.cpp \ @@ -2276,7 +2276,7 @@ else ifeq ($(ARCH),cortexM3_stm32f2) ARCH_SRC += \ arch/cpu/armv7m/interfaces-impl/cpu.cpp \ arch/cpu/common/cortexMx_interrupts.cpp \ - arch/cpu/armv7m/interfaces-impl/userspace.cpp \ + arch/cpu/common/cortexMx_userspace.cpp \ arch/common/os_timer/stm32_32bit_os_timer.cpp \ arch/common/sleep/cortexMx_sleep.cpp \ arch/common/drivers/stm32_gpio.cpp \ @@ -2378,7 +2378,7 @@ else ifeq ($(ARCH),cortexM3_stm32l1) ARCH_SRC += \ arch/cpu/armv7m/interfaces-impl/cpu.cpp \ arch/cpu/common/cortexMx_interrupts.cpp \ - arch/cpu/armv7m/interfaces-impl/userspace.cpp \ + arch/cpu/common/cortexMx_userspace.cpp \ arch/common/os_timer/stm32_16bit_os_timer.cpp \ arch/common/sleep/cortexMx_sleep.cpp \ arch/common/drivers/stm32_gpio.cpp \ @@ -2456,7 +2456,7 @@ else ifeq ($(ARCH),cortexM3_efm32gg) ARCH_SRC += \ arch/cpu/armv7m/interfaces-impl/cpu.cpp \ arch/cpu/common/cortexMx_interrupts.cpp \ - arch/cpu/armv7m/interfaces-impl/userspace.cpp \ + arch/cpu/common/cortexMx_userspace.cpp \ arch/common/sleep/cortexMx_sleep.cpp \ arch/common/drivers/efm32_gpio.cpp \ arch/common/drivers/efm32_serial.cpp \ @@ -2640,7 +2640,7 @@ else ifeq ($(ARCH),cortexM7_stm32f7) ARCH_SRC += \ arch/cpu/armv7m/interfaces-impl/cpu.cpp \ arch/cpu/common/cortexMx_interrupts.cpp \ - arch/cpu/armv7m/interfaces-impl/userspace.cpp \ + arch/cpu/common/cortexMx_userspace.cpp \ arch/common/os_timer/stm32_32bit_os_timer.cpp \ arch/common/sleep/cortexMx_sleep.cpp \ arch/common/cache/cortexMx_cache.cpp \ @@ -2787,7 +2787,7 @@ else ifeq ($(ARCH),cortexM7_stm32h7) ARCH_SRC += \ arch/cpu/armv7m/interfaces-impl/cpu.cpp \ arch/cpu/common/cortexMx_interrupts.cpp \ - arch/cpu/armv7m/interfaces-impl/userspace.cpp \ + arch/cpu/common/cortexMx_userspace.cpp \ arch/common/os_timer/stm32_32bit_os_timer.cpp \ arch/common/sleep/cortexMx_sleep.cpp \ arch/common/cache/cortexMx_cache.cpp \ @@ -2971,7 +2971,7 @@ else ifeq ($(ARCH),cortexM4_stm32f3) ARCH_SRC += \ arch/cpu/armv7m/interfaces-impl/cpu.cpp \ arch/cpu/common/cortexMx_interrupts.cpp \ - arch/cpu/armv7m/interfaces-impl/userspace.cpp \ + arch/cpu/common/cortexMx_userspace.cpp \ arch/common/os_timer/stm32_32bit_os_timer.cpp \ arch/common/sleep/cortexMx_sleep.cpp \ arch/common/drivers/stm32_gpio.cpp \ @@ -3073,7 +3073,7 @@ else ifeq ($(ARCH),cortexM4_stm32l4) ARCH_SRC += \ arch/cpu/armv7m/interfaces-impl/cpu.cpp \ arch/cpu/common/cortexMx_interrupts.cpp \ - arch/cpu/armv7m/interfaces-impl/userspace.cpp \ + arch/cpu/common/cortexMx_userspace.cpp \ arch/common/os_timer/stm32_32bit_os_timer.cpp \ arch/common/sleep/cortexMx_sleep.cpp \ arch/common/drivers/stm32_gpio.cpp \ @@ -3144,7 +3144,7 @@ else ifeq ($(ARCH),cortexM4_atsam4l) ARCH_SRC += \ arch/cpu/armv7m/interfaces-impl/cpu.cpp \ arch/cpu/common/cortexMx_interrupts.cpp \ - arch/cpu/armv7m/interfaces-impl/userspace.cpp \ + arch/cpu/common/cortexMx_userspace.cpp \ arch/common/os_timer/atsam4l_os_timer.cpp \ arch/common/sleep/cortexMx_sleep.cpp \ arch/common/drivers/serial_atsam4l.cpp \ @@ -3207,7 +3207,7 @@ else ifeq ($(ARCH),cortexM3_efm32g) ARCH_SRC += \ arch/cpu/armv7m/interfaces-impl/cpu.cpp \ arch/cpu/common/cortexMx_interrupts.cpp \ - arch/cpu/armv7m/interfaces-impl/userspace.cpp \ + arch/cpu/common/cortexMx_userspace.cpp \ arch/common/os_timer/efm32_os_timer.cpp \ arch/common/sleep/cortexMx_sleep.cpp \ arch/common/drivers/efm32_gpio.cpp \ @@ -3381,6 +3381,7 @@ else ifeq ($(ARCH),cortexM0plus_rp2040) ARCH_SRC += \ arch/cpu/armv6m/interfaces-impl/cpu.cpp \ arch/cpu/common/cortexMx_interrupts.cpp \ + arch/cpu/common/cortexMx_userspace.cpp \ arch/common/os_timer/rp2040_os_timer.cpp \ arch/common/sleep/cortexMx_sleep.cpp \ arch/common/drivers/rp2040_serial.cpp \ -- GitLab