diff --git a/demos/RP/RT-RP2040-PICO/Makefile b/demos/RP/RT-RP2040-PICO/Makefile index ada153743..9dcf377cc 100644 --- a/demos/RP/RT-RP2040-PICO/Makefile +++ b/demos/RP/RT-RP2040-PICO/Makefile @@ -154,10 +154,10 @@ CPPWARN = -Wall -Wextra -Wundef # # List all user C define here, like -D_DEBUG=1 -UDEFS = -DCRT0_VTOR_INIT=1 -DPICO_NO_FPGA_CHECK +UDEFS = -DCRT0_VTOR_INIT=1 -DCRT0_EXTRA_CORES_NUMBER=1 -DPICO_NO_FPGA_CHECK # Define ASM defines here -UADEFS = -DCRT0_VTOR_INIT=1 +UADEFS = -DCRT0_VTOR_INIT=1 -DCRT0_EXTRA_CORES_NUMBER=1 # List all user directories here UINCDIR = diff --git a/demos/RP/RT-RP2040-PICO/main.c b/demos/RP/RT-RP2040-PICO/main.c index 933fba81b..8d7f910e1 100644 --- a/demos/RP/RT-RP2040-PICO/main.c +++ b/demos/RP/RT-RP2040-PICO/main.c @@ -49,11 +49,77 @@ static THD_FUNCTION(Thread1, arg) { } } +static inline bool multicore_fifo_rvalid(void) { + + return (bool)((SIO->FIFO_ST & SIO_FIFO_ST_VLD) != 0U); +} +static inline bool multicore_fifo_wready(void) { + + return (bool)((SIO->FIFO_ST & SIO_FIFO_ST_RDY) != 0U); +} + +static inline void multicore_fifo_drain(void) { + + while (multicore_fifo_rvalid()) + (void)SIO->FIFO_RD; +} + +static inline void multicore_fifo_push_blocking(uint32_t data) { + + // We wait for the fifo to have some space + while (!multicore_fifo_wready()) { + } + + SIO->FIFO_WR = data; + + // Fire off an event to the other core + __SEV(); +} + +static inline uint32_t multicore_fifo_pop_blocking(void) { + + // If nothing there yet, we wait for an event first, + // to try and avoid too much busy waiting + while (!multicore_fifo_rvalid()) { + __WFE(); + } + + return SIO->FIFO_RD; +} + +static void start_core1(void) { + extern uint32_t __c1_main_stack_end__, _vectors; + extern void _crt0_c1_entry(void); + uint32_t cmd_sequence[] = {0, 0, 1, + (uint32_t)&_vectors, + (uint32_t)&__c1_main_stack_end__, + (uint32_t)_crt0_c1_entry}; + unsigned seq; + + seq = 0; + do { + uint32_t response; + uint32_t cmd = cmd_sequence[seq]; + + // we drain before sending a 0 + if (!cmd) { + multicore_fifo_drain(); + __SEV(); // core 1 may be waiting for fifo space + } + multicore_fifo_push_blocking(cmd); + response = multicore_fifo_pop_blocking(); + // move to next state on correct response otherwise start over + seq = cmd == response ? seq + 1 : 0; + } while (seq < count_of(cmd_sequence)); +} + /* * Application entry point. */ int main(void) { + start_core1(); + /* * System initializations. * - HAL initialization, this also initializes the configured device drivers @@ -95,3 +161,12 @@ int main(void) { } } +/** + * Core 1 entry point. + */ +void c1_main(void) { + + while (true) { + + } +} diff --git a/os/common/ext/RP/RP2040/rp2040.h b/os/common/ext/RP/RP2040/rp2040.h index 28161e398..bdbbc3ffd 100644 --- a/os/common/ext/RP/RP2040/rp2040.h +++ b/os/common/ext/RP/RP2040/rp2040.h @@ -293,6 +293,23 @@ typedef struct { #define RESETS_ALLREG_ADC (1U << 0) /** @} */ +/** + * @name SIO bits definitions + */ +#define SIO_FIFO_ST_VLD_Pos 0U +#define SIO_FIFO_ST_VLD_Msk (1U << SIO_FIFO_ST_VLD_Pos) +#define SIO_FIFO_ST_VLD SIO_FIFO_ST_VLD_Msk +#define SIO_FIFO_ST_RDY_Pos 1U +#define SIO_FIFO_ST_RDY_Msk (1U << SIO_FIFO_ST_RDY_Pos) +#define SIO_FIFO_ST_RDY SIO_FIFO_ST_RDY_Msk +#define SIO_FIFO_ST_WOF_Pos 2U +#define SIO_FIFO_ST_WOF_Msk (1U << SIO_FIFO_ST_WOF_Pos) +#define SIO_FIFO_ST_WOF SIO_FIFO_ST_WOF_Msk +#define SIO_FIFO_ST_ROE_Pos 3U +#define SIO_FIFO_ST_ROE_Msk (1U << SIO_FIFO_ST_ROE_Pos) +#define SIO_FIFO_ST_ROE SIO_FIFO_ST_ROE_Msk +/** @} */ + /** * @name TIMER bits definitions */ diff --git a/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S b/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S index 57dfa2d13..de2666f2a 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S +++ b/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S @@ -129,6 +129,13 @@ #define CRT0_CALL_DESTRUCTORS TRUE #endif +/** + * @brief Number of extra cores. + */ +#if !defined(CRT0_EXTRA_CORES_NUMBER) || defined(__DOXYGEN__) +#define CRT0_EXTRA_CORES_NUMBER 0 +#endif + /*===========================================================================*/ /* Code section. */ /*===========================================================================*/ @@ -285,4 +292,83 @@ endfiniloop: #endif +#if CRT0_EXTRA_CORES_NUMBER > 0 + .align 2 + .thumb_func + .global _crt0_c1_entry +_crt0_c1_entry: + /* Interrupts are globally masked initially.*/ + cpsid i + +#if CRT0_FORCE_MSP_INIT == TRUE + /* MSP stack pointers initialization.*/ + ldr r0, =__c1_main_stack_end__ + msr MSP, r0 +#endif + + /* PSP stack pointers initialization.*/ + ldr r0, =__c1_process_stack_end__ + msr PSP, r0 + + /* CPU mode initialization as configured.*/ + movs r0, #CRT0_CONTROL_INIT + msr CONTROL, r0 + isb + +#if CRT0_VTOR_INIT == TRUE + ldr r0, =_vectors + ldr r1, =SCB_VTOR + str r0, [r1] +#endif + +#if CRT0_INIT_CORE == TRUE + /* Core initialization.*/ + bl __c1_cpu_init +#endif + + /* Early initialization..*/ + bl __c1_early_init + +#if CRT0_INIT_STACKS == TRUE + ldr r0, =CRT0_STACKS_FILL_PATTERN + /* Main Stack initialization. Note, it assumes that the + stack size is a multiple of 4 so the linker file must + ensure this.*/ + ldr r1, =__c1_main_stack_base__ + ldr r2, =__c1_main_stack_end__ +c1msloop: + cmp r1, r2 + bge c1endmsloop + str r0, [r1] + adds r1, #4 + b c1msloop +c1endmsloop: + /* Process Stack initialization. Note, it assumes that the + stack size is a multiple of 4 so the linker file must + ensure this.*/ + ldr r1, =__c1_process_stack_base__ + ldr r2, =__c1_process_stack_end__ +c1psloop: + cmp r1, r2 + bge c1endpsloop + str r0, [r1] + adds r1, #4 + b c1psloop +c1endpsloop: +#endif + + /* Late initialization..*/ + bl __c1_late_init + + /* Main program invocation, r0 contains the returned value.*/ + bl c1_main + + /* Branching to the defined exit handler.*/ + ldr r1, =__c1_default_exit + bx r1 + +#elif CRT0_EXTRA_CORES_NUMBER > 1 +#error "unsupported number of extra cores" +#endif + /** @} */ diff --git a/os/common/startup/ARMCMx/compilers/GCC/crt1.c b/os/common/startup/ARMCMx/compilers/GCC/crt1.c index 19cd8daba..2a80022a3 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/crt1.c +++ b/os/common/startup/ARMCMx/compilers/GCC/crt1.c @@ -31,12 +31,16 @@ /* Module local definitions. */ /*===========================================================================*/ -#if !defined(CRT1_AREAS_NUMBER) || defined(__DOXYGEN__) -#define CRT1_AREAS_NUMBER 8 +#if !defined(CRT0_EXTRA_CORES_NUMBER) || defined(__DOXYGEN__) +#define CRT0_EXTRA_CORES_NUMBER 0 #endif -#if (CRT1_AREAS_NUMBER < 0) || (CRT1_AREAS_NUMBER > 8) -#error "CRT1_AREAS_NUMBER must be within 0 and 8" +#if !defined(CRT0_AREAS_NUMBER) || defined(__DOXYGEN__) +#define CRT0_AREAS_NUMBER 8 +#endif + +#if (CRT0_AREAS_NUMBER < 0) || (CRT0_AREAS_NUMBER > 8) +#error "CRT0_AREAS_NUMBER must be within 0 and 8" #endif /*===========================================================================*/ @@ -61,56 +65,56 @@ typedef struct { /* Module local variables. */ /*===========================================================================*/ -#if (CRT1_AREAS_NUMBER > 0) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 0) || defined(__DOXYGEN__) extern uint32_t __ram0_init_text__, __ram0_init__, __ram0_clear__, __ram0_noinit__; #endif -#if (CRT1_AREAS_NUMBER > 1) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 1) || defined(__DOXYGEN__) extern uint32_t __ram1_init_text__, __ram1_init__, __ram1_clear__, __ram1_noinit__; #endif -#if (CRT1_AREAS_NUMBER > 2) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 2) || defined(__DOXYGEN__) extern uint32_t __ram2_init_text__, __ram2_init__, __ram2_clear__, __ram2_noinit__; #endif -#if (CRT1_AREAS_NUMBER > 3) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 3) || defined(__DOXYGEN__) extern uint32_t __ram3_init_text__, __ram3_init__, __ram3_clear__, __ram3_noinit__; #endif -#if (CRT1_AREAS_NUMBER > 4) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 4) || defined(__DOXYGEN__) extern uint32_t __ram4_init_text__, __ram4_init__, __ram4_clear__, __ram4_noinit__; #endif -#if (CRT1_AREAS_NUMBER > 5) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 5) || defined(__DOXYGEN__) extern uint32_t __ram5_init_text__, __ram5_init__, __ram5_clear__, __ram5_noinit__; #endif -#if (CRT1_AREAS_NUMBER > 6) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 6) || defined(__DOXYGEN__) extern uint32_t __ram6_init_text__, __ram6_init__, __ram6_clear__, __ram6_noinit__; #endif -#if (CRT1_AREAS_NUMBER > 7) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 7) || defined(__DOXYGEN__) extern uint32_t __ram7_init_text__, __ram7_init__, __ram7_clear__, __ram7_noinit__; #endif /** * @brief Static table of areas to be initialized. */ -#if (CRT1_AREAS_NUMBER > 0) || defined(__DOXYGEN__) -static const ram_init_area_t ram_areas[CRT1_AREAS_NUMBER] = { +#if (CRT0_AREAS_NUMBER > 0) || defined(__DOXYGEN__) +static const ram_init_area_t ram_areas[CRT0_AREAS_NUMBER] = { {&__ram0_init_text__, &__ram0_init__, &__ram0_clear__, &__ram0_noinit__}, -#if (CRT1_AREAS_NUMBER > 1) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 1) || defined(__DOXYGEN__) {&__ram1_init_text__, &__ram1_init__, &__ram1_clear__, &__ram1_noinit__}, #endif -#if (CRT1_AREAS_NUMBER > 2) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 2) || defined(__DOXYGEN__) {&__ram2_init_text__, &__ram2_init__, &__ram2_clear__, &__ram2_noinit__}, #endif -#if (CRT1_AREAS_NUMBER > 3) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 3) || defined(__DOXYGEN__) {&__ram3_init_text__, &__ram3_init__, &__ram3_clear__, &__ram3_noinit__}, #endif -#if (CRT1_AREAS_NUMBER > 4) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 4) || defined(__DOXYGEN__) {&__ram4_init_text__, &__ram4_init__, &__ram4_clear__, &__ram4_noinit__}, #endif -#if (CRT1_AREAS_NUMBER > 5) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 5) || defined(__DOXYGEN__) {&__ram5_init_text__, &__ram5_init__, &__ram5_clear__, &__ram5_noinit__}, #endif -#if (CRT1_AREAS_NUMBER > 6) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 6) || defined(__DOXYGEN__) {&__ram6_init_text__, &__ram6_init__, &__ram6_clear__, &__ram6_noinit__}, #endif -#if (CRT1_AREAS_NUMBER > 7) || defined(__DOXYGEN__) +#if (CRT0_AREAS_NUMBER > 7) || defined(__DOXYGEN__) {&__ram7_init_text__, &__ram7_init__, &__ram7_clear__, &__ram7_noinit__}, #endif }; @@ -187,11 +191,50 @@ void __default_exit(void) { } } +#if (CRT0_EXTRA_CORES_NUMBER > 0) || defined(__DOXYGEN__) +#if !defined(__DOXYGEN__) +__attribute__((weak)) +#endif +/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ +void __c1_cpu_init(void) { + +#if CORTEX_MODEL == 7 + SCB_EnableICache(); + SCB_EnableDCache(); +#endif +} + +#if !defined(__DOXYGEN__) +__attribute__((weak)) +#endif +/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ +void __c1_early_init(void) {} +/*lint -restore*/ + +#if !defined(__DOXYGEN__) +__attribute__((weak)) +#endif +/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ +void __c1_late_init(void) {} +/*lint -restore*/ + +#if !defined(__DOXYGEN__) +__attribute__((noreturn, weak)) +#endif +/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ +void __c1_default_exit(void) { +/*lint -restore*/ + + while (true) { + } +} +#endif + /** * @brief Performs the initialization of the various RAM areas. */ void __init_ram_areas(void) { -#if CRT1_AREAS_NUMBER > 0 +#if CRT0_AREAS_NUMBER > 0 const ram_init_area_t *rap = ram_areas; do { @@ -212,7 +255,7 @@ void __init_ram_areas(void) { } rap++; } - while (rap < &ram_areas[CRT1_AREAS_NUMBER]); + while (rap < &ram_areas[CRT0_AREAS_NUMBER]); #endif } diff --git a/os/common/startup/ARMCMx/compilers/GCC/ld/RP2040_RAM.ld b/os/common/startup/ARMCMx/compilers/GCC/ld/RP2040_RAM.ld index 1ec0bae66..812da8ff6 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/ld/RP2040_RAM.ld +++ b/os/common/startup/ARMCMx/compilers/GCC/ld/RP2040_RAM.ld @@ -71,6 +71,14 @@ REGION_ALIAS("MAIN_STACK_RAM", ram4); the main() function.*/ REGION_ALIAS("PROCESS_STACK_RAM", ram4); +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("C1_MAIN_STACK_RAM", ram5); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("C1_PROCESS_STACK_RAM", ram5); + /* RAM region to be used for data segment.*/ REGION_ALIAS("DATA_RAM", ram0); REGION_ALIAS("DATA_RAM_LMA", ram0); @@ -82,5 +90,9 @@ REGION_ALIAS("BSS_RAM", ram0); REGION_ALIAS("HEAP_RAM", ram0); /* Generic rules inclusion.*/ -INCLUDE rules.ld +INCLUDE rules_stacks.ld +INCLUDE rules_stacks_c1.ld +INCLUDE rules_code.ld +INCLUDE rules_data.ld +INCLUDE rules_memory.ld diff --git a/os/common/startup/ARMCMx/compilers/GCC/ld/rules_stacks_c1.ld b/os/common/startup/ARMCMx/compilers/GCC/ld/rules_stacks_c1.ld new file mode 100644 index 000000000..f4d747b03 --- /dev/null +++ b/os/common/startup/ARMCMx/compilers/GCC/ld/rules_stacks_c1.ld @@ -0,0 +1,40 @@ +/* + ChibiOS - Copyright (C) 2006..2021 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +SECTIONS +{ + /* Special section for exceptions stack.*/ + .c1_mstack (NOLOAD) : + { + . = ALIGN(8); + __c1_main_stack_base__ = .; + . += __main_stack_size__; + . = ALIGN(8); + __c1_main_stack_end__ = .; + } > C1_MAIN_STACK_RAM + + /* Special section for process stack.*/ + .pstack (NOLOAD) : + { + . = ALIGN(8); + __c1_process_stack_base__ = .; + __c1_main_thread_stack_base__ = .; + . += __process_stack_size__; + . = ALIGN(8); + __c1_process_stack_end__ = .; + __c1_main_thread_stack_end__ = .; + } > C1_PROCESS_STACK_RAM +}