From b8f699f6ff4aaf16c7cb9641f4041aace9f3bc61 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 1 Dec 2025 19:32:27 +0000 Subject: [PATCH 001/127] Separate linker scripts out into include files Allows for much simpler custom linker scripts --- .../pico_crt0/rp2040/memmap_blocked_ram.ld | 287 +--------------- .../pico_crt0/rp2040/memmap_copy_to_ram.ld | 288 +--------------- .../pico_crt0/rp2040/memmap_default.ld | 287 +--------------- .../pico_crt0/rp2040/memmap_no_flash.ld | 249 +------------- .../pico_crt0/rp2040/memory_blocked_ram.ld | 4 + .../pico_crt0/rp2040/memory_flash.ld | 4 + src/rp2_common/pico_crt0/rp2040/memory_ram.ld | 4 + .../pico_crt0/rp2040/memory_scratch.ld | 5 + .../pico_crt0/rp2040/sections_copy_to_ram.ld | 276 ++++++++++++++++ .../pico_crt0/rp2040/sections_default.ld | 275 ++++++++++++++++ .../pico_crt0/rp2040/sections_no_flash.ld | 239 ++++++++++++++ .../pico_crt0/rp2350/memmap_copy_to_ram.ld | 310 +----------------- .../pico_crt0/rp2350/memmap_default.ld | 303 +---------------- .../pico_crt0/rp2350/memmap_no_flash.ld | 256 +-------------- .../pico_crt0/rp2350/memory_copy_to_ram.ld | 0 .../pico_crt0/rp2350/memory_flash.ld | 4 + src/rp2_common/pico_crt0/rp2350/memory_ram.ld | 4 + .../pico_crt0/rp2350/memory_scratch.ld | 5 + .../pico_crt0/rp2350/memory_xip_ram.ld | 4 + .../pico_crt0/rp2350/sections_copy_to_ram.ld | 298 +++++++++++++++++ .../pico_crt0/rp2350/sections_default.ld | 291 ++++++++++++++++ .../pico_crt0/rp2350/sections_no_flash.ld | 246 ++++++++++++++ .../pico_standard_link/CMakeLists.txt | 5 +- 23 files changed, 1689 insertions(+), 1955 deletions(-) create mode 100644 src/rp2_common/pico_crt0/rp2040/memory_blocked_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/memory_flash.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/memory_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/memory_scratch.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/sections_default.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/memory_copy_to_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/memory_flash.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/memory_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/memory_scratch.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/memory_xip_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/sections_default.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld index 6f5000566..150176eba 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld @@ -1,286 +1,7 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -MEMORY -{ - INCLUDE "pico_flash_region.ld" - RAM(rwx) : ORIGIN = 0x21000000, LENGTH = 256k - SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k -} +INCLUDE "memory_flash.ld" +INCLUDE "memory_blocked_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .text : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - /* TODO revisit this now memset/memcpy/float in ROM */ - /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from - * FLASH ... we will include any thing excluded here in .data below by default */ - *(.init) - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.eh_frame*) - . = ALIGN(4); - } > FLASH - - .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ - *(.text*) - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} - +INCLUDE "sections_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld index 842ebfd3c..7b99a7745 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld @@ -1,287 +1,7 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -MEMORY -{ - INCLUDE "pico_flash_region.ld" - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k - SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k -} +INCLUDE "memory_flash.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .flashtext : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - } - - .rodata : { - /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - /* Vector table goes first in RAM, to avoid large alignment hole */ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .text : { - __ram_text_start__ = .; - *(.init) - *(.text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - . = ALIGN(4); - __ram_text_end__ = .; - } > RAM AT> FLASH - __ram_text_source__ = LOADADDR(.text); - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} - +INCLUDE "sections_copy_to_ram.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_default.ld b/src/rp2_common/pico_crt0/rp2040/memmap_default.ld index 51254012d..75fd340d5 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_default.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_default.ld @@ -1,286 +1,7 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -MEMORY -{ - INCLUDE "pico_flash_region.ld" - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k - SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k -} +INCLUDE "memory_flash.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .text : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - /* TODO revisit this now memset/memcpy/float in ROM */ - /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from - * FLASH ... we will include any thing excluded here in .data below by default */ - *(.init) - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.eh_frame*) - . = ALIGN(4); - } > FLASH - - .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ - *(.text*) - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} - +INCLUDE "sections_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld b/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld index dbf006a8c..cde630592 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld @@ -1,249 +1,6 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -MEMORY -{ - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k - SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k -} +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - /* Note in NO_FLASH builds the entry point for both the bootrom, and debugger - entry (ELF entry point), are *first* in the image, and the vector table - follows immediately afterward. This is because the bootrom enters RAM - binaries directly at their lowest address (preferring main RAM over XIP - cache-as-SRAM if both are used). - */ - - .text : { - __logical_binary_start = .; - __reset_start = .; - KEEP (*(.reset)) - __reset_end = .; - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - . = ALIGN(256); - KEEP (*(.vectors)) - *(.time_critical*) - *(.text*) - . = ALIGN(4); - *(.init) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - } > RAM - - .rodata : { - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > RAM - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > RAM - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > RAM - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > RAM - __binary_info_end = .; - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM - PROVIDE(__data_end__ = .); - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} - +INCLUDE "sections_no_flash.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memory_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/memory_blocked_ram.ld new file mode 100644 index 000000000..57cbad6b7 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/memory_blocked_ram.ld @@ -0,0 +1,4 @@ +MEMORY +{ + RAM(rwx) : ORIGIN = 0x21000000, LENGTH = 256k +} diff --git a/src/rp2_common/pico_crt0/rp2040/memory_flash.ld b/src/rp2_common/pico_crt0/rp2040/memory_flash.ld new file mode 100644 index 000000000..669fe00e3 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/memory_flash.ld @@ -0,0 +1,4 @@ +MEMORY +{ + INCLUDE "pico_flash_region.ld" +} diff --git a/src/rp2_common/pico_crt0/rp2040/memory_ram.ld b/src/rp2_common/pico_crt0/rp2040/memory_ram.ld new file mode 100644 index 000000000..1e1515dd3 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/memory_ram.ld @@ -0,0 +1,4 @@ +MEMORY +{ + RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k +} diff --git a/src/rp2_common/pico_crt0/rp2040/memory_scratch.ld b/src/rp2_common/pico_crt0/rp2040/memory_scratch.ld new file mode 100644 index 000000000..a4b982b92 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/memory_scratch.ld @@ -0,0 +1,5 @@ +MEMORY +{ + SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k + SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k +} diff --git a/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld new file mode 100644 index 000000000..5557ee1cb --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld @@ -0,0 +1,276 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* Second stage bootloader is prepended to the image. It must be 256 bytes big + and checksummed. It is usually built by the boot_stage2 target + in the Raspberry Pi Pico SDK + */ + + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + .boot2 : { + __boot2_start__ = .; + KEEP (*(.boot2)) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ == 256, + "ERROR: Pico second stage bootloader must be 256 bytes in size") + + /* The second stage will always enter the image at the start of .text. + The debugger will use the ELF entry point, which is the _entry_point + symbol if present, otherwise defaults to start of .text. + This can be used to transfer control back to the bootrom on debugger + launches only, to perform proper flash setup. + */ + + .flashtext : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + } + + .rodata : { + /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); + + /* Vector table goes first in RAM, to avoid large alignment hole */ + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .text : { + __ram_text_start__ = .; + *(.init) + *(.text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + . = ALIGN(4); + __ram_text_end__ = .; + } > RAM AT> FLASH + __ram_text_source__ = LOADADDR(.text); + . = ALIGN(4); + + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + + *(.data*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X AT > FLASH + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y AT > FLASH + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y + + .flash_end : { + KEEP(*(.embedded_end_block*)) + PROVIDE(__flash_binary_end = .); + } > FLASH + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2040/sections_default.ld b/src/rp2_common/pico_crt0/rp2040/sections_default.ld new file mode 100644 index 000000000..57984e46b --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/sections_default.ld @@ -0,0 +1,275 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* Second stage bootloader is prepended to the image. It must be 256 bytes big + and checksummed. It is usually built by the boot_stage2 target + in the Raspberry Pi Pico SDK + */ + + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + .boot2 : { + __boot2_start__ = .; + KEEP (*(.boot2)) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ == 256, + "ERROR: Pico second stage bootloader must be 256 bytes in size") + + /* The second stage will always enter the image at the start of .text. + The debugger will use the ELF entry point, which is the _entry_point + symbol if present, otherwise defaults to start of .text. + This can be used to transfer control back to the bootrom on debugger + launches only, to perform proper flash setup. + */ + + .text : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + /* TODO revisit this now memset/memcpy/float in ROM */ + /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from + * FLASH ... we will include any thing excluded here in .data below by default */ + *(.init) + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.eh_frame*) + . = ALIGN(4); + } > FLASH + + .rodata : { + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); + + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ + *(.text*) + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + + *(.data*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X AT > FLASH + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y AT > FLASH + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y + + .flash_end : { + KEEP(*(.embedded_end_block*)) + PROVIDE(__flash_binary_end = .); + } > FLASH + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld b/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld new file mode 100644 index 000000000..9e082d53c --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld @@ -0,0 +1,239 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* Note in NO_FLASH builds the entry point for both the bootrom, and debugger + entry (ELF entry point), are *first* in the image, and the vector table + follows immediately afterward. This is because the bootrom enters RAM + binaries directly at their lowest address (preferring main RAM over XIP + cache-as-SRAM if both are used). + */ + + .text : { + __logical_binary_start = .; + __reset_start = .; + KEEP (*(.reset)) + __reset_end = .; + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + . = ALIGN(256); + KEEP (*(.vectors)) + *(.time_critical*) + *(.text*) + . = ALIGN(4); + *(.init) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + } > RAM + + .rodata : { + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > RAM + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > RAM + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > RAM + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > RAM + __binary_info_end = .; + . = ALIGN(4); + + .data : { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM + PROVIDE(__data_end__ = .); + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld index 44c69f3b9..7b99a7745 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld @@ -1,309 +1,7 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -MEMORY -{ - INCLUDE "pico_flash_region.ld" - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k - SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k -} +INCLUDE "memory_flash.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - /* On Arm, the bootrom expects a VT at the start of the - image by default; on RISC-V, the default is to enter the image at its - lowest address, so an IMAGE_DEF item is required to specify the - nondefault entry point. */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - /* The bootrom will enter the image at the point indicated in your - IMAGE_DEF, which is usually the reset handler of your vector table. - - The debugger will use the ELF entry point, which is the _entry_point - symbol, and in our case is *different from the bootrom's entry point.* - This is used to go back through the bootrom on debugger launches only, - to perform the same initial flash setup that would be performed on a - cold boot. - */ - - .flashtext : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - . = ALIGN(4); - } > FLASH - - /* Note the boot2 section is optional, and should be discarded if there is - no reference to it *inside* the binary, as it is not called by the - bootrom. (The bootrom performs a simple best-effort XIP setup and - leaves it to the binary to do anything more sophisticated.) However - there is still a size limit of 256 bytes, to ensure the boot2 can be - stored in boot RAM. - - Really this is a "XIP setup function" -- the name boot2 is historic and - refers to its dual-purpose on RP2040, where it also handled vectoring - from the bootrom into the user image. - */ - - .boot2 : { - __boot2_start__ = .; - *(.boot2) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ <= 256, - "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") - - .rodata : { - /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - /* Vector table goes first in RAM, to avoid large alignment hole */ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .text : { - __ram_text_start__ = .; - *(.init) - *(.text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - . = ALIGN(4); - __ram_text_end__ = .; - } > RAM AT> FLASH - __ram_text_source__ = LOADADDR(.text); - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - . = ALIGN(4); - *(.rodata*) - *(.srodata*) - . = ALIGN(4); - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH =0xaa - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") - ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ -} - +INCLUDE "sections_copy_to_ram.ld" diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld index bce316d14..75fd340d5 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld @@ -1,302 +1,7 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -MEMORY -{ - INCLUDE "pico_flash_region.ld" - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k - SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k -} +INCLUDE "memory_flash.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - /* The bootrom will enter the image at the point indicated in your - IMAGE_DEF, which is usually the reset handler of your vector table. - - The debugger will use the ELF entry point, which is the _entry_point - symbol, and in our case is *different from the bootrom's entry point.* - This is used to go back through the bootrom on debugger launches only, - to perform the same initial flash setup that would be performed on a - cold boot. - */ - - .text : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - /* TODO revisit this now memset/memcpy/float in ROM */ - /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from - * FLASH ... we will include any thing excluded here in .data below by default */ - *(.init) - *libgcc.a:cmse_nonsecure_call.o - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.eh_frame*) - . = ALIGN(4); - } > FLASH - - /* Note the boot2 section is optional, and should be discarded if there is - no reference to it *inside* the binary, as it is not called by the - bootrom. (The bootrom performs a simple best-effort XIP setup and - leaves it to the binary to do anything more sophisticated.) However - there is still a size limit of 256 bytes, to ensure the boot2 can be - stored in boot RAM. - - Really this is a "XIP setup function" -- the name boot2 is historic and - refers to its dual-purpose on RP2040, where it also handled vectoring - from the bootrom into the user image. - */ - - .boot2 : { - __boot2_start__ = .; - *(.boot2) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ <= 256, - "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") - - .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) - *(.srodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ - *(.text*) - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH =0xaa - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") - ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ -} - +INCLUDE "sections_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld index 5bedf6d21..cde630592 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld @@ -1,256 +1,6 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -MEMORY -{ - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k - SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k -} +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - /* Note unlike RP2040, we start the image with a vector table even for - NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the - image by default; on RISC-V, the default is to enter the image at its - lowest address, so an IMAGE_DEF item is required to specify the - nondefault entry point. */ - - .text : { - __logical_binary_start = .; - /* Vectors require 512-byte alignment on v8-M when >48 IRQs are used, - so we would waste RAM if the vector table were not at the - start. */ - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - __reset_start = .; - KEEP (*(.reset)) - __reset_end = .; - *(.time_critical*) - *(.text*) - . = ALIGN(4); - *(.init) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - } > RAM - - .rodata : { - . = ALIGN(4); - *(.rodata*) - *(.srodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > RAM - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > RAM - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > RAM - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > RAM - __binary_info_end = .; - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM - PROVIDE(__data_end__ = .); - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") - ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ -} - +INCLUDE "sections_no_flash.ld" diff --git a/src/rp2_common/pico_crt0/rp2350/memory_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/memory_copy_to_ram.ld new file mode 100644 index 000000000..e69de29bb diff --git a/src/rp2_common/pico_crt0/rp2350/memory_flash.ld b/src/rp2_common/pico_crt0/rp2350/memory_flash.ld new file mode 100644 index 000000000..669fe00e3 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/memory_flash.ld @@ -0,0 +1,4 @@ +MEMORY +{ + INCLUDE "pico_flash_region.ld" +} diff --git a/src/rp2_common/pico_crt0/rp2350/memory_ram.ld b/src/rp2_common/pico_crt0/rp2350/memory_ram.ld new file mode 100644 index 000000000..434cdab97 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/memory_ram.ld @@ -0,0 +1,4 @@ +MEMORY +{ + RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k +} diff --git a/src/rp2_common/pico_crt0/rp2350/memory_scratch.ld b/src/rp2_common/pico_crt0/rp2350/memory_scratch.ld new file mode 100644 index 000000000..246bbf050 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/memory_scratch.ld @@ -0,0 +1,5 @@ +MEMORY +{ + SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k + SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k +} diff --git a/src/rp2_common/pico_crt0/rp2350/memory_xip_ram.ld b/src/rp2_common/pico_crt0/rp2350/memory_xip_ram.ld new file mode 100644 index 000000000..e94479b54 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/memory_xip_ram.ld @@ -0,0 +1,4 @@ +MEMORY +{ + XIP_RAM(rwx) : ORIGIN = 0x13FFC000, LENGTH = 16k +} diff --git a/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld new file mode 100644 index 000000000..9cc60b10a --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld @@ -0,0 +1,298 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* On Arm, the bootrom expects a VT at the start of the + image by default; on RISC-V, the default is to enter the image at its + lowest address, so an IMAGE_DEF item is required to specify the + nondefault entry point. */ + + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + /* The bootrom will enter the image at the point indicated in your + IMAGE_DEF, which is usually the reset handler of your vector table. + + The debugger will use the ELF entry point, which is the _entry_point + symbol, and in our case is *different from the bootrom's entry point.* + This is used to go back through the bootrom on debugger launches only, + to perform the same initial flash setup that would be performed on a + cold boot. + */ + + .flashtext : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + . = ALIGN(4); + } > FLASH + + /* Note the boot2 section is optional, and should be discarded if there is + no reference to it *inside* the binary, as it is not called by the + bootrom. (The bootrom performs a simple best-effort XIP setup and + leaves it to the binary to do anything more sophisticated.) However + there is still a size limit of 256 bytes, to ensure the boot2 can be + stored in boot RAM. + + Really this is a "XIP setup function" -- the name boot2 is historic and + refers to its dual-purpose on RP2040, where it also handled vectoring + from the bootrom into the user image. + */ + + .boot2 : { + __boot2_start__ = .; + *(.boot2) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ <= 256, + "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") + + .rodata : { + /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); + + /* Vector table goes first in RAM, to avoid large alignment hole */ + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .text : { + __ram_text_start__ = .; + *(.init) + *(.text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + . = ALIGN(4); + __ram_text_end__ = .; + } > RAM AT> FLASH + __ram_text_source__ = LOADADDR(.text); + . = ALIGN(4); + + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + . = ALIGN(4); + *(.rodata*) + *(.srodata*) + . = ALIGN(4); + + *(.data*) + *(.sdata*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X AT > FLASH + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y AT > FLASH + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y + + .flash_end : { + KEEP(*(.embedded_end_block*)) + PROVIDE(__flash_binary_end = .); + } > FLASH =0xaa + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") + ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") + + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2350/sections_default.ld b/src/rp2_common/pico_crt0/rp2350/sections_default.ld new file mode 100644 index 000000000..cb2c6e114 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/sections_default.ld @@ -0,0 +1,291 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + /* The bootrom will enter the image at the point indicated in your + IMAGE_DEF, which is usually the reset handler of your vector table. + + The debugger will use the ELF entry point, which is the _entry_point + symbol, and in our case is *different from the bootrom's entry point.* + This is used to go back through the bootrom on debugger launches only, + to perform the same initial flash setup that would be performed on a + cold boot. + */ + + .text : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + /* TODO revisit this now memset/memcpy/float in ROM */ + /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from + * FLASH ... we will include any thing excluded here in .data below by default */ + *(.init) + *libgcc.a:cmse_nonsecure_call.o + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.eh_frame*) + . = ALIGN(4); + } > FLASH + + /* Note the boot2 section is optional, and should be discarded if there is + no reference to it *inside* the binary, as it is not called by the + bootrom. (The bootrom performs a simple best-effort XIP setup and + leaves it to the binary to do anything more sophisticated.) However + there is still a size limit of 256 bytes, to ensure the boot2 can be + stored in boot RAM. + + Really this is a "XIP setup function" -- the name boot2 is historic and + refers to its dual-purpose on RP2040, where it also handled vectoring + from the bootrom into the user image. + */ + + .boot2 : { + __boot2_start__ = .; + *(.boot2) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ <= 256, + "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") + + .rodata : { + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) + *(.srodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); + + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ + *(.text*) + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + + *(.data*) + *(.sdata*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X AT > FLASH + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y AT > FLASH + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y + + .flash_end : { + KEEP(*(.embedded_end_block*)) + PROVIDE(__flash_binary_end = .); + } > FLASH =0xaa + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") + ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") + + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld new file mode 100644 index 000000000..869d86436 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld @@ -0,0 +1,246 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* Note unlike RP2040, we start the image with a vector table even for + NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the + image by default; on RISC-V, the default is to enter the image at its + lowest address, so an IMAGE_DEF item is required to specify the + nondefault entry point. */ + + .text : { + __logical_binary_start = .; + /* Vectors require 512-byte alignment on v8-M when >48 IRQs are used, + so we would waste RAM if the vector table were not at the + start. */ + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + __reset_start = .; + KEEP (*(.reset)) + __reset_end = .; + *(.time_critical*) + *(.text*) + . = ALIGN(4); + *(.init) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + } > RAM + + .rodata : { + . = ALIGN(4); + *(.rodata*) + *(.srodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > RAM + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > RAM + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > RAM + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > RAM + __binary_info_end = .; + . = ALIGN(4); + + .data : { + __data_start__ = .; + *(vtable) + *(.data*) + *(.sdata*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM + PROVIDE(__data_end__ = .); + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") + ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") + + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index c16968bba..5905d3da1 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -124,9 +124,12 @@ if (NOT TARGET pico_standard_link) #math(EXPR PICO_FLASH_SIZE_BYTES_STRING "${PICO_FLASH_SIZE_BYTES}" OUTPUT_FORMAT HEXADECIMAL) set(PICO_FLASH_SIZE_BYTES_STRING "${PICO_FLASH_SIZE_BYTES}") configure_file(${CMAKE_CURRENT_LIST_DIR}/pico_flash_region.template.ld ${CMAKE_BINARY_DIR}/pico_flash_region.ld) - # add include path for linker scripts + # add include path for linker scripts to find it target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_BINARY_DIR}") + # add include path for main linker script sections + target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}") + # LINKER script will be PICO_TARGET_LINKER_SCRIPT if set on target, or ${CMAKE_CURRENT_LIST_DIR}/memmap_foo.ld # if PICO_TARGET_BINARY_TYPE is set to foo on the target, otherwise ${CMAKE_CURRENT_LIST_DIR}/memmap_${PICO_DEFAULT_BINARY_TYPE).ld set(_LINKER_SCRIPT_EXPRESSION "$>,$,${PICO_LINKER_SCRIPT_PATH}/memmap_$,>,${PICO_DEFAULT_BINARY_TYPE},$>.ld>") From 6dc06e6d1d70d9e7ad7bb785cf57360515072b31 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 1 Dec 2025 20:40:45 +0000 Subject: [PATCH 002/127] Add customisable heap location, with pico_set_linker_script_var function --- .../pico_crt0/rp2040/sections_copy_to_ram.ld | 4 ++-- src/rp2_common/pico_crt0/rp2040/sections_default.ld | 4 ++-- src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld | 4 ++-- .../pico_crt0/rp2350/sections_copy_to_ram.ld | 4 ++-- src/rp2_common/pico_crt0/rp2350/sections_default.ld | 4 ++-- src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld | 4 ++-- src/rp2_common/pico_standard_link/CMakeLists.txt | 12 ++++++++++++ 7 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld index 5557ee1cb..1777f6604 100644 --- a/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld @@ -199,7 +199,7 @@ SECTIONS __bss_end__ = .; } > RAM - .heap (NOLOAD): + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -207,7 +207,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_crt0/rp2040/sections_default.ld b/src/rp2_common/pico_crt0/rp2040/sections_default.ld index 57984e46b..2e72b83b1 100644 --- a/src/rp2_common/pico_crt0/rp2040/sections_default.ld +++ b/src/rp2_common/pico_crt0/rp2040/sections_default.ld @@ -198,7 +198,7 @@ SECTIONS __bss_end__ = .; } > RAM - .heap (NOLOAD): + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -206,7 +206,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld b/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld index 9e082d53c..c71ee3b01 100644 --- a/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld @@ -167,7 +167,7 @@ SECTIONS __bss_end__ = .; } > RAM - .heap (NOLOAD): + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -175,7 +175,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld index 9cc60b10a..4b76bc04c 100644 --- a/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld @@ -219,7 +219,7 @@ SECTIONS __bss_end__ = .; } > RAM - .heap (NOLOAD): + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -227,7 +227,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_crt0/rp2350/sections_default.ld b/src/rp2_common/pico_crt0/rp2350/sections_default.ld index cb2c6e114..eaeee2723 100644 --- a/src/rp2_common/pico_crt0/rp2350/sections_default.ld +++ b/src/rp2_common/pico_crt0/rp2350/sections_default.ld @@ -212,7 +212,7 @@ SECTIONS __bss_end__ = .; } > RAM - .heap (NOLOAD): + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -220,7 +220,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld index 869d86436..595d69778 100644 --- a/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld @@ -172,7 +172,7 @@ SECTIONS __bss_end__ = .; } > RAM - .heap (NOLOAD): + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -180,7 +180,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index 5905d3da1..5dd40909d 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -70,6 +70,15 @@ if (NOT TARGET pico_standard_link) set_target_properties(${TARGET} PROPERTIES PICO_TARGET_LINKER_SCRIPT ${LDSCRIPT}) endfunction() + # pico_set_linker_script_var(TARGET NAME VALUE) + # \brief\ Set the linker script for the target + # + # \param\ NAME Name of varAible to set + # \param\ VALUE Value of variable to set + function(pico_set_linker_script_var TARGET NAME VALUE) + set_property(TARGET ${TARGET} APPEND PROPERTY PICO_TARGET_LINKER_SCRIPT_VARS "--defsym=${NAME}=${VALUE}") + endfunction() + # pico_set_binary_type(TARGET TYPE) # \brief\ Set the binary type for the target # @@ -130,6 +139,9 @@ if (NOT TARGET pico_standard_link) # add include path for main linker script sections target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}") + # add variables set by pico_set_linker_script_var function + target_link_options(pico_standard_link INTERFACE "LINKER:$,,>") + # LINKER script will be PICO_TARGET_LINKER_SCRIPT if set on target, or ${CMAKE_CURRENT_LIST_DIR}/memmap_foo.ld # if PICO_TARGET_BINARY_TYPE is set to foo on the target, otherwise ${CMAKE_CURRENT_LIST_DIR}/memmap_${PICO_DEFAULT_BINARY_TYPE).ld set(_LINKER_SCRIPT_EXPRESSION "$>,$,${PICO_LINKER_SCRIPT_PATH}/memmap_$,>,${PICO_DEFAULT_BINARY_TYPE},$>.ld>") From 727cabd4d0c1d9ffda7ec1bd456ee160527508aa Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 1 Dec 2025 20:41:39 +0000 Subject: [PATCH 003/127] Add kitchen sink test of custom linker scripts --- test/kitchen_sink/CMakeLists.txt | 8 ++++++++ test/kitchen_sink/memmap_custom.ld | 12 ++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 test/kitchen_sink/memmap_custom.ld diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt index 1d6110f4c..71b8a58b6 100644 --- a/test/kitchen_sink/CMakeLists.txt +++ b/test/kitchen_sink/CMakeLists.txt @@ -214,6 +214,14 @@ if (NOT KITCHEN_SINK_NO_BINARY_TYPE_VARIANTS) pico_add_extra_outputs(kitchen_sink_blocked_ram) target_compile_definitions(kitchen_sink_blocked_ram PRIVATE KITCHEN_SINK_ID="blocked-ram binary") endif() + + add_executable(kitchen_sink_memmap_custom ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) + # Have heap start from 0x20030000, and custom linker script + pico_set_linker_script(kitchen_sink_memmap_custom ${CMAKE_CURRENT_LIST_DIR}/memmap_custom.ld) + pico_set_linker_script_var(kitchen_sink_memmap_custom HEAP_LOC 0x20030000) + target_link_libraries(kitchen_sink_memmap_custom kitchen_sink_libs kitchen_sink_options) + pico_add_extra_outputs(kitchen_sink_memmap_custom) + target_compile_definitions(kitchen_sink_memmap_custom PRIVATE KITCHEN_SINK_ID="custom memmap binary") endif() add_executable(kitchen_sink_cpp ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_cpp.cpp) diff --git a/test/kitchen_sink/memmap_custom.ld b/test/kitchen_sink/memmap_custom.ld new file mode 100644 index 000000000..081913e58 --- /dev/null +++ b/test/kitchen_sink/memmap_custom.ld @@ -0,0 +1,12 @@ +INCLUDE "memory_flash.ld" +INCLUDE "memory_scratch.ld" + +/* Only use 128k of SRAM, starting at 0x20020000 */ +MEMORY +{ + RAM(rwx) : ORIGIN = 0x20020000, LENGTH = 128k +} + +ENTRY(_entry_point) + +INCLUDE "sections_default.ld" From 3a83dc7838de5688aee3fbcc49787c0203403034 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 2 Dec 2025 14:48:02 +0000 Subject: [PATCH 004/127] Separate out rp2_common and platform-specific linker script sections --- .../pico_crt0/rp2040/memmap_blocked_ram.ld | 14 +- .../pico_crt0/rp2040/memmap_copy_to_ram.ld | 8 +- .../pico_crt0/rp2040/memmap_default.ld | 8 +- .../pico_crt0/rp2040/memmap_no_flash.ld | 7 +- .../{ => platform}/memory_blocked_ram.ld | 0 .../rp2040/{ => platform}/memory_ram.ld | 0 .../rp2040/{ => platform}/memory_scratch.ld | 0 .../platform/section_copy_to_ram_data.ld | 79 +++++ .../platform/section_copy_to_ram_text.ld | 101 ++++++ .../rp2040/platform/section_default_data.ld | 70 ++++ .../rp2040/platform/section_default_text.ld | 109 +++++++ .../rp2040/platform/section_no_flash_data.ld | 79 +++++ .../rp2040/platform/section_no_flash_text.ld | 71 +++++ .../rp2040/platform/section_platform_end.ld | 50 +++ .../pico_crt0/rp2040/sections_copy_to_ram.ld | 276 ---------------- .../pico_crt0/rp2040/sections_default.ld | 275 ---------------- .../pico_crt0/rp2040/sections_no_flash.ld | 239 -------------- .../pico_crt0/rp2350/memmap_copy_to_ram.ld | 8 +- .../pico_crt0/rp2350/memmap_default.ld | 8 +- .../pico_crt0/rp2350/memmap_no_flash.ld | 7 +- .../pico_crt0/rp2350/memory_copy_to_ram.ld | 0 .../pico_crt0/rp2350/memory_flash.ld | 4 - .../rp2350/{ => platform}/memory_ram.ld | 0 .../rp2350/{ => platform}/memory_scratch.ld | 0 .../rp2350/{ => platform}/memory_xip_ram.ld | 0 .../platform/section_copy_to_ram_data.ld | 83 +++++ .../platform/section_copy_to_ram_text.ld | 117 +++++++ .../rp2350/platform/section_default_data.ld | 72 +++++ .../rp2350/platform/section_default_text.ld | 121 +++++++ .../rp2350/platform/section_no_flash_data.ld | 82 +++++ .../rp2350/platform/section_no_flash_text.ld | 73 +++++ .../rp2350/platform/section_platform_end.ld | 7 + .../pico_crt0/rp2350/sections_copy_to_ram.ld | 298 ------------------ .../pico_crt0/rp2350/sections_default.ld | 291 ----------------- .../pico_crt0/rp2350/sections_no_flash.ld | 246 --------------- .../pico_standard_link/CMakeLists.txt | 1 + .../scripts/rp2_common/memmap_copy_to_ram.ld | 13 + .../scripts/rp2_common/memmap_default.ld | 13 + .../scripts/rp2_common/memmap_no_flash.ld | 12 + .../rp2_common/memory_aliases_default.ld | 3 + .../rp2_common/memory_aliases_no_flash.ld | 3 + .../scripts/rp2_common}/memory_flash.ld | 0 .../scripts/rp2_common/section_end.ld | 49 +++ .../scripts/rp2_common/section_flash_end.ld | 7 + .../scripts/rp2_common/section_heap.ld | 12 + .../scripts/rp2_common/section_scratch.ld | 37 +++ .../rp2_common/sections_copy_to_ram.ld | 7 + .../scripts/rp2_common/sections_default.ld | 7 + .../scripts/rp2_common/sections_no_flash.ld | 6 + test/kitchen_sink/memmap_custom.ld | 12 +- 50 files changed, 1309 insertions(+), 1676 deletions(-) rename src/rp2_common/pico_crt0/rp2040/{ => platform}/memory_blocked_ram.ld (100%) rename src/rp2_common/pico_crt0/rp2040/{ => platform}/memory_ram.ld (100%) rename src/rp2_common/pico_crt0/rp2040/{ => platform}/memory_scratch.ld (100%) create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_text.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_default_text.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_text.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_platform_end.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/sections_default.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/memory_copy_to_ram.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/memory_flash.ld rename src/rp2_common/pico_crt0/rp2350/{ => platform}/memory_ram.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{ => platform}/memory_scratch.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{ => platform}/memory_xip_ram.ld (100%) create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_text.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_default_text.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_text.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_platform_end.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/sections_default.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_default.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_no_flash.ld rename src/rp2_common/{pico_crt0/rp2040 => pico_standard_link/scripts/rp2_common}/memory_flash.ld (100%) create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/section_end.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/section_flash_end.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/section_heap.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/section_scratch.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld index 150176eba..330e9bde3 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld @@ -1,7 +1,13 @@ -INCLUDE "memory_flash.ld" -INCLUDE "memory_blocked_ram.ld" -INCLUDE "memory_scratch.ld" +/* Include memory regions used */ +INCLUDE "rp2_common/memory_flash.ld" +INCLUDE "platform/memory_blocked_ram.ld" +INCLUDE "platform/memory_scratch.ld" +/* Include aliases for storage memory regions */ +INCLUDE "rp2_common/memory_aliases_default.ld" + +/* Define entry point symbol */ ENTRY(_entry_point) -INCLUDE "sections_default.ld" +/* Include default sections */ +INCLUDE "rp2_common/sections_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld index 7b99a7745..6a1647d4a 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld @@ -1,7 +1 @@ -INCLUDE "memory_flash.ld" -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -ENTRY(_entry_point) - -INCLUDE "sections_copy_to_ram.ld" +INCLUDE "rp2_common/memmap_copy_to_ram.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_default.ld b/src/rp2_common/pico_crt0/rp2040/memmap_default.ld index 75fd340d5..8e2073718 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_default.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_default.ld @@ -1,7 +1 @@ -INCLUDE "memory_flash.ld" -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -ENTRY(_entry_point) - -INCLUDE "sections_default.ld" +INCLUDE "rp2_common/memmap_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld b/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld index cde630592..b8d1dcf36 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld @@ -1,6 +1 @@ -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -ENTRY(_entry_point) - -INCLUDE "sections_no_flash.ld" +INCLUDE "rp2_common/memmap_no_flash.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memory_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/platform/memory_blocked_ram.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/memory_blocked_ram.ld rename to src/rp2_common/pico_crt0/rp2040/platform/memory_blocked_ram.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memory_ram.ld b/src/rp2_common/pico_crt0/rp2040/platform/memory_ram.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/memory_ram.ld rename to src/rp2_common/pico_crt0/rp2040/platform/memory_ram.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memory_scratch.ld b/src/rp2_common/pico_crt0/rp2040/platform/memory_scratch.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/memory_scratch.ld rename to src/rp2_common/pico_crt0/rp2040/platform/memory_scratch.ld diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld new file mode 100644 index 000000000..661b4df00 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld @@ -0,0 +1,79 @@ +SECTIONS +{ + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + + *(.data*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM +} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_text.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_text.ld new file mode 100644 index 000000000..77a45941b --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_text.ld @@ -0,0 +1,101 @@ +SECTIONS +{ + /* Second stage bootloader is prepended to the image. It must be 256 bytes big + and checksummed. It is usually built by the boot_stage2 target + in the Raspberry Pi Pico SDK + */ + + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + .boot2 : { + __boot2_start__ = .; + KEEP (*(.boot2)) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ == 256, + "ERROR: Pico second stage bootloader must be 256 bytes in size") + + /* The second stage will always enter the image at the start of .text. + The debugger will use the ELF entry point, which is the _entry_point + symbol if present, otherwise defaults to start of .text. + This can be used to transfer control back to the bootrom on debugger + launches only, to perform proper flash setup. + */ + + .flashtext : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + } + + .rodata : { + /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); + + /* Vector table goes first in RAM, to avoid large alignment hole */ + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .text : { + __ram_text_start__ = .; + *(.init) + *(.text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + . = ALIGN(4); + __ram_text_end__ = .; + } > RAM AT> FLASH + __ram_text_source__ = LOADADDR(.text); + . = ALIGN(4); +} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld new file mode 100644 index 000000000..482c3fa5a --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld @@ -0,0 +1,70 @@ +SECTIONS +{ + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ + *(.text*) + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + + *(.data*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM +} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_default_text.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_default_text.ld new file mode 100644 index 000000000..7aa5c9399 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_default_text.ld @@ -0,0 +1,109 @@ +SECTIONS +{ + /* Second stage bootloader is prepended to the image. It must be 256 bytes big + and checksummed. It is usually built by the boot_stage2 target + in the Raspberry Pi Pico SDK + */ + + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + .boot2 : { + __boot2_start__ = .; + KEEP (*(.boot2)) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ == 256, + "ERROR: Pico second stage bootloader must be 256 bytes in size") + + /* The second stage will always enter the image at the start of .text. + The debugger will use the ELF entry point, which is the _entry_point + symbol if present, otherwise defaults to start of .text. + This can be used to transfer control back to the bootrom on debugger + launches only, to perform proper flash setup. + */ + + .text : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + /* TODO revisit this now memset/memcpy/float in ROM */ + /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from + * FLASH ... we will include any thing excluded here in .data below by default */ + *(.init) + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.eh_frame*) + . = ALIGN(4); + } > FLASH + + .rodata : { + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); +} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld new file mode 100644 index 000000000..a6634f74d --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld @@ -0,0 +1,79 @@ +SECTIONS +{ + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + *(.data*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM + PROVIDE(__data_end__ = .); + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM +} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_text.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_text.ld new file mode 100644 index 000000000..b4ad44ba7 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_text.ld @@ -0,0 +1,71 @@ +SECTIONS +{ + /* Note in NO_FLASH builds the entry point for both the bootrom, and debugger + entry (ELF entry point), are *first* in the image, and the vector table + follows immediately afterward. This is because the bootrom enters RAM + binaries directly at their lowest address (preferring main RAM over XIP + cache-as-SRAM if both are used). + */ + + .text : { + __logical_binary_start = .; + __reset_start = .; + KEEP (*(.reset)) + __reset_end = .; + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + . = ALIGN(256); + KEEP (*(.vectors)) + *(.text*) + . = ALIGN(4); + *(.init) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + } > RAM + + .rodata : { + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > RAM + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > RAM + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > RAM + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > RAM + __binary_info_end = .; + . = ALIGN(4); +} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_platform_end.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_platform_end.ld new file mode 100644 index 000000000..2d0165aa4 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_platform_end.ld @@ -0,0 +1,50 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld deleted file mode 100644 index 1777f6604..000000000 --- a/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld +++ /dev/null @@ -1,276 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .flashtext : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - } - - .rodata : { - /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - /* Vector table goes first in RAM, to avoid large alignment hole */ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .text : { - __ram_text_start__ = .; - *(.init) - *(.text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - . = ALIGN(4); - __ram_text_end__ = .; - } > RAM AT> FLASH - __ram_text_source__ = LOADADDR(.text); - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_crt0/rp2040/sections_default.ld b/src/rp2_common/pico_crt0/rp2040/sections_default.ld deleted file mode 100644 index 2e72b83b1..000000000 --- a/src/rp2_common/pico_crt0/rp2040/sections_default.ld +++ /dev/null @@ -1,275 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .text : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - /* TODO revisit this now memset/memcpy/float in ROM */ - /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from - * FLASH ... we will include any thing excluded here in .data below by default */ - *(.init) - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.eh_frame*) - . = ALIGN(4); - } > FLASH - - .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ - *(.text*) - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld b/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld deleted file mode 100644 index c71ee3b01..000000000 --- a/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld +++ /dev/null @@ -1,239 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - /* Note in NO_FLASH builds the entry point for both the bootrom, and debugger - entry (ELF entry point), are *first* in the image, and the vector table - follows immediately afterward. This is because the bootrom enters RAM - binaries directly at their lowest address (preferring main RAM over XIP - cache-as-SRAM if both are used). - */ - - .text : { - __logical_binary_start = .; - __reset_start = .; - KEEP (*(.reset)) - __reset_end = .; - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - . = ALIGN(256); - KEEP (*(.vectors)) - *(.time_critical*) - *(.text*) - . = ALIGN(4); - *(.init) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - } > RAM - - .rodata : { - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > RAM - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > RAM - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > RAM - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > RAM - __binary_info_end = .; - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM - PROVIDE(__data_end__ = .); - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld index 7b99a7745..6a1647d4a 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld @@ -1,7 +1 @@ -INCLUDE "memory_flash.ld" -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -ENTRY(_entry_point) - -INCLUDE "sections_copy_to_ram.ld" +INCLUDE "rp2_common/memmap_copy_to_ram.ld" diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld index 75fd340d5..8e2073718 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld @@ -1,7 +1 @@ -INCLUDE "memory_flash.ld" -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -ENTRY(_entry_point) - -INCLUDE "sections_default.ld" +INCLUDE "rp2_common/memmap_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld index cde630592..b8d1dcf36 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld @@ -1,6 +1 @@ -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -ENTRY(_entry_point) - -INCLUDE "sections_no_flash.ld" +INCLUDE "rp2_common/memmap_no_flash.ld" diff --git a/src/rp2_common/pico_crt0/rp2350/memory_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/memory_copy_to_ram.ld deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/rp2_common/pico_crt0/rp2350/memory_flash.ld b/src/rp2_common/pico_crt0/rp2350/memory_flash.ld deleted file mode 100644 index 669fe00e3..000000000 --- a/src/rp2_common/pico_crt0/rp2350/memory_flash.ld +++ /dev/null @@ -1,4 +0,0 @@ -MEMORY -{ - INCLUDE "pico_flash_region.ld" -} diff --git a/src/rp2_common/pico_crt0/rp2350/memory_ram.ld b/src/rp2_common/pico_crt0/rp2350/platform/memory_ram.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/memory_ram.ld rename to src/rp2_common/pico_crt0/rp2350/platform/memory_ram.ld diff --git a/src/rp2_common/pico_crt0/rp2350/memory_scratch.ld b/src/rp2_common/pico_crt0/rp2350/platform/memory_scratch.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/memory_scratch.ld rename to src/rp2_common/pico_crt0/rp2350/platform/memory_scratch.ld diff --git a/src/rp2_common/pico_crt0/rp2350/memory_xip_ram.ld b/src/rp2_common/pico_crt0/rp2350/platform/memory_xip_ram.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/memory_xip_ram.ld rename to src/rp2_common/pico_crt0/rp2350/platform/memory_xip_ram.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld new file mode 100644 index 000000000..19082589c --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld @@ -0,0 +1,83 @@ +SECTIONS +{ + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + . = ALIGN(4); + *(.rodata*) + *(.srodata*) + . = ALIGN(4); + + *(.data*) + *(.sdata*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) + . = ALIGN(4); + __bss_end__ = .; + } > RAM +} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_text.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_text.ld new file mode 100644 index 000000000..d35f7209e --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_text.ld @@ -0,0 +1,117 @@ +SECTIONS +{ + /* On Arm, the bootrom expects a VT at the start of the + image by default; on RISC-V, the default is to enter the image at its + lowest address, so an IMAGE_DEF item is required to specify the + nondefault entry point. */ + + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + /* The bootrom will enter the image at the point indicated in your + IMAGE_DEF, which is usually the reset handler of your vector table. + + The debugger will use the ELF entry point, which is the _entry_point + symbol, and in our case is *different from the bootrom's entry point.* + This is used to go back through the bootrom on debugger launches only, + to perform the same initial flash setup that would be performed on a + cold boot. + */ + + .flashtext : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + . = ALIGN(4); + } > FLASH + + /* Note the boot2 section is optional, and should be discarded if there is + no reference to it *inside* the binary, as it is not called by the + bootrom. (The bootrom performs a simple best-effort XIP setup and + leaves it to the binary to do anything more sophisticated.) However + there is still a size limit of 256 bytes, to ensure the boot2 can be + stored in boot RAM. + + Really this is a "XIP setup function" -- the name boot2 is historic and + refers to its dual-purpose on RP2040, where it also handled vectoring + from the bootrom into the user image. + */ + + .boot2 : { + __boot2_start__ = .; + *(.boot2) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ <= 256, + "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") + + .rodata : { + /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); + + /* Vector table goes first in RAM, to avoid large alignment hole */ + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .text : { + __ram_text_start__ = .; + *(.init) + *(.text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + . = ALIGN(4); + __ram_text_end__ = .; + } > RAM AT> FLASH + __ram_text_source__ = LOADADDR(.text); + . = ALIGN(4); +} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld new file mode 100644 index 000000000..9ffa5d163 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld @@ -0,0 +1,72 @@ +SECTIONS +{ + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ + *(.text*) + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + + *(.data*) + *(.sdata*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) + . = ALIGN(4); + __bss_end__ = .; + } > RAM +} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_default_text.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_default_text.ld new file mode 100644 index 000000000..fdd963321 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_default_text.ld @@ -0,0 +1,121 @@ +SECTIONS +{ + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + /* The bootrom will enter the image at the point indicated in your + IMAGE_DEF, which is usually the reset handler of your vector table. + + The debugger will use the ELF entry point, which is the _entry_point + symbol, and in our case is *different from the bootrom's entry point.* + This is used to go back through the bootrom on debugger launches only, + to perform the same initial flash setup that would be performed on a + cold boot. + */ + + .text : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + /* TODO revisit this now memset/memcpy/float in ROM */ + /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from + * FLASH ... we will include any thing excluded here in .data below by default */ + *(.init) + *libgcc.a:cmse_nonsecure_call.o + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.eh_frame*) + . = ALIGN(4); + } > FLASH + + /* Note the boot2 section is optional, and should be discarded if there is + no reference to it *inside* the binary, as it is not called by the + bootrom. (The bootrom performs a simple best-effort XIP setup and + leaves it to the binary to do anything more sophisticated.) However + there is still a size limit of 256 bytes, to ensure the boot2 can be + stored in boot RAM. + + Really this is a "XIP setup function" -- the name boot2 is historic and + refers to its dual-purpose on RP2040, where it also handled vectoring + from the bootrom into the user image. + */ + + .boot2 : { + __boot2_start__ = .; + *(.boot2) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ <= 256, + "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") + + .rodata : { + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) + *(.srodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); +} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld new file mode 100644 index 000000000..5658d8a4b --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld @@ -0,0 +1,82 @@ +SECTIONS +{ + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + *(.data*) + *(.sdata*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM + PROVIDE(__data_end__ = .); + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) + . = ALIGN(4); + __bss_end__ = .; + } > RAM +} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_text.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_text.ld new file mode 100644 index 000000000..833d8c42b --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_text.ld @@ -0,0 +1,73 @@ +SECTIONS +{ + /* Note unlike RP2040, we start the image with a vector table even for + NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the + image by default; on RISC-V, the default is to enter the image at its + lowest address, so an IMAGE_DEF item is required to specify the + nondefault entry point. */ + + .text : { + __logical_binary_start = .; + /* Vectors require 512-byte alignment on v8-M when >48 IRQs are used, + so we would waste RAM if the vector table were not at the + start. */ + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + __reset_start = .; + KEEP (*(.reset)) + __reset_end = .; + *(.text*) + . = ALIGN(4); + *(.init) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + } > RAM + + .rodata : { + . = ALIGN(4); + *(.rodata*) + *(.srodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > RAM + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > RAM + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > RAM + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > RAM + __binary_info_end = .; + . = ALIGN(4); +} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_platform_end.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_platform_end.ld new file mode 100644 index 000000000..43cc19ecd --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_platform_end.ld @@ -0,0 +1,7 @@ +SECTIONS +{ + ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") + ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") + + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld deleted file mode 100644 index 4b76bc04c..000000000 --- a/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld +++ /dev/null @@ -1,298 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - /* On Arm, the bootrom expects a VT at the start of the - image by default; on RISC-V, the default is to enter the image at its - lowest address, so an IMAGE_DEF item is required to specify the - nondefault entry point. */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - /* The bootrom will enter the image at the point indicated in your - IMAGE_DEF, which is usually the reset handler of your vector table. - - The debugger will use the ELF entry point, which is the _entry_point - symbol, and in our case is *different from the bootrom's entry point.* - This is used to go back through the bootrom on debugger launches only, - to perform the same initial flash setup that would be performed on a - cold boot. - */ - - .flashtext : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - . = ALIGN(4); - } > FLASH - - /* Note the boot2 section is optional, and should be discarded if there is - no reference to it *inside* the binary, as it is not called by the - bootrom. (The bootrom performs a simple best-effort XIP setup and - leaves it to the binary to do anything more sophisticated.) However - there is still a size limit of 256 bytes, to ensure the boot2 can be - stored in boot RAM. - - Really this is a "XIP setup function" -- the name boot2 is historic and - refers to its dual-purpose on RP2040, where it also handled vectoring - from the bootrom into the user image. - */ - - .boot2 : { - __boot2_start__ = .; - *(.boot2) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ <= 256, - "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") - - .rodata : { - /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - /* Vector table goes first in RAM, to avoid large alignment hole */ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .text : { - __ram_text_start__ = .; - *(.init) - *(.text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - . = ALIGN(4); - __ram_text_end__ = .; - } > RAM AT> FLASH - __ram_text_source__ = LOADADDR(.text); - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - . = ALIGN(4); - *(.rodata*) - *(.srodata*) - . = ALIGN(4); - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH =0xaa - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") - ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_crt0/rp2350/sections_default.ld b/src/rp2_common/pico_crt0/rp2350/sections_default.ld deleted file mode 100644 index eaeee2723..000000000 --- a/src/rp2_common/pico_crt0/rp2350/sections_default.ld +++ /dev/null @@ -1,291 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - /* The bootrom will enter the image at the point indicated in your - IMAGE_DEF, which is usually the reset handler of your vector table. - - The debugger will use the ELF entry point, which is the _entry_point - symbol, and in our case is *different from the bootrom's entry point.* - This is used to go back through the bootrom on debugger launches only, - to perform the same initial flash setup that would be performed on a - cold boot. - */ - - .text : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - /* TODO revisit this now memset/memcpy/float in ROM */ - /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from - * FLASH ... we will include any thing excluded here in .data below by default */ - *(.init) - *libgcc.a:cmse_nonsecure_call.o - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.eh_frame*) - . = ALIGN(4); - } > FLASH - - /* Note the boot2 section is optional, and should be discarded if there is - no reference to it *inside* the binary, as it is not called by the - bootrom. (The bootrom performs a simple best-effort XIP setup and - leaves it to the binary to do anything more sophisticated.) However - there is still a size limit of 256 bytes, to ensure the boot2 can be - stored in boot RAM. - - Really this is a "XIP setup function" -- the name boot2 is historic and - refers to its dual-purpose on RP2040, where it also handled vectoring - from the bootrom into the user image. - */ - - .boot2 : { - __boot2_start__ = .; - *(.boot2) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ <= 256, - "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") - - .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) - *(.srodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ - *(.text*) - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH =0xaa - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") - ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld deleted file mode 100644 index 595d69778..000000000 --- a/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld +++ /dev/null @@ -1,246 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - /* Note unlike RP2040, we start the image with a vector table even for - NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the - image by default; on RISC-V, the default is to enter the image at its - lowest address, so an IMAGE_DEF item is required to specify the - nondefault entry point. */ - - .text : { - __logical_binary_start = .; - /* Vectors require 512-byte alignment on v8-M when >48 IRQs are used, - so we would waste RAM if the vector table were not at the - start. */ - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - __reset_start = .; - KEEP (*(.reset)) - __reset_end = .; - *(.time_critical*) - *(.text*) - . = ALIGN(4); - *(.init) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - } > RAM - - .rodata : { - . = ALIGN(4); - *(.rodata*) - *(.srodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > RAM - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > RAM - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > RAM - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > RAM - __binary_info_end = .; - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM - PROVIDE(__data_end__ = .); - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") - ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index 5dd40909d..8fc240346 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -138,6 +138,7 @@ if (NOT TARGET pico_standard_link) # add include path for main linker script sections target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}") + target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_CURRENT_LIST_DIR}/scripts") # add variables set by pico_set_linker_script_var function target_link_options(pico_standard_link INTERFACE "LINKER:$,,>") diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld new file mode 100644 index 000000000..88127d894 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld @@ -0,0 +1,13 @@ +/* Include memory regions used */ +INCLUDE "rp2_common/memory_flash.ld" +INCLUDE "platform/memory_ram.ld" +INCLUDE "platform/memory_scratch.ld" + +/* Include aliases for storage memory regions */ +INCLUDE "rp2_common/memory_aliases_default.ld" + +/* Define entry point symbol */ +ENTRY(_entry_point) + +/* Include default sections */ +INCLUDE "rp2_common/sections_copy_to_ram.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld new file mode 100644 index 000000000..a8de400d9 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld @@ -0,0 +1,13 @@ +/* Include memory regions used */ +INCLUDE "rp2_common/memory_flash.ld" +INCLUDE "platform/memory_ram.ld" +INCLUDE "platform/memory_scratch.ld" + +/* Include aliases for storage memory regions */ +INCLUDE "rp2_common/memory_aliases_default.ld" + +/* Define entry point symbol */ +ENTRY(_entry_point) + +/* Include default sections */ +INCLUDE "rp2_common/sections_default.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld new file mode 100644 index 000000000..61ae84dc7 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld @@ -0,0 +1,12 @@ +/* Include memory regions used */ +INCLUDE "platform/memory_ram.ld" +INCLUDE "platform/memory_scratch.ld" + +/* Include aliases for no_flash storage memory regions (alias to themselves) */ +INCLUDE "rp2_common/memory_aliases_no_flash.ld" + +/* Define entry point symbol */ +ENTRY(_entry_point) + +/* Include no_flash sections */ +INCLUDE "rp2_common/sections_no_flash.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_default.ld new file mode 100644 index 000000000..7c56254bd --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_default.ld @@ -0,0 +1,3 @@ +REGION_ALIAS("RAM_STORE", FLASH); +REGION_ALIAS("SCRATCH_X_STORE", FLASH); +REGION_ALIAS("SCRATCH_Y_STORE", FLASH); diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_no_flash.ld new file mode 100644 index 000000000..063b5b6fc --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_no_flash.ld @@ -0,0 +1,3 @@ +REGION_ALIAS("RAM_STORE", RAM); +REGION_ALIAS("SCRATCH_X_STORE", SCRATCH_X); +REGION_ALIAS("SCRATCH_Y_STORE", SCRATCH_Y); diff --git a/src/rp2_common/pico_crt0/rp2040/memory_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_flash.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/memory_flash.ld rename to src/rp2_common/pico_standard_link/scripts/rp2_common/memory_flash.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_end.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_end.ld new file mode 100644 index 000000000..53d328174 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_end.ld @@ -0,0 +1,49 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_flash_end.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_flash_end.ld new file mode 100644 index 000000000..8591406ff --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_flash_end.ld @@ -0,0 +1,7 @@ +SECTIONS +{ + .flash_end : { + KEEP(*(.embedded_end_block*)) + PROVIDE(__flash_binary_end = .); + } > FLASH =0xaa +} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_heap.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_heap.ld new file mode 100644 index 000000000..1cc9e0de1 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_heap.ld @@ -0,0 +1,12 @@ +SECTIONS +{ + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); +} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_scratch.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_scratch.ld new file mode 100644 index 000000000..f61c39639 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_scratch.ld @@ -0,0 +1,37 @@ +SECTIONS +{ + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X AT> SCRATCH_X_STORE + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y AT> SCRATCH_Y_STORE + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y +} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld new file mode 100644 index 000000000..0017f385b --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld @@ -0,0 +1,7 @@ +INCLUDE "platform/section_copy_to_ram_text.ld" +INCLUDE "platform/section_copy_to_ram_data.ld" +INCLUDE "rp2_common/section_heap.ld" +INCLUDE "rp2_common/section_scratch.ld" +INCLUDE "rp2_common/section_flash_end.ld" +INCLUDE "rp2_common/section_end.ld" +INCLUDE "platform/section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld new file mode 100644 index 000000000..e0138db34 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld @@ -0,0 +1,7 @@ +INCLUDE "platform/section_default_text.ld" +INCLUDE "platform/section_default_data.ld" +INCLUDE "rp2_common/section_heap.ld" +INCLUDE "rp2_common/section_scratch.ld" +INCLUDE "rp2_common/section_flash_end.ld" +INCLUDE "rp2_common/section_end.ld" +INCLUDE "platform/section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld new file mode 100644 index 000000000..ebc062e6a --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld @@ -0,0 +1,6 @@ +INCLUDE "platform/section_no_flash_text.ld" +INCLUDE "platform/section_no_flash_data.ld" +INCLUDE "rp2_common/section_heap.ld" +INCLUDE "rp2_common/section_scratch.ld" +INCLUDE "rp2_common/section_end.ld" +INCLUDE "platform/section_platform_end.ld" diff --git a/test/kitchen_sink/memmap_custom.ld b/test/kitchen_sink/memmap_custom.ld index 081913e58..7fe2098f1 100644 --- a/test/kitchen_sink/memmap_custom.ld +++ b/test/kitchen_sink/memmap_custom.ld @@ -1,5 +1,6 @@ -INCLUDE "memory_flash.ld" -INCLUDE "memory_scratch.ld" +/* Include memory regions used */ +INCLUDE "rp2_common/memory_flash.ld" +INCLUDE "platform/memory_scratch.ld" /* Only use 128k of SRAM, starting at 0x20020000 */ MEMORY @@ -7,6 +8,11 @@ MEMORY RAM(rwx) : ORIGIN = 0x20020000, LENGTH = 128k } +/* Include aliases for storage memory regions */ +INCLUDE "rp2_common/memory_aliases_default.ld" + +/* Define entry point symbol */ ENTRY(_entry_point) -INCLUDE "sections_default.ld" +/* Include default sections */ +INCLUDE "rp2_common/sections_default.ld" From 4b1a3ec061db2394709e073c5f4659c27fea7def Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 2 Dec 2025 14:56:53 +0000 Subject: [PATCH 005/127] More de-duplication --- .../platform/section_copy_to_ram_data.ld | 79 ------------------- .../rp2040/platform/section_default_data.ld | 70 ---------------- .../rp2040/platform/section_no_flash_data.ld | 79 ------------------- .../rp2_common}/section_copy_to_ram_data.ld | 0 .../rp2_common}/section_default_data.ld | 0 .../rp2_common}/section_no_flash_data.ld | 0 .../rp2_common/sections_copy_to_ram.ld | 2 +- .../scripts/rp2_common/sections_default.ld | 2 +- .../scripts/rp2_common/sections_no_flash.ld | 2 +- 9 files changed, 3 insertions(+), 231 deletions(-) delete mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld rename src/rp2_common/{pico_crt0/rp2350/platform => pico_standard_link/scripts/rp2_common}/section_copy_to_ram_data.ld (100%) rename src/rp2_common/{pico_crt0/rp2350/platform => pico_standard_link/scripts/rp2_common}/section_default_data.ld (100%) rename src/rp2_common/{pico_crt0/rp2350/platform => pico_standard_link/scripts/rp2_common}/section_no_flash_data.ld (100%) diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld deleted file mode 100644 index 661b4df00..000000000 --- a/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld +++ /dev/null @@ -1,79 +0,0 @@ -SECTIONS -{ - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM -} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld deleted file mode 100644 index 482c3fa5a..000000000 --- a/src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld +++ /dev/null @@ -1,70 +0,0 @@ -SECTIONS -{ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ - *(.text*) - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM -} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld deleted file mode 100644 index a6634f74d..000000000 --- a/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld +++ /dev/null @@ -1,79 +0,0 @@ -SECTIONS -{ - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM - PROVIDE(__data_end__ = .); - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM -} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_copy_to_ram_data.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld rename to src/rp2_common/pico_standard_link/scripts/rp2_common/section_copy_to_ram_data.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_default_data.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld rename to src/rp2_common/pico_standard_link/scripts/rp2_common/section_default_data.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_no_flash_data.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld rename to src/rp2_common/pico_standard_link/scripts/rp2_common/section_no_flash_data.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld index 0017f385b..5e86d7c0c 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld @@ -1,5 +1,5 @@ INCLUDE "platform/section_copy_to_ram_text.ld" -INCLUDE "platform/section_copy_to_ram_data.ld" +INCLUDE "rp2_common/section_copy_to_ram_data.ld" INCLUDE "rp2_common/section_heap.ld" INCLUDE "rp2_common/section_scratch.ld" INCLUDE "rp2_common/section_flash_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld index e0138db34..558ec1848 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld @@ -1,5 +1,5 @@ INCLUDE "platform/section_default_text.ld" -INCLUDE "platform/section_default_data.ld" +INCLUDE "rp2_common/section_default_data.ld" INCLUDE "rp2_common/section_heap.ld" INCLUDE "rp2_common/section_scratch.ld" INCLUDE "rp2_common/section_flash_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld index ebc062e6a..b9b3973b2 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld @@ -1,5 +1,5 @@ INCLUDE "platform/section_no_flash_text.ld" -INCLUDE "platform/section_no_flash_data.ld" +INCLUDE "rp2_common/section_no_flash_data.ld" INCLUDE "rp2_common/section_heap.ld" INCLUDE "rp2_common/section_scratch.ld" INCLUDE "rp2_common/section_end.ld" From ae97a2294d6c26eb40fd8f5a92f5ee0906d3dbe3 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 2 Dec 2025 17:31:49 +0000 Subject: [PATCH 006/127] Make overriding ram locations simpler --- .../pico_crt0/rp2040/memmap_blocked_ram.ld | 15 +++------------ .../rp2040/platform/default_locations.ld | 8 ++++++++ .../rp2040/platform/memory_blocked_ram.ld | 4 ---- .../pico_crt0/rp2040/platform/memory_ram.ld | 4 ---- .../rp2040/platform/memory_scratch.ld | 5 ----- .../rp2350/platform/default_locations.ld | 8 ++++++++ .../pico_crt0/rp2350/platform/memory_ram.ld | 4 ---- .../rp2350/platform/memory_scratch.ld | 5 ----- .../rp2350/platform/memory_xip_ram.ld | 4 ---- .../scripts/rp2_common/memmap_copy_to_ram.ld | 7 +++++-- .../scripts/rp2_common/memmap_default.ld | 7 +++++-- .../scripts/rp2_common/memmap_no_flash.ld | 7 +++++-- .../scripts/rp2_common/memory_ram.ld | 4 ++++ .../scripts/rp2_common/memory_scratch.ld | 5 +++++ .../scripts/rp2_common/memory_xip_ram.ld | 4 ++++ test/kitchen_sink/CMakeLists.txt | 15 ++++++++------- test/kitchen_sink/memmap_custom.ld | 18 ------------------ 17 files changed, 55 insertions(+), 69 deletions(-) create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/platform/memory_blocked_ram.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/platform/memory_ram.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/platform/memory_scratch.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/platform/memory_ram.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/platform/memory_scratch.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/platform/memory_xip_ram.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memory_ram.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memory_scratch.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memory_xip_ram.ld delete mode 100644 test/kitchen_sink/memmap_custom.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld index 330e9bde3..a4a528950 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld @@ -1,13 +1,4 @@ -/* Include memory regions used */ -INCLUDE "rp2_common/memory_flash.ld" -INCLUDE "platform/memory_blocked_ram.ld" -INCLUDE "platform/memory_scratch.ld" +/* Use blocked ram */ +RAM_ORIGIN = 0x21000000; -/* Include aliases for storage memory regions */ -INCLUDE "rp2_common/memory_aliases_default.ld" - -/* Define entry point symbol */ -ENTRY(_entry_point) - -/* Include default sections */ -INCLUDE "rp2_common/sections_default.ld" +INCLUDE "memmap_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld b/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld new file mode 100644 index 000000000..684418b73 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld @@ -0,0 +1,8 @@ +RAM_ORIGIN = DEFINED(RAM_ORIGIN) ? RAM_ORIGIN : 0x20000000; +RAM_LENGTH = DEFINED(RAM_LENGTH) ? RAM_LENGTH : 256k; +SCRATCH_X_ORIGIN = DEFINED(SCRATCH_X_ORIGIN) ? SCRATCH_X_ORIGIN : 0x20040000; +SCRATCH_X_LENGTH = DEFINED(SCRATCH_X_LENGTH) ? SCRATCH_X_LENGTH : 4k; +SCRATCH_Y_ORIGIN = DEFINED(SCRATCH_Y_ORIGIN) ? SCRATCH_Y_ORIGIN : 0x20041000; +SCRATCH_Y_LENGTH = DEFINED(SCRATCH_Y_LENGTH) ? SCRATCH_Y_LENGTH : 4k; +XIP_RAM_ORIGIN = DEFINED(XIP_RAM_ORIGIN) ? XIP_RAM_ORIGIN : 0x15000000; +XIP_RAM_LENGTH = DEFINED(XIP_RAM_LENGTH) ? XIP_RAM_LENGTH : 16k; diff --git a/src/rp2_common/pico_crt0/rp2040/platform/memory_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/platform/memory_blocked_ram.ld deleted file mode 100644 index 57cbad6b7..000000000 --- a/src/rp2_common/pico_crt0/rp2040/platform/memory_blocked_ram.ld +++ /dev/null @@ -1,4 +0,0 @@ -MEMORY -{ - RAM(rwx) : ORIGIN = 0x21000000, LENGTH = 256k -} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/memory_ram.ld b/src/rp2_common/pico_crt0/rp2040/platform/memory_ram.ld deleted file mode 100644 index 1e1515dd3..000000000 --- a/src/rp2_common/pico_crt0/rp2040/platform/memory_ram.ld +++ /dev/null @@ -1,4 +0,0 @@ -MEMORY -{ - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k -} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/memory_scratch.ld b/src/rp2_common/pico_crt0/rp2040/platform/memory_scratch.ld deleted file mode 100644 index a4b982b92..000000000 --- a/src/rp2_common/pico_crt0/rp2040/platform/memory_scratch.ld +++ /dev/null @@ -1,5 +0,0 @@ -MEMORY -{ - SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k -} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld b/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld new file mode 100644 index 000000000..0b1611d40 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld @@ -0,0 +1,8 @@ +RAM_ORIGIN = DEFINED(RAM_ORIGIN) ? RAM_ORIGIN : 0x20000000; +RAM_LENGTH = DEFINED(RAM_LENGTH) ? RAM_LENGTH : 512k; +SCRATCH_X_ORIGIN = DEFINED(SCRATCH_X_ORIGIN) ? SCRATCH_X_ORIGIN : 0x20080000; +SCRATCH_X_LENGTH = DEFINED(SCRATCH_X_LENGTH) ? SCRATCH_X_LENGTH : 4k; +SCRATCH_Y_ORIGIN = DEFINED(SCRATCH_Y_ORIGIN) ? SCRATCH_Y_ORIGIN : 0x20081000; +SCRATCH_Y_LENGTH = DEFINED(SCRATCH_Y_LENGTH) ? SCRATCH_Y_LENGTH : 4k; +XIP_RAM_ORIGIN = DEFINED(XIP_RAM_ORIGIN) ? XIP_RAM_ORIGIN : 0x13FFC000; +XIP_RAM_LENGTH = DEFINED(XIP_RAM_LENGTH) ? XIP_RAM_LENGTH : 16k; diff --git a/src/rp2_common/pico_crt0/rp2350/platform/memory_ram.ld b/src/rp2_common/pico_crt0/rp2350/platform/memory_ram.ld deleted file mode 100644 index 434cdab97..000000000 --- a/src/rp2_common/pico_crt0/rp2350/platform/memory_ram.ld +++ /dev/null @@ -1,4 +0,0 @@ -MEMORY -{ - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k -} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/memory_scratch.ld b/src/rp2_common/pico_crt0/rp2350/platform/memory_scratch.ld deleted file mode 100644 index 246bbf050..000000000 --- a/src/rp2_common/pico_crt0/rp2350/platform/memory_scratch.ld +++ /dev/null @@ -1,5 +0,0 @@ -MEMORY -{ - SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k -} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/memory_xip_ram.ld b/src/rp2_common/pico_crt0/rp2350/platform/memory_xip_ram.ld deleted file mode 100644 index e94479b54..000000000 --- a/src/rp2_common/pico_crt0/rp2350/platform/memory_xip_ram.ld +++ /dev/null @@ -1,4 +0,0 @@ -MEMORY -{ - XIP_RAM(rwx) : ORIGIN = 0x13FFC000, LENGTH = 16k -} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld index 88127d894..12b7c85ab 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld @@ -1,7 +1,10 @@ +/* Include platform memory locations */ +INCLUDE "platform/default_locations.ld" + /* Include memory regions used */ INCLUDE "rp2_common/memory_flash.ld" -INCLUDE "platform/memory_ram.ld" -INCLUDE "platform/memory_scratch.ld" +INCLUDE "rp2_common/memory_ram.ld" +INCLUDE "rp2_common/memory_scratch.ld" /* Include aliases for storage memory regions */ INCLUDE "rp2_common/memory_aliases_default.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld index a8de400d9..6b1ccf827 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld @@ -1,7 +1,10 @@ +/* Include platform memory locations */ +INCLUDE "platform/default_locations.ld" + /* Include memory regions used */ INCLUDE "rp2_common/memory_flash.ld" -INCLUDE "platform/memory_ram.ld" -INCLUDE "platform/memory_scratch.ld" +INCLUDE "rp2_common/memory_ram.ld" +INCLUDE "rp2_common/memory_scratch.ld" /* Include aliases for storage memory regions */ INCLUDE "rp2_common/memory_aliases_default.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld index 61ae84dc7..8fb49e6bd 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld @@ -1,6 +1,9 @@ +/* Include platform memory locations */ +INCLUDE "platform/default_locations.ld" + /* Include memory regions used */ -INCLUDE "platform/memory_ram.ld" -INCLUDE "platform/memory_scratch.ld" +INCLUDE "rp2_common/memory_ram.ld" +INCLUDE "rp2_common/memory_scratch.ld" /* Include aliases for no_flash storage memory regions (alias to themselves) */ INCLUDE "rp2_common/memory_aliases_no_flash.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_ram.ld new file mode 100644 index 000000000..2b8a88a06 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_ram.ld @@ -0,0 +1,4 @@ +MEMORY +{ + RAM(rwx) : ORIGIN = RAM_ORIGIN, LENGTH = RAM_LENGTH +} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_scratch.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_scratch.ld new file mode 100644 index 000000000..7ba5d2172 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_scratch.ld @@ -0,0 +1,5 @@ +MEMORY +{ + SCRATCH_X(rwx) : ORIGIN = SCRATCH_X_ORIGIN, LENGTH = SCRATCH_X_LENGTH + SCRATCH_Y(rwx) : ORIGIN = SCRATCH_Y_ORIGIN, LENGTH = SCRATCH_Y_LENGTH +} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_xip_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_xip_ram.ld new file mode 100644 index 000000000..636e90137 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_xip_ram.ld @@ -0,0 +1,4 @@ +MEMORY +{ + XIP_RAM(rwx) : ORIGIN = XIP_RAM_ORIGIN, LENGTH = XIP_RAM_LENGTH +} diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt index 71b8a58b6..33e5fbc24 100644 --- a/test/kitchen_sink/CMakeLists.txt +++ b/test/kitchen_sink/CMakeLists.txt @@ -215,13 +215,14 @@ if (NOT KITCHEN_SINK_NO_BINARY_TYPE_VARIANTS) target_compile_definitions(kitchen_sink_blocked_ram PRIVATE KITCHEN_SINK_ID="blocked-ram binary") endif() - add_executable(kitchen_sink_memmap_custom ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) - # Have heap start from 0x20030000, and custom linker script - pico_set_linker_script(kitchen_sink_memmap_custom ${CMAKE_CURRENT_LIST_DIR}/memmap_custom.ld) - pico_set_linker_script_var(kitchen_sink_memmap_custom HEAP_LOC 0x20030000) - target_link_libraries(kitchen_sink_memmap_custom kitchen_sink_libs kitchen_sink_options) - pico_add_extra_outputs(kitchen_sink_memmap_custom) - target_compile_definitions(kitchen_sink_memmap_custom PRIVATE KITCHEN_SINK_ID="custom memmap binary") + add_executable(kitchen_sink_ram_custom ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) + # Have ram start from 0x20020000 length 128k, and heap start from 0x20030000 + pico_set_linker_script_var(kitchen_sink_ram_custom RAM_ORIGIN 0x20020000) + pico_set_linker_script_var(kitchen_sink_ram_custom RAM_LENGTH 128k) + pico_set_linker_script_var(kitchen_sink_ram_custom HEAP_LOC 0x20030000) + target_link_libraries(kitchen_sink_ram_custom kitchen_sink_libs kitchen_sink_options) + pico_add_extra_outputs(kitchen_sink_ram_custom) + target_compile_definitions(kitchen_sink_ram_custom PRIVATE KITCHEN_SINK_ID="custom ram binary") endif() add_executable(kitchen_sink_cpp ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_cpp.cpp) diff --git a/test/kitchen_sink/memmap_custom.ld b/test/kitchen_sink/memmap_custom.ld deleted file mode 100644 index 7fe2098f1..000000000 --- a/test/kitchen_sink/memmap_custom.ld +++ /dev/null @@ -1,18 +0,0 @@ -/* Include memory regions used */ -INCLUDE "rp2_common/memory_flash.ld" -INCLUDE "platform/memory_scratch.ld" - -/* Only use 128k of SRAM, starting at 0x20020000 */ -MEMORY -{ - RAM(rwx) : ORIGIN = 0x20020000, LENGTH = 128k -} - -/* Include aliases for storage memory regions */ -INCLUDE "rp2_common/memory_aliases_default.ld" - -/* Define entry point symbol */ -ENTRY(_entry_point) - -/* Include default sections */ -INCLUDE "rp2_common/sections_default.ld" From 3811e671d54c0198dad8b04f5249b36b8e9ddfd0 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 4 Dec 2025 10:14:26 +0000 Subject: [PATCH 007/127] Make it possible to reference default locations in pico_set_linker_script_var variables Means that CMake doesn't need to know the default memory addresses for different platforms --- .../rp2040/platform/default_locations.ld | 16 ++++++++-------- .../rp2350/platform/default_locations.ld | 16 ++++++++-------- src/rp2_common/pico_standard_link/CMakeLists.txt | 3 +++ .../scripts/rp2_common/memmap_copy_to_ram.ld | 2 +- .../scripts/rp2_common/memmap_default.ld | 2 +- .../scripts/rp2_common/memmap_no_flash.ld | 2 +- .../scripts/rp2_common/set_memory_locations.ld | 8 ++++++++ 7 files changed, 30 insertions(+), 19 deletions(-) create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/set_memory_locations.ld diff --git a/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld b/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld index 684418b73..03144ea07 100644 --- a/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld +++ b/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld @@ -1,8 +1,8 @@ -RAM_ORIGIN = DEFINED(RAM_ORIGIN) ? RAM_ORIGIN : 0x20000000; -RAM_LENGTH = DEFINED(RAM_LENGTH) ? RAM_LENGTH : 256k; -SCRATCH_X_ORIGIN = DEFINED(SCRATCH_X_ORIGIN) ? SCRATCH_X_ORIGIN : 0x20040000; -SCRATCH_X_LENGTH = DEFINED(SCRATCH_X_LENGTH) ? SCRATCH_X_LENGTH : 4k; -SCRATCH_Y_ORIGIN = DEFINED(SCRATCH_Y_ORIGIN) ? SCRATCH_Y_ORIGIN : 0x20041000; -SCRATCH_Y_LENGTH = DEFINED(SCRATCH_Y_LENGTH) ? SCRATCH_Y_LENGTH : 4k; -XIP_RAM_ORIGIN = DEFINED(XIP_RAM_ORIGIN) ? XIP_RAM_ORIGIN : 0x15000000; -XIP_RAM_LENGTH = DEFINED(XIP_RAM_LENGTH) ? XIP_RAM_LENGTH : 16k; +RAM_ORIGIN_DEFAULT = 0x20000000; +RAM_LENGTH_DEFAULT = 256k; +SCRATCH_X_ORIGIN_DEFAULT = 0x20040000; +SCRATCH_X_LENGTH_DEFAULT = 4k; +SCRATCH_Y_ORIGIN_DEFAULT = 0x20041000; +SCRATCH_Y_LENGTH_DEFAULT = 4k; +XIP_RAM_ORIGIN_DEFAULT = 0x15000000; +XIP_RAM_LENGTH_DEFAULT = 16k; diff --git a/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld b/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld index 0b1611d40..15ddc7374 100644 --- a/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld +++ b/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld @@ -1,8 +1,8 @@ -RAM_ORIGIN = DEFINED(RAM_ORIGIN) ? RAM_ORIGIN : 0x20000000; -RAM_LENGTH = DEFINED(RAM_LENGTH) ? RAM_LENGTH : 512k; -SCRATCH_X_ORIGIN = DEFINED(SCRATCH_X_ORIGIN) ? SCRATCH_X_ORIGIN : 0x20080000; -SCRATCH_X_LENGTH = DEFINED(SCRATCH_X_LENGTH) ? SCRATCH_X_LENGTH : 4k; -SCRATCH_Y_ORIGIN = DEFINED(SCRATCH_Y_ORIGIN) ? SCRATCH_Y_ORIGIN : 0x20081000; -SCRATCH_Y_LENGTH = DEFINED(SCRATCH_Y_LENGTH) ? SCRATCH_Y_LENGTH : 4k; -XIP_RAM_ORIGIN = DEFINED(XIP_RAM_ORIGIN) ? XIP_RAM_ORIGIN : 0x13FFC000; -XIP_RAM_LENGTH = DEFINED(XIP_RAM_LENGTH) ? XIP_RAM_LENGTH : 16k; +RAM_ORIGIN_DEFAULT = 0x20000000; +RAM_LENGTH_DEFAULT = 512k; +SCRATCH_X_ORIGIN_DEFAULT = 0x20080000; +SCRATCH_X_LENGTH_DEFAULT = 4k; +SCRATCH_Y_ORIGIN_DEFAULT = 0x20081000; +SCRATCH_Y_LENGTH_DEFAULT = 4k; +XIP_RAM_ORIGIN_DEFAULT = 0x13FFC000; +XIP_RAM_LENGTH_DEFAULT = 16k; diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index 8fc240346..69f5751ef 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -140,6 +140,9 @@ if (NOT TARGET pico_standard_link) target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}") target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_CURRENT_LIST_DIR}/scripts") + # add default locations script, so they can be referenced by pico_set_linker_script_var variables + target_link_options(pico_standard_link INTERFACE "LINKER:--script=${PICO_LINKER_SCRIPT_PATH}/platform/default_locations.ld") + # add variables set by pico_set_linker_script_var function target_link_options(pico_standard_link INTERFACE "LINKER:$,,>") diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld index 12b7c85ab..1cb8f7597 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld @@ -1,5 +1,5 @@ /* Include platform memory locations */ -INCLUDE "platform/default_locations.ld" +INCLUDE "rp2_common/set_memory_locations.ld" /* Include memory regions used */ INCLUDE "rp2_common/memory_flash.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld index 6b1ccf827..2c8f3ffa1 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld @@ -1,5 +1,5 @@ /* Include platform memory locations */ -INCLUDE "platform/default_locations.ld" +INCLUDE "rp2_common/set_memory_locations.ld" /* Include memory regions used */ INCLUDE "rp2_common/memory_flash.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld index 8fb49e6bd..2e3695ef9 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld @@ -1,5 +1,5 @@ /* Include platform memory locations */ -INCLUDE "platform/default_locations.ld" +INCLUDE "rp2_common/set_memory_locations.ld" /* Include memory regions used */ INCLUDE "rp2_common/memory_ram.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/set_memory_locations.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/set_memory_locations.ld new file mode 100644 index 000000000..a9110eb59 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/set_memory_locations.ld @@ -0,0 +1,8 @@ +RAM_ORIGIN = DEFINED(RAM_ORIGIN) ? RAM_ORIGIN : RAM_ORIGIN_DEFAULT; +RAM_LENGTH = DEFINED(RAM_LENGTH) ? RAM_LENGTH : RAM_LENGTH_DEFAULT; +SCRATCH_X_ORIGIN = DEFINED(SCRATCH_X_ORIGIN) ? SCRATCH_X_ORIGIN : SCRATCH_X_ORIGIN_DEFAULT; +SCRATCH_X_LENGTH = DEFINED(SCRATCH_X_LENGTH) ? SCRATCH_X_LENGTH : SCRATCH_X_LENGTH_DEFAULT; +SCRATCH_Y_ORIGIN = DEFINED(SCRATCH_Y_ORIGIN) ? SCRATCH_Y_ORIGIN : SCRATCH_Y_ORIGIN_DEFAULT; +SCRATCH_Y_LENGTH = DEFINED(SCRATCH_Y_LENGTH) ? SCRATCH_Y_LENGTH : SCRATCH_Y_LENGTH_DEFAULT; +XIP_RAM_ORIGIN = DEFINED(XIP_RAM_ORIGIN) ? XIP_RAM_ORIGIN : XIP_RAM_ORIGIN_DEFAULT; +XIP_RAM_LENGTH = DEFINED(XIP_RAM_LENGTH) ? XIP_RAM_LENGTH : XIP_RAM_LENGTH_DEFAULT; From a20f86a7e7bfa377bb4a8a28e8c8db9171f6efdd Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 11 Feb 2026 18:57:12 +0000 Subject: [PATCH 008/127] Add pico_add_linker_script_override_path to make overriding individual files easier Restructured so that it includes the platform-specific files before common ones, so common ones can be overridden --- .../pico_crt0/rp2040/memmap_blocked_ram.ld | 2 +- .../default_locations.ld | 0 .../section_copy_to_ram_text.ld | 0 .../section_default_text.ld | 0 .../section_no_flash_text.ld | 0 .../section_platform_end.ld | 0 .../default_locations.ld | 0 .../section_copy_to_ram_text.ld | 0 .../section_default_text.ld | 0 .../section_no_flash_text.ld | 0 .../section_platform_end.ld | 0 .../pico_standard_link/CMakeLists.txt | 27 ++++++++++++++++--- .../memory_aliases_default.ld | 0 .../memory_aliases_no_flash.ld | 0 .../scripts/{rp2_common => }/memory_flash.ld | 0 .../scripts/{rp2_common => }/memory_ram.ld | 0 .../{rp2_common => }/memory_scratch.ld | 0 .../{rp2_common => }/memory_xip_ram.ld | 0 .../scripts/rp2_common/memmap_copy_to_ram.ld | 12 ++++----- .../scripts/rp2_common/memmap_default.ld | 12 ++++----- .../scripts/rp2_common/memmap_no_flash.ld | 10 +++---- .../rp2_common/sections_copy_to_ram.ld | 7 ----- .../scripts/rp2_common/sections_default.ld | 7 ----- .../scripts/rp2_common/sections_no_flash.ld | 6 ----- .../section_copy_to_ram_data.ld | 0 .../{rp2_common => }/section_default_data.ld | 0 .../scripts/{rp2_common => }/section_end.ld | 0 .../{rp2_common => }/section_flash_end.ld | 0 .../scripts/{rp2_common => }/section_heap.ld | 0 .../{rp2_common => }/section_no_flash_data.ld | 0 .../{rp2_common => }/section_scratch.ld | 0 .../scripts/sections_copy_to_ram.ld | 7 +++++ .../scripts/sections_default.ld | 7 +++++ .../scripts/sections_no_flash.ld | 6 +++++ .../{rp2_common => }/set_memory_locations.ld | 0 test/kitchen_sink/CMakeLists.txt | 6 +++++ test/kitchen_sink/kitchen_sink.c | 12 +++++++++ .../sections_default.ld | 19 +++++++++++++ 38 files changed, 99 insertions(+), 41 deletions(-) rename src/rp2_common/pico_crt0/rp2040/{platform => scripts}/default_locations.ld (100%) rename src/rp2_common/pico_crt0/rp2040/{platform => scripts}/section_copy_to_ram_text.ld (100%) rename src/rp2_common/pico_crt0/rp2040/{platform => scripts}/section_default_text.ld (100%) rename src/rp2_common/pico_crt0/rp2040/{platform => scripts}/section_no_flash_text.ld (100%) rename src/rp2_common/pico_crt0/rp2040/{platform => scripts}/section_platform_end.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{platform => scripts}/default_locations.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{platform => scripts}/section_copy_to_ram_text.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{platform => scripts}/section_default_text.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{platform => scripts}/section_no_flash_text.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{platform => scripts}/section_platform_end.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memory_aliases_default.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memory_aliases_no_flash.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memory_flash.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memory_ram.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memory_scratch.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memory_xip_ram.ld (100%) delete mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_copy_to_ram_data.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_default_data.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_end.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_flash_end.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_heap.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_no_flash_data.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_scratch.ld (100%) create mode 100644 src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/sections_default.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/set_memory_locations.ld (100%) create mode 100644 test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld index a4a528950..15a98861d 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld @@ -1,4 +1,4 @@ /* Use blocked ram */ RAM_ORIGIN = 0x21000000; -INCLUDE "memmap_default.ld" +INCLUDE "rp2_common/memmap_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld b/src/rp2_common/pico_crt0/rp2040/scripts/default_locations.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld rename to src/rp2_common/pico_crt0/rp2040/scripts/default_locations.ld diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_text.ld b/src/rp2_common/pico_crt0/rp2040/scripts/section_copy_to_ram_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_text.ld rename to src/rp2_common/pico_crt0/rp2040/scripts/section_copy_to_ram_text.ld diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_default_text.ld b/src/rp2_common/pico_crt0/rp2040/scripts/section_default_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/platform/section_default_text.ld rename to src/rp2_common/pico_crt0/rp2040/scripts/section_default_text.ld diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_text.ld b/src/rp2_common/pico_crt0/rp2040/scripts/section_no_flash_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_text.ld rename to src/rp2_common/pico_crt0/rp2040/scripts/section_no_flash_text.ld diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_platform_end.ld b/src/rp2_common/pico_crt0/rp2040/scripts/section_platform_end.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/platform/section_platform_end.ld rename to src/rp2_common/pico_crt0/rp2040/scripts/section_platform_end.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld b/src/rp2_common/pico_crt0/rp2350/scripts/default_locations.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld rename to src/rp2_common/pico_crt0/rp2350/scripts/default_locations.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_text.ld b/src/rp2_common/pico_crt0/rp2350/scripts/section_copy_to_ram_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_text.ld rename to src/rp2_common/pico_crt0/rp2350/scripts/section_copy_to_ram_text.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_default_text.ld b/src/rp2_common/pico_crt0/rp2350/scripts/section_default_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/platform/section_default_text.ld rename to src/rp2_common/pico_crt0/rp2350/scripts/section_default_text.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_text.ld b/src/rp2_common/pico_crt0/rp2350/scripts/section_no_flash_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_text.ld rename to src/rp2_common/pico_crt0/rp2350/scripts/section_no_flash_text.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_platform_end.ld b/src/rp2_common/pico_crt0/rp2350/scripts/section_platform_end.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/platform/section_platform_end.ld rename to src/rp2_common/pico_crt0/rp2350/scripts/section_platform_end.ld diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index 69f5751ef..24978fe68 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -73,12 +73,33 @@ if (NOT TARGET pico_standard_link) # pico_set_linker_script_var(TARGET NAME VALUE) # \brief\ Set the linker script for the target # - # \param\ NAME Name of varAible to set + # \param\ NAME Name of variable to set # \param\ VALUE Value of variable to set function(pico_set_linker_script_var TARGET NAME VALUE) set_property(TARGET ${TARGET} APPEND PROPERTY PICO_TARGET_LINKER_SCRIPT_VARS "--defsym=${NAME}=${VALUE}") endfunction() + # pico_add_linker_script_override_path(TARGET PATH) + # \brief\ Add an override linker script path to the target + # + # This can be used to override default linker script files with custom versions. + # + # For example, to use custom files in ${CMAKE_CURRENT_LIST_DIR}/extra_scripts instead of the default ones, + # call pico_add_linker_script_override_path(TARGET ${CMAKE_CURRENT_LIST_DIR}/extra_scripts). This will + # include the custom files first, overriding the default ones. + # + # Must be called before target_link_libraries, otherwise it will not override the default linker scripts. + # + # \param\ TARGET The target to add the linker script override path to + # \param\ PATH The path containing the overriding linker scripts + function(pico_add_linker_script_override_path TARGET PATH) + get_target_property(OUT ${TARGET} LINK_LIBRARIES) + if (OUT) + message(WARNING "pico_add_linker_script_override_path does not work when called after target_link_libraries") + endif() + target_link_options(${TARGET} PRIVATE "LINKER:-L${PATH}") + endfunction() + # pico_set_binary_type(TARGET TYPE) # \brief\ Set the binary type for the target # @@ -137,11 +158,11 @@ if (NOT TARGET pico_standard_link) target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_BINARY_DIR}") # add include path for main linker script sections - target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}") + target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}/scripts") target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_CURRENT_LIST_DIR}/scripts") # add default locations script, so they can be referenced by pico_set_linker_script_var variables - target_link_options(pico_standard_link INTERFACE "LINKER:--script=${PICO_LINKER_SCRIPT_PATH}/platform/default_locations.ld") + target_link_options(pico_standard_link INTERFACE "LINKER:--script=${PICO_LINKER_SCRIPT_PATH}/scripts/default_locations.ld") # add variables set by pico_set_linker_script_var function target_link_options(pico_standard_link INTERFACE "LINKER:$,,>") diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_default.ld b/src/rp2_common/pico_standard_link/scripts/memory_aliases_default.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_default.ld rename to src/rp2_common/pico_standard_link/scripts/memory_aliases_default.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/memory_aliases_no_flash.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_no_flash.ld rename to src/rp2_common/pico_standard_link/scripts/memory_aliases_no_flash.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_flash.ld b/src/rp2_common/pico_standard_link/scripts/memory_flash.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memory_flash.ld rename to src/rp2_common/pico_standard_link/scripts/memory_flash.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_ram.ld b/src/rp2_common/pico_standard_link/scripts/memory_ram.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memory_ram.ld rename to src/rp2_common/pico_standard_link/scripts/memory_ram.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_scratch.ld b/src/rp2_common/pico_standard_link/scripts/memory_scratch.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memory_scratch.ld rename to src/rp2_common/pico_standard_link/scripts/memory_scratch.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_xip_ram.ld b/src/rp2_common/pico_standard_link/scripts/memory_xip_ram.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memory_xip_ram.ld rename to src/rp2_common/pico_standard_link/scripts/memory_xip_ram.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld index 1cb8f7597..eb2c5ffd9 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld @@ -1,16 +1,16 @@ /* Include platform memory locations */ -INCLUDE "rp2_common/set_memory_locations.ld" +INCLUDE "set_memory_locations.ld" /* Include memory regions used */ -INCLUDE "rp2_common/memory_flash.ld" -INCLUDE "rp2_common/memory_ram.ld" -INCLUDE "rp2_common/memory_scratch.ld" +INCLUDE "memory_flash.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" /* Include aliases for storage memory regions */ -INCLUDE "rp2_common/memory_aliases_default.ld" +INCLUDE "memory_aliases_default.ld" /* Define entry point symbol */ ENTRY(_entry_point) /* Include default sections */ -INCLUDE "rp2_common/sections_copy_to_ram.ld" +INCLUDE "sections_copy_to_ram.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld index 2c8f3ffa1..04acbefbb 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld @@ -1,16 +1,16 @@ /* Include platform memory locations */ -INCLUDE "rp2_common/set_memory_locations.ld" +INCLUDE "set_memory_locations.ld" /* Include memory regions used */ -INCLUDE "rp2_common/memory_flash.ld" -INCLUDE "rp2_common/memory_ram.ld" -INCLUDE "rp2_common/memory_scratch.ld" +INCLUDE "memory_flash.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" /* Include aliases for storage memory regions */ -INCLUDE "rp2_common/memory_aliases_default.ld" +INCLUDE "memory_aliases_default.ld" /* Define entry point symbol */ ENTRY(_entry_point) /* Include default sections */ -INCLUDE "rp2_common/sections_default.ld" +INCLUDE "sections_default.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld index 2e3695ef9..958915a71 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld @@ -1,15 +1,15 @@ /* Include platform memory locations */ -INCLUDE "rp2_common/set_memory_locations.ld" +INCLUDE "set_memory_locations.ld" /* Include memory regions used */ -INCLUDE "rp2_common/memory_ram.ld" -INCLUDE "rp2_common/memory_scratch.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" /* Include aliases for no_flash storage memory regions (alias to themselves) */ -INCLUDE "rp2_common/memory_aliases_no_flash.ld" +INCLUDE "memory_aliases_no_flash.ld" /* Define entry point symbol */ ENTRY(_entry_point) /* Include no_flash sections */ -INCLUDE "rp2_common/sections_no_flash.ld" +INCLUDE "sections_no_flash.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld deleted file mode 100644 index 5e86d7c0c..000000000 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld +++ /dev/null @@ -1,7 +0,0 @@ -INCLUDE "platform/section_copy_to_ram_text.ld" -INCLUDE "rp2_common/section_copy_to_ram_data.ld" -INCLUDE "rp2_common/section_heap.ld" -INCLUDE "rp2_common/section_scratch.ld" -INCLUDE "rp2_common/section_flash_end.ld" -INCLUDE "rp2_common/section_end.ld" -INCLUDE "platform/section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld deleted file mode 100644 index 558ec1848..000000000 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld +++ /dev/null @@ -1,7 +0,0 @@ -INCLUDE "platform/section_default_text.ld" -INCLUDE "rp2_common/section_default_data.ld" -INCLUDE "rp2_common/section_heap.ld" -INCLUDE "rp2_common/section_scratch.ld" -INCLUDE "rp2_common/section_flash_end.ld" -INCLUDE "rp2_common/section_end.ld" -INCLUDE "platform/section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld deleted file mode 100644 index b9b3973b2..000000000 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld +++ /dev/null @@ -1,6 +0,0 @@ -INCLUDE "platform/section_no_flash_text.ld" -INCLUDE "rp2_common/section_no_flash_data.ld" -INCLUDE "rp2_common/section_heap.ld" -INCLUDE "rp2_common/section_scratch.ld" -INCLUDE "rp2_common/section_end.ld" -INCLUDE "platform/section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_copy_to_ram_data.ld b/src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_data.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_copy_to_ram_data.ld rename to src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_data.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_default_data.ld b/src/rp2_common/pico_standard_link/scripts/section_default_data.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_default_data.ld rename to src/rp2_common/pico_standard_link/scripts/section_default_data.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_end.ld b/src/rp2_common/pico_standard_link/scripts/section_end.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_end.ld rename to src/rp2_common/pico_standard_link/scripts/section_end.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_flash_end.ld b/src/rp2_common/pico_standard_link/scripts/section_flash_end.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_flash_end.ld rename to src/rp2_common/pico_standard_link/scripts/section_flash_end.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_heap.ld b/src/rp2_common/pico_standard_link/scripts/section_heap.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_heap.ld rename to src/rp2_common/pico_standard_link/scripts/section_heap.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_no_flash_data.ld b/src/rp2_common/pico_standard_link/scripts/section_no_flash_data.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_no_flash_data.ld rename to src/rp2_common/pico_standard_link/scripts/section_no_flash_data.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_scratch.ld b/src/rp2_common/pico_standard_link/scripts/section_scratch.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_scratch.ld rename to src/rp2_common/pico_standard_link/scripts/section_scratch.ld diff --git a/src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld new file mode 100644 index 000000000..fe7caf546 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld @@ -0,0 +1,7 @@ +INCLUDE "section_copy_to_ram_text.ld" +INCLUDE "section_copy_to_ram_data.ld" +INCLUDE "section_heap.ld" +INCLUDE "section_scratch.ld" +INCLUDE "section_flash_end.ld" +INCLUDE "section_end.ld" +INCLUDE "section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/sections_default.ld b/src/rp2_common/pico_standard_link/scripts/sections_default.ld new file mode 100644 index 000000000..f22558a9f --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/sections_default.ld @@ -0,0 +1,7 @@ +INCLUDE "section_default_text.ld" +INCLUDE "section_default_data.ld" +INCLUDE "section_heap.ld" +INCLUDE "section_scratch.ld" +INCLUDE "section_flash_end.ld" +INCLUDE "section_end.ld" +INCLUDE "section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld new file mode 100644 index 000000000..77bad234e --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld @@ -0,0 +1,6 @@ +INCLUDE "section_no_flash_text.ld" +INCLUDE "section_no_flash_data.ld" +INCLUDE "section_heap.ld" +INCLUDE "section_scratch.ld" +INCLUDE "section_end.ld" +INCLUDE "section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/set_memory_locations.ld b/src/rp2_common/pico_standard_link/scripts/set_memory_locations.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/set_memory_locations.ld rename to src/rp2_common/pico_standard_link/scripts/set_memory_locations.ld diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt index 33e5fbc24..594f1b0a1 100644 --- a/test/kitchen_sink/CMakeLists.txt +++ b/test/kitchen_sink/CMakeLists.txt @@ -223,6 +223,12 @@ if (NOT KITCHEN_SINK_NO_BINARY_TYPE_VARIANTS) target_link_libraries(kitchen_sink_ram_custom kitchen_sink_libs kitchen_sink_options) pico_add_extra_outputs(kitchen_sink_ram_custom) target_compile_definitions(kitchen_sink_ram_custom PRIVATE KITCHEN_SINK_ID="custom ram binary") + + add_executable(kitchen_sink_ram_section ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) + pico_add_linker_script_override_path(kitchen_sink_ram_section ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_ram_section_scripts) + target_link_libraries(kitchen_sink_ram_section kitchen_sink_libs kitchen_sink_options) + pico_add_extra_outputs(kitchen_sink_ram_section) + target_compile_definitions(kitchen_sink_ram_section PRIVATE KITCHEN_SINK_ID="ram section binary" EXTRA_DATA_SECTION=1) endif() add_executable(kitchen_sink_cpp ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_cpp.cpp) diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index 7bc2bcd11..16c9a34b9 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -85,6 +85,18 @@ int main(void) { hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL)); hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL)); printf("%f\n", foox(1.3f, 2.6f)); +#ifdef EXTRA_DATA_SECTION + static int extra_data __attribute__((section(".extra_data"))) = 12345678; + printf("extra_data before load = %d\n", extra_data); + + extern uint32_t __extra_data_source__; + extern uint32_t __extra_data_start__; + extern uint32_t __extra_data_end__; + uint32_t stored_words = (uint32_t)(&__extra_data_end__ - &__extra_data_start__); + memcpy(&__extra_data_start__, &__extra_data_source__, 4 * stored_words); + + printf("extra_data after load = %d\n", extra_data); +#endif #ifndef __riscv // this should compile as we are Cortex M0+ pico_default_asm ("SVC #3"); diff --git a/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.ld b/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.ld new file mode 100644 index 000000000..9ffef1a28 --- /dev/null +++ b/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.ld @@ -0,0 +1,19 @@ +INCLUDE "section_default_text.ld" +INCLUDE "section_default_data.ld" + +SECTIONS +{ + .extra_data : { + __extra_data_start__ = .; + *(.extra_data*) + . = ALIGN(4); + __extra_data_end__ = .; + } > RAM AT> RAM_STORE + __extra_data_source__ = LOADADDR(.extra_data); +} + +INCLUDE "section_heap.ld" +INCLUDE "section_scratch.ld" +INCLUDE "section_flash_end.ld" +INCLUDE "section_end.ld" +INCLUDE "section_platform_end.ld" \ No newline at end of file From 6bd9e5b3210f6deff0d404c89ad109889b4f45c0 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 26 Feb 2026 11:58:34 +0000 Subject: [PATCH 009/127] Add simple overlay demo --- test/kitchen_sink/CMakeLists.txt | 9 +++++++ test/kitchen_sink/kitchen_sink.c | 24 +++++++++++++++++++ .../sections_default.ld | 24 +++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.ld diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt index 594f1b0a1..245e26904 100644 --- a/test/kitchen_sink/CMakeLists.txt +++ b/test/kitchen_sink/CMakeLists.txt @@ -229,6 +229,15 @@ if (NOT KITCHEN_SINK_NO_BINARY_TYPE_VARIANTS) target_link_libraries(kitchen_sink_ram_section kitchen_sink_libs kitchen_sink_options) pico_add_extra_outputs(kitchen_sink_ram_section) target_compile_definitions(kitchen_sink_ram_section PRIVATE KITCHEN_SINK_ID="ram section binary" EXTRA_DATA_SECTION=1) + + if (NOT PICO_C_COMPILER_IS_CLANG) + # Clang does not support overlay sections + add_executable(kitchen_sink_simple_overlay ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) + pico_add_linker_script_override_path(kitchen_sink_simple_overlay ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_simple_overlay_scripts) + target_link_libraries(kitchen_sink_simple_overlay kitchen_sink_libs kitchen_sink_options) + pico_add_extra_outputs(kitchen_sink_simple_overlay) + target_compile_definitions(kitchen_sink_simple_overlay PRIVATE KITCHEN_SINK_ID="simple overlay binary" EXTRA_DATA_SECTION=2) + endif() endif() add_executable(kitchen_sink_cpp ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_cpp.cpp) diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index 16c9a34b9..6a3a5fbee 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -86,6 +86,29 @@ int main(void) { hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL)); printf("%f\n", foox(1.3f, 2.6f)); #ifdef EXTRA_DATA_SECTION +#if EXTRA_DATA_SECTION > 1 + extern uint32_t __overlays_start__; + uint32_t stored_words; + + static int overlay_first __attribute__((section(".overlay_first"))) = 12345678; + printf("overlay_first before load = %d\n", overlay_first); + static int overlay_second_one __attribute__((section(".overlay_second"))) = 34567890; + static int overlay_second_two __attribute__((section(".overlay_second"))) = 56789012; + printf("overlay_second before load = %d, %d\n", overlay_second_one, overlay_second_two); + + extern uint32_t __load_start_overlay_second; + extern uint32_t __load_stop_overlay_second; + stored_words = (uint32_t)(&__load_stop_overlay_second - &__load_start_overlay_second); + memcpy(&__overlays_start__, &__load_start_overlay_second, 4 * stored_words); + printf("overlay_second after load = %d, %d\n", overlay_second_one, overlay_second_two); + + extern uint32_t __load_start_overlay_first; + extern uint32_t __load_stop_overlay_first; + stored_words = (uint32_t)(&__load_stop_overlay_first - &__load_start_overlay_first); + memcpy(&__overlays_start__, &__load_start_overlay_first, 4 * stored_words); + printf("overlay_first after load = %d\n", overlay_first); + printf("overlay_second after overlay_first load = %d, %d\n", overlay_second_one, overlay_second_two); +#else static int extra_data __attribute__((section(".extra_data"))) = 12345678; printf("extra_data before load = %d\n", extra_data); @@ -97,6 +120,7 @@ int main(void) { printf("extra_data after load = %d\n", extra_data); #endif +#endif #ifndef __riscv // this should compile as we are Cortex M0+ pico_default_asm ("SVC #3"); diff --git a/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.ld b/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.ld new file mode 100644 index 000000000..9a69c883a --- /dev/null +++ b/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.ld @@ -0,0 +1,24 @@ +INCLUDE "section_default_text.ld" +INCLUDE "section_default_data.ld" + +SECTIONS +{ + PROVIDE(__overlays_start__ = .); + OVERLAY : { + .overlay_first { + KEEP (*(.first*)) + . = ALIGN(4); + } + .overlay_second { + KEEP (*(.second*)) + . = ALIGN(4); + } + } > RAM AT> RAM_STORE + PROVIDE(__overlays_end__ = .); +} + +INCLUDE "section_heap.ld" +INCLUDE "section_scratch.ld" +INCLUDE "section_flash_end.ld" +INCLUDE "section_end.ld" +INCLUDE "section_platform_end.ld" From 2bf8555fd4a3549346624ab4c9ab67d47030cef8 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 27 Feb 2026 10:49:07 +0000 Subject: [PATCH 010/127] Add scripts to bazel build Use new include_linker_script_dir and use_linker_script_file functions to add the linker arguments --- bazel/util/pico_linker_scripts.bzl | 49 +++++++++++++++ src/rp2_common/pico_crt0/rp2040/BUILD.bazel | 46 +++++++++++--- .../pico_crt0/rp2040/scripts/BUILD.bazel | 31 ++++++++++ src/rp2_common/pico_crt0/rp2350/BUILD.bazel | 40 ++++++++++-- .../pico_crt0/rp2350/scripts/BUILD.bazel | 31 ++++++++++ .../pico_standard_link/scripts/BUILD.bazel | 61 +++++++++++++++++++ 6 files changed, 244 insertions(+), 14 deletions(-) create mode 100644 bazel/util/pico_linker_scripts.bzl create mode 100644 src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel create mode 100644 src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel create mode 100644 src/rp2_common/pico_standard_link/scripts/BUILD.bazel diff --git a/bazel/util/pico_linker_scripts.bzl b/bazel/util/pico_linker_scripts.bzl new file mode 100644 index 000000000..f453b0761 --- /dev/null +++ b/bazel/util/pico_linker_scripts.bzl @@ -0,0 +1,49 @@ +load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "use_cpp_toolchain") + +def _include_linker_script_dir_impl(ctx): + link_include_dir = str(ctx.label.package) + depset_direct = ["-L" + str(link_include_dir)] + if len(ctx.files.use_scripts): + for script in ctx.files.use_scripts: + depset_direct.append("-T" + str(script.path)) + + linking_inputs = cc_common.create_linker_input( + owner = ctx.label, + user_link_flags = depset( + direct = depset_direct, + ), + ) + return [ + CcInfo(linking_context = cc_common.create_linking_context(linker_inputs = depset(direct = [linking_inputs]))), + ] + +include_linker_script_dir = rule( + implementation = _include_linker_script_dir_impl, + attrs = { + "use_scripts": attr.label_list(allow_files = [".ld"]), + }, + toolchains = use_cpp_toolchain(), + fragments = ["cpp"], +) + +def _use_linker_script_file_impl(ctx): + link_file = ctx.file.script.path + + linking_inputs = cc_common.create_linker_input( + owner = ctx.label, + user_link_flags = depset( + direct = ["-T" + str(link_file)], + ), + ) + return [ + CcInfo(linking_context = cc_common.create_linking_context(linker_inputs = depset(direct = [linking_inputs]))), + ] + +use_linker_script_file = rule( + implementation = _use_linker_script_file_impl, + attrs = { + "script": attr.label(mandatory = True, allow_single_file = [".ld"]), + }, + toolchains = use_cpp_toolchain(), + fragments = ["cpp"], +) diff --git a/src/rp2_common/pico_crt0/rp2040/BUILD.bazel b/src/rp2_common/pico_crt0/rp2040/BUILD.bazel index 44912f0c8..77cd27297 100644 --- a/src/rp2_common/pico_crt0/rp2040/BUILD.bazel +++ b/src/rp2_common/pico_crt0/rp2040/BUILD.bazel @@ -2,6 +2,8 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library") package(default_visibility = ["//visibility:public"]) +load("//bazel/util:pico_linker_scripts.bzl", "use_linker_script_file") + exports_files( [ "memmap_blocked_ram.ld", @@ -11,6 +13,26 @@ exports_files( ], ) +use_linker_script_file( + name = "memmap_default_args", + script = "memmap_default.ld", +) + +use_linker_script_file( + name = "memmap_blocked_ram_args", + script = "memmap_blocked_ram.ld", +) + +use_linker_script_file( + name = "memmap_copy_to_ram_args", + script = "memmap_copy_to_ram.ld", +) + +use_linker_script_file( + name = "memmap_no_flash_args", + script = "memmap_no_flash.ld", +) + # It's possible to set linker scripts globally or on a per-binary basis. # # Setting globally: @@ -22,12 +44,14 @@ exports_files( # * Manually add your desired linker script to each cc_binary. cc_library( name = "default_linker_script", - linkopts = ["-T$(location memmap_default.ld)"], target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ - "memmap_default.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2040/scripts:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_default.ld", + "memmap_default_args", ], ) @@ -35,12 +59,14 @@ cc_library( cc_library( name = "blocked_ram_linker_script", defines = ["PICO_USE_BLOCKED_RAM=1"], - linkopts = ["-T$(location memmap_blocked_ram.ld)"], target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ - "memmap_blocked_ram.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2040/scripts:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_blocked_ram.ld", + "memmap_blocked_ram_args", ], ) @@ -48,12 +74,14 @@ cc_library( cc_library( name = "copy_to_ram_linker_script", defines = ["PICO_COPY_TO_RAM=1"], - linkopts = ["-T$(location memmap_copy_to_ram.ld)"], target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ - "memmap_copy_to_ram.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2040/scripts:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_copy_to_ram.ld", + "memmap_copy_to_ram_args", ], ) @@ -61,10 +89,12 @@ cc_library( cc_library( name = "no_flash_linker_script", defines = ["PICO_NO_FLASH=1"], - linkopts = ["-T$(location memmap_no_flash.ld)"], target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ - "memmap_no_flash.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2040/scripts:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", + "memmap_no_flash.ld", + "memmap_no_flash_args", ], ) diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel b/src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel new file mode 100644 index 000000000..492842565 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel @@ -0,0 +1,31 @@ +package(default_visibility = ["//visibility:public"]) + +load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") + +exports_files( + [ + "default_locations.ld", + "section_copy_to_ram_text.ld", + "section_default_text.ld", + "section_no_flash_text.ld", + "section_platform_end.ld", + ] +) + +include_linker_script_dir( + name = "rp2040_linker_script_args", + use_scripts = ["default_locations.ld"], +) + +cc_library( + name = "rp2040_linker_scripts", + target_compatible_with = ["//bazel/constraint:rp2040"], + deps = [ + "default_locations.ld", + "section_copy_to_ram_text.ld", + "section_default_text.ld", + "section_no_flash_text.ld", + "section_platform_end.ld", + "rp2040_linker_script_args", + ], +) \ No newline at end of file diff --git a/src/rp2_common/pico_crt0/rp2350/BUILD.bazel b/src/rp2_common/pico_crt0/rp2350/BUILD.bazel index b0f1ca7dd..aae30de87 100644 --- a/src/rp2_common/pico_crt0/rp2350/BUILD.bazel +++ b/src/rp2_common/pico_crt0/rp2350/BUILD.bazel @@ -2,6 +2,8 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library") package(default_visibility = ["//visibility:public"]) +load("//bazel/util:pico_linker_scripts.bzl", "use_linker_script_file") + exports_files( [ "memmap_copy_to_ram.ld", @@ -10,6 +12,26 @@ exports_files( ], ) +use_linker_script_file( + name = "memmap_default_args", + script = "memmap_default.ld", +) + +use_linker_script_file( + name = "memmap_blocked_ram_args", + script = "memmap_blocked_ram.ld", +) + +use_linker_script_file( + name = "memmap_copy_to_ram_args", + script = "memmap_copy_to_ram.ld", +) + +use_linker_script_file( + name = "memmap_no_flash_args", + script = "memmap_no_flash.ld", +) + # It's possible to set linker scripts globally or on a per-binary basis. # # Setting globally: @@ -21,12 +43,14 @@ exports_files( # * Manually add your desired linker script to each cc_binary. cc_library( name = "default_linker_script", - linkopts = ["-T$(location memmap_default.ld)"], target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ - "memmap_default.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2350/scripts:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_default.ld", + "memmap_default_args", ], ) @@ -34,12 +58,14 @@ cc_library( cc_library( name = "copy_to_ram_linker_script", defines = ["PICO_COPY_TO_RAM=1"], - linkopts = ["-T$(location memmap_copy_to_ram.ld)"], target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ - "memmap_copy_to_ram.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2350/scripts:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_copy_to_ram.ld", + "memmap_copy_to_ram_args", ], ) @@ -47,10 +73,12 @@ cc_library( cc_library( name = "no_flash_linker_script", defines = ["PICO_NO_FLASH=1"], - linkopts = ["-T$(location memmap_no_flash.ld)"], target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ - "memmap_no_flash.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2350/scripts:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", + "memmap_no_flash.ld", + "memmap_no_flash_args", ], ) diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel b/src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel new file mode 100644 index 000000000..9c9aa7329 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel @@ -0,0 +1,31 @@ +package(default_visibility = ["//visibility:public"]) + +load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") + +exports_files( + [ + "default_locations.ld", + "section_copy_to_ram_text.ld", + "section_default_text.ld", + "section_no_flash_text.ld", + "section_platform_end.ld", + ] +) + +include_linker_script_dir( + name = "rp2350_linker_script_args", + use_scripts = ["default_locations.ld"], +) + +cc_library( + name = "rp2350_linker_scripts", + target_compatible_with = ["//bazel/constraint:rp2350"], + deps = [ + "default_locations.ld", + "section_copy_to_ram_text.ld", + "section_default_text.ld", + "section_no_flash_text.ld", + "section_platform_end.ld", + "rp2350_linker_script_args", + ], +) \ No newline at end of file diff --git a/src/rp2_common/pico_standard_link/scripts/BUILD.bazel b/src/rp2_common/pico_standard_link/scripts/BUILD.bazel new file mode 100644 index 000000000..ac6239a11 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/BUILD.bazel @@ -0,0 +1,61 @@ +load("//bazel:defs.bzl", "compatible_with_rp2") +load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") + +package(default_visibility = ["//visibility:public"]) + +exports_files( + [ + "memory_aliases_default.ld", + "memory_aliases_no_flash.ld", + "memory_flash.ld", + "memory_ram.ld", + "memory_scratch.ld", + "memory_xip_ram.ld", + "section_copy_to_ram_data.ld", + "section_default_data.ld", + "section_end.ld", + "section_flash_end.ld", + "section_heap.ld", + "section_no_flash_data.ld", + "sections_copy_to_ram.ld", + "section_scratch.ld", + "sections_default.ld", + "sections_no_flash.ld", + "set_memory_locations.ld", + "rp2_common/memmap_default.ld", + "rp2_common/memmap_no_flash.ld", + "rp2_common/memmap_copy_to_ram.ld", + ] +) + +include_linker_script_dir( + name = "rp2_linker_script_args", +) + +cc_library( + name = "rp2_linker_scripts", + target_compatible_with = compatible_with_rp2(), + deps = [ + "rp2_linker_script_args", + "memory_aliases_default.ld", + "memory_aliases_no_flash.ld", + "memory_flash.ld", + "memory_ram.ld", + "memory_scratch.ld", + "memory_xip_ram.ld", + "section_copy_to_ram_data.ld", + "section_default_data.ld", + "section_end.ld", + "section_flash_end.ld", + "section_heap.ld", + "section_no_flash_data.ld", + "sections_copy_to_ram.ld", + "section_scratch.ld", + "sections_default.ld", + "sections_no_flash.ld", + "set_memory_locations.ld", + "rp2_common/memmap_default.ld", + "rp2_common/memmap_no_flash.ld", + "rp2_common/memmap_copy_to_ram.ld", + ], +) \ No newline at end of file From fe2d56b68fe9597a05abba9203585c2f7d7a30a1 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 6 Mar 2026 11:29:14 +0000 Subject: [PATCH 011/127] Move linker scripts out of crt0 Breaking change for Bazel builds using different binary types, instead of setting PICO_DEFAULT_LINKER_SCRIPT to eg `//src/rp2_common/pico_crt0:no_flash_linker_script` it is now `//src/rp2_common/pico_standard_link:no_flash_linker_script` --- bazel/config/BUILD.bazel | 4 +- src/cmake/rp2_common.cmake | 1 + .../pico_platform_link}/BUILD.bazel | 8 ++-- src/rp2040/pico_platform_link/CMakeLists.txt | 6 +++ .../pico_platform_link}/memmap_blocked_ram.ld | 0 .../pico_platform_link}/memmap_copy_to_ram.ld | 0 .../pico_platform_link}/memmap_default.ld | 0 .../pico_platform_link}/memmap_no_flash.ld | 0 .../pico_platform_link}/scripts/BUILD.bazel | 0 .../scripts/default_locations.ld | 0 .../scripts/section_copy_to_ram_text.ld | 0 .../scripts/section_default_text.ld | 0 .../scripts/section_no_flash_text.ld | 0 .../scripts/section_platform_end.ld | 0 .../pico_platform_link}/BUILD.bazel | 6 +-- src/rp2350/pico_platform_link/CMakeLists.txt | 6 +++ .../pico_platform_link}/memmap_copy_to_ram.ld | 0 .../pico_platform_link}/memmap_default.ld | 0 .../pico_platform_link}/memmap_no_flash.ld | 0 .../pico_platform_link}/scripts/BUILD.bazel | 0 .../scripts/default_locations.ld | 0 .../scripts/section_copy_to_ram_text.ld | 0 .../scripts/section_default_text.ld | 0 .../scripts/section_no_flash_text.ld | 0 .../scripts/section_platform_end.ld | 0 src/rp2_common/pico_crt0/BUILD.bazel | 37 +------------------ src/rp2_common/pico_crt0/CMakeLists.txt | 5 --- src/rp2_common/pico_standard_link/BUILD.bazel | 35 ++++++++++++++++++ 28 files changed, 58 insertions(+), 50 deletions(-) rename src/{rp2_common/pico_crt0/rp2040 => rp2040/pico_platform_link}/BUILD.bazel (91%) create mode 100644 src/rp2040/pico_platform_link/CMakeLists.txt rename src/{rp2_common/pico_crt0/rp2040 => rp2040/pico_platform_link}/memmap_blocked_ram.ld (100%) rename src/{rp2_common/pico_crt0/rp2040 => rp2040/pico_platform_link}/memmap_copy_to_ram.ld (100%) rename src/{rp2_common/pico_crt0/rp2040 => rp2040/pico_platform_link}/memmap_default.ld (100%) rename src/{rp2_common/pico_crt0/rp2040 => rp2040/pico_platform_link}/memmap_no_flash.ld (100%) rename src/{rp2_common/pico_crt0/rp2040 => rp2040/pico_platform_link}/scripts/BUILD.bazel (100%) rename src/{rp2_common/pico_crt0/rp2040 => rp2040/pico_platform_link}/scripts/default_locations.ld (100%) rename src/{rp2_common/pico_crt0/rp2040 => rp2040/pico_platform_link}/scripts/section_copy_to_ram_text.ld (100%) rename src/{rp2_common/pico_crt0/rp2040 => rp2040/pico_platform_link}/scripts/section_default_text.ld (100%) rename src/{rp2_common/pico_crt0/rp2040 => rp2040/pico_platform_link}/scripts/section_no_flash_text.ld (100%) rename src/{rp2_common/pico_crt0/rp2040 => rp2040/pico_platform_link}/scripts/section_platform_end.ld (100%) rename src/{rp2_common/pico_crt0/rp2350 => rp2350/pico_platform_link}/BUILD.bazel (91%) create mode 100644 src/rp2350/pico_platform_link/CMakeLists.txt rename src/{rp2_common/pico_crt0/rp2350 => rp2350/pico_platform_link}/memmap_copy_to_ram.ld (100%) rename src/{rp2_common/pico_crt0/rp2350 => rp2350/pico_platform_link}/memmap_default.ld (100%) rename src/{rp2_common/pico_crt0/rp2350 => rp2350/pico_platform_link}/memmap_no_flash.ld (100%) rename src/{rp2_common/pico_crt0/rp2350 => rp2350/pico_platform_link}/scripts/BUILD.bazel (100%) rename src/{rp2_common/pico_crt0/rp2350 => rp2350/pico_platform_link}/scripts/default_locations.ld (100%) rename src/{rp2_common/pico_crt0/rp2350 => rp2350/pico_platform_link}/scripts/section_copy_to_ram_text.ld (100%) rename src/{rp2_common/pico_crt0/rp2350 => rp2350/pico_platform_link}/scripts/section_default_text.ld (100%) rename src/{rp2_common/pico_crt0/rp2350 => rp2350/pico_platform_link}/scripts/section_no_flash_text.ld (100%) rename src/{rp2_common/pico_crt0/rp2350 => rp2350/pico_platform_link}/scripts/section_platform_end.ld (100%) diff --git a/bazel/config/BUILD.bazel b/bazel/config/BUILD.bazel index 84eac746e..6b5b1f7c8 100644 --- a/bazel/config/BUILD.bazel +++ b/bazel/config/BUILD.bazel @@ -217,10 +217,10 @@ string_flag( build_setting_default = "Debug", ) -# PICO_BAZEL_CONFIG: PICO_DEFAULT_LINKER_SCRIPT, [Bazel only] The library that provides a linker script to link into all binaries, default=//src/rp2_common/pico_crt0:default_linker_script, group=pico_standard_link +# PICO_BAZEL_CONFIG: PICO_DEFAULT_LINKER_SCRIPT, [Bazel only] The library that provides a linker script to link into all binaries, default=//src/rp2_common/pico_standard_link:default_linker_script, group=pico_standard_link label_flag( name = "PICO_DEFAULT_LINKER_SCRIPT", - build_setting_default = "//src/rp2_common/pico_crt0:default_linker_script", + build_setting_default = "//src/rp2_common/pico_standard_link:default_linker_script", ) # PICO_BAZEL_CONFIG: PICO_NO_TARGET_NAME, Don't define PICO_TARGET_NAME, type=bool, default=0, group=build diff --git a/src/cmake/rp2_common.cmake b/src/cmake/rp2_common.cmake index 273839f70..f608e5c05 100644 --- a/src/cmake/rp2_common.cmake +++ b/src/cmake/rp2_common.cmake @@ -28,6 +28,7 @@ pico_add_subdirectory(common/hardware_claim) # # RP2040/RP2350 specific From standard build variants pico_add_subdirectory(${RP2_VARIANT_DIR}/pico_platform) +pico_add_subdirectory(${RP2_VARIANT_DIR}/pico_platform_link) pico_add_subdirectory(${RP2_VARIANT_DIR}/hardware_regs) pico_add_subdirectory(${RP2_VARIANT_DIR}/hardware_structs) pico_add_subdirectory(${RP2_VARIANT_DIR}/boot_stage2) diff --git a/src/rp2_common/pico_crt0/rp2040/BUILD.bazel b/src/rp2040/pico_platform_link/BUILD.bazel similarity index 91% rename from src/rp2_common/pico_crt0/rp2040/BUILD.bazel rename to src/rp2040/pico_platform_link/BUILD.bazel index 77cd27297..34e0ff71b 100644 --- a/src/rp2_common/pico_crt0/rp2040/BUILD.bazel +++ b/src/rp2040/pico_platform_link/BUILD.bazel @@ -47,7 +47,7 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2_common/pico_crt0/rp2040/scripts:rp2040_linker_scripts", + "//src/rp2040/pico_platform_link/scripts:rp2040_linker_scripts", "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_default.ld", @@ -62,7 +62,7 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2_common/pico_crt0/rp2040/scripts:rp2040_linker_scripts", + "//src/rp2040/pico_platform_link/scripts:rp2040_linker_scripts", "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_blocked_ram.ld", @@ -77,7 +77,7 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2_common/pico_crt0/rp2040/scripts:rp2040_linker_scripts", + "//src/rp2040/pico_platform_link/scripts:rp2040_linker_scripts", "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_copy_to_ram.ld", @@ -92,7 +92,7 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2_common/pico_crt0/rp2040/scripts:rp2040_linker_scripts", + "//src/rp2040/pico_platform_link/scripts:rp2040_linker_scripts", "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "memmap_no_flash.ld", "memmap_no_flash_args", diff --git a/src/rp2040/pico_platform_link/CMakeLists.txt b/src/rp2040/pico_platform_link/CMakeLists.txt new file mode 100644 index 000000000..af6943ebd --- /dev/null +++ b/src/rp2040/pico_platform_link/CMakeLists.txt @@ -0,0 +1,6 @@ +pico_register_common_scope_var(PICO_LINKER_SCRIPT_PATH) +if (NOT PICO_LINKER_SCRIPT_PATH) + set(PICO_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_LIST_DIR}) +endif() + +pico_promote_common_scope_vars() \ No newline at end of file diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld b/src/rp2040/pico_platform_link/memmap_blocked_ram.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld rename to src/rp2040/pico_platform_link/memmap_blocked_ram.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld b/src/rp2040/pico_platform_link/memmap_copy_to_ram.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld rename to src/rp2040/pico_platform_link/memmap_copy_to_ram.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_default.ld b/src/rp2040/pico_platform_link/memmap_default.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/memmap_default.ld rename to src/rp2040/pico_platform_link/memmap_default.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld b/src/rp2040/pico_platform_link/memmap_no_flash.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld rename to src/rp2040/pico_platform_link/memmap_no_flash.ld diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel b/src/rp2040/pico_platform_link/scripts/BUILD.bazel similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel rename to src/rp2040/pico_platform_link/scripts/BUILD.bazel diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/default_locations.ld b/src/rp2040/pico_platform_link/scripts/default_locations.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/scripts/default_locations.ld rename to src/rp2040/pico_platform_link/scripts/default_locations.ld diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/section_copy_to_ram_text.ld b/src/rp2040/pico_platform_link/scripts/section_copy_to_ram_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/scripts/section_copy_to_ram_text.ld rename to src/rp2040/pico_platform_link/scripts/section_copy_to_ram_text.ld diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/section_default_text.ld b/src/rp2040/pico_platform_link/scripts/section_default_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/scripts/section_default_text.ld rename to src/rp2040/pico_platform_link/scripts/section_default_text.ld diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/section_no_flash_text.ld b/src/rp2040/pico_platform_link/scripts/section_no_flash_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/scripts/section_no_flash_text.ld rename to src/rp2040/pico_platform_link/scripts/section_no_flash_text.ld diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/section_platform_end.ld b/src/rp2040/pico_platform_link/scripts/section_platform_end.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/scripts/section_platform_end.ld rename to src/rp2040/pico_platform_link/scripts/section_platform_end.ld diff --git a/src/rp2_common/pico_crt0/rp2350/BUILD.bazel b/src/rp2350/pico_platform_link/BUILD.bazel similarity index 91% rename from src/rp2_common/pico_crt0/rp2350/BUILD.bazel rename to src/rp2350/pico_platform_link/BUILD.bazel index aae30de87..0b630064f 100644 --- a/src/rp2_common/pico_crt0/rp2350/BUILD.bazel +++ b/src/rp2350/pico_platform_link/BUILD.bazel @@ -46,7 +46,7 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2_common/pico_crt0/rp2350/scripts:rp2350_linker_scripts", + "//src/rp2350/pico_platform_link/scripts:rp2350_linker_scripts", "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_default.ld", @@ -61,7 +61,7 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2_common/pico_crt0/rp2350/scripts:rp2350_linker_scripts", + "//src/rp2350/pico_platform_link/scripts:rp2350_linker_scripts", "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_copy_to_ram.ld", @@ -76,7 +76,7 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2_common/pico_crt0/rp2350/scripts:rp2350_linker_scripts", + "//src/rp2350/pico_platform_link/scripts:rp2350_linker_scripts", "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "memmap_no_flash.ld", "memmap_no_flash_args", diff --git a/src/rp2350/pico_platform_link/CMakeLists.txt b/src/rp2350/pico_platform_link/CMakeLists.txt new file mode 100644 index 000000000..af6943ebd --- /dev/null +++ b/src/rp2350/pico_platform_link/CMakeLists.txt @@ -0,0 +1,6 @@ +pico_register_common_scope_var(PICO_LINKER_SCRIPT_PATH) +if (NOT PICO_LINKER_SCRIPT_PATH) + set(PICO_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_LIST_DIR}) +endif() + +pico_promote_common_scope_vars() \ No newline at end of file diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld b/src/rp2350/pico_platform_link/memmap_copy_to_ram.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld rename to src/rp2350/pico_platform_link/memmap_copy_to_ram.ld diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld b/src/rp2350/pico_platform_link/memmap_default.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/memmap_default.ld rename to src/rp2350/pico_platform_link/memmap_default.ld diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld b/src/rp2350/pico_platform_link/memmap_no_flash.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld rename to src/rp2350/pico_platform_link/memmap_no_flash.ld diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel b/src/rp2350/pico_platform_link/scripts/BUILD.bazel similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel rename to src/rp2350/pico_platform_link/scripts/BUILD.bazel diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/default_locations.ld b/src/rp2350/pico_platform_link/scripts/default_locations.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/scripts/default_locations.ld rename to src/rp2350/pico_platform_link/scripts/default_locations.ld diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/section_copy_to_ram_text.ld b/src/rp2350/pico_platform_link/scripts/section_copy_to_ram_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/scripts/section_copy_to_ram_text.ld rename to src/rp2350/pico_platform_link/scripts/section_copy_to_ram_text.ld diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/section_default_text.ld b/src/rp2350/pico_platform_link/scripts/section_default_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/scripts/section_default_text.ld rename to src/rp2350/pico_platform_link/scripts/section_default_text.ld diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/section_no_flash_text.ld b/src/rp2350/pico_platform_link/scripts/section_no_flash_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/scripts/section_no_flash_text.ld rename to src/rp2350/pico_platform_link/scripts/section_no_flash_text.ld diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/section_platform_end.ld b/src/rp2350/pico_platform_link/scripts/section_platform_end.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/scripts/section_platform_end.ld rename to src/rp2350/pico_platform_link/scripts/section_platform_end.ld diff --git a/src/rp2_common/pico_crt0/BUILD.bazel b/src/rp2_common/pico_crt0/BUILD.bazel index b47b9c6cf..99c9244bd 100644 --- a/src/rp2_common/pico_crt0/BUILD.bazel +++ b/src/rp2_common/pico_crt0/BUILD.bazel @@ -3,48 +3,13 @@ load("//bazel:defs.bzl", "compatible_with_rp2") package(default_visibility = ["//visibility:public"]) -alias( - name = "default_linker_script", - actual = select({ - "//bazel/constraint:rp2040": "//src/rp2_common/pico_crt0/rp2040:default_linker_script", - "//bazel/constraint:rp2350": "//src/rp2_common/pico_crt0/rp2350:default_linker_script", - "//conditions:default": "//bazel:incompatible_cc_lib", - }), -) - -alias( - name = "blocked_ram_linker_script", - actual = select({ - "//bazel/constraint:rp2040": "//src/rp2_common/pico_crt0/rp2040:blocked_ram_linker_script", - "//conditions:default": "//bazel:incompatible_cc_lib", - }), -) - -alias( - name = "copy_to_ram_linker_script", - actual = select({ - "//bazel/constraint:rp2040": "//src/rp2_common/pico_crt0/rp2040:copy_to_ram_linker_script", - "//bazel/constraint:rp2350": "//src/rp2_common/pico_crt0/rp2350:copy_to_ram_linker_script", - "//conditions:default": "//bazel:incompatible_cc_lib", - }), -) - -alias( - name = "no_flash_linker_script", - actual = select({ - "//bazel/constraint:rp2040": "//src/rp2_common/pico_crt0/rp2040:no_flash_linker_script", - "//bazel/constraint:rp2350": "//src/rp2_common/pico_crt0/rp2350:no_flash_linker_script", - "//conditions:default": "//bazel:incompatible_cc_lib", - }), -) - cc_library( name = "no_warn_rwx_flag", linkopts = select({ "//bazel/constraint:pico_toolchain_gcc_enabled": ["-Wl,--no-warn-rwx-segments"], "//conditions:default": [], }), - visibility = [":__subpackages__"], + visibility = ["//src:__subpackages__"], ) cc_library( diff --git a/src/rp2_common/pico_crt0/CMakeLists.txt b/src/rp2_common/pico_crt0/CMakeLists.txt index bd4156932..1bbbac742 100644 --- a/src/rp2_common/pico_crt0/CMakeLists.txt +++ b/src/rp2_common/pico_crt0/CMakeLists.txt @@ -11,9 +11,4 @@ if (NOT TARGET pico_crt0) target_link_libraries(pico_crt0 INTERFACE boot_picobin_headers pico_bootrom_headers) endif() -pico_register_common_scope_var(PICO_LINKER_SCRIPT_PATH) -if (NOT PICO_LINKER_SCRIPT_PATH) - set(PICO_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_LIST_DIR}/${PICO_CHIP}) -endif() - pico_promote_common_scope_vars() \ No newline at end of file diff --git a/src/rp2_common/pico_standard_link/BUILD.bazel b/src/rp2_common/pico_standard_link/BUILD.bazel index 4c8ff249a..6c84336bf 100644 --- a/src/rp2_common/pico_standard_link/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/BUILD.bazel @@ -18,6 +18,41 @@ generated_pico_flash_region( }), ) +alias( + name = "default_linker_script", + actual = select({ + "//bazel/constraint:rp2040": "//src/rp2040/pico_platform_link:default_linker_script", + "//bazel/constraint:rp2350": "//src/rp2350/pico_platform_link:default_linker_script", + "//conditions:default": "//bazel:incompatible_cc_lib", + }), +) + +alias( + name = "blocked_ram_linker_script", + actual = select({ + "//bazel/constraint:rp2040": "//src/rp2040/pico_platform_link:blocked_ram_linker_script", + "//conditions:default": "//bazel:incompatible_cc_lib", + }), +) + +alias( + name = "copy_to_ram_linker_script", + actual = select({ + "//bazel/constraint:rp2040": "//src/rp2040/pico_platform_link:copy_to_ram_linker_script", + "//bazel/constraint:rp2350": "//src/rp2350/pico_platform_link:copy_to_ram_linker_script", + "//conditions:default": "//bazel:incompatible_cc_lib", + }), +) + +alias( + name = "no_flash_linker_script", + actual = select({ + "//bazel/constraint:rp2040": "//src/rp2040/pico_platform_link:no_flash_linker_script", + "//bazel/constraint:rp2350": "//src/rp2350/pico_platform_link:no_flash_linker_script", + "//conditions:default": "//bazel:incompatible_cc_lib", + }), +) + cc_library( name = "pico_standard_link", target_compatible_with = compatible_with_rp2(), From 1bd7089eb4c395b48bf5293899ad7901306c957b Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 6 Mar 2026 11:43:57 +0000 Subject: [PATCH 012/127] Make rp2350 text sections the default Treat rp2040 layout (boot2 instead of embedded blocks) as the outlier --- .../pico_platform_link/memmap_blocked_ram.ld | 2 +- .../pico_platform_link/memmap_copy_to_ram.ld | 2 +- .../pico_platform_link/memmap_default.ld | 2 +- .../pico_platform_link/memmap_no_flash.ld | 2 +- .../pico_platform_link/memmap_copy_to_ram.ld | 2 +- .../pico_platform_link/memmap_default.ld | 2 +- .../pico_platform_link/memmap_no_flash.ld | 2 +- .../pico_platform_link/scripts/BUILD.bazel | 6 ------ .../pico_standard_link/scripts/BUILD.bazel | 18 ++++++++++++------ .../{rp2_common => }/memmap_copy_to_ram.ld | 0 .../scripts/{rp2_common => }/memmap_default.ld | 0 .../{rp2_common => }/memmap_no_flash.ld | 0 .../scripts/section_copy_to_ram_text.ld | 0 .../scripts/section_default_text.ld | 0 .../scripts/section_no_flash_text.ld | 0 15 files changed, 19 insertions(+), 19 deletions(-) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memmap_copy_to_ram.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memmap_default.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memmap_no_flash.ld (100%) rename src/{rp2350/pico_platform_link => rp2_common/pico_standard_link}/scripts/section_copy_to_ram_text.ld (100%) rename src/{rp2350/pico_platform_link => rp2_common/pico_standard_link}/scripts/section_default_text.ld (100%) rename src/{rp2350/pico_platform_link => rp2_common/pico_standard_link}/scripts/section_no_flash_text.ld (100%) diff --git a/src/rp2040/pico_platform_link/memmap_blocked_ram.ld b/src/rp2040/pico_platform_link/memmap_blocked_ram.ld index 15a98861d..a4a528950 100644 --- a/src/rp2040/pico_platform_link/memmap_blocked_ram.ld +++ b/src/rp2040/pico_platform_link/memmap_blocked_ram.ld @@ -1,4 +1,4 @@ /* Use blocked ram */ RAM_ORIGIN = 0x21000000; -INCLUDE "rp2_common/memmap_default.ld" +INCLUDE "memmap_default.ld" diff --git a/src/rp2040/pico_platform_link/memmap_copy_to_ram.ld b/src/rp2040/pico_platform_link/memmap_copy_to_ram.ld index 6a1647d4a..cd51ceeaa 100644 --- a/src/rp2040/pico_platform_link/memmap_copy_to_ram.ld +++ b/src/rp2040/pico_platform_link/memmap_copy_to_ram.ld @@ -1 +1 @@ -INCLUDE "rp2_common/memmap_copy_to_ram.ld" +INCLUDE "memmap_copy_to_ram.ld" diff --git a/src/rp2040/pico_platform_link/memmap_default.ld b/src/rp2040/pico_platform_link/memmap_default.ld index 8e2073718..c256a9071 100644 --- a/src/rp2040/pico_platform_link/memmap_default.ld +++ b/src/rp2040/pico_platform_link/memmap_default.ld @@ -1 +1 @@ -INCLUDE "rp2_common/memmap_default.ld" +INCLUDE "memmap_default.ld" diff --git a/src/rp2040/pico_platform_link/memmap_no_flash.ld b/src/rp2040/pico_platform_link/memmap_no_flash.ld index b8d1dcf36..3e5be9e01 100644 --- a/src/rp2040/pico_platform_link/memmap_no_flash.ld +++ b/src/rp2040/pico_platform_link/memmap_no_flash.ld @@ -1 +1 @@ -INCLUDE "rp2_common/memmap_no_flash.ld" +INCLUDE "memmap_no_flash.ld" diff --git a/src/rp2350/pico_platform_link/memmap_copy_to_ram.ld b/src/rp2350/pico_platform_link/memmap_copy_to_ram.ld index 6a1647d4a..cd51ceeaa 100644 --- a/src/rp2350/pico_platform_link/memmap_copy_to_ram.ld +++ b/src/rp2350/pico_platform_link/memmap_copy_to_ram.ld @@ -1 +1 @@ -INCLUDE "rp2_common/memmap_copy_to_ram.ld" +INCLUDE "memmap_copy_to_ram.ld" diff --git a/src/rp2350/pico_platform_link/memmap_default.ld b/src/rp2350/pico_platform_link/memmap_default.ld index 8e2073718..c256a9071 100644 --- a/src/rp2350/pico_platform_link/memmap_default.ld +++ b/src/rp2350/pico_platform_link/memmap_default.ld @@ -1 +1 @@ -INCLUDE "rp2_common/memmap_default.ld" +INCLUDE "memmap_default.ld" diff --git a/src/rp2350/pico_platform_link/memmap_no_flash.ld b/src/rp2350/pico_platform_link/memmap_no_flash.ld index b8d1dcf36..3e5be9e01 100644 --- a/src/rp2350/pico_platform_link/memmap_no_flash.ld +++ b/src/rp2350/pico_platform_link/memmap_no_flash.ld @@ -1 +1 @@ -INCLUDE "rp2_common/memmap_no_flash.ld" +INCLUDE "memmap_no_flash.ld" diff --git a/src/rp2350/pico_platform_link/scripts/BUILD.bazel b/src/rp2350/pico_platform_link/scripts/BUILD.bazel index 9c9aa7329..5161b096b 100644 --- a/src/rp2350/pico_platform_link/scripts/BUILD.bazel +++ b/src/rp2350/pico_platform_link/scripts/BUILD.bazel @@ -5,9 +5,6 @@ load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") exports_files( [ "default_locations.ld", - "section_copy_to_ram_text.ld", - "section_default_text.ld", - "section_no_flash_text.ld", "section_platform_end.ld", ] ) @@ -22,9 +19,6 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ "default_locations.ld", - "section_copy_to_ram_text.ld", - "section_default_text.ld", - "section_no_flash_text.ld", "section_platform_end.ld", "rp2350_linker_script_args", ], diff --git a/src/rp2_common/pico_standard_link/scripts/BUILD.bazel b/src/rp2_common/pico_standard_link/scripts/BUILD.bazel index ac6239a11..b0e51da98 100644 --- a/src/rp2_common/pico_standard_link/scripts/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/scripts/BUILD.bazel @@ -12,19 +12,22 @@ exports_files( "memory_scratch.ld", "memory_xip_ram.ld", "section_copy_to_ram_data.ld", + "section_copy_to_ram_text.ld", "section_default_data.ld", + "section_default_text.ld", "section_end.ld", "section_flash_end.ld", "section_heap.ld", "section_no_flash_data.ld", + "section_no_flash_text.ld", "sections_copy_to_ram.ld", "section_scratch.ld", "sections_default.ld", "sections_no_flash.ld", "set_memory_locations.ld", - "rp2_common/memmap_default.ld", - "rp2_common/memmap_no_flash.ld", - "rp2_common/memmap_copy_to_ram.ld", + "memmap_default.ld", + "memmap_no_flash.ld", + "memmap_copy_to_ram.ld", ] ) @@ -44,18 +47,21 @@ cc_library( "memory_scratch.ld", "memory_xip_ram.ld", "section_copy_to_ram_data.ld", + "section_copy_to_ram_text.ld", "section_default_data.ld", + "section_default_text.ld", "section_end.ld", "section_flash_end.ld", "section_heap.ld", "section_no_flash_data.ld", + "section_no_flash_text.ld", "sections_copy_to_ram.ld", "section_scratch.ld", "sections_default.ld", "sections_no_flash.ld", "set_memory_locations.ld", - "rp2_common/memmap_default.ld", - "rp2_common/memmap_no_flash.ld", - "rp2_common/memmap_copy_to_ram.ld", + "memmap_default.ld", + "memmap_no_flash.ld", + "memmap_copy_to_ram.ld", ], ) \ No newline at end of file diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/memmap_copy_to_ram.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld rename to src/rp2_common/pico_standard_link/scripts/memmap_copy_to_ram.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld b/src/rp2_common/pico_standard_link/scripts/memmap_default.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld rename to src/rp2_common/pico_standard_link/scripts/memmap_default.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/memmap_no_flash.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld rename to src/rp2_common/pico_standard_link/scripts/memmap_no_flash.ld diff --git a/src/rp2350/pico_platform_link/scripts/section_copy_to_ram_text.ld b/src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_text.ld similarity index 100% rename from src/rp2350/pico_platform_link/scripts/section_copy_to_ram_text.ld rename to src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_text.ld diff --git a/src/rp2350/pico_platform_link/scripts/section_default_text.ld b/src/rp2_common/pico_standard_link/scripts/section_default_text.ld similarity index 100% rename from src/rp2350/pico_platform_link/scripts/section_default_text.ld rename to src/rp2_common/pico_standard_link/scripts/section_default_text.ld diff --git a/src/rp2350/pico_platform_link/scripts/section_no_flash_text.ld b/src/rp2_common/pico_standard_link/scripts/section_no_flash_text.ld similarity index 100% rename from src/rp2350/pico_platform_link/scripts/section_no_flash_text.ld rename to src/rp2_common/pico_standard_link/scripts/section_no_flash_text.ld From 72adb670c15675ae3d124b6dc0bd8306e4c09d22 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 6 Mar 2026 11:49:41 +0000 Subject: [PATCH 013/127] Rename scripts include directories to standard_scripts and platform_scripts --- src/rp2040/pico_platform_link/BUILD.bazel | 16 ++++++++-------- .../{scripts => platform_scripts}/BUILD.bazel | 0 .../default_locations.ld | 0 .../section_copy_to_ram_text.ld | 0 .../section_default_text.ld | 0 .../section_no_flash_text.ld | 0 .../section_platform_end.ld | 0 src/rp2350/pico_platform_link/BUILD.bazel | 12 ++++++------ .../{scripts => platform_scripts}/BUILD.bazel | 0 .../default_locations.ld | 0 .../section_platform_end.ld | 0 src/rp2_common/pico_standard_link/CMakeLists.txt | 6 +++--- .../{scripts => standard_scripts}/BUILD.bazel | 0 .../memmap_copy_to_ram.ld | 0 .../memmap_default.ld | 0 .../memmap_no_flash.ld | 0 .../memory_aliases_default.ld | 0 .../memory_aliases_no_flash.ld | 0 .../memory_flash.ld | 0 .../{scripts => standard_scripts}/memory_ram.ld | 0 .../memory_scratch.ld | 0 .../memory_xip_ram.ld | 0 .../section_copy_to_ram_data.ld | 0 .../section_copy_to_ram_text.ld | 0 .../section_default_data.ld | 0 .../section_default_text.ld | 0 .../{scripts => standard_scripts}/section_end.ld | 0 .../section_flash_end.ld | 0 .../section_heap.ld | 0 .../section_no_flash_data.ld | 0 .../section_no_flash_text.ld | 0 .../section_scratch.ld | 0 .../sections_copy_to_ram.ld | 0 .../sections_default.ld | 0 .../sections_no_flash.ld | 0 .../set_memory_locations.ld | 0 36 files changed, 17 insertions(+), 17 deletions(-) rename src/rp2040/pico_platform_link/{scripts => platform_scripts}/BUILD.bazel (100%) rename src/rp2040/pico_platform_link/{scripts => platform_scripts}/default_locations.ld (100%) rename src/rp2040/pico_platform_link/{scripts => platform_scripts}/section_copy_to_ram_text.ld (100%) rename src/rp2040/pico_platform_link/{scripts => platform_scripts}/section_default_text.ld (100%) rename src/rp2040/pico_platform_link/{scripts => platform_scripts}/section_no_flash_text.ld (100%) rename src/rp2040/pico_platform_link/{scripts => platform_scripts}/section_platform_end.ld (100%) rename src/rp2350/pico_platform_link/{scripts => platform_scripts}/BUILD.bazel (100%) rename src/rp2350/pico_platform_link/{scripts => platform_scripts}/default_locations.ld (100%) rename src/rp2350/pico_platform_link/{scripts => platform_scripts}/section_platform_end.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/BUILD.bazel (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/memmap_copy_to_ram.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/memmap_default.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/memmap_no_flash.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/memory_aliases_default.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/memory_aliases_no_flash.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/memory_flash.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/memory_ram.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/memory_scratch.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/memory_xip_ram.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/section_copy_to_ram_data.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/section_copy_to_ram_text.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/section_default_data.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/section_default_text.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/section_end.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/section_flash_end.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/section_heap.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/section_no_flash_data.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/section_no_flash_text.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/section_scratch.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/sections_copy_to_ram.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/sections_default.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/sections_no_flash.ld (100%) rename src/rp2_common/pico_standard_link/{scripts => standard_scripts}/set_memory_locations.ld (100%) diff --git a/src/rp2040/pico_platform_link/BUILD.bazel b/src/rp2040/pico_platform_link/BUILD.bazel index 34e0ff71b..147cba5e2 100644 --- a/src/rp2040/pico_platform_link/BUILD.bazel +++ b/src/rp2040/pico_platform_link/BUILD.bazel @@ -47,8 +47,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2040/pico_platform_link/scripts:rp2040_linker_scripts", - "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", + "//src/rp2040/pico_platform_link/platform_scripts:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_default.ld", "memmap_default_args", @@ -62,8 +62,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2040/pico_platform_link/scripts:rp2040_linker_scripts", - "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", + "//src/rp2040/pico_platform_link/platform_scripts:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_blocked_ram.ld", "memmap_blocked_ram_args", @@ -77,8 +77,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2040/pico_platform_link/scripts:rp2040_linker_scripts", - "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", + "//src/rp2040/pico_platform_link/platform_scripts:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_copy_to_ram.ld", "memmap_copy_to_ram_args", @@ -92,8 +92,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2040/pico_platform_link/scripts:rp2040_linker_scripts", - "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", + "//src/rp2040/pico_platform_link/platform_scripts:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", "memmap_no_flash.ld", "memmap_no_flash_args", ], diff --git a/src/rp2040/pico_platform_link/scripts/BUILD.bazel b/src/rp2040/pico_platform_link/platform_scripts/BUILD.bazel similarity index 100% rename from src/rp2040/pico_platform_link/scripts/BUILD.bazel rename to src/rp2040/pico_platform_link/platform_scripts/BUILD.bazel diff --git a/src/rp2040/pico_platform_link/scripts/default_locations.ld b/src/rp2040/pico_platform_link/platform_scripts/default_locations.ld similarity index 100% rename from src/rp2040/pico_platform_link/scripts/default_locations.ld rename to src/rp2040/pico_platform_link/platform_scripts/default_locations.ld diff --git a/src/rp2040/pico_platform_link/scripts/section_copy_to_ram_text.ld b/src/rp2040/pico_platform_link/platform_scripts/section_copy_to_ram_text.ld similarity index 100% rename from src/rp2040/pico_platform_link/scripts/section_copy_to_ram_text.ld rename to src/rp2040/pico_platform_link/platform_scripts/section_copy_to_ram_text.ld diff --git a/src/rp2040/pico_platform_link/scripts/section_default_text.ld b/src/rp2040/pico_platform_link/platform_scripts/section_default_text.ld similarity index 100% rename from src/rp2040/pico_platform_link/scripts/section_default_text.ld rename to src/rp2040/pico_platform_link/platform_scripts/section_default_text.ld diff --git a/src/rp2040/pico_platform_link/scripts/section_no_flash_text.ld b/src/rp2040/pico_platform_link/platform_scripts/section_no_flash_text.ld similarity index 100% rename from src/rp2040/pico_platform_link/scripts/section_no_flash_text.ld rename to src/rp2040/pico_platform_link/platform_scripts/section_no_flash_text.ld diff --git a/src/rp2040/pico_platform_link/scripts/section_platform_end.ld b/src/rp2040/pico_platform_link/platform_scripts/section_platform_end.ld similarity index 100% rename from src/rp2040/pico_platform_link/scripts/section_platform_end.ld rename to src/rp2040/pico_platform_link/platform_scripts/section_platform_end.ld diff --git a/src/rp2350/pico_platform_link/BUILD.bazel b/src/rp2350/pico_platform_link/BUILD.bazel index 0b630064f..355002d04 100644 --- a/src/rp2350/pico_platform_link/BUILD.bazel +++ b/src/rp2350/pico_platform_link/BUILD.bazel @@ -46,8 +46,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2350/pico_platform_link/scripts:rp2350_linker_scripts", - "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", + "//src/rp2350/pico_platform_link/platform_scripts:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_default.ld", "memmap_default_args", @@ -61,8 +61,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2350/pico_platform_link/scripts:rp2350_linker_scripts", - "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", + "//src/rp2350/pico_platform_link/platform_scripts:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_copy_to_ram.ld", "memmap_copy_to_ram_args", @@ -76,8 +76,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2350/pico_platform_link/scripts:rp2350_linker_scripts", - "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", + "//src/rp2350/pico_platform_link/platform_scripts:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", "memmap_no_flash.ld", "memmap_no_flash_args", ], diff --git a/src/rp2350/pico_platform_link/scripts/BUILD.bazel b/src/rp2350/pico_platform_link/platform_scripts/BUILD.bazel similarity index 100% rename from src/rp2350/pico_platform_link/scripts/BUILD.bazel rename to src/rp2350/pico_platform_link/platform_scripts/BUILD.bazel diff --git a/src/rp2350/pico_platform_link/scripts/default_locations.ld b/src/rp2350/pico_platform_link/platform_scripts/default_locations.ld similarity index 100% rename from src/rp2350/pico_platform_link/scripts/default_locations.ld rename to src/rp2350/pico_platform_link/platform_scripts/default_locations.ld diff --git a/src/rp2350/pico_platform_link/scripts/section_platform_end.ld b/src/rp2350/pico_platform_link/platform_scripts/section_platform_end.ld similarity index 100% rename from src/rp2350/pico_platform_link/scripts/section_platform_end.ld rename to src/rp2350/pico_platform_link/platform_scripts/section_platform_end.ld diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index 24978fe68..d1ae1cd2a 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -158,11 +158,11 @@ if (NOT TARGET pico_standard_link) target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_BINARY_DIR}") # add include path for main linker script sections - target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}/scripts") - target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_CURRENT_LIST_DIR}/scripts") + target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}/platform_scripts") + target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_CURRENT_LIST_DIR}/standard_scripts") # add default locations script, so they can be referenced by pico_set_linker_script_var variables - target_link_options(pico_standard_link INTERFACE "LINKER:--script=${PICO_LINKER_SCRIPT_PATH}/scripts/default_locations.ld") + target_link_options(pico_standard_link INTERFACE "LINKER:--script=${PICO_LINKER_SCRIPT_PATH}/platform_scripts/default_locations.ld") # add variables set by pico_set_linker_script_var function target_link_options(pico_standard_link INTERFACE "LINKER:$,,>") diff --git a/src/rp2_common/pico_standard_link/scripts/BUILD.bazel b/src/rp2_common/pico_standard_link/standard_scripts/BUILD.bazel similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/BUILD.bazel rename to src/rp2_common/pico_standard_link/standard_scripts/BUILD.bazel diff --git a/src/rp2_common/pico_standard_link/scripts/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/standard_scripts/memmap_copy_to_ram.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/memmap_copy_to_ram.ld rename to src/rp2_common/pico_standard_link/standard_scripts/memmap_copy_to_ram.ld diff --git a/src/rp2_common/pico_standard_link/scripts/memmap_default.ld b/src/rp2_common/pico_standard_link/standard_scripts/memmap_default.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/memmap_default.ld rename to src/rp2_common/pico_standard_link/standard_scripts/memmap_default.ld diff --git a/src/rp2_common/pico_standard_link/scripts/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/standard_scripts/memmap_no_flash.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/memmap_no_flash.ld rename to src/rp2_common/pico_standard_link/standard_scripts/memmap_no_flash.ld diff --git a/src/rp2_common/pico_standard_link/scripts/memory_aliases_default.ld b/src/rp2_common/pico_standard_link/standard_scripts/memory_aliases_default.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/memory_aliases_default.ld rename to src/rp2_common/pico_standard_link/standard_scripts/memory_aliases_default.ld diff --git a/src/rp2_common/pico_standard_link/scripts/memory_aliases_no_flash.ld b/src/rp2_common/pico_standard_link/standard_scripts/memory_aliases_no_flash.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/memory_aliases_no_flash.ld rename to src/rp2_common/pico_standard_link/standard_scripts/memory_aliases_no_flash.ld diff --git a/src/rp2_common/pico_standard_link/scripts/memory_flash.ld b/src/rp2_common/pico_standard_link/standard_scripts/memory_flash.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/memory_flash.ld rename to src/rp2_common/pico_standard_link/standard_scripts/memory_flash.ld diff --git a/src/rp2_common/pico_standard_link/scripts/memory_ram.ld b/src/rp2_common/pico_standard_link/standard_scripts/memory_ram.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/memory_ram.ld rename to src/rp2_common/pico_standard_link/standard_scripts/memory_ram.ld diff --git a/src/rp2_common/pico_standard_link/scripts/memory_scratch.ld b/src/rp2_common/pico_standard_link/standard_scripts/memory_scratch.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/memory_scratch.ld rename to src/rp2_common/pico_standard_link/standard_scripts/memory_scratch.ld diff --git a/src/rp2_common/pico_standard_link/scripts/memory_xip_ram.ld b/src/rp2_common/pico_standard_link/standard_scripts/memory_xip_ram.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/memory_xip_ram.ld rename to src/rp2_common/pico_standard_link/standard_scripts/memory_xip_ram.ld diff --git a/src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_data.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_copy_to_ram_data.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_data.ld rename to src/rp2_common/pico_standard_link/standard_scripts/section_copy_to_ram_data.ld diff --git a/src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_text.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_copy_to_ram_text.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_text.ld rename to src/rp2_common/pico_standard_link/standard_scripts/section_copy_to_ram_text.ld diff --git a/src/rp2_common/pico_standard_link/scripts/section_default_data.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_default_data.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/section_default_data.ld rename to src/rp2_common/pico_standard_link/standard_scripts/section_default_data.ld diff --git a/src/rp2_common/pico_standard_link/scripts/section_default_text.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_default_text.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/section_default_text.ld rename to src/rp2_common/pico_standard_link/standard_scripts/section_default_text.ld diff --git a/src/rp2_common/pico_standard_link/scripts/section_end.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_end.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/section_end.ld rename to src/rp2_common/pico_standard_link/standard_scripts/section_end.ld diff --git a/src/rp2_common/pico_standard_link/scripts/section_flash_end.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_flash_end.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/section_flash_end.ld rename to src/rp2_common/pico_standard_link/standard_scripts/section_flash_end.ld diff --git a/src/rp2_common/pico_standard_link/scripts/section_heap.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_heap.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/section_heap.ld rename to src/rp2_common/pico_standard_link/standard_scripts/section_heap.ld diff --git a/src/rp2_common/pico_standard_link/scripts/section_no_flash_data.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_no_flash_data.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/section_no_flash_data.ld rename to src/rp2_common/pico_standard_link/standard_scripts/section_no_flash_data.ld diff --git a/src/rp2_common/pico_standard_link/scripts/section_no_flash_text.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_no_flash_text.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/section_no_flash_text.ld rename to src/rp2_common/pico_standard_link/standard_scripts/section_no_flash_text.ld diff --git a/src/rp2_common/pico_standard_link/scripts/section_scratch.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_scratch.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/section_scratch.ld rename to src/rp2_common/pico_standard_link/standard_scripts/section_scratch.ld diff --git a/src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld b/src/rp2_common/pico_standard_link/standard_scripts/sections_copy_to_ram.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld rename to src/rp2_common/pico_standard_link/standard_scripts/sections_copy_to_ram.ld diff --git a/src/rp2_common/pico_standard_link/scripts/sections_default.ld b/src/rp2_common/pico_standard_link/standard_scripts/sections_default.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/sections_default.ld rename to src/rp2_common/pico_standard_link/standard_scripts/sections_default.ld diff --git a/src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld b/src/rp2_common/pico_standard_link/standard_scripts/sections_no_flash.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld rename to src/rp2_common/pico_standard_link/standard_scripts/sections_no_flash.ld diff --git a/src/rp2_common/pico_standard_link/scripts/set_memory_locations.ld b/src/rp2_common/pico_standard_link/standard_scripts/set_memory_locations.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/set_memory_locations.ld rename to src/rp2_common/pico_standard_link/standard_scripts/set_memory_locations.ld From e47fe099bdfaf90fbffbd08b9a509209bdff8abc Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 6 Mar 2026 12:04:33 +0000 Subject: [PATCH 014/127] Move and add example to Bazel docs for changing linker scripts --- src/rp2040/pico_platform_link/BUILD.bazel | 9 --------- src/rp2350/pico_platform_link/BUILD.bazel | 9 --------- src/rp2_common/pico_standard_link/BUILD.bazel | 9 +++++++++ 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/rp2040/pico_platform_link/BUILD.bazel b/src/rp2040/pico_platform_link/BUILD.bazel index 147cba5e2..0a3556242 100644 --- a/src/rp2040/pico_platform_link/BUILD.bazel +++ b/src/rp2040/pico_platform_link/BUILD.bazel @@ -33,15 +33,6 @@ use_linker_script_file( script = "memmap_no_flash.ld", ) -# It's possible to set linker scripts globally or on a per-binary basis. -# -# Setting globally: -# * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT to point to your -# desired linker script. -# -# Setting per-binary: -# * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT=@pico-sdk//bazel:empty_cc_lib -# * Manually add your desired linker script to each cc_binary. cc_library( name = "default_linker_script", target_compatible_with = ["//bazel/constraint:rp2040"], diff --git a/src/rp2350/pico_platform_link/BUILD.bazel b/src/rp2350/pico_platform_link/BUILD.bazel index 355002d04..d3aae9161 100644 --- a/src/rp2350/pico_platform_link/BUILD.bazel +++ b/src/rp2350/pico_platform_link/BUILD.bazel @@ -32,15 +32,6 @@ use_linker_script_file( script = "memmap_no_flash.ld", ) -# It's possible to set linker scripts globally or on a per-binary basis. -# -# Setting globally: -# * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT to point to your -# desired linker script. -# -# Setting per-binary: -# * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT=@pico-sdk//bazel:empty_cc_lib -# * Manually add your desired linker script to each cc_binary. cc_library( name = "default_linker_script", target_compatible_with = ["//bazel/constraint:rp2350"], diff --git a/src/rp2_common/pico_standard_link/BUILD.bazel b/src/rp2_common/pico_standard_link/BUILD.bazel index 6c84336bf..924358d50 100644 --- a/src/rp2_common/pico_standard_link/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/BUILD.bazel @@ -18,6 +18,15 @@ generated_pico_flash_region( }), ) +# It's possible to set linker scripts globally or on a per-binary basis. +# +# Setting globally: +# * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT to point to your +# desired linker script (eg @pico-sdk//src/pico_standard_link:no_flash_linker_script) +# +# Setting per-binary: +# * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT=@pico-sdk//bazel:empty_cc_lib +# * Manually add your desired linker script to each cc_binary. alias( name = "default_linker_script", actual = select({ From 9c0ed0cc453fd2ad31facfa1368a01c3e31a2c55 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 6 Mar 2026 15:41:32 +0000 Subject: [PATCH 015/127] Add cc_library load to new bazel files --- src/rp2040/pico_platform_link/platform_scripts/BUILD.bazel | 2 ++ src/rp2350/pico_platform_link/platform_scripts/BUILD.bazel | 2 ++ src/rp2_common/pico_standard_link/standard_scripts/BUILD.bazel | 1 + 3 files changed, 5 insertions(+) diff --git a/src/rp2040/pico_platform_link/platform_scripts/BUILD.bazel b/src/rp2040/pico_platform_link/platform_scripts/BUILD.bazel index 492842565..337252e6c 100644 --- a/src/rp2040/pico_platform_link/platform_scripts/BUILD.bazel +++ b/src/rp2040/pico_platform_link/platform_scripts/BUILD.bazel @@ -1,3 +1,5 @@ +load("@rules_cc//cc:cc_library.bzl", "cc_library") + package(default_visibility = ["//visibility:public"]) load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") diff --git a/src/rp2350/pico_platform_link/platform_scripts/BUILD.bazel b/src/rp2350/pico_platform_link/platform_scripts/BUILD.bazel index 5161b096b..5b234a016 100644 --- a/src/rp2350/pico_platform_link/platform_scripts/BUILD.bazel +++ b/src/rp2350/pico_platform_link/platform_scripts/BUILD.bazel @@ -1,3 +1,5 @@ +load("@rules_cc//cc:cc_library.bzl", "cc_library") + package(default_visibility = ["//visibility:public"]) load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") diff --git a/src/rp2_common/pico_standard_link/standard_scripts/BUILD.bazel b/src/rp2_common/pico_standard_link/standard_scripts/BUILD.bazel index b0e51da98..04a1af5d9 100644 --- a/src/rp2_common/pico_standard_link/standard_scripts/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/standard_scripts/BUILD.bazel @@ -1,3 +1,4 @@ +load("@rules_cc//cc:cc_library.bzl", "cc_library") load("//bazel:defs.bzl", "compatible_with_rp2") load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") From e44bdea25f2b1c24cd37d96ee7461aab9046ee6a Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 16 Mar 2026 12:45:28 +0000 Subject: [PATCH 016/127] Add excludes.ld files for default memmap Allows overriding what to exclude from .text/.rodata and put in .data --- .../platform_scripts/section_default_text.ld | 4 ++-- .../pico_standard_link/standard_scripts/BUILD.bazel | 4 ++++ .../standard_scripts/section_default_data.ld | 2 +- .../standard_scripts/section_default_rodata_excludes.ld | 1 + .../standard_scripts/section_default_text.ld | 4 ++-- .../standard_scripts/section_default_text_excludes.ld | 1 + 6 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 src/rp2_common/pico_standard_link/standard_scripts/section_default_rodata_excludes.ld create mode 100644 src/rp2_common/pico_standard_link/standard_scripts/section_default_text_excludes.ld diff --git a/src/rp2040/pico_platform_link/platform_scripts/section_default_text.ld b/src/rp2040/pico_platform_link/platform_scripts/section_default_text.ld index 7aa5c9399..2f25a1d4d 100644 --- a/src/rp2040/pico_platform_link/platform_scripts/section_default_text.ld +++ b/src/rp2040/pico_platform_link/platform_scripts/section_default_text.ld @@ -37,7 +37,7 @@ SECTIONS /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from * FLASH ... we will include any thing excluded here in .data below by default */ *(.init) - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) + INCLUDE "section_default_text_excludes.ld" *(.fini) /* Pull all c'tors into .text */ *crtbegin.o(.ctors) @@ -78,7 +78,7 @@ SECTIONS } > FLASH .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) + INCLUDE "section_default_rodata_excludes.ld" . = ALIGN(4); *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) . = ALIGN(4); diff --git a/src/rp2_common/pico_standard_link/standard_scripts/BUILD.bazel b/src/rp2_common/pico_standard_link/standard_scripts/BUILD.bazel index 04a1af5d9..ba56b59d3 100644 --- a/src/rp2_common/pico_standard_link/standard_scripts/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/standard_scripts/BUILD.bazel @@ -16,6 +16,8 @@ exports_files( "section_copy_to_ram_text.ld", "section_default_data.ld", "section_default_text.ld", + "section_default_text_excludes.ld", + "section_default_rodata_excludes.ld", "section_end.ld", "section_flash_end.ld", "section_heap.ld", @@ -51,6 +53,8 @@ cc_library( "section_copy_to_ram_text.ld", "section_default_data.ld", "section_default_text.ld", + "section_default_text_excludes.ld", + "section_default_rodata_excludes.ld", "section_end.ld", "section_flash_end.ld", "section_heap.ld", diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_default_data.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_default_data.ld index 9ffa5d163..5bd1cf569 100644 --- a/src/rp2_common/pico_standard_link/standard_scripts/section_default_data.ld +++ b/src/rp2_common/pico_standard_link/standard_scripts/section_default_data.ld @@ -15,7 +15,7 @@ SECTIONS *(.time_critical*) - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ + /* remaining .text and .rodata; i.e. stuff we exclude in ..._excludes files because we want it in RAM */ *(.text*) . = ALIGN(4); *(.rodata*) diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_default_rodata_excludes.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_default_rodata_excludes.ld new file mode 100644 index 000000000..3d57435bb --- /dev/null +++ b/src/rp2_common/pico_standard_link/standard_scripts/section_default_rodata_excludes.ld @@ -0,0 +1 @@ +*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) \ No newline at end of file diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_default_text.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_default_text.ld index fdd963321..ab86ade78 100644 --- a/src/rp2_common/pico_standard_link/standard_scripts/section_default_text.ld +++ b/src/rp2_common/pico_standard_link/standard_scripts/section_default_text.ld @@ -27,7 +27,7 @@ SECTIONS * FLASH ... we will include any thing excluded here in .data below by default */ *(.init) *libgcc.a:cmse_nonsecure_call.o - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) + INCLUDE "section_default_text_excludes.ld" *(.fini) /* Pull all c'tors into .text */ *crtbegin.o(.ctors) @@ -89,7 +89,7 @@ SECTIONS "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) + INCLUDE "section_default_rodata_excludes.ld" *(.srodata*) . = ALIGN(4); *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_default_text_excludes.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_default_text_excludes.ld new file mode 100644 index 000000000..69bc10cdb --- /dev/null +++ b/src/rp2_common/pico_standard_link/standard_scripts/section_default_text_excludes.ld @@ -0,0 +1 @@ +*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) \ No newline at end of file From dc3a2e861adebdff1b7009f950580f1f719366d1 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 16 Mar 2026 14:19:26 +0000 Subject: [PATCH 017/127] Put mem functions in SRAM These were being placed in Flash due to a missing space, and also are under libc on some compilers --- .../standard_scripts/section_default_rodata_excludes.ld | 2 +- .../standard_scripts/section_default_text_excludes.ld | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_default_rodata_excludes.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_default_rodata_excludes.ld index 3d57435bb..920e30383 100644 --- a/src/rp2_common/pico_standard_link/standard_scripts/section_default_rodata_excludes.ld +++ b/src/rp2_common/pico_standard_link/standard_scripts/section_default_rodata_excludes.ld @@ -1 +1 @@ -*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) \ No newline at end of file +*(EXCLUDE_FILE(*libgcc.a: *libc.a: *lib*_a-mem*.o *libm.a:) .rodata*) \ No newline at end of file diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_default_text_excludes.ld b/src/rp2_common/pico_standard_link/standard_scripts/section_default_text_excludes.ld index 69bc10cdb..e81ae31bf 100644 --- a/src/rp2_common/pico_standard_link/standard_scripts/section_default_text_excludes.ld +++ b/src/rp2_common/pico_standard_link/standard_scripts/section_default_text_excludes.ld @@ -1 +1 @@ -*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) \ No newline at end of file +*(EXCLUDE_FILE(*libgcc.a: *libc.a: *lib*_a-mem*.o *libm.a:) .text*) \ No newline at end of file From afbc07eae4bcebcf899547966b1e2330b80f3129 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Tue, 27 Aug 2024 14:17:43 -0500 Subject: [PATCH 018/127] transplant sleep2 onto develop --- src/cmake/rp2_common.cmake | 2 + .../pico_util/include/pico/util/bitset.h | 135 ++++++ src/rp2_common/hardware_clocks/clocks.c | 15 + .../hardware_clocks/include/hardware/clocks.h | 29 ++ src/rp2_common/hardware_rosc/CMakeLists.txt | 1 + .../hardware_rosc/include/hardware/rosc.h | 97 +++++ src/rp2_common/hardware_rosc/rosc.c | 69 +++ .../hardware_rtc/include/hardware/rtc.h | 8 + src/rp2_common/hardware_rtc/rtc.c | 4 + src/rp2_common/pico_low_power/CMakeLists.txt | 18 + .../pico_low_power/include/pico/low_power.h | 122 ++++++ src/rp2_common/pico_low_power/low_power.c | 395 ++++++++++++++++++ test/CMakeLists.txt | 1 + test/hello_sleep/CMakeLists.txt | 8 + test/hello_sleep/hello_sleep.c | 101 +++++ test/kitchen_sink/CMakeLists.txt | 1 + test/kitchen_sink/kitchen_sink.c | 26 ++ 17 files changed, 1032 insertions(+) create mode 100644 src/common/pico_util/include/pico/util/bitset.h create mode 100644 src/rp2_common/hardware_rosc/CMakeLists.txt create mode 100644 src/rp2_common/hardware_rosc/include/hardware/rosc.h create mode 100644 src/rp2_common/hardware_rosc/rosc.c create mode 100644 src/rp2_common/pico_low_power/CMakeLists.txt create mode 100644 src/rp2_common/pico_low_power/include/pico/low_power.h create mode 100644 src/rp2_common/pico_low_power/low_power.c create mode 100644 test/hello_sleep/CMakeLists.txt create mode 100644 test/hello_sleep/hello_sleep.c diff --git a/src/cmake/rp2_common.cmake b/src/cmake/rp2_common.cmake index 273839f70..a5a090927 100644 --- a/src/cmake/rp2_common.cmake +++ b/src/cmake/rp2_common.cmake @@ -49,6 +49,7 @@ pico_add_subdirectory(rp2_common/hardware_pio) pico_add_subdirectory(rp2_common/hardware_pll) pico_add_subdirectory(rp2_common/hardware_pwm) pico_add_subdirectory(rp2_common/hardware_resets) +pico_add_subdirectory(rp2_common/hardware_rosc) if (PICO_RP2040 OR PICO_COMBINED_DOCS) pico_add_subdirectory(rp2_common/hardware_rtc) endif() @@ -103,6 +104,7 @@ if (NOT PICO_BARE_METAL) pico_add_subdirectory(rp2_common/pico_int64_ops) pico_add_subdirectory(rp2_common/pico_flash) pico_add_subdirectory(rp2_common/pico_float) + pico_add_subdirectory(rp2_common/pico_low_power) pico_add_subdirectory(rp2_common/pico_mem_ops) pico_add_subdirectory(rp2_common/pico_malloc) pico_add_subdirectory(rp2_common/pico_printf) diff --git a/src/common/pico_util/include/pico/util/bitset.h b/src/common/pico_util/include/pico/util/bitset.h new file mode 100644 index 000000000..2a277fcc4 --- /dev/null +++ b/src/common/pico_util/include/pico/util/bitset.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _PICO_UTIL_BITSET_H +#define _PICO_UTIL_BITSET_H + +#include "pico.h" + +/** \file bitset.h + * \defgroup bitset bitset + * \brief Simple bitset implementation + * + * \ingroup pico_util + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint16_t size; \ + uint16_t word_size; \ + uint32_t words[]; +} generic_bitset_t; + +#define bitset_type_t(N) union { \ + generic_bitset_t bitset; \ + struct { \ + uint16_t size; \ + uint16_t word_size; \ + uint32_t words[((N) + 31) / 32]; \ + } sized_bitset; \ +} +#define bitset_sizeof_for(N) ((((N) + 63u) / 32u) * 4u) + +extern bitset_type_t(32) __not_real_bitset32; +extern bitset_type_t(33) __not_real_bitset33; +static_assert(sizeof(__not_real_bitset32) == bitset_sizeof_for(1),""); +static_assert(sizeof(__not_real_bitset33) == bitset_sizeof_for(37), ""); + +#define bitset_init(ptr, type, N, fill) ({ \ + assert(sizeof(type) == bitset_sizeof_for(N)); \ + __unused type *type_check = ptr; \ + __builtin_memset(ptr, (fill) ? 0xff : 0, sizeof(type)); \ + (ptr)->bitset.size = N; \ + (ptr)->bitset.word_size = ((N) + 31u) / 32u; \ +}) + +static inline uint bitset_size(const generic_bitset_t *bitset) { + return bitset->size; +} + +static inline uint bitset_word_size(const generic_bitset_t *bitset) { + return bitset->word_size; +} + +static inline void check_bitset(const generic_bitset_t *bitset) { + assert(bitset->word_size == (bitset->size + 31) / 32); +} + +static inline generic_bitset_t *bitset_write_word(generic_bitset_t *bitset, uint word_num, uint32_t value) { + check_bitset(bitset); + if (word_num < bitset_word_size(bitset)) { + bitset->words[word_num] = value; + } +} + +static inline uint32_t bitset_read_word(const generic_bitset_t *bitset, uint word_num) { + check_bitset(bitset); + if (word_num < bitset_word_size(bitset)) { + return bitset->words[word_num]; + } + return 0; +} + +static inline generic_bitset_t *bitset_clear(generic_bitset_t *bitset) { + check_bitset(bitset); + __builtin_memset(bitset->words, 0, bitset->word_size * sizeof(uint32_t)); + return bitset; +} + +static inline generic_bitset_t *bitset_set_all(generic_bitset_t *bitset) { + check_bitset(bitset); + __builtin_memset(bitset->words, 0xff, bitset->word_size * sizeof(uint32_t)); + return bitset; +} + +static inline generic_bitset_t *bitset_set_bit(generic_bitset_t *bitset, uint bit) { + check_bitset(bitset); + if (bit < bitset->size) { + bitset->words[bit / 32u] |= 1u << (bit % 32u); + } + return bitset; +} + +static inline generic_bitset_t *bitset_clear_bit(generic_bitset_t *bitset, uint bit) { + check_bitset(bitset); + if (bit < bitset->size) { + bitset->words[bit / 32u] &= ~(1u << (bit % 32u)); + } + return bitset; +} + +static inline bool bitset_get_bit(generic_bitset_t *bitset, uint bit) { + check_bitset(bitset); + assert(bit < bitset->size); +// if (bit < bitset->size) { + return bitset->words[bit / 32u] & (1u << (bit % 32u)); +// } + return false; +} + +typedef uint32_t tiny_encoded_bitset_t; +typedef uint64_t encoded_bitset_t; + +#define encoded_bitset_empty() 0 +#define encoded_bitset_of1(v) (1u | ((v) << 8)) +#define encoded_bitset_of2(v1, v2) (2u | ((v1) << 8) | ((v2) << 16)) +#define encoded_bitset_of3(v1, v2, v3) (3u | ((v1) << 8) | ((v2) << 16) | (((v3) << 24))) +#define encoded_bitset_of4(v1, v2, v3, v4) (4u | ((v1) << 8) | ((v2) << 16) | (((v3) << 24)) | (((uint64_t)(v4)) << 32)) +#define encoded_bitset_of5(v1, v2, v3, v4, v5) (5u | ((v1) << 8) | ((v2) << 16) | (((v3) << 24)) | (((uint64_t)((v4) | ((v5)<<8u))) << 32)) + +#define encoded_bitset_foreach(bitset, x) ({ \ + for(uint _i=0;_i<((bitset)&0xffu);_i++) { \ + uint bit = (uint8_t)((bitset) >> (8 * _i)); \ + x; \ + } \ +}) +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/rp2_common/hardware_clocks/clocks.c b/src/rp2_common/hardware_clocks/clocks.c index 2bcaa5741..8870a9478 100644 --- a/src/rp2_common/hardware_clocks/clocks.c +++ b/src/rp2_common/hardware_clocks/clocks.c @@ -441,3 +441,18 @@ bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_out, uint *postdiv1_out, u } return false; } + + +void clock_get_sleep_en_gate(clock_dest_set_t *dests) { + static_assert(CLOCKS_SLEEP_EN1_OFFSET == CLOCKS_SLEEP_EN0_OFFSET + 4, ""); + for(uint i=0;i < bitset_word_size(&dests->bitset); i++) { + bitset_write_word(&dests->bitset, i, clocks_hw->sleep_en[i]); + } +} + +void clock_gate_sleep_en(const clock_dest_set_t *dests) { + static_assert(CLOCKS_SLEEP_EN1_OFFSET == CLOCKS_SLEEP_EN0_OFFSET + 4, ""); + for(uint i=0;i < bitset_word_size(&dests->bitset); i++) { + clocks_hw->sleep_en[i] = bitset_read_word(&dests->bitset, i); + } +} diff --git a/src/rp2_common/hardware_clocks/include/hardware/clocks.h b/src/rp2_common/hardware_clocks/include/hardware/clocks.h index 9e1c3f4a6..768988def 100644 --- a/src/rp2_common/hardware_clocks/include/hardware/clocks.h +++ b/src/rp2_common/hardware_clocks/include/hardware/clocks.h @@ -578,6 +578,35 @@ static inline bool set_sys_clock_khz(uint32_t freq_khz, bool required) { return false; } +#include "pico/util/bitset.h" + +typedef bitset_type_t(NUM_CLOCK_DESTINATIONS) clock_dest_set_t; +#define clock_dest_set_none() ({ clock_dest_set_t bitset; bitset_init(&bitset, clock_dest_set_t, NUM_CLOCK_DESTINATIONS, 0); bitset; }) +#define clock_dest_set_all() ({ clock_dest_set_t bitset; bitset_init(&bitset, clock_dest_set_t, NUM_CLOCK_DESTINATIONS, 1); bitset; }) + +static inline clock_dest_set_t *clock_dest_set_clear(clock_dest_set_t *dests) { + bitset_clear(&dests->bitset); + return dests; +} + +static inline clock_dest_set_t *clock_dest_set_add_all(clock_dest_set_t *dests) { + bitset_set_all(&dests->bitset); + return dests; +} + +static inline clock_dest_set_t *clock_dest_set_add(clock_dest_set_t *dests, clock_dest_num_t dest) { + bitset_set_bit(&dests->bitset, dest); + return dests; +} + +static inline clock_dest_set_t *clock_dest_set_remove(clock_dest_set_t *dests, clock_dest_num_t dest) { + bitset_clear_bit(&dests->bitset, dest); + return dests; +} + +void clock_get_sleep_en_gate(clock_dest_set_t *clocks); +void clock_gate_sleep_en(const clock_dest_set_t *clocks); + #define GPIO_TO_GPOUT_CLOCK_HANDLE_RP2040(gpio, default_clk_handle) \ ((gpio) == 21 ? clk_gpout0 : \ ((gpio) == 23 ? clk_gpout1 : \ diff --git a/src/rp2_common/hardware_rosc/CMakeLists.txt b/src/rp2_common/hardware_rosc/CMakeLists.txt new file mode 100644 index 000000000..3ee667e29 --- /dev/null +++ b/src/rp2_common/hardware_rosc/CMakeLists.txt @@ -0,0 +1 @@ +pico_simple_hardware_target(rosc) \ No newline at end of file diff --git a/src/rp2_common/hardware_rosc/include/hardware/rosc.h b/src/rp2_common/hardware_rosc/include/hardware/rosc.h new file mode 100644 index 000000000..eff5a5c80 --- /dev/null +++ b/src/rp2_common/hardware_rosc/include/hardware/rosc.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _HARDWARE_ROSC_H_ +#define _HARDWARE_ROSC_H_ + +#include "pico.h" +#include "hardware/structs/rosc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file rosc.h + * \defgroup hardware_rosc hardware_rosc + * + * Ring Oscillator (ROSC) API + * + * A Ring Oscillator is an on-chip oscillator that requires no external crystal. Instead, the output is generated from a series of + * inverters that are chained together to create a feedback loop. RP2040 boots from the ring oscillator initially, meaning the + * first stages of the bootrom, including booting from SPI flash, will be clocked by the ring oscillator. If your design has a + * crystal oscillator, you’ll likely want to switch to this as your reference clock as soon as possible, because the frequency is + * more accurate than the ring oscillator. + */ + +/*! \brief Set frequency of the Ring Oscillator + * \ingroup hardware_rosc + * + * \param code The drive strengths. See the RP2040 datasheet for information on this value. + */ +void rosc_set_freq(uint32_t code); + +/*! \brief Set range of the Ring Oscillator + * \ingroup hardware_rosc + * + * Frequency range. Frequencies will vary with Process, Voltage & Temperature (PVT). + * Clock output will not glitch when changing the range up one step at a time. + * + * \param range 0x01 Low, 0x02 Medium, 0x03 High, 0x04 Too High. + */ +void rosc_set_range(uint range); + +/*! \brief Disable the Ring Oscillator + * \ingroup hardware_rosc + * + */ +void rosc_disable(void); + +/*! \brief Put Ring Oscillator in to dormant mode. + * \ingroup hardware_rosc + * + * The ROSC supports a dormant mode,which stops oscillation until woken up up by an asynchronous interrupt. + * This can either come from the RTC, being clocked by an external clock, or a GPIO pin going high or low. + * If no IRQ is configured before going into dormant mode the ROSC will never restart. + * + * PLLs should be stopped before selecting dormant mode. + */ +void rosc_set_dormant(void); + +/*! \brief Re-enable the ring oscillator so that the processor cores can wake up after sleep/dormant mode + \ingroup hardware_sleep + + This must be called at the end of the sleeping period (e.g., in an interrupt service routine) +*/ +void rosc_restart(void); + +// FIXME: Add doxygen + +uint32_t next_rosc_code(uint32_t code); + +uint rosc_find_freq(uint32_t low_mhz, uint32_t high_mhz); + +void rosc_set_div(uint32_t div); + +inline static void rosc_clear_bad_write(void) { + hw_clear_bits(&rosc_hw->status, ROSC_STATUS_BADWRITE_BITS); +} + +inline static bool rosc_write_okay(void) { + return !(rosc_hw->status & ROSC_STATUS_BADWRITE_BITS); +} + +inline static void rosc_write(io_rw_32 *addr, uint32_t value) { + rosc_clear_bad_write(); + assert(rosc_write_okay()); + *addr = value; + assert(rosc_write_okay()); +}; + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/rp2_common/hardware_rosc/rosc.c b/src/rp2_common/hardware_rosc/rosc.c new file mode 100644 index 000000000..f58f65bd6 --- /dev/null +++ b/src/rp2_common/hardware_rosc/rosc.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "pico.h" + +// For MHZ definitions etc +#include "hardware/clocks.h" +#include "hardware/rosc.h" + +// Given a ROSC delay stage code, return the next-numerically-higher code. +// Top result bit is set when called on maximum ROSC code. +uint32_t next_rosc_code(uint32_t code) { + return ((code | 0x08888888u) + 1u) & 0xf7777777u; +} + +uint rosc_find_freq(uint32_t low_mhz, uint32_t high_mhz) { + // TODO: This could be a lot better + rosc_set_div(1); + for (uint32_t code = 0; code <= 0x77777777u; code = next_rosc_code(code)) { + rosc_set_freq(code); + uint rosc_mhz = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC) / 1000; + if ((rosc_mhz >= low_mhz) && (rosc_mhz <= high_mhz)) { + return rosc_mhz; + } + } + return 0; +} + +void rosc_set_div(uint32_t div) { + assert(div <= 31 && div >= 1); + rosc_write(&rosc_hw->div, ROSC_DIV_VALUE_PASS + div); +} + +void rosc_set_freq(uint32_t code) { + rosc_write(&rosc_hw->freqa, (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB) | (code & 0xffffu)); + rosc_write(&rosc_hw->freqb, (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB) | (code >> 16u)); +} + +void rosc_set_range(uint range) { + // Range should use enumvals from the headers and thus have the password correct + rosc_write(&rosc_hw->ctrl, (ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB) | range); +} + +void rosc_disable(void) { + uint32_t tmp = rosc_hw->ctrl; + tmp &= (~ROSC_CTRL_ENABLE_BITS); + tmp |= (ROSC_CTRL_ENABLE_VALUE_DISABLE << ROSC_CTRL_ENABLE_LSB); + rosc_write(&rosc_hw->ctrl, tmp); + // Wait for stable to go away + while (rosc_hw->status & ROSC_STATUS_STABLE_BITS); +} + +void rosc_set_dormant(void) { + // WARNING: This stops the rosc until woken up by an irq + rosc_write(&rosc_hw->dormant, ROSC_DORMANT_VALUE_DORMANT); + // Wait for it to become stable once woken up + while (!(rosc_hw->status & ROSC_STATUS_STABLE_BITS)); +} + +void rosc_restart(void) { + //Re-enable the rosc + rosc_write(&rosc_hw->ctrl, ROSC_CTRL_ENABLE_BITS); + + //Wait for it to become stable once restarted + while (!(rosc_hw->status & ROSC_STATUS_STABLE_BITS)); +} \ No newline at end of file diff --git a/src/rp2_common/hardware_rtc/include/hardware/rtc.h b/src/rp2_common/hardware_rtc/include/hardware/rtc.h index 9e05c7afb..500c4ee4c 100644 --- a/src/rp2_common/hardware_rtc/include/hardware/rtc.h +++ b/src/rp2_common/hardware_rtc/include/hardware/rtc.h @@ -90,6 +90,14 @@ void rtc_enable_alarm(void); */ void rtc_disable_alarm(void); +/*! \brief Run the RTC from an external clock source through GPIO + * \ingroup hardware_sleep + * + * \param src_hz The frequency of the external clock source + * \param gpio_pin The input pin providing the external clock (GP20 or GP22) + */ +void rtc_run_from_external_source(uint src_hz, uint gpio_pin); + #ifdef __cplusplus } #endif diff --git a/src/rp2_common/hardware_rtc/rtc.c b/src/rp2_common/hardware_rtc/rtc.c index f3f61eabf..1c056a822 100644 --- a/src/rp2_common/hardware_rtc/rtc.c +++ b/src/rp2_common/hardware_rtc/rtc.c @@ -188,3 +188,7 @@ void rtc_disable_alarm(void) { tight_loop_contents(); } } + +void rtc_run_from_external_source(uint src_hz, uint gpio_pin) { + clock_configure_gpin(clk_rtc, gpio_pin, src_hz, 46875); +} \ No newline at end of file diff --git a/src/rp2_common/pico_low_power/CMakeLists.txt b/src/rp2_common/pico_low_power/CMakeLists.txt new file mode 100644 index 000000000..b66336779 --- /dev/null +++ b/src/rp2_common/pico_low_power/CMakeLists.txt @@ -0,0 +1,18 @@ +pico_add_library(pico_low_power) + +target_sources(pico_low_power INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/low_power.c +) + +target_include_directories(pico_low_power INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/include +) + +pico_mirrored_target_link_libraries(pico_low_power INTERFACE + hardware_clocks + hardware_rosc + hardware_xosc + hardware_irq + hardware_timer + pico_aon_timer + ) diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h new file mode 100644 index 000000000..999d3870a --- /dev/null +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _PICO_LOW_POWER_H_ +#define _PICO_LOW_POWER_H_ + +#include "pico.h" +#include "hardware/timer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file low_power.h + * \defgroup pico_low_power pico_low_power + * + * Lower Power Sleep APIs + * + * The difference between sleep and dormant is that ALL clocks are stopped in dormant mode, + * until the source (either xosc or rosc) is started again by an external event. + * + * In sleep mode some clocks can be left running controlled by the SLEEP_EN registers in the clocks + * block. For example you could keep clk_rtc running. Some destinations (proc0 and proc1 wakeup logic) + * can't be stopped in sleep mode otherwise there wouldn't be enough logic to wake up again. + * + * \subsection sleep_example Example + * \addtogroup pico_sleep + * \include hello_sleep.c + */ + +// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_PICO_LOW_POWER, Enable/disable assertions in the pico_low_power module, type=bool, default=0, group=pico_low_power +#ifndef PARAM_ASSERTIONS_ENABLED_PICO_LOW_POWER +#define PARAM_ASSERTIONS_ENABLED_PICO_LOW_POWER 0 +#endif + +#include "hardware/clocks.h" + +typedef enum { + DORMANT_CLOCK_SOURCE_XOSC, + DORMANT_CLOCK_SOURCE_ROSC, +#if !PICO_RP2040 + DORMANT_CLOCK_SOURCE_LPOSC, +#endif +} dormant_clock_source_t; + + +// sleep until the given timer reaches the specified value; if the time passes then no sleep occurs +// keep_enabled defaults to none if NULL +// ** LIAM BLESSED ** +int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, const clock_dest_set_t *keep_enabled); + +static inline int low_power_deep_sleep_until_default_timer(absolute_time_t until, const clock_dest_set_t *keep_enabled) { + return low_power_sleep_until_timer(PICO_DEFAULT_TIMER_INSTANCE(), until, keep_enabled); +} + +// ** LIAM BLESSED this for RP2040; why not RP2350 ** +void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high); + +// ** LIAM SAYS THIS IS NO MORE USEFUL THAN SLEEP_UNTIL TIMER... ** +int low_power_sleep_until_aon_timer(absolute_time_t until, const clock_dest_set_t *keep_enabled); + +// ** LIAM BLESSED but we need to impl it correctly (note not blessed for RP2040, but we should do it anyway for orthogonality ** +int low_power_dormant_until_aon_timer(absolute_time_t until, + dormant_clock_source_t dormant_clock_source, + uint src_hz, uint gpio_pin, + const clock_dest_set_t *keep_enabled); + +// ** LIAM BLESSED but we need to impl it correctly (note not blessed for RP2040, but we should do it anyway for orthogonality ** +void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, + dormant_clock_source_t dormant_clock_source, + const clock_dest_set_t *keep_enabled); + +#if !PICO_RP2040 +void low_power_pstate_until_aon_timer(void); +void low_power_pstate_until_pin_state(void); +#endif + +void low_power_setup_clocks_for_dormant(dormant_clock_source_t dormant_source); +void low_power_wake_from_dormant(void); + +#if 0 +void sleep_run_from_dormant_source(dormant_clock_source_t dormant_source); +/*! \brief Send system to sleep until a leading high edge is detected on GPIO + * \ingroup pico_sleep + * + * One of the sleep_run_* functions must be called prior to this call + * + * \param gpio_pin The pin to provide the wake up + */ +static inline void sleep_goto_dormant_until_edge_high(uint gpio_pin) { + sleep_goto_dormant_until_pin(gpio_pin, true, true); +} + +/*! \brief Send system to sleep until a high level is detected on GPIO + * \ingroup pico_sleep + * + * One of the sleep_run_* functions must be called prior to this call + * + * \param gpio_pin The pin to provide the wake up + */ +static inline void sleep_goto_dormant_until_level_high(uint gpio_pin) { + sleep_goto_dormant_until_pin(gpio_pin, false, true); +} + +#endif + +/*! \brief Reconfigure clocks to wake up properly from sleep/dormant mode + * \ingroup pico_sleep + * + * This must be called immediately after continuing execution when waking up from sleep/dormant mode + * + */ +void sleep_power_up(void); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c new file mode 100644 index 000000000..f42b454e0 --- /dev/null +++ b/src/rp2_common/pico_low_power/low_power.c @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "pico.h" + +#include "pico/low_power.h" +#include "pico/aon_timer.h" +#include "pico/runtime_init.h" + +#include "hardware/pll.h" +#include "hardware/claim.h" +#include "hardware/clocks.h" +#include "hardware/gpio.h" +#include "hardware/rosc.h" +#include "hardware/sync.h" +#include "hardware/timer.h" +#include "hardware/uart.h" +#include "hardware/watchdog.h" +#include "hardware/xosc.h" + +// todo this is a hack for now as we use setup_default_uart(); this is deliberately not in +// the library dependencies right now, as this should get fixed up by better "pre/post" clock +// setup hooks +#include "pico/stdlib.h" + +#if HAS_RP2040_RTC +#include "hardware/rtc.h" +#elif HAS_POWMAN_TIMER +#include "hardware/powman.h" +#endif + +// For __wfi +#ifdef __riscv +#include "hardware/riscv.h" +#else +// For scb_hw so we can enable deep sleep +#include "hardware/structs/scb.h" +#endif + + +// The difference between sleep and dormant is that ALL clocks are stopped in dormant mode, +// until the source (either xosc or rosc) is started again by an external event. +// In sleep mode some clocks can be left running controlled by the SLEEP_EN registers in the clocks +// block. For example you could keep clk_rtc running. Some destinations (proc0 and proc1 wakeup logic) +// can't be stopped in sleep mode otherwise there wouldn't be enough logic to wake up again. + + +// TODO: Optionally, memories can also be powered down. + +// ------------------------------------------------------------------------------------------------------ +// todo these probably belong in h/w clocks as some sort of registered thing, but leave them private here +// for now +static void prepare_for_clock_gating(void) { + // particularly for UART we want nothing left to clock out + stdio_flush(); +} + +static void post_clock_gating(void) { + +} + +static void prepare_for_clock_switch(void) { + // particularly for UART we want nothing left to clock out + prepare_for_clock_gating(); +} + +static void post_clock_switch(void) { + setup_default_uart(); +} +// ------------------------------------------------------------------------------------------------------ + +// todo should we make this a save/restore thing? +void low_power_enable_processor_deep_sleep(void) { + // Enable deep sleep at the proc +#ifdef __riscv + uint32_t bits = RVCSR_MSLEEP_POWERDOWN_BITS; + if (!get_core_num()) { + // todo errata ref + bits |= RVCSR_MSLEEP_DEEPSLEEP_BITS; + } + riscv_set_csr(RVCSR_MSLEEP_OFFSET, bits); +#else + scb_hw->scr |= ARM_CPU_PREFIXED(SCR_SLEEPDEEP_BITS); +#endif +} + +void low_power_disable_processor_deep_sleep(void) { +#ifdef __riscv + riscv_clear_csr(RVCSR_MSLEEP_OFFSET, RVCSR_MSLEEP_POWERDOWN_BITS | RVCSR_MSLEEP_DEEPSLEEP_BITS); +#else + scb_hw->scr &= ~ARM_CPU_PREFIXED(SCR_SLEEPDEEP_BITS); +#endif +} + +volatile bool event_happened; + +static void low_power_wakeup(void) { + event_happened = true; +} + +static void replace_null_enable_values(const clock_dest_set_t *keep_enabled, + clock_dest_set_t *local_keep_enabled) { + if (keep_enabled) { + *local_keep_enabled = *keep_enabled; + } else { + // default to keep nothing on + *local_keep_enabled = clock_dest_set_none(); + } +} + +// only the deep_sleep variant of this, as DORMANT cannot wake from TIMER +int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, + const clock_dest_set_t *keep_enabled) { + int alarm_num = timer_hardware_alarm_claim_unused(timer, false); + if (alarm_num < 0) return PICO_ERROR_INSUFFICIENT_RESOURCES; + + event_happened = false; + timer_hardware_alarm_set_callback(timer, alarm_num, ((hardware_alarm_callback_t )low_power_wakeup)); + if (timer_hardware_alarm_set_target(timer, alarm_num, until)) { + timer_hardware_alarm_unclaim(timer, alarm_num); + // the time has passed already + return 0; + } + + clock_dest_set_t local_keep_enabled; + replace_null_enable_values(keep_enabled, &local_keep_enabled); + // todo we need mapping of hardware to clocks; also this needs to come from AON timer + // we know that people in the wild (MicroPython) have wanted to do some mapping to also + // figure out what PLLs are still on via these bits +#if PICO_RP2040 + clock_dests_add(&local_keep_enabled, CLK_DEST_SYS_TIMER); +#elif PICO_RP2350 + clock_dest_set_add(&local_keep_enabled, timer_get_index(timer) ? CLK_DEST_SYS_TIMER1 : CLK_DEST_SYS_TIMER0); + clock_dest_set_add(&local_keep_enabled, CLK_DEST_REF_TICKS); +#else +#error Unknown processor +#endif + prepare_for_clock_gating(); + // gate clocks + clock_gate_sleep_en(&local_keep_enabled); + + low_power_enable_processor_deep_sleep(); + // Go to sleep until the wakeup event happens (note it may have happened already) + while (!event_happened) __wfi(); + low_power_disable_processor_deep_sleep(); + + timer_hardware_alarm_set_callback(timer, alarm_num, NULL); + timer_hardware_alarm_unclaim(timer, alarm_num); + + post_clock_gating(); + + return 0; +} + +// todo note this has (not surprisingly a lot of commonality with the timer one) +int low_power_sleep_until_aon_timer(absolute_time_t until, + const clock_dest_set_t *keep_enabled) { + event_happened = false; + + clock_dest_set_t local_keep_enabled; + replace_null_enable_values(keep_enabled, &local_keep_enabled); + // Turn off all clocks except for the timer + // todo we need mapping of hardware to clocks; also this needs to come from AON timer + // we know that people in the wild (MicroPython) have wanted to do some mapping to also + // figure out what PLLs are still on via these bits + // + // todo note also here that this should come from AON_TIMER via AON_TIMER_CLOCK_DEST_NUM() but + // how do we indicate multiple bits there; actually todo (graham) and no one steal this as it sounds + // fun, we probably want to have a "sparse" bitset macro encoded as 4 bytes or 8 bytes (for 4 or 7 indices + // between 0 and 254) - i say 7, to leave encoding space for maybe indices > 256 in the 8 byte variant +#if PICO_RP2040 + clock_dests_add(&local_keep_enabled, CLOCK_DEST_RTC_RTC); +#elif PICO_RP2350 + clock_dest_set_add(&local_keep_enabled, CLK_DEST_REF_POWMAN); +#else +#error Unknown processor +#endif + // todo catch race condition here (or just plain in the past) + struct timespec ts; + us_to_timespec(to_us_since_boot(until), &ts); + // note wakeup from low power == false, means don't wake up from dormant + aon_timer_enable_alarm(&ts, (aon_timer_alarm_handler_t)low_power_wakeup, false); + + prepare_for_clock_gating(); + // gate clocks + clock_gate_sleep_en(&local_keep_enabled); + + low_power_enable_processor_deep_sleep(); + // Go to sleep until the wakeup event happens (note it may have happened already) + while (!event_happened) { + __wfi(); + } + low_power_disable_processor_deep_sleep(); + + post_clock_gating(); + return 0; +} + + +// In order to go into dormant mode we need to be running from a stoppable clock source: +// either the xosc or rosc with no PLLs running. This means we disable the USB and ADC clocks +// and all PLLs +void low_power_setup_clocks_for_dormant(dormant_clock_source_t dormant_source) { + prepare_for_clock_switch(); + + uint src_hz; + uint32_t clk_ref_src; + switch (dormant_source) { + case DORMANT_CLOCK_SOURCE_XOSC: + src_hz = XOSC_HZ; + clk_ref_src = CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC; + break; + case DORMANT_CLOCK_SOURCE_ROSC: + src_hz = 6500 * KHZ; // todo + clk_ref_src = CLOCKS_CLK_REF_CTRL_SRC_VALUE_ROSC_CLKSRC_PH; + break; +#if !PICO_RP2040 + case DORMANT_CLOCK_SOURCE_LPOSC: + src_hz = 32 * KHZ; + clk_ref_src = CLOCKS_CLK_REF_CTRL_SRC_VALUE_LPOSC_CLKSRC; + break; +#endif + default: + hard_assert(false); + } + + clock_configure_undivided(clk_ref, + clk_ref_src, + 0, + src_hz); + + // CLK SYS = CLK_REF + clock_configure_undivided(clk_sys, + CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF, + 0, // Using glitchless mux + src_hz); + + + // CLK ADC = 0MHz + clock_stop(clk_adc); + clock_stop(clk_usb); +#if HAS_HSTX + clock_stop(clk_hstx); +#endif + +#if HAS_RP2040_RTC + // CLK RTC = ideally XOSC (12MHz) / 256 = 46875Hz but could be rosc + uint clk_rtc_src = (dormant_source == DORMANT_CLOCK_SOURCE_XOSC) ? + CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC : + CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH; + + clock_configure(clk_rtc, + 0, // No GLMUX + clk_rtc_src, + src_hz, + 46875); +#endif + + // CLK PERI = clk_sys. Used as reference clock for Peripherals. No dividers so just select and enable + clock_configure(clk_peri, + 0, + CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS, + src_hz, + src_hz); + + pll_deinit(pll_sys); + pll_deinit(pll_usb); + + // Assuming both xosc and rosc are running at the moment + if (dormant_source == DORMANT_CLOCK_SOURCE_XOSC) { + // Safe to disable rosc + rosc_disable(); + } else { + // Safe to disable xosc + xosc_disable(); + } +} + +//To be called after waking up from sleep/dormant mode to restore system clocks properly +void low_power_wake_from_dormant(void) { + //Re-enable the ring oscillator, which will essentially kickstart the proc + rosc_restart(); + + post_clock_gating(); + + //Restore all inactive clocks + runtime_init_clocks(); + post_clock_switch(); +} + +void low_power_go_dormant(dormant_clock_source_t dormant_clock_source) { + assert(dormant_clock_source == DORMANT_CLOCK_SOURCE_XOSC || dormant_clock_source == DORMANT_CLOCK_SOURCE_ROSC); + + if (dormant_clock_source == DORMANT_CLOCK_SOURCE_XOSC) { + xosc_dormant(); + } else { + rosc_set_dormant(); + } +} + +int low_power_dormant_until_aon_timer(absolute_time_t until, + dormant_clock_source_t dormant_clock_source, + __unused uint src_hz, uint gpio_pin, + const clock_dest_set_t *keep_enabled) { + low_power_setup_clocks_for_dormant(dormant_clock_source); + + clock_dest_set_t local_keep_enabled; + replace_null_enable_values(keep_enabled, &local_keep_enabled); + + // todo ugh this doesn't really belong here like this; need to encapsulate in aon timer? +#if PICO_RP2040 + // The RTC must be run from an external source, since the dormant source will be inactive + rtc_run_from_external_source(src_hz, gpio_pin); + clock_dests_add(&local_keep_enabled, CLOCK_DEST_RTC_RTC); +#elif PICO_RP2350 + // todo + ((void)gpio_pin); + if (dormant_clock_source == DORMANT_CLOCK_SOURCE_LPOSC) + powman_timer_set_1khz_tick_source_lposc(); + else + return PICO_ERROR_INVALID_ARG; + + clock_dest_set_add(&local_keep_enabled, CLK_DEST_REF_POWMAN); +#else + #error Unknown processor +#endif + + // todo catch race condition here (or just plain in the past) + struct timespec ts; + us_to_timespec(to_us_since_boot(until), &ts); + event_happened = false; + // note wakeup from low power == false, means don't wake up from dormant + aon_timer_enable_alarm(&ts, (aon_timer_alarm_handler_t)low_power_wakeup, true); + + prepare_for_clock_gating(); + // gate clocks + clock_gate_sleep_en(&local_keep_enabled); + + low_power_enable_processor_deep_sleep(); + + //Go dormant + low_power_go_dormant(dormant_clock_source); + + + assert(event_happened); // does it? + low_power_wake_from_dormant(); + + return 0; +} + +void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, + dormant_clock_source_t dormant_clock_source, + const clock_dest_set_t *keep_enabled) { + + low_power_setup_clocks_for_dormant(dormant_clock_source); + + clock_dest_set_t local_keep_enabled; + replace_null_enable_values(keep_enabled, &local_keep_enabled); + + bool low = !high; + bool level = !edge; + + // Configure the appropriate IRQ at IO bank 0 + assert(gpio_pin < NUM_BANK0_GPIOS); + + uint32_t event = 0; + + if (level && low) event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_LEVEL_LOW_BITS; + if (level && high) event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_LEVEL_HIGH_BITS; + if (edge && high) event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_EDGE_HIGH_BITS; + if (edge && low) event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_EDGE_LOW_BITS; + + gpio_init(gpio_pin); + gpio_set_input_enabled(gpio_pin, true); + gpio_set_dormant_irq_enabled(gpio_pin, event, true); + + prepare_for_clock_gating(); + // gate clocks + clock_gate_sleep_en(&local_keep_enabled); + + low_power_enable_processor_deep_sleep(); + + //Go dormant + low_power_go_dormant(dormant_clock_source); + + // Clear the irq so we can go back to dormant mode again if we want + gpio_acknowledge_irq(gpio_pin, event); + gpio_set_input_enabled(gpio_pin, false); + + low_power_wake_from_dormant(); +} + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c772bda63..f0643298e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,4 +14,5 @@ if (PICO_ON_DEVICE) add_subdirectory(cmsis_test) add_subdirectory(pico_sem_test) add_subdirectory(pico_sha256_test) + add_subdirectory(hello_sleep) endif() diff --git a/test/hello_sleep/CMakeLists.txt b/test/hello_sleep/CMakeLists.txt new file mode 100644 index 000000000..fb1abb738 --- /dev/null +++ b/test/hello_sleep/CMakeLists.txt @@ -0,0 +1,8 @@ +add_executable(hello_sleep + hello_sleep.c + ) + +target_link_libraries(hello_sleep pico_stdlib pico_low_power) + +# create map/bin/hex file etc. +pico_add_extra_outputs(hello_sleep) \ No newline at end of file diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c new file mode 100644 index 000000000..76d2392be --- /dev/null +++ b/test/hello_sleep/hello_sleep.c @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "pico/stdlib.h" +#include "pico/low_power.h" +#include "pico/aon_timer.h" + +bool repeater(repeating_timer_t *timer) { + printf("Repeating timer at %dms\n", time_us_32() / 1000); + return true; +} + +int main() { + stdio_init_all(); + printf("Hello Sleep!\n"); +#if PICO_RP2350 + // use a second repeating timer on the other TIMER instance; it should be gated + // during our sleep (todo not sure how it affects power!) + alarm_pool_t *alarm_pool = alarm_pool_create_on_timer_with_unused_hardware_alarm(timer1_hw, 4); + repeating_timer_t repeat; + alarm_pool_add_repeating_timer_ms(alarm_pool, 500, repeater, NULL, &repeat); + printf("Waiting 1 sec\n"); // so we can see some repeat printfs + busy_wait_ms(1100); +#endif + printf("Going to sleep for 5 seconds via TIMER\n"); + + absolute_time_t start_time = get_absolute_time(); + absolute_time_t wakeup_time = delayed_by_ms(start_time, 5000); + low_power_sleep_until_timer(timer_hw, wakeup_time, NULL); + int64_t diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); + printf("Woken up now @%dus since target\n", (int)diff); + if (diff < 0) { + printf("ERROR: Woke up too soon\n"); + return -1; + } + busy_wait_ms(3000); + + printf("Going to sleep for 5 seconds via AON TIMER\n"); + + // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync + start_time = get_absolute_time(); + struct timespec ts; + us_to_timespec(start_time, &ts); + aon_timer_start(&ts); + + wakeup_time = delayed_by_ms(start_time, 5000); + low_power_sleep_until_aon_timer(wakeup_time, NULL); + diff = absolute_time_diff_us(get_absolute_time(), wakeup_time); + // need to use the AON timer for checking time, since the other timer is unclocked + diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); + if (diff > -4000000) { + printf("ERROR: doesn't seem like timer was stopped\n"); + return - 1; + } + aon_timer_get_time(&ts); + uint64_t current_aon = timespec_to_us(&ts); + diff = absolute_time_diff_us(wakeup_time, from_us_since_boot(current_aon)); + printf("Woken up now @%dus since target\n", (int)diff); + if (diff < 0) { + printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); + } + printf("5 second pause to prove timer still running\n"); + busy_wait_ms(5000); + + printf("Going DORMANT for 5 seconds via AON TIMER\n"); + + // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync + start_time = get_absolute_time(); + us_to_timespec(start_time, &ts); + aon_timer_start(&ts); + + wakeup_time = delayed_by_ms(start_time, 5000); + low_power_dormant_until_aon_timer(wakeup_time, DORMANT_CLOCK_SOURCE_LPOSC, XOSC_KHZ * 1000, + 0, // gpio pin (unused with powman) + NULL); + low_power_sleep_until_aon_timer(wakeup_time, NULL); + diff = absolute_time_diff_us(get_absolute_time(), wakeup_time); + // need to use the AON timer for checking time, since the other timer is unclocked + diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); + if (diff > -4000000) { + printf("ERROR: doesn't seem like timer was stopped\n"); + return - 1; + } + aon_timer_get_time(&ts); + current_aon = timespec_to_us(&ts); + diff = absolute_time_diff_us(wakeup_time, from_us_since_boot(current_aon)); + printf("Woken up now @%dus since target\n", (int)diff); + if (diff < 0) { + printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); + } + printf("Final 5 second pause to prove timer still running\n"); + busy_wait_ms(5000); + + printf("SUCCESS\n"); + + return 0; +} \ No newline at end of file diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt index 1d6110f4c..e605f0885 100644 --- a/test/kitchen_sink/CMakeLists.txt +++ b/test/kitchen_sink/CMakeLists.txt @@ -46,6 +46,7 @@ set(KITCHEN_SINK_LIBS pico_float pico_i2c_slave pico_int64_ops + pico_low_power pico_malloc pico_mem_ops pico_multicore diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index 7bc2bcd11..7c4202e90 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -84,9 +84,35 @@ int main(void) { hard_assert(!mutex_try_enter(&mutex, NULL)); hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL)); hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL)); + typedef bitset_type_t(47) foop_t; +//#define WOOP encoded_bitset_of3(1, 27, 32) +#define WOOP encoded_bitset_of5(1, 27, 32, 40, 3) + encoded_bitset_foreach(WOOP, printf("Flarn %d\n", bit)); + foop_t fooper; + bitset_init(&fooper, foop_t, 47, 0); + encoded_bitset_foreach(WOOP, bitset_set_bit(&fooper.bitset, bit)); + for(uint i=0;i Date: Thu, 12 Dec 2024 13:42:52 +0000 Subject: [PATCH 019/127] Add sleep3 notes from meeting --- .../pico_low_power/include/pico/low_power.h | 63 +++++++++++++------ 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 999d3870a..d26642186 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -26,6 +26,8 @@ extern "C" { * block. For example you could keep clk_rtc running. Some destinations (proc0 and proc1 wakeup logic) * can't be stopped in sleep mode otherwise there wouldn't be enough logic to wake up again. * + * In pstate mode some power domains are switched off and don't retain state. + * * \subsection sleep_example Example * \addtogroup pico_sleep * \include hello_sleep.c @@ -38,48 +40,69 @@ extern "C" { #include "hardware/clocks.h" -typedef enum { - DORMANT_CLOCK_SOURCE_XOSC, - DORMANT_CLOCK_SOURCE_ROSC, -#if !PICO_RP2040 - DORMANT_CLOCK_SOURCE_LPOSC, -#endif -} dormant_clock_source_t; +// NOTE: Need to deinit usb before doing into any of these sleep states +// could keep usb clk_sys and clk_usb to usbctrl running during low_power_sleep. Although you'll get woken +// up pretty quickly +// Also you are plugged into a host so why bother? + +// sleep is really just calling a __wfi() until an irq, with some optional clock gating in the sleep_en register. Activated once processor goes to sleep +// So can just do it for arbitrary interrupts. processors implement their own internal clock gating, just leaving the wakeup interrupt controller running during +// __wfi() +int low_power_sleep_until_irq(const clock_dest_set_t *keep_enabled) // sleep until the given timer reaches the specified value; if the time passes then no sleep occurs // keep_enabled defaults to none if NULL // ** LIAM BLESSED ** -int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, const clock_dest_set_t *keep_enabled); +int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, const clock_dest_set_t *keep_enabled, bool exclusive); +// Note bool above saying shall we only listen for timer irq or other irqs +// Need to defer handling of irqs to do clock setup etc -static inline int low_power_deep_sleep_until_default_timer(absolute_time_t until, const clock_dest_set_t *keep_enabled) { +static inline int low_power_sleep_until_default_timer(absolute_time_t until, const clock_dest_set_t *keep_enabled) { + // Need to assert (or add) ticks block and timer clocks to the keep_enabled list return low_power_sleep_until_timer(PICO_DEFAULT_TIMER_INSTANCE(), until, keep_enabled); } // ** LIAM BLESSED this for RP2040; why not RP2350 ** +// This should work on both via io bank interrupts void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high); // ** LIAM SAYS THIS IS NO MORE USEFUL THAN SLEEP_UNTIL TIMER... ** +// There isn't much advantage to using the aon timer here as system timers are more accurate and on anyway int low_power_sleep_until_aon_timer(absolute_time_t until, const clock_dest_set_t *keep_enabled); // ** LIAM BLESSED but we need to impl it correctly (note not blessed for RP2040, but we should do it anyway for orthogonality ** -int low_power_dormant_until_aon_timer(absolute_time_t until, - dormant_clock_source_t dormant_clock_source, - uint src_hz, uint gpio_pin, - const clock_dest_set_t *keep_enabled); +// Only works for RP2350 as every clock will be stopped on RP2040 (unless you provide a clock for the RTC) +// Easier to not support on RP2040 - might as well buy a 2350 + +// NOTE: Asserting that we will alway use rosc for dormant and simplifies the API +// Means if the user has sped up the rosc they should slow it down before going into dormant +// Need to re initialize clocks after this +int low_power_dormant_until_aon_timer(absolute_time_t until, uint src_hz, uint gpio_pin); // ** LIAM BLESSED but we need to impl it correctly (note not blessed for RP2040, but we should do it anyway for orthogonality ** -void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, - dormant_clock_source_t dormant_clock_source, - const clock_dest_set_t *keep_enabled); +// This works on both +// Need to re initialize clocks after this +void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high); #if !PICO_RP2040 -void low_power_pstate_until_aon_timer(void); -void low_power_pstate_until_pin_state(void); +// pstate functions should return to the pstate you were in +void low_power_pstate_until_aon_timer(pstate_bitset_t *pstate); +void low_power_pstate_until_pin_state(pstate_bitset_t *pstate); #endif -void low_power_setup_clocks_for_dormant(dormant_clock_source_t dormant_source); -void low_power_wake_from_dormant(void); +// Or a function saying how did I boot? +// Would like to make it easy to get back to main after going to sleep + +// Two configs: +// - Everything off apart from AON, ram needs zeroing on boot +// - Switched core off (args are which rams you want to keep on) +// Switched core, XIP cache + bootram, SRAM0 bank, SRAM1 bank + SCRATCH + +// Go to a pstate +// Doesn't support powering down switched core domain +void low_power_pstate_set(pstate_bitset_t *pstate); +pstate_bitset_t low_power_pstate_get(void); #if 0 void sleep_run_from_dormant_source(dormant_clock_source_t dormant_source); From c81b09fea18bc8f2c2c6817c7c554925894f3949 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 20 Aug 2025 17:14:19 +0100 Subject: [PATCH 020/127] Make it compile and work with RP2040 and RP2350 Includes AMY-1782 workaround --- .../pico_low_power/include/pico/low_power.h | 33 +++++++++----- src/rp2_common/pico_low_power/low_power.c | 37 +++++++++++++--- .../include/pico/runtime_init.h | 16 +++++++ test/hello_sleep/hello_sleep.c | 43 ++++++------------- 4 files changed, 82 insertions(+), 47 deletions(-) diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index d26642186..2a215acc9 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -41,6 +41,16 @@ extern "C" { #include "hardware/clocks.h" +typedef enum { + DORMANT_CLOCK_SOURCE_XOSC, + DORMANT_CLOCK_SOURCE_ROSC, +#if !PICO_RP2040 + DORMANT_CLOCK_SOURCE_LPOSC, +#endif + NUM_DORMANT_CLOCK_SOURCES +} dormant_clock_source_t; + + // NOTE: Need to deinit usb before doing into any of these sleep states // could keep usb clk_sys and clk_usb to usbctrl running during low_power_sleep. Although you'll get woken // up pretty quickly @@ -49,7 +59,7 @@ extern "C" { // sleep is really just calling a __wfi() until an irq, with some optional clock gating in the sleep_en register. Activated once processor goes to sleep // So can just do it for arbitrary interrupts. processors implement their own internal clock gating, just leaving the wakeup interrupt controller running during // __wfi() -int low_power_sleep_until_irq(const clock_dest_set_t *keep_enabled) +int low_power_sleep_until_irq(const clock_dest_set_t *keep_enabled); // sleep until the given timer reaches the specified value; if the time passes then no sleep occurs // keep_enabled defaults to none if NULL @@ -58,18 +68,21 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, const // Note bool above saying shall we only listen for timer irq or other irqs // Need to defer handling of irqs to do clock setup etc -static inline int low_power_sleep_until_default_timer(absolute_time_t until, const clock_dest_set_t *keep_enabled) { +static inline int low_power_sleep_until_default_timer(absolute_time_t until, const clock_dest_set_t *keep_enabled, bool exclusive) { // Need to assert (or add) ticks block and timer clocks to the keep_enabled list - return low_power_sleep_until_timer(PICO_DEFAULT_TIMER_INSTANCE(), until, keep_enabled); + return low_power_sleep_until_timer(PICO_DEFAULT_TIMER_INSTANCE(), until, keep_enabled, exclusive); } // ** LIAM BLESSED this for RP2040; why not RP2350 ** // This should work on both via io bank interrupts void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high); +#if 0 // ** LIAM SAYS THIS IS NO MORE USEFUL THAN SLEEP_UNTIL TIMER... ** // There isn't much advantage to using the aon timer here as system timers are more accurate and on anyway +// ** WILL AGREES WITH LIAM ON THIS ** int low_power_sleep_until_aon_timer(absolute_time_t until, const clock_dest_set_t *keep_enabled); +#endif // ** LIAM BLESSED but we need to impl it correctly (note not blessed for RP2040, but we should do it anyway for orthogonality ** // Only works for RP2350 as every clock will be stopped on RP2040 (unless you provide a clock for the RTC) @@ -78,18 +91,17 @@ int low_power_sleep_until_aon_timer(absolute_time_t until, const clock_dest_set_ // NOTE: Asserting that we will alway use rosc for dormant and simplifies the API // Means if the user has sped up the rosc they should slow it down before going into dormant // Need to re initialize clocks after this -int low_power_dormant_until_aon_timer(absolute_time_t until, uint src_hz, uint gpio_pin); +int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_source_t dormant_clock_source, uint src_hz, uint gpio_pin, const clock_dest_set_t *keep_enabled); // ** LIAM BLESSED but we need to impl it correctly (note not blessed for RP2040, but we should do it anyway for orthogonality ** // This works on both // Need to re initialize clocks after this -void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high); +void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_set_t *keep_enabled); -#if !PICO_RP2040 +#if !PICO_RP2040 && 0 // todo - implement these // pstate functions should return to the pstate you were in void low_power_pstate_until_aon_timer(pstate_bitset_t *pstate); void low_power_pstate_until_pin_state(pstate_bitset_t *pstate); -#endif // Or a function saying how did I boot? // Would like to make it easy to get back to main after going to sleep @@ -103,8 +115,9 @@ void low_power_pstate_until_pin_state(pstate_bitset_t *pstate); // Doesn't support powering down switched core domain void low_power_pstate_set(pstate_bitset_t *pstate); pstate_bitset_t low_power_pstate_get(void); +#endif -#if 0 +#if 0 // todo - I think these are not being done? void sleep_run_from_dormant_source(dormant_clock_source_t dormant_source); /*! \brief Send system to sleep until a leading high edge is detected on GPIO * \ingroup pico_sleep @@ -128,8 +141,6 @@ static inline void sleep_goto_dormant_until_level_high(uint gpio_pin) { sleep_goto_dormant_until_pin(gpio_pin, false, true); } -#endif - /*! \brief Reconfigure clocks to wake up properly from sleep/dormant mode * \ingroup pico_sleep * @@ -138,6 +149,8 @@ static inline void sleep_goto_dormant_until_level_high(uint gpio_pin) { */ void sleep_power_up(void); +#endif + #ifdef __cplusplus } #endif diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index f42b454e0..e9092f3f4 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -59,7 +59,9 @@ static void prepare_for_clock_gating(void) { } static void post_clock_gating(void) { - + // restore all clocks in sleep mode, to prevent other __wfi from causing issues + clock_dest_set_t all = clock_dest_set_all(); + clock_gate_sleep_en(&all); } static void prepare_for_clock_switch(void) { @@ -113,7 +115,7 @@ static void replace_null_enable_values(const clock_dest_set_t *keep_enabled, // only the deep_sleep variant of this, as DORMANT cannot wake from TIMER int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, - const clock_dest_set_t *keep_enabled) { + const clock_dest_set_t *keep_enabled, __unused bool exclusive) { int alarm_num = timer_hardware_alarm_claim_unused(timer, false); if (alarm_num < 0) return PICO_ERROR_INSUFFICIENT_RESOURCES; @@ -131,7 +133,7 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, // we know that people in the wild (MicroPython) have wanted to do some mapping to also // figure out what PLLs are still on via these bits #if PICO_RP2040 - clock_dests_add(&local_keep_enabled, CLK_DEST_SYS_TIMER); + clock_dest_set_add(&local_keep_enabled, CLK_DEST_SYS_TIMER); #elif PICO_RP2350 clock_dest_set_add(&local_keep_enabled, timer_get_index(timer) ? CLK_DEST_SYS_TIMER1 : CLK_DEST_SYS_TIMER0); clock_dest_set_add(&local_keep_enabled, CLK_DEST_REF_TICKS); @@ -155,6 +157,7 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, return 0; } +#if 0 // todo note this has (not surprisingly a lot of commonality with the timer one) int low_power_sleep_until_aon_timer(absolute_time_t until, const clock_dest_set_t *keep_enabled) { @@ -172,7 +175,7 @@ int low_power_sleep_until_aon_timer(absolute_time_t until, // fun, we probably want to have a "sparse" bitset macro encoded as 4 bytes or 8 bytes (for 4 or 7 indices // between 0 and 254) - i say 7, to leave encoding space for maybe indices > 256 in the 8 byte variant #if PICO_RP2040 - clock_dests_add(&local_keep_enabled, CLOCK_DEST_RTC_RTC); + clock_dest_set_add(&local_keep_enabled, CLOCK_DEST_RTC_RTC); #elif PICO_RP2350 clock_dest_set_add(&local_keep_enabled, CLK_DEST_REF_POWMAN); #else @@ -198,7 +201,7 @@ int low_power_sleep_until_aon_timer(absolute_time_t until, post_clock_gating(); return 0; } - +#endif // In order to go into dormant mode we need to be running from a stoppable clock source: // either the xosc or rosc with no PLLs running. This means we disable the USB and ADC clocks @@ -225,6 +228,7 @@ void low_power_setup_clocks_for_dormant(dormant_clock_source_t dormant_source) { #endif default: hard_assert(false); + __builtin_unreachable(); } clock_configure_undivided(clk_ref, @@ -314,7 +318,7 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, #if PICO_RP2040 // The RTC must be run from an external source, since the dormant source will be inactive rtc_run_from_external_source(src_hz, gpio_pin); - clock_dests_add(&local_keep_enabled, CLOCK_DEST_RTC_RTC); + clock_dest_set_add(&local_keep_enabled, CLK_DEST_RTC_RTC); #elif PICO_RP2350 // todo ((void)gpio_pin); @@ -393,3 +397,24 @@ void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, low_power_wake_from_dormant(); } +#if !PICO_RUNTIME_NO_INIT_RP2350_SLEEP_FIX +#include "hardware/sync.h" +void __weak runtime_init_rp2350_sleep_fix(void) { + if (watchdog_hw->reason && WATCHDOG_REASON_TIMER_BITS) { // detect rom_reboot() usage + int alarm_num = timer_hardware_alarm_claim_unused(timer_hw, false); + if (alarm_num < 0) return; + + timer_hardware_alarm_set_callback(timer_hw, alarm_num, ((hardware_alarm_callback_t )low_power_wakeup)); + timer_hardware_alarm_set_target(timer_hw, alarm_num, make_timeout_time_us(100)); + + __wfi(); + + timer_hardware_alarm_set_callback(timer_hw, alarm_num, NULL); + timer_hardware_alarm_unclaim(timer_hw, alarm_num); + } +} +#endif + +#if !PICO_RUNTIME_SKIP_INIT_RP2350_SLEEP_FIX +PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_rp2350_sleep_fix, PICO_RUNTIME_INIT_RP2350_SLEEP_FIX); +#endif diff --git a/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h b/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h index c6ed4cf8e..f93590fe6 100644 --- a/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h +++ b/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h @@ -416,6 +416,22 @@ void runtime_init_bootrom_locking_enable(void); #endif #endif +// ------------------------------------------------------------ +// RP2350 sleep fix +// ------------------------------------------------------------ + +#ifndef PICO_RUNTIME_INIT_RP2350_SLEEP_FIX +#define PICO_RUNTIME_INIT_RP2350_SLEEP_FIX "11010" +#endif + +#ifndef PICO_RUNTIME_SKIP_INIT_RP2350_SLEEP_FIX +#define PICO_RUNTIME_SKIP_INIT_RP2350_SLEEP_FIX !PICO_RP2350 +#endif + +#ifndef PICO_RUNTIME_NO_INIT_RP2350_SLEEP_FIX +#define PICO_RUNTIME_NO_INIT_RP2350_SLEEP_FIX !PICO_RP2350 +#endif + // ------------------------------------------------------------------------------------------------ // stack guard; these are a special case as they take a parameter; however the normal defines apply // ------------------------------------------------------------------------------------------------ diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index 76d2392be..404a6290e 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -26,46 +26,27 @@ int main() { printf("Waiting 1 sec\n"); // so we can see some repeat printfs busy_wait_ms(1100); #endif - printf("Going to sleep for 5 seconds via TIMER\n"); - absolute_time_t start_time = get_absolute_time(); - absolute_time_t wakeup_time = delayed_by_ms(start_time, 5000); - low_power_sleep_until_timer(timer_hw, wakeup_time, NULL); - int64_t diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); - printf("Woken up now @%dus since target\n", (int)diff); - if (diff < 0) { - printf("ERROR: Woke up too soon\n"); - return -1; - } - busy_wait_ms(3000); + absolute_time_t start_time; + absolute_time_t wakeup_time; + int64_t diff; + uint64_t current_aon; + struct timespec ts; - printf("Going to sleep for 5 seconds via AON TIMER\n"); + printf("Going to sleep for 5 seconds via TIMER\n"); - // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync start_time = get_absolute_time(); - struct timespec ts; - us_to_timespec(start_time, &ts); - aon_timer_start(&ts); - wakeup_time = delayed_by_ms(start_time, 5000); - low_power_sleep_until_aon_timer(wakeup_time, NULL); - diff = absolute_time_diff_us(get_absolute_time(), wakeup_time); - // need to use the AON timer for checking time, since the other timer is unclocked + low_power_sleep_until_timer(timer_hw, wakeup_time, NULL, true); diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); - if (diff > -4000000) { - printf("ERROR: doesn't seem like timer was stopped\n"); - return - 1; - } - aon_timer_get_time(&ts); - uint64_t current_aon = timespec_to_us(&ts); - diff = absolute_time_diff_us(wakeup_time, from_us_since_boot(current_aon)); printf("Woken up now @%dus since target\n", (int)diff); if (diff < 0) { - printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); + printf("ERROR: Woke up too soon\n"); + return -1; } - printf("5 second pause to prove timer still running\n"); - busy_wait_ms(5000); + busy_wait_ms(3000); +#if !PICO_RP2040 printf("Going DORMANT for 5 seconds via AON TIMER\n"); // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync @@ -77,7 +58,6 @@ int main() { low_power_dormant_until_aon_timer(wakeup_time, DORMANT_CLOCK_SOURCE_LPOSC, XOSC_KHZ * 1000, 0, // gpio pin (unused with powman) NULL); - low_power_sleep_until_aon_timer(wakeup_time, NULL); diff = absolute_time_diff_us(get_absolute_time(), wakeup_time); // need to use the AON timer for checking time, since the other timer is unclocked diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); @@ -94,6 +74,7 @@ int main() { } printf("Final 5 second pause to prove timer still running\n"); busy_wait_ms(5000); +#endif printf("SUCCESS\n"); From 1807c25e841eba27bc196fce73c602bbc67d999c Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 21 Aug 2025 15:10:42 +0100 Subject: [PATCH 021/127] Implement pstate functions --- .../hardware_powman/include/hardware/powman.h | 40 ++++++ src/rp2_common/pico_aon_timer/aon_timer.c | 6 + .../pico_aon_timer/include/pico/aon_timer.h | 7 + .../pico_low_power/include/pico/low_power.h | 12 +- src/rp2_common/pico_low_power/low_power.c | 84 ++++++++++++ .../include/pico/runtime_init.h | 16 +++ test/hello_sleep/CMakeLists.txt | 2 +- test/hello_sleep/hello_sleep.c | 121 ++++++++++++++++-- 8 files changed, 268 insertions(+), 20 deletions(-) diff --git a/src/rp2_common/hardware_powman/include/hardware/powman.h b/src/rp2_common/hardware_powman/include/hardware/powman.h index 94988035d..e7dbad278 100644 --- a/src/rp2_common/hardware_powman/include/hardware/powman.h +++ b/src/rp2_common/hardware_powman/include/hardware/powman.h @@ -9,6 +9,7 @@ #include "pico.h" #include "hardware/structs/powman.h" +#include "pico/util/bitset.h" #ifdef __cplusplus extern "C" { @@ -167,9 +168,48 @@ enum powman_power_domains { POWMAN_POWER_DOMAIN_SWITCHED_CORE = 3, ///< Switched core logic (processors, busfabric, peris etc) POWMAN_POWER_DOMAIN_COUNT = 4, }; +typedef enum powman_power_domains powman_power_domain_t; typedef uint32_t powman_power_state; +typedef bitset_type_t(POWMAN_POWER_DOMAIN_COUNT) pstate_bitset_t; +#define pstate_bitset_none() ({ pstate_bitset_t bitset; bitset_init(&bitset, pstate_bitset_t, POWMAN_POWER_DOMAIN_COUNT, 0); bitset; }) +#define pstate_bitset_all() ({ pstate_bitset_t bitset; bitset_init(&bitset, pstate_bitset_t, POWMAN_POWER_DOMAIN_COUNT, 1); bitset; }) + +static inline pstate_bitset_t *pstate_bitset_clear(pstate_bitset_t *domains) { + bitset_clear(&domains->bitset); + return domains; +} + +static inline pstate_bitset_t *pstate_bitset_add_all(pstate_bitset_t *domains) { + bitset_set_all(&domains->bitset); + return domains; +} + +static inline pstate_bitset_t *pstate_bitset_add(pstate_bitset_t *domains, powman_power_domain_t domain) { + bitset_set_bit(&domains->bitset, domain); + return domains; +} + +static inline pstate_bitset_t *pstate_bitset_remove(pstate_bitset_t *domains, powman_power_domain_t domain) { + bitset_clear_bit(&domains->bitset, domain); + return domains; +} + +static inline bool pstate_bitset_is_set(pstate_bitset_t *domains, powman_power_domain_t domain) { + return bitset_get_bit(&domains->bitset, domain); +} + +static inline pstate_bitset_t pstate_bitset_from_powman_power_state(powman_power_state pstate) { + pstate_bitset_t bitset; + bitset_init(&bitset, pstate_bitset_t, POWMAN_POWER_DOMAIN_COUNT, pstate); + return bitset; +} + +static inline powman_power_state pstate_bitset_to_powman_power_state(pstate_bitset_t *pstate) { + return pstate->bitset.words[0]; +} + /*! \brief Get the current power state * \ingroup hardware_powman */ diff --git a/src/rp2_common/pico_aon_timer/aon_timer.c b/src/rp2_common/pico_aon_timer/aon_timer.c index 62ef6c27a..b9a2e33e9 100644 --- a/src/rp2_common/pico_aon_timer/aon_timer.c +++ b/src/rp2_common/pico_aon_timer/aon_timer.c @@ -102,6 +102,12 @@ bool aon_timer_get_time_calendar(struct tm *tm) { #endif } +absolute_time_t aon_timer_get_absolute_time(void) { + struct timespec ts; + aon_timer_get_time(&ts); + return from_us_since_boot(timespec_to_us(&ts)); +} + aon_timer_alarm_handler_t aon_timer_enable_alarm(const struct timespec *ts, aon_timer_alarm_handler_t handler, bool wakeup_from_low_power) { #if HAS_RP2040_RTC struct tm tm; diff --git a/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h b/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h index b3095d8e0..f78b617dd 100644 --- a/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h +++ b/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h @@ -180,6 +180,13 @@ bool aon_timer_get_time(struct timespec *ts); */ bool aon_timer_get_time_calendar(struct tm *tm); +/** + * \brief Get the current time of the AON timer as an absolute time + * \ingroup pico_aon_timer + * \return the current time of the AON timer as an absolute time + */ +absolute_time_t aon_timer_get_absolute_time(void); + /** * \brief Get the resolution of the AON timer * \ingroup pico_aon_timer diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 2a215acc9..06ab74640 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -39,7 +39,7 @@ extern "C" { #endif #include "hardware/clocks.h" - +#include "hardware/powman.h" typedef enum { DORMANT_CLOCK_SOURCE_XOSC, @@ -50,6 +50,8 @@ typedef enum { NUM_DORMANT_CLOCK_SOURCES } dormant_clock_source_t; +typedef void (*low_power_pstate_resume_func)(void); + // NOTE: Need to deinit usb before doing into any of these sleep states // could keep usb clk_sys and clk_usb to usbctrl running during low_power_sleep. Although you'll get woken @@ -98,10 +100,10 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_sourc // Need to re initialize clocks after this void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_set_t *keep_enabled); -#if !PICO_RP2040 && 0 // todo - implement these +#if !PICO_RP2040 // pstate functions should return to the pstate you were in -void low_power_pstate_until_aon_timer(pstate_bitset_t *pstate); -void low_power_pstate_until_pin_state(pstate_bitset_t *pstate); +int low_power_pstate_until_aon_timer(absolute_time_t until, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func); +int low_power_pstate_until_pin_state(uint gpio_pin, bool edge, bool high, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func); // Or a function saying how did I boot? // Would like to make it easy to get back to main after going to sleep @@ -113,7 +115,7 @@ void low_power_pstate_until_pin_state(pstate_bitset_t *pstate); // Go to a pstate // Doesn't support powering down switched core domain -void low_power_pstate_set(pstate_bitset_t *pstate); +int low_power_pstate_set(pstate_bitset_t *pstate); pstate_bitset_t low_power_pstate_get(void); #endif diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index e9092f3f4..9cd0cad42 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -72,6 +72,16 @@ static void prepare_for_clock_switch(void) { static void post_clock_switch(void) { setup_default_uart(); } + +#if HAS_POWMAN_TIMER +static void prepare_for_pstate_change(void) { + prepare_for_clock_switch(); +} + +static void post_pstate_change(void) { +} +#endif + // ------------------------------------------------------------------------------------------------------ // todo should we make this a save/restore thing? @@ -397,6 +407,80 @@ void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, low_power_wake_from_dormant(); } +#if !PICO_RP2040 +int low_power_pstate_set(pstate_bitset_t *pstate) { + invalid_params_if(PICO_LOW_POWER, !pstate_bitset_is_set(pstate, POWMAN_POWER_DOMAIN_SWITCHED_CORE)); + + return powman_set_power_state(pstate_bitset_to_powman_power_state(pstate)); +} + +pstate_bitset_t low_power_pstate_get(void) { + return pstate_bitset_from_powman_power_state(powman_get_power_state()); +} + +int low_power_go_pstate(pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func) { + prepare_for_pstate_change(); + + // Configure the wakeup state + pstate_bitset_t current_pstate = low_power_pstate_get(); + bool valid_state = powman_configure_wakeup_state(pstate_bitset_to_powman_power_state(pstate), pstate_bitset_to_powman_power_state(¤t_pstate)); + if (!valid_state) { + return PICO_ERROR_INVALID_STATE; + } + + // reboot to main + powman_hw->boot[0] = 0; + powman_hw->boot[1] = 0; + powman_hw->boot[2] = 0; + powman_hw->boot[3] = 0; + + powman_hw->scratch[7] = (uint32_t)resume_func; + + // Switch to required power state + int rc = powman_set_power_state(pstate_bitset_to_powman_power_state(pstate)); + if (rc != PICO_OK) { + return rc; + } + + // Power down + while (true) __wfi(); + + post_pstate_change(); + + return rc; +} + +int low_power_pstate_until_aon_timer(absolute_time_t until, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func) { + powman_enable_alarm_wakeup_at_ms(to_ms_since_boot(until)); + + return low_power_go_pstate(pstate, resume_func); +} + +int low_power_pstate_until_pin_state(uint gpio_pin, bool edge, bool high, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func) { + powman_enable_gpio_wakeup(0, gpio_pin, edge, high); + + return low_power_go_pstate(pstate, resume_func); +} + +#if !PICO_RUNTIME_NO_INIT_LOW_POWER_REBOOT_CHECK +void __weak runtime_init_low_power_reboot_check(void) { + // check if we came from powman reboot + if (powman_hw->chip_reset & POWMAN_CHIP_RESET_HAD_SWCORE_PD_BITS) { + // we came from powman reboot, so execute the resume function + if (powman_hw->scratch[7]) { + ((low_power_pstate_resume_func)powman_hw->scratch[7])(); + powman_hw->scratch[7] = 0; + } + } +} +#endif + +#if !PICO_RUNTIME_SKIP_INIT_LOW_POWER_REBOOT_CHECK +PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_low_power_reboot_check, PICO_RUNTIME_INIT_LOW_POWER_REBOOT_CHECK); +#endif + +#endif // !PICO_RP2040 + #if !PICO_RUNTIME_NO_INIT_RP2350_SLEEP_FIX #include "hardware/sync.h" void __weak runtime_init_rp2350_sleep_fix(void) { diff --git a/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h b/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h index f93590fe6..68bc053ae 100644 --- a/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h +++ b/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h @@ -432,6 +432,22 @@ void runtime_init_bootrom_locking_enable(void); #define PICO_RUNTIME_NO_INIT_RP2350_SLEEP_FIX !PICO_RP2350 #endif +// ------------------------------------------------------------ +// Low power reboot check +// ------------------------------------------------------------ + +#ifndef PICO_RUNTIME_INIT_LOW_POWER_REBOOT_CHECK +#define PICO_RUNTIME_INIT_LOW_POWER_REBOOT_CHECK "11020" +#endif + +#ifndef PICO_RUNTIME_SKIP_INIT_LOW_POWER_REBOOT_CHECK +#define PICO_RUNTIME_SKIP_INIT_LOW_POWER_REBOOT_CHECK !HAS_POWMAN_TIMER +#endif + +#ifndef PICO_RUNTIME_NO_INIT_LOW_POWER_REBOOT_CHECK +#define PICO_RUNTIME_NO_INIT_LOW_POWER_REBOOT_CHECK !HAS_POWMAN_TIMER +#endif + // ------------------------------------------------------------------------------------------------ // stack guard; these are a special case as they take a parameter; however the normal defines apply // ------------------------------------------------------------------------------------------------ diff --git a/test/hello_sleep/CMakeLists.txt b/test/hello_sleep/CMakeLists.txt index fb1abb738..ea0bb7bca 100644 --- a/test/hello_sleep/CMakeLists.txt +++ b/test/hello_sleep/CMakeLists.txt @@ -2,7 +2,7 @@ add_executable(hello_sleep hello_sleep.c ) -target_link_libraries(hello_sleep pico_stdlib pico_low_power) +target_link_libraries(hello_sleep pico_stdlib pico_low_power pico_status_led) # create map/bin/hex file etc. pico_add_extra_outputs(hello_sleep) \ No newline at end of file diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index 404a6290e..e626ff74d 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -5,24 +5,67 @@ */ #include +#include #include "pico/stdlib.h" #include "pico/low_power.h" #include "pico/aon_timer.h" +#include "pico/status_led.h" + +#define SLEEP_TIME_S 2 +#define SLEEP_TIME_MS SLEEP_TIME_S * 1000 bool repeater(repeating_timer_t *timer) { - printf("Repeating timer at %dms\n", time_us_32() / 1000); + if (aon_timer_is_running()) { + printf(" Repeating timer at %dms (aon: %dms)\n", to_ms_since_boot(get_absolute_time()), to_ms_since_boot(aon_timer_get_absolute_time())); + } else { + printf(" Repeating timer at %dms (aon: not running)\n", to_ms_since_boot(get_absolute_time())); + } + status_led_set_state(!status_led_get_state()); return true; } +static bool came_from_pstate = false; +static bool gpio_pwrup = false; +static char powman_last_pwrup[100]; + +void pstate_resume_func(void) { + came_from_pstate = true; + switch (powman_hw->last_swcore_pwrup) { + // 0 = chip reset, for the source of the last reset see + case 1 << 0: strcpy(powman_last_pwrup, "Chip reset"); break; + case 1 << 1: strcpy(powman_last_pwrup, "Pwrup0"); gpio_pwrup = true; break; + case 1 << 2: strcpy(powman_last_pwrup, "Pwrup1"); gpio_pwrup = true; break; + case 1 << 3: strcpy(powman_last_pwrup, "Pwrup2"); gpio_pwrup = true; break; + case 1 << 4: strcpy(powman_last_pwrup, "Pwrup3"); gpio_pwrup = true; break; + case 1 << 5: strcpy(powman_last_pwrup, "Coresight_pwrup"); break; + case 1 << 6: strcpy(powman_last_pwrup, "Alarm_pwrup"); break; + default: strcpy(powman_last_pwrup, "Unknown pwrup"); break; + } +} + int main() { stdio_init_all(); + status_led_init(); printf("Hello Sleep!\n"); -#if PICO_RP2350 +#if !PICO_RP2040 // use a second repeating timer on the other TIMER instance; it should be gated // during our sleep (todo not sure how it affects power!) alarm_pool_t *alarm_pool = alarm_pool_create_on_timer_with_unused_hardware_alarm(timer1_hw, 4); repeating_timer_t repeat; alarm_pool_add_repeating_timer_ms(alarm_pool, 500, repeater, NULL, &repeat); +#endif + + if (came_from_pstate) { + if (gpio_pwrup) { + printf("Came from GPIO powerup %s - done\n", powman_last_pwrup); + goto post_pstate_gpio; + } else { + printf("Came from powerup %s - skipping to end\n", powman_last_pwrup); + goto post_pstate_timer; + } + } + +#if !PICO_RP2040 printf("Waiting 1 sec\n"); // so we can see some repeat printfs busy_wait_ms(1100); #endif @@ -30,13 +73,14 @@ int main() { absolute_time_t start_time; absolute_time_t wakeup_time; int64_t diff; - uint64_t current_aon; struct timespec ts; + int ret; + pstate_bitset_t pstate; - printf("Going to sleep for 5 seconds via TIMER\n"); + printf("Going to sleep for %d seconds via TIMER\n", SLEEP_TIME_S); start_time = get_absolute_time(); - wakeup_time = delayed_by_ms(start_time, 5000); + wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); low_power_sleep_until_timer(timer_hw, wakeup_time, NULL, true); diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); printf("Woken up now @%dus since target\n", (int)diff); @@ -44,36 +88,85 @@ int main() { printf("ERROR: Woke up too soon\n"); return -1; } - busy_wait_ms(3000); + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); #if !PICO_RP2040 - printf("Going DORMANT for 5 seconds via AON TIMER\n"); + printf("Going DORMANT for %d seconds via AON TIMER\n", SLEEP_TIME_S); // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync start_time = get_absolute_time(); us_to_timespec(start_time, &ts); aon_timer_start(&ts); - wakeup_time = delayed_by_ms(start_time, 5000); + wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); low_power_dormant_until_aon_timer(wakeup_time, DORMANT_CLOCK_SOURCE_LPOSC, XOSC_KHZ * 1000, 0, // gpio pin (unused with powman) NULL); diff = absolute_time_diff_us(get_absolute_time(), wakeup_time); // need to use the AON timer for checking time, since the other timer is unclocked diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); - if (diff > -4000000) { + if (diff > -1000000) { printf("ERROR: doesn't seem like timer was stopped\n"); return - 1; } - aon_timer_get_time(&ts); - current_aon = timespec_to_us(&ts); - diff = absolute_time_diff_us(wakeup_time, from_us_since_boot(current_aon)); + diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); printf("Woken up now @%dus since target\n", (int)diff); if (diff < 0) { printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); } - printf("Final 5 second pause to prove timer still running\n"); - busy_wait_ms(5000); + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); + + printf("Going to PSTATE for %d seconds\n", SLEEP_TIME_S); + + start_time = aon_timer_get_absolute_time(); + + wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); + powman_hw->scratch[0] = to_us_since_boot(wakeup_time) & 0xFFFFFFFF; + powman_hw->scratch[1] = to_us_since_boot(wakeup_time) >> 32; + pstate = pstate_bitset_none(); + ret = low_power_pstate_until_aon_timer(wakeup_time, &pstate, pstate_resume_func); + + __breakpoint(); + + printf("%d low_power_pstate_until_aon_timer returned\n", ret); + while (true) { + printf("Waiting\n"); + busy_wait_ms(1000); + } + +post_pstate_timer: + + // restore from scratch + wakeup_time = from_us_since_boot((uint64_t)powman_hw->scratch[1] << 32 | (uint64_t)powman_hw->scratch[0]); + + diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); + printf("Woken up now @%dus since target\n", (int)diff); + if (diff < 0) { + printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); + } + + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); + + printf("Going to PSTATE until GPIO wakeup\n"); + + pstate = pstate_bitset_none(); + ret = low_power_pstate_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, &pstate, pstate_resume_func); + + __breakpoint(); + + printf("%d low_power_pstate_until_pin_state returned\n", ret); + while (true) { + printf("Waiting\n"); + busy_wait_ms(1000); + } + +post_pstate_gpio: + + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); #endif printf("SUCCESS\n"); From bcd27977198b8f28f8c95dbb38cc676a9d972a04 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 21 Aug 2025 18:09:54 +0100 Subject: [PATCH 022/127] Fix pin_state functions on RP2350 Don't seem to work on RP2040 --- .../pico_low_power/include/pico/low_power.h | 4 +- src/rp2_common/pico_low_power/low_power.c | 64 +++++++++- test/hello_sleep/CMakeLists.txt | 11 +- test/hello_sleep/hello_sleep.c | 47 ++------ test/hello_sleep/hello_sleep_gpio.c | 112 ++++++++++++++++++ 5 files changed, 195 insertions(+), 43 deletions(-) create mode 100644 test/hello_sleep/hello_sleep_gpio.c diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 06ab74640..83c500f78 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -39,7 +39,9 @@ extern "C" { #endif #include "hardware/clocks.h" +#if !PICO_RP2040 #include "hardware/powman.h" +#endif typedef enum { DORMANT_CLOCK_SOURCE_XOSC, @@ -77,7 +79,7 @@ static inline int low_power_sleep_until_default_timer(absolute_time_t until, con // ** LIAM BLESSED this for RP2040; why not RP2350 ** // This should work on both via io bank interrupts -void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high); +void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_set_t *keep_enabled, bool exclusive); #if 0 // ** LIAM SAYS THIS IS NO MORE USEFUL THAN SLEEP_UNTIL TIMER... ** diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 9cd0cad42..02ff37a47 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -64,13 +64,22 @@ static void post_clock_gating(void) { clock_gate_sleep_en(&all); } +static uint32_t interrupt_flags; + static void prepare_for_clock_switch(void) { // particularly for UART we want nothing left to clock out prepare_for_clock_gating(); + + // disable interrupts + interrupt_flags = save_and_disable_interrupts(); } static void post_clock_switch(void) { + // restore UART baudrate setup_default_uart(); + + // restore interrupts + restore_interrupts_from_disabled(interrupt_flags); } #if HAS_POWMAN_TIMER @@ -113,6 +122,10 @@ static void low_power_wakeup(void) { event_happened = true; } +static void low_power_wakeup_gpio(__unused uint gpio, __unused uint32_t event_mask) { + low_power_wakeup(); +} + static void replace_null_enable_values(const clock_dest_set_t *keep_enabled, clock_dest_set_t *local_keep_enabled) { if (keep_enabled) { @@ -167,6 +180,46 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, return 0; } +void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, + const clock_dest_set_t *keep_enabled, __unused bool exclusive) { + + event_happened = false; + + clock_dest_set_t local_keep_enabled; + replace_null_enable_values(keep_enabled, &local_keep_enabled); + + bool low = !high; + bool level = !edge; + + // Configure the appropriate IRQ at IO bank 0 + assert(gpio_pin < NUM_BANK0_GPIOS); + + uint32_t event = 0; + + if (level && low) event = GPIO_IRQ_LEVEL_LOW; + if (level && high) event = GPIO_IRQ_LEVEL_HIGH; + if (edge && high) event = GPIO_IRQ_EDGE_RISE; + if (edge && low) event = GPIO_IRQ_EDGE_FALL; + + gpio_set_input_enabled(gpio_pin, true); + gpio_set_irq_enabled_with_callback(gpio_pin, event, true, low_power_wakeup_gpio); + + prepare_for_clock_gating(); + // gate clocks + clock_gate_sleep_en(&local_keep_enabled); + + low_power_enable_processor_deep_sleep(); + // Go to sleep until the wakeup event happens (note it may have happened already) + while (!event_happened) __wfi(); + low_power_disable_processor_deep_sleep(); + + // Clear the irq so we can go back to dormant mode again if we want + gpio_acknowledge_irq(gpio_pin, event); + gpio_set_irq_enabled_with_callback(gpio_pin, event, false, NULL); + + post_clock_gating(); +} + #if 0 // todo note this has (not surprisingly a lot of commonality with the timer one) int low_power_sleep_until_aon_timer(absolute_time_t until, @@ -382,12 +435,11 @@ void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, uint32_t event = 0; - if (level && low) event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_LEVEL_LOW_BITS; - if (level && high) event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_LEVEL_HIGH_BITS; - if (edge && high) event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_EDGE_HIGH_BITS; - if (edge && low) event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_EDGE_LOW_BITS; + if (level && low) event = GPIO_IRQ_LEVEL_LOW; + if (level && high) event = GPIO_IRQ_LEVEL_HIGH; + if (edge && high) event = GPIO_IRQ_EDGE_RISE; + if (edge && low) event = GPIO_IRQ_EDGE_FALL; - gpio_init(gpio_pin); gpio_set_input_enabled(gpio_pin, true); gpio_set_dormant_irq_enabled(gpio_pin, event, true); @@ -402,7 +454,7 @@ void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, // Clear the irq so we can go back to dormant mode again if we want gpio_acknowledge_irq(gpio_pin, event); - gpio_set_input_enabled(gpio_pin, false); + gpio_set_dormant_irq_enabled(gpio_pin, event, false); low_power_wake_from_dormant(); } diff --git a/test/hello_sleep/CMakeLists.txt b/test/hello_sleep/CMakeLists.txt index ea0bb7bca..d565e10d2 100644 --- a/test/hello_sleep/CMakeLists.txt +++ b/test/hello_sleep/CMakeLists.txt @@ -5,4 +5,13 @@ add_executable(hello_sleep target_link_libraries(hello_sleep pico_stdlib pico_low_power pico_status_led) # create map/bin/hex file etc. -pico_add_extra_outputs(hello_sleep) \ No newline at end of file +pico_add_extra_outputs(hello_sleep) + +add_executable(hello_sleep_gpio + hello_sleep_gpio.c + ) + +target_link_libraries(hello_sleep_gpio pico_stdlib pico_low_power pico_status_led) + +# create map/bin/hex file etc. +pico_add_extra_outputs(hello_sleep_gpio) diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index e626ff74d..3c9d9a727 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -24,8 +24,8 @@ bool repeater(repeating_timer_t *timer) { return true; } +#if !PICO_RP2040 static bool came_from_pstate = false; -static bool gpio_pwrup = false; static char powman_last_pwrup[100]; void pstate_resume_func(void) { @@ -33,15 +33,16 @@ void pstate_resume_func(void) { switch (powman_hw->last_swcore_pwrup) { // 0 = chip reset, for the source of the last reset see case 1 << 0: strcpy(powman_last_pwrup, "Chip reset"); break; - case 1 << 1: strcpy(powman_last_pwrup, "Pwrup0"); gpio_pwrup = true; break; - case 1 << 2: strcpy(powman_last_pwrup, "Pwrup1"); gpio_pwrup = true; break; - case 1 << 3: strcpy(powman_last_pwrup, "Pwrup2"); gpio_pwrup = true; break; - case 1 << 4: strcpy(powman_last_pwrup, "Pwrup3"); gpio_pwrup = true; break; + case 1 << 1: strcpy(powman_last_pwrup, "Pwrup0"); break; + case 1 << 2: strcpy(powman_last_pwrup, "Pwrup1"); break; + case 1 << 3: strcpy(powman_last_pwrup, "Pwrup2"); break; + case 1 << 4: strcpy(powman_last_pwrup, "Pwrup3"); break; case 1 << 5: strcpy(powman_last_pwrup, "Coresight_pwrup"); break; case 1 << 6: strcpy(powman_last_pwrup, "Alarm_pwrup"); break; default: strcpy(powman_last_pwrup, "Unknown pwrup"); break; } } +#endif int main() { stdio_init_all(); @@ -53,21 +54,16 @@ int main() { alarm_pool_t *alarm_pool = alarm_pool_create_on_timer_with_unused_hardware_alarm(timer1_hw, 4); repeating_timer_t repeat; alarm_pool_add_repeating_timer_ms(alarm_pool, 500, repeater, NULL, &repeat); -#endif if (came_from_pstate) { - if (gpio_pwrup) { - printf("Came from GPIO powerup %s - done\n", powman_last_pwrup); - goto post_pstate_gpio; - } else { - printf("Came from powerup %s - skipping to end\n", powman_last_pwrup); - goto post_pstate_timer; - } + printf("Came from powerup %s - skipping to end\n", powman_last_pwrup); + goto post_pstate_timer; } -#if !PICO_RP2040 - printf("Waiting 1 sec\n"); // so we can see some repeat printfs - busy_wait_ms(1100); + printf("Waiting %d seconds\n", SLEEP_TIME_S); // so we can see some repeat printfs + busy_wait_ms(SLEEP_TIME_MS); + + pstate_bitset_t pstate; #endif absolute_time_t start_time; @@ -75,7 +71,6 @@ int main() { int64_t diff; struct timespec ts; int ret; - pstate_bitset_t pstate; printf("Going to sleep for %d seconds via TIMER\n", SLEEP_TIME_S); @@ -149,24 +144,6 @@ int main() { printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); - - printf("Going to PSTATE until GPIO wakeup\n"); - - pstate = pstate_bitset_none(); - ret = low_power_pstate_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, &pstate, pstate_resume_func); - - __breakpoint(); - - printf("%d low_power_pstate_until_pin_state returned\n", ret); - while (true) { - printf("Waiting\n"); - busy_wait_ms(1000); - } - -post_pstate_gpio: - - printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); - busy_wait_ms(SLEEP_TIME_MS); #endif printf("SUCCESS\n"); diff --git a/test/hello_sleep/hello_sleep_gpio.c b/test/hello_sleep/hello_sleep_gpio.c new file mode 100644 index 000000000..a7f1e1ea0 --- /dev/null +++ b/test/hello_sleep/hello_sleep_gpio.c @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "pico/stdlib.h" +#include "pico/low_power.h" +#include "pico/aon_timer.h" +#include "pico/status_led.h" + +#define SLEEP_TIME_S 2 +#define SLEEP_TIME_MS SLEEP_TIME_S * 1000 + +bool repeater(repeating_timer_t *timer) { + if (aon_timer_is_running()) { + printf(" Repeating timer at %dms (aon: %dms)\n", to_ms_since_boot(get_absolute_time()), to_ms_since_boot(aon_timer_get_absolute_time())); + } else { + printf(" Repeating timer at %dms (aon: not running)\n", to_ms_since_boot(get_absolute_time())); + } + status_led_set_state(!status_led_get_state()); + return true; +} + +#if !PICO_RP2040 +static bool came_from_pstate = false; +static char powman_last_pwrup[100]; + +void pstate_resume_func(void) { + came_from_pstate = true; + switch (powman_hw->last_swcore_pwrup) { + // 0 = chip reset, for the source of the last reset see + case 1 << 0: strcpy(powman_last_pwrup, "Chip reset"); break; + case 1 << 1: strcpy(powman_last_pwrup, "Pwrup0"); break; + case 1 << 2: strcpy(powman_last_pwrup, "Pwrup1"); break; + case 1 << 3: strcpy(powman_last_pwrup, "Pwrup2"); break; + case 1 << 4: strcpy(powman_last_pwrup, "Pwrup3"); break; + case 1 << 5: strcpy(powman_last_pwrup, "Coresight_pwrup"); break; + case 1 << 6: strcpy(powman_last_pwrup, "Alarm_pwrup"); break; + default: strcpy(powman_last_pwrup, "Unknown pwrup"); break; + } +} +#endif + +int main() { + stdio_init_all(); + status_led_init(); + printf("Hello Sleep!\n"); +#if !PICO_RP2040 + // use a second repeating timer on the other TIMER instance; it should be gated + // during our sleep (todo not sure how it affects power!) + alarm_pool_t *alarm_pool = alarm_pool_create_on_timer_with_unused_hardware_alarm(timer1_hw, 4); + repeating_timer_t repeat; + alarm_pool_add_repeating_timer_ms(alarm_pool, 500, repeater, NULL, &repeat); + + if (came_from_pstate) { + printf("Came from powerup %s - skipping to end\n", powman_last_pwrup); + goto post_pstate_gpio; + } + + printf("Waiting %d seconds\n", SLEEP_TIME_S); // so we can see some repeat printfs + busy_wait_ms(SLEEP_TIME_MS); + pstate_bitset_t pstate; +#endif + + absolute_time_t start_time; + struct timespec ts; + int ret; + + printf("Going to sleep until GPIO wakeup\n"); + + low_power_sleep_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, NULL, true); + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); + + // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync + start_time = get_absolute_time(); + us_to_timespec(start_time, &ts); + aon_timer_start(&ts); + + printf("Going DORMANT until GPIO wakeup\n"); + + low_power_dormant_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, DORMANT_CLOCK_SOURCE_ROSC, NULL); + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); + +#if !PICO_RP2040 + printf("Going to PSTATE until GPIO wakeup\n"); + + pstate = pstate_bitset_none(); + ret = low_power_pstate_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, &pstate, pstate_resume_func); + + __breakpoint(); + + printf("%d low_power_pstate_until_pin_state returned\n", ret); + while (true) { + printf("Waiting\n"); + busy_wait_ms(1000); + } + +post_pstate_gpio: + + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); +#endif + + printf("SUCCESS\n"); + + return 0; +} \ No newline at end of file From b62de58522919888209f9cc465accc5af98a15db Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 22 Aug 2025 12:29:36 +0100 Subject: [PATCH 023/127] Fix hello_sleep_gpio on RP2040 --- src/rp2_common/pico_low_power/low_power.c | 6 +++++- test/hello_sleep/hello_sleep_gpio.c | 12 ++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 02ff37a47..27aa3da41 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -215,7 +215,11 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, // Clear the irq so we can go back to dormant mode again if we want gpio_acknowledge_irq(gpio_pin, event); - gpio_set_irq_enabled_with_callback(gpio_pin, event, false, NULL); + + // todo fix race in gpio_set_irq_enabled_with_callback + // gpio_set_irq_enabled_with_callback(gpio_pin, event, false, NULL); + gpio_set_irq_enabled(gpio_pin, event, false); + gpio_set_irq_callback(NULL); post_clock_gating(); } diff --git a/test/hello_sleep/hello_sleep_gpio.c b/test/hello_sleep/hello_sleep_gpio.c index a7f1e1ea0..9ba082e5d 100644 --- a/test/hello_sleep/hello_sleep_gpio.c +++ b/test/hello_sleep/hello_sleep_gpio.c @@ -48,23 +48,23 @@ int main() { stdio_init_all(); status_led_init(); printf("Hello Sleep!\n"); -#if !PICO_RP2040 - // use a second repeating timer on the other TIMER instance; it should be gated + // use a repeating timer; it should be gated // during our sleep (todo not sure how it affects power!) - alarm_pool_t *alarm_pool = alarm_pool_create_on_timer_with_unused_hardware_alarm(timer1_hw, 4); repeating_timer_t repeat; - alarm_pool_add_repeating_timer_ms(alarm_pool, 500, repeater, NULL, &repeat); + add_repeating_timer_ms(500, repeater, NULL, &repeat); +#if !PICO_RP2040 if (came_from_pstate) { printf("Came from powerup %s - skipping to end\n", powman_last_pwrup); goto post_pstate_gpio; } - printf("Waiting %d seconds\n", SLEEP_TIME_S); // so we can see some repeat printfs - busy_wait_ms(SLEEP_TIME_MS); pstate_bitset_t pstate; #endif + printf("Waiting %d seconds\n", SLEEP_TIME_S); // so we can see some repeat printfs + busy_wait_ms(SLEEP_TIME_MS); + absolute_time_t start_time; struct timespec ts; int ret; From abc62553ab371085301d5221851fcd15c32f2223 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 22 Aug 2025 14:59:27 +0100 Subject: [PATCH 024/127] Add support for RP2040 dormant (using external RTC clock) --- src/rp2_common/pico_low_power/low_power.c | 9 +++---- test/hello_sleep/CMakeLists.txt | 11 ++++++++ test/hello_sleep/hello_sleep.c | 14 +++++++--- test/hello_sleep/rtc_clksrc.c | 33 +++++++++++++++++++++++ 4 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 test/hello_sleep/rtc_clksrc.c diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 27aa3da41..548950041 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -215,11 +215,7 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, // Clear the irq so we can go back to dormant mode again if we want gpio_acknowledge_irq(gpio_pin, event); - - // todo fix race in gpio_set_irq_enabled_with_callback - // gpio_set_irq_enabled_with_callback(gpio_pin, event, false, NULL); - gpio_set_irq_enabled(gpio_pin, event, false); - gpio_set_irq_callback(NULL); + gpio_set_irq_enabled_with_callback(gpio_pin, event, false, NULL); post_clock_gating(); } @@ -374,7 +370,7 @@ void low_power_go_dormant(dormant_clock_source_t dormant_clock_source) { int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_source_t dormant_clock_source, - __unused uint src_hz, uint gpio_pin, + uint src_hz, uint gpio_pin, const clock_dest_set_t *keep_enabled) { low_power_setup_clocks_for_dormant(dormant_clock_source); @@ -388,6 +384,7 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, clock_dest_set_add(&local_keep_enabled, CLK_DEST_RTC_RTC); #elif PICO_RP2350 // todo + ((void)src_hz); ((void)gpio_pin); if (dormant_clock_source == DORMANT_CLOCK_SOURCE_LPOSC) powman_timer_set_1khz_tick_source_lposc(); diff --git a/test/hello_sleep/CMakeLists.txt b/test/hello_sleep/CMakeLists.txt index d565e10d2..921741737 100644 --- a/test/hello_sleep/CMakeLists.txt +++ b/test/hello_sleep/CMakeLists.txt @@ -7,6 +7,17 @@ target_link_libraries(hello_sleep pico_stdlib pico_low_power pico_status_led) # create map/bin/hex file etc. pico_add_extra_outputs(hello_sleep) +if (PICO_RP2040) + add_executable(rtc_clksrc + rtc_clksrc.c + ) + + target_link_libraries(rtc_clksrc pico_stdlib pico_status_led) + + # create map/bin/hex file etc. + pico_add_extra_outputs(rtc_clksrc) +endif() + add_executable(hello_sleep_gpio hello_sleep_gpio.c ) diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index 3c9d9a727..895e53656 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -14,6 +14,8 @@ #define SLEEP_TIME_S 2 #define SLEEP_TIME_MS SLEEP_TIME_S * 1000 +#define RTC_GPIO 22 // must support clock input, see the GPIO function table in the datasheet. + bool repeater(repeating_timer_t *timer) { if (aon_timer_is_running()) { printf(" Repeating timer at %dms (aon: %dms)\n", to_ms_since_boot(get_absolute_time()), to_ms_since_boot(aon_timer_get_absolute_time())); @@ -86,7 +88,6 @@ int main() { printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); -#if !PICO_RP2040 printf("Going DORMANT for %d seconds via AON TIMER\n", SLEEP_TIME_S); // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync @@ -95,9 +96,13 @@ int main() { aon_timer_start(&ts); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); - low_power_dormant_until_aon_timer(wakeup_time, DORMANT_CLOCK_SOURCE_LPOSC, XOSC_KHZ * 1000, - 0, // gpio pin (unused with powman) - NULL); + low_power_dormant_until_aon_timer(wakeup_time, + #if PICO_RP2040 + DORMANT_CLOCK_SOURCE_XOSC, 46875, + #else + DORMANT_CLOCK_SOURCE_LPOSC, XOSC_HZ, + #endif + RTC_GPIO, NULL); diff = absolute_time_diff_us(get_absolute_time(), wakeup_time); // need to use the AON timer for checking time, since the other timer is unclocked diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); @@ -113,6 +118,7 @@ int main() { printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); +#if !PICO_RP2040 printf("Going to PSTATE for %d seconds\n", SLEEP_TIME_S); start_time = aon_timer_get_absolute_time(); diff --git a/test/hello_sleep/rtc_clksrc.c b/test/hello_sleep/rtc_clksrc.c new file mode 100644 index 000000000..287903b65 --- /dev/null +++ b/test/hello_sleep/rtc_clksrc.c @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "pico/stdlib.h" +#include "pico/status_led.h" +#include "pico/sync.h" +#include "hardware/clocks.h" + +#define RTC_GPIO 21 + +bool repeater(repeating_timer_t *timer) { + printf(" Repeating timer at %dms\n", to_ms_since_boot(get_absolute_time())); + status_led_set_state(!status_led_get_state()); + return true; +} + +int main() { + stdio_init_all(); + status_led_init(); + + clock_gpio_init(RTC_GPIO, CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_VALUE_CLK_RTC, 1); + + repeating_timer_t repeat; + add_repeating_timer_ms(500, repeater, NULL, &repeat); + + while (true) __wfi(); + + return 0; +} \ No newline at end of file From ed3716ea97414ba5b84a318ab8f935711c542292 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 22 Aug 2025 16:42:56 +0100 Subject: [PATCH 025/127] Pass low power state through powman reboot, so software knows what wasn't persisted Also fix riscv --- .../pico_util/include/pico/util/bitset.h | 7 ++++ .../hardware_powman/include/hardware/powman.h | 5 +++ .../pico_low_power/include/pico/low_power.h | 40 +++---------------- src/rp2_common/pico_low_power/low_power.c | 7 +++- .../include/pico/runtime_init.h | 12 +++++- test/hello_sleep/hello_sleep.c | 12 ++++-- test/hello_sleep/hello_sleep_gpio.c | 12 ++++-- 7 files changed, 49 insertions(+), 46 deletions(-) diff --git a/src/common/pico_util/include/pico/util/bitset.h b/src/common/pico_util/include/pico/util/bitset.h index 2a277fcc4..74bd94b8e 100644 --- a/src/common/pico_util/include/pico/util/bitset.h +++ b/src/common/pico_util/include/pico/util/bitset.h @@ -113,6 +113,13 @@ static inline bool bitset_get_bit(generic_bitset_t *bitset, uint bit) { return false; } +static inline bool bitset_equal(const generic_bitset_t *bitset1, const generic_bitset_t *bitset2) { + check_bitset(bitset1); + check_bitset(bitset2); + assert(bitset1->size == bitset2->size); + return __builtin_memcmp(bitset1->words, bitset2->words, bitset1->word_size * sizeof(uint32_t)) == 0; +} + typedef uint32_t tiny_encoded_bitset_t; typedef uint64_t encoded_bitset_t; diff --git a/src/rp2_common/hardware_powman/include/hardware/powman.h b/src/rp2_common/hardware_powman/include/hardware/powman.h index e7dbad278..0d0cc1c2c 100644 --- a/src/rp2_common/hardware_powman/include/hardware/powman.h +++ b/src/rp2_common/hardware_powman/include/hardware/powman.h @@ -200,6 +200,11 @@ static inline bool pstate_bitset_is_set(pstate_bitset_t *domains, powman_power_d return bitset_get_bit(&domains->bitset, domain); } +static inline bool pstate_bitset_none_set(pstate_bitset_t *domains) { + pstate_bitset_t none = pstate_bitset_none(); + return bitset_equal(&domains->bitset, &none.bitset); +} + static inline pstate_bitset_t pstate_bitset_from_powman_power_state(powman_power_state pstate) { pstate_bitset_t bitset; bitset_init(&bitset, pstate_bitset_t, POWMAN_POWER_DOMAIN_COUNT, pstate); diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 83c500f78..ad565b885 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -52,7 +52,9 @@ typedef enum { NUM_DORMANT_CLOCK_SOURCES } dormant_clock_source_t; -typedef void (*low_power_pstate_resume_func)(void); +#if !PICO_RP2040 +typedef void (*low_power_pstate_resume_func)(pstate_bitset_t *pstate); +#endif // NOTE: Need to deinit usb before doing into any of these sleep states @@ -104,6 +106,8 @@ void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dorm #if !PICO_RP2040 // pstate functions should return to the pstate you were in + +// pass resume_func which will be called on reboot by runtime_init_low_power_reboot_check int low_power_pstate_until_aon_timer(absolute_time_t until, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func); int low_power_pstate_until_pin_state(uint gpio_pin, bool edge, bool high, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func); @@ -121,40 +125,6 @@ int low_power_pstate_set(pstate_bitset_t *pstate); pstate_bitset_t low_power_pstate_get(void); #endif -#if 0 // todo - I think these are not being done? -void sleep_run_from_dormant_source(dormant_clock_source_t dormant_source); -/*! \brief Send system to sleep until a leading high edge is detected on GPIO - * \ingroup pico_sleep - * - * One of the sleep_run_* functions must be called prior to this call - * - * \param gpio_pin The pin to provide the wake up - */ -static inline void sleep_goto_dormant_until_edge_high(uint gpio_pin) { - sleep_goto_dormant_until_pin(gpio_pin, true, true); -} - -/*! \brief Send system to sleep until a high level is detected on GPIO - * \ingroup pico_sleep - * - * One of the sleep_run_* functions must be called prior to this call - * - * \param gpio_pin The pin to provide the wake up - */ -static inline void sleep_goto_dormant_until_level_high(uint gpio_pin) { - sleep_goto_dormant_until_pin(gpio_pin, false, true); -} - -/*! \brief Reconfigure clocks to wake up properly from sleep/dormant mode - * \ingroup pico_sleep - * - * This must be called immediately after continuing execution when waking up from sleep/dormant mode - * - */ -void sleep_power_up(void); - -#endif - #ifdef __cplusplus } #endif diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 548950041..4d251a895 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -487,6 +487,8 @@ int low_power_go_pstate(pstate_bitset_t *pstate, low_power_pstate_resume_func re powman_hw->boot[2] = 0; powman_hw->boot[3] = 0; + // Store the low power state and resume function for use after reboot + powman_hw->scratch[6] = pstate_bitset_to_powman_power_state(pstate); powman_hw->scratch[7] = (uint32_t)resume_func; // Switch to required power state @@ -521,7 +523,10 @@ void __weak runtime_init_low_power_reboot_check(void) { if (powman_hw->chip_reset & POWMAN_CHIP_RESET_HAD_SWCORE_PD_BITS) { // we came from powman reboot, so execute the resume function if (powman_hw->scratch[7]) { - ((low_power_pstate_resume_func)powman_hw->scratch[7])(); + pstate_bitset_t pstate = pstate_bitset_from_powman_power_state(powman_hw->scratch[6]); + ((low_power_pstate_resume_func)powman_hw->scratch[7])(&pstate); + // clear the scratch registers + powman_hw->scratch[6] = 0; powman_hw->scratch[7] = 0; } } diff --git a/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h b/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h index 68bc053ae..b4cf31c00 100644 --- a/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h +++ b/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h @@ -425,11 +425,19 @@ void runtime_init_bootrom_locking_enable(void); #endif #ifndef PICO_RUNTIME_SKIP_INIT_RP2350_SLEEP_FIX -#define PICO_RUNTIME_SKIP_INIT_RP2350_SLEEP_FIX !PICO_RP2350 +#if PICO_RP2350 && !defined(__riscv) +#define PICO_RUNTIME_SKIP_INIT_RP2350_SLEEP_FIX 0 +#else +#define PICO_RUNTIME_SKIP_INIT_RP2350_SLEEP_FIX 1 +#endif #endif #ifndef PICO_RUNTIME_NO_INIT_RP2350_SLEEP_FIX -#define PICO_RUNTIME_NO_INIT_RP2350_SLEEP_FIX !PICO_RP2350 +#if PICO_RP2350 && !defined(__riscv) +#define PICO_RUNTIME_NO_INIT_RP2350_SLEEP_FIX 0 +#else +#define PICO_RUNTIME_NO_INIT_RP2350_SLEEP_FIX 1 +#endif #endif // ------------------------------------------------------------ diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index 895e53656..d8715960e 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -29,8 +29,9 @@ bool repeater(repeating_timer_t *timer) { #if !PICO_RP2040 static bool came_from_pstate = false; static char powman_last_pwrup[100]; +static char powman_last_pstate[100]; -void pstate_resume_func(void) { +void pstate_resume_func(pstate_bitset_t *pstate) { came_from_pstate = true; switch (powman_hw->last_swcore_pwrup) { // 0 = chip reset, for the source of the last reset see @@ -43,6 +44,11 @@ void pstate_resume_func(void) { case 1 << 6: strcpy(powman_last_pwrup, "Alarm_pwrup"); break; default: strcpy(powman_last_pwrup, "Unknown pwrup"); break; } + + if (pstate_bitset_is_set(pstate, POWMAN_POWER_DOMAIN_XIP_CACHE)) strcat(powman_last_pstate, "XIP_CACHE, "); + if (pstate_bitset_is_set(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK0)) strcat(powman_last_pstate, "SRAM_BANK0, "); + if (pstate_bitset_is_set(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK1)) strcat(powman_last_pstate, "SRAM_BANK1, "); + if (pstate_bitset_none_set(pstate)) strcat(powman_last_pstate, "NONE, "); } #endif @@ -58,7 +64,7 @@ int main() { alarm_pool_add_repeating_timer_ms(alarm_pool, 500, repeater, NULL, &repeat); if (came_from_pstate) { - printf("Came from powerup %s - skipping to end\n", powman_last_pwrup); + printf("Came from powerup %s with (%s) memory kept on - skipping to end\n", powman_last_pwrup, powman_last_pstate); goto post_pstate_timer; } @@ -129,8 +135,6 @@ int main() { pstate = pstate_bitset_none(); ret = low_power_pstate_until_aon_timer(wakeup_time, &pstate, pstate_resume_func); - __breakpoint(); - printf("%d low_power_pstate_until_aon_timer returned\n", ret); while (true) { printf("Waiting\n"); diff --git a/test/hello_sleep/hello_sleep_gpio.c b/test/hello_sleep/hello_sleep_gpio.c index 9ba082e5d..b929855bb 100644 --- a/test/hello_sleep/hello_sleep_gpio.c +++ b/test/hello_sleep/hello_sleep_gpio.c @@ -27,8 +27,9 @@ bool repeater(repeating_timer_t *timer) { #if !PICO_RP2040 static bool came_from_pstate = false; static char powman_last_pwrup[100]; +static char powman_last_pstate[100]; -void pstate_resume_func(void) { +void pstate_resume_func(pstate_bitset_t *pstate) { came_from_pstate = true; switch (powman_hw->last_swcore_pwrup) { // 0 = chip reset, for the source of the last reset see @@ -41,6 +42,11 @@ void pstate_resume_func(void) { case 1 << 6: strcpy(powman_last_pwrup, "Alarm_pwrup"); break; default: strcpy(powman_last_pwrup, "Unknown pwrup"); break; } + + if (pstate_bitset_is_set(pstate, POWMAN_POWER_DOMAIN_XIP_CACHE)) strcat(powman_last_pstate, "XIP_CACHE, "); + if (pstate_bitset_is_set(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK0)) strcat(powman_last_pstate, "SRAM_BANK0, "); + if (pstate_bitset_is_set(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK1)) strcat(powman_last_pstate, "SRAM_BANK1, "); + if (pstate_bitset_none_set(pstate)) strcat(powman_last_pstate, "NONE, "); } #endif @@ -55,7 +61,7 @@ int main() { #if !PICO_RP2040 if (came_from_pstate) { - printf("Came from powerup %s - skipping to end\n", powman_last_pwrup); + printf("Came from powerup %s with (%s) memory kept on - skipping to end\n", powman_last_pwrup, powman_last_pstate); goto post_pstate_gpio; } @@ -92,8 +98,6 @@ int main() { pstate = pstate_bitset_none(); ret = low_power_pstate_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, &pstate, pstate_resume_func); - __breakpoint(); - printf("%d low_power_pstate_until_pin_state returned\n", ret); while (true) { printf("Waiting\n"); From 5a2677cdc9abd94863a38f653469c2daf3b3e00f Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 22 Aug 2025 17:20:02 +0100 Subject: [PATCH 026/127] Implement exclusive variable when sleeping Disables all other interrupts --- .../hardware_irq/include/hardware/irq.h | 15 ++++++++ src/rp2_common/hardware_irq/irq.c | 21 +++++++++++ src/rp2_common/pico_low_power/low_power.c | 37 ++++++++++++++++++- 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/rp2_common/hardware_irq/include/hardware/irq.h b/src/rp2_common/hardware_irq/include/hardware/irq.h index 0dcc49d59..b1b7b31a1 100644 --- a/src/rp2_common/hardware_irq/include/hardware/irq.h +++ b/src/rp2_common/hardware_irq/include/hardware/irq.h @@ -276,6 +276,21 @@ void irq_set_mask_enabled(uint32_t mask, bool enabled); */ void irq_set_mask_n_enabled(uint n, uint32_t mask, bool enabled); +/*! \brief Get the current enabled mask on the executing core + * \ingroup hardware_irq + * + * \return mask 32-bit mask with one bits set for the enabled interrupts \ref interrupt_nums + */ + uint32_t irq_get_mask(void); + + /*! \brief Get the current enabled mask on the executing core + * \ingroup hardware_irq + * + * \param n the index of the mask to update. n == 0 means 0->31, n == 1 mean 32->63 etc. + * \return mask 32-bit mask with one bits set for the enabled interrupts \ref interrupt_nums + */ + uint32_t irq_get_mask_n(uint n); + /*! \brief Set an exclusive interrupt handler for an interrupt on the executing core. * \ingroup hardware_irq * diff --git a/src/rp2_common/hardware_irq/irq.c b/src/rp2_common/hardware_irq/irq.c index fdcbb00fb..698bb3f7a 100644 --- a/src/rp2_common/hardware_irq/irq.c +++ b/src/rp2_common/hardware_irq/irq.c @@ -113,6 +113,27 @@ void irq_set_mask_n_enabled(uint n, uint32_t mask, bool enabled) { irq_set_mask_n_enabled_internal(n, mask, enabled); } +static inline uint32_t irq_get_mask_n_internal(uint n) { + invalid_params_if(HARDWARE_IRQ, n * 32u >= ((PICO_NUM_VTABLE_IRQS + 31u) & ~31u)); +#if defined(__riscv) + return (hazard3_irqarray_read(RVCSR_MEIEA_OFFSET, 2 * n) & 0xffffu) | (hazard3_irqarray_read(RVCSR_MEIEA_OFFSET, 2 * n + 1) << 16); +#elif PICO_RP2040 + ((void)n); + return nvic_hw->iser; +#else + // >32 IRQs (well this works for the bottom 32 which is all that is passed in + return nvic_hw->iser[n]; +#endif +} + +uint32_t irq_get_mask(void) { + return irq_get_mask_n_internal(0); +} + +uint32_t irq_get_mask_n(uint n) { + return irq_get_mask_n_internal(n); +} + void irq_set_pending(uint num) { check_irq_param(num); #ifdef __riscv diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 4d251a895..f51c51a89 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -136,9 +136,27 @@ static void replace_null_enable_values(const clock_dest_set_t *keep_enabled, } } +static uint32_t irq_mask_disabled_during_sleep[NUM_IRQS]; + +static void save_and_disable_other_interrupts(uint32_t irq) { + for (uint n = 0; n <= ((NUM_IRQS-1) / 32); n++) { + irq_mask_disabled_during_sleep[n] = irq_get_mask_n(n); + if (irq >= n * 32 && irq < (n + 1) * 32) { + irq_mask_disabled_during_sleep[n] &= ~(1u << (irq % 32)); + } + irq_set_mask_n_enabled(n, irq_mask_disabled_during_sleep[n], false); + } +} + +static void restore_other_interrupts(void) { + for (uint n = 0; n < NUM_IRQS; n++) { + irq_set_mask_n_enabled(n, irq_mask_disabled_during_sleep[n], true); + } +} + // only the deep_sleep variant of this, as DORMANT cannot wake from TIMER int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, - const clock_dest_set_t *keep_enabled, __unused bool exclusive) { + const clock_dest_set_t *keep_enabled, bool exclusive) { int alarm_num = timer_hardware_alarm_claim_unused(timer, false); if (alarm_num < 0) return PICO_ERROR_INSUFFICIENT_RESOURCES; @@ -163,6 +181,15 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, #else #error Unknown processor #endif + +#if NUM_GENERIC_TIMERS == 1 +#define TIMER_BASE_IRQ TIMER_IRQ_0 +#else +#define TIMER_BASE_IRQ TIMER0_IRQ_0 +#endif + + if (exclusive) save_and_disable_other_interrupts(TIMER_BASE_IRQ + alarm_num + (timer_get_index(timer) * NUM_ALARMS)); + prepare_for_clock_gating(); // gate clocks clock_gate_sleep_en(&local_keep_enabled); @@ -177,11 +204,13 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, post_clock_gating(); + if (exclusive) restore_other_interrupts(); + return 0; } void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, - const clock_dest_set_t *keep_enabled, __unused bool exclusive) { + const clock_dest_set_t *keep_enabled, bool exclusive) { event_happened = false; @@ -204,6 +233,8 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, gpio_set_input_enabled(gpio_pin, true); gpio_set_irq_enabled_with_callback(gpio_pin, event, true, low_power_wakeup_gpio); + if (exclusive) save_and_disable_other_interrupts(IO_IRQ_BANK0); + prepare_for_clock_gating(); // gate clocks clock_gate_sleep_en(&local_keep_enabled); @@ -218,6 +249,8 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, gpio_set_irq_enabled_with_callback(gpio_pin, event, false, NULL); post_clock_gating(); + + if (exclusive) restore_other_interrupts(); } #if 0 From c3a3b7c96dd71109e78dcd081c8602e193959c31 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 22 Aug 2025 17:49:54 +0100 Subject: [PATCH 027/127] Demonstrate non-exclusive sleep --- test/hello_sleep/hello_sleep.c | 36 +++++++++++++++++++++++------ test/hello_sleep/hello_sleep_gpio.c | 15 ++++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index d8715960e..2a8f14046 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -18,9 +18,9 @@ bool repeater(repeating_timer_t *timer) { if (aon_timer_is_running()) { - printf(" Repeating timer at %dms (aon: %dms)\n", to_ms_since_boot(get_absolute_time()), to_ms_since_boot(aon_timer_get_absolute_time())); + printf(" Repeating timer %d at %dms (aon: %dms)\n", *(uint32_t*)timer->user_data, to_ms_since_boot(get_absolute_time()), to_ms_since_boot(aon_timer_get_absolute_time())); } else { - printf(" Repeating timer at %dms (aon: not running)\n", to_ms_since_boot(get_absolute_time())); + printf(" Repeating timer %d at %dms (aon: not running)\n", *(uint32_t*)timer->user_data, to_ms_since_boot(get_absolute_time())); } status_led_set_state(!status_led_get_state()); return true; @@ -56,24 +56,32 @@ int main() { stdio_init_all(); status_led_init(); printf("Hello Sleep!\n"); + + // use a repeating timer on the same TIMER instance; it should be disabled + // during exclusive sleep (todo not sure how it affects power!) + repeating_timer_t repeat; + uint32_t repeater_id = 0; + add_repeating_timer_ms(500, repeater, &repeater_id, &repeat); + #if !PICO_RP2040 // use a second repeating timer on the other TIMER instance; it should be gated // during our sleep (todo not sure how it affects power!) alarm_pool_t *alarm_pool = alarm_pool_create_on_timer_with_unused_hardware_alarm(timer1_hw, 4); - repeating_timer_t repeat; - alarm_pool_add_repeating_timer_ms(alarm_pool, 500, repeater, NULL, &repeat); + repeating_timer_t repeat2; + uint32_t repeater2_id = 1; + alarm_pool_add_repeating_timer_ms(alarm_pool, 500, repeater, &repeater2_id, &repeat2); if (came_from_pstate) { printf("Came from powerup %s with (%s) memory kept on - skipping to end\n", powman_last_pwrup, powman_last_pstate); goto post_pstate_timer; } - printf("Waiting %d seconds\n", SLEEP_TIME_S); // so we can see some repeat printfs - busy_wait_ms(SLEEP_TIME_MS); - pstate_bitset_t pstate; #endif + printf("Waiting %d seconds\n", SLEEP_TIME_S); // so we can see some repeat printfs + busy_wait_ms(SLEEP_TIME_MS); + absolute_time_t start_time; absolute_time_t wakeup_time; int64_t diff; @@ -94,6 +102,20 @@ int main() { printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); + printf("Going to non-exclusive sleep for %d seconds via TIMER\n", SLEEP_TIME_S); + + start_time = get_absolute_time(); + wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); + low_power_sleep_until_timer(timer_hw, wakeup_time, NULL, false); + diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); + printf("Woken up now @%dus since target\n", (int)diff); + if (diff < 0) { + printf("ERROR: Woke up too soon\n"); + return -1; + } + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); + printf("Going DORMANT for %d seconds via AON TIMER\n", SLEEP_TIME_S); // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync diff --git a/test/hello_sleep/hello_sleep_gpio.c b/test/hello_sleep/hello_sleep_gpio.c index b929855bb..36daf350c 100644 --- a/test/hello_sleep/hello_sleep_gpio.c +++ b/test/hello_sleep/hello_sleep_gpio.c @@ -81,6 +81,21 @@ int main() { printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); + printf("Going to non-exclusive sleep until GPIO wakeup\n"); + + // need to keep the timer running + clock_dest_set_t keep_enabled = clock_dest_set_none(); +#if PICO_RP2040 + clock_dest_set_add(&keep_enabled, CLK_DEST_SYS_TIMER); +#else + clock_dest_set_add(&keep_enabled, CLK_DEST_SYS_TIMER0); + clock_dest_set_add(&keep_enabled, CLK_DEST_REF_TICKS); +#endif + + low_power_sleep_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, &keep_enabled, false); + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); + // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync start_time = get_absolute_time(); us_to_timespec(start_time, &ts); From a1eb46ff12affa315b455e93f706aae45f8c5a6d Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 1 Sep 2025 10:28:31 +0100 Subject: [PATCH 028/127] Add skips of data_copy in arm crt0 --- .../hardware_powman/include/hardware/powman.h | 11 +- src/rp2_common/pico_crt0/crt0.S | 62 +++++++++ .../pico_low_power/include/pico/low_power.h | 2 +- src/rp2_common/pico_low_power/low_power.c | 11 +- test/hello_sleep/hello_sleep.c | 122 +++++++++++++++++- 5 files changed, 194 insertions(+), 14 deletions(-) diff --git a/src/rp2_common/hardware_powman/include/hardware/powman.h b/src/rp2_common/hardware_powman/include/hardware/powman.h index 0d0cc1c2c..659ec6c2e 100644 --- a/src/rp2_common/hardware_powman/include/hardware/powman.h +++ b/src/rp2_common/hardware_powman/include/hardware/powman.h @@ -205,14 +205,13 @@ static inline bool pstate_bitset_none_set(pstate_bitset_t *domains) { return bitset_equal(&domains->bitset, &none.bitset); } -static inline pstate_bitset_t pstate_bitset_from_powman_power_state(powman_power_state pstate) { - pstate_bitset_t bitset; - bitset_init(&bitset, pstate_bitset_t, POWMAN_POWER_DOMAIN_COUNT, pstate); - return bitset; +static inline pstate_bitset_t *pstate_bitset_from_powman_power_state(pstate_bitset_t *domains, powman_power_state pstate) { + bitset_write_word(&domains->bitset, 0, pstate); + return domains; } -static inline powman_power_state pstate_bitset_to_powman_power_state(pstate_bitset_t *pstate) { - return pstate->bitset.words[0]; +static inline powman_power_state pstate_bitset_to_powman_power_state(pstate_bitset_t *domains) { + return bitset_read_word(&domains->bitset, 0); } /*! \brief Get the current power state diff --git a/src/rp2_common/pico_crt0/crt0.S b/src/rp2_common/pico_crt0/crt0.S index ea3b99a5a..2193d5fa6 100644 --- a/src/rp2_common/pico_crt0/crt0.S +++ b/src/rp2_common/pico_crt0/crt0.S @@ -15,6 +15,10 @@ #include "boot/picobin.h" #include "pico/bootrom.h" +#if !PICO_RP2040 +#include "hardware/regs/powman.h" +#endif + // PICO_CONFIG: PICO_CRT0_NEAR_CALLS, Whether calls from crt0 into the binary are near (<16M away) - ignored for PICO_COPY_TO_RAM, default=0, type=bool, group=pico_crt0 #ifndef PICO_CRT0_NEAR_CALLS #define PICO_CRT0_NEAR_CALLS 0 @@ -478,6 +482,11 @@ _call_xip_setup: // In a NO_FLASH binary, don't perform .data etc copy, since it's loaded // in-place by the SRAM load. Still need to clear .bss #if !PICO_NO_FLASH +#if LIB_PICO_LOW_POWER && !PICO_RP2040 + // Load previous power state into r6 + ldr r6, =(POWMAN_BASE+POWMAN_SCRATCH6_OFFSET) + ldr r6, [r6] +#endif adr r4, data_cpy_table // assume there is at least one entry @@ -485,6 +494,11 @@ _call_xip_setup: ldmia r4!, {r1-r3} cmp r1, #0 beq 2f +#if LIB_PICO_LOW_POWER && !PICO_RP2040 + bl data_cpy_check + cmp r0, #1 + beq 1b +#endif bl data_cpy b 1b 2: @@ -530,6 +544,54 @@ data_cpy: cmp r2, r3 blo data_cpy_loop bx lr + +#if LIB_PICO_LOW_POWER && !PICO_RP2040 +data_cpy_check: + // uses r5 and r7 as scratch + // uses the powman_power_state in r6 + // returns in r0 + mov r0, #0 + // First check start of copy (r2) + mov r7, r2 +check_r7: + ldr r5, =(SRAM_BASE >> 16) + cmp r5, r7, lsr #16 + bgt check_xip_sram + ldr r5, =(SRAM4_BASE >> 16) + cmp r5, r7, lsr #16 + bgt check_sram0 + b check_sram1 +check_xip_sram: + mov r5, #(1 << 2) // POWMAN_POWER_DOMAIN_XIP_CACHE + and r5, r6 + cmp r5, #(1 << 2) + beq skip + b noskip +check_sram0: + mov r5, #(1 << 1) // POWMAN_POWER_DOMAIN_SRAM_BANK0 + and r5, r6 + cmp r5, #(1 << 1) + beq skip + b noskip +check_sram1: + mov r5, #(1 << 0) // POWMAN_POWER_DOMAIN_SRAM_BANK1 + and r5, r6 + cmp r5, #(1 << 0) + beq skip + b noskip +skip: + cmp r0, #1 + bne check_end + bx lr +check_end: + add r0, #1 + // If start was skipped, check end of copy + mov r7, r3 + b check_r7 +noskip: + mov r0, #0 + bx lr +#endif #endif // Note the data copy table is still included for NO_FLASH builds, even though diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index ad565b885..5ac068571 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -122,7 +122,7 @@ int low_power_pstate_until_pin_state(uint gpio_pin, bool edge, bool high, pstate // Go to a pstate // Doesn't support powering down switched core domain int low_power_pstate_set(pstate_bitset_t *pstate); -pstate_bitset_t low_power_pstate_get(void); +pstate_bitset_t *low_power_pstate_get(pstate_bitset_t *pstate); #endif #ifdef __cplusplus diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index f51c51a89..91055757a 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -500,15 +500,17 @@ int low_power_pstate_set(pstate_bitset_t *pstate) { return powman_set_power_state(pstate_bitset_to_powman_power_state(pstate)); } -pstate_bitset_t low_power_pstate_get(void) { - return pstate_bitset_from_powman_power_state(powman_get_power_state()); +pstate_bitset_t *low_power_pstate_get(pstate_bitset_t *pstate) { + pstate_bitset_from_powman_power_state(pstate, powman_get_power_state()); + return pstate; } int low_power_go_pstate(pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func) { prepare_for_pstate_change(); // Configure the wakeup state - pstate_bitset_t current_pstate = low_power_pstate_get(); + pstate_bitset_t current_pstate = pstate_bitset_none(); + low_power_pstate_get(¤t_pstate); bool valid_state = powman_configure_wakeup_state(pstate_bitset_to_powman_power_state(pstate), pstate_bitset_to_powman_power_state(¤t_pstate)); if (!valid_state) { return PICO_ERROR_INVALID_STATE; @@ -556,7 +558,8 @@ void __weak runtime_init_low_power_reboot_check(void) { if (powman_hw->chip_reset & POWMAN_CHIP_RESET_HAD_SWCORE_PD_BITS) { // we came from powman reboot, so execute the resume function if (powman_hw->scratch[7]) { - pstate_bitset_t pstate = pstate_bitset_from_powman_power_state(powman_hw->scratch[6]); + pstate_bitset_t pstate = pstate_bitset_none(); + pstate_bitset_from_powman_power_state(&pstate, powman_hw->scratch[6]); ((low_power_pstate_resume_func)powman_hw->scratch[7])(&pstate); // clear the scratch registers powman_hw->scratch[6] = 0; diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index 2a8f14046..40d272633 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -30,9 +30,13 @@ bool repeater(repeating_timer_t *timer) { static bool came_from_pstate = false; static char powman_last_pwrup[100]; static char powman_last_pstate[100]; +static char powman_last_pstate_val[10]; void pstate_resume_func(pstate_bitset_t *pstate) { came_from_pstate = true; + memset(powman_last_pwrup, 0, sizeof(powman_last_pwrup)); + memset(powman_last_pstate, 0, sizeof(powman_last_pstate)); + memset(powman_last_pstate_val, 0, sizeof(powman_last_pstate_val)); switch (powman_hw->last_swcore_pwrup) { // 0 = chip reset, for the source of the last reset see case 1 << 0: strcpy(powman_last_pwrup, "Chip reset"); break; @@ -50,6 +54,8 @@ void pstate_resume_func(pstate_bitset_t *pstate) { if (pstate_bitset_is_set(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK1)) strcat(powman_last_pstate, "SRAM_BANK1, "); if (pstate_bitset_none_set(pstate)) strcat(powman_last_pstate, "NONE, "); } + +static volatile int my_number = 12345; #endif int main() { @@ -73,7 +79,13 @@ int main() { if (came_from_pstate) { printf("Came from powerup %s with (%s) memory kept on - skipping to end\n", powman_last_pwrup, powman_last_pstate); - goto post_pstate_timer; + if (strstr(powman_last_pstate, "SRAM_BANK0") != NULL) { + goto post_pstate_sram0_on; + } else if (strstr(powman_last_pstate, "SRAM_BANK1") != NULL) { + goto post_pstate_sram1_on; + } else { + goto post_pstate_sram_off; + } } pstate_bitset_t pstate; @@ -88,6 +100,9 @@ int main() { struct timespec ts; int ret; + + + // exclusive sleep printf("Going to sleep for %d seconds via TIMER\n", SLEEP_TIME_S); start_time = get_absolute_time(); @@ -102,6 +117,9 @@ int main() { printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); + + + // non-exclusive sleep printf("Going to non-exclusive sleep for %d seconds via TIMER\n", SLEEP_TIME_S); start_time = get_absolute_time(); @@ -116,6 +134,9 @@ int main() { printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); + + + // dormant printf("Going DORMANT for %d seconds via AON TIMER\n", SLEEP_TIME_S); // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync @@ -146,8 +167,18 @@ int main() { printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); + + + // powman states #if !PICO_RP2040 - printf("Going to PSTATE for %d seconds\n", SLEEP_TIME_S); + // pstate with sram0 on + printf("Going to PSTATE with SRAM0 on for %d seconds\n", SLEEP_TIME_S); + + if (my_number != 12345) { + printf("ERROR: my_number is %d not 12345 - initialisation issue?\n", my_number); + return -1; + } + my_number = 67890; start_time = aon_timer_get_absolute_time(); @@ -155,6 +186,8 @@ int main() { powman_hw->scratch[0] = to_us_since_boot(wakeup_time) & 0xFFFFFFFF; powman_hw->scratch[1] = to_us_since_boot(wakeup_time) >> 32; pstate = pstate_bitset_none(); + pstate_bitset_add(&pstate, POWMAN_POWER_DOMAIN_SRAM_BANK0); + printf("pstate: %08x\n", pstate_bitset_to_powman_power_state(&pstate)); ret = low_power_pstate_until_aon_timer(wakeup_time, &pstate, pstate_resume_func); printf("%d low_power_pstate_until_aon_timer returned\n", ret); @@ -163,17 +196,100 @@ int main() { busy_wait_ms(1000); } -post_pstate_timer: +post_pstate_sram0_on: + // restore from scratch + wakeup_time = from_us_since_boot((uint64_t)powman_hw->scratch[1] << 32 | (uint64_t)powman_hw->scratch[0]); + diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); + printf("Woken up now @%dus since target\n", (int)diff); + if (diff < 0) { + printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); + } + + if (my_number != 67890) { + printf("ERROR: my_number is %d not 67890 - SRAM has been re-loaded\n", my_number); + return -1; + } else { + printf("my_number in sram: %d\n", my_number); + } + + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); + + + + // pstate with sram1 on + printf("Going to PSTATE with SRAM1 on for %d seconds\n", SLEEP_TIME_S); + + start_time = aon_timer_get_absolute_time(); + + wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); + powman_hw->scratch[0] = to_us_since_boot(wakeup_time) & 0xFFFFFFFF; + powman_hw->scratch[1] = to_us_since_boot(wakeup_time) >> 32; + pstate = pstate_bitset_none(); + pstate_bitset_add(&pstate, POWMAN_POWER_DOMAIN_SRAM_BANK1); + printf("pstate: %08x\n", pstate_bitset_to_powman_power_state(&pstate)); + ret = low_power_pstate_until_aon_timer(wakeup_time, &pstate, pstate_resume_func); + + printf("%d low_power_pstate_until_aon_timer returned\n", ret); + while (true) { + printf("Waiting\n"); + busy_wait_ms(1000); + } +post_pstate_sram1_on: // restore from scratch wakeup_time = from_us_since_boot((uint64_t)powman_hw->scratch[1] << 32 | (uint64_t)powman_hw->scratch[0]); + diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); + printf("Woken up now @%dus since target\n", (int)diff); + if (diff < 0) { + printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); + } + + if (my_number != 12345) { + printf("ERROR: my_number is %d not 12345 - SRAM has not been re-loaded\n", my_number); + return -1; + } else { + printf("my_number in sram: %d\n", my_number); + } + + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); + + + // pstate with sram off + printf("Going to PSTATE with SRAM off for %d seconds\n", SLEEP_TIME_S); + + start_time = aon_timer_get_absolute_time(); + + wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); + powman_hw->scratch[0] = to_us_since_boot(wakeup_time) & 0xFFFFFFFF; + powman_hw->scratch[1] = to_us_since_boot(wakeup_time) >> 32; + pstate = pstate_bitset_none(); + ret = low_power_pstate_until_aon_timer(wakeup_time, &pstate, pstate_resume_func); + + printf("%d low_power_pstate_until_aon_timer returned\n", ret); + while (true) { + printf("Waiting\n"); + busy_wait_ms(1000); + } + +post_pstate_sram_off: + // restore from scratch + wakeup_time = from_us_since_boot((uint64_t)powman_hw->scratch[1] << 32 | (uint64_t)powman_hw->scratch[0]); diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); printf("Woken up now @%dus since target\n", (int)diff); if (diff < 0) { printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); } + if (my_number != 12345) { + printf("ERROR: my_number is not 12345 - SRAM has not been re-loaded\n"); + return -1; + } else { + printf("my_number in sram: %d\n", my_number); + } + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); #endif From 26b0a667bf724da50138554c5270114f1ef64391 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 1 Sep 2025 11:06:33 +0100 Subject: [PATCH 029/127] Add Risc-V crt0 data_cpy skip Also shrink Arm one, and standardise PICO_NO_FLASH skipped code between them --- src/rp2_common/pico_crt0/crt0.S | 29 ++++++-------- src/rp2_common/pico_crt0/crt0_riscv.S | 54 +++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 17 deletions(-) diff --git a/src/rp2_common/pico_crt0/crt0.S b/src/rp2_common/pico_crt0/crt0.S index 2193d5fa6..4a78a8fbc 100644 --- a/src/rp2_common/pico_crt0/crt0.S +++ b/src/rp2_common/pico_crt0/crt0.S @@ -554,29 +554,24 @@ data_cpy_check: // First check start of copy (r2) mov r7, r2 check_r7: - ldr r5, =(SRAM_BASE >> 16) - cmp r5, r7, lsr #16 + ldr r5, =SRAM_BASE + cmp r5, r7 bgt check_xip_sram - ldr r5, =(SRAM4_BASE >> 16) - cmp r5, r7, lsr #16 + ldr r5, =SRAM4_BASE + cmp r5, r7 bgt check_sram0 - b check_sram1 +check_sram1: + mov r5, #(1 << 0) // POWMAN_POWER_DOMAIN_SRAM_BANK1 + b do_check check_xip_sram: mov r5, #(1 << 2) // POWMAN_POWER_DOMAIN_XIP_CACHE - and r5, r6 - cmp r5, #(1 << 2) - beq skip - b noskip + b do_check check_sram0: mov r5, #(1 << 1) // POWMAN_POWER_DOMAIN_SRAM_BANK0 - and r5, r6 - cmp r5, #(1 << 1) - beq skip - b noskip -check_sram1: - mov r5, #(1 << 0) // POWMAN_POWER_DOMAIN_SRAM_BANK1 - and r5, r6 - cmp r5, #(1 << 0) + b do_check +do_check: + and r7, r5, r6 + cmp r5, r7 beq skip b noskip skip: diff --git a/src/rp2_common/pico_crt0/crt0_riscv.S b/src/rp2_common/pico_crt0/crt0_riscv.S index 82864d017..970531a12 100644 --- a/src/rp2_common/pico_crt0/crt0_riscv.S +++ b/src/rp2_common/pico_crt0/crt0_riscv.S @@ -12,6 +12,10 @@ #include "boot/picobin.h" #include "pico/bootrom_constants.h" +#if !PICO_RP2040 +#include "hardware/regs/powman.h" +#endif + #ifdef NDEBUG #ifndef COLLAPSE_IRQS #define COLLAPSE_IRQS @@ -345,6 +349,11 @@ _call_xip_setup: // In a NO_FLASH binary, don't perform .data etc copy, since it's loaded // in-place by the SRAM load. Still need to clear .bss #if !PICO_NO_FLASH +#if LIB_PICO_LOW_POWER && !PICO_RP2040 + // Load previous power state into r6 + li a6, POWMAN_BASE+POWMAN_SCRATCH6_OFFSET + lw a6, 0(a6) +#endif la a4, data_cpy_table // assume there is at least one entry @@ -354,6 +363,10 @@ _call_xip_setup: lw a2, 4(a4) lw a3, 8(a4) addi a4, a4, 12 +#if LIB_PICO_LOW_POWER && !PICO_RP2040 + jal data_cpy_check + bnez a0, 1b +#endif jal data_cpy j 1b 2: @@ -383,6 +396,8 @@ platform_entry: // symbol for stack traces ebreak j 1b + +#if !PICO_NO_FLASH data_cpy_loop: lw a0, (a1) sw a0, (a2) @@ -392,6 +407,45 @@ data_cpy: bltu a2, a3, data_cpy_loop ret +#if LIB_PICO_LOW_POWER && !PICO_RP2040 +data_cpy_check: + // uses a5 and a7 as scratch + // uses the powman_power_state in a6 + // returns in a0 + li a0, 0 + // First check start of copy (a2) + mv a7, a2 +check_a7: + li a5, SRAM_BASE + bgt a5, a7, check_xip_sram + li a5, SRAM4_BASE + bgt a5, a7, check_sram0 +check_sram1: + li a5, 1 << 0 // POWMAN_POWER_DOMAIN_SRAM_BANK1 + j do_check +check_xip_sram: + li a5, 1 << 2 // POWMAN_POWER_DOMAIN_XIP_CACHE + j do_check +check_sram0: + li a5, 1 << 1 // POWMAN_POWER_DOMAIN_SRAM_BANK0 + j do_check +do_check: + and a7, a5, a6 + beq a5, a7, skip + j noskip +skip: + beqz a0, check_end + ret +check_end: + addi a0, a0, 1 + mv a7, a3 + j check_a7 +noskip: + li a0, 0 + ret +#endif +#endif + .align 2 data_cpy_table: #if PICO_RP2350 && PICO_EMBED_XIP_SETUP && !PICO_NO_FLASH From fa1199eed267d09ad6fd1c7fc514a42218538e24 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 1 Sep 2025 11:34:44 +0100 Subject: [PATCH 030/127] Tidy up non-RP2040 defines Use HAS_POWMAN_TIMER instead --- src/rp2_common/pico_crt0/crt0.S | 8 ++++---- src/rp2_common/pico_crt0/crt0_riscv.S | 8 ++++---- src/rp2_common/pico_low_power/include/pico/low_power.h | 6 +++--- src/rp2_common/pico_low_power/low_power.c | 4 ++-- test/hello_sleep/hello_sleep.c | 6 +++--- test/hello_sleep/hello_sleep_gpio.c | 9 ++++++--- 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/rp2_common/pico_crt0/crt0.S b/src/rp2_common/pico_crt0/crt0.S index 4a78a8fbc..411909a47 100644 --- a/src/rp2_common/pico_crt0/crt0.S +++ b/src/rp2_common/pico_crt0/crt0.S @@ -15,7 +15,7 @@ #include "boot/picobin.h" #include "pico/bootrom.h" -#if !PICO_RP2040 +#if HAS_POWMAN_TIMER #include "hardware/regs/powman.h" #endif @@ -482,7 +482,7 @@ _call_xip_setup: // In a NO_FLASH binary, don't perform .data etc copy, since it's loaded // in-place by the SRAM load. Still need to clear .bss #if !PICO_NO_FLASH -#if LIB_PICO_LOW_POWER && !PICO_RP2040 +#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER // Load previous power state into r6 ldr r6, =(POWMAN_BASE+POWMAN_SCRATCH6_OFFSET) ldr r6, [r6] @@ -494,7 +494,7 @@ _call_xip_setup: ldmia r4!, {r1-r3} cmp r1, #0 beq 2f -#if LIB_PICO_LOW_POWER && !PICO_RP2040 +#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER bl data_cpy_check cmp r0, #1 beq 1b @@ -545,7 +545,7 @@ data_cpy: blo data_cpy_loop bx lr -#if LIB_PICO_LOW_POWER && !PICO_RP2040 +#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER data_cpy_check: // uses r5 and r7 as scratch // uses the powman_power_state in r6 diff --git a/src/rp2_common/pico_crt0/crt0_riscv.S b/src/rp2_common/pico_crt0/crt0_riscv.S index 970531a12..674a69e3a 100644 --- a/src/rp2_common/pico_crt0/crt0_riscv.S +++ b/src/rp2_common/pico_crt0/crt0_riscv.S @@ -12,7 +12,7 @@ #include "boot/picobin.h" #include "pico/bootrom_constants.h" -#if !PICO_RP2040 +#if HAS_POWMAN_TIMER #include "hardware/regs/powman.h" #endif @@ -349,7 +349,7 @@ _call_xip_setup: // In a NO_FLASH binary, don't perform .data etc copy, since it's loaded // in-place by the SRAM load. Still need to clear .bss #if !PICO_NO_FLASH -#if LIB_PICO_LOW_POWER && !PICO_RP2040 +#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER // Load previous power state into r6 li a6, POWMAN_BASE+POWMAN_SCRATCH6_OFFSET lw a6, 0(a6) @@ -363,7 +363,7 @@ _call_xip_setup: lw a2, 4(a4) lw a3, 8(a4) addi a4, a4, 12 -#if LIB_PICO_LOW_POWER && !PICO_RP2040 +#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER jal data_cpy_check bnez a0, 1b #endif @@ -407,7 +407,7 @@ data_cpy: bltu a2, a3, data_cpy_loop ret -#if LIB_PICO_LOW_POWER && !PICO_RP2040 +#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER data_cpy_check: // uses a5 and a7 as scratch // uses the powman_power_state in a6 diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 5ac068571..417060170 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -39,7 +39,7 @@ extern "C" { #endif #include "hardware/clocks.h" -#if !PICO_RP2040 +#if HAS_POWMAN_TIMER #include "hardware/powman.h" #endif @@ -52,7 +52,7 @@ typedef enum { NUM_DORMANT_CLOCK_SOURCES } dormant_clock_source_t; -#if !PICO_RP2040 +#if HAS_POWMAN_TIMER typedef void (*low_power_pstate_resume_func)(pstate_bitset_t *pstate); #endif @@ -104,7 +104,7 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_sourc // Need to re initialize clocks after this void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_set_t *keep_enabled); -#if !PICO_RP2040 +#if HAS_POWMAN_TIMER // pstate functions should return to the pstate you were in // pass resume_func which will be called on reboot by runtime_init_low_power_reboot_check diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 91055757a..a5438f322 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -493,7 +493,7 @@ void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, low_power_wake_from_dormant(); } -#if !PICO_RP2040 +#if HAS_POWMAN_TIMER int low_power_pstate_set(pstate_bitset_t *pstate) { invalid_params_if(PICO_LOW_POWER, !pstate_bitset_is_set(pstate, POWMAN_POWER_DOMAIN_SWITCHED_CORE)); @@ -573,7 +573,7 @@ void __weak runtime_init_low_power_reboot_check(void) { PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_low_power_reboot_check, PICO_RUNTIME_INIT_LOW_POWER_REBOOT_CHECK); #endif -#endif // !PICO_RP2040 +#endif // HAS_POWMAN_TIMER #if !PICO_RUNTIME_NO_INIT_RP2350_SLEEP_FIX #include "hardware/sync.h" diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index 40d272633..0d6d1582b 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -26,7 +26,7 @@ bool repeater(repeating_timer_t *timer) { return true; } -#if !PICO_RP2040 +#if HAS_POWMAN_TIMER static bool came_from_pstate = false; static char powman_last_pwrup[100]; static char powman_last_pstate[100]; @@ -69,7 +69,7 @@ int main() { uint32_t repeater_id = 0; add_repeating_timer_ms(500, repeater, &repeater_id, &repeat); -#if !PICO_RP2040 +#if HAS_POWMAN_TIMER // use a second repeating timer on the other TIMER instance; it should be gated // during our sleep (todo not sure how it affects power!) alarm_pool_t *alarm_pool = alarm_pool_create_on_timer_with_unused_hardware_alarm(timer1_hw, 4); @@ -170,7 +170,7 @@ int main() { // powman states -#if !PICO_RP2040 +#if HAS_POWMAN_TIMER // pstate with sram0 on printf("Going to PSTATE with SRAM0 on for %d seconds\n", SLEEP_TIME_S); diff --git a/test/hello_sleep/hello_sleep_gpio.c b/test/hello_sleep/hello_sleep_gpio.c index 36daf350c..3c79a2e8c 100644 --- a/test/hello_sleep/hello_sleep_gpio.c +++ b/test/hello_sleep/hello_sleep_gpio.c @@ -24,13 +24,16 @@ bool repeater(repeating_timer_t *timer) { return true; } -#if !PICO_RP2040 +#if HAS_POWMAN_TIMER static bool came_from_pstate = false; static char powman_last_pwrup[100]; static char powman_last_pstate[100]; void pstate_resume_func(pstate_bitset_t *pstate) { came_from_pstate = true; + memset(powman_last_pwrup, 0, sizeof(powman_last_pwrup)); + memset(powman_last_pstate, 0, sizeof(powman_last_pstate)); + memset(powman_last_pstate_val, 0, sizeof(powman_last_pstate_val)); switch (powman_hw->last_swcore_pwrup) { // 0 = chip reset, for the source of the last reset see case 1 << 0: strcpy(powman_last_pwrup, "Chip reset"); break; @@ -59,7 +62,7 @@ int main() { repeating_timer_t repeat; add_repeating_timer_ms(500, repeater, NULL, &repeat); -#if !PICO_RP2040 +#if HAS_POWMAN_TIMER if (came_from_pstate) { printf("Came from powerup %s with (%s) memory kept on - skipping to end\n", powman_last_pwrup, powman_last_pstate); goto post_pstate_gpio; @@ -107,7 +110,7 @@ int main() { printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); -#if !PICO_RP2040 +#if HAS_POWMAN_TIMER printf("Going to PSTATE until GPIO wakeup\n"); pstate = pstate_bitset_none(); From 1c6575077efb695882df87fa932edad34b38a05e Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 4 Sep 2025 16:23:39 +0100 Subject: [PATCH 031/127] Redo memory handling Now only persists __persistent_data, and adds low_power_persistent_pstate_get function to return the pstate that persists all that data This uses a new pico_ld_constants.ld file, to allow CMake to modify the addresses of persistent data and the heap This new __persistent_data is only supported with HAS_POWMAN_TIMER, and does not work if your binary is signed --- src/rp2_common/pico_crt0/crt0.S | 10 +++ .../pico_crt0/embedded_start_block.inc.S | 14 ++++ .../pico_crt0/rp2350/memmap_copy_to_ram.ld | 14 +++- .../pico_crt0/rp2350/memmap_default.ld | 14 +++- .../pico_crt0/rp2350/memmap_no_flash.ld | 14 +++- .../pico_crt0/rp2350/pico_ld_constants.ld | 1 + src/rp2_common/pico_low_power/CMakeLists.txt | 24 +++++++ .../pico_low_power/include/pico/low_power.h | 3 + src/rp2_common/pico_low_power/low_power.c | 26 ++++++++ .../include/pico/platform/sections.h | 32 +++++++++ .../pico_standard_link/CMakeLists.txt | 37 +++++++++++ .../pico_ld_constants.template.ld | 1 + test/hello_sleep/CMakeLists.txt | 26 ++++++++ test/hello_sleep/hello_sleep.c | 65 +++++-------------- test/hello_sleep/hello_sleep_gpio.c | 1 - tools/CMakeLists.txt | 3 + 16 files changed, 230 insertions(+), 55 deletions(-) create mode 100644 src/rp2_common/pico_crt0/rp2350/pico_ld_constants.ld create mode 100644 src/rp2_common/pico_standard_link/pico_ld_constants.template.ld diff --git a/src/rp2_common/pico_crt0/crt0.S b/src/rp2_common/pico_crt0/crt0.S index 411909a47..c0e15d8cc 100644 --- a/src/rp2_common/pico_crt0/crt0.S +++ b/src/rp2_common/pico_crt0/crt0.S @@ -551,6 +551,10 @@ data_cpy_check: // uses the powman_power_state in r6 // returns in r0 mov r0, #0 + // Check if this is the persistent_data section + ldr r7, =__persistent_data_start__ + cmp r2, r7 + bne noskip // First check start of copy (r2) mov r7, r2 check_r7: @@ -609,6 +613,12 @@ data_cpy_table: .word __data_start__ .word __data_end__ +#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER +.word __persistent_data_loadaddr__ +.word __persistent_data_start__ +.word __persistent_data_end__ +#endif + .word __scratch_x_source__ .word __scratch_x_start__ .word __scratch_x_end__ diff --git a/src/rp2_common/pico_crt0/embedded_start_block.inc.S b/src/rp2_common/pico_crt0/embedded_start_block.inc.S index b76b34c79..e3fcd6dfc 100644 --- a/src/rp2_common/pico_crt0/embedded_start_block.inc.S +++ b/src/rp2_common/pico_crt0/embedded_start_block.inc.S @@ -38,6 +38,10 @@ #define PICO_CRT0_IMAGE_TYPE_TBYB 0 #endif +#ifndef PICO_CRT0_PIN_XIP_SRAM +#define PICO_CRT0_PIN_XIP_SRAM 0 +#endif + #if PICO_CRT0_IMAGE_TYPE_TBYB #define CRT0_TBYB_FLAG PICOBIN_IMAGE_TYPE_EXE_TBYB_BITS #else @@ -120,6 +124,16 @@ embedded_block: .word __vectors #endif +#if PICO_CRT0_PIN_XIP_SRAM +.byte PICOBIN_BLOCK_ITEM_LOAD_MAP +.byte 0x04 // word size +.byte 0 // pad +.byte 0x01 // number of entries +.word 0 // clear +.word XIP_END - 4 // last word of XIP_SRAM +.word 4 // size +#endif + .byte PICOBIN_BLOCK_ITEM_2BS_LAST .hword (embedded_block_end - embedded_block - 16 ) / 4 // total size of all .byte 0 diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld index 44c69f3b9..fa8ccdbce 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld @@ -21,6 +21,8 @@ __stack (== StackTop) */ +INCLUDE "pico_ld_constants.ld" + MEMORY { INCLUDE "pico_flash_region.ld" @@ -229,7 +231,15 @@ SECTIONS __bss_end__ = .; } > RAM - .heap (NOLOAD): + .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . : { + __persistent_data_start__ = .; + *(.persistent_data*) + . = ALIGN(4); + } AT> FLASH + PROVIDE(__persistent_data_end__ = .); + __persistent_data_loadaddr__ = LOADADDR(.persistent_data); + + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -237,7 +247,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld index bce316d14..445e72738 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld @@ -21,6 +21,8 @@ __stack (== StackTop) */ +INCLUDE "pico_ld_constants.ld" + MEMORY { INCLUDE "pico_flash_region.ld" @@ -222,7 +224,15 @@ SECTIONS __bss_end__ = .; } > RAM - .heap (NOLOAD): + .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . : { + __persistent_data_start__ = .; + *(.persistent_data*) + . = ALIGN(4); + } AT> FLASH + PROVIDE(__persistent_data_end__ = .); + __persistent_data_loadaddr__ = LOADADDR(.persistent_data); + + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -230,7 +240,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld index 5bedf6d21..2afa912df 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld @@ -21,6 +21,8 @@ __stack (== StackTop) */ +INCLUDE "pico_ld_constants.ld" + MEMORY { RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k @@ -181,7 +183,15 @@ SECTIONS __bss_end__ = .; } > RAM - .heap (NOLOAD): + .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . : { + __persistent_data_start__ = .; + *(.persistent_data*) + . = ALIGN(4); + } AT> FLASH + PROVIDE(__persistent_data_end__ = .); + __persistent_data_loadaddr__ = LOADADDR(.persistent_data); + + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -189,7 +199,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_crt0/rp2350/pico_ld_constants.ld b/src/rp2_common/pico_crt0/rp2350/pico_ld_constants.ld new file mode 100644 index 000000000..1e5bfda51 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/pico_ld_constants.ld @@ -0,0 +1 @@ +/* default file is empty */ \ No newline at end of file diff --git a/src/rp2_common/pico_low_power/CMakeLists.txt b/src/rp2_common/pico_low_power/CMakeLists.txt index b66336779..3e68153da 100644 --- a/src/rp2_common/pico_low_power/CMakeLists.txt +++ b/src/rp2_common/pico_low_power/CMakeLists.txt @@ -16,3 +16,27 @@ pico_mirrored_target_link_libraries(pico_low_power INTERFACE hardware_timer pico_aon_timer ) + +function(pico_set_persistent_data_loc TARGET PERSISTENT_DATA_LOC) + set_target_properties(${TARGET} PROPERTIES PICO_TARGET_PERSISTENT_DATA_LOC ${PERSISTENT_DATA_LOC}) + + if (PERSISTENT_DATA_LOC LESS 0x20000000) + # XIP_SRAM, so heap should come after bss + set_target_properties(${TARGET} PROPERTIES + PICO_TARGET_HEAP_LOC __bss_end__) + elseif (PERSISTENT_DATA_LOC LESS 0x20040000) + # SRAM0, so heap should come after persistent data + set_target_properties(${TARGET} PROPERTIES + PICO_TARGET_HEAP_LOC __persistent_data_end__) + elseif(PERSISTENT_DATA_LOC LESS 0x20080000) + # SRAM1, so heap should come before persistent data + set_target_properties(${TARGET} PROPERTIES + PICO_TARGET_HEAP_LOC __bss_end__ + PICO_TARGET_HEAP_LIMIT ${PERSISTENT_DATA_LOC}) + else() + # Not supported in scratch, as the linker script will overwrite persistent data with scratch data + message(FATAL_ERROR "pico_set_persistent_data_loc only supports persistent data in XIP_SRAM or SRAM0-7") + endif() + + pico_add_linker_constants(${TARGET}) +endfunction() \ No newline at end of file diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 417060170..6367e4c1f 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -123,6 +123,9 @@ int low_power_pstate_until_pin_state(uint gpio_pin, bool edge, bool high, pstate // Doesn't support powering down switched core domain int low_power_pstate_set(pstate_bitset_t *pstate); pstate_bitset_t *low_power_pstate_get(pstate_bitset_t *pstate); + +// get pstate which keeps persistent data powered on +pstate_bitset_t *low_power_persistent_pstate_get(pstate_bitset_t *pstate); #endif #ifdef __cplusplus diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index a5438f322..8c7fd32ec 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -505,6 +505,32 @@ pstate_bitset_t *low_power_pstate_get(pstate_bitset_t *pstate) { return pstate; } +pstate_bitset_t *low_power_persistent_pstate_get(pstate_bitset_t *pstate) { + pstate_bitset_clear(pstate); + extern unsigned char __persistent_data_start__[]; + extern unsigned char __persistent_data_end__[]; + + // Keep __persistent_data_start__ on + if ((uint32_t)__persistent_data_start__ < SRAM_BASE) { + pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_XIP_CACHE); + } else if ((uint32_t)__persistent_data_start__ < SRAM4_BASE) { + pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK0); + } else { + pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK1); + } + + // Keep __persistent_data_end__ on + if ((uint32_t)__persistent_data_end__ < SRAM_BASE) { + pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_XIP_CACHE); + } else if ((uint32_t)__persistent_data_end__ < SRAM4_BASE) { + pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK0); + } else { + pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK1); + } + + return pstate; +} + int low_power_go_pstate(pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func) { prepare_for_pstate_change(); diff --git a/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h b/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h index e85700295..293cb3195 100644 --- a/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h +++ b/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h @@ -98,6 +98,38 @@ #define __uninitialized_ram(group) __attribute__((section(".uninitialized_data." #group))) group #endif +#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER && !PICO_PICOTOOL_SEALED +/*! \brief Section attribute macro for placement in RAM in a section persisted across POWMAN resets + * \ingroup pico_platform + * + * Data marked this way will retain its value across a reset (normally uninitialized data - in the .persistent_data + * section) is initialized to zero during runtime initialization + * + * For example a `uint32_t` foo that will retain its value if the program is restarted by reset. + * + * uint32_t __persistent_data(foo) = 23; + * + * The section attribute is `.persistent_data.` + * + * Note: This macro is not supported for sealed binaries, as they will overwrite the persistent data + * due to the load map - use __uninitialized_ram instead. + * + * \param group a string suffix to use in the section name to distinguish groups that can be linker + * garbage-collected independently + */ +#ifndef __persistent_data +#define __persistent_data(group) __attribute__((section(".persistent_data." #group))) group +#endif +#elif PICO_PICOTOOL_SEALED +#ifndef __persistent_data +#define __persistent_data(group) group; static_assert(false, "__persistent_data is not supported for sealed binaries - use __uninitialized_ram instead") +#endif +#elif !LIB_PICO_LOW_POWER +#ifndef __persistent_data +#define __persistent_data(group) group; static_assert(false, "__persistent_data is only supported when using pico_low_power - use __uninitialized_ram instead") +#endif +#endif + /*! \brief Section attribute macro for placement in flash even in a COPY_TO_RAM binary * \ingroup pico_platform * diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index c16968bba..53cad5538 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -61,6 +61,35 @@ if (NOT TARGET pico_standard_link) endif() endfunction() + function(pico_add_linker_constants TARGET) + set(pico_ld_constants_dir ${CMAKE_BINARY_DIR}/pico_ld_constants/${TARGET}) + + # add extra constants to content + set(pico_ld_constants_content "") + get_target_property(PERSISTENT_DATA_LOC ${TARGET} PICO_TARGET_PERSISTENT_DATA_LOC) + if (PERSISTENT_DATA_LOC) + set(pico_ld_constants_content "${pico_ld_constants_content}PERSISTENT_DATA_LOC = ${PERSISTENT_DATA_LOC}; ") + endif() + get_target_property(HEAP_LOC ${TARGET} PICO_TARGET_HEAP_LOC) + if (HEAP_LOC) + set(pico_ld_constants_content "${pico_ld_constants_content}HEAP_LOC = ${HEAP_LOC}; ") + endif() + get_target_property(HEAP_LIMIT ${TARGET} PICO_TARGET_HEAP_LIMIT) + if (HEAP_LIMIT) + set(pico_ld_constants_content "${pico_ld_constants_content}HEAP_LIMIT = ${HEAP_LIMIT}; ") + endif() + + # write the constants file + if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") + # CMAKE_CURRENT_FUNCTION_LIST_DIR added in 3.17.0 + configure_file(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/pico_ld_constants.template.ld ${pico_ld_constants_dir}/pico_ld_constants.ld @ONLY) + else() + configure_file(${PICO_SDK_PATH}src/rp2_common/pico_standard_link/pico_ld_constants.template.ld ${pico_ld_constants_dir}/pico_ld_constants.ld @ONLY) + endif() + set_target_properties(${TARGET} PROPERTIES PICO_TARGET_LINKER_SCRIPT_INCLUDE_DIR ${pico_ld_constants_dir}) + pico_add_link_depend(pico_standard_link ${pico_ld_constants_dir}/pico_ld_constants.ld) + endfunction() + # pico_set_linker_script(TARGET LDSCRIPT) # \brief\ Set the linker script for the target # @@ -124,9 +153,17 @@ if (NOT TARGET pico_standard_link) #math(EXPR PICO_FLASH_SIZE_BYTES_STRING "${PICO_FLASH_SIZE_BYTES}" OUTPUT_FORMAT HEXADECIMAL) set(PICO_FLASH_SIZE_BYTES_STRING "${PICO_FLASH_SIZE_BYTES}") configure_file(${CMAKE_CURRENT_LIST_DIR}/pico_flash_region.template.ld ${CMAKE_BINARY_DIR}/pico_flash_region.ld) + pico_add_link_depend(pico_standard_link ${CMAKE_BINARY_DIR}/pico_flash_region.ld) # add include path for linker scripts target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_BINARY_DIR}") + # set extra linker script include dir + set(_LINKER_SCRIPT_INCLUDE_DIR "$>,$,${PICO_LINKER_SCRIPT_PATH}>") + target_link_options(pico_standard_link INTERFACE + "LINKER:-L${_LINKER_SCRIPT_INCLUDE_DIR}" + ) + unset(_LINKER_SCRIPT_INCLUDE_DIR) + # LINKER script will be PICO_TARGET_LINKER_SCRIPT if set on target, or ${CMAKE_CURRENT_LIST_DIR}/memmap_foo.ld # if PICO_TARGET_BINARY_TYPE is set to foo on the target, otherwise ${CMAKE_CURRENT_LIST_DIR}/memmap_${PICO_DEFAULT_BINARY_TYPE).ld set(_LINKER_SCRIPT_EXPRESSION "$>,$,${PICO_LINKER_SCRIPT_PATH}/memmap_$,>,${PICO_DEFAULT_BINARY_TYPE},$>.ld>") diff --git a/src/rp2_common/pico_standard_link/pico_ld_constants.template.ld b/src/rp2_common/pico_standard_link/pico_ld_constants.template.ld new file mode 100644 index 000000000..d7425ac28 --- /dev/null +++ b/src/rp2_common/pico_standard_link/pico_ld_constants.template.ld @@ -0,0 +1 @@ +@pico_ld_constants_content@ \ No newline at end of file diff --git a/test/hello_sleep/CMakeLists.txt b/test/hello_sleep/CMakeLists.txt index 921741737..91ef08c5e 100644 --- a/test/hello_sleep/CMakeLists.txt +++ b/test/hello_sleep/CMakeLists.txt @@ -7,6 +7,32 @@ target_link_libraries(hello_sleep pico_stdlib pico_low_power pico_status_led) # create map/bin/hex file etc. pico_add_extra_outputs(hello_sleep) + +add_executable(hello_sleep_sram1 + hello_sleep.c + ) + +target_link_libraries(hello_sleep_sram1 pico_stdlib pico_low_power pico_status_led) + +pico_set_persistent_data_loc(hello_sleep_sram1 0x20040000) + +# create map/bin/hex file etc. +pico_add_extra_outputs(hello_sleep_sram1) + + +add_executable(hello_sleep_xip_sram + hello_sleep.c + ) + +target_link_libraries(hello_sleep_xip_sram pico_stdlib pico_low_power pico_status_led) + +target_compile_definitions(hello_sleep_xip_sram PRIVATE PICO_CRT0_PIN_XIP_SRAM=1) + +pico_set_persistent_data_loc(hello_sleep_xip_sram 0x13ffc000) + +# create map/bin/hex file etc. +pico_add_extra_outputs(hello_sleep_xip_sram) + if (PICO_RP2040) add_executable(rtc_clksrc rtc_clksrc.c diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index 0d6d1582b..7693fccef 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -30,13 +30,11 @@ bool repeater(repeating_timer_t *timer) { static bool came_from_pstate = false; static char powman_last_pwrup[100]; static char powman_last_pstate[100]; -static char powman_last_pstate_val[10]; void pstate_resume_func(pstate_bitset_t *pstate) { came_from_pstate = true; memset(powman_last_pwrup, 0, sizeof(powman_last_pwrup)); memset(powman_last_pstate, 0, sizeof(powman_last_pstate)); - memset(powman_last_pstate_val, 0, sizeof(powman_last_pstate_val)); switch (powman_hw->last_swcore_pwrup) { // 0 = chip reset, for the source of the last reset see case 1 << 0: strcpy(powman_last_pwrup, "Chip reset"); break; @@ -55,7 +53,9 @@ void pstate_resume_func(pstate_bitset_t *pstate) { if (pstate_bitset_none_set(pstate)) strcat(powman_last_pstate, "NONE, "); } -static volatile int my_number = 12345; +int __persistent_data(my_number) = 12345; +int my_other_numer = 12345; + #endif int main() { @@ -79,12 +79,10 @@ int main() { if (came_from_pstate) { printf("Came from powerup %s with (%s) memory kept on - skipping to end\n", powman_last_pwrup, powman_last_pstate); - if (strstr(powman_last_pstate, "SRAM_BANK0") != NULL) { - goto post_pstate_sram0_on; - } else if (strstr(powman_last_pstate, "SRAM_BANK1") != NULL) { - goto post_pstate_sram1_on; - } else { + if (strstr(powman_last_pstate, "NONE") != NULL) { goto post_pstate_sram_off; + } else { + goto post_pstate_sram_on; } } @@ -172,13 +170,18 @@ int main() { // powman states #if HAS_POWMAN_TIMER // pstate with sram0 on - printf("Going to PSTATE with SRAM0 on for %d seconds\n", SLEEP_TIME_S); + printf("Going to PSTATE with persistent data on for %d seconds\n", SLEEP_TIME_S); if (my_number != 12345) { printf("ERROR: my_number is %d not 12345 - initialisation issue?\n", my_number); return -1; } my_number = 67890; + if (my_other_numer != 12345) { + printf("ERROR: my_other_numer is %d not 12345 - initialisation issue?\n", my_other_numer); + return -1; + } + my_other_numer = 67890; start_time = aon_timer_get_absolute_time(); @@ -186,7 +189,7 @@ int main() { powman_hw->scratch[0] = to_us_since_boot(wakeup_time) & 0xFFFFFFFF; powman_hw->scratch[1] = to_us_since_boot(wakeup_time) >> 32; pstate = pstate_bitset_none(); - pstate_bitset_add(&pstate, POWMAN_POWER_DOMAIN_SRAM_BANK0); + low_power_persistent_pstate_get(&pstate); printf("pstate: %08x\n", pstate_bitset_to_powman_power_state(&pstate)); ret = low_power_pstate_until_aon_timer(wakeup_time, &pstate, pstate_resume_func); @@ -196,7 +199,7 @@ int main() { busy_wait_ms(1000); } -post_pstate_sram0_on: +post_pstate_sram_on: // restore from scratch wakeup_time = from_us_since_boot((uint64_t)powman_hw->scratch[1] << 32 | (uint64_t)powman_hw->scratch[0]); diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); @@ -211,45 +214,11 @@ int main() { } else { printf("my_number in sram: %d\n", my_number); } - - printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); - busy_wait_ms(SLEEP_TIME_MS); - - - - // pstate with sram1 on - printf("Going to PSTATE with SRAM1 on for %d seconds\n", SLEEP_TIME_S); - - start_time = aon_timer_get_absolute_time(); - - wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); - powman_hw->scratch[0] = to_us_since_boot(wakeup_time) & 0xFFFFFFFF; - powman_hw->scratch[1] = to_us_since_boot(wakeup_time) >> 32; - pstate = pstate_bitset_none(); - pstate_bitset_add(&pstate, POWMAN_POWER_DOMAIN_SRAM_BANK1); - printf("pstate: %08x\n", pstate_bitset_to_powman_power_state(&pstate)); - ret = low_power_pstate_until_aon_timer(wakeup_time, &pstate, pstate_resume_func); - - printf("%d low_power_pstate_until_aon_timer returned\n", ret); - while (true) { - printf("Waiting\n"); - busy_wait_ms(1000); - } - -post_pstate_sram1_on: - // restore from scratch - wakeup_time = from_us_since_boot((uint64_t)powman_hw->scratch[1] << 32 | (uint64_t)powman_hw->scratch[0]); - diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); - printf("Woken up now @%dus since target\n", (int)diff); - if (diff < 0) { - printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); - } - - if (my_number != 12345) { - printf("ERROR: my_number is %d not 12345 - SRAM has not been re-loaded\n", my_number); + if (my_other_numer != 12345) { + printf("ERROR: my_other_numer is %d not 12345 - SRAM has not been re-loaded\n", my_other_numer); return -1; } else { - printf("my_number in sram: %d\n", my_number); + printf("my_other_numer in sram: %d\n", my_other_numer); } printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); diff --git a/test/hello_sleep/hello_sleep_gpio.c b/test/hello_sleep/hello_sleep_gpio.c index 3c79a2e8c..4a0be33a7 100644 --- a/test/hello_sleep/hello_sleep_gpio.c +++ b/test/hello_sleep/hello_sleep_gpio.c @@ -33,7 +33,6 @@ void pstate_resume_func(pstate_bitset_t *pstate) { came_from_pstate = true; memset(powman_last_pwrup, 0, sizeof(powman_last_pwrup)); memset(powman_last_pstate, 0, sizeof(powman_last_pstate)); - memset(powman_last_pstate_val, 0, sizeof(powman_last_pstate_val)); switch (powman_hw->last_swcore_pwrup) { // 0 = chip reset, for the source of the last reset see case 1 << 0: strcpy(powman_last_pwrup, "Chip reset"); break; diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 5a6795ef2..09d5db9cf 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -709,6 +709,9 @@ function(picotool_postprocess_binary TARGET) ${picotool_args} COMMAND_EXPAND_LISTS VERBATIM) + + # tag that this binary will be sealed + target_compile_definitions(${TARGET} PRIVATE PICO_PICOTOOL_SEALED=1) endif() # Encryption if (picotool_aesfile AND picotool_ivfile) From e2232d8bc6837af614e8bdd27163c20b21616f6d Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 4 Sep 2025 17:22:25 +0100 Subject: [PATCH 032/127] Add runtime init function to unpin xip cache that isn't persistent data --- src/rp2_common/pico_low_power/CMakeLists.txt | 2 ++ src/rp2_common/pico_low_power/low_power.c | 29 +++++++++++++++++++ .../include/pico/runtime_init.h | 16 +++++++++- test/hello_sleep/CMakeLists.txt | 2 -- test/hello_sleep/hello_sleep.c | 4 +++ 5 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/rp2_common/pico_low_power/CMakeLists.txt b/src/rp2_common/pico_low_power/CMakeLists.txt index 3e68153da..3ee14c884 100644 --- a/src/rp2_common/pico_low_power/CMakeLists.txt +++ b/src/rp2_common/pico_low_power/CMakeLists.txt @@ -24,6 +24,8 @@ function(pico_set_persistent_data_loc TARGET PERSISTENT_DATA_LOC) # XIP_SRAM, so heap should come after bss set_target_properties(${TARGET} PROPERTIES PICO_TARGET_HEAP_LOC __bss_end__) + # Also pin the XIP_SRAM + target_compile_definitions(${TARGET} PRIVATE PICO_CRT0_PIN_XIP_SRAM=1) elseif (PERSISTENT_DATA_LOC LESS 0x20040000) # SRAM0, so heap should come after persistent data set_target_properties(${TARGET} PROPERTIES diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 8c7fd32ec..680c197b7 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -599,6 +599,35 @@ void __weak runtime_init_low_power_reboot_check(void) { PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_low_power_reboot_check, PICO_RUNTIME_INIT_LOW_POWER_REBOOT_CHECK); #endif +#if !PICO_RUNTIME_NO_INIT_LOW_POWER_CACHE_UNPIN +void __weak __no_inline_not_in_flash_func(runtime_init_low_power_cache_unpin)(void) { + extern unsigned char __persistent_data_start__[]; + extern unsigned char __persistent_data_end__[]; + + // if persistent data is in xip_sram, then the whole cache is currently pinned + // for performance, we should unpin the rest of it + if ((uint32_t)__persistent_data_start__ < SRAM_BASE) { + uint32_t persistent_data_start_maintenance = XIP_MAINTENANCE_BASE + ((uint32_t)__persistent_data_start__ - XIP_BASE); + uint32_t persistent_data_end_maintenance = XIP_MAINTENANCE_BASE + ((uint32_t)__persistent_data_end__ - XIP_BASE); + volatile uint8_t* cache; + for ( + cache = (volatile uint8_t*)(XIP_MAINTENANCE_BASE + XIP_SRAM_BASE - XIP_BASE); + cache < (volatile uint8_t*)(XIP_MAINTENANCE_BASE + XIP_END - XIP_BASE); + cache += 8 + ) { + if ((uint32_t)cache >= persistent_data_start_maintenance && (uint32_t)cache < persistent_data_end_maintenance) { + continue; + } + *(cache + 0) = 0; // invalidate + } + } +} +#endif + +#if !PICO_RUNTIME_SKIP_INIT_LOW_POWER_CACHE_UNPIN +PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_low_power_cache_unpin, PICO_RUNTIME_INIT_LOW_POWER_CACHE_UNPIN); +#endif + #endif // HAS_POWMAN_TIMER #if !PICO_RUNTIME_NO_INIT_RP2350_SLEEP_FIX diff --git a/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h b/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h index b4cf31c00..a33585134 100644 --- a/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h +++ b/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h @@ -441,9 +441,23 @@ void runtime_init_bootrom_locking_enable(void); #endif // ------------------------------------------------------------ -// Low power reboot check +// Low power initialization // ------------------------------------------------------------ +// Unpin cache if persistent data is in xip_sram - do this early for performance +#ifndef PICO_RUNTIME_INIT_LOW_POWER_CACHE_UNPIN +#define PICO_RUNTIME_INIT_LOW_POWER_CACHE_UNPIN "00650" +#endif + +#ifndef PICO_RUNTIME_SKIP_INIT_LOW_POWER_CACHE_UNPIN +#define PICO_RUNTIME_SKIP_INIT_LOW_POWER_CACHE_UNPIN !HAS_POWMAN_TIMER || PICO_NO_FLASH || !PICO_CRT0_PIN_XIP_SRAM +#endif + +#ifndef PICO_RUNTIME_NO_INIT_LOW_POWER_CACHE_UNPIN +#define PICO_RUNTIME_NO_INIT_LOW_POWER_CACHE_UNPIN !HAS_POWMAN_TIMER || PICO_NO_FLASH || !PICO_CRT0_PIN_XIP_SRAM +#endif + +// Run user callback if this is a powman reboot - do this later, so user has a full SDK to work with #ifndef PICO_RUNTIME_INIT_LOW_POWER_REBOOT_CHECK #define PICO_RUNTIME_INIT_LOW_POWER_REBOOT_CHECK "11020" #endif diff --git a/test/hello_sleep/CMakeLists.txt b/test/hello_sleep/CMakeLists.txt index 91ef08c5e..c347c33e4 100644 --- a/test/hello_sleep/CMakeLists.txt +++ b/test/hello_sleep/CMakeLists.txt @@ -26,8 +26,6 @@ add_executable(hello_sleep_xip_sram target_link_libraries(hello_sleep_xip_sram pico_stdlib pico_low_power pico_status_led) -target_compile_definitions(hello_sleep_xip_sram PRIVATE PICO_CRT0_PIN_XIP_SRAM=1) - pico_set_persistent_data_loc(hello_sleep_xip_sram 0x13ffc000) # create map/bin/hex file etc. diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index 7693fccef..1ce701847 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -10,6 +10,7 @@ #include "pico/low_power.h" #include "pico/aon_timer.h" #include "pico/status_led.h" +#include "hardware/structs/xip_ctrl.h" #define SLEEP_TIME_S 2 #define SLEEP_TIME_MS SLEEP_TIME_S * 1000 @@ -22,6 +23,9 @@ bool repeater(repeating_timer_t *timer) { } else { printf(" Repeating timer %d at %dms (aon: not running)\n", *(uint32_t*)timer->user_data, to_ms_since_boot(get_absolute_time())); } + + printf("Cache hits: %f\n", (float)xip_ctrl_hw->ctr_hit / (float)xip_ctrl_hw->ctr_acc); + status_led_set_state(!status_led_get_state()); return true; } From edb88383016d3fc4c91b58137b3458534c194d2d Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 4 Sep 2025 17:31:39 +0100 Subject: [PATCH 033/127] Accept NULL pstate as default --- src/rp2_common/pico_low_power/low_power.c | 11 +++++++++++ test/hello_sleep/hello_sleep.c | 5 +---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 680c197b7..d15883c02 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -510,6 +510,11 @@ pstate_bitset_t *low_power_persistent_pstate_get(pstate_bitset_t *pstate) { extern unsigned char __persistent_data_start__[]; extern unsigned char __persistent_data_end__[]; + if (__persistent_data_start__ == __persistent_data_end__) { + // No persistent data, so power down everything + return pstate; + } + // Keep __persistent_data_start__ on if ((uint32_t)__persistent_data_start__ < SRAM_BASE) { pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_XIP_CACHE); @@ -532,6 +537,12 @@ pstate_bitset_t *low_power_persistent_pstate_get(pstate_bitset_t *pstate) { } int low_power_go_pstate(pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func) { + pstate_bitset_t default_pstate = pstate_bitset_none(); + if (pstate == NULL) { + pstate = &default_pstate; + low_power_persistent_pstate_get(pstate); + } + prepare_for_pstate_change(); // Configure the wakeup state diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index 1ce701847..b43bb6526 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -192,10 +192,7 @@ int main() { wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); powman_hw->scratch[0] = to_us_since_boot(wakeup_time) & 0xFFFFFFFF; powman_hw->scratch[1] = to_us_since_boot(wakeup_time) >> 32; - pstate = pstate_bitset_none(); - low_power_persistent_pstate_get(&pstate); - printf("pstate: %08x\n", pstate_bitset_to_powman_power_state(&pstate)); - ret = low_power_pstate_until_aon_timer(wakeup_time, &pstate, pstate_resume_func); + ret = low_power_pstate_until_aon_timer(wakeup_time, NULL, pstate_resume_func); printf("%d low_power_pstate_until_aon_timer returned\n", ret); while (true) { From 0e27c5bf82302f4840281fe3184464616d83c62f Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 4 Sep 2025 18:13:04 +0100 Subject: [PATCH 034/127] Make persistent_data NOLOAD This allows sealing, but does mean you have to initialise it (like uninitialised_data) --- .../pico_crt0/rp2350/memmap_copy_to_ram.ld | 2 +- .../pico_crt0/rp2350/memmap_default.ld | 2 +- .../pico_crt0/rp2350/memmap_no_flash.ld | 4 +-- .../include/pico/platform/sections.h | 29 +++++-------------- test/hello_sleep/hello_sleep.c | 24 +++++++++++---- test/hello_sleep/hello_sleep_gpio.c | 5 +--- 6 files changed, 31 insertions(+), 35 deletions(-) diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld index fa8ccdbce..3def1adc6 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld @@ -231,7 +231,7 @@ SECTIONS __bss_end__ = .; } > RAM - .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . : { + .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { __persistent_data_start__ = .; *(.persistent_data*) . = ALIGN(4); diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld index 445e72738..3aa11d12e 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld @@ -224,7 +224,7 @@ SECTIONS __bss_end__ = .; } > RAM - .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . : { + .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { __persistent_data_start__ = .; *(.persistent_data*) . = ALIGN(4); diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld index 2afa912df..cd4b36965 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld @@ -183,11 +183,11 @@ SECTIONS __bss_end__ = .; } > RAM - .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . : { + .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { __persistent_data_start__ = .; *(.persistent_data*) . = ALIGN(4); - } AT> FLASH + } PROVIDE(__persistent_data_end__ = .); __persistent_data_loadaddr__ = LOADADDR(.persistent_data); diff --git a/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h b/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h index 293cb3195..8ae73ab56 100644 --- a/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h +++ b/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h @@ -98,35 +98,22 @@ #define __uninitialized_ram(group) __attribute__((section(".uninitialized_data." #group))) group #endif -#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER && !PICO_PICOTOOL_SEALED -/*! \brief Section attribute macro for placement in RAM in a section persisted across POWMAN resets +#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER +/*! \brief Section attribute macro for placement in a section persisted across default POWMAN resets * \ingroup pico_platform * - * Data marked this way will retain its value across a reset (normally uninitialized data - in the .persistent_data - * section) is initialized to zero during runtime initialization - * - * For example a `uint32_t` foo that will retain its value if the program is restarted by reset. + * Data marked this way will retain its value across a default POWMAN reset * - * uint32_t __persistent_data(foo) = 23; + * For example a `uint32_t` foo that will retain its value if the program is restarted by default POWMAN reset. * - * The section attribute is `.persistent_data.` + * uint32_t __persistent_data(foo); * - * Note: This macro is not supported for sealed binaries, as they will overwrite the persistent data - * due to the load map - use __uninitialized_ram instead. + * The section attribute is `.persistent_data.` * - * \param group a string suffix to use in the section name to distinguish groups that can be linker - * garbage-collected independently + * \param name the name of the variable to place in the section */ #ifndef __persistent_data -#define __persistent_data(group) __attribute__((section(".persistent_data." #group))) group -#endif -#elif PICO_PICOTOOL_SEALED -#ifndef __persistent_data -#define __persistent_data(group) group; static_assert(false, "__persistent_data is not supported for sealed binaries - use __uninitialized_ram instead") -#endif -#elif !LIB_PICO_LOW_POWER -#ifndef __persistent_data -#define __persistent_data(group) group; static_assert(false, "__persistent_data is only supported when using pico_low_power - use __uninitialized_ram instead") +#define __persistent_data(name) __attribute__((section(".persistent_data." #name))) name #endif #endif diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index b43bb6526..7cd623a11 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -35,6 +35,9 @@ static bool came_from_pstate = false; static char powman_last_pwrup[100]; static char powman_last_pstate[100]; +int __persistent_data(my_number); +int my_other_numer = 12345; + void pstate_resume_func(pstate_bitset_t *pstate) { came_from_pstate = true; memset(powman_last_pwrup, 0, sizeof(powman_last_pwrup)); @@ -55,11 +58,17 @@ void pstate_resume_func(pstate_bitset_t *pstate) { if (pstate_bitset_is_set(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK0)) strcat(powman_last_pstate, "SRAM_BANK0, "); if (pstate_bitset_is_set(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK1)) strcat(powman_last_pstate, "SRAM_BANK1, "); if (pstate_bitset_none_set(pstate)) strcat(powman_last_pstate, "NONE, "); -} - -int __persistent_data(my_number) = 12345; -int my_other_numer = 12345; + pstate_bitset_t default_pstate = pstate_bitset_none(); + low_power_persistent_pstate_get(&default_pstate); + for (int i = 0; i < POWMAN_POWER_DOMAIN_COUNT; i++) { + if (pstate_bitset_is_set(&default_pstate, i) && !pstate_bitset_is_set(pstate, i)) { + strcat(powman_last_pstate, "PERSISTENT_DATA_OFF, "); + my_number = 34567; + break; + } + } +} #endif int main() { @@ -88,6 +97,9 @@ int main() { } else { goto post_pstate_sram_on; } + } else { + // initialise my_number on first boot + my_number = 12345; } pstate_bitset_t pstate; @@ -253,8 +265,8 @@ int main() { printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); } - if (my_number != 12345) { - printf("ERROR: my_number is not 12345 - SRAM has not been re-loaded\n"); + if (my_number != 34567) { + printf("ERROR: my_number is %d not 34567 - SRAM has not been re-loaded\n", my_number); return -1; } else { printf("my_number in sram: %d\n", my_number); diff --git a/test/hello_sleep/hello_sleep_gpio.c b/test/hello_sleep/hello_sleep_gpio.c index 4a0be33a7..0a925cee3 100644 --- a/test/hello_sleep/hello_sleep_gpio.c +++ b/test/hello_sleep/hello_sleep_gpio.c @@ -66,8 +66,6 @@ int main() { printf("Came from powerup %s with (%s) memory kept on - skipping to end\n", powman_last_pwrup, powman_last_pstate); goto post_pstate_gpio; } - - pstate_bitset_t pstate; #endif printf("Waiting %d seconds\n", SLEEP_TIME_S); // so we can see some repeat printfs @@ -112,8 +110,7 @@ int main() { #if HAS_POWMAN_TIMER printf("Going to PSTATE until GPIO wakeup\n"); - pstate = pstate_bitset_none(); - ret = low_power_pstate_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, &pstate, pstate_resume_func); + ret = low_power_pstate_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, NULL, pstate_resume_func); printf("%d low_power_pstate_until_pin_state returned\n", ret); while (true) { From 7bf2452c8978295a198804557c4e818400c8c0e6 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 5 Sep 2025 11:44:42 +0100 Subject: [PATCH 035/127] Persistent data now zeroed on non-persisted boot --- src/rp2_common/pico_crt0/crt0.S | 49 ++++++++------- src/rp2_common/pico_crt0/crt0_riscv.S | 36 ++++++----- .../pico_crt0/rp2350/memmap_copy_to_ram.ld | 3 +- .../pico_crt0/rp2350/memmap_default.ld | 3 +- .../pico_crt0/rp2350/memmap_no_flash.ld | 1 - .../include/pico/platform/sections.h | 6 +- test/hello_sleep/hello_sleep.c | 60 +++++++++++-------- 7 files changed, 88 insertions(+), 70 deletions(-) diff --git a/src/rp2_common/pico_crt0/crt0.S b/src/rp2_common/pico_crt0/crt0.S index c0e15d8cc..bd53ffdb5 100644 --- a/src/rp2_common/pico_crt0/crt0.S +++ b/src/rp2_common/pico_crt0/crt0.S @@ -482,11 +482,6 @@ _call_xip_setup: // In a NO_FLASH binary, don't perform .data etc copy, since it's loaded // in-place by the SRAM load. Still need to clear .bss #if !PICO_NO_FLASH -#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER - // Load previous power state into r6 - ldr r6, =(POWMAN_BASE+POWMAN_SCRATCH6_OFFSET) - ldr r6, [r6] -#endif adr r4, data_cpy_table // assume there is at least one entry @@ -494,11 +489,6 @@ _call_xip_setup: ldmia r4!, {r1-r3} cmp r1, #0 beq 2f -#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER - bl data_cpy_check - cmp r0, #1 - beq 1b -#endif bl data_cpy b 1b 2: @@ -507,6 +497,7 @@ _call_xip_setup: // Zero out the BSS ldr r1, =__bss_start__ ldr r2, =__bss_end__ +1: movs r0, #0 b bss_fill_test bss_fill_loop: @@ -515,6 +506,24 @@ bss_fill_test: cmp r1, r2 bne bss_fill_loop +#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER + // Check if we're done + ldr r6, =__bss_end__ + cmp r2, r6 + bne 1f + // Zero out persistent_data on non-powman boot + ldr r1, =__persistent_data_start__ + ldr r2, =__persistent_data_end__ + // Load previous power state into r6 + ldr r6, =(POWMAN_BASE+POWMAN_SCRATCH6_OFFSET) + ldr r6, [r6] + // Check if we should skip zeroing + bl persistent_zero_check + cmp r0, #0 + beq 1b +1: +#endif + platform_entry: // symbol for stack traces #if PICO_CRT0_NEAR_CALLS && !PICO_COPY_TO_RAM bl runtime_init @@ -544,19 +553,16 @@ data_cpy: cmp r2, r3 blo data_cpy_loop bx lr +#endif #if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER -data_cpy_check: +persistent_zero_check: // uses r5 and r7 as scratch // uses the powman_power_state in r6 // returns in r0 mov r0, #0 - // Check if this is the persistent_data section + // First check __persistent_data_start__ ldr r7, =__persistent_data_start__ - cmp r2, r7 - bne noskip - // First check start of copy (r2) - mov r7, r2 check_r7: ldr r5, =SRAM_BASE cmp r5, r7 @@ -584,14 +590,13 @@ skip: bx lr check_end: add r0, #1 - // If start was skipped, check end of copy - mov r7, r3 + // If start was skipped, check __persistent_data_end__ + ldr r7, =__persistent_data_end__ b check_r7 noskip: mov r0, #0 bx lr #endif -#endif // Note the data copy table is still included for NO_FLASH builds, even though // we skip the copy, because it is listed in binary info @@ -613,12 +618,6 @@ data_cpy_table: .word __data_start__ .word __data_end__ -#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER -.word __persistent_data_loadaddr__ -.word __persistent_data_start__ -.word __persistent_data_end__ -#endif - .word __scratch_x_source__ .word __scratch_x_start__ .word __scratch_x_end__ diff --git a/src/rp2_common/pico_crt0/crt0_riscv.S b/src/rp2_common/pico_crt0/crt0_riscv.S index 674a69e3a..202289de5 100644 --- a/src/rp2_common/pico_crt0/crt0_riscv.S +++ b/src/rp2_common/pico_crt0/crt0_riscv.S @@ -349,11 +349,6 @@ _call_xip_setup: // In a NO_FLASH binary, don't perform .data etc copy, since it's loaded // in-place by the SRAM load. Still need to clear .bss #if !PICO_NO_FLASH -#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER - // Load previous power state into r6 - li a6, POWMAN_BASE+POWMAN_SCRATCH6_OFFSET - lw a6, 0(a6) -#endif la a4, data_cpy_table // assume there is at least one entry @@ -363,10 +358,6 @@ _call_xip_setup: lw a2, 4(a4) lw a3, 8(a4) addi a4, a4, 12 -#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER - jal data_cpy_check - bnez a0, 1b -#endif jal data_cpy j 1b 2: @@ -382,6 +373,22 @@ bss_fill_loop: bss_fill_test: bne a1, a2, bss_fill_loop +#if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER + // Check if we're done + la a6, __bss_end__ + bne a2, a6, 1f + // Zero out persistent_data on non-powman boot + la a1, __persistent_data_start__ + la a2, __persistent_data_end__ + // Load previous power state into r6 + li a6, POWMAN_BASE+POWMAN_SCRATCH6_OFFSET + lw a6, 0(a6) + // Check if we should skip zeroing + jal persistent_zero_check + beqz a0, bss_fill_test +1: +#endif + platform_entry: // symbol for stack traces // Use `call` pseudo-instruction instead of a bare `jal` so that the // linker can use longer sequences if these are out of `jal` range. Will @@ -406,15 +413,16 @@ data_cpy_loop: data_cpy: bltu a2, a3, data_cpy_loop ret +#endif #if LIB_PICO_LOW_POWER && HAS_POWMAN_TIMER -data_cpy_check: +persistent_zero_check: // uses a5 and a7 as scratch // uses the powman_power_state in a6 // returns in a0 li a0, 0 - // First check start of copy (a2) - mv a7, a2 + // First check __persistent_data_start__ + la a7, __persistent_data_start__ check_a7: li a5, SRAM_BASE bgt a5, a7, check_xip_sram @@ -438,13 +446,13 @@ skip: ret check_end: addi a0, a0, 1 - mv a7, a3 + // If start was skipped, check __persistent_data_end__ + la a7, __persistent_data_end__ j check_a7 noskip: li a0, 0 ret #endif -#endif .align 2 data_cpy_table: diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld index 3def1adc6..186225423 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld @@ -235,9 +235,8 @@ SECTIONS __persistent_data_start__ = .; *(.persistent_data*) . = ALIGN(4); - } AT> FLASH + } PROVIDE(__persistent_data_end__ = .); - __persistent_data_loadaddr__ = LOADADDR(.persistent_data); .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld index 3aa11d12e..f6f150ad6 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld @@ -228,9 +228,8 @@ SECTIONS __persistent_data_start__ = .; *(.persistent_data*) . = ALIGN(4); - } AT> FLASH + } PROVIDE(__persistent_data_end__ = .); - __persistent_data_loadaddr__ = LOADADDR(.persistent_data); .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld index cd4b36965..798891406 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld @@ -189,7 +189,6 @@ SECTIONS . = ALIGN(4); } PROVIDE(__persistent_data_end__ = .); - __persistent_data_loadaddr__ = LOADADDR(.persistent_data); .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { diff --git a/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h b/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h index 8ae73ab56..6a61b0729 100644 --- a/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h +++ b/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h @@ -102,9 +102,11 @@ /*! \brief Section attribute macro for placement in a section persisted across default POWMAN resets * \ingroup pico_platform * - * Data marked this way will retain its value across a default POWMAN reset + * Data marked this way will retain its value across a default POWMAN reset, and will be zeroed on + * any other reset. * - * For example a `uint32_t` foo that will retain its value if the program is restarted by default POWMAN reset. + * For example a `uint32_t` foo that will be zeroed initially, then retain its value if the program + * is restarted by default POWMAN reset. * * uint32_t __persistent_data(foo); * diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index 7cd623a11..30621e30d 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -19,12 +19,16 @@ bool repeater(repeating_timer_t *timer) { if (aon_timer_is_running()) { - printf(" Repeating timer %d at %dms (aon: %dms)\n", *(uint32_t*)timer->user_data, to_ms_since_boot(get_absolute_time()), to_ms_since_boot(aon_timer_get_absolute_time())); + printf(" Repeating timer %d at %dms (aon: %dms)", *(uint32_t*)timer->user_data, to_ms_since_boot(get_absolute_time()), to_ms_since_boot(aon_timer_get_absolute_time())); } else { - printf(" Repeating timer %d at %dms (aon: not running)\n", *(uint32_t*)timer->user_data, to_ms_since_boot(get_absolute_time())); + printf(" Repeating timer %d at %dms (aon: not running)", *(uint32_t*)timer->user_data, to_ms_since_boot(get_absolute_time())); } - printf("Cache hits: %f\n", (float)xip_ctrl_hw->ctr_hit / (float)xip_ctrl_hw->ctr_acc); +#if PICO_NO_FLASH || PICO_COPY_TO_RAM + printf("\n"); +#else + printf(" - Cache hit rate %.2f%%\n", ((float)xip_ctrl_hw->ctr_hit / (float)xip_ctrl_hw->ctr_acc) * 100.0f); +#endif status_led_set_state(!status_led_get_state()); return true; @@ -36,7 +40,9 @@ static char powman_last_pwrup[100]; static char powman_last_pstate[100]; int __persistent_data(my_number); -int my_other_numer = 12345; + +// Increase this size to see the cache hit rate decrease, when using XIP_SRAM for persistent data +char __persistent_data(large_thing)[0x1000]; void pstate_resume_func(pstate_bitset_t *pstate) { came_from_pstate = true; @@ -64,7 +70,7 @@ void pstate_resume_func(pstate_bitset_t *pstate) { for (int i = 0; i < POWMAN_POWER_DOMAIN_COUNT; i++) { if (pstate_bitset_is_set(&default_pstate, i) && !pstate_bitset_is_set(pstate, i)) { strcat(powman_last_pstate, "PERSISTENT_DATA_OFF, "); - my_number = 34567; + if (my_number == 0) my_number = 34567; // initialise my_number to special value break; } } @@ -90,6 +96,14 @@ int main() { uint32_t repeater2_id = 1; alarm_pool_add_repeating_timer_ms(alarm_pool, 500, repeater, &repeater2_id, &repeat2); + if (my_number == 0) { + // initialise persistent data + my_number = 12345; + memset(large_thing, 0x55, sizeof(large_thing)); + // track number of reboots + powman_hw->scratch[3] = 0; + } + if (came_from_pstate) { printf("Came from powerup %s with (%s) memory kept on - skipping to end\n", powman_last_pwrup, powman_last_pstate); if (strstr(powman_last_pstate, "NONE") != NULL) { @@ -97,9 +111,6 @@ int main() { } else { goto post_pstate_sram_on; } - } else { - // initialise my_number on first boot - my_number = 12345; } pstate_bitset_t pstate; @@ -109,7 +120,7 @@ int main() { busy_wait_ms(SLEEP_TIME_MS); absolute_time_t start_time; - absolute_time_t wakeup_time; + static absolute_time_t __persistent_data(wakeup_time); int64_t diff; struct timespec ts; int ret; @@ -193,17 +204,10 @@ int main() { return -1; } my_number = 67890; - if (my_other_numer != 12345) { - printf("ERROR: my_other_numer is %d not 12345 - initialisation issue?\n", my_other_numer); - return -1; - } - my_other_numer = 67890; start_time = aon_timer_get_absolute_time(); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); - powman_hw->scratch[0] = to_us_since_boot(wakeup_time) & 0xFFFFFFFF; - powman_hw->scratch[1] = to_us_since_boot(wakeup_time) >> 32; ret = low_power_pstate_until_aon_timer(wakeup_time, NULL, pstate_resume_func); printf("%d low_power_pstate_until_aon_timer returned\n", ret); @@ -213,12 +217,15 @@ int main() { } post_pstate_sram_on: - // restore from scratch - wakeup_time = from_us_since_boot((uint64_t)powman_hw->scratch[1] << 32 | (uint64_t)powman_hw->scratch[0]); + // track number of reboots + powman_hw->scratch[3]++; diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); printf("Woken up now @%dus since target\n", (int)diff); if (diff < 0) { printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); + } else if (diff > 1000000) { + printf("ERROR: Woke up more than %d seconds late\n", (int)(diff / 1000000)); + return -1; } if (my_number != 67890) { @@ -227,12 +234,6 @@ int main() { } else { printf("my_number in sram: %d\n", my_number); } - if (my_other_numer != 12345) { - printf("ERROR: my_other_numer is %d not 12345 - SRAM has not been re-loaded\n", my_other_numer); - return -1; - } else { - printf("my_other_numer in sram: %d\n", my_other_numer); - } printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); @@ -245,6 +246,7 @@ int main() { start_time = aon_timer_get_absolute_time(); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); + // store in scratch, as not persisting memory over this reboot powman_hw->scratch[0] = to_us_since_boot(wakeup_time) & 0xFFFFFFFF; powman_hw->scratch[1] = to_us_since_boot(wakeup_time) >> 32; pstate = pstate_bitset_none(); @@ -257,12 +259,17 @@ int main() { } post_pstate_sram_off: + // track number of reboots + powman_hw->scratch[3]++; // restore from scratch wakeup_time = from_us_since_boot((uint64_t)powman_hw->scratch[1] << 32 | (uint64_t)powman_hw->scratch[0]); diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); printf("Woken up now @%dus since target\n", (int)diff); if (diff < 0) { printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); + } else if (diff > 1000000) { + printf("ERROR: Woke up more than %d seconds late\n", (int)(diff / 1000000)); + return -1; } if (my_number != 34567) { @@ -274,6 +281,11 @@ int main() { printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); + + if (powman_hw->scratch[3] != 2) { + printf("ERROR: number of POWMAN reboots was %d not 2\n", powman_hw->scratch[3]); + return -1; + } #endif printf("SUCCESS\n"); From 95eacfef0942fc83e8a4f6b6e2b2e8caa633cac8 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 5 Sep 2025 14:57:46 +0100 Subject: [PATCH 036/127] Add USB support and chars_available callback Also add no_flash test for RP2350 --- src/rp2_common/pico_low_power/CMakeLists.txt | 5 +- src/rp2_common/pico_low_power/low_power.c | 38 ++++++++++- .../include/pico/platform/sections.h | 5 ++ src/rp2_common/pico_stdio_usb/stdio_usb.c | 9 ++- test/hello_sleep/CMakeLists.txt | 68 ++++++++++++++++--- test/hello_sleep/hello_sleep.c | 31 +++++++-- 6 files changed, 137 insertions(+), 19 deletions(-) diff --git a/src/rp2_common/pico_low_power/CMakeLists.txt b/src/rp2_common/pico_low_power/CMakeLists.txt index 3ee14c884..848a0413e 100644 --- a/src/rp2_common/pico_low_power/CMakeLists.txt +++ b/src/rp2_common/pico_low_power/CMakeLists.txt @@ -18,6 +18,9 @@ pico_mirrored_target_link_libraries(pico_low_power INTERFACE ) function(pico_set_persistent_data_loc TARGET PERSISTENT_DATA_LOC) + if (NOT PICO_RP2350) + message(FATAL_ERROR "pico_set_persistent_data_loc is only supported on RP2350") + endif() set_target_properties(${TARGET} PROPERTIES PICO_TARGET_PERSISTENT_DATA_LOC ${PERSISTENT_DATA_LOC}) if (PERSISTENT_DATA_LOC LESS 0x20000000) @@ -41,4 +44,4 @@ function(pico_set_persistent_data_loc TARGET PERSISTENT_DATA_LOC) endif() pico_add_linker_constants(${TARGET}) -endfunction() \ No newline at end of file +endfunction() diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index d15883c02..db684c2ad 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -70,16 +70,23 @@ static void prepare_for_clock_switch(void) { // particularly for UART we want nothing left to clock out prepare_for_clock_gating(); +#if LIB_PICO_STDIO_USB + // deinit USB + stdio_usb_deinit(); +#endif + // disable interrupts interrupt_flags = save_and_disable_interrupts(); } static void post_clock_switch(void) { - // restore UART baudrate - setup_default_uart(); - // restore interrupts restore_interrupts_from_disabled(interrupt_flags); + +#if LIB_PICO_STDIO_USB + // reinit USB + stdio_usb_init(); +#endif } #if HAS_POWMAN_TIMER @@ -136,6 +143,27 @@ static void replace_null_enable_values(const clock_dest_set_t *keep_enabled, } } +static void add_stdio_clocks(clock_dest_set_t *local_keep_enabled) { +#if LIB_PICO_STDIO_USB + // this is necessary to prevent dropping the connection + #if PICO_RP2040 + clock_dest_set_add(local_keep_enabled, CLK_DEST_SYS_USBCTRL); + clock_dest_set_add(local_keep_enabled, CLK_DEST_USB_USBCTRL); + #elif PICO_RP2350 + clock_dest_set_add(local_keep_enabled, CLK_DEST_SYS_USBCTRL); + clock_dest_set_add(local_keep_enabled, CLK_DEST_USB); + #else + #error Unknown processor + #endif +#endif + +#if LIB_PICO_STDIO_UART + // this is only needed to prevent losing stdin while sleeping + clock_dest_set_add(local_keep_enabled, PICO_DEFAULT_UART ? CLK_DEST_PERI_UART1 : CLK_DEST_PERI_UART0); + clock_dest_set_add(local_keep_enabled, PICO_DEFAULT_UART ? CLK_DEST_SYS_UART1 : CLK_DEST_SYS_UART0); +#endif +} + static uint32_t irq_mask_disabled_during_sleep[NUM_IRQS]; static void save_and_disable_other_interrupts(uint32_t irq) { @@ -182,6 +210,8 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, #error Unknown processor #endif + add_stdio_clocks(&local_keep_enabled); + #if NUM_GENERIC_TIMERS == 1 #define TIMER_BASE_IRQ TIMER_IRQ_0 #else @@ -217,6 +247,8 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, clock_dest_set_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); + add_stdio_clocks(&local_keep_enabled); + bool low = !high; bool level = !edge; diff --git a/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h b/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h index 6a61b0729..591e9e3b2 100644 --- a/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h +++ b/src/rp2_common/pico_platform_sections/include/pico/platform/sections.h @@ -117,6 +117,11 @@ #ifndef __persistent_data #define __persistent_data(name) __attribute__((section(".persistent_data." #name))) name #endif +#else +// If not supported, use the .bss section, as that will be zeroed on boot +#ifndef __persistent_data +#define __persistent_data(name) __attribute__((section(".bss." #name))) name +#endif #endif /*! \brief Section attribute macro for placement in flash even in a COPY_TO_RAM binary diff --git a/src/rp2_common/pico_stdio_usb/stdio_usb.c b/src/rp2_common/pico_stdio_usb/stdio_usb.c index bbff5f612..e2b74a45f 100644 --- a/src/rp2_common/pico_stdio_usb/stdio_usb.c +++ b/src/rp2_common/pico_stdio_usb/stdio_usb.c @@ -261,8 +261,6 @@ bool stdio_usb_deinit(void) { return false; } - assert(tud_inited()); // we expect the caller to have initialized when calling sdio_usb_init - bool rc = true; stdio_set_driver_enabled(&stdio_usb, false); @@ -271,6 +269,13 @@ bool stdio_usb_deinit(void) { sleep_ms(PICO_STDIO_USB_DEINIT_DELAY_MS); #endif +#if PICO_STDIO_USB_ENABLE_TINYUSB_INIT + // deinitialize TinyUSB + tud_deinit(0); +#else + assert(!tud_inited()); // we expect the caller to have deinitialized if they are using TinyUSB +#endif + #if PICO_STDIO_USB_ENABLE_IRQ_BACKGROUND_TASK if (irq_has_shared_handler(USBCTRL_IRQ)) { spin_lock_unclaim(spin_lock_get_num(one_shot_timer_crit_sec.spin_lock)); diff --git a/test/hello_sleep/CMakeLists.txt b/test/hello_sleep/CMakeLists.txt index c347c33e4..6706f42b7 100644 --- a/test/hello_sleep/CMakeLists.txt +++ b/test/hello_sleep/CMakeLists.txt @@ -8,28 +8,58 @@ target_link_libraries(hello_sleep pico_stdlib pico_low_power pico_status_led) pico_add_extra_outputs(hello_sleep) -add_executable(hello_sleep_sram1 +add_executable(hello_sleep_usb hello_sleep.c ) -target_link_libraries(hello_sleep_sram1 pico_stdlib pico_low_power pico_status_led) +target_link_libraries(hello_sleep_usb pico_stdlib pico_low_power pico_status_led) -pico_set_persistent_data_loc(hello_sleep_sram1 0x20040000) +pico_enable_stdio_usb(hello_sleep_usb 1) # create map/bin/hex file etc. -pico_add_extra_outputs(hello_sleep_sram1) +pico_add_extra_outputs(hello_sleep_usb) -add_executable(hello_sleep_xip_sram +add_executable(hello_sleep_sram1 hello_sleep.c ) -target_link_libraries(hello_sleep_xip_sram pico_stdlib pico_low_power pico_status_led) +target_link_libraries(hello_sleep_sram1 pico_stdlib pico_low_power pico_status_led) -pico_set_persistent_data_loc(hello_sleep_xip_sram 0x13ffc000) +if (NOT PICO_RP2040) + pico_set_persistent_data_loc(hello_sleep_sram1 0x20040000) +endif() # create map/bin/hex file etc. -pico_add_extra_outputs(hello_sleep_xip_sram) +pico_add_extra_outputs(hello_sleep_sram1) + +if (NOT PICO_RP2040) + add_executable(hello_sleep_xip_sram + hello_sleep.c + ) + + target_link_libraries(hello_sleep_xip_sram pico_stdlib pico_low_power pico_status_led) + + pico_set_persistent_data_loc(hello_sleep_xip_sram 0x13ffc000) + + # create map/bin/hex file etc. + pico_add_extra_outputs(hello_sleep_xip_sram) + + + add_executable(hello_sleep_xip_sram_no_flash + hello_sleep.c + ) + + target_link_libraries(hello_sleep_xip_sram_no_flash pico_stdlib pico_low_power pico_status_led) + + pico_set_persistent_data_loc(hello_sleep_xip_sram_no_flash 0x13ffc000) + + pico_set_binary_type(hello_sleep_xip_sram_no_flash no_flash) + pico_package_uf2_output(hello_sleep_xip_sram_no_flash) + + # create map/bin/hex file etc. + pico_add_extra_outputs(hello_sleep_xip_sram_no_flash) +endif() if (PICO_RP2040) add_executable(rtc_clksrc @@ -50,3 +80,25 @@ target_link_libraries(hello_sleep_gpio pico_stdlib pico_low_power pico_status_le # create map/bin/hex file etc. pico_add_extra_outputs(hello_sleep_gpio) + + +add_executable(hello_sleep_gpio_usb + hello_sleep_gpio.c + ) + +target_link_libraries(hello_sleep_gpio_usb pico_stdlib pico_low_power pico_status_led) + +pico_enable_stdio_usb(hello_sleep_gpio_usb 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(hello_sleep_gpio_usb) + + +add_custom_target(hello_sleep_examples) +get_directory_property(targets BUILDSYSTEM_TARGETS DIRECTORY ${CMAKE_CURRENT_LIST_DIR}) +foreach(target IN LISTS targets) + get_target_property(type ${target} TYPE) + if(type STREQUAL "EXECUTABLE") + add_dependencies(hello_sleep_examples ${target}) + endif() +endforeach() diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index 30621e30d..538a273d2 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -34,6 +34,13 @@ bool repeater(repeating_timer_t *timer) { return true; } +void chars_available_callback(__unused void *param) { + char buf[16] = {0}; + while (stdio_get_until(buf, sizeof(buf), make_timeout_time_us(10)) > 0) { + printf("Chars available callback: %s\n", buf); + } +} + #if HAS_POWMAN_TIMER static bool came_from_pstate = false; static char powman_last_pwrup[100]; @@ -88,13 +95,16 @@ int main() { uint32_t repeater_id = 0; add_repeating_timer_ms(500, repeater, &repeater_id, &repeat); + // test stdio_set_chars_available_callback + stdio_set_chars_available_callback(chars_available_callback, NULL); + #if HAS_POWMAN_TIMER // use a second repeating timer on the other TIMER instance; it should be gated // during our sleep (todo not sure how it affects power!) alarm_pool_t *alarm_pool = alarm_pool_create_on_timer_with_unused_hardware_alarm(timer1_hw, 4); repeating_timer_t repeat2; uint32_t repeater2_id = 1; - alarm_pool_add_repeating_timer_ms(alarm_pool, 500, repeater, &repeater2_id, &repeat2); + alarm_pool_add_repeating_timer_ms(alarm_pool, 700, repeater, &repeater2_id, &repeat2); if (my_number == 0) { // initialise persistent data @@ -177,10 +187,13 @@ int main() { DORMANT_CLOCK_SOURCE_LPOSC, XOSC_HZ, #endif RTC_GPIO, NULL); - diff = absolute_time_diff_us(get_absolute_time(), wakeup_time); // need to use the AON timer for checking time, since the other timer is unclocked diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); - if (diff > -1000000) { + if (diff > -1000000 + #ifdef PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS + + (PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS * 1000) + #endif + ) { printf("ERROR: doesn't seem like timer was stopped\n"); return - 1; } @@ -223,7 +236,11 @@ int main() { printf("Woken up now @%dus since target\n", (int)diff); if (diff < 0) { printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); - } else if (diff > 1000000) { + } else if (diff > 1000000 + #ifdef PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS + + (PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS * 1000) + #endif + ) { printf("ERROR: Woke up more than %d seconds late\n", (int)(diff / 1000000)); return -1; } @@ -267,7 +284,11 @@ int main() { printf("Woken up now @%dus since target\n", (int)diff); if (diff < 0) { printf("WARNING: Woke up too soon - is this within the resolution of the aon timer?\n"); - } else if (diff > 1000000) { + } else if (diff > 1000000 + #ifdef PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS + + (PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS * 1000) + #endif + ) { printf("ERROR: Woke up more than %d seconds late\n", (int)(diff / 1000000)); return -1; } From 7e23f0b20d91aee62180ecb78cc50ef64a014a7f Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 5 Sep 2025 15:56:01 +0100 Subject: [PATCH 037/127] Implement low_power_sleep_until_irq Add to hello_sleep_gpio test using chars_available_callback --- src/rp2_common/pico_low_power/low_power.c | 20 ++++++++++++++++++++ test/hello_sleep/hello_sleep_gpio.c | 16 ++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index db684c2ad..d12e02fe5 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -182,6 +182,26 @@ static void restore_other_interrupts(void) { } } +int low_power_sleep_until_irq(const clock_dest_set_t *keep_enabled) { + clock_dest_set_t local_keep_enabled; + replace_null_enable_values(keep_enabled, &local_keep_enabled); + + add_stdio_clocks(&local_keep_enabled); + + prepare_for_clock_gating(); + // gate clocks + clock_gate_sleep_en(&local_keep_enabled); + + low_power_enable_processor_deep_sleep(); + // Go to sleep until any event happens + __wfi(); + low_power_disable_processor_deep_sleep(); + + post_clock_gating(); + + return 0; +} + // only the deep_sleep variant of this, as DORMANT cannot wake from TIMER int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, const clock_dest_set_t *keep_enabled, bool exclusive) { diff --git a/test/hello_sleep/hello_sleep_gpio.c b/test/hello_sleep/hello_sleep_gpio.c index 0a925cee3..f2789f618 100644 --- a/test/hello_sleep/hello_sleep_gpio.c +++ b/test/hello_sleep/hello_sleep_gpio.c @@ -24,6 +24,13 @@ bool repeater(repeating_timer_t *timer) { return true; } +void chars_available_callback(__unused void *param) { + char buf[16] = {0}; + while (stdio_get_until(buf, sizeof(buf), make_timeout_time_us(10)) > 0) { + printf("Chars available callback: %s\n", buf); + } +} + #if HAS_POWMAN_TIMER static bool came_from_pstate = false; static char powman_last_pwrup[100]; @@ -61,6 +68,9 @@ int main() { repeating_timer_t repeat; add_repeating_timer_ms(500, repeater, NULL, &repeat); + // test stdio_set_chars_available_callback + stdio_set_chars_available_callback(chars_available_callback, NULL); + #if HAS_POWMAN_TIMER if (came_from_pstate) { printf("Came from powerup %s with (%s) memory kept on - skipping to end\n", powman_last_pwrup, powman_last_pstate); @@ -96,6 +106,12 @@ int main() { printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); + printf("Going to sleep until any wakeup (expecting stdin characters)\n"); + + low_power_sleep_until_irq(NULL); + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); + // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync start_time = get_absolute_time(); us_to_timespec(start_time, &ts); From 0559a34c7401c2971f4ab09167ca60f2e7303fb8 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 5 Sep 2025 16:07:16 +0100 Subject: [PATCH 038/127] Fix infinite loop with no persistent data --- src/rp2_common/pico_crt0/crt0.S | 3 +++ src/rp2_common/pico_crt0/crt0_riscv.S | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/rp2_common/pico_crt0/crt0.S b/src/rp2_common/pico_crt0/crt0.S index bd53ffdb5..fa113fbab 100644 --- a/src/rp2_common/pico_crt0/crt0.S +++ b/src/rp2_common/pico_crt0/crt0.S @@ -514,6 +514,9 @@ bss_fill_test: // Zero out persistent_data on non-powman boot ldr r1, =__persistent_data_start__ ldr r2, =__persistent_data_end__ + // Skip if there is no persistent data + cmp r1, r2 + beq 1f // Load previous power state into r6 ldr r6, =(POWMAN_BASE+POWMAN_SCRATCH6_OFFSET) ldr r6, [r6] diff --git a/src/rp2_common/pico_crt0/crt0_riscv.S b/src/rp2_common/pico_crt0/crt0_riscv.S index 202289de5..31d39749f 100644 --- a/src/rp2_common/pico_crt0/crt0_riscv.S +++ b/src/rp2_common/pico_crt0/crt0_riscv.S @@ -380,6 +380,8 @@ bss_fill_test: // Zero out persistent_data on non-powman boot la a1, __persistent_data_start__ la a2, __persistent_data_end__ + // Skip if there is no persistent data + beq a1, a2, 1f // Load previous power state into r6 li a6, POWMAN_BASE+POWMAN_SCRATCH6_OFFSET lw a6, 0(a6) From e65135f15bc084687af1cc3f346e0b73c8de5d58 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 5 Sep 2025 16:55:52 +0100 Subject: [PATCH 039/127] Add encrypted sleep test --- test/hello_sleep/CMakeLists.txt | 17 +++++++++++++++++ tools/CMakeLists.txt | 20 +++++++++++++++++++- tools/example_keys/ivsalt.bin | 1 + 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 tools/example_keys/ivsalt.bin diff --git a/test/hello_sleep/CMakeLists.txt b/test/hello_sleep/CMakeLists.txt index 6706f42b7..093ec60a3 100644 --- a/test/hello_sleep/CMakeLists.txt +++ b/test/hello_sleep/CMakeLists.txt @@ -34,6 +34,23 @@ endif() pico_add_extra_outputs(hello_sleep_sram1) if (NOT PICO_RP2040) + if (NOT PICO_RISCV) + add_executable(hello_sleep_encrypted + hello_sleep.c + ) + + target_link_libraries(hello_sleep_encrypted pico_stdlib pico_low_power pico_status_led) + + pico_set_binary_type(hello_sleep_encrypted no_flash) + pico_package_uf2_output(hello_sleep_encrypted) + pico_sign_binary(hello_sleep_encrypted ${CMAKE_SOURCE_DIR}/tools/example_keys/private.pem) + pico_encrypt_binary(hello_sleep_encrypted ${CMAKE_SOURCE_DIR}/tools/example_keys/privateaes.bin ${CMAKE_SOURCE_DIR}/tools/example_keys/ivsalt.bin EMBED NO_CLEAR) + + # create map/bin/hex file etc. + pico_add_extra_outputs(hello_sleep_encrypted) + endif() + + add_executable(hello_sleep_xip_sram hello_sleep.c ) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 09d5db9cf..60eb5dd3b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -65,6 +65,12 @@ define_property(TARGET BRIEF_DOCS "OTP page storing the AES key" FULL_DOCS "OTP page storing the AES key" ) +define_property(TARGET + PROPERTY PICOTOOL_ENC_NO_CLEAR + INHERITED + BRIEF_DOCS "Do not clear SRAM when loading encrypted binary" + FULL_DOCS "Do not clear SRAM when loading encrypted binary" +) define_property(TARGET PROPERTY PICOTOOL_ENC_SIGFILE INHERITED @@ -510,8 +516,9 @@ endfunction() # \param\ EMBED Embed a decryption stage into the encrypted binary # \param\ MBEDTLS Use MbedTLS based decryption stage (faster, but less secure) # \param\ OTP_KEY_PAGE The OTP page storing the AES key +# \param\ NO_CLEAR Do not clear SRAM when loading encrypted binary function(pico_encrypt_binary TARGET AESFILE IVFILE) - set(options EMBED MBEDTLS) + set(options EMBED MBEDTLS NO_CLEAR) set(oneValueArgs OTP_KEY_PAGE SIGFILE) # set(multiValueArgs ) cmake_parse_arguments(PARSE_ARGV 3 ENC "${options}" "${oneValueArgs}" "${multiValueArgs}") @@ -543,6 +550,12 @@ function(pico_encrypt_binary TARGET AESFILE IVFILE) ) endif() + if (ENC_NO_CLEAR) + set_target_properties(${TARGET} PROPERTIES + PICOTOOL_ENC_NO_CLEAR TRUE + ) + endif() + if (ENC_OTP_KEY_PAGE) set_target_properties(${TARGET} PROPERTIES PICOTOOL_OTP_KEY_PAGE ${ENC_OTP_KEY_PAGE} @@ -715,6 +728,11 @@ function(picotool_postprocess_binary TARGET) endif() # Encryption if (picotool_aesfile AND picotool_ivfile) + get_target_property(enc_no_clear ${TARGET} PICOTOOL_ENC_NO_CLEAR) + if (NOT enc_no_clear) + list(APPEND picotool_encrypt_args "--clear") + endif() + get_target_property(picotool_embed_decryption ${TARGET} PICOTOOL_EMBED_DECRYPTION) if (picotool_embed_decryption) list(APPEND picotool_encrypt_args "--embed") diff --git a/tools/example_keys/ivsalt.bin b/tools/example_keys/ivsalt.bin new file mode 100644 index 000000000..fb9ef50b8 --- /dev/null +++ b/tools/example_keys/ivsalt.bin @@ -0,0 +1 @@ +Œ¶ÆxìÛ%Ü^ùÂ=T’ÄŒ \ No newline at end of file From 7aa06f471cc12d7c39ad86c594bbea6e971df522 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 9 Sep 2025 11:59:30 +0100 Subject: [PATCH 040/127] Update xip pinning load map size of 0 works --- src/rp2_common/pico_crt0/embedded_start_block.inc.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rp2_common/pico_crt0/embedded_start_block.inc.S b/src/rp2_common/pico_crt0/embedded_start_block.inc.S index e3fcd6dfc..000da904b 100644 --- a/src/rp2_common/pico_crt0/embedded_start_block.inc.S +++ b/src/rp2_common/pico_crt0/embedded_start_block.inc.S @@ -130,8 +130,8 @@ embedded_block: .byte 0 // pad .byte 0x01 // number of entries .word 0 // clear -.word XIP_END - 4 // last word of XIP_SRAM -.word 4 // size +.word XIP_SRAM_BASE +.word 0 // size #endif .byte PICOBIN_BLOCK_ITEM_2BS_LAST From 49d03aacd0e6b3dd740ba85d5b1261d90127996e Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 9 Sep 2025 12:31:20 +0100 Subject: [PATCH 041/127] Add support for sleep, dormant, and powman with tinyusb device and host Deinit and init tusb as required, and keep clocks on during sleep --- src/rp2_common/pico_low_power/low_power.c | 42 +++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index d12e02fe5..483ab0b54 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -26,6 +26,10 @@ // setup hooks #include "pico/stdlib.h" +#if LIB_TINYUSB_DEVICE || LIB_TINYUSB_HOST +#include "tusb.h" +#endif + #if HAS_RP2040_RTC #include "hardware/rtc.h" #elif HAS_POWMAN_TIMER @@ -66,10 +70,28 @@ static void post_clock_gating(void) { static uint32_t interrupt_flags; +#if LIB_TINYUSB_DEVICE +static bool tud_was_inited = false; +#endif + +#if LIB_TINYUSB_HOST +static bool tuh_was_inited = false; +#endif + static void prepare_for_clock_switch(void) { // particularly for UART we want nothing left to clock out prepare_for_clock_gating(); +#if LIB_TINYUSB_DEVICE + tud_was_inited = tud_inited(); + if (tud_was_inited) tud_deinit(0); +#endif + +#if LIB_TINYUSB_HOST + tuh_was_inited = tuh_inited(); + if (tuh_was_inited) tuh_deinit(0); +#endif + #if LIB_PICO_STDIO_USB // deinit USB stdio_usb_deinit(); @@ -83,6 +105,14 @@ static void post_clock_switch(void) { // restore interrupts restore_interrupts_from_disabled(interrupt_flags); +#if LIB_TINYUSB_DEVICE + if (tud_was_inited) tud_init(0); +#endif + +#if LIB_TINYUSB_HOST + if (tuh_was_inited) tuh_init(0); +#endif + #if LIB_PICO_STDIO_USB // reinit USB stdio_usb_init(); @@ -143,8 +173,8 @@ static void replace_null_enable_values(const clock_dest_set_t *keep_enabled, } } -static void add_stdio_clocks(clock_dest_set_t *local_keep_enabled) { -#if LIB_PICO_STDIO_USB +static void add_library_clocks(clock_dest_set_t *local_keep_enabled) { +#if LIB_PICO_STDIO_USB || LIB_TINYUSB_HOST || LIB_TINYUSB_DEVICE // this is necessary to prevent dropping the connection #if PICO_RP2040 clock_dest_set_add(local_keep_enabled, CLK_DEST_SYS_USBCTRL); @@ -186,7 +216,7 @@ int low_power_sleep_until_irq(const clock_dest_set_t *keep_enabled) { clock_dest_set_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); - add_stdio_clocks(&local_keep_enabled); + add_library_clocks(&local_keep_enabled); prepare_for_clock_gating(); // gate clocks @@ -230,7 +260,7 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, #error Unknown processor #endif - add_stdio_clocks(&local_keep_enabled); + add_library_clocks(&local_keep_enabled); #if NUM_GENERIC_TIMERS == 1 #define TIMER_BASE_IRQ TIMER_IRQ_0 @@ -267,7 +297,7 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, clock_dest_set_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); - add_stdio_clocks(&local_keep_enabled); + add_library_clocks(&local_keep_enabled); bool low = !high; bool level = !edge; @@ -562,7 +592,7 @@ pstate_bitset_t *low_power_persistent_pstate_get(pstate_bitset_t *pstate) { extern unsigned char __persistent_data_start__[]; extern unsigned char __persistent_data_end__[]; - if (__persistent_data_start__ == __persistent_data_end__) { + if ((uint32_t)__persistent_data_start__ == (uint32_t)__persistent_data_end__) { // No persistent data, so power down everything return pstate; } From 10aa67495d46e5c8264bc2d524b215bdb8454418 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 10 Sep 2025 16:33:03 +0100 Subject: [PATCH 042/127] Use better runtime_init_rp2350_sleep_fix Use dummy IRQ, rather than a timer --- src/rp2_common/pico_low_power/low_power.c | 42 +++++++++++++++---- .../include/pico/runtime_init.h | 2 +- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 483ab0b54..e6ef02d77 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -725,18 +725,42 @@ PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_low_power_cache_unpin, PICO_RUNTIME_ #if !PICO_RUNTIME_NO_INIT_RP2350_SLEEP_FIX #include "hardware/sync.h" -void __weak runtime_init_rp2350_sleep_fix(void) { +void __weak __not_in_flash_func(runtime_init_rp2350_sleep_fix)(void) { if (watchdog_hw->reason && WATCHDOG_REASON_TIMER_BITS) { // detect rom_reboot() usage - int alarm_num = timer_hardware_alarm_claim_unused(timer_hw, false); - if (alarm_num < 0) return; - - timer_hardware_alarm_set_callback(timer_hw, alarm_num, ((hardware_alarm_callback_t )low_power_wakeup)); - timer_hardware_alarm_set_target(timer_hw, alarm_num, make_timeout_time_us(100)); + uint32_t flags = save_and_disable_interrupts(); + uint32_t num_irq_words = (NUM_IRQS + 31u) / 32u; + + // Clear (and save) NVIC mask so only the dummy can fire + uint32_t saved_irq_mask[num_irq_words]; + for (int i = 0; i < num_irq_words; ++i) { + saved_irq_mask[i] = nvic_hw->icer[i]; + nvic_hw->icer[i] = -1u; + } - __wfi(); + // Un-pend then enable the dummy + const uint32_t dummy_irq_idx = FIRST_USER_IRQ / 32u; + const uint32_t dummy_irq_bit = FIRST_USER_IRQ % 32u; + nvic_hw->icpr[dummy_irq_idx] = 1u << dummy_irq_bit; + nvic_hw->iser[dummy_irq_idx] = 1u << dummy_irq_bit; + + // Sleep and immediately dummy-IRQ back out of sleep (these events happen + // in reverse order on M33; Armv8-M doesn't specify the ordering) + pico_default_asm_volatile ( + ".p2align 2\n" // Make sure both 16-bit instructions are fetched + "str %0, [%1]\n" + "wfi\n" + : + : "l" (1u << dummy_irq_bit), + "l" (&nvic_hw->ispr[dummy_irq_idx]) + ); + + // Restore NVIC mask + nvic_hw->icer[dummy_irq_idx] = 1u << dummy_irq_bit; + for (int i = 0; i < num_irq_words; ++i) { + nvic_hw->iser[i] = saved_irq_mask[i]; + } - timer_hardware_alarm_set_callback(timer_hw, alarm_num, NULL); - timer_hardware_alarm_unclaim(timer_hw, alarm_num); + restore_interrupts(flags); } } #endif diff --git a/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h b/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h index a33585134..bcf10dce5 100644 --- a/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h +++ b/src/rp2_common/pico_runtime_init/include/pico/runtime_init.h @@ -421,7 +421,7 @@ void runtime_init_bootrom_locking_enable(void); // ------------------------------------------------------------ #ifndef PICO_RUNTIME_INIT_RP2350_SLEEP_FIX -#define PICO_RUNTIME_INIT_RP2350_SLEEP_FIX "11010" +#define PICO_RUNTIME_INIT_RP2350_SLEEP_FIX "00070" #endif #ifndef PICO_RUNTIME_SKIP_INIT_RP2350_SLEEP_FIX From 1806da69a7ddcdec4c5fbd99f585614265d14ebe Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 12 Sep 2025 11:52:49 +0100 Subject: [PATCH 043/127] Fix powman doc https://forums.raspberrypi.com/viewtopic.php?t=391783 --- src/rp2_common/hardware_powman/include/hardware/powman.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rp2_common/hardware_powman/include/hardware/powman.h b/src/rp2_common/hardware_powman/include/hardware/powman.h index 659ec6c2e..b3c530cb9 100644 --- a/src/rp2_common/hardware_powman/include/hardware/powman.h +++ b/src/rp2_common/hardware_powman/include/hardware/powman.h @@ -224,8 +224,8 @@ powman_power_state powman_get_power_state(void); * * Check the desired state is valid. Powman will go to the state if it is valid and there are no pending power up requests. * - * Note that if you are turning off the switched core then this function will never return as the processor will have - * been turned off at the end. + * Note that if you are turning off the switched core then you need to call __wfi() after this function returns, otherwise + * the transition will not take place. * * \param state the power state to go to * \returns PICO_OK if the state is valid. Misc PICO_ERRORs are returned if not From 9cc19ed76baea5ca1ee400981b2b390786ef5b60 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 15 Sep 2025 14:07:13 +0100 Subject: [PATCH 044/127] Add bazel build, and some CMake function docs --- src/common/pico_util/BUILD.bazel | 1 + src/rp2_common/hardware_rosc/BUILD.bazel | 19 ++++++++++ src/rp2_common/hardware_rosc/CMakeLists.txt | 3 +- src/rp2_common/pico_low_power/BUILD.bazel | 22 +++++++++++ src/rp2_common/pico_low_power/CMakeLists.txt | 11 ++++++ .../pico_standard_link/CMakeLists.txt | 6 +++ test/hello_sleep/BUILD.bazel | 38 +++++++++++++++++++ tools/CMakeLists.txt | 2 +- 8 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 src/rp2_common/hardware_rosc/BUILD.bazel create mode 100644 src/rp2_common/pico_low_power/BUILD.bazel create mode 100644 test/hello_sleep/BUILD.bazel diff --git a/src/common/pico_util/BUILD.bazel b/src/common/pico_util/BUILD.bazel index d1e73c0cb..a7a70c4aa 100644 --- a/src/common/pico_util/BUILD.bazel +++ b/src/common/pico_util/BUILD.bazel @@ -11,6 +11,7 @@ cc_library( "queue.c", ], hdrs = [ + "include/pico/util/bitset.h", "include/pico/util/datetime.h", "include/pico/util/pheap.h", "include/pico/util/queue.h", diff --git a/src/rp2_common/hardware_rosc/BUILD.bazel b/src/rp2_common/hardware_rosc/BUILD.bazel new file mode 100644 index 000000000..2da676ae6 --- /dev/null +++ b/src/rp2_common/hardware_rosc/BUILD.bazel @@ -0,0 +1,19 @@ +load("//bazel:defs.bzl", "compatible_with_rp2") + +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "hardware_rosc", + srcs = ["rosc.c"], + hdrs = ["include/hardware/rosc.h"], + includes = ["include"], + target_compatible_with = compatible_with_rp2(), + deps = [ + "//src/common/pico_base_headers", + "//src/rp2_common:hardware_regs", + "//src/rp2_common:hardware_structs", + "//src/rp2_common:pico_platform_internal", + "//src/rp2_common:platform_defs", + "//src/rp2_common/hardware_clocks:hardware_clocks_headers", + ], +) diff --git a/src/rp2_common/hardware_rosc/CMakeLists.txt b/src/rp2_common/hardware_rosc/CMakeLists.txt index 3ee667e29..83a6c3732 100644 --- a/src/rp2_common/hardware_rosc/CMakeLists.txt +++ b/src/rp2_common/hardware_rosc/CMakeLists.txt @@ -1 +1,2 @@ -pico_simple_hardware_target(rosc) \ No newline at end of file +pico_simple_hardware_target(rosc) +pico_mirrored_target_link_libraries(hardware_rosc INTERFACE hardware_clocks) diff --git a/src/rp2_common/pico_low_power/BUILD.bazel b/src/rp2_common/pico_low_power/BUILD.bazel new file mode 100644 index 000000000..275fd75df --- /dev/null +++ b/src/rp2_common/pico_low_power/BUILD.bazel @@ -0,0 +1,22 @@ +load("//bazel:defs.bzl", "compatible_with_rp2") + +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "pico_low_power", + srcs = ["low_power.c"], + hdrs = ["include/pico/low_power.h"], + includes = ["include"], + target_compatible_with = compatible_with_rp2(), + deps = [ + "//src/common/pico_time", + "//src/rp2_common:hardware_structs", + "//src/rp2_common:pico_platform", + "//src/rp2_common/hardware_clocks", + "//src/rp2_common/hardware_rosc", + "//src/rp2_common/hardware_xosc", + "//src/rp2_common/hardware_irq", + "//src/rp2_common/hardware_timer", + "//src/rp2_common/pico_aon_timer", + ], +) diff --git a/src/rp2_common/pico_low_power/CMakeLists.txt b/src/rp2_common/pico_low_power/CMakeLists.txt index 848a0413e..cee328a56 100644 --- a/src/rp2_common/pico_low_power/CMakeLists.txt +++ b/src/rp2_common/pico_low_power/CMakeLists.txt @@ -17,6 +17,17 @@ pico_mirrored_target_link_libraries(pico_low_power INTERFACE pico_aon_timer ) +# pico_set_persistent_data_loc(TARGET PERSISTENT_DATA_LOC) +# \brief\ Set the persistent data location for the target +# +# This sets the target property PICO_TARGET_PERSISTENT_DATA_LOC to the given value, +# and also sets the target property PICO_TARGET_HEAP_LOC and PICO_TARGET_HEAP_LIMIT +# to the appropriate values based on the persistent data location. +# +# It also sets PICO_CRT0_PIN_XIP_SRAM=1 to pin the XIP_SRAM, +# if the persistent data is stored in XIP_SRAM on RP2350. +# +# \param\ PERSISTENT_DATA_LOC The persistent data location to set function(pico_set_persistent_data_loc TARGET PERSISTENT_DATA_LOC) if (NOT PICO_RP2350) message(FATAL_ERROR "pico_set_persistent_data_loc is only supported on RP2350") diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index 53cad5538..6b37c6ef5 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -61,6 +61,12 @@ if (NOT TARGET pico_standard_link) endif() endfunction() + # pico_add_linker_constants(TARGET) + # \brief\ Add custom linker script constants to the target + # + # This reads target properties PICO_TARGET_PERSISTENT_DATA_LOC, PICO_TARGET_HEAP_LOC, + # and PICO_TARGET_HEAP_LIMIT and writes them to a linker script constant file, which + # is included by the linker script function(pico_add_linker_constants TARGET) set(pico_ld_constants_dir ${CMAKE_BINARY_DIR}/pico_ld_constants/${TARGET}) diff --git a/test/hello_sleep/BUILD.bazel b/test/hello_sleep/BUILD.bazel new file mode 100644 index 000000000..a26073420 --- /dev/null +++ b/test/hello_sleep/BUILD.bazel @@ -0,0 +1,38 @@ +load("//bazel:defs.bzl", "compatible_with_rp2") + +package(default_visibility = ["//visibility:public"]) + +cc_binary( + name = "hello_sleep", + testonly = True, + srcs = ["hello_sleep.c"], + target_compatible_with = compatible_with_rp2(), + deps = [ + "//src/rp2_common/pico_stdlib", + "//src/rp2_common/pico_low_power", + "//src/rp2_common/pico_status_led", + ], +) + +cc_binary( + name = "hello_sleep_gpio", + testonly = True, + srcs = ["hello_sleep_gpio.c"], + target_compatible_with = compatible_with_rp2(), + deps = [ + "//src/rp2_common/pico_stdlib", + "//src/rp2_common/pico_low_power", + "//src/rp2_common/pico_status_led", + ], +) + +cc_binary( + name = "rtc_clksrc", + testonly = True, + srcs = ["rtc_clksrc.c"], + target_compatible_with = compatible_with_rp2(), + deps = [ + "//src/rp2_common/pico_stdlib", + "//src/rp2_common/pico_status_led", + ], +) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 60eb5dd3b..6849c1778 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -486,7 +486,7 @@ function(pico_embed_pt_in_binary TARGET PTFILE) ) endfunction() -# pico_encrypt_binary(TARGET AESFILE IVFILE [SIGFILE ] [EMBED] [MBEDTLS] [OTP_KEY_PAGE ]) +# pico_encrypt_binary(TARGET AESFILE IVFILE [SIGFILE ] [EMBED] [MBEDTLS] [OTP_KEY_PAGE ] [NO_CLEAR]) # \brief_nodesc\ Encrypt the taget binary # # Encrypt the target binary with the given AES key (should be a binary From c65b5960fae9e07e2b9b599736001b90df62ee2a Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 15 Sep 2025 14:09:04 +0100 Subject: [PATCH 045/127] Fix config check --- tools/extract_cmake_functions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/extract_cmake_functions.py b/tools/extract_cmake_functions.py index 48020768e..27ca51a6b 100755 --- a/tools/extract_cmake_functions.py +++ b/tools/extract_cmake_functions.py @@ -73,6 +73,7 @@ def __init__(self, message, errors): 'pico_standard_link': ('Pico Standard Link', 'CMake functions to configure the linker'), 'pico_stdio': ('Pico Standard I/O', 'CMake functions to configure the standard I/O library'), 'pico_pio': ('Pico PIO', 'CMake functions to generate PIO headers'), + 'pico_low_power': ('Pico Low Power', 'CMake functions to configure the low power library'), 'other': ('Other', 'Other CMake functions'), } From 7293cebb13d11fcf86b1a1182be66a47eb2a5461 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 15 Sep 2025 14:12:52 +0100 Subject: [PATCH 046/127] Fix hardware_rosc bazel build --- src/common/pico_base_headers/BUILD.bazel | 1 + src/rp2_common/BUILD.bazel | 1 + src/rp2_common/hardware_clocks/BUILD.bazel | 2 ++ tools/bazel_build.py | 3 +++ 4 files changed, 7 insertions(+) diff --git a/src/common/pico_base_headers/BUILD.bazel b/src/common/pico_base_headers/BUILD.bazel index d7058ee85..931e5a580 100644 --- a/src/common/pico_base_headers/BUILD.bazel +++ b/src/common/pico_base_headers/BUILD.bazel @@ -113,6 +113,7 @@ cc_library( "//src/rp2_common/hardware_ticks:__pkg__", "//src/rp2_common/hardware_timer:__pkg__", "//src/rp2_common/hardware_watchdog:__pkg__", + "//src/rp2_common/hardware_rosc:__pkg__", "//src/rp2_common/hardware_xosc:__pkg__", "//src/rp2_common/pico_crt0:__pkg__", "//src/rp2_common/pico_platform_common:__pkg__", diff --git a/src/rp2_common/BUILD.bazel b/src/rp2_common/BUILD.bazel index fe1c0c3e3..d5ccf6555 100644 --- a/src/rp2_common/BUILD.bazel +++ b/src/rp2_common/BUILD.bazel @@ -73,6 +73,7 @@ alias( "//src/rp2_common/hardware_pll:__pkg__", "//src/rp2_common/hardware_vreg:__pkg__", "//src/rp2_common/hardware_watchdog:__pkg__", + "//src/rp2_common/hardware_rosc:__pkg__", "//src/rp2_common/hardware_xosc:__pkg__", "//src/rp2_common/pico_bit_ops:__pkg__", "//src/rp2_common/pico_bootrom:__pkg__", diff --git a/src/rp2_common/hardware_clocks/BUILD.bazel b/src/rp2_common/hardware_clocks/BUILD.bazel index 29c1bb104..e00d05229 100644 --- a/src/rp2_common/hardware_clocks/BUILD.bazel +++ b/src/rp2_common/hardware_clocks/BUILD.bazel @@ -13,10 +13,12 @@ cc_library( target_compatible_with = compatible_with_rp2(), visibility = [ "//src/rp2_common/hardware_pll:__pkg__", + "//src/rp2_common/hardware_rosc:__pkg__", "//src/rp2_common/hardware_xosc:__pkg__", ], deps = [ "//src/common/pico_base_headers", + "//src/common/pico_util", "//src/rp2_common:hardware_structs", "//src/rp2_common/hardware_base", ], diff --git a/tools/bazel_build.py b/tools/bazel_build.py index 522f28310..471a935a7 100755 --- a/tools/bazel_build.py +++ b/tools/bazel_build.py @@ -47,6 +47,9 @@ "//test/pico_sha256_test:pico_sha256_test", "//test/pico_stdio_test:pico_stdio_test", "//test/pico_time_test:pico_time_test", + "//test/hello_sleep:hello_sleep", + "//test/hello_sleep:hello_sleep_gpio", + "//test/hello_sleep:rtc_clksrc", # Pretty much only Picotool and pioasm build on Windows. "//..." if os.name == "nt" else "", From 575617e5571a083262b61ab54498632d8d8ce273 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 15 Sep 2025 14:56:25 +0100 Subject: [PATCH 047/127] Fix some kitchen sink errors --- src/rp2_common/pico_low_power/low_power.c | 10 ++++------ test/kitchen_sink/kitchen_sink.c | 7 ++++++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index e6ef02d77..09d41702f 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -576,6 +576,9 @@ void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, } #if HAS_POWMAN_TIMER +extern unsigned char __persistent_data_start__[]; +extern unsigned char __persistent_data_end__[]; + int low_power_pstate_set(pstate_bitset_t *pstate) { invalid_params_if(PICO_LOW_POWER, !pstate_bitset_is_set(pstate, POWMAN_POWER_DOMAIN_SWITCHED_CORE)); @@ -589,8 +592,6 @@ pstate_bitset_t *low_power_pstate_get(pstate_bitset_t *pstate) { pstate_bitset_t *low_power_persistent_pstate_get(pstate_bitset_t *pstate) { pstate_bitset_clear(pstate); - extern unsigned char __persistent_data_start__[]; - extern unsigned char __persistent_data_end__[]; if ((uint32_t)__persistent_data_start__ == (uint32_t)__persistent_data_end__) { // No persistent data, so power down everything @@ -694,9 +695,6 @@ PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_low_power_reboot_check, PICO_RUNTIME #if !PICO_RUNTIME_NO_INIT_LOW_POWER_CACHE_UNPIN void __weak __no_inline_not_in_flash_func(runtime_init_low_power_cache_unpin)(void) { - extern unsigned char __persistent_data_start__[]; - extern unsigned char __persistent_data_end__[]; - // if persistent data is in xip_sram, then the whole cache is currently pinned // for performance, we should unpin the rest of it if ((uint32_t)__persistent_data_start__ < SRAM_BASE) { @@ -728,7 +726,7 @@ PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_low_power_cache_unpin, PICO_RUNTIME_ void __weak __not_in_flash_func(runtime_init_rp2350_sleep_fix)(void) { if (watchdog_hw->reason && WATCHDOG_REASON_TIMER_BITS) { // detect rom_reboot() usage uint32_t flags = save_and_disable_interrupts(); - uint32_t num_irq_words = (NUM_IRQS + 31u) / 32u; + int32_t num_irq_words = (NUM_IRQS + 31u) / 32u; // Clear (and save) NVIC mask so only the dummy can fire uint32_t saved_irq_mask[num_irq_words]; diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index 7c4202e90..01d95bf11 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -11,6 +11,7 @@ #include "hardware/dma.h" #include "pico/sync.h" #include "pico/stdlib.h" +#include "pico/util/bitset.h" #if LIB_PICO_BINARY_INFO #include "pico/binary_info.h" #endif @@ -95,6 +96,7 @@ int main(void) { if (bitset_get_bit(&fooper.bitset, i)) printf("Have at %d\n", i); } printf("%f\n", foox(1.3f, 2.6f)); +#if LIB_PICO_AON_TIMER aon_timer_start_with_timeofday(); void spoop(void); struct timespec ts; @@ -106,6 +108,7 @@ int main(void) { printf("%ld %ld\n", (long)ts.tv_sec, ts.tv_nsec); busy_wait_ms(4000); } +#endif #ifndef __riscv // this should compile as we are Cortex M0+ @@ -113,6 +116,8 @@ int main(void) { #endif } +#if LIB_PICO_AON_TIMER void spoop(void) { printf("XXXX YARGLE XXXX\n"); -} \ No newline at end of file +} +#endif From 7ce8c6ade717411192f2b62c1f91bad72439f488 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 15 Sep 2025 15:11:14 +0100 Subject: [PATCH 048/127] fixups --- src/rp2_common/pico_crt0/rp2040/BUILD.bazel | 4 +++ src/rp2_common/pico_crt0/rp2350/BUILD.bazel | 3 +++ src/rp2_common/pico_low_power/BUILD.bazel | 3 +++ src/rp2_common/pico_low_power/CMakeLists.txt | 2 ++ src/rp2_common/pico_low_power/low_power.c | 10 +++---- src/rp2_common/pico_standard_link/BUILD.bazel | 5 ++++ .../pico_standard_link/pico_ld_constants.bzl | 27 +++++++++++++++++++ test/kitchen_sink/kitchen_sink.c | 3 +++ tools/bazel_build.py | 10 ++++++- 9 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 src/rp2_common/pico_standard_link/pico_ld_constants.bzl diff --git a/src/rp2_common/pico_crt0/rp2040/BUILD.bazel b/src/rp2_common/pico_crt0/rp2040/BUILD.bazel index 44912f0c8..e6bf14d32 100644 --- a/src/rp2_common/pico_crt0/rp2040/BUILD.bazel +++ b/src/rp2_common/pico_crt0/rp2040/BUILD.bazel @@ -28,6 +28,7 @@ cc_library( "memmap_default.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", "//src/rp2_common/pico_standard_link:default_flash_region", + "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) @@ -41,6 +42,7 @@ cc_library( "memmap_blocked_ram.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", "//src/rp2_common/pico_standard_link:default_flash_region", + "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) @@ -54,6 +56,7 @@ cc_library( "memmap_copy_to_ram.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", "//src/rp2_common/pico_standard_link:default_flash_region", + "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) @@ -66,5 +69,6 @@ cc_library( deps = [ "memmap_no_flash.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) diff --git a/src/rp2_common/pico_crt0/rp2350/BUILD.bazel b/src/rp2_common/pico_crt0/rp2350/BUILD.bazel index b0f1ca7dd..54fff295e 100644 --- a/src/rp2_common/pico_crt0/rp2350/BUILD.bazel +++ b/src/rp2_common/pico_crt0/rp2350/BUILD.bazel @@ -27,6 +27,7 @@ cc_library( "memmap_default.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", "//src/rp2_common/pico_standard_link:default_flash_region", + "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) @@ -40,6 +41,7 @@ cc_library( "memmap_copy_to_ram.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", "//src/rp2_common/pico_standard_link:default_flash_region", + "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) @@ -52,5 +54,6 @@ cc_library( deps = [ "memmap_no_flash.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) diff --git a/src/rp2_common/pico_low_power/BUILD.bazel b/src/rp2_common/pico_low_power/BUILD.bazel index 275fd75df..e2456a668 100644 --- a/src/rp2_common/pico_low_power/BUILD.bazel +++ b/src/rp2_common/pico_low_power/BUILD.bazel @@ -10,6 +10,7 @@ cc_library( target_compatible_with = compatible_with_rp2(), deps = [ "//src/common/pico_time", + "//src/common/pico_util", "//src/rp2_common:hardware_structs", "//src/rp2_common:pico_platform", "//src/rp2_common/hardware_clocks", @@ -17,6 +18,8 @@ cc_library( "//src/rp2_common/hardware_xosc", "//src/rp2_common/hardware_irq", "//src/rp2_common/hardware_timer", + "//src/rp2_common/hardware_uart", "//src/rp2_common/pico_aon_timer", + "//src/rp2_common/pico_stdio", ], ) diff --git a/src/rp2_common/pico_low_power/CMakeLists.txt b/src/rp2_common/pico_low_power/CMakeLists.txt index cee328a56..d07cf6c2e 100644 --- a/src/rp2_common/pico_low_power/CMakeLists.txt +++ b/src/rp2_common/pico_low_power/CMakeLists.txt @@ -15,6 +15,8 @@ pico_mirrored_target_link_libraries(pico_low_power INTERFACE hardware_irq hardware_timer pico_aon_timer + hardware_uart + pico_stdio ) # pico_set_persistent_data_loc(TARGET PERSISTENT_DATA_LOC) diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 09d41702f..6156f06ec 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -9,6 +9,11 @@ #include "pico/low_power.h" #include "pico/aon_timer.h" #include "pico/runtime_init.h" +#include "pico/time.h" +#include "pico/stdio.h" +#if LIB_PICO_STDIO_USB +#include "pico/stdio_usb.h" +#endif #include "hardware/pll.h" #include "hardware/claim.h" @@ -21,11 +26,6 @@ #include "hardware/watchdog.h" #include "hardware/xosc.h" -// todo this is a hack for now as we use setup_default_uart(); this is deliberately not in -// the library dependencies right now, as this should get fixed up by better "pre/post" clock -// setup hooks -#include "pico/stdlib.h" - #if LIB_TINYUSB_DEVICE || LIB_TINYUSB_HOST #include "tusb.h" #endif diff --git a/src/rp2_common/pico_standard_link/BUILD.bazel b/src/rp2_common/pico_standard_link/BUILD.bazel index 4c8ff249a..8b9697c29 100644 --- a/src/rp2_common/pico_standard_link/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/BUILD.bazel @@ -1,6 +1,7 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library") load("//bazel:defs.bzl", "compatible_with_rp2") load("pico_flash_region.bzl", "generated_pico_flash_region") +load("pico_ld_constants.bzl", "generated_pico_ld_constants") package(default_visibility = ["//visibility:public"]) @@ -18,6 +19,10 @@ generated_pico_flash_region( }), ) +generated_pico_ld_constants( + name = "default_ld_constants", +) + cc_library( name = "pico_standard_link", target_compatible_with = compatible_with_rp2(), diff --git a/src/rp2_common/pico_standard_link/pico_ld_constants.bzl b/src/rp2_common/pico_standard_link/pico_ld_constants.bzl new file mode 100644 index 000000000..fc2a57c17 --- /dev/null +++ b/src/rp2_common/pico_standard_link/pico_ld_constants.bzl @@ -0,0 +1,27 @@ +load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "use_cpp_toolchain") + +def _generated_pico_ld_constants_impl(ctx): + ld_constants_linker_fragment = ctx.actions.declare_file(ctx.label.name + "/ldinclude/pico_ld_constants.ld") + link_include_dir = ld_constants_linker_fragment.dirname + + file_contents = "\n" + ctx.actions.write(ld_constants_linker_fragment, file_contents) + linking_inputs = cc_common.create_linker_input( + owner = ctx.label, + user_link_flags = depset( + direct = ["-L" + str(link_include_dir)], + ), + additional_inputs = depset( + direct = [ld_constants_linker_fragment], + ), + ) + return [ + DefaultInfo(files = depset([ld_constants_linker_fragment])), + CcInfo(linking_context = cc_common.create_linking_context(linker_inputs = depset(direct = [linking_inputs]))), + ] + +generated_pico_ld_constants = rule( + implementation = _generated_pico_ld_constants_impl, + toolchains = use_cpp_toolchain(), + fragments = ["cpp"], +) diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index 01d95bf11..0ba4b6850 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -15,6 +15,9 @@ #if LIB_PICO_BINARY_INFO #include "pico/binary_info.h" #endif +#if LIB_PICO_AON_TIMER +#include "pico/aon_timer.h" +#endif #else #include KITCHEN_SINK_INCLUDE_HEADER #endif diff --git a/tools/bazel_build.py b/tools/bazel_build.py index 471a935a7..2bc629ffe 100755 --- a/tools/bazel_build.py +++ b/tools/bazel_build.py @@ -87,6 +87,8 @@ "//test/kitchen_sink:kitchen_sink_lwip_background", # Host only. "//test/pico_float_test:hazard3_test_gen", + # RP2040 only. + "//test/hello_sleep:rtc_clksrc", # TODO: RISC-V support. "//test/pico_float_test:pico_float_test_hazard3", ) @@ -125,6 +127,8 @@ "//test/kitchen_sink:kitchen_sink_lwip_background", # Host only. "//test/pico_float_test:hazard3_test_gen", + # RP2040 only. + "//test/hello_sleep:rtc_clksrc", # TODO: RISC-V support. "//test/pico_float_test:pico_float_test_hazard3", ) @@ -159,7 +163,9 @@ ( # Host only. "//test/pico_float_test:hazard3_test_gen", - # No RISC-V on RP2040. + # RP2040 only. + "//test/hello_sleep:rtc_clksrc", + # TODO: RISC-V support. "//test/pico_float_test:pico_float_test_hazard3", ) ), @@ -201,6 +207,8 @@ def build_all_configurations(picotool_dir): build_targets = [ t for t in default_build_targets if t not in config["exclusions"] ] + print("Build targets: ", build_targets) + print("Exclusions: ", config["exclusions"]) build_targets.extend(config["extra_targets"]) args = list(config["args"]) From 6509d947470581c135a849851267ad567b4c7c02 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 1 Dec 2025 19:32:27 +0000 Subject: [PATCH 049/127] Separate linker scripts out into include files Allows for much simpler custom linker scripts --- .../pico_crt0/rp2040/memmap_blocked_ram.ld | 287 +--------------- .../pico_crt0/rp2040/memmap_copy_to_ram.ld | 288 +--------------- .../pico_crt0/rp2040/memmap_default.ld | 287 +--------------- .../pico_crt0/rp2040/memmap_no_flash.ld | 249 +------------- .../pico_crt0/rp2040/memory_blocked_ram.ld | 4 + .../pico_crt0/rp2040/memory_flash.ld | 4 + src/rp2_common/pico_crt0/rp2040/memory_ram.ld | 4 + .../pico_crt0/rp2040/memory_scratch.ld | 5 + .../pico_crt0/rp2040/sections_copy_to_ram.ld | 276 +++++++++++++++ .../pico_crt0/rp2040/sections_default.ld | 275 +++++++++++++++ .../pico_crt0/rp2040/sections_no_flash.ld | 239 +++++++++++++ .../pico_crt0/rp2350/memmap_copy_to_ram.ld | 319 +----------------- .../pico_crt0/rp2350/memmap_default.ld | 312 +---------------- .../pico_crt0/rp2350/memmap_no_flash.ld | 265 +-------------- .../pico_crt0/rp2350/memory_copy_to_ram.ld | 0 .../pico_crt0/rp2350/memory_flash.ld | 4 + src/rp2_common/pico_crt0/rp2350/memory_ram.ld | 4 + .../pico_crt0/rp2350/memory_scratch.ld | 5 + .../pico_crt0/rp2350/memory_xip_ram.ld | 4 + .../pico_crt0/rp2350/sections_copy_to_ram.ld | 305 +++++++++++++++++ .../pico_crt0/rp2350/sections_default.ld | 298 ++++++++++++++++ .../pico_crt0/rp2350/sections_no_flash.ld | 253 ++++++++++++++ .../pico_standard_link/CMakeLists.txt | 11 +- 23 files changed, 1709 insertions(+), 1989 deletions(-) create mode 100644 src/rp2_common/pico_crt0/rp2040/memory_blocked_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/memory_flash.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/memory_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/memory_scratch.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/sections_default.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/memory_copy_to_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/memory_flash.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/memory_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/memory_scratch.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/memory_xip_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/sections_default.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld index 6f5000566..150176eba 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld @@ -1,286 +1,7 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -MEMORY -{ - INCLUDE "pico_flash_region.ld" - RAM(rwx) : ORIGIN = 0x21000000, LENGTH = 256k - SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k -} +INCLUDE "memory_flash.ld" +INCLUDE "memory_blocked_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .text : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - /* TODO revisit this now memset/memcpy/float in ROM */ - /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from - * FLASH ... we will include any thing excluded here in .data below by default */ - *(.init) - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.eh_frame*) - . = ALIGN(4); - } > FLASH - - .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ - *(.text*) - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} - +INCLUDE "sections_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld index 842ebfd3c..7b99a7745 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld @@ -1,287 +1,7 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -MEMORY -{ - INCLUDE "pico_flash_region.ld" - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k - SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k -} +INCLUDE "memory_flash.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .flashtext : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - } - - .rodata : { - /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - /* Vector table goes first in RAM, to avoid large alignment hole */ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .text : { - __ram_text_start__ = .; - *(.init) - *(.text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - . = ALIGN(4); - __ram_text_end__ = .; - } > RAM AT> FLASH - __ram_text_source__ = LOADADDR(.text); - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} - +INCLUDE "sections_copy_to_ram.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_default.ld b/src/rp2_common/pico_crt0/rp2040/memmap_default.ld index 51254012d..75fd340d5 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_default.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_default.ld @@ -1,286 +1,7 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -MEMORY -{ - INCLUDE "pico_flash_region.ld" - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k - SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k -} +INCLUDE "memory_flash.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .text : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - /* TODO revisit this now memset/memcpy/float in ROM */ - /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from - * FLASH ... we will include any thing excluded here in .data below by default */ - *(.init) - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.eh_frame*) - . = ALIGN(4); - } > FLASH - - .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ - *(.text*) - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} - +INCLUDE "sections_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld b/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld index dbf006a8c..cde630592 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld @@ -1,249 +1,6 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -MEMORY -{ - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k - SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k -} +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - /* Note in NO_FLASH builds the entry point for both the bootrom, and debugger - entry (ELF entry point), are *first* in the image, and the vector table - follows immediately afterward. This is because the bootrom enters RAM - binaries directly at their lowest address (preferring main RAM over XIP - cache-as-SRAM if both are used). - */ - - .text : { - __logical_binary_start = .; - __reset_start = .; - KEEP (*(.reset)) - __reset_end = .; - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - . = ALIGN(256); - KEEP (*(.vectors)) - *(.time_critical*) - *(.text*) - . = ALIGN(4); - *(.init) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - } > RAM - - .rodata : { - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > RAM - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > RAM - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > RAM - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > RAM - __binary_info_end = .; - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM - PROVIDE(__data_end__ = .); - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} - +INCLUDE "sections_no_flash.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memory_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/memory_blocked_ram.ld new file mode 100644 index 000000000..57cbad6b7 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/memory_blocked_ram.ld @@ -0,0 +1,4 @@ +MEMORY +{ + RAM(rwx) : ORIGIN = 0x21000000, LENGTH = 256k +} diff --git a/src/rp2_common/pico_crt0/rp2040/memory_flash.ld b/src/rp2_common/pico_crt0/rp2040/memory_flash.ld new file mode 100644 index 000000000..669fe00e3 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/memory_flash.ld @@ -0,0 +1,4 @@ +MEMORY +{ + INCLUDE "pico_flash_region.ld" +} diff --git a/src/rp2_common/pico_crt0/rp2040/memory_ram.ld b/src/rp2_common/pico_crt0/rp2040/memory_ram.ld new file mode 100644 index 000000000..1e1515dd3 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/memory_ram.ld @@ -0,0 +1,4 @@ +MEMORY +{ + RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k +} diff --git a/src/rp2_common/pico_crt0/rp2040/memory_scratch.ld b/src/rp2_common/pico_crt0/rp2040/memory_scratch.ld new file mode 100644 index 000000000..a4b982b92 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/memory_scratch.ld @@ -0,0 +1,5 @@ +MEMORY +{ + SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k + SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k +} diff --git a/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld new file mode 100644 index 000000000..5557ee1cb --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld @@ -0,0 +1,276 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* Second stage bootloader is prepended to the image. It must be 256 bytes big + and checksummed. It is usually built by the boot_stage2 target + in the Raspberry Pi Pico SDK + */ + + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + .boot2 : { + __boot2_start__ = .; + KEEP (*(.boot2)) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ == 256, + "ERROR: Pico second stage bootloader must be 256 bytes in size") + + /* The second stage will always enter the image at the start of .text. + The debugger will use the ELF entry point, which is the _entry_point + symbol if present, otherwise defaults to start of .text. + This can be used to transfer control back to the bootrom on debugger + launches only, to perform proper flash setup. + */ + + .flashtext : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + } + + .rodata : { + /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); + + /* Vector table goes first in RAM, to avoid large alignment hole */ + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .text : { + __ram_text_start__ = .; + *(.init) + *(.text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + . = ALIGN(4); + __ram_text_end__ = .; + } > RAM AT> FLASH + __ram_text_source__ = LOADADDR(.text); + . = ALIGN(4); + + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + + *(.data*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X AT > FLASH + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y AT > FLASH + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y + + .flash_end : { + KEEP(*(.embedded_end_block*)) + PROVIDE(__flash_binary_end = .); + } > FLASH + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2040/sections_default.ld b/src/rp2_common/pico_crt0/rp2040/sections_default.ld new file mode 100644 index 000000000..57984e46b --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/sections_default.ld @@ -0,0 +1,275 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* Second stage bootloader is prepended to the image. It must be 256 bytes big + and checksummed. It is usually built by the boot_stage2 target + in the Raspberry Pi Pico SDK + */ + + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + .boot2 : { + __boot2_start__ = .; + KEEP (*(.boot2)) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ == 256, + "ERROR: Pico second stage bootloader must be 256 bytes in size") + + /* The second stage will always enter the image at the start of .text. + The debugger will use the ELF entry point, which is the _entry_point + symbol if present, otherwise defaults to start of .text. + This can be used to transfer control back to the bootrom on debugger + launches only, to perform proper flash setup. + */ + + .text : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + /* TODO revisit this now memset/memcpy/float in ROM */ + /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from + * FLASH ... we will include any thing excluded here in .data below by default */ + *(.init) + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.eh_frame*) + . = ALIGN(4); + } > FLASH + + .rodata : { + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); + + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ + *(.text*) + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + + *(.data*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X AT > FLASH + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y AT > FLASH + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y + + .flash_end : { + KEEP(*(.embedded_end_block*)) + PROVIDE(__flash_binary_end = .); + } > FLASH + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld b/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld new file mode 100644 index 000000000..9e082d53c --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld @@ -0,0 +1,239 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* Note in NO_FLASH builds the entry point for both the bootrom, and debugger + entry (ELF entry point), are *first* in the image, and the vector table + follows immediately afterward. This is because the bootrom enters RAM + binaries directly at their lowest address (preferring main RAM over XIP + cache-as-SRAM if both are used). + */ + + .text : { + __logical_binary_start = .; + __reset_start = .; + KEEP (*(.reset)) + __reset_end = .; + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + . = ALIGN(256); + KEEP (*(.vectors)) + *(.time_critical*) + *(.text*) + . = ALIGN(4); + *(.init) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + } > RAM + + .rodata : { + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > RAM + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > RAM + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > RAM + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > RAM + __binary_info_end = .; + . = ALIGN(4); + + .data : { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM + PROVIDE(__data_end__ = .); + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld index 186225423..7b99a7745 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld @@ -1,318 +1,7 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -INCLUDE "pico_ld_constants.ld" - -MEMORY -{ - INCLUDE "pico_flash_region.ld" - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k - SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k -} +INCLUDE "memory_flash.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - /* On Arm, the bootrom expects a VT at the start of the - image by default; on RISC-V, the default is to enter the image at its - lowest address, so an IMAGE_DEF item is required to specify the - nondefault entry point. */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - /* The bootrom will enter the image at the point indicated in your - IMAGE_DEF, which is usually the reset handler of your vector table. - - The debugger will use the ELF entry point, which is the _entry_point - symbol, and in our case is *different from the bootrom's entry point.* - This is used to go back through the bootrom on debugger launches only, - to perform the same initial flash setup that would be performed on a - cold boot. - */ - - .flashtext : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - . = ALIGN(4); - } > FLASH - - /* Note the boot2 section is optional, and should be discarded if there is - no reference to it *inside* the binary, as it is not called by the - bootrom. (The bootrom performs a simple best-effort XIP setup and - leaves it to the binary to do anything more sophisticated.) However - there is still a size limit of 256 bytes, to ensure the boot2 can be - stored in boot RAM. - - Really this is a "XIP setup function" -- the name boot2 is historic and - refers to its dual-purpose on RP2040, where it also handled vectoring - from the bootrom into the user image. - */ - - .boot2 : { - __boot2_start__ = .; - *(.boot2) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ <= 256, - "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") - - .rodata : { - /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - /* Vector table goes first in RAM, to avoid large alignment hole */ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .text : { - __ram_text_start__ = .; - *(.init) - *(.text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - . = ALIGN(4); - __ram_text_end__ = .; - } > RAM AT> FLASH - __ram_text_source__ = LOADADDR(.text); - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - . = ALIGN(4); - *(.rodata*) - *(.srodata*) - . = ALIGN(4); - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { - __persistent_data_start__ = .; - *(.persistent_data*) - . = ALIGN(4); - } - PROVIDE(__persistent_data_end__ = .); - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH =0xaa - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") - ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ -} - +INCLUDE "sections_copy_to_ram.ld" diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld index f6f150ad6..75fd340d5 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld @@ -1,311 +1,7 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -INCLUDE "pico_ld_constants.ld" - -MEMORY -{ - INCLUDE "pico_flash_region.ld" - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k - SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k -} +INCLUDE "memory_flash.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - /* The bootrom will enter the image at the point indicated in your - IMAGE_DEF, which is usually the reset handler of your vector table. - - The debugger will use the ELF entry point, which is the _entry_point - symbol, and in our case is *different from the bootrom's entry point.* - This is used to go back through the bootrom on debugger launches only, - to perform the same initial flash setup that would be performed on a - cold boot. - */ - - .text : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - /* TODO revisit this now memset/memcpy/float in ROM */ - /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from - * FLASH ... we will include any thing excluded here in .data below by default */ - *(.init) - *libgcc.a:cmse_nonsecure_call.o - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.eh_frame*) - . = ALIGN(4); - } > FLASH - - /* Note the boot2 section is optional, and should be discarded if there is - no reference to it *inside* the binary, as it is not called by the - bootrom. (The bootrom performs a simple best-effort XIP setup and - leaves it to the binary to do anything more sophisticated.) However - there is still a size limit of 256 bytes, to ensure the boot2 can be - stored in boot RAM. - - Really this is a "XIP setup function" -- the name boot2 is historic and - refers to its dual-purpose on RP2040, where it also handled vectoring - from the bootrom into the user image. - */ - - .boot2 : { - __boot2_start__ = .; - *(.boot2) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ <= 256, - "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") - - .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) - *(.srodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ - *(.text*) - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { - __persistent_data_start__ = .; - *(.persistent_data*) - . = ALIGN(4); - } - PROVIDE(__persistent_data_end__ = .); - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH =0xaa - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") - ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ -} - +INCLUDE "sections_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld index 798891406..cde630592 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld @@ -1,265 +1,6 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -INCLUDE "pico_ld_constants.ld" - -MEMORY -{ - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k - SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k -} +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" ENTRY(_entry_point) -SECTIONS -{ - /* Note unlike RP2040, we start the image with a vector table even for - NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the - image by default; on RISC-V, the default is to enter the image at its - lowest address, so an IMAGE_DEF item is required to specify the - nondefault entry point. */ - - .text : { - __logical_binary_start = .; - /* Vectors require 512-byte alignment on v8-M when >48 IRQs are used, - so we would waste RAM if the vector table were not at the - start. */ - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - __reset_start = .; - KEEP (*(.reset)) - __reset_end = .; - *(.time_critical*) - *(.text*) - . = ALIGN(4); - *(.init) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - } > RAM - - .rodata : { - . = ALIGN(4); - *(.rodata*) - *(.srodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > RAM - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > RAM - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > RAM - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > RAM - __binary_info_end = .; - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM - PROVIDE(__data_end__ = .); - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { - __persistent_data_start__ = .; - *(.persistent_data*) - . = ALIGN(4); - } - PROVIDE(__persistent_data_end__ = .); - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") - ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ -} - +INCLUDE "sections_no_flash.ld" diff --git a/src/rp2_common/pico_crt0/rp2350/memory_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/memory_copy_to_ram.ld new file mode 100644 index 000000000..e69de29bb diff --git a/src/rp2_common/pico_crt0/rp2350/memory_flash.ld b/src/rp2_common/pico_crt0/rp2350/memory_flash.ld new file mode 100644 index 000000000..669fe00e3 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/memory_flash.ld @@ -0,0 +1,4 @@ +MEMORY +{ + INCLUDE "pico_flash_region.ld" +} diff --git a/src/rp2_common/pico_crt0/rp2350/memory_ram.ld b/src/rp2_common/pico_crt0/rp2350/memory_ram.ld new file mode 100644 index 000000000..434cdab97 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/memory_ram.ld @@ -0,0 +1,4 @@ +MEMORY +{ + RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k +} diff --git a/src/rp2_common/pico_crt0/rp2350/memory_scratch.ld b/src/rp2_common/pico_crt0/rp2350/memory_scratch.ld new file mode 100644 index 000000000..246bbf050 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/memory_scratch.ld @@ -0,0 +1,5 @@ +MEMORY +{ + SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k + SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k +} diff --git a/src/rp2_common/pico_crt0/rp2350/memory_xip_ram.ld b/src/rp2_common/pico_crt0/rp2350/memory_xip_ram.ld new file mode 100644 index 000000000..e94479b54 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/memory_xip_ram.ld @@ -0,0 +1,4 @@ +MEMORY +{ + XIP_RAM(rwx) : ORIGIN = 0x13FFC000, LENGTH = 16k +} diff --git a/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld new file mode 100644 index 000000000..296eb46dd --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld @@ -0,0 +1,305 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* On Arm, the bootrom expects a VT at the start of the + image by default; on RISC-V, the default is to enter the image at its + lowest address, so an IMAGE_DEF item is required to specify the + nondefault entry point. */ + + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + /* The bootrom will enter the image at the point indicated in your + IMAGE_DEF, which is usually the reset handler of your vector table. + + The debugger will use the ELF entry point, which is the _entry_point + symbol, and in our case is *different from the bootrom's entry point.* + This is used to go back through the bootrom on debugger launches only, + to perform the same initial flash setup that would be performed on a + cold boot. + */ + + .flashtext : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + . = ALIGN(4); + } > FLASH + + /* Note the boot2 section is optional, and should be discarded if there is + no reference to it *inside* the binary, as it is not called by the + bootrom. (The bootrom performs a simple best-effort XIP setup and + leaves it to the binary to do anything more sophisticated.) However + there is still a size limit of 256 bytes, to ensure the boot2 can be + stored in boot RAM. + + Really this is a "XIP setup function" -- the name boot2 is historic and + refers to its dual-purpose on RP2040, where it also handled vectoring + from the bootrom into the user image. + */ + + .boot2 : { + __boot2_start__ = .; + *(.boot2) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ <= 256, + "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") + + .rodata : { + /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); + + /* Vector table goes first in RAM, to avoid large alignment hole */ + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .text : { + __ram_text_start__ = .; + *(.init) + *(.text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + . = ALIGN(4); + __ram_text_end__ = .; + } > RAM AT> FLASH + __ram_text_source__ = LOADADDR(.text); + . = ALIGN(4); + + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + . = ALIGN(4); + *(.rodata*) + *(.srodata*) + . = ALIGN(4); + + *(.data*) + *(.sdata*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { + __persistent_data_start__ = .; + *(.persistent_data*) + . = ALIGN(4); + } + PROVIDE(__persistent_data_end__ = .); + + .heap (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X AT > FLASH + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y AT > FLASH + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y + + .flash_end : { + KEEP(*(.embedded_end_block*)) + PROVIDE(__flash_binary_end = .); + } > FLASH =0xaa + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") + ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") + + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2350/sections_default.ld b/src/rp2_common/pico_crt0/rp2350/sections_default.ld new file mode 100644 index 000000000..42cebd903 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/sections_default.ld @@ -0,0 +1,298 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + /* The bootrom will enter the image at the point indicated in your + IMAGE_DEF, which is usually the reset handler of your vector table. + + The debugger will use the ELF entry point, which is the _entry_point + symbol, and in our case is *different from the bootrom's entry point.* + This is used to go back through the bootrom on debugger launches only, + to perform the same initial flash setup that would be performed on a + cold boot. + */ + + .text : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + /* TODO revisit this now memset/memcpy/float in ROM */ + /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from + * FLASH ... we will include any thing excluded here in .data below by default */ + *(.init) + *libgcc.a:cmse_nonsecure_call.o + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.eh_frame*) + . = ALIGN(4); + } > FLASH + + /* Note the boot2 section is optional, and should be discarded if there is + no reference to it *inside* the binary, as it is not called by the + bootrom. (The bootrom performs a simple best-effort XIP setup and + leaves it to the binary to do anything more sophisticated.) However + there is still a size limit of 256 bytes, to ensure the boot2 can be + stored in boot RAM. + + Really this is a "XIP setup function" -- the name boot2 is historic and + refers to its dual-purpose on RP2040, where it also handled vectoring + from the bootrom into the user image. + */ + + .boot2 : { + __boot2_start__ = .; + *(.boot2) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ <= 256, + "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") + + .rodata : { + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) + *(.srodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); + + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ + *(.text*) + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + + *(.data*) + *(.sdata*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { + __persistent_data_start__ = .; + *(.persistent_data*) + . = ALIGN(4); + } + PROVIDE(__persistent_data_end__ = .); + + .heap (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X AT > FLASH + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y AT > FLASH + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y + + .flash_end : { + KEEP(*(.embedded_end_block*)) + PROVIDE(__flash_binary_end = .); + } > FLASH =0xaa + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") + ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") + + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld new file mode 100644 index 000000000..5149282c4 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld @@ -0,0 +1,253 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* Note unlike RP2040, we start the image with a vector table even for + NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the + image by default; on RISC-V, the default is to enter the image at its + lowest address, so an IMAGE_DEF item is required to specify the + nondefault entry point. */ + + .text : { + __logical_binary_start = .; + /* Vectors require 512-byte alignment on v8-M when >48 IRQs are used, + so we would waste RAM if the vector table were not at the + start. */ + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + __reset_start = .; + KEEP (*(.reset)) + __reset_end = .; + *(.time_critical*) + *(.text*) + . = ALIGN(4); + *(.init) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + } > RAM + + .rodata : { + . = ALIGN(4); + *(.rodata*) + *(.srodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > RAM + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > RAM + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > RAM + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > RAM + __binary_info_end = .; + . = ALIGN(4); + + .data : { + __data_start__ = .; + *(vtable) + *(.data*) + *(.sdata*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM + PROVIDE(__data_end__ = .); + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { + __persistent_data_start__ = .; + *(.persistent_data*) + . = ALIGN(4); + } + PROVIDE(__persistent_data_end__ = .); + + .heap (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") + ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") + + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index 6b37c6ef5..61e93a8cf 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -159,16 +159,11 @@ if (NOT TARGET pico_standard_link) #math(EXPR PICO_FLASH_SIZE_BYTES_STRING "${PICO_FLASH_SIZE_BYTES}" OUTPUT_FORMAT HEXADECIMAL) set(PICO_FLASH_SIZE_BYTES_STRING "${PICO_FLASH_SIZE_BYTES}") configure_file(${CMAKE_CURRENT_LIST_DIR}/pico_flash_region.template.ld ${CMAKE_BINARY_DIR}/pico_flash_region.ld) - pico_add_link_depend(pico_standard_link ${CMAKE_BINARY_DIR}/pico_flash_region.ld) - # add include path for linker scripts + # add include path for linker scripts to find it target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_BINARY_DIR}") - # set extra linker script include dir - set(_LINKER_SCRIPT_INCLUDE_DIR "$>,$,${PICO_LINKER_SCRIPT_PATH}>") - target_link_options(pico_standard_link INTERFACE - "LINKER:-L${_LINKER_SCRIPT_INCLUDE_DIR}" - ) - unset(_LINKER_SCRIPT_INCLUDE_DIR) + # add include path for main linker script sections + target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}") # LINKER script will be PICO_TARGET_LINKER_SCRIPT if set on target, or ${CMAKE_CURRENT_LIST_DIR}/memmap_foo.ld # if PICO_TARGET_BINARY_TYPE is set to foo on the target, otherwise ${CMAKE_CURRENT_LIST_DIR}/memmap_${PICO_DEFAULT_BINARY_TYPE).ld From 9c1b67fa11034e02be3ee0049b4a1092678b33fa Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 1 Dec 2025 20:40:45 +0000 Subject: [PATCH 050/127] Add customisable heap location, with pico_set_linker_script_var function --- .../pico_crt0/rp2040/sections_copy_to_ram.ld | 4 ++-- src/rp2_common/pico_crt0/rp2040/sections_default.ld | 4 ++-- src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld | 4 ++-- .../pico_crt0/rp2350/sections_copy_to_ram.ld | 4 ++-- src/rp2_common/pico_crt0/rp2350/sections_default.ld | 4 ++-- src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld | 4 ++-- src/rp2_common/pico_standard_link/CMakeLists.txt | 12 ++++++++++++ 7 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld index 5557ee1cb..1777f6604 100644 --- a/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld @@ -199,7 +199,7 @@ SECTIONS __bss_end__ = .; } > RAM - .heap (NOLOAD): + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -207,7 +207,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_crt0/rp2040/sections_default.ld b/src/rp2_common/pico_crt0/rp2040/sections_default.ld index 57984e46b..2e72b83b1 100644 --- a/src/rp2_common/pico_crt0/rp2040/sections_default.ld +++ b/src/rp2_common/pico_crt0/rp2040/sections_default.ld @@ -198,7 +198,7 @@ SECTIONS __bss_end__ = .; } > RAM - .heap (NOLOAD): + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -206,7 +206,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld b/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld index 9e082d53c..c71ee3b01 100644 --- a/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld @@ -167,7 +167,7 @@ SECTIONS __bss_end__ = .; } > RAM - .heap (NOLOAD): + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -175,7 +175,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld index 296eb46dd..3c372f1aa 100644 --- a/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld @@ -226,7 +226,7 @@ SECTIONS } PROVIDE(__persistent_data_end__ = .); - .heap (NOLOAD): + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -234,7 +234,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_crt0/rp2350/sections_default.ld b/src/rp2_common/pico_crt0/rp2350/sections_default.ld index 42cebd903..71379640b 100644 --- a/src/rp2_common/pico_crt0/rp2350/sections_default.ld +++ b/src/rp2_common/pico_crt0/rp2350/sections_default.ld @@ -219,7 +219,7 @@ SECTIONS } PROVIDE(__persistent_data_end__ = .); - .heap (NOLOAD): + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -227,7 +227,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld index 5149282c4..84340896f 100644 --- a/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld @@ -179,7 +179,7 @@ SECTIONS } PROVIDE(__persistent_data_end__ = .); - .heap (NOLOAD): + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; end = __end__; @@ -187,7 +187,7 @@ SECTIONS } > RAM /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); /* Start and end symbols must be word-aligned */ .scratch_x : { diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index 61e93a8cf..d5292a5cc 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -105,6 +105,15 @@ if (NOT TARGET pico_standard_link) set_target_properties(${TARGET} PROPERTIES PICO_TARGET_LINKER_SCRIPT ${LDSCRIPT}) endfunction() + # pico_set_linker_script_var(TARGET NAME VALUE) + # \brief\ Set the linker script for the target + # + # \param\ NAME Name of varAible to set + # \param\ VALUE Value of variable to set + function(pico_set_linker_script_var TARGET NAME VALUE) + set_property(TARGET ${TARGET} APPEND PROPERTY PICO_TARGET_LINKER_SCRIPT_VARS "--defsym=${NAME}=${VALUE}") + endfunction() + # pico_set_binary_type(TARGET TYPE) # \brief\ Set the binary type for the target # @@ -165,6 +174,9 @@ if (NOT TARGET pico_standard_link) # add include path for main linker script sections target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}") + # add variables set by pico_set_linker_script_var function + target_link_options(pico_standard_link INTERFACE "LINKER:$,,>") + # LINKER script will be PICO_TARGET_LINKER_SCRIPT if set on target, or ${CMAKE_CURRENT_LIST_DIR}/memmap_foo.ld # if PICO_TARGET_BINARY_TYPE is set to foo on the target, otherwise ${CMAKE_CURRENT_LIST_DIR}/memmap_${PICO_DEFAULT_BINARY_TYPE).ld set(_LINKER_SCRIPT_EXPRESSION "$>,$,${PICO_LINKER_SCRIPT_PATH}/memmap_$,>,${PICO_DEFAULT_BINARY_TYPE},$>.ld>") From 7fa5cbbdd08f1774948980230b11c535af9213de Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 1 Dec 2025 20:41:39 +0000 Subject: [PATCH 051/127] Add kitchen sink test of custom linker scripts --- test/kitchen_sink/CMakeLists.txt | 8 ++++++++ test/kitchen_sink/memmap_custom.ld | 12 ++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 test/kitchen_sink/memmap_custom.ld diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt index e605f0885..85a94fa01 100644 --- a/test/kitchen_sink/CMakeLists.txt +++ b/test/kitchen_sink/CMakeLists.txt @@ -215,6 +215,14 @@ if (NOT KITCHEN_SINK_NO_BINARY_TYPE_VARIANTS) pico_add_extra_outputs(kitchen_sink_blocked_ram) target_compile_definitions(kitchen_sink_blocked_ram PRIVATE KITCHEN_SINK_ID="blocked-ram binary") endif() + + add_executable(kitchen_sink_memmap_custom ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) + # Have heap start from 0x20030000, and custom linker script + pico_set_linker_script(kitchen_sink_memmap_custom ${CMAKE_CURRENT_LIST_DIR}/memmap_custom.ld) + pico_set_linker_script_var(kitchen_sink_memmap_custom HEAP_LOC 0x20030000) + target_link_libraries(kitchen_sink_memmap_custom kitchen_sink_libs kitchen_sink_options) + pico_add_extra_outputs(kitchen_sink_memmap_custom) + target_compile_definitions(kitchen_sink_memmap_custom PRIVATE KITCHEN_SINK_ID="custom memmap binary") endif() add_executable(kitchen_sink_cpp ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_cpp.cpp) diff --git a/test/kitchen_sink/memmap_custom.ld b/test/kitchen_sink/memmap_custom.ld new file mode 100644 index 000000000..081913e58 --- /dev/null +++ b/test/kitchen_sink/memmap_custom.ld @@ -0,0 +1,12 @@ +INCLUDE "memory_flash.ld" +INCLUDE "memory_scratch.ld" + +/* Only use 128k of SRAM, starting at 0x20020000 */ +MEMORY +{ + RAM(rwx) : ORIGIN = 0x20020000, LENGTH = 128k +} + +ENTRY(_entry_point) + +INCLUDE "sections_default.ld" From fe63e922f869718468f7feb8d393aed1f17d068f Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 1 Dec 2025 21:26:30 +0000 Subject: [PATCH 052/127] Remove pico_ld_constants and use pico_set_linker_script_var --- src/rp2_common/pico_crt0/rp2040/BUILD.bazel | 4 --- src/rp2_common/pico_crt0/rp2350/BUILD.bazel | 3 -- .../pico_crt0/rp2350/pico_ld_constants.ld | 1 - src/rp2_common/pico_low_power/BUILD.bazel | 2 +- src/rp2_common/pico_low_power/CMakeLists.txt | 16 ++++----- src/rp2_common/pico_standard_link/BUILD.bazel | 5 --- .../pico_standard_link/CMakeLists.txt | 35 ------------------- .../pico_standard_link/pico_ld_constants.bzl | 27 -------------- .../pico_ld_constants.template.ld | 1 - 9 files changed, 7 insertions(+), 87 deletions(-) delete mode 100644 src/rp2_common/pico_crt0/rp2350/pico_ld_constants.ld delete mode 100644 src/rp2_common/pico_standard_link/pico_ld_constants.bzl delete mode 100644 src/rp2_common/pico_standard_link/pico_ld_constants.template.ld diff --git a/src/rp2_common/pico_crt0/rp2040/BUILD.bazel b/src/rp2_common/pico_crt0/rp2040/BUILD.bazel index e6bf14d32..44912f0c8 100644 --- a/src/rp2_common/pico_crt0/rp2040/BUILD.bazel +++ b/src/rp2_common/pico_crt0/rp2040/BUILD.bazel @@ -28,7 +28,6 @@ cc_library( "memmap_default.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", "//src/rp2_common/pico_standard_link:default_flash_region", - "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) @@ -42,7 +41,6 @@ cc_library( "memmap_blocked_ram.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", "//src/rp2_common/pico_standard_link:default_flash_region", - "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) @@ -56,7 +54,6 @@ cc_library( "memmap_copy_to_ram.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", "//src/rp2_common/pico_standard_link:default_flash_region", - "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) @@ -69,6 +66,5 @@ cc_library( deps = [ "memmap_no_flash.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) diff --git a/src/rp2_common/pico_crt0/rp2350/BUILD.bazel b/src/rp2_common/pico_crt0/rp2350/BUILD.bazel index 54fff295e..b0f1ca7dd 100644 --- a/src/rp2_common/pico_crt0/rp2350/BUILD.bazel +++ b/src/rp2_common/pico_crt0/rp2350/BUILD.bazel @@ -27,7 +27,6 @@ cc_library( "memmap_default.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", "//src/rp2_common/pico_standard_link:default_flash_region", - "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) @@ -41,7 +40,6 @@ cc_library( "memmap_copy_to_ram.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", "//src/rp2_common/pico_standard_link:default_flash_region", - "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) @@ -54,6 +52,5 @@ cc_library( deps = [ "memmap_no_flash.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2_common/pico_standard_link:default_ld_constants", ], ) diff --git a/src/rp2_common/pico_crt0/rp2350/pico_ld_constants.ld b/src/rp2_common/pico_crt0/rp2350/pico_ld_constants.ld deleted file mode 100644 index 1e5bfda51..000000000 --- a/src/rp2_common/pico_crt0/rp2350/pico_ld_constants.ld +++ /dev/null @@ -1 +0,0 @@ -/* default file is empty */ \ No newline at end of file diff --git a/src/rp2_common/pico_low_power/BUILD.bazel b/src/rp2_common/pico_low_power/BUILD.bazel index e2456a668..796ea2894 100644 --- a/src/rp2_common/pico_low_power/BUILD.bazel +++ b/src/rp2_common/pico_low_power/BUILD.bazel @@ -20,6 +20,6 @@ cc_library( "//src/rp2_common/hardware_timer", "//src/rp2_common/hardware_uart", "//src/rp2_common/pico_aon_timer", - "//src/rp2_common/pico_stdio", + "//src/rp2_common/pico_stdio", ], ) diff --git a/src/rp2_common/pico_low_power/CMakeLists.txt b/src/rp2_common/pico_low_power/CMakeLists.txt index d07cf6c2e..a29748177 100644 --- a/src/rp2_common/pico_low_power/CMakeLists.txt +++ b/src/rp2_common/pico_low_power/CMakeLists.txt @@ -34,27 +34,23 @@ function(pico_set_persistent_data_loc TARGET PERSISTENT_DATA_LOC) if (NOT PICO_RP2350) message(FATAL_ERROR "pico_set_persistent_data_loc is only supported on RP2350") endif() - set_target_properties(${TARGET} PROPERTIES PICO_TARGET_PERSISTENT_DATA_LOC ${PERSISTENT_DATA_LOC}) + + pico_set_linker_script_var(${TARGET} PERSISTENT_DATA_LOC ${PERSISTENT_DATA_LOC}) if (PERSISTENT_DATA_LOC LESS 0x20000000) # XIP_SRAM, so heap should come after bss - set_target_properties(${TARGET} PROPERTIES - PICO_TARGET_HEAP_LOC __bss_end__) + pico_set_linker_script_var(${TARGET} HEAP_LOC __bss_end__) # Also pin the XIP_SRAM target_compile_definitions(${TARGET} PRIVATE PICO_CRT0_PIN_XIP_SRAM=1) elseif (PERSISTENT_DATA_LOC LESS 0x20040000) # SRAM0, so heap should come after persistent data - set_target_properties(${TARGET} PROPERTIES - PICO_TARGET_HEAP_LOC __persistent_data_end__) + pico_set_linker_script_var(${TARGET} HEAP_LOC __persistent_data_end__) elseif(PERSISTENT_DATA_LOC LESS 0x20080000) # SRAM1, so heap should come before persistent data - set_target_properties(${TARGET} PROPERTIES - PICO_TARGET_HEAP_LOC __bss_end__ - PICO_TARGET_HEAP_LIMIT ${PERSISTENT_DATA_LOC}) + pico_set_linker_script_var(${TARGET} HEAP_LOC __bss_end__) + pico_set_linker_script_var(${TARGET} HEAP_LIMIT ${PERSISTENT_DATA_LOC}) else() # Not supported in scratch, as the linker script will overwrite persistent data with scratch data message(FATAL_ERROR "pico_set_persistent_data_loc only supports persistent data in XIP_SRAM or SRAM0-7") endif() - - pico_add_linker_constants(${TARGET}) endfunction() diff --git a/src/rp2_common/pico_standard_link/BUILD.bazel b/src/rp2_common/pico_standard_link/BUILD.bazel index 8b9697c29..4c8ff249a 100644 --- a/src/rp2_common/pico_standard_link/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/BUILD.bazel @@ -1,7 +1,6 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library") load("//bazel:defs.bzl", "compatible_with_rp2") load("pico_flash_region.bzl", "generated_pico_flash_region") -load("pico_ld_constants.bzl", "generated_pico_ld_constants") package(default_visibility = ["//visibility:public"]) @@ -19,10 +18,6 @@ generated_pico_flash_region( }), ) -generated_pico_ld_constants( - name = "default_ld_constants", -) - cc_library( name = "pico_standard_link", target_compatible_with = compatible_with_rp2(), diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index d5292a5cc..5dd40909d 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -61,41 +61,6 @@ if (NOT TARGET pico_standard_link) endif() endfunction() - # pico_add_linker_constants(TARGET) - # \brief\ Add custom linker script constants to the target - # - # This reads target properties PICO_TARGET_PERSISTENT_DATA_LOC, PICO_TARGET_HEAP_LOC, - # and PICO_TARGET_HEAP_LIMIT and writes them to a linker script constant file, which - # is included by the linker script - function(pico_add_linker_constants TARGET) - set(pico_ld_constants_dir ${CMAKE_BINARY_DIR}/pico_ld_constants/${TARGET}) - - # add extra constants to content - set(pico_ld_constants_content "") - get_target_property(PERSISTENT_DATA_LOC ${TARGET} PICO_TARGET_PERSISTENT_DATA_LOC) - if (PERSISTENT_DATA_LOC) - set(pico_ld_constants_content "${pico_ld_constants_content}PERSISTENT_DATA_LOC = ${PERSISTENT_DATA_LOC}; ") - endif() - get_target_property(HEAP_LOC ${TARGET} PICO_TARGET_HEAP_LOC) - if (HEAP_LOC) - set(pico_ld_constants_content "${pico_ld_constants_content}HEAP_LOC = ${HEAP_LOC}; ") - endif() - get_target_property(HEAP_LIMIT ${TARGET} PICO_TARGET_HEAP_LIMIT) - if (HEAP_LIMIT) - set(pico_ld_constants_content "${pico_ld_constants_content}HEAP_LIMIT = ${HEAP_LIMIT}; ") - endif() - - # write the constants file - if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") - # CMAKE_CURRENT_FUNCTION_LIST_DIR added in 3.17.0 - configure_file(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/pico_ld_constants.template.ld ${pico_ld_constants_dir}/pico_ld_constants.ld @ONLY) - else() - configure_file(${PICO_SDK_PATH}src/rp2_common/pico_standard_link/pico_ld_constants.template.ld ${pico_ld_constants_dir}/pico_ld_constants.ld @ONLY) - endif() - set_target_properties(${TARGET} PROPERTIES PICO_TARGET_LINKER_SCRIPT_INCLUDE_DIR ${pico_ld_constants_dir}) - pico_add_link_depend(pico_standard_link ${pico_ld_constants_dir}/pico_ld_constants.ld) - endfunction() - # pico_set_linker_script(TARGET LDSCRIPT) # \brief\ Set the linker script for the target # diff --git a/src/rp2_common/pico_standard_link/pico_ld_constants.bzl b/src/rp2_common/pico_standard_link/pico_ld_constants.bzl deleted file mode 100644 index fc2a57c17..000000000 --- a/src/rp2_common/pico_standard_link/pico_ld_constants.bzl +++ /dev/null @@ -1,27 +0,0 @@ -load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "use_cpp_toolchain") - -def _generated_pico_ld_constants_impl(ctx): - ld_constants_linker_fragment = ctx.actions.declare_file(ctx.label.name + "/ldinclude/pico_ld_constants.ld") - link_include_dir = ld_constants_linker_fragment.dirname - - file_contents = "\n" - ctx.actions.write(ld_constants_linker_fragment, file_contents) - linking_inputs = cc_common.create_linker_input( - owner = ctx.label, - user_link_flags = depset( - direct = ["-L" + str(link_include_dir)], - ), - additional_inputs = depset( - direct = [ld_constants_linker_fragment], - ), - ) - return [ - DefaultInfo(files = depset([ld_constants_linker_fragment])), - CcInfo(linking_context = cc_common.create_linking_context(linker_inputs = depset(direct = [linking_inputs]))), - ] - -generated_pico_ld_constants = rule( - implementation = _generated_pico_ld_constants_impl, - toolchains = use_cpp_toolchain(), - fragments = ["cpp"], -) diff --git a/src/rp2_common/pico_standard_link/pico_ld_constants.template.ld b/src/rp2_common/pico_standard_link/pico_ld_constants.template.ld deleted file mode 100644 index d7425ac28..000000000 --- a/src/rp2_common/pico_standard_link/pico_ld_constants.template.ld +++ /dev/null @@ -1 +0,0 @@ -@pico_ld_constants_content@ \ No newline at end of file From 81a182baa29e4a148bbad57913acaba8b2b003a0 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 2 Dec 2025 14:48:02 +0000 Subject: [PATCH 053/127] Separate out rp2_common and platform-specific linker script sections --- .../pico_crt0/rp2040/memmap_blocked_ram.ld | 14 +- .../pico_crt0/rp2040/memmap_copy_to_ram.ld | 8 +- .../pico_crt0/rp2040/memmap_default.ld | 8 +- .../pico_crt0/rp2040/memmap_no_flash.ld | 7 +- .../{ => platform}/memory_blocked_ram.ld | 0 .../rp2040/{ => platform}/memory_ram.ld | 0 .../rp2040/{ => platform}/memory_scratch.ld | 0 .../platform/section_copy_to_ram_data.ld | 86 +++++ .../platform/section_copy_to_ram_text.ld | 101 ++++++ .../rp2040/platform/section_default_data.ld | 77 +++++ .../rp2040/platform/section_default_text.ld | 109 +++++++ .../rp2040/platform/section_no_flash_data.ld | 86 +++++ .../rp2040/platform/section_no_flash_text.ld | 71 ++++ .../rp2040/platform/section_platform_end.ld | 50 +++ .../pico_crt0/rp2040/sections_copy_to_ram.ld | 276 ---------------- .../pico_crt0/rp2040/sections_default.ld | 275 ---------------- .../pico_crt0/rp2040/sections_no_flash.ld | 239 -------------- .../pico_crt0/rp2350/memmap_copy_to_ram.ld | 8 +- .../pico_crt0/rp2350/memmap_default.ld | 8 +- .../pico_crt0/rp2350/memmap_no_flash.ld | 7 +- .../pico_crt0/rp2350/memory_copy_to_ram.ld | 0 .../pico_crt0/rp2350/memory_flash.ld | 4 - .../rp2350/{ => platform}/memory_ram.ld | 0 .../rp2350/{ => platform}/memory_scratch.ld | 0 .../rp2350/{ => platform}/memory_xip_ram.ld | 0 .../platform/section_copy_to_ram_data.ld | 83 +++++ .../platform/section_copy_to_ram_text.ld | 117 +++++++ .../rp2350/platform/section_default_data.ld | 72 +++++ .../rp2350/platform/section_default_text.ld | 121 +++++++ .../rp2350/platform/section_no_flash_data.ld | 82 +++++ .../rp2350/platform/section_no_flash_text.ld | 73 +++++ .../rp2350/platform/section_platform_end.ld | 7 + .../pico_crt0/rp2350/sections_copy_to_ram.ld | 305 ------------------ .../pico_crt0/rp2350/sections_default.ld | 298 ----------------- .../pico_crt0/rp2350/sections_no_flash.ld | 253 --------------- .../pico_standard_link/CMakeLists.txt | 1 + .../scripts/rp2_common/memmap_copy_to_ram.ld | 13 + .../scripts/rp2_common/memmap_default.ld | 13 + .../scripts/rp2_common/memmap_no_flash.ld | 12 + .../rp2_common/memory_aliases_default.ld | 3 + .../rp2_common/memory_aliases_no_flash.ld | 3 + .../scripts/rp2_common}/memory_flash.ld | 0 .../scripts/rp2_common/section_end.ld | 49 +++ .../scripts/rp2_common/section_flash_end.ld | 7 + .../scripts/rp2_common/section_heap.ld | 12 + .../scripts/rp2_common/section_scratch.ld | 37 +++ .../rp2_common/sections_copy_to_ram.ld | 7 + .../scripts/rp2_common/sections_default.ld | 7 + .../scripts/rp2_common/sections_no_flash.ld | 6 + test/kitchen_sink/memmap_custom.ld | 12 +- 50 files changed, 1330 insertions(+), 1697 deletions(-) rename src/rp2_common/pico_crt0/rp2040/{ => platform}/memory_blocked_ram.ld (100%) rename src/rp2_common/pico_crt0/rp2040/{ => platform}/memory_ram.ld (100%) rename src/rp2_common/pico_crt0/rp2040/{ => platform}/memory_scratch.ld (100%) create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_text.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_default_text.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_text.ld create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/section_platform_end.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/sections_default.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/memory_copy_to_ram.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/memory_flash.ld rename src/rp2_common/pico_crt0/rp2350/{ => platform}/memory_ram.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{ => platform}/memory_scratch.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{ => platform}/memory_xip_ram.ld (100%) create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_text.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_default_text.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_text.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_platform_end.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/sections_default.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_default.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_no_flash.ld rename src/rp2_common/{pico_crt0/rp2040 => pico_standard_link/scripts/rp2_common}/memory_flash.ld (100%) create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/section_end.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/section_flash_end.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/section_heap.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/section_scratch.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld index 150176eba..330e9bde3 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld @@ -1,7 +1,13 @@ -INCLUDE "memory_flash.ld" -INCLUDE "memory_blocked_ram.ld" -INCLUDE "memory_scratch.ld" +/* Include memory regions used */ +INCLUDE "rp2_common/memory_flash.ld" +INCLUDE "platform/memory_blocked_ram.ld" +INCLUDE "platform/memory_scratch.ld" +/* Include aliases for storage memory regions */ +INCLUDE "rp2_common/memory_aliases_default.ld" + +/* Define entry point symbol */ ENTRY(_entry_point) -INCLUDE "sections_default.ld" +/* Include default sections */ +INCLUDE "rp2_common/sections_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld index 7b99a7745..6a1647d4a 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_copy_to_ram.ld @@ -1,7 +1 @@ -INCLUDE "memory_flash.ld" -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -ENTRY(_entry_point) - -INCLUDE "sections_copy_to_ram.ld" +INCLUDE "rp2_common/memmap_copy_to_ram.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_default.ld b/src/rp2_common/pico_crt0/rp2040/memmap_default.ld index 75fd340d5..8e2073718 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_default.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_default.ld @@ -1,7 +1 @@ -INCLUDE "memory_flash.ld" -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -ENTRY(_entry_point) - -INCLUDE "sections_default.ld" +INCLUDE "rp2_common/memmap_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld b/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld index cde630592..b8d1dcf36 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_no_flash.ld @@ -1,6 +1 @@ -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -ENTRY(_entry_point) - -INCLUDE "sections_no_flash.ld" +INCLUDE "rp2_common/memmap_no_flash.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/memory_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/platform/memory_blocked_ram.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/memory_blocked_ram.ld rename to src/rp2_common/pico_crt0/rp2040/platform/memory_blocked_ram.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memory_ram.ld b/src/rp2_common/pico_crt0/rp2040/platform/memory_ram.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/memory_ram.ld rename to src/rp2_common/pico_crt0/rp2040/platform/memory_ram.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memory_scratch.ld b/src/rp2_common/pico_crt0/rp2040/platform/memory_scratch.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/memory_scratch.ld rename to src/rp2_common/pico_crt0/rp2040/platform/memory_scratch.ld diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld new file mode 100644 index 000000000..325da150f --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld @@ -0,0 +1,86 @@ +SECTIONS +{ + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + + *(.data*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { + __persistent_data_start__ = .; + *(.persistent_data*) + . = ALIGN(4); + } + PROVIDE(__persistent_data_end__ = .); +} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_text.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_text.ld new file mode 100644 index 000000000..77a45941b --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_text.ld @@ -0,0 +1,101 @@ +SECTIONS +{ + /* Second stage bootloader is prepended to the image. It must be 256 bytes big + and checksummed. It is usually built by the boot_stage2 target + in the Raspberry Pi Pico SDK + */ + + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + .boot2 : { + __boot2_start__ = .; + KEEP (*(.boot2)) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ == 256, + "ERROR: Pico second stage bootloader must be 256 bytes in size") + + /* The second stage will always enter the image at the start of .text. + The debugger will use the ELF entry point, which is the _entry_point + symbol if present, otherwise defaults to start of .text. + This can be used to transfer control back to the bootrom on debugger + launches only, to perform proper flash setup. + */ + + .flashtext : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + } + + .rodata : { + /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); + + /* Vector table goes first in RAM, to avoid large alignment hole */ + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .text : { + __ram_text_start__ = .; + *(.init) + *(.text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + . = ALIGN(4); + __ram_text_end__ = .; + } > RAM AT> FLASH + __ram_text_source__ = LOADADDR(.text); + . = ALIGN(4); +} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld new file mode 100644 index 000000000..27da2e947 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld @@ -0,0 +1,77 @@ +SECTIONS +{ + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ + *(.text*) + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + + *(.data*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { + __persistent_data_start__ = .; + *(.persistent_data*) + . = ALIGN(4); + } + PROVIDE(__persistent_data_end__ = .); +} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_default_text.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_default_text.ld new file mode 100644 index 000000000..7aa5c9399 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_default_text.ld @@ -0,0 +1,109 @@ +SECTIONS +{ + /* Second stage bootloader is prepended to the image. It must be 256 bytes big + and checksummed. It is usually built by the boot_stage2 target + in the Raspberry Pi Pico SDK + */ + + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + .boot2 : { + __boot2_start__ = .; + KEEP (*(.boot2)) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ == 256, + "ERROR: Pico second stage bootloader must be 256 bytes in size") + + /* The second stage will always enter the image at the start of .text. + The debugger will use the ELF entry point, which is the _entry_point + symbol if present, otherwise defaults to start of .text. + This can be used to transfer control back to the bootrom on debugger + launches only, to perform proper flash setup. + */ + + .text : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + /* TODO revisit this now memset/memcpy/float in ROM */ + /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from + * FLASH ... we will include any thing excluded here in .data below by default */ + *(.init) + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.eh_frame*) + . = ALIGN(4); + } > FLASH + + .rodata : { + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); +} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld new file mode 100644 index 000000000..bdce39b44 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld @@ -0,0 +1,86 @@ +SECTIONS +{ + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + *(.data*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM + PROVIDE(__data_end__ = .); + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { + __persistent_data_start__ = .; + *(.persistent_data*) + . = ALIGN(4); + } + PROVIDE(__persistent_data_end__ = .); +} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_text.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_text.ld new file mode 100644 index 000000000..b4ad44ba7 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_text.ld @@ -0,0 +1,71 @@ +SECTIONS +{ + /* Note in NO_FLASH builds the entry point for both the bootrom, and debugger + entry (ELF entry point), are *first* in the image, and the vector table + follows immediately afterward. This is because the bootrom enters RAM + binaries directly at their lowest address (preferring main RAM over XIP + cache-as-SRAM if both are used). + */ + + .text : { + __logical_binary_start = .; + __reset_start = .; + KEEP (*(.reset)) + __reset_end = .; + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + . = ALIGN(256); + KEEP (*(.vectors)) + *(.text*) + . = ALIGN(4); + *(.init) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + } > RAM + + .rodata : { + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > RAM + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > RAM + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > RAM + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > RAM + __binary_info_end = .; + . = ALIGN(4); +} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_platform_end.ld b/src/rp2_common/pico_crt0/rp2040/platform/section_platform_end.ld new file mode 100644 index 000000000..2d0165aa4 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/section_platform_end.ld @@ -0,0 +1,50 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld deleted file mode 100644 index 1777f6604..000000000 --- a/src/rp2_common/pico_crt0/rp2040/sections_copy_to_ram.ld +++ /dev/null @@ -1,276 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .flashtext : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - } - - .rodata : { - /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - /* Vector table goes first in RAM, to avoid large alignment hole */ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .text : { - __ram_text_start__ = .; - *(.init) - *(.text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - . = ALIGN(4); - __ram_text_end__ = .; - } > RAM AT> FLASH - __ram_text_source__ = LOADADDR(.text); - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_crt0/rp2040/sections_default.ld b/src/rp2_common/pico_crt0/rp2040/sections_default.ld deleted file mode 100644 index 2e72b83b1..000000000 --- a/src/rp2_common/pico_crt0/rp2040/sections_default.ld +++ /dev/null @@ -1,275 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .text : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - /* TODO revisit this now memset/memcpy/float in ROM */ - /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from - * FLASH ... we will include any thing excluded here in .data below by default */ - *(.init) - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.eh_frame*) - . = ALIGN(4); - } > FLASH - - .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ - *(.text*) - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld b/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld deleted file mode 100644 index c71ee3b01..000000000 --- a/src/rp2_common/pico_crt0/rp2040/sections_no_flash.ld +++ /dev/null @@ -1,239 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - /* Note in NO_FLASH builds the entry point for both the bootrom, and debugger - entry (ELF entry point), are *first* in the image, and the vector table - follows immediately afterward. This is because the bootrom enters RAM - binaries directly at their lowest address (preferring main RAM over XIP - cache-as-SRAM if both are used). - */ - - .text : { - __logical_binary_start = .; - __reset_start = .; - KEEP (*(.reset)) - __reset_end = .; - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - . = ALIGN(256); - KEEP (*(.vectors)) - *(.time_critical*) - *(.text*) - . = ALIGN(4); - *(.init) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - } > RAM - - .rodata : { - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > RAM - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > RAM - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > RAM - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > RAM - __binary_info_end = .; - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - *(.data*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM - PROVIDE(__data_end__ = .); - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld index 7b99a7745..6a1647d4a 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_copy_to_ram.ld @@ -1,7 +1 @@ -INCLUDE "memory_flash.ld" -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -ENTRY(_entry_point) - -INCLUDE "sections_copy_to_ram.ld" +INCLUDE "rp2_common/memmap_copy_to_ram.ld" diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld index 75fd340d5..8e2073718 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_default.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_default.ld @@ -1,7 +1 @@ -INCLUDE "memory_flash.ld" -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -ENTRY(_entry_point) - -INCLUDE "sections_default.ld" +INCLUDE "rp2_common/memmap_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld index cde630592..b8d1dcf36 100644 --- a/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld +++ b/src/rp2_common/pico_crt0/rp2350/memmap_no_flash.ld @@ -1,6 +1 @@ -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -ENTRY(_entry_point) - -INCLUDE "sections_no_flash.ld" +INCLUDE "rp2_common/memmap_no_flash.ld" diff --git a/src/rp2_common/pico_crt0/rp2350/memory_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/memory_copy_to_ram.ld deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/rp2_common/pico_crt0/rp2350/memory_flash.ld b/src/rp2_common/pico_crt0/rp2350/memory_flash.ld deleted file mode 100644 index 669fe00e3..000000000 --- a/src/rp2_common/pico_crt0/rp2350/memory_flash.ld +++ /dev/null @@ -1,4 +0,0 @@ -MEMORY -{ - INCLUDE "pico_flash_region.ld" -} diff --git a/src/rp2_common/pico_crt0/rp2350/memory_ram.ld b/src/rp2_common/pico_crt0/rp2350/platform/memory_ram.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/memory_ram.ld rename to src/rp2_common/pico_crt0/rp2350/platform/memory_ram.ld diff --git a/src/rp2_common/pico_crt0/rp2350/memory_scratch.ld b/src/rp2_common/pico_crt0/rp2350/platform/memory_scratch.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/memory_scratch.ld rename to src/rp2_common/pico_crt0/rp2350/platform/memory_scratch.ld diff --git a/src/rp2_common/pico_crt0/rp2350/memory_xip_ram.ld b/src/rp2_common/pico_crt0/rp2350/platform/memory_xip_ram.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/memory_xip_ram.ld rename to src/rp2_common/pico_crt0/rp2350/platform/memory_xip_ram.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld new file mode 100644 index 000000000..19082589c --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld @@ -0,0 +1,83 @@ +SECTIONS +{ + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + . = ALIGN(4); + *(.rodata*) + *(.srodata*) + . = ALIGN(4); + + *(.data*) + *(.sdata*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) + . = ALIGN(4); + __bss_end__ = .; + } > RAM +} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_text.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_text.ld new file mode 100644 index 000000000..d35f7209e --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_text.ld @@ -0,0 +1,117 @@ +SECTIONS +{ + /* On Arm, the bootrom expects a VT at the start of the + image by default; on RISC-V, the default is to enter the image at its + lowest address, so an IMAGE_DEF item is required to specify the + nondefault entry point. */ + + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + /* The bootrom will enter the image at the point indicated in your + IMAGE_DEF, which is usually the reset handler of your vector table. + + The debugger will use the ELF entry point, which is the _entry_point + symbol, and in our case is *different from the bootrom's entry point.* + This is used to go back through the bootrom on debugger launches only, + to perform the same initial flash setup that would be performed on a + cold boot. + */ + + .flashtext : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + . = ALIGN(4); + } > FLASH + + /* Note the boot2 section is optional, and should be discarded if there is + no reference to it *inside* the binary, as it is not called by the + bootrom. (The bootrom performs a simple best-effort XIP setup and + leaves it to the binary to do anything more sophisticated.) However + there is still a size limit of 256 bytes, to ensure the boot2 can be + stored in boot RAM. + + Really this is a "XIP setup function" -- the name boot2 is historic and + refers to its dual-purpose on RP2040, where it also handled vectoring + from the bootrom into the user image. + */ + + .boot2 : { + __boot2_start__ = .; + *(.boot2) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ <= 256, + "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") + + .rodata : { + /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); + + /* Vector table goes first in RAM, to avoid large alignment hole */ + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .text : { + __ram_text_start__ = .; + *(.init) + *(.text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + . = ALIGN(4); + __ram_text_end__ = .; + } > RAM AT> FLASH + __ram_text_source__ = LOADADDR(.text); + . = ALIGN(4); +} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld new file mode 100644 index 000000000..9ffa5d163 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld @@ -0,0 +1,72 @@ +SECTIONS +{ + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ + *(.text*) + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + + *(.data*) + *(.sdata*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM AT> FLASH + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM AT> FLASH + PROVIDE(__data_end__ = .); + + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) + . = ALIGN(4); + __bss_end__ = .; + } > RAM +} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_default_text.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_default_text.ld new file mode 100644 index 000000000..fdd963321 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_default_text.ld @@ -0,0 +1,121 @@ +SECTIONS +{ + .flash_begin : { + __flash_binary_start = .; + } > FLASH + + /* The bootrom will enter the image at the point indicated in your + IMAGE_DEF, which is usually the reset handler of your vector table. + + The debugger will use the ELF entry point, which is the _entry_point + symbol, and in our case is *different from the bootrom's entry point.* + This is used to go back through the bootrom on debugger launches only, + to perform the same initial flash setup that would be performed on a + cold boot. + */ + + .text : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + /* TODO revisit this now memset/memcpy/float in ROM */ + /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from + * FLASH ... we will include any thing excluded here in .data below by default */ + *(.init) + *libgcc.a:cmse_nonsecure_call.o + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.eh_frame*) + . = ALIGN(4); + } > FLASH + + /* Note the boot2 section is optional, and should be discarded if there is + no reference to it *inside* the binary, as it is not called by the + bootrom. (The bootrom performs a simple best-effort XIP setup and + leaves it to the binary to do anything more sophisticated.) However + there is still a size limit of 256 bytes, to ensure the boot2 can be + stored in boot RAM. + + Really this is a "XIP setup function" -- the name boot2 is historic and + refers to its dual-purpose on RP2040, where it also handled vectoring + from the bootrom into the user image. + */ + + .boot2 : { + __boot2_start__ = .; + *(.boot2) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ <= 256, + "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") + + .rodata : { + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) + *(.srodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > FLASH + __binary_info_end = .; + . = ALIGN(4); +} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld new file mode 100644 index 000000000..5658d8a4b --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld @@ -0,0 +1,82 @@ +SECTIONS +{ + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + *(.data*) + *(.sdata*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + } > RAM + + .tdata : { + . = ALIGN(4); + *(.tdata .tdata.* .gnu.linkonce.td.*) + /* All data end */ + __tdata_end = .; + } > RAM + PROVIDE(__data_end__ = .); + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) + . = ALIGN(4); + __bss_end__ = .; + } > RAM +} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_text.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_text.ld new file mode 100644 index 000000000..833d8c42b --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_text.ld @@ -0,0 +1,73 @@ +SECTIONS +{ + /* Note unlike RP2040, we start the image with a vector table even for + NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the + image by default; on RISC-V, the default is to enter the image at its + lowest address, so an IMAGE_DEF item is required to specify the + nondefault entry point. */ + + .text : { + __logical_binary_start = .; + /* Vectors require 512-byte alignment on v8-M when >48 IRQs are used, + so we would waste RAM if the vector table were not at the + start. */ + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + __reset_start = .; + KEEP (*(.reset)) + __reset_end = .; + *(.text*) + . = ALIGN(4); + *(.init) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + } > RAM + + .rodata : { + . = ALIGN(4); + *(.rodata*) + *(.srodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > RAM + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > RAM + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > RAM + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > RAM + __binary_info_end = .; + . = ALIGN(4); +} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_platform_end.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_platform_end.ld new file mode 100644 index 000000000..43cc19ecd --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/section_platform_end.ld @@ -0,0 +1,7 @@ +SECTIONS +{ + ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") + ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") + + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld b/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld deleted file mode 100644 index 3c372f1aa..000000000 --- a/src/rp2_common/pico_crt0/rp2350/sections_copy_to_ram.ld +++ /dev/null @@ -1,305 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - /* On Arm, the bootrom expects a VT at the start of the - image by default; on RISC-V, the default is to enter the image at its - lowest address, so an IMAGE_DEF item is required to specify the - nondefault entry point. */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - /* The bootrom will enter the image at the point indicated in your - IMAGE_DEF, which is usually the reset handler of your vector table. - - The debugger will use the ELF entry point, which is the _entry_point - symbol, and in our case is *different from the bootrom's entry point.* - This is used to go back through the bootrom on debugger launches only, - to perform the same initial flash setup that would be performed on a - cold boot. - */ - - .flashtext : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - . = ALIGN(4); - } > FLASH - - /* Note the boot2 section is optional, and should be discarded if there is - no reference to it *inside* the binary, as it is not called by the - bootrom. (The bootrom performs a simple best-effort XIP setup and - leaves it to the binary to do anything more sophisticated.) However - there is still a size limit of 256 bytes, to ensure the boot2 can be - stored in boot RAM. - - Really this is a "XIP setup function" -- the name boot2 is historic and - refers to its dual-purpose on RP2040, where it also handled vectoring - from the bootrom into the user image. - */ - - .boot2 : { - __boot2_start__ = .; - *(.boot2) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ <= 256, - "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") - - .rodata : { - /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - /* Vector table goes first in RAM, to avoid large alignment hole */ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .text : { - __ram_text_start__ = .; - *(.init) - *(.text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - . = ALIGN(4); - __ram_text_end__ = .; - } > RAM AT> FLASH - __ram_text_source__ = LOADADDR(.text); - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - . = ALIGN(4); - *(.rodata*) - *(.srodata*) - . = ALIGN(4); - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { - __persistent_data_start__ = .; - *(.persistent_data*) - . = ALIGN(4); - } - PROVIDE(__persistent_data_end__ = .); - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH =0xaa - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") - ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_crt0/rp2350/sections_default.ld b/src/rp2_common/pico_crt0/rp2350/sections_default.ld deleted file mode 100644 index 71379640b..000000000 --- a/src/rp2_common/pico_crt0/rp2350/sections_default.ld +++ /dev/null @@ -1,298 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - /* The bootrom will enter the image at the point indicated in your - IMAGE_DEF, which is usually the reset handler of your vector table. - - The debugger will use the ELF entry point, which is the _entry_point - symbol, and in our case is *different from the bootrom's entry point.* - This is used to go back through the bootrom on debugger launches only, - to perform the same initial flash setup that would be performed on a - cold boot. - */ - - .text : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - /* TODO revisit this now memset/memcpy/float in ROM */ - /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from - * FLASH ... we will include any thing excluded here in .data below by default */ - *(.init) - *libgcc.a:cmse_nonsecure_call.o - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.eh_frame*) - . = ALIGN(4); - } > FLASH - - /* Note the boot2 section is optional, and should be discarded if there is - no reference to it *inside* the binary, as it is not called by the - bootrom. (The bootrom performs a simple best-effort XIP setup and - leaves it to the binary to do anything more sophisticated.) However - there is still a size limit of 256 bytes, to ensure the boot2 can be - stored in boot RAM. - - Really this is a "XIP setup function" -- the name boot2 is historic and - refers to its dual-purpose on RP2040, where it also handled vectoring - from the bootrom into the user image. - */ - - .boot2 : { - __boot2_start__ = .; - *(.boot2) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ <= 256, - "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") - - .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) - *(.srodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ - *(.text*) - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { - __persistent_data_start__ = .; - *(.persistent_data*) - . = ALIGN(4); - } - PROVIDE(__persistent_data_end__ = .); - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT > FLASH - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT > FLASH - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH =0xaa - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") - ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld b/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld deleted file mode 100644 index 84340896f..000000000 --- a/src/rp2_common/pico_crt0/rp2350/sections_no_flash.ld +++ /dev/null @@ -1,253 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - /* Note unlike RP2040, we start the image with a vector table even for - NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the - image by default; on RISC-V, the default is to enter the image at its - lowest address, so an IMAGE_DEF item is required to specify the - nondefault entry point. */ - - .text : { - __logical_binary_start = .; - /* Vectors require 512-byte alignment on v8-M when >48 IRQs are used, - so we would waste RAM if the vector table were not at the - start. */ - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - __reset_start = .; - KEEP (*(.reset)) - __reset_end = .; - *(.time_critical*) - *(.text*) - . = ALIGN(4); - *(.init) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - } > RAM - - .rodata : { - . = ALIGN(4); - *(.rodata*) - *(.srodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > RAM - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > RAM - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > RAM - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > RAM - __binary_info_end = .; - . = ALIGN(4); - - .data : { - __data_start__ = .; - *(vtable) - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM - PROVIDE(__data_end__ = .); - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { - __persistent_data_start__ = .; - *(.persistent_data*) - . = ALIGN(4); - } - PROVIDE(__persistent_data_end__ = .); - - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); - - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y - - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") - ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index 5dd40909d..8fc240346 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -138,6 +138,7 @@ if (NOT TARGET pico_standard_link) # add include path for main linker script sections target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}") + target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_CURRENT_LIST_DIR}/scripts") # add variables set by pico_set_linker_script_var function target_link_options(pico_standard_link INTERFACE "LINKER:$,,>") diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld new file mode 100644 index 000000000..88127d894 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld @@ -0,0 +1,13 @@ +/* Include memory regions used */ +INCLUDE "rp2_common/memory_flash.ld" +INCLUDE "platform/memory_ram.ld" +INCLUDE "platform/memory_scratch.ld" + +/* Include aliases for storage memory regions */ +INCLUDE "rp2_common/memory_aliases_default.ld" + +/* Define entry point symbol */ +ENTRY(_entry_point) + +/* Include default sections */ +INCLUDE "rp2_common/sections_copy_to_ram.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld new file mode 100644 index 000000000..a8de400d9 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld @@ -0,0 +1,13 @@ +/* Include memory regions used */ +INCLUDE "rp2_common/memory_flash.ld" +INCLUDE "platform/memory_ram.ld" +INCLUDE "platform/memory_scratch.ld" + +/* Include aliases for storage memory regions */ +INCLUDE "rp2_common/memory_aliases_default.ld" + +/* Define entry point symbol */ +ENTRY(_entry_point) + +/* Include default sections */ +INCLUDE "rp2_common/sections_default.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld new file mode 100644 index 000000000..61ae84dc7 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld @@ -0,0 +1,12 @@ +/* Include memory regions used */ +INCLUDE "platform/memory_ram.ld" +INCLUDE "platform/memory_scratch.ld" + +/* Include aliases for no_flash storage memory regions (alias to themselves) */ +INCLUDE "rp2_common/memory_aliases_no_flash.ld" + +/* Define entry point symbol */ +ENTRY(_entry_point) + +/* Include no_flash sections */ +INCLUDE "rp2_common/sections_no_flash.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_default.ld new file mode 100644 index 000000000..7c56254bd --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_default.ld @@ -0,0 +1,3 @@ +REGION_ALIAS("RAM_STORE", FLASH); +REGION_ALIAS("SCRATCH_X_STORE", FLASH); +REGION_ALIAS("SCRATCH_Y_STORE", FLASH); diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_no_flash.ld new file mode 100644 index 000000000..063b5b6fc --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_no_flash.ld @@ -0,0 +1,3 @@ +REGION_ALIAS("RAM_STORE", RAM); +REGION_ALIAS("SCRATCH_X_STORE", SCRATCH_X); +REGION_ALIAS("SCRATCH_Y_STORE", SCRATCH_Y); diff --git a/src/rp2_common/pico_crt0/rp2040/memory_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_flash.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/memory_flash.ld rename to src/rp2_common/pico_standard_link/scripts/rp2_common/memory_flash.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_end.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_end.ld new file mode 100644 index 000000000..53d328174 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_end.ld @@ -0,0 +1,49 @@ +/* Based on GCC ARM embedded samples. + Defines the following symbols for use by code: + __exidx_start + __exidx_end + __etext + __data_start__ + __preinit_array_start + __preinit_array_end + __init_array_start + __init_array_end + __fini_array_start + __fini_array_end + __data_end__ + __bss_start__ + __bss_end__ + __end__ + end + __HeapLimit + __StackLimit + __StackTop + __stack (== StackTop) +*/ + +SECTIONS +{ + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* picolibc and LLVM */ + PROVIDE (__heap_start = __end__); + PROVIDE (__heap_end = __HeapLimit); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + + /* llvm-libc */ + PROVIDE (_end = __end__); + PROVIDE (__llvm_libc_heap_limit = __HeapLimit); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + /* todo assert on extra code */ +} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_flash_end.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_flash_end.ld new file mode 100644 index 000000000..8591406ff --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_flash_end.ld @@ -0,0 +1,7 @@ +SECTIONS +{ + .flash_end : { + KEEP(*(.embedded_end_block*)) + PROVIDE(__flash_binary_end = .); + } > FLASH =0xaa +} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_heap.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_heap.ld new file mode 100644 index 000000000..1cc9e0de1 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_heap.ld @@ -0,0 +1,12 @@ +SECTIONS +{ + .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + } > RAM + /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however + to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ + __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); +} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_scratch.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_scratch.ld new file mode 100644 index 000000000..f61c39639 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_scratch.ld @@ -0,0 +1,37 @@ +SECTIONS +{ + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } > SCRATCH_X AT> SCRATCH_X_STORE + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } > SCRATCH_Y AT> SCRATCH_Y_STORE + __scratch_y_source__ = LOADADDR(.scratch_y); + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y +} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld new file mode 100644 index 000000000..0017f385b --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld @@ -0,0 +1,7 @@ +INCLUDE "platform/section_copy_to_ram_text.ld" +INCLUDE "platform/section_copy_to_ram_data.ld" +INCLUDE "rp2_common/section_heap.ld" +INCLUDE "rp2_common/section_scratch.ld" +INCLUDE "rp2_common/section_flash_end.ld" +INCLUDE "rp2_common/section_end.ld" +INCLUDE "platform/section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld new file mode 100644 index 000000000..e0138db34 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld @@ -0,0 +1,7 @@ +INCLUDE "platform/section_default_text.ld" +INCLUDE "platform/section_default_data.ld" +INCLUDE "rp2_common/section_heap.ld" +INCLUDE "rp2_common/section_scratch.ld" +INCLUDE "rp2_common/section_flash_end.ld" +INCLUDE "rp2_common/section_end.ld" +INCLUDE "platform/section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld new file mode 100644 index 000000000..ebc062e6a --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld @@ -0,0 +1,6 @@ +INCLUDE "platform/section_no_flash_text.ld" +INCLUDE "platform/section_no_flash_data.ld" +INCLUDE "rp2_common/section_heap.ld" +INCLUDE "rp2_common/section_scratch.ld" +INCLUDE "rp2_common/section_end.ld" +INCLUDE "platform/section_platform_end.ld" diff --git a/test/kitchen_sink/memmap_custom.ld b/test/kitchen_sink/memmap_custom.ld index 081913e58..7fe2098f1 100644 --- a/test/kitchen_sink/memmap_custom.ld +++ b/test/kitchen_sink/memmap_custom.ld @@ -1,5 +1,6 @@ -INCLUDE "memory_flash.ld" -INCLUDE "memory_scratch.ld" +/* Include memory regions used */ +INCLUDE "rp2_common/memory_flash.ld" +INCLUDE "platform/memory_scratch.ld" /* Only use 128k of SRAM, starting at 0x20020000 */ MEMORY @@ -7,6 +8,11 @@ MEMORY RAM(rwx) : ORIGIN = 0x20020000, LENGTH = 128k } +/* Include aliases for storage memory regions */ +INCLUDE "rp2_common/memory_aliases_default.ld" + +/* Define entry point symbol */ ENTRY(_entry_point) -INCLUDE "sections_default.ld" +/* Include default sections */ +INCLUDE "rp2_common/sections_default.ld" From fba2c74149e723d437c58f4393f84aa3ee554e66 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 2 Dec 2025 14:56:53 +0000 Subject: [PATCH 054/127] More de-duplication --- .../platform/section_copy_to_ram_data.ld | 83 ------------------- .../rp2350/platform/section_default_data.ld | 72 ---------------- .../rp2350/platform/section_no_flash_data.ld | 82 ------------------ .../rp2_common}/section_copy_to_ram_data.ld | 4 + .../rp2_common}/section_default_data.ld | 4 +- .../rp2_common}/section_no_flash_data.ld | 3 + .../rp2_common/sections_copy_to_ram.ld | 2 +- .../scripts/rp2_common/sections_default.ld | 2 +- .../scripts/rp2_common/sections_no_flash.ld | 2 +- 9 files changed, 13 insertions(+), 241 deletions(-) delete mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld rename src/rp2_common/{pico_crt0/rp2040/platform => pico_standard_link/scripts/rp2_common}/section_copy_to_ram_data.ld (95%) rename src/rp2_common/{pico_crt0/rp2040/platform => pico_standard_link/scripts/rp2_common}/section_default_data.ld (95%) rename src/rp2_common/{pico_crt0/rp2040/platform => pico_standard_link/scripts/rp2_common}/section_no_flash_data.ld (96%) diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld deleted file mode 100644 index 19082589c..000000000 --- a/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_data.ld +++ /dev/null @@ -1,83 +0,0 @@ -SECTIONS -{ - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - . = ALIGN(4); - *(.rodata*) - *(.srodata*) - . = ALIGN(4); - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM -} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld deleted file mode 100644 index 9ffa5d163..000000000 --- a/src/rp2_common/pico_crt0/rp2350/platform/section_default_data.ld +++ /dev/null @@ -1,72 +0,0 @@ -SECTIONS -{ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ - *(.text*) - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM -} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld b/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld deleted file mode 100644 index 5658d8a4b..000000000 --- a/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_data.ld +++ /dev/null @@ -1,82 +0,0 @@ -SECTIONS -{ - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM - PROVIDE(__data_end__ = .); - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM -} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_copy_to_ram_data.ld similarity index 95% rename from src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld rename to src/rp2_common/pico_standard_link/scripts/rp2_common/section_copy_to_ram_data.ld index 325da150f..a05a00334 100644 --- a/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_data.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_copy_to_ram_data.ld @@ -8,9 +8,11 @@ SECTIONS . = ALIGN(4); *(.rodata*) + *(.srodata*) . = ALIGN(4); *(.data*) + *(.sdata*) . = ALIGN(4); *(.after_data.*) @@ -73,6 +75,8 @@ SECTIONS *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) . = ALIGN(4); __bss_end__ = .; } > RAM diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_default_data.ld similarity index 95% rename from src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld rename to src/rp2_common/pico_standard_link/scripts/rp2_common/section_default_data.ld index 27da2e947..ca2f5d7de 100644 --- a/src/rp2_common/pico_crt0/rp2040/platform/section_default_data.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_default_data.ld @@ -22,6 +22,7 @@ SECTIONS . = ALIGN(4); *(.data*) + *(.sdata*) . = ALIGN(4); *(.after_data.*) @@ -32,7 +33,6 @@ SECTIONS KEEP(*(.mutex_array)) PROVIDE_HIDDEN (__mutex_array_end = .); - . = ALIGN(4); *(.jcr) . = ALIGN(4); } > RAM AT> FLASH @@ -64,6 +64,8 @@ SECTIONS *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) . = ALIGN(4); __bss_end__ = .; } > RAM diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_no_flash_data.ld similarity index 96% rename from src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld rename to src/rp2_common/pico_standard_link/scripts/rp2_common/section_no_flash_data.ld index bdce39b44..35325db6e 100644 --- a/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_data.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/section_no_flash_data.ld @@ -7,6 +7,7 @@ SECTIONS *(.time_critical*) *(.data*) + *(.sdata*) . = ALIGN(4); *(.after_data.*) @@ -73,6 +74,8 @@ SECTIONS *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) . = ALIGN(4); __bss_end__ = .; } > RAM diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld index 0017f385b..5e86d7c0c 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld @@ -1,5 +1,5 @@ INCLUDE "platform/section_copy_to_ram_text.ld" -INCLUDE "platform/section_copy_to_ram_data.ld" +INCLUDE "rp2_common/section_copy_to_ram_data.ld" INCLUDE "rp2_common/section_heap.ld" INCLUDE "rp2_common/section_scratch.ld" INCLUDE "rp2_common/section_flash_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld index e0138db34..558ec1848 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld @@ -1,5 +1,5 @@ INCLUDE "platform/section_default_text.ld" -INCLUDE "platform/section_default_data.ld" +INCLUDE "rp2_common/section_default_data.ld" INCLUDE "rp2_common/section_heap.ld" INCLUDE "rp2_common/section_scratch.ld" INCLUDE "rp2_common/section_flash_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld index ebc062e6a..b9b3973b2 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld @@ -1,5 +1,5 @@ INCLUDE "platform/section_no_flash_text.ld" -INCLUDE "platform/section_no_flash_data.ld" +INCLUDE "rp2_common/section_no_flash_data.ld" INCLUDE "rp2_common/section_heap.ld" INCLUDE "rp2_common/section_scratch.ld" INCLUDE "rp2_common/section_end.ld" From f33d5a4a2f9b852c700a3b7c1ad13d021db3bf33 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 2 Dec 2025 17:31:49 +0000 Subject: [PATCH 055/127] Make overriding ram locations simpler --- .../pico_crt0/rp2040/memmap_blocked_ram.ld | 15 +++------------ .../rp2040/platform/default_locations.ld | 8 ++++++++ .../rp2040/platform/memory_blocked_ram.ld | 4 ---- .../pico_crt0/rp2040/platform/memory_ram.ld | 4 ---- .../rp2040/platform/memory_scratch.ld | 5 ----- .../rp2350/platform/default_locations.ld | 8 ++++++++ .../pico_crt0/rp2350/platform/memory_ram.ld | 4 ---- .../rp2350/platform/memory_scratch.ld | 5 ----- .../rp2350/platform/memory_xip_ram.ld | 4 ---- .../scripts/rp2_common/memmap_copy_to_ram.ld | 7 +++++-- .../scripts/rp2_common/memmap_default.ld | 7 +++++-- .../scripts/rp2_common/memmap_no_flash.ld | 7 +++++-- .../scripts/rp2_common/memory_ram.ld | 4 ++++ .../scripts/rp2_common/memory_scratch.ld | 5 +++++ .../scripts/rp2_common/memory_xip_ram.ld | 4 ++++ test/kitchen_sink/CMakeLists.txt | 15 ++++++++------- test/kitchen_sink/memmap_custom.ld | 18 ------------------ 17 files changed, 55 insertions(+), 69 deletions(-) create mode 100644 src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/platform/memory_blocked_ram.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/platform/memory_ram.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/platform/memory_scratch.ld create mode 100644 src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/platform/memory_ram.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/platform/memory_scratch.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/platform/memory_xip_ram.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memory_ram.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memory_scratch.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memory_xip_ram.ld delete mode 100644 test/kitchen_sink/memmap_custom.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld index 330e9bde3..a4a528950 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld @@ -1,13 +1,4 @@ -/* Include memory regions used */ -INCLUDE "rp2_common/memory_flash.ld" -INCLUDE "platform/memory_blocked_ram.ld" -INCLUDE "platform/memory_scratch.ld" +/* Use blocked ram */ +RAM_ORIGIN = 0x21000000; -/* Include aliases for storage memory regions */ -INCLUDE "rp2_common/memory_aliases_default.ld" - -/* Define entry point symbol */ -ENTRY(_entry_point) - -/* Include default sections */ -INCLUDE "rp2_common/sections_default.ld" +INCLUDE "memmap_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld b/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld new file mode 100644 index 000000000..684418b73 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld @@ -0,0 +1,8 @@ +RAM_ORIGIN = DEFINED(RAM_ORIGIN) ? RAM_ORIGIN : 0x20000000; +RAM_LENGTH = DEFINED(RAM_LENGTH) ? RAM_LENGTH : 256k; +SCRATCH_X_ORIGIN = DEFINED(SCRATCH_X_ORIGIN) ? SCRATCH_X_ORIGIN : 0x20040000; +SCRATCH_X_LENGTH = DEFINED(SCRATCH_X_LENGTH) ? SCRATCH_X_LENGTH : 4k; +SCRATCH_Y_ORIGIN = DEFINED(SCRATCH_Y_ORIGIN) ? SCRATCH_Y_ORIGIN : 0x20041000; +SCRATCH_Y_LENGTH = DEFINED(SCRATCH_Y_LENGTH) ? SCRATCH_Y_LENGTH : 4k; +XIP_RAM_ORIGIN = DEFINED(XIP_RAM_ORIGIN) ? XIP_RAM_ORIGIN : 0x15000000; +XIP_RAM_LENGTH = DEFINED(XIP_RAM_LENGTH) ? XIP_RAM_LENGTH : 16k; diff --git a/src/rp2_common/pico_crt0/rp2040/platform/memory_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/platform/memory_blocked_ram.ld deleted file mode 100644 index 57cbad6b7..000000000 --- a/src/rp2_common/pico_crt0/rp2040/platform/memory_blocked_ram.ld +++ /dev/null @@ -1,4 +0,0 @@ -MEMORY -{ - RAM(rwx) : ORIGIN = 0x21000000, LENGTH = 256k -} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/memory_ram.ld b/src/rp2_common/pico_crt0/rp2040/platform/memory_ram.ld deleted file mode 100644 index 1e1515dd3..000000000 --- a/src/rp2_common/pico_crt0/rp2040/platform/memory_ram.ld +++ /dev/null @@ -1,4 +0,0 @@ -MEMORY -{ - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k -} diff --git a/src/rp2_common/pico_crt0/rp2040/platform/memory_scratch.ld b/src/rp2_common/pico_crt0/rp2040/platform/memory_scratch.ld deleted file mode 100644 index a4b982b92..000000000 --- a/src/rp2_common/pico_crt0/rp2040/platform/memory_scratch.ld +++ /dev/null @@ -1,5 +0,0 @@ -MEMORY -{ - SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k -} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld b/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld new file mode 100644 index 000000000..0b1611d40 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld @@ -0,0 +1,8 @@ +RAM_ORIGIN = DEFINED(RAM_ORIGIN) ? RAM_ORIGIN : 0x20000000; +RAM_LENGTH = DEFINED(RAM_LENGTH) ? RAM_LENGTH : 512k; +SCRATCH_X_ORIGIN = DEFINED(SCRATCH_X_ORIGIN) ? SCRATCH_X_ORIGIN : 0x20080000; +SCRATCH_X_LENGTH = DEFINED(SCRATCH_X_LENGTH) ? SCRATCH_X_LENGTH : 4k; +SCRATCH_Y_ORIGIN = DEFINED(SCRATCH_Y_ORIGIN) ? SCRATCH_Y_ORIGIN : 0x20081000; +SCRATCH_Y_LENGTH = DEFINED(SCRATCH_Y_LENGTH) ? SCRATCH_Y_LENGTH : 4k; +XIP_RAM_ORIGIN = DEFINED(XIP_RAM_ORIGIN) ? XIP_RAM_ORIGIN : 0x13FFC000; +XIP_RAM_LENGTH = DEFINED(XIP_RAM_LENGTH) ? XIP_RAM_LENGTH : 16k; diff --git a/src/rp2_common/pico_crt0/rp2350/platform/memory_ram.ld b/src/rp2_common/pico_crt0/rp2350/platform/memory_ram.ld deleted file mode 100644 index 434cdab97..000000000 --- a/src/rp2_common/pico_crt0/rp2350/platform/memory_ram.ld +++ /dev/null @@ -1,4 +0,0 @@ -MEMORY -{ - RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k -} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/memory_scratch.ld b/src/rp2_common/pico_crt0/rp2350/platform/memory_scratch.ld deleted file mode 100644 index 246bbf050..000000000 --- a/src/rp2_common/pico_crt0/rp2350/platform/memory_scratch.ld +++ /dev/null @@ -1,5 +0,0 @@ -MEMORY -{ - SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k - SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k -} diff --git a/src/rp2_common/pico_crt0/rp2350/platform/memory_xip_ram.ld b/src/rp2_common/pico_crt0/rp2350/platform/memory_xip_ram.ld deleted file mode 100644 index e94479b54..000000000 --- a/src/rp2_common/pico_crt0/rp2350/platform/memory_xip_ram.ld +++ /dev/null @@ -1,4 +0,0 @@ -MEMORY -{ - XIP_RAM(rwx) : ORIGIN = 0x13FFC000, LENGTH = 16k -} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld index 88127d894..12b7c85ab 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld @@ -1,7 +1,10 @@ +/* Include platform memory locations */ +INCLUDE "platform/default_locations.ld" + /* Include memory regions used */ INCLUDE "rp2_common/memory_flash.ld" -INCLUDE "platform/memory_ram.ld" -INCLUDE "platform/memory_scratch.ld" +INCLUDE "rp2_common/memory_ram.ld" +INCLUDE "rp2_common/memory_scratch.ld" /* Include aliases for storage memory regions */ INCLUDE "rp2_common/memory_aliases_default.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld index a8de400d9..6b1ccf827 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld @@ -1,7 +1,10 @@ +/* Include platform memory locations */ +INCLUDE "platform/default_locations.ld" + /* Include memory regions used */ INCLUDE "rp2_common/memory_flash.ld" -INCLUDE "platform/memory_ram.ld" -INCLUDE "platform/memory_scratch.ld" +INCLUDE "rp2_common/memory_ram.ld" +INCLUDE "rp2_common/memory_scratch.ld" /* Include aliases for storage memory regions */ INCLUDE "rp2_common/memory_aliases_default.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld index 61ae84dc7..8fb49e6bd 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld @@ -1,6 +1,9 @@ +/* Include platform memory locations */ +INCLUDE "platform/default_locations.ld" + /* Include memory regions used */ -INCLUDE "platform/memory_ram.ld" -INCLUDE "platform/memory_scratch.ld" +INCLUDE "rp2_common/memory_ram.ld" +INCLUDE "rp2_common/memory_scratch.ld" /* Include aliases for no_flash storage memory regions (alias to themselves) */ INCLUDE "rp2_common/memory_aliases_no_flash.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_ram.ld new file mode 100644 index 000000000..2b8a88a06 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_ram.ld @@ -0,0 +1,4 @@ +MEMORY +{ + RAM(rwx) : ORIGIN = RAM_ORIGIN, LENGTH = RAM_LENGTH +} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_scratch.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_scratch.ld new file mode 100644 index 000000000..7ba5d2172 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_scratch.ld @@ -0,0 +1,5 @@ +MEMORY +{ + SCRATCH_X(rwx) : ORIGIN = SCRATCH_X_ORIGIN, LENGTH = SCRATCH_X_LENGTH + SCRATCH_Y(rwx) : ORIGIN = SCRATCH_Y_ORIGIN, LENGTH = SCRATCH_Y_LENGTH +} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_xip_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_xip_ram.ld new file mode 100644 index 000000000..636e90137 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_xip_ram.ld @@ -0,0 +1,4 @@ +MEMORY +{ + XIP_RAM(rwx) : ORIGIN = XIP_RAM_ORIGIN, LENGTH = XIP_RAM_LENGTH +} diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt index 85a94fa01..88d0806ee 100644 --- a/test/kitchen_sink/CMakeLists.txt +++ b/test/kitchen_sink/CMakeLists.txt @@ -216,13 +216,14 @@ if (NOT KITCHEN_SINK_NO_BINARY_TYPE_VARIANTS) target_compile_definitions(kitchen_sink_blocked_ram PRIVATE KITCHEN_SINK_ID="blocked-ram binary") endif() - add_executable(kitchen_sink_memmap_custom ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) - # Have heap start from 0x20030000, and custom linker script - pico_set_linker_script(kitchen_sink_memmap_custom ${CMAKE_CURRENT_LIST_DIR}/memmap_custom.ld) - pico_set_linker_script_var(kitchen_sink_memmap_custom HEAP_LOC 0x20030000) - target_link_libraries(kitchen_sink_memmap_custom kitchen_sink_libs kitchen_sink_options) - pico_add_extra_outputs(kitchen_sink_memmap_custom) - target_compile_definitions(kitchen_sink_memmap_custom PRIVATE KITCHEN_SINK_ID="custom memmap binary") + add_executable(kitchen_sink_ram_custom ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) + # Have ram start from 0x20020000 length 128k, and heap start from 0x20030000 + pico_set_linker_script_var(kitchen_sink_ram_custom RAM_ORIGIN 0x20020000) + pico_set_linker_script_var(kitchen_sink_ram_custom RAM_LENGTH 128k) + pico_set_linker_script_var(kitchen_sink_ram_custom HEAP_LOC 0x20030000) + target_link_libraries(kitchen_sink_ram_custom kitchen_sink_libs kitchen_sink_options) + pico_add_extra_outputs(kitchen_sink_ram_custom) + target_compile_definitions(kitchen_sink_ram_custom PRIVATE KITCHEN_SINK_ID="custom ram binary") endif() add_executable(kitchen_sink_cpp ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_cpp.cpp) diff --git a/test/kitchen_sink/memmap_custom.ld b/test/kitchen_sink/memmap_custom.ld deleted file mode 100644 index 7fe2098f1..000000000 --- a/test/kitchen_sink/memmap_custom.ld +++ /dev/null @@ -1,18 +0,0 @@ -/* Include memory regions used */ -INCLUDE "rp2_common/memory_flash.ld" -INCLUDE "platform/memory_scratch.ld" - -/* Only use 128k of SRAM, starting at 0x20020000 */ -MEMORY -{ - RAM(rwx) : ORIGIN = 0x20020000, LENGTH = 128k -} - -/* Include aliases for storage memory regions */ -INCLUDE "rp2_common/memory_aliases_default.ld" - -/* Define entry point symbol */ -ENTRY(_entry_point) - -/* Include default sections */ -INCLUDE "rp2_common/sections_default.ld" From 12c92b1817e26892a899cc86672319a7ee889f4d Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 4 Dec 2025 10:14:26 +0000 Subject: [PATCH 056/127] Make it possible to reference default locations in pico_set_linker_script_var variables Means that CMake doesn't need to know the default memory addresses for different platforms --- .../rp2040/platform/default_locations.ld | 16 ++++++++-------- .../rp2350/platform/default_locations.ld | 16 ++++++++-------- src/rp2_common/pico_standard_link/CMakeLists.txt | 3 +++ .../scripts/rp2_common/memmap_copy_to_ram.ld | 2 +- .../scripts/rp2_common/memmap_default.ld | 2 +- .../scripts/rp2_common/memmap_no_flash.ld | 2 +- .../scripts/rp2_common/set_memory_locations.ld | 8 ++++++++ 7 files changed, 30 insertions(+), 19 deletions(-) create mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/set_memory_locations.ld diff --git a/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld b/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld index 684418b73..03144ea07 100644 --- a/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld +++ b/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld @@ -1,8 +1,8 @@ -RAM_ORIGIN = DEFINED(RAM_ORIGIN) ? RAM_ORIGIN : 0x20000000; -RAM_LENGTH = DEFINED(RAM_LENGTH) ? RAM_LENGTH : 256k; -SCRATCH_X_ORIGIN = DEFINED(SCRATCH_X_ORIGIN) ? SCRATCH_X_ORIGIN : 0x20040000; -SCRATCH_X_LENGTH = DEFINED(SCRATCH_X_LENGTH) ? SCRATCH_X_LENGTH : 4k; -SCRATCH_Y_ORIGIN = DEFINED(SCRATCH_Y_ORIGIN) ? SCRATCH_Y_ORIGIN : 0x20041000; -SCRATCH_Y_LENGTH = DEFINED(SCRATCH_Y_LENGTH) ? SCRATCH_Y_LENGTH : 4k; -XIP_RAM_ORIGIN = DEFINED(XIP_RAM_ORIGIN) ? XIP_RAM_ORIGIN : 0x15000000; -XIP_RAM_LENGTH = DEFINED(XIP_RAM_LENGTH) ? XIP_RAM_LENGTH : 16k; +RAM_ORIGIN_DEFAULT = 0x20000000; +RAM_LENGTH_DEFAULT = 256k; +SCRATCH_X_ORIGIN_DEFAULT = 0x20040000; +SCRATCH_X_LENGTH_DEFAULT = 4k; +SCRATCH_Y_ORIGIN_DEFAULT = 0x20041000; +SCRATCH_Y_LENGTH_DEFAULT = 4k; +XIP_RAM_ORIGIN_DEFAULT = 0x15000000; +XIP_RAM_LENGTH_DEFAULT = 16k; diff --git a/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld b/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld index 0b1611d40..15ddc7374 100644 --- a/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld +++ b/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld @@ -1,8 +1,8 @@ -RAM_ORIGIN = DEFINED(RAM_ORIGIN) ? RAM_ORIGIN : 0x20000000; -RAM_LENGTH = DEFINED(RAM_LENGTH) ? RAM_LENGTH : 512k; -SCRATCH_X_ORIGIN = DEFINED(SCRATCH_X_ORIGIN) ? SCRATCH_X_ORIGIN : 0x20080000; -SCRATCH_X_LENGTH = DEFINED(SCRATCH_X_LENGTH) ? SCRATCH_X_LENGTH : 4k; -SCRATCH_Y_ORIGIN = DEFINED(SCRATCH_Y_ORIGIN) ? SCRATCH_Y_ORIGIN : 0x20081000; -SCRATCH_Y_LENGTH = DEFINED(SCRATCH_Y_LENGTH) ? SCRATCH_Y_LENGTH : 4k; -XIP_RAM_ORIGIN = DEFINED(XIP_RAM_ORIGIN) ? XIP_RAM_ORIGIN : 0x13FFC000; -XIP_RAM_LENGTH = DEFINED(XIP_RAM_LENGTH) ? XIP_RAM_LENGTH : 16k; +RAM_ORIGIN_DEFAULT = 0x20000000; +RAM_LENGTH_DEFAULT = 512k; +SCRATCH_X_ORIGIN_DEFAULT = 0x20080000; +SCRATCH_X_LENGTH_DEFAULT = 4k; +SCRATCH_Y_ORIGIN_DEFAULT = 0x20081000; +SCRATCH_Y_LENGTH_DEFAULT = 4k; +XIP_RAM_ORIGIN_DEFAULT = 0x13FFC000; +XIP_RAM_LENGTH_DEFAULT = 16k; diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index 8fc240346..69f5751ef 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -140,6 +140,9 @@ if (NOT TARGET pico_standard_link) target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}") target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_CURRENT_LIST_DIR}/scripts") + # add default locations script, so they can be referenced by pico_set_linker_script_var variables + target_link_options(pico_standard_link INTERFACE "LINKER:--script=${PICO_LINKER_SCRIPT_PATH}/platform/default_locations.ld") + # add variables set by pico_set_linker_script_var function target_link_options(pico_standard_link INTERFACE "LINKER:$,,>") diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld index 12b7c85ab..1cb8f7597 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld @@ -1,5 +1,5 @@ /* Include platform memory locations */ -INCLUDE "platform/default_locations.ld" +INCLUDE "rp2_common/set_memory_locations.ld" /* Include memory regions used */ INCLUDE "rp2_common/memory_flash.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld index 6b1ccf827..2c8f3ffa1 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld @@ -1,5 +1,5 @@ /* Include platform memory locations */ -INCLUDE "platform/default_locations.ld" +INCLUDE "rp2_common/set_memory_locations.ld" /* Include memory regions used */ INCLUDE "rp2_common/memory_flash.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld index 8fb49e6bd..2e3695ef9 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld @@ -1,5 +1,5 @@ /* Include platform memory locations */ -INCLUDE "platform/default_locations.ld" +INCLUDE "rp2_common/set_memory_locations.ld" /* Include memory regions used */ INCLUDE "rp2_common/memory_ram.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/set_memory_locations.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/set_memory_locations.ld new file mode 100644 index 000000000..a9110eb59 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/set_memory_locations.ld @@ -0,0 +1,8 @@ +RAM_ORIGIN = DEFINED(RAM_ORIGIN) ? RAM_ORIGIN : RAM_ORIGIN_DEFAULT; +RAM_LENGTH = DEFINED(RAM_LENGTH) ? RAM_LENGTH : RAM_LENGTH_DEFAULT; +SCRATCH_X_ORIGIN = DEFINED(SCRATCH_X_ORIGIN) ? SCRATCH_X_ORIGIN : SCRATCH_X_ORIGIN_DEFAULT; +SCRATCH_X_LENGTH = DEFINED(SCRATCH_X_LENGTH) ? SCRATCH_X_LENGTH : SCRATCH_X_LENGTH_DEFAULT; +SCRATCH_Y_ORIGIN = DEFINED(SCRATCH_Y_ORIGIN) ? SCRATCH_Y_ORIGIN : SCRATCH_Y_ORIGIN_DEFAULT; +SCRATCH_Y_LENGTH = DEFINED(SCRATCH_Y_LENGTH) ? SCRATCH_Y_LENGTH : SCRATCH_Y_LENGTH_DEFAULT; +XIP_RAM_ORIGIN = DEFINED(XIP_RAM_ORIGIN) ? XIP_RAM_ORIGIN : XIP_RAM_ORIGIN_DEFAULT; +XIP_RAM_LENGTH = DEFINED(XIP_RAM_LENGTH) ? XIP_RAM_LENGTH : XIP_RAM_LENGTH_DEFAULT; From 1bcfac30c13149e4cab262e2c246d5f5471cdc35 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 11 Feb 2026 18:57:12 +0000 Subject: [PATCH 057/127] Add pico_add_linker_script_override_path to make overriding individual files easier Restructured so that it includes the platform-specific files before common ones, so common ones can be overridden --- .../pico_crt0/rp2040/memmap_blocked_ram.ld | 2 +- .../default_locations.ld | 0 .../section_copy_to_ram_text.ld | 0 .../section_default_text.ld | 0 .../section_no_flash_text.ld | 0 .../section_platform_end.ld | 0 .../default_locations.ld | 0 .../section_copy_to_ram_text.ld | 0 .../section_default_text.ld | 0 .../section_no_flash_text.ld | 0 .../section_platform_end.ld | 0 .../pico_standard_link/CMakeLists.txt | 27 ++++++++++++++++--- .../memory_aliases_default.ld | 0 .../memory_aliases_no_flash.ld | 0 .../scripts/{rp2_common => }/memory_flash.ld | 0 .../scripts/{rp2_common => }/memory_ram.ld | 0 .../{rp2_common => }/memory_scratch.ld | 0 .../{rp2_common => }/memory_xip_ram.ld | 0 .../scripts/rp2_common/memmap_copy_to_ram.ld | 12 ++++----- .../scripts/rp2_common/memmap_default.ld | 12 ++++----- .../scripts/rp2_common/memmap_no_flash.ld | 10 +++---- .../rp2_common/sections_copy_to_ram.ld | 7 ----- .../scripts/rp2_common/sections_default.ld | 7 ----- .../scripts/rp2_common/sections_no_flash.ld | 6 ----- .../section_copy_to_ram_data.ld | 0 .../{rp2_common => }/section_default_data.ld | 0 .../scripts/{rp2_common => }/section_end.ld | 0 .../{rp2_common => }/section_flash_end.ld | 0 .../scripts/{rp2_common => }/section_heap.ld | 0 .../{rp2_common => }/section_no_flash_data.ld | 0 .../{rp2_common => }/section_scratch.ld | 0 .../scripts/sections_copy_to_ram.ld | 7 +++++ .../scripts/sections_default.ld | 7 +++++ .../scripts/sections_no_flash.ld | 6 +++++ .../{rp2_common => }/set_memory_locations.ld | 0 test/kitchen_sink/CMakeLists.txt | 6 +++++ test/kitchen_sink/kitchen_sink.c | 12 +++++++++ .../sections_default.ld | 19 +++++++++++++ 38 files changed, 99 insertions(+), 41 deletions(-) rename src/rp2_common/pico_crt0/rp2040/{platform => scripts}/default_locations.ld (100%) rename src/rp2_common/pico_crt0/rp2040/{platform => scripts}/section_copy_to_ram_text.ld (100%) rename src/rp2_common/pico_crt0/rp2040/{platform => scripts}/section_default_text.ld (100%) rename src/rp2_common/pico_crt0/rp2040/{platform => scripts}/section_no_flash_text.ld (100%) rename src/rp2_common/pico_crt0/rp2040/{platform => scripts}/section_platform_end.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{platform => scripts}/default_locations.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{platform => scripts}/section_copy_to_ram_text.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{platform => scripts}/section_default_text.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{platform => scripts}/section_no_flash_text.ld (100%) rename src/rp2_common/pico_crt0/rp2350/{platform => scripts}/section_platform_end.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memory_aliases_default.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memory_aliases_no_flash.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memory_flash.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memory_ram.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memory_scratch.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/memory_xip_ram.ld (100%) delete mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_copy_to_ram_data.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_default_data.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_end.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_flash_end.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_heap.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_no_flash_data.ld (100%) rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/section_scratch.ld (100%) create mode 100644 src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/sections_default.ld create mode 100644 src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld rename src/rp2_common/pico_standard_link/scripts/{rp2_common => }/set_memory_locations.ld (100%) create mode 100644 test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.ld diff --git a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld index a4a528950..15a98861d 100644 --- a/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld +++ b/src/rp2_common/pico_crt0/rp2040/memmap_blocked_ram.ld @@ -1,4 +1,4 @@ /* Use blocked ram */ RAM_ORIGIN = 0x21000000; -INCLUDE "memmap_default.ld" +INCLUDE "rp2_common/memmap_default.ld" diff --git a/src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld b/src/rp2_common/pico_crt0/rp2040/scripts/default_locations.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/platform/default_locations.ld rename to src/rp2_common/pico_crt0/rp2040/scripts/default_locations.ld diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_text.ld b/src/rp2_common/pico_crt0/rp2040/scripts/section_copy_to_ram_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/platform/section_copy_to_ram_text.ld rename to src/rp2_common/pico_crt0/rp2040/scripts/section_copy_to_ram_text.ld diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_default_text.ld b/src/rp2_common/pico_crt0/rp2040/scripts/section_default_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/platform/section_default_text.ld rename to src/rp2_common/pico_crt0/rp2040/scripts/section_default_text.ld diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_text.ld b/src/rp2_common/pico_crt0/rp2040/scripts/section_no_flash_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/platform/section_no_flash_text.ld rename to src/rp2_common/pico_crt0/rp2040/scripts/section_no_flash_text.ld diff --git a/src/rp2_common/pico_crt0/rp2040/platform/section_platform_end.ld b/src/rp2_common/pico_crt0/rp2040/scripts/section_platform_end.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2040/platform/section_platform_end.ld rename to src/rp2_common/pico_crt0/rp2040/scripts/section_platform_end.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld b/src/rp2_common/pico_crt0/rp2350/scripts/default_locations.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/platform/default_locations.ld rename to src/rp2_common/pico_crt0/rp2350/scripts/default_locations.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_text.ld b/src/rp2_common/pico_crt0/rp2350/scripts/section_copy_to_ram_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/platform/section_copy_to_ram_text.ld rename to src/rp2_common/pico_crt0/rp2350/scripts/section_copy_to_ram_text.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_default_text.ld b/src/rp2_common/pico_crt0/rp2350/scripts/section_default_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/platform/section_default_text.ld rename to src/rp2_common/pico_crt0/rp2350/scripts/section_default_text.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_text.ld b/src/rp2_common/pico_crt0/rp2350/scripts/section_no_flash_text.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/platform/section_no_flash_text.ld rename to src/rp2_common/pico_crt0/rp2350/scripts/section_no_flash_text.ld diff --git a/src/rp2_common/pico_crt0/rp2350/platform/section_platform_end.ld b/src/rp2_common/pico_crt0/rp2350/scripts/section_platform_end.ld similarity index 100% rename from src/rp2_common/pico_crt0/rp2350/platform/section_platform_end.ld rename to src/rp2_common/pico_crt0/rp2350/scripts/section_platform_end.ld diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index 69f5751ef..24978fe68 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -73,12 +73,33 @@ if (NOT TARGET pico_standard_link) # pico_set_linker_script_var(TARGET NAME VALUE) # \brief\ Set the linker script for the target # - # \param\ NAME Name of varAible to set + # \param\ NAME Name of variable to set # \param\ VALUE Value of variable to set function(pico_set_linker_script_var TARGET NAME VALUE) set_property(TARGET ${TARGET} APPEND PROPERTY PICO_TARGET_LINKER_SCRIPT_VARS "--defsym=${NAME}=${VALUE}") endfunction() + # pico_add_linker_script_override_path(TARGET PATH) + # \brief\ Add an override linker script path to the target + # + # This can be used to override default linker script files with custom versions. + # + # For example, to use custom files in ${CMAKE_CURRENT_LIST_DIR}/extra_scripts instead of the default ones, + # call pico_add_linker_script_override_path(TARGET ${CMAKE_CURRENT_LIST_DIR}/extra_scripts). This will + # include the custom files first, overriding the default ones. + # + # Must be called before target_link_libraries, otherwise it will not override the default linker scripts. + # + # \param\ TARGET The target to add the linker script override path to + # \param\ PATH The path containing the overriding linker scripts + function(pico_add_linker_script_override_path TARGET PATH) + get_target_property(OUT ${TARGET} LINK_LIBRARIES) + if (OUT) + message(WARNING "pico_add_linker_script_override_path does not work when called after target_link_libraries") + endif() + target_link_options(${TARGET} PRIVATE "LINKER:-L${PATH}") + endfunction() + # pico_set_binary_type(TARGET TYPE) # \brief\ Set the binary type for the target # @@ -137,11 +158,11 @@ if (NOT TARGET pico_standard_link) target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_BINARY_DIR}") # add include path for main linker script sections - target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}") + target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}/scripts") target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_CURRENT_LIST_DIR}/scripts") # add default locations script, so they can be referenced by pico_set_linker_script_var variables - target_link_options(pico_standard_link INTERFACE "LINKER:--script=${PICO_LINKER_SCRIPT_PATH}/platform/default_locations.ld") + target_link_options(pico_standard_link INTERFACE "LINKER:--script=${PICO_LINKER_SCRIPT_PATH}/scripts/default_locations.ld") # add variables set by pico_set_linker_script_var function target_link_options(pico_standard_link INTERFACE "LINKER:$,,>") diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_default.ld b/src/rp2_common/pico_standard_link/scripts/memory_aliases_default.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_default.ld rename to src/rp2_common/pico_standard_link/scripts/memory_aliases_default.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/memory_aliases_no_flash.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memory_aliases_no_flash.ld rename to src/rp2_common/pico_standard_link/scripts/memory_aliases_no_flash.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_flash.ld b/src/rp2_common/pico_standard_link/scripts/memory_flash.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memory_flash.ld rename to src/rp2_common/pico_standard_link/scripts/memory_flash.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_ram.ld b/src/rp2_common/pico_standard_link/scripts/memory_ram.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memory_ram.ld rename to src/rp2_common/pico_standard_link/scripts/memory_ram.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_scratch.ld b/src/rp2_common/pico_standard_link/scripts/memory_scratch.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memory_scratch.ld rename to src/rp2_common/pico_standard_link/scripts/memory_scratch.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memory_xip_ram.ld b/src/rp2_common/pico_standard_link/scripts/memory_xip_ram.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/memory_xip_ram.ld rename to src/rp2_common/pico_standard_link/scripts/memory_xip_ram.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld index 1cb8f7597..eb2c5ffd9 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld @@ -1,16 +1,16 @@ /* Include platform memory locations */ -INCLUDE "rp2_common/set_memory_locations.ld" +INCLUDE "set_memory_locations.ld" /* Include memory regions used */ -INCLUDE "rp2_common/memory_flash.ld" -INCLUDE "rp2_common/memory_ram.ld" -INCLUDE "rp2_common/memory_scratch.ld" +INCLUDE "memory_flash.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" /* Include aliases for storage memory regions */ -INCLUDE "rp2_common/memory_aliases_default.ld" +INCLUDE "memory_aliases_default.ld" /* Define entry point symbol */ ENTRY(_entry_point) /* Include default sections */ -INCLUDE "rp2_common/sections_copy_to_ram.ld" +INCLUDE "sections_copy_to_ram.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld index 2c8f3ffa1..04acbefbb 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld @@ -1,16 +1,16 @@ /* Include platform memory locations */ -INCLUDE "rp2_common/set_memory_locations.ld" +INCLUDE "set_memory_locations.ld" /* Include memory regions used */ -INCLUDE "rp2_common/memory_flash.ld" -INCLUDE "rp2_common/memory_ram.ld" -INCLUDE "rp2_common/memory_scratch.ld" +INCLUDE "memory_flash.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" /* Include aliases for storage memory regions */ -INCLUDE "rp2_common/memory_aliases_default.ld" +INCLUDE "memory_aliases_default.ld" /* Define entry point symbol */ ENTRY(_entry_point) /* Include default sections */ -INCLUDE "rp2_common/sections_default.ld" +INCLUDE "sections_default.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld index 2e3695ef9..958915a71 100644 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld +++ b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld @@ -1,15 +1,15 @@ /* Include platform memory locations */ -INCLUDE "rp2_common/set_memory_locations.ld" +INCLUDE "set_memory_locations.ld" /* Include memory regions used */ -INCLUDE "rp2_common/memory_ram.ld" -INCLUDE "rp2_common/memory_scratch.ld" +INCLUDE "memory_ram.ld" +INCLUDE "memory_scratch.ld" /* Include aliases for no_flash storage memory regions (alias to themselves) */ -INCLUDE "rp2_common/memory_aliases_no_flash.ld" +INCLUDE "memory_aliases_no_flash.ld" /* Define entry point symbol */ ENTRY(_entry_point) /* Include no_flash sections */ -INCLUDE "rp2_common/sections_no_flash.ld" +INCLUDE "sections_no_flash.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld deleted file mode 100644 index 5e86d7c0c..000000000 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_copy_to_ram.ld +++ /dev/null @@ -1,7 +0,0 @@ -INCLUDE "platform/section_copy_to_ram_text.ld" -INCLUDE "rp2_common/section_copy_to_ram_data.ld" -INCLUDE "rp2_common/section_heap.ld" -INCLUDE "rp2_common/section_scratch.ld" -INCLUDE "rp2_common/section_flash_end.ld" -INCLUDE "rp2_common/section_end.ld" -INCLUDE "platform/section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld deleted file mode 100644 index 558ec1848..000000000 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_default.ld +++ /dev/null @@ -1,7 +0,0 @@ -INCLUDE "platform/section_default_text.ld" -INCLUDE "rp2_common/section_default_data.ld" -INCLUDE "rp2_common/section_heap.ld" -INCLUDE "rp2_common/section_scratch.ld" -INCLUDE "rp2_common/section_flash_end.ld" -INCLUDE "rp2_common/section_end.ld" -INCLUDE "platform/section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld deleted file mode 100644 index b9b3973b2..000000000 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/sections_no_flash.ld +++ /dev/null @@ -1,6 +0,0 @@ -INCLUDE "platform/section_no_flash_text.ld" -INCLUDE "rp2_common/section_no_flash_data.ld" -INCLUDE "rp2_common/section_heap.ld" -INCLUDE "rp2_common/section_scratch.ld" -INCLUDE "rp2_common/section_end.ld" -INCLUDE "platform/section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_copy_to_ram_data.ld b/src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_data.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_copy_to_ram_data.ld rename to src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_data.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_default_data.ld b/src/rp2_common/pico_standard_link/scripts/section_default_data.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_default_data.ld rename to src/rp2_common/pico_standard_link/scripts/section_default_data.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_end.ld b/src/rp2_common/pico_standard_link/scripts/section_end.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_end.ld rename to src/rp2_common/pico_standard_link/scripts/section_end.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_flash_end.ld b/src/rp2_common/pico_standard_link/scripts/section_flash_end.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_flash_end.ld rename to src/rp2_common/pico_standard_link/scripts/section_flash_end.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_heap.ld b/src/rp2_common/pico_standard_link/scripts/section_heap.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_heap.ld rename to src/rp2_common/pico_standard_link/scripts/section_heap.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_no_flash_data.ld b/src/rp2_common/pico_standard_link/scripts/section_no_flash_data.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_no_flash_data.ld rename to src/rp2_common/pico_standard_link/scripts/section_no_flash_data.ld diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/section_scratch.ld b/src/rp2_common/pico_standard_link/scripts/section_scratch.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/section_scratch.ld rename to src/rp2_common/pico_standard_link/scripts/section_scratch.ld diff --git a/src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld new file mode 100644 index 000000000..fe7caf546 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld @@ -0,0 +1,7 @@ +INCLUDE "section_copy_to_ram_text.ld" +INCLUDE "section_copy_to_ram_data.ld" +INCLUDE "section_heap.ld" +INCLUDE "section_scratch.ld" +INCLUDE "section_flash_end.ld" +INCLUDE "section_end.ld" +INCLUDE "section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/sections_default.ld b/src/rp2_common/pico_standard_link/scripts/sections_default.ld new file mode 100644 index 000000000..f22558a9f --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/sections_default.ld @@ -0,0 +1,7 @@ +INCLUDE "section_default_text.ld" +INCLUDE "section_default_data.ld" +INCLUDE "section_heap.ld" +INCLUDE "section_scratch.ld" +INCLUDE "section_flash_end.ld" +INCLUDE "section_end.ld" +INCLUDE "section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld new file mode 100644 index 000000000..77bad234e --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld @@ -0,0 +1,6 @@ +INCLUDE "section_no_flash_text.ld" +INCLUDE "section_no_flash_data.ld" +INCLUDE "section_heap.ld" +INCLUDE "section_scratch.ld" +INCLUDE "section_end.ld" +INCLUDE "section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/set_memory_locations.ld b/src/rp2_common/pico_standard_link/scripts/set_memory_locations.ld similarity index 100% rename from src/rp2_common/pico_standard_link/scripts/rp2_common/set_memory_locations.ld rename to src/rp2_common/pico_standard_link/scripts/set_memory_locations.ld diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt index 88d0806ee..acf573eab 100644 --- a/test/kitchen_sink/CMakeLists.txt +++ b/test/kitchen_sink/CMakeLists.txt @@ -224,6 +224,12 @@ if (NOT KITCHEN_SINK_NO_BINARY_TYPE_VARIANTS) target_link_libraries(kitchen_sink_ram_custom kitchen_sink_libs kitchen_sink_options) pico_add_extra_outputs(kitchen_sink_ram_custom) target_compile_definitions(kitchen_sink_ram_custom PRIVATE KITCHEN_SINK_ID="custom ram binary") + + add_executable(kitchen_sink_ram_section ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) + pico_add_linker_script_override_path(kitchen_sink_ram_section ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_ram_section_scripts) + target_link_libraries(kitchen_sink_ram_section kitchen_sink_libs kitchen_sink_options) + pico_add_extra_outputs(kitchen_sink_ram_section) + target_compile_definitions(kitchen_sink_ram_section PRIVATE KITCHEN_SINK_ID="ram section binary" EXTRA_DATA_SECTION=1) endif() add_executable(kitchen_sink_cpp ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_cpp.cpp) diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index 0ba4b6850..97ea8104d 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -113,6 +113,18 @@ int main(void) { } #endif +#ifdef EXTRA_DATA_SECTION + static int extra_data __attribute__((section(".extra_data"))) = 12345678; + printf("extra_data before load = %d\n", extra_data); + + extern uint32_t __extra_data_source__; + extern uint32_t __extra_data_start__; + extern uint32_t __extra_data_end__; + uint32_t stored_words = (uint32_t)(&__extra_data_end__ - &__extra_data_start__); + memcpy(&__extra_data_start__, &__extra_data_source__, 4 * stored_words); + + printf("extra_data after load = %d\n", extra_data); +#endif #ifndef __riscv // this should compile as we are Cortex M0+ pico_default_asm ("SVC #3"); diff --git a/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.ld b/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.ld new file mode 100644 index 000000000..9ffef1a28 --- /dev/null +++ b/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.ld @@ -0,0 +1,19 @@ +INCLUDE "section_default_text.ld" +INCLUDE "section_default_data.ld" + +SECTIONS +{ + .extra_data : { + __extra_data_start__ = .; + *(.extra_data*) + . = ALIGN(4); + __extra_data_end__ = .; + } > RAM AT> RAM_STORE + __extra_data_source__ = LOADADDR(.extra_data); +} + +INCLUDE "section_heap.ld" +INCLUDE "section_scratch.ld" +INCLUDE "section_flash_end.ld" +INCLUDE "section_end.ld" +INCLUDE "section_platform_end.ld" \ No newline at end of file From 609e666f22d63bdd443fc02eb5e85d5bd7e2aaaf Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 26 Feb 2026 11:58:34 +0000 Subject: [PATCH 058/127] Add simple overlay demo --- test/kitchen_sink/CMakeLists.txt | 9 +++++++ test/kitchen_sink/kitchen_sink.c | 24 +++++++++++++++++++ .../sections_default.ld | 24 +++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.ld diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt index acf573eab..7e6f7a41d 100644 --- a/test/kitchen_sink/CMakeLists.txt +++ b/test/kitchen_sink/CMakeLists.txt @@ -230,6 +230,15 @@ if (NOT KITCHEN_SINK_NO_BINARY_TYPE_VARIANTS) target_link_libraries(kitchen_sink_ram_section kitchen_sink_libs kitchen_sink_options) pico_add_extra_outputs(kitchen_sink_ram_section) target_compile_definitions(kitchen_sink_ram_section PRIVATE KITCHEN_SINK_ID="ram section binary" EXTRA_DATA_SECTION=1) + + if (NOT PICO_C_COMPILER_IS_CLANG) + # Clang does not support overlay sections + add_executable(kitchen_sink_simple_overlay ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) + pico_add_linker_script_override_path(kitchen_sink_simple_overlay ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_simple_overlay_scripts) + target_link_libraries(kitchen_sink_simple_overlay kitchen_sink_libs kitchen_sink_options) + pico_add_extra_outputs(kitchen_sink_simple_overlay) + target_compile_definitions(kitchen_sink_simple_overlay PRIVATE KITCHEN_SINK_ID="simple overlay binary" EXTRA_DATA_SECTION=2) + endif() endif() add_executable(kitchen_sink_cpp ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_cpp.cpp) diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index 97ea8104d..18c07bad3 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -114,6 +114,29 @@ int main(void) { #endif #ifdef EXTRA_DATA_SECTION +#if EXTRA_DATA_SECTION > 1 + extern uint32_t __overlays_start__; + uint32_t stored_words; + + static int overlay_first __attribute__((section(".overlay_first"))) = 12345678; + printf("overlay_first before load = %d\n", overlay_first); + static int overlay_second_one __attribute__((section(".overlay_second"))) = 34567890; + static int overlay_second_two __attribute__((section(".overlay_second"))) = 56789012; + printf("overlay_second before load = %d, %d\n", overlay_second_one, overlay_second_two); + + extern uint32_t __load_start_overlay_second; + extern uint32_t __load_stop_overlay_second; + stored_words = (uint32_t)(&__load_stop_overlay_second - &__load_start_overlay_second); + memcpy(&__overlays_start__, &__load_start_overlay_second, 4 * stored_words); + printf("overlay_second after load = %d, %d\n", overlay_second_one, overlay_second_two); + + extern uint32_t __load_start_overlay_first; + extern uint32_t __load_stop_overlay_first; + stored_words = (uint32_t)(&__load_stop_overlay_first - &__load_start_overlay_first); + memcpy(&__overlays_start__, &__load_start_overlay_first, 4 * stored_words); + printf("overlay_first after load = %d\n", overlay_first); + printf("overlay_second after overlay_first load = %d, %d\n", overlay_second_one, overlay_second_two); +#else static int extra_data __attribute__((section(".extra_data"))) = 12345678; printf("extra_data before load = %d\n", extra_data); @@ -125,6 +148,7 @@ int main(void) { printf("extra_data after load = %d\n", extra_data); #endif +#endif #ifndef __riscv // this should compile as we are Cortex M0+ pico_default_asm ("SVC #3"); diff --git a/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.ld b/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.ld new file mode 100644 index 000000000..9a69c883a --- /dev/null +++ b/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.ld @@ -0,0 +1,24 @@ +INCLUDE "section_default_text.ld" +INCLUDE "section_default_data.ld" + +SECTIONS +{ + PROVIDE(__overlays_start__ = .); + OVERLAY : { + .overlay_first { + KEEP (*(.first*)) + . = ALIGN(4); + } + .overlay_second { + KEEP (*(.second*)) + . = ALIGN(4); + } + } > RAM AT> RAM_STORE + PROVIDE(__overlays_end__ = .); +} + +INCLUDE "section_heap.ld" +INCLUDE "section_scratch.ld" +INCLUDE "section_flash_end.ld" +INCLUDE "section_end.ld" +INCLUDE "section_platform_end.ld" From 5343b6eb0ec10d57a3307857af8d73b1185c9473 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 27 Feb 2026 10:49:07 +0000 Subject: [PATCH 059/127] Add scripts to bazel build Use new include_linker_script_dir and use_linker_script_file functions to add the linker arguments --- bazel/util/pico_linker_scripts.bzl | 49 +++++++++++++++ src/rp2_common/pico_crt0/rp2040/BUILD.bazel | 46 +++++++++++--- .../pico_crt0/rp2040/scripts/BUILD.bazel | 31 ++++++++++ src/rp2_common/pico_crt0/rp2350/BUILD.bazel | 40 ++++++++++-- .../pico_crt0/rp2350/scripts/BUILD.bazel | 31 ++++++++++ .../pico_standard_link/scripts/BUILD.bazel | 61 +++++++++++++++++++ 6 files changed, 244 insertions(+), 14 deletions(-) create mode 100644 bazel/util/pico_linker_scripts.bzl create mode 100644 src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel create mode 100644 src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel create mode 100644 src/rp2_common/pico_standard_link/scripts/BUILD.bazel diff --git a/bazel/util/pico_linker_scripts.bzl b/bazel/util/pico_linker_scripts.bzl new file mode 100644 index 000000000..f453b0761 --- /dev/null +++ b/bazel/util/pico_linker_scripts.bzl @@ -0,0 +1,49 @@ +load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "use_cpp_toolchain") + +def _include_linker_script_dir_impl(ctx): + link_include_dir = str(ctx.label.package) + depset_direct = ["-L" + str(link_include_dir)] + if len(ctx.files.use_scripts): + for script in ctx.files.use_scripts: + depset_direct.append("-T" + str(script.path)) + + linking_inputs = cc_common.create_linker_input( + owner = ctx.label, + user_link_flags = depset( + direct = depset_direct, + ), + ) + return [ + CcInfo(linking_context = cc_common.create_linking_context(linker_inputs = depset(direct = [linking_inputs]))), + ] + +include_linker_script_dir = rule( + implementation = _include_linker_script_dir_impl, + attrs = { + "use_scripts": attr.label_list(allow_files = [".ld"]), + }, + toolchains = use_cpp_toolchain(), + fragments = ["cpp"], +) + +def _use_linker_script_file_impl(ctx): + link_file = ctx.file.script.path + + linking_inputs = cc_common.create_linker_input( + owner = ctx.label, + user_link_flags = depset( + direct = ["-T" + str(link_file)], + ), + ) + return [ + CcInfo(linking_context = cc_common.create_linking_context(linker_inputs = depset(direct = [linking_inputs]))), + ] + +use_linker_script_file = rule( + implementation = _use_linker_script_file_impl, + attrs = { + "script": attr.label(mandatory = True, allow_single_file = [".ld"]), + }, + toolchains = use_cpp_toolchain(), + fragments = ["cpp"], +) diff --git a/src/rp2_common/pico_crt0/rp2040/BUILD.bazel b/src/rp2_common/pico_crt0/rp2040/BUILD.bazel index 44912f0c8..77cd27297 100644 --- a/src/rp2_common/pico_crt0/rp2040/BUILD.bazel +++ b/src/rp2_common/pico_crt0/rp2040/BUILD.bazel @@ -2,6 +2,8 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library") package(default_visibility = ["//visibility:public"]) +load("//bazel/util:pico_linker_scripts.bzl", "use_linker_script_file") + exports_files( [ "memmap_blocked_ram.ld", @@ -11,6 +13,26 @@ exports_files( ], ) +use_linker_script_file( + name = "memmap_default_args", + script = "memmap_default.ld", +) + +use_linker_script_file( + name = "memmap_blocked_ram_args", + script = "memmap_blocked_ram.ld", +) + +use_linker_script_file( + name = "memmap_copy_to_ram_args", + script = "memmap_copy_to_ram.ld", +) + +use_linker_script_file( + name = "memmap_no_flash_args", + script = "memmap_no_flash.ld", +) + # It's possible to set linker scripts globally or on a per-binary basis. # # Setting globally: @@ -22,12 +44,14 @@ exports_files( # * Manually add your desired linker script to each cc_binary. cc_library( name = "default_linker_script", - linkopts = ["-T$(location memmap_default.ld)"], target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ - "memmap_default.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2040/scripts:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_default.ld", + "memmap_default_args", ], ) @@ -35,12 +59,14 @@ cc_library( cc_library( name = "blocked_ram_linker_script", defines = ["PICO_USE_BLOCKED_RAM=1"], - linkopts = ["-T$(location memmap_blocked_ram.ld)"], target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ - "memmap_blocked_ram.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2040/scripts:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_blocked_ram.ld", + "memmap_blocked_ram_args", ], ) @@ -48,12 +74,14 @@ cc_library( cc_library( name = "copy_to_ram_linker_script", defines = ["PICO_COPY_TO_RAM=1"], - linkopts = ["-T$(location memmap_copy_to_ram.ld)"], target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ - "memmap_copy_to_ram.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2040/scripts:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_copy_to_ram.ld", + "memmap_copy_to_ram_args", ], ) @@ -61,10 +89,12 @@ cc_library( cc_library( name = "no_flash_linker_script", defines = ["PICO_NO_FLASH=1"], - linkopts = ["-T$(location memmap_no_flash.ld)"], target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ - "memmap_no_flash.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2040/scripts:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", + "memmap_no_flash.ld", + "memmap_no_flash_args", ], ) diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel b/src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel new file mode 100644 index 000000000..492842565 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel @@ -0,0 +1,31 @@ +package(default_visibility = ["//visibility:public"]) + +load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") + +exports_files( + [ + "default_locations.ld", + "section_copy_to_ram_text.ld", + "section_default_text.ld", + "section_no_flash_text.ld", + "section_platform_end.ld", + ] +) + +include_linker_script_dir( + name = "rp2040_linker_script_args", + use_scripts = ["default_locations.ld"], +) + +cc_library( + name = "rp2040_linker_scripts", + target_compatible_with = ["//bazel/constraint:rp2040"], + deps = [ + "default_locations.ld", + "section_copy_to_ram_text.ld", + "section_default_text.ld", + "section_no_flash_text.ld", + "section_platform_end.ld", + "rp2040_linker_script_args", + ], +) \ No newline at end of file diff --git a/src/rp2_common/pico_crt0/rp2350/BUILD.bazel b/src/rp2_common/pico_crt0/rp2350/BUILD.bazel index b0f1ca7dd..aae30de87 100644 --- a/src/rp2_common/pico_crt0/rp2350/BUILD.bazel +++ b/src/rp2_common/pico_crt0/rp2350/BUILD.bazel @@ -2,6 +2,8 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library") package(default_visibility = ["//visibility:public"]) +load("//bazel/util:pico_linker_scripts.bzl", "use_linker_script_file") + exports_files( [ "memmap_copy_to_ram.ld", @@ -10,6 +12,26 @@ exports_files( ], ) +use_linker_script_file( + name = "memmap_default_args", + script = "memmap_default.ld", +) + +use_linker_script_file( + name = "memmap_blocked_ram_args", + script = "memmap_blocked_ram.ld", +) + +use_linker_script_file( + name = "memmap_copy_to_ram_args", + script = "memmap_copy_to_ram.ld", +) + +use_linker_script_file( + name = "memmap_no_flash_args", + script = "memmap_no_flash.ld", +) + # It's possible to set linker scripts globally or on a per-binary basis. # # Setting globally: @@ -21,12 +43,14 @@ exports_files( # * Manually add your desired linker script to each cc_binary. cc_library( name = "default_linker_script", - linkopts = ["-T$(location memmap_default.ld)"], target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ - "memmap_default.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2350/scripts:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_default.ld", + "memmap_default_args", ], ) @@ -34,12 +58,14 @@ cc_library( cc_library( name = "copy_to_ram_linker_script", defines = ["PICO_COPY_TO_RAM=1"], - linkopts = ["-T$(location memmap_copy_to_ram.ld)"], target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ - "memmap_copy_to_ram.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2350/scripts:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_copy_to_ram.ld", + "memmap_copy_to_ram_args", ], ) @@ -47,10 +73,12 @@ cc_library( cc_library( name = "no_flash_linker_script", defines = ["PICO_NO_FLASH=1"], - linkopts = ["-T$(location memmap_no_flash.ld)"], target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ - "memmap_no_flash.ld", "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2_common/pico_crt0/rp2350/scripts:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/scripts:rp2_linker_scripts", + "memmap_no_flash.ld", + "memmap_no_flash_args", ], ) diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel b/src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel new file mode 100644 index 000000000..9c9aa7329 --- /dev/null +++ b/src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel @@ -0,0 +1,31 @@ +package(default_visibility = ["//visibility:public"]) + +load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") + +exports_files( + [ + "default_locations.ld", + "section_copy_to_ram_text.ld", + "section_default_text.ld", + "section_no_flash_text.ld", + "section_platform_end.ld", + ] +) + +include_linker_script_dir( + name = "rp2350_linker_script_args", + use_scripts = ["default_locations.ld"], +) + +cc_library( + name = "rp2350_linker_scripts", + target_compatible_with = ["//bazel/constraint:rp2350"], + deps = [ + "default_locations.ld", + "section_copy_to_ram_text.ld", + "section_default_text.ld", + "section_no_flash_text.ld", + "section_platform_end.ld", + "rp2350_linker_script_args", + ], +) \ No newline at end of file diff --git a/src/rp2_common/pico_standard_link/scripts/BUILD.bazel b/src/rp2_common/pico_standard_link/scripts/BUILD.bazel new file mode 100644 index 000000000..ac6239a11 --- /dev/null +++ b/src/rp2_common/pico_standard_link/scripts/BUILD.bazel @@ -0,0 +1,61 @@ +load("//bazel:defs.bzl", "compatible_with_rp2") +load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") + +package(default_visibility = ["//visibility:public"]) + +exports_files( + [ + "memory_aliases_default.ld", + "memory_aliases_no_flash.ld", + "memory_flash.ld", + "memory_ram.ld", + "memory_scratch.ld", + "memory_xip_ram.ld", + "section_copy_to_ram_data.ld", + "section_default_data.ld", + "section_end.ld", + "section_flash_end.ld", + "section_heap.ld", + "section_no_flash_data.ld", + "sections_copy_to_ram.ld", + "section_scratch.ld", + "sections_default.ld", + "sections_no_flash.ld", + "set_memory_locations.ld", + "rp2_common/memmap_default.ld", + "rp2_common/memmap_no_flash.ld", + "rp2_common/memmap_copy_to_ram.ld", + ] +) + +include_linker_script_dir( + name = "rp2_linker_script_args", +) + +cc_library( + name = "rp2_linker_scripts", + target_compatible_with = compatible_with_rp2(), + deps = [ + "rp2_linker_script_args", + "memory_aliases_default.ld", + "memory_aliases_no_flash.ld", + "memory_flash.ld", + "memory_ram.ld", + "memory_scratch.ld", + "memory_xip_ram.ld", + "section_copy_to_ram_data.ld", + "section_default_data.ld", + "section_end.ld", + "section_flash_end.ld", + "section_heap.ld", + "section_no_flash_data.ld", + "sections_copy_to_ram.ld", + "section_scratch.ld", + "sections_default.ld", + "sections_no_flash.ld", + "set_memory_locations.ld", + "rp2_common/memmap_default.ld", + "rp2_common/memmap_no_flash.ld", + "rp2_common/memmap_copy_to_ram.ld", + ], +) \ No newline at end of file From 59fe386ae8c656893a3eb246e1e28074f65c1558 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 27 Feb 2026 11:48:11 +0000 Subject: [PATCH 060/127] Mark rtc_clksrc as rp2040 only in bazel build --- test/hello_sleep/BUILD.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hello_sleep/BUILD.bazel b/test/hello_sleep/BUILD.bazel index a26073420..2c007c6bc 100644 --- a/test/hello_sleep/BUILD.bazel +++ b/test/hello_sleep/BUILD.bazel @@ -30,7 +30,7 @@ cc_binary( name = "rtc_clksrc", testonly = True, srcs = ["rtc_clksrc.c"], - target_compatible_with = compatible_with_rp2(), + target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common/pico_stdlib", "//src/rp2_common/pico_status_led", From cacafe6a8d34983f4b9e85a99f779b97ec9de6f6 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 5 Mar 2026 17:22:56 +0000 Subject: [PATCH 061/127] Add some docs to low power functions --- .../pico_low_power/include/pico/low_power.h | 109 +++++++++++++++--- 1 file changed, 94 insertions(+), 15 deletions(-) diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 6367e4c1f..c6a5be8bc 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -65,30 +65,64 @@ typedef void (*low_power_pstate_resume_func)(pstate_bitset_t *pstate); // sleep is really just calling a __wfi() until an irq, with some optional clock gating in the sleep_en register. Activated once processor goes to sleep // So can just do it for arbitrary interrupts. processors implement their own internal clock gating, just leaving the wakeup interrupt controller running during // __wfi() + +/*! \brief Sleep until an interrupt occurs + * \ingroup pico_low_power + * Sleep until any interrupt occurs. The clocks specified in keep_enabled will be kept enabled during sleep. + * + * \param keep_enabled The clocks to keep enabled during sleep. + * \return 0 on success, non-zero on error. + */ int low_power_sleep_until_irq(const clock_dest_set_t *keep_enabled); // sleep until the given timer reaches the specified value; if the time passes then no sleep occurs // keep_enabled defaults to none if NULL // ** LIAM BLESSED ** + +/*! \brief Sleep until time using timer + * \ingroup pico_low_power + * Sleep until the given timer reaches the specified value. The clocks specified in keep_enabled will be kept enabled during sleep, along with clocks required + * for the timer. If exclusive is true, only the timer interrupt will be listened for, otherwise other interrupts will be listened for. + * + * \param timer The timer to use. + * \param until The time to sleep until. + * \param keep_enabled The clocks to keep enabled during sleep. + * \param exclusive Whether to only listen for the timer interrupt, or other interrupts. + * \return 0 on success, non-zero on error. + */ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, const clock_dest_set_t *keep_enabled, bool exclusive); // Note bool above saying shall we only listen for timer irq or other irqs // Need to defer handling of irqs to do clock setup etc +/*! \brief Sleep until time using default timer + * \ingroup pico_low_power + * See \ref low_power_sleep_until_timer for more information. + * + * \param until The time to sleep until. + * \param keep_enabled The clocks to keep enabled during sleep. + * \param exclusive Whether to only listen for the timer interrupt, or other interrupts. + * \return 0 on success, non-zero on error. + */ static inline int low_power_sleep_until_default_timer(absolute_time_t until, const clock_dest_set_t *keep_enabled, bool exclusive) { // Need to assert (or add) ticks block and timer clocks to the keep_enabled list return low_power_sleep_until_timer(PICO_DEFAULT_TIMER_INSTANCE(), until, keep_enabled, exclusive); } -// ** LIAM BLESSED this for RP2040; why not RP2350 ** -// This should work on both via io bank interrupts + +/*! \brief Sleep until pin state changes + * \ingroup pico_low_power + * Sleep until the given GPIO pin changes state. The clocks specified in keep_enabled will be kept enabled during sleep. + * If exclusive is true, only the GPIO interrupt will be listened for, otherwise other interrupts will be listened for. + * + * \param gpio_pin The GPIO pin to use. + * \param edge Whether to listen for edge or level. + * \param high Whether to listen for the high/low level, or rising/falling edge. + * \param keep_enabled The clocks to keep enabled during sleep. + * \param exclusive Whether to only listen for the GPIO interrupt, or other interrupts. + * \return 0 on success, non-zero on error. + */ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_set_t *keep_enabled, bool exclusive); -#if 0 -// ** LIAM SAYS THIS IS NO MORE USEFUL THAN SLEEP_UNTIL TIMER... ** -// There isn't much advantage to using the aon timer here as system timers are more accurate and on anyway -// ** WILL AGREES WITH LIAM ON THIS ** -int low_power_sleep_until_aon_timer(absolute_time_t until, const clock_dest_set_t *keep_enabled); -#endif // ** LIAM BLESSED but we need to impl it correctly (note not blessed for RP2040, but we should do it anyway for orthogonality ** // Only works for RP2350 as every clock will be stopped on RP2040 (unless you provide a clock for the RTC) @@ -97,18 +131,63 @@ int low_power_sleep_until_aon_timer(absolute_time_t until, const clock_dest_set_ // NOTE: Asserting that we will alway use rosc for dormant and simplifies the API // Means if the user has sped up the rosc they should slow it down before going into dormant // Need to re initialize clocks after this + +/*! \brief Go dormant until time using AON timer + * \ingroup pico_low_power + * Go dormant until the given AON timer reaches the specified value. The clocks specified in keep_enabled will be kept enabled during sleep. + * + * \param until The time to go dormant until. + * \param dormant_clock_source The clock source to use for dormant. Must be DORMANT_CLOCK_SOURCE_LPOSC on RP2350. + * \param src_hz The frequency of the clock source on RP2040. Ignored on RP2350. + * \param gpio_pin The GPIO pin to use for the RTC on RP2040. Ignored on RP2350. + * \param keep_enabled The clocks to keep enabled during dormant. + * \return 0 on success, non-zero on error. + */ int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_source_t dormant_clock_source, uint src_hz, uint gpio_pin, const clock_dest_set_t *keep_enabled); // ** LIAM BLESSED but we need to impl it correctly (note not blessed for RP2040, but we should do it anyway for orthogonality ** // This works on both // Need to re initialize clocks after this + +/*! \brief Go dormant until pin state changes + * \ingroup pico_low_power + * Go dormant until the given GPIO pin changes state. The clocks specified in keep_enabled will be kept enabled during dormant. + * + * \param gpio_pin The GPIO pin to use. + * \param edge Whether to listen for edge or level. + * \param high Whether to listen for the high/low level, or rising/falling edge. + * \param dormant_clock_source The clock source to use for dormant. Must be DORMANT_CLOCK_SOURCE_LPOSC on RP2350. + * \param keep_enabled The clocks to keep enabled during dormant. + */ void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_set_t *keep_enabled); #if HAS_POWMAN_TIMER // pstate functions should return to the pstate you were in // pass resume_func which will be called on reboot by runtime_init_low_power_reboot_check + +/*! \brief Go to Pstate until time using AON timer + * \ingroup pico_low_power + * Go to Pstate until the given AON timer reaches the specified value. The function specified in resume_func will be called on reboot. + * + * \param until The time to go to Pstate until. + * \param pstate The Pstate to use. If NULL, the Pstate will keep persistent data powered on. + * \param resume_func The function to call on reboot. + * \return 0 on success, non-zero on error. + */ int low_power_pstate_until_aon_timer(absolute_time_t until, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func); + +/*! \brief Go Pstate until pin state changes + * \ingroup pico_low_power + * Go Pstate until the given GPIO pin changes state. The function specified in resume_func will be called on reboot. + * + * \param gpio_pin The GPIO pin to use. + * \param edge Whether to listen for edge or level. + * \param high Whether to listen for the high/low level, or rising/falling edge. + * \param pstate The Pstate to use. If NULL, the Pstate will keep persistent data powered on. + * \param resume_func The function to call on reboot. + * \return 0 on success, non-zero on error. + */ int low_power_pstate_until_pin_state(uint gpio_pin, bool edge, bool high, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func); // Or a function saying how did I boot? @@ -119,12 +198,12 @@ int low_power_pstate_until_pin_state(uint gpio_pin, bool edge, bool high, pstate // - Switched core off (args are which rams you want to keep on) // Switched core, XIP cache + bootram, SRAM0 bank, SRAM1 bank + SCRATCH -// Go to a pstate -// Doesn't support powering down switched core domain -int low_power_pstate_set(pstate_bitset_t *pstate); -pstate_bitset_t *low_power_pstate_get(pstate_bitset_t *pstate); - -// get pstate which keeps persistent data powered on +/*! \brief Get Pstate which keeps persistent data powered on + * \ingroup pico_low_power + * + * \param pstate Pointer to the Pstate to write the result to. + * \return The Pstate. + */ pstate_bitset_t *low_power_persistent_pstate_get(pstate_bitset_t *pstate); #endif @@ -132,4 +211,4 @@ pstate_bitset_t *low_power_persistent_pstate_get(pstate_bitset_t *pstate); } #endif -#endif \ No newline at end of file +#endif From 1deea52be45b49e4b4b7a5d7a1884296fa6234a9 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 6 Mar 2026 14:27:04 +0000 Subject: [PATCH 062/127] Run clk_sys from ROSC when dormant with DORMANT_CLOCK_SOURCE_LPOSC Also use measured ROSC freq when going dormant --- .../hardware_rosc/include/hardware/rosc.h | 18 +++- src/rp2_common/hardware_rosc/rosc.c | 6 +- .../pico_low_power/include/pico/low_power.h | 24 +++-- src/rp2_common/pico_low_power/low_power.c | 87 +++++++------------ 4 files changed, 69 insertions(+), 66 deletions(-) diff --git a/src/rp2_common/hardware_rosc/include/hardware/rosc.h b/src/rp2_common/hardware_rosc/include/hardware/rosc.h index eff5a5c80..499bb9cbb 100644 --- a/src/rp2_common/hardware_rosc/include/hardware/rosc.h +++ b/src/rp2_common/hardware_rosc/include/hardware/rosc.h @@ -71,7 +71,23 @@ void rosc_restart(void); uint32_t next_rosc_code(uint32_t code); -uint rosc_find_freq(uint32_t low_mhz, uint32_t high_mhz); +/*! \brief Set the frequency of the Ring Oscillator within a range + * \ingroup hardware_rosc + * + * This function will set the frequency of the Ring Oscillator to the first frequency within the range. + * + * \param low_mhz The bottom of the range to search for. + * \param high_mhz The top of the range to search for. + * \return The frequency of the Ring Oscillator within the range in MHz, or 0 if no frequency within the range is found. + */ +uint rosc_find_freq_mhz(uint32_t low_mhz, uint32_t high_mhz); + +/*! \brief Measure the frequency of the Ring Oscillator + * \ingroup hardware_rosc + * + * \return The frequency of the Ring Oscillator in kHz. + */ +uint rosc_measure_freq_khz(void); void rosc_set_div(uint32_t div); diff --git a/src/rp2_common/hardware_rosc/rosc.c b/src/rp2_common/hardware_rosc/rosc.c index f58f65bd6..a6e3ee51f 100644 --- a/src/rp2_common/hardware_rosc/rosc.c +++ b/src/rp2_common/hardware_rosc/rosc.c @@ -16,7 +16,7 @@ uint32_t next_rosc_code(uint32_t code) { return ((code | 0x08888888u) + 1u) & 0xf7777777u; } -uint rosc_find_freq(uint32_t low_mhz, uint32_t high_mhz) { +uint rosc_find_freq_mhz(uint32_t low_mhz, uint32_t high_mhz) { // TODO: This could be a lot better rosc_set_div(1); for (uint32_t code = 0; code <= 0x77777777u; code = next_rosc_code(code)) { @@ -29,6 +29,10 @@ uint rosc_find_freq(uint32_t low_mhz, uint32_t high_mhz) { return 0; } +uint rosc_measure_freq_khz(void) { + return frequency_count_khz(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC); +} + void rosc_set_div(uint32_t div) { assert(div <= 31 && div >= 1); rosc_write(&rosc_hw->div, ROSC_DIV_VALUE_PASS + div); diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index c6a5be8bc..58a171c82 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -26,7 +26,7 @@ extern "C" { * block. For example you could keep clk_rtc running. Some destinations (proc0 and proc1 wakeup logic) * can't be stopped in sleep mode otherwise there wouldn't be enough logic to wake up again. * - * In pstate mode some power domains are switched off and don't retain state. + * In Pstate mode some power domains are switched off and don't retain state. * * \subsection sleep_example Example * \addtogroup pico_sleep @@ -134,7 +134,8 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const /*! \brief Go dormant until time using AON timer * \ingroup pico_low_power - * Go dormant until the given AON timer reaches the specified value. The clocks specified in keep_enabled will be kept enabled during sleep. + * Go dormant until the given AON timer reaches the specified value. + * The clocks specified in keep_enabled will be kept enabled during dormant, but XOSC and ROSC will be stopped. * * \param until The time to go dormant until. * \param dormant_clock_source The clock source to use for dormant. Must be DORMANT_CLOCK_SOURCE_LPOSC on RP2350. @@ -151,12 +152,13 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_sourc /*! \brief Go dormant until pin state changes * \ingroup pico_low_power - * Go dormant until the given GPIO pin changes state. The clocks specified in keep_enabled will be kept enabled during dormant. + * Go dormant until the given GPIO pin changes state. + * The clocks specified in keep_enabled will be kept enabled during dormant, but XOSC and ROSC will be stopped. * * \param gpio_pin The GPIO pin to use. * \param edge Whether to listen for edge or level. * \param high Whether to listen for the high/low level, or rising/falling edge. - * \param dormant_clock_source The clock source to use for dormant. Must be DORMANT_CLOCK_SOURCE_LPOSC on RP2350. + * \param dormant_clock_source The clock source to use for dormant. * \param keep_enabled The clocks to keep enabled during dormant. */ void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_set_t *keep_enabled); @@ -170,6 +172,12 @@ void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dorm * \ingroup pico_low_power * Go to Pstate until the given AON timer reaches the specified value. The function specified in resume_func will be called on reboot. * + * If pstate is NULL, it will go to the minimum Pstate that will keep persistent data powered on. + * + * NOTE: This function will overwrite the last 2 powman scratch registers - the other scratch registers are not modified. + * + * To also wake up from a GPIO, configure that using \ref powman_enable_gpio_wakeup before calling this function. + * * \param until The time to go to Pstate until. * \param pstate The Pstate to use. If NULL, the Pstate will keep persistent data powered on. * \param resume_func The function to call on reboot. @@ -177,9 +185,13 @@ void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dorm */ int low_power_pstate_until_aon_timer(absolute_time_t until, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func); -/*! \brief Go Pstate until pin state changes +/*! \brief Go to Pstate until pin state changes * \ingroup pico_low_power - * Go Pstate until the given GPIO pin changes state. The function specified in resume_func will be called on reboot. + * Go to Pstate until the given GPIO pin changes state. The function specified in resume_func will be called on reboot. + * + * If pstate is NULL, it will go to the minimum Pstate that will keep persistent data powered on. + * + * NOTE: This function will overwrite the last 2 powman scratch registers - the other scratch registers are not modified. * * \param gpio_pin The GPIO pin to use. * \param edge Whether to listen for edge or level. diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 6156f06ec..2bc341b95 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -335,73 +335,39 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, if (exclusive) restore_other_interrupts(); } -#if 0 -// todo note this has (not surprisingly a lot of commonality with the timer one) -int low_power_sleep_until_aon_timer(absolute_time_t until, - const clock_dest_set_t *keep_enabled) { - event_happened = false; - - clock_dest_set_t local_keep_enabled; - replace_null_enable_values(keep_enabled, &local_keep_enabled); - // Turn off all clocks except for the timer - // todo we need mapping of hardware to clocks; also this needs to come from AON timer - // we know that people in the wild (MicroPython) have wanted to do some mapping to also - // figure out what PLLs are still on via these bits - // - // todo note also here that this should come from AON_TIMER via AON_TIMER_CLOCK_DEST_NUM() but - // how do we indicate multiple bits there; actually todo (graham) and no one steal this as it sounds - // fun, we probably want to have a "sparse" bitset macro encoded as 4 bytes or 8 bytes (for 4 or 7 indices - // between 0 and 254) - i say 7, to leave encoding space for maybe indices > 256 in the 8 byte variant -#if PICO_RP2040 - clock_dest_set_add(&local_keep_enabled, CLOCK_DEST_RTC_RTC); -#elif PICO_RP2350 - clock_dest_set_add(&local_keep_enabled, CLK_DEST_REF_POWMAN); -#else -#error Unknown processor -#endif - // todo catch race condition here (or just plain in the past) - struct timespec ts; - us_to_timespec(to_us_since_boot(until), &ts); - // note wakeup from low power == false, means don't wake up from dormant - aon_timer_enable_alarm(&ts, (aon_timer_alarm_handler_t)low_power_wakeup, false); - - prepare_for_clock_gating(); - // gate clocks - clock_gate_sleep_en(&local_keep_enabled); - - low_power_enable_processor_deep_sleep(); - // Go to sleep until the wakeup event happens (note it may have happened already) - while (!event_happened) { - __wfi(); - } - low_power_disable_processor_deep_sleep(); - - post_clock_gating(); - return 0; -} -#endif - // In order to go into dormant mode we need to be running from a stoppable clock source: // either the xosc or rosc with no PLLs running. This means we disable the USB and ADC clocks // and all PLLs void low_power_setup_clocks_for_dormant(dormant_clock_source_t dormant_source) { prepare_for_clock_switch(); - uint src_hz; + uint clk_ref_src_hz; uint32_t clk_ref_src; + uint clk_sys_src_hz; + uint32_t clk_sys_src; + uint32_t clk_sys_aux_src; switch (dormant_source) { case DORMANT_CLOCK_SOURCE_XOSC: - src_hz = XOSC_HZ; + clk_ref_src_hz = XOSC_HZ; clk_ref_src = CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC; + clk_sys_src_hz = clk_ref_src_hz; + clk_sys_src = CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF; + clk_sys_aux_src = 0; break; case DORMANT_CLOCK_SOURCE_ROSC: - src_hz = 6500 * KHZ; // todo + clk_ref_src_hz = rosc_measure_freq_khz() * KHZ; clk_ref_src = CLOCKS_CLK_REF_CTRL_SRC_VALUE_ROSC_CLKSRC_PH; + clk_sys_src_hz = clk_ref_src_hz; + clk_sys_src = CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF; + clk_sys_aux_src = 0; break; #if !PICO_RP2040 case DORMANT_CLOCK_SOURCE_LPOSC: - src_hz = 32 * KHZ; + clk_ref_src_hz = 32 * KHZ; clk_ref_src = CLOCKS_CLK_REF_CTRL_SRC_VALUE_LPOSC_CLKSRC; + clk_sys_src_hz = rosc_measure_freq_khz() * KHZ; + clk_sys_src = CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX; + clk_sys_aux_src = CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC; break; #endif default: @@ -412,13 +378,13 @@ void low_power_setup_clocks_for_dormant(dormant_clock_source_t dormant_source) { clock_configure_undivided(clk_ref, clk_ref_src, 0, - src_hz); + clk_ref_src_hz); // CLK SYS = CLK_REF clock_configure_undivided(clk_sys, - CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF, - 0, // Using glitchless mux - src_hz); + clk_sys_src, + clk_sys_aux_src, + clk_sys_src_hz); // CLK ADC = 0MHz @@ -437,7 +403,7 @@ void low_power_setup_clocks_for_dormant(dormant_clock_source_t dormant_source) { clock_configure(clk_rtc, 0, // No GLMUX clk_rtc_src, - src_hz, + clk_sys_src_hz, 46875); #endif @@ -445,8 +411,8 @@ void low_power_setup_clocks_for_dormant(dormant_clock_source_t dormant_source) { clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS, - src_hz, - src_hz); + clk_sys_src_hz, + clk_sys_src_hz); pll_deinit(pll_sys); pll_deinit(pll_usb); @@ -474,7 +440,12 @@ void low_power_wake_from_dormant(void) { } void low_power_go_dormant(dormant_clock_source_t dormant_clock_source) { - assert(dormant_clock_source == DORMANT_CLOCK_SOURCE_XOSC || dormant_clock_source == DORMANT_CLOCK_SOURCE_ROSC); + assert( + dormant_clock_source == DORMANT_CLOCK_SOURCE_XOSC || dormant_clock_source == DORMANT_CLOCK_SOURCE_ROSC + #if !PICO_RP2040 + || dormant_clock_source == DORMANT_CLOCK_SOURCE_LPOSC + #endif + ); if (dormant_clock_source == DORMANT_CLOCK_SOURCE_XOSC) { xosc_dormant(); From 89276fa2673aa248dfd7052d94e8d754780fdbae Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 6 Mar 2026 14:59:57 +0000 Subject: [PATCH 063/127] Tidy up comments, and add more docs --- .../pico_low_power/include/pico/low_power.h | 104 +++++++++--------- 1 file changed, 49 insertions(+), 55 deletions(-) diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 58a171c82..48553f67f 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -17,17 +17,40 @@ extern "C" { /** \file low_power.h * \defgroup pico_low_power pico_low_power * - * Lower Power Sleep APIs + * Lower Power APIs + * + * There are three modes of operation: sleep, dormant, and Pstate, with the lowest power consumption being Pstate. + * + * \if rp2040_specific + * NOTE: On RP2040, there is no Pstate mode. + * \endif + * + * In sleep mode: + * - Some clocks can be left running controlled by the SLEEP_EN registers in the clocks + * block. For example you could keep clk_rtc running. + * - Some destinations (proc0 and proc1 wakeup logic) can't be stopped in sleep mode otherwise there wouldn't be enough logic to wake up again. + * - You can wake up from sleep by any interrupt, provided the clock for that interrupt is kept enabled + * - The sleep APIs will keep the clocks enabled for stdio during sleep, along with USB clocks when using tinyusb. + * + * In dormant mode: + * - Both xosc and rosc are stopped, until the dormant clock source is started again by an external event. + * - USB will be disabled before going into dormant, and re-enabled after waking up. + * - You can only wake up from dormant using the AON timer, or a GPIO interrupt configured using \ref gpio_set_dormant_irq_enabled. + * All other interrupts will be disabled during dormant. + * + * \if (!rp2040_specific) + * In Pstate mode: + * - Some power domains are switched off and don't retain state (eg specified SRAMs). By default, only the power domains + * required to keep persistent data powered on will be kept on. + * - You can only wake up from Pstate using the AON timer, or a GPIO wakeup configured using \ref powman_enable_gpio_wakeup. + * - Waking up from Pstate will run your program from the start, optionally executing a resume_func during runtime init. + * All non-persistent data will be overwritten by crt0 when the program starts again. + * - Variables can be marked as persistent using the __persistent_data macro. The location of the CMake function pico_set_persistent_data_loc. + * For example, the persistent data could be stored in XIP_SRAM, SRAM0, or SRAM1. + * - The Pstate APIs will overwrite the last 2 powman scratch registers - the other scratch registers are not modified, + * so can be used for other persistent data. + * \endif * - * The difference between sleep and dormant is that ALL clocks are stopped in dormant mode, - * until the source (either xosc or rosc) is started again by an external event. - * - * In sleep mode some clocks can be left running controlled by the SLEEP_EN registers in the clocks - * block. For example you could keep clk_rtc running. Some destinations (proc0 and proc1 wakeup logic) - * can't be stopped in sleep mode otherwise there wouldn't be enough logic to wake up again. - * - * In Pstate mode some power domains are switched off and don't retain state. - * * \subsection sleep_example Example * \addtogroup pico_sleep * \include hello_sleep.c @@ -57,15 +80,6 @@ typedef void (*low_power_pstate_resume_func)(pstate_bitset_t *pstate); #endif -// NOTE: Need to deinit usb before doing into any of these sleep states -// could keep usb clk_sys and clk_usb to usbctrl running during low_power_sleep. Although you'll get woken -// up pretty quickly -// Also you are plugged into a host so why bother? - -// sleep is really just calling a __wfi() until an irq, with some optional clock gating in the sleep_en register. Activated once processor goes to sleep -// So can just do it for arbitrary interrupts. processors implement their own internal clock gating, just leaving the wakeup interrupt controller running during -// __wfi() - /*! \brief Sleep until an interrupt occurs * \ingroup pico_low_power * Sleep until any interrupt occurs. The clocks specified in keep_enabled will be kept enabled during sleep. @@ -75,10 +89,6 @@ typedef void (*low_power_pstate_resume_func)(pstate_bitset_t *pstate); */ int low_power_sleep_until_irq(const clock_dest_set_t *keep_enabled); -// sleep until the given timer reaches the specified value; if the time passes then no sleep occurs -// keep_enabled defaults to none if NULL -// ** LIAM BLESSED ** - /*! \brief Sleep until time using timer * \ingroup pico_low_power * Sleep until the given timer reaches the specified value. The clocks specified in keep_enabled will be kept enabled during sleep, along with clocks required @@ -91,8 +101,6 @@ int low_power_sleep_until_irq(const clock_dest_set_t *keep_enabled); * \return 0 on success, non-zero on error. */ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, const clock_dest_set_t *keep_enabled, bool exclusive); -// Note bool above saying shall we only listen for timer irq or other irqs -// Need to defer handling of irqs to do clock setup etc /*! \brief Sleep until time using default timer * \ingroup pico_low_power @@ -104,7 +112,6 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, const * \return 0 on success, non-zero on error. */ static inline int low_power_sleep_until_default_timer(absolute_time_t until, const clock_dest_set_t *keep_enabled, bool exclusive) { - // Need to assert (or add) ticks block and timer clocks to the keep_enabled list return low_power_sleep_until_timer(PICO_DEFAULT_TIMER_INSTANCE(), until, keep_enabled, exclusive); } @@ -123,20 +130,16 @@ static inline int low_power_sleep_until_default_timer(absolute_time_t until, con */ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_set_t *keep_enabled, bool exclusive); - -// ** LIAM BLESSED but we need to impl it correctly (note not blessed for RP2040, but we should do it anyway for orthogonality ** -// Only works for RP2350 as every clock will be stopped on RP2040 (unless you provide a clock for the RTC) -// Easier to not support on RP2040 - might as well buy a 2350 - -// NOTE: Asserting that we will alway use rosc for dormant and simplifies the API -// Means if the user has sped up the rosc they should slow it down before going into dormant -// Need to re initialize clocks after this - /*! \brief Go dormant until time using AON timer * \ingroup pico_low_power * Go dormant until the given AON timer reaches the specified value. * The clocks specified in keep_enabled will be kept enabled during dormant, but XOSC and ROSC will be stopped. * + * \if (!rp2040_specific) + * If the clock source is set to DORMANT_CLOCK_SOURCE_LPOSC, clk_sys will be run from the ROSC while dormant so + * it can be stopped, while clk_ref will be run from the LPOSC so that continues running for the timer. + * \endif + * * \param until The time to go dormant until. * \param dormant_clock_source The clock source to use for dormant. Must be DORMANT_CLOCK_SOURCE_LPOSC on RP2350. * \param src_hz The frequency of the clock source on RP2040. Ignored on RP2350. @@ -146,15 +149,16 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const */ int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_source_t dormant_clock_source, uint src_hz, uint gpio_pin, const clock_dest_set_t *keep_enabled); -// ** LIAM BLESSED but we need to impl it correctly (note not blessed for RP2040, but we should do it anyway for orthogonality ** -// This works on both -// Need to re initialize clocks after this - /*! \brief Go dormant until pin state changes * \ingroup pico_low_power * Go dormant until the given GPIO pin changes state. * The clocks specified in keep_enabled will be kept enabled during dormant, but XOSC and ROSC will be stopped. * + * \if (!rp2040_specific) + * If the clock source is set to DORMANT_CLOCK_SOURCE_LPOSC, clk_sys will be run from the ROSC while dormant so + * it can be stopped, while clk_ref will be run from the LPOSC so that continues running for the GPIO interrupt. + * \endif + * * \param gpio_pin The GPIO pin to use. * \param edge Whether to listen for edge or level. * \param high Whether to listen for the high/low level, or rising/falling edge. @@ -164,20 +168,17 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_sourc void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_set_t *keep_enabled); #if HAS_POWMAN_TIMER -// pstate functions should return to the pstate you were in - -// pass resume_func which will be called on reboot by runtime_init_low_power_reboot_check - /*! \brief Go to Pstate until time using AON timer * \ingroup pico_low_power - * Go to Pstate until the given AON timer reaches the specified value. The function specified in resume_func will be called on reboot. + * Go to Pstate until the given AON timer reaches the specified value. The function specified in resume_func will be called on reboot, + * with the low power Pstate passed to it. * * If pstate is NULL, it will go to the minimum Pstate that will keep persistent data powered on. * - * NOTE: This function will overwrite the last 2 powman scratch registers - the other scratch registers are not modified. - * * To also wake up from a GPIO, configure that using \ref powman_enable_gpio_wakeup before calling this function. * + * NOTE: This function will overwrite the last 2 powman scratch registers - the other scratch registers are not modified. + * * \param until The time to go to Pstate until. * \param pstate The Pstate to use. If NULL, the Pstate will keep persistent data powered on. * \param resume_func The function to call on reboot. @@ -187,7 +188,8 @@ int low_power_pstate_until_aon_timer(absolute_time_t until, pstate_bitset_t *pst /*! \brief Go to Pstate until pin state changes * \ingroup pico_low_power - * Go to Pstate until the given GPIO pin changes state. The function specified in resume_func will be called on reboot. + * Go to Pstate until the given GPIO pin changes state. The function specified in resume_func will be called on reboot, + * with the low power Pstate passed to it. * * If pstate is NULL, it will go to the minimum Pstate that will keep persistent data powered on. * @@ -202,14 +204,6 @@ int low_power_pstate_until_aon_timer(absolute_time_t until, pstate_bitset_t *pst */ int low_power_pstate_until_pin_state(uint gpio_pin, bool edge, bool high, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func); -// Or a function saying how did I boot? -// Would like to make it easy to get back to main after going to sleep - -// Two configs: -// - Everything off apart from AON, ram needs zeroing on boot -// - Switched core off (args are which rams you want to keep on) -// Switched core, XIP cache + bootram, SRAM0 bank, SRAM1 bank + SCRATCH - /*! \brief Get Pstate which keeps persistent data powered on * \ingroup pico_low_power * From 5ae8b76156e82fcf29da79f94eb5e941e7b06bed Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 6 Mar 2026 16:00:01 +0000 Subject: [PATCH 064/127] Tidy up some comments --- src/rp2_common/pico_low_power/low_power.c | 24 +++-------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 2bc341b95..03ac58373 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -44,16 +44,6 @@ #include "hardware/structs/scb.h" #endif - -// The difference between sleep and dormant is that ALL clocks are stopped in dormant mode, -// until the source (either xosc or rosc) is started again by an external event. -// In sleep mode some clocks can be left running controlled by the SLEEP_EN registers in the clocks -// block. For example you could keep clk_rtc running. Some destinations (proc0 and proc1 wakeup logic) -// can't be stopped in sleep mode otherwise there wouldn't be enough logic to wake up again. - - -// TODO: Optionally, memories can also be powered down. - // ------------------------------------------------------------------------------------------------------ // todo these probably belong in h/w clocks as some sort of registered thing, but leave them private here // for now @@ -128,15 +118,12 @@ static void post_pstate_change(void) { } #endif -// ------------------------------------------------------------------------------------------------------ - -// todo should we make this a save/restore thing? void low_power_enable_processor_deep_sleep(void) { // Enable deep sleep at the proc #ifdef __riscv uint32_t bits = RVCSR_MSLEEP_POWERDOWN_BITS; if (!get_core_num()) { - // todo errata ref + // see errata RP2350-E4 bits |= RVCSR_MSLEEP_DEEPSLEEP_BITS; } riscv_set_csr(RVCSR_MSLEEP_OFFSET, bits); @@ -248,9 +235,6 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, clock_dest_set_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); - // todo we need mapping of hardware to clocks; also this needs to come from AON timer - // we know that people in the wild (MicroPython) have wanted to do some mapping to also - // figure out what PLLs are still on via these bits #if PICO_RP2040 clock_dest_set_add(&local_keep_enabled, CLK_DEST_SYS_TIMER); #elif PICO_RP2350 @@ -463,13 +447,11 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, clock_dest_set_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); - // todo ugh this doesn't really belong here like this; need to encapsulate in aon timer? #if PICO_RP2040 // The RTC must be run from an external source, since the dormant source will be inactive rtc_run_from_external_source(src_hz, gpio_pin); clock_dest_set_add(&local_keep_enabled, CLK_DEST_RTC_RTC); #elif PICO_RP2350 - // todo ((void)src_hz); ((void)gpio_pin); if (dormant_clock_source == DORMANT_CLOCK_SOURCE_LPOSC) @@ -486,7 +468,6 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, struct timespec ts; us_to_timespec(to_us_since_boot(until), &ts); event_happened = false; - // note wakeup from low power == false, means don't wake up from dormant aon_timer_enable_alarm(&ts, (aon_timer_alarm_handler_t)low_power_wakeup, true); prepare_for_clock_gating(); @@ -499,7 +480,7 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, low_power_go_dormant(dormant_clock_source); - assert(event_happened); // does it? + assert(event_happened); low_power_wake_from_dormant(); return 0; @@ -626,6 +607,7 @@ int low_power_go_pstate(pstate_bitset_t *pstate, low_power_pstate_resume_func re // Power down while (true) __wfi(); + // Should not reach here post_pstate_change(); return rc; From b521c119520855f6824fb49aef2692210cf24101 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 6 Mar 2026 17:23:44 +0000 Subject: [PATCH 065/127] Use gmtime_r instead of localtime_r on Clang Some Clang versions (eg the one currently used by Bazel) don't have the localtime_r function --- src/rp2_common/pico_clib_interface/llvm_libc_interface.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/rp2_common/pico_clib_interface/llvm_libc_interface.c b/src/rp2_common/pico_clib_interface/llvm_libc_interface.c index dfcab015e..69e513c31 100644 --- a/src/rp2_common/pico_clib_interface/llvm_libc_interface.c +++ b/src/rp2_common/pico_clib_interface/llvm_libc_interface.c @@ -41,6 +41,11 @@ int settimeofday(__unused const struct timeval *tv, __unused const struct timezo return 0; } +// Some Clang versions don't support localtime_r, so we use gmtime_r instead. +__weak struct tm* localtime_r(const time_t* time, struct tm* tm) { + return gmtime_r((time_t*)time, tm); +} + // TODO: This should be a thread-local variable. int errno; From e464234287caea8ea40de77d99cfe17546cce21d Mon Sep 17 00:00:00 2001 From: will-v-pi <108662275+will-v-pi@users.noreply.github.com> Date: Tue, 10 Mar 2026 10:04:21 +0000 Subject: [PATCH 066/127] Apply documentation suggestions from code review to low_power.h Co-authored-by: Andrew Scheller --- .../pico_low_power/include/pico/low_power.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 48553f67f..5d8a5c207 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -45,8 +45,8 @@ extern "C" { * - You can only wake up from Pstate using the AON timer, or a GPIO wakeup configured using \ref powman_enable_gpio_wakeup. * - Waking up from Pstate will run your program from the start, optionally executing a resume_func during runtime init. * All non-persistent data will be overwritten by crt0 when the program starts again. - * - Variables can be marked as persistent using the __persistent_data macro. The location of the CMake function pico_set_persistent_data_loc. - * For example, the persistent data could be stored in XIP_SRAM, SRAM0, or SRAM1. + * - Variables can be marked as persistent using the __persistent_data macro. The location of the data can be set using the + * CMake function pico_set_persistent_data_loc. The persistent data can be stored in XIP_SRAM or main SRAM. * - The Pstate APIs will overwrite the last 2 powman scratch registers - the other scratch registers are not modified, * so can be used for other persistent data. * \endif @@ -92,7 +92,7 @@ int low_power_sleep_until_irq(const clock_dest_set_t *keep_enabled); /*! \brief Sleep until time using timer * \ingroup pico_low_power * Sleep until the given timer reaches the specified value. The clocks specified in keep_enabled will be kept enabled during sleep, along with clocks required - * for the timer. If exclusive is true, only the timer interrupt will be listened for, otherwise other interrupts will be listened for. + * for the timer. If exclusive is true, only the timer interrupt will be listened for, otherwise other interrupts will also be listened for. * * \param timer The timer to use. * \param until The time to sleep until. @@ -119,11 +119,11 @@ static inline int low_power_sleep_until_default_timer(absolute_time_t until, con /*! \brief Sleep until pin state changes * \ingroup pico_low_power * Sleep until the given GPIO pin changes state. The clocks specified in keep_enabled will be kept enabled during sleep. - * If exclusive is true, only the GPIO interrupt will be listened for, otherwise other interrupts will be listened for. + * If exclusive is true, only the GPIO interrupt will be listened for, otherwise other interrupts will also be listened for. * * \param gpio_pin The GPIO pin to use. * \param edge Whether to listen for edge or level. - * \param high Whether to listen for the high/low level, or rising/falling edge. + * \param high Whether to listen for high level / rising edge (true), or low level / falling edge (false). * \param keep_enabled The clocks to keep enabled during sleep. * \param exclusive Whether to only listen for the GPIO interrupt, or other interrupts. * \return 0 on success, non-zero on error. @@ -142,8 +142,8 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const * * \param until The time to go dormant until. * \param dormant_clock_source The clock source to use for dormant. Must be DORMANT_CLOCK_SOURCE_LPOSC on RP2350. - * \param src_hz The frequency of the clock source on RP2040. Ignored on RP2350. - * \param gpio_pin The GPIO pin to use for the RTC on RP2040. Ignored on RP2350. + * \param src_hz The frequency of the external RTC clock source on RP2040. Ignored on RP2350. + * \param gpio_pin The GPIO pin to use for the external RTC clock source on RP2040. Ignored on RP2350. * \param keep_enabled The clocks to keep enabled during dormant. * \return 0 on success, non-zero on error. */ @@ -161,7 +161,7 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_sourc * * \param gpio_pin The GPIO pin to use. * \param edge Whether to listen for edge or level. - * \param high Whether to listen for the high/low level, or rising/falling edge. + * \param high Whether to listen for high level / rising edge (true), or low level / falling edge (false). * \param dormant_clock_source The clock source to use for dormant. * \param keep_enabled The clocks to keep enabled during dormant. */ From e51ca45c776225782282d154e1659a2822733e2c Mon Sep 17 00:00:00 2001 From: will-v-pi <108662275+will-v-pi@users.noreply.github.com> Date: Tue, 10 Mar 2026 10:18:05 +0000 Subject: [PATCH 067/127] Apply suggestions from code review to low_power.c and low_power.h --- .../pico_low_power/include/pico/low_power.h | 4 +-- src/rp2_common/pico_low_power/low_power.c | 26 ++++++++----------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 5d8a5c207..de4ec46e3 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -136,8 +136,8 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const * The clocks specified in keep_enabled will be kept enabled during dormant, but XOSC and ROSC will be stopped. * * \if (!rp2040_specific) - * If the clock source is set to DORMANT_CLOCK_SOURCE_LPOSC, clk_sys will be run from the ROSC while dormant so - * it can be stopped, while clk_ref will be run from the LPOSC so that continues running for the timer. + * If the clock source is set to DORMANT_CLOCK_SOURCE_LPOSC, clk_sys will be switched to the ROSC while dormant so + * it can be stopped, while clk_ref will be run from the LPOSC so that it continues running for the timer. * \endif * * \param until The time to go dormant until. diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 03ac58373..caa1d53cd 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -181,7 +181,7 @@ static void add_library_clocks(clock_dest_set_t *local_keep_enabled) { #endif } -static uint32_t irq_mask_disabled_during_sleep[NUM_IRQS]; +static uint32_t irq_mask_disabled_during_sleep[((NUM_IRQS-1) / 32)]; static void save_and_disable_other_interrupts(uint32_t irq) { for (uint n = 0; n <= ((NUM_IRQS-1) / 32); n++) { @@ -283,18 +283,16 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, add_library_clocks(&local_keep_enabled); - bool low = !high; - bool level = !edge; - // Configure the appropriate IRQ at IO bank 0 assert(gpio_pin < NUM_BANK0_GPIOS); uint32_t event = 0; - if (level && low) event = GPIO_IRQ_LEVEL_LOW; - if (level && high) event = GPIO_IRQ_LEVEL_HIGH; - if (edge && high) event = GPIO_IRQ_EDGE_RISE; - if (edge && low) event = GPIO_IRQ_EDGE_FALL; + if (edge) { + event = high ? GPIO_IRQ_EDGE_RISE : GPIO_IRQ_EDGE_FALL; + } else { // level + event = high ? GPIO_IRQ_LEVEL_HIGH : GPIO_IRQ_LEVEL_LOW; + } gpio_set_input_enabled(gpio_pin, true); gpio_set_irq_enabled_with_callback(gpio_pin, event, true, low_power_wakeup_gpio); @@ -495,18 +493,16 @@ void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, clock_dest_set_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); - bool low = !high; - bool level = !edge; - // Configure the appropriate IRQ at IO bank 0 assert(gpio_pin < NUM_BANK0_GPIOS); uint32_t event = 0; - if (level && low) event = GPIO_IRQ_LEVEL_LOW; - if (level && high) event = GPIO_IRQ_LEVEL_HIGH; - if (edge && high) event = GPIO_IRQ_EDGE_RISE; - if (edge && low) event = GPIO_IRQ_EDGE_FALL; + if (edge) { + event = high ? GPIO_IRQ_EDGE_RISE : GPIO_IRQ_EDGE_FALL; + } else { // level + event = high ? GPIO_IRQ_LEVEL_HIGH : GPIO_IRQ_LEVEL_LOW; + } gpio_set_input_enabled(gpio_pin, true); gpio_set_dormant_irq_enabled(gpio_pin, event, true); From fa6064c82141409ef3406439189fb0eb6a68f609 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 10 Mar 2026 12:00:22 +0000 Subject: [PATCH 068/127] Review fixups Add NUM_IRQ_WORDS define, and make it give correct value `low_power_sleep_until_pin_state` and dormant equivalent now return 0, so they can return errors if those are added in future --- .../pico_low_power/include/pico/low_power.h | 5 +-- src/rp2_common/pico_low_power/low_power.c | 36 ++++++++++--------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index de4ec46e3..35c2ed91e 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -128,7 +128,7 @@ static inline int low_power_sleep_until_default_timer(absolute_time_t until, con * \param exclusive Whether to only listen for the GPIO interrupt, or other interrupts. * \return 0 on success, non-zero on error. */ -void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_set_t *keep_enabled, bool exclusive); +int low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_set_t *keep_enabled, bool exclusive); /*! \brief Go dormant until time using AON timer * \ingroup pico_low_power @@ -164,8 +164,9 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_sourc * \param high Whether to listen for high level / rising edge (true), or low level / falling edge (false). * \param dormant_clock_source The clock source to use for dormant. * \param keep_enabled The clocks to keep enabled during dormant. + * \return 0 on success, non-zero on error. */ -void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_set_t *keep_enabled); +int low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_set_t *keep_enabled); #if HAS_POWMAN_TIMER /*! \brief Go to Pstate until time using AON timer diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index caa1d53cd..35bb857c2 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -181,10 +181,13 @@ static void add_library_clocks(clock_dest_set_t *local_keep_enabled) { #endif } -static uint32_t irq_mask_disabled_during_sleep[((NUM_IRQS-1) / 32)]; +// Ceiling division of NUM_IRQS by 32 +#define NUM_IRQ_WORDS ((NUM_IRQS / 32) + ((NUM_IRQS % 32) > 0)) + +static uint32_t irq_mask_disabled_during_sleep[NUM_IRQ_WORDS]; static void save_and_disable_other_interrupts(uint32_t irq) { - for (uint n = 0; n <= ((NUM_IRQS-1) / 32); n++) { + for (uint n = 0; n < NUM_IRQ_WORDS; n++) { irq_mask_disabled_during_sleep[n] = irq_get_mask_n(n); if (irq >= n * 32 && irq < (n + 1) * 32) { irq_mask_disabled_during_sleep[n] &= ~(1u << (irq % 32)); @@ -194,7 +197,7 @@ static void save_and_disable_other_interrupts(uint32_t irq) { } static void restore_other_interrupts(void) { - for (uint n = 0; n < NUM_IRQS; n++) { + for (uint n = 0; n < NUM_IRQ_WORDS; n++) { irq_set_mask_n_enabled(n, irq_mask_disabled_during_sleep[n], true); } } @@ -273,7 +276,7 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, return 0; } -void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, +int low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_set_t *keep_enabled, bool exclusive) { event_happened = false; @@ -315,6 +318,8 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, post_clock_gating(); if (exclusive) restore_other_interrupts(); + + return 0; } // In order to go into dormant mode we need to be running from a stoppable clock source: @@ -484,7 +489,7 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, return 0; } -void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, +int low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_set_t *keep_enabled) { @@ -521,6 +526,8 @@ void low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, gpio_set_dormant_irq_enabled(gpio_pin, event, false); low_power_wake_from_dormant(); + + return 0; } #if HAS_POWMAN_TIMER @@ -551,15 +558,11 @@ pstate_bitset_t *low_power_persistent_pstate_get(pstate_bitset_t *pstate) { pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_XIP_CACHE); } else if ((uint32_t)__persistent_data_start__ < SRAM4_BASE) { pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK0); - } else { - pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK1); - } - // Keep __persistent_data_end__ on - if ((uint32_t)__persistent_data_end__ < SRAM_BASE) { - pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_XIP_CACHE); - } else if ((uint32_t)__persistent_data_end__ < SRAM4_BASE) { - pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK0); + // Keep __persistent_data_end__ on too, if it is in SRAM bank 1 + if ((uint32_t)__persistent_data_end__ >= SRAM4_BASE) { + pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK1); + } } else { pstate_bitset_add(pstate, POWMAN_POWER_DOMAIN_SRAM_BANK1); } @@ -675,11 +678,10 @@ PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_low_power_cache_unpin, PICO_RUNTIME_ void __weak __not_in_flash_func(runtime_init_rp2350_sleep_fix)(void) { if (watchdog_hw->reason && WATCHDOG_REASON_TIMER_BITS) { // detect rom_reboot() usage uint32_t flags = save_and_disable_interrupts(); - int32_t num_irq_words = (NUM_IRQS + 31u) / 32u; // Clear (and save) NVIC mask so only the dummy can fire - uint32_t saved_irq_mask[num_irq_words]; - for (int i = 0; i < num_irq_words; ++i) { + uint32_t saved_irq_mask[NUM_IRQ_WORDS]; + for (uint i = 0; i < NUM_IRQ_WORDS; ++i) { saved_irq_mask[i] = nvic_hw->icer[i]; nvic_hw->icer[i] = -1u; } @@ -703,7 +705,7 @@ void __weak __not_in_flash_func(runtime_init_rp2350_sleep_fix)(void) { // Restore NVIC mask nvic_hw->icer[dummy_irq_idx] = 1u << dummy_irq_bit; - for (int i = 0; i < num_irq_words; ++i) { + for (uint i = 0; i < NUM_IRQ_WORDS; ++i) { nvic_hw->iser[i] = saved_irq_mask[i]; } From 298fd2a6bd9f927f5b2371126a2a671bbeb125e2 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 10 Mar 2026 13:08:16 +0000 Subject: [PATCH 069/127] Fix some returns --- src/common/pico_util/include/pico/util/bitset.h | 1 + src/rp2_common/hardware_rtc/include/hardware/rtc.h | 3 ++- src/rp2_common/hardware_rtc/rtc.c | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/common/pico_util/include/pico/util/bitset.h b/src/common/pico_util/include/pico/util/bitset.h index 74bd94b8e..f8ab21d29 100644 --- a/src/common/pico_util/include/pico/util/bitset.h +++ b/src/common/pico_util/include/pico/util/bitset.h @@ -66,6 +66,7 @@ static inline generic_bitset_t *bitset_write_word(generic_bitset_t *bitset, uint if (word_num < bitset_word_size(bitset)) { bitset->words[word_num] = value; } + return bitset; } static inline uint32_t bitset_read_word(const generic_bitset_t *bitset, uint word_num) { diff --git a/src/rp2_common/hardware_rtc/include/hardware/rtc.h b/src/rp2_common/hardware_rtc/include/hardware/rtc.h index 500c4ee4c..6b5576c7f 100644 --- a/src/rp2_common/hardware_rtc/include/hardware/rtc.h +++ b/src/rp2_common/hardware_rtc/include/hardware/rtc.h @@ -95,8 +95,9 @@ void rtc_disable_alarm(void); * * \param src_hz The frequency of the external clock source * \param gpio_pin The input pin providing the external clock (GP20 or GP22) + * \return true if it is possible to run the RTC from the external clock frequency, false otherwise. */ -void rtc_run_from_external_source(uint src_hz, uint gpio_pin); +bool rtc_run_from_external_source(uint32_t src_hz, uint gpio_pin); #ifdef __cplusplus } diff --git a/src/rp2_common/hardware_rtc/rtc.c b/src/rp2_common/hardware_rtc/rtc.c index 1c056a822..faba578c3 100644 --- a/src/rp2_common/hardware_rtc/rtc.c +++ b/src/rp2_common/hardware_rtc/rtc.c @@ -189,6 +189,6 @@ void rtc_disable_alarm(void) { } } -void rtc_run_from_external_source(uint src_hz, uint gpio_pin) { - clock_configure_gpin(clk_rtc, gpio_pin, src_hz, 46875); +bool rtc_run_from_external_source(uint32_t src_hz, uint gpio_pin) { + return clock_configure_gpin(clk_rtc, gpio_pin, src_hz, 46875); } \ No newline at end of file From 77e9e406e177fefd078020ac62103e2cef554186 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 10 Mar 2026 13:53:35 +0000 Subject: [PATCH 070/127] Add some doxygen to bitset.h, and tidy up some macros --- .../pico_util/include/pico/util/bitset.h | 91 +++++++++++++++++++ .../hardware_clocks/include/hardware/clocks.h | 4 +- .../hardware_powman/include/hardware/powman.h | 4 +- 3 files changed, 95 insertions(+), 4 deletions(-) diff --git a/src/common/pico_util/include/pico/util/bitset.h b/src/common/pico_util/include/pico/util/bitset.h index f8ab21d29..269d3142d 100644 --- a/src/common/pico_util/include/pico/util/bitset.h +++ b/src/common/pico_util/include/pico/util/bitset.h @@ -26,6 +26,18 @@ typedef struct { uint32_t words[]; } generic_bitset_t; +/*! \brief Macro used to define a bitset type + * \ingroup pico_util + * This macro is used to define a bitset type. It is used as follows: + * ``` + * typedef bitset_type_t(32) my_bitset_t; + * ``` + * will define a new bitset type called `my_bitset_t` that can hold 32 bits. + * + * The type can be used as `my_bitset_t bitset;` to declare a new bitset. + * + * \param N the number of bits in the bitset + */ #define bitset_type_t(N) union { \ generic_bitset_t bitset; \ struct { \ @@ -36,11 +48,28 @@ typedef struct { } #define bitset_sizeof_for(N) ((((N) + 63u) / 32u) * 4u) +/*! \brief Macro used to create a bitset with all bits set to a value + * \ingroup pico_util + * \param type the type of the bitset + * \param N the number of bits in the bitset + * \param value the value to set the bits to (0 or 1) + * \return the bitset + */ +#define bitset_with_value(type, N, value) ({ type bitset; bitset_init(&bitset, type, N, value); bitset; }) + +// Quick test that the bitset macros give the correct size extern bitset_type_t(32) __not_real_bitset32; extern bitset_type_t(33) __not_real_bitset33; static_assert(sizeof(__not_real_bitset32) == bitset_sizeof_for(1),""); static_assert(sizeof(__not_real_bitset33) == bitset_sizeof_for(37), ""); +/*! \brief Initialize a bitset + * \ingroup pico_util + * \param ptr the bitset to initialize + * \param type the type of the bitset + * \param N the number of bits in the bitset + * \param fill the value to fill the bitset with (0 or 1) + */ #define bitset_init(ptr, type, N, fill) ({ \ assert(sizeof(type) == bitset_sizeof_for(N)); \ __unused type *type_check = ptr; \ @@ -49,18 +78,40 @@ static_assert(sizeof(__not_real_bitset33) == bitset_sizeof_for(37), ""); (ptr)->bitset.word_size = ((N) + 31u) / 32u; \ }) +/*! \brief Get the size of the bitset + * \ingroup pico_util + * \param bitset the bitset to get the size of + * \return the size of the bitset + */ static inline uint bitset_size(const generic_bitset_t *bitset) { return bitset->size; } +/*! \brief Get the size of the bitset in words + * \ingroup pico_util + * \param bitset the bitset to get the size of + * \return the size of the bitset in words + */ static inline uint bitset_word_size(const generic_bitset_t *bitset) { return bitset->word_size; } +/*! \brief Check that the bitset is valid + * \ingroup pico_util + * This function will assert if the bitset is not valid. + * \param bitset the bitset to check + */ static inline void check_bitset(const generic_bitset_t *bitset) { assert(bitset->word_size == (bitset->size + 31) / 32); } +/*! \brief Write a word in the bitset + * \ingroup pico_util + * \param bitset the bitset to write to + * \param word_num the word number to write to + * \param value the value to write to the word + * \return the bitset + */ static inline generic_bitset_t *bitset_write_word(generic_bitset_t *bitset, uint word_num, uint32_t value) { check_bitset(bitset); if (word_num < bitset_word_size(bitset)) { @@ -69,6 +120,12 @@ static inline generic_bitset_t *bitset_write_word(generic_bitset_t *bitset, uint return bitset; } +/*! \brief Read a word in the bitset + * \ingroup pico_util + * \param bitset the bitset to read from + * \param word_num the word number to read from + * \return the value of the word + */ static inline uint32_t bitset_read_word(const generic_bitset_t *bitset, uint word_num) { check_bitset(bitset); if (word_num < bitset_word_size(bitset)) { @@ -77,18 +134,34 @@ static inline uint32_t bitset_read_word(const generic_bitset_t *bitset, uint wor return 0; } +/*! \brief Clear all bits in the bitset + * \ingroup pico_util + * \param bitset the bitset to clear + * \return the bitset + */ static inline generic_bitset_t *bitset_clear(generic_bitset_t *bitset) { check_bitset(bitset); __builtin_memset(bitset->words, 0, bitset->word_size * sizeof(uint32_t)); return bitset; } +/*! \brief Set all bits in the bitset + * \ingroup pico_util + * \param bitset the bitset to set + * \return the bitset + */ static inline generic_bitset_t *bitset_set_all(generic_bitset_t *bitset) { check_bitset(bitset); __builtin_memset(bitset->words, 0xff, bitset->word_size * sizeof(uint32_t)); return bitset; } +/*! \brief Set a single bit in the bitset + * \ingroup pico_util + * \param bitset the bitset to set + * \param bit the bit to set + * \return the bitset + */ static inline generic_bitset_t *bitset_set_bit(generic_bitset_t *bitset, uint bit) { check_bitset(bitset); if (bit < bitset->size) { @@ -97,6 +170,12 @@ static inline generic_bitset_t *bitset_set_bit(generic_bitset_t *bitset, uint bi return bitset; } +/*! \brief Clear a single bit in the bitset + * \ingroup pico_util + * \param bitset the bitset to clear + * \param bit the bit to clear + * \return the bitset + */ static inline generic_bitset_t *bitset_clear_bit(generic_bitset_t *bitset, uint bit) { check_bitset(bitset); if (bit < bitset->size) { @@ -105,6 +184,12 @@ static inline generic_bitset_t *bitset_clear_bit(generic_bitset_t *bitset, uint return bitset; } +/*! \brief Get the value of a single bit in the bitset + * \ingroup pico_util + * \param bitset the bitset to get the value of + * \param bit the bit to get the value of + * \return the value of the bit + */ static inline bool bitset_get_bit(generic_bitset_t *bitset, uint bit) { check_bitset(bitset); assert(bit < bitset->size); @@ -114,6 +199,12 @@ static inline bool bitset_get_bit(generic_bitset_t *bitset, uint bit) { return false; } +/*! \brief Check if two bitsets are equal + * \ingroup pico_util + * \param bitset1 the first bitset to check + * \param bitset2 the second bitset to check + * \return true if the bitsets are equal, false otherwise + */ static inline bool bitset_equal(const generic_bitset_t *bitset1, const generic_bitset_t *bitset2) { check_bitset(bitset1); check_bitset(bitset2); diff --git a/src/rp2_common/hardware_clocks/include/hardware/clocks.h b/src/rp2_common/hardware_clocks/include/hardware/clocks.h index 768988def..48738d230 100644 --- a/src/rp2_common/hardware_clocks/include/hardware/clocks.h +++ b/src/rp2_common/hardware_clocks/include/hardware/clocks.h @@ -581,8 +581,8 @@ static inline bool set_sys_clock_khz(uint32_t freq_khz, bool required) { #include "pico/util/bitset.h" typedef bitset_type_t(NUM_CLOCK_DESTINATIONS) clock_dest_set_t; -#define clock_dest_set_none() ({ clock_dest_set_t bitset; bitset_init(&bitset, clock_dest_set_t, NUM_CLOCK_DESTINATIONS, 0); bitset; }) -#define clock_dest_set_all() ({ clock_dest_set_t bitset; bitset_init(&bitset, clock_dest_set_t, NUM_CLOCK_DESTINATIONS, 1); bitset; }) +#define clock_dest_set_none() bitset_with_value(clock_dest_set_t, NUM_CLOCK_DESTINATIONS, 0) +#define clock_dest_set_all() bitset_with_value(clock_dest_set_t, NUM_CLOCK_DESTINATIONS, 1) static inline clock_dest_set_t *clock_dest_set_clear(clock_dest_set_t *dests) { bitset_clear(&dests->bitset); diff --git a/src/rp2_common/hardware_powman/include/hardware/powman.h b/src/rp2_common/hardware_powman/include/hardware/powman.h index b3c530cb9..161764c12 100644 --- a/src/rp2_common/hardware_powman/include/hardware/powman.h +++ b/src/rp2_common/hardware_powman/include/hardware/powman.h @@ -173,8 +173,8 @@ typedef enum powman_power_domains powman_power_domain_t; typedef uint32_t powman_power_state; typedef bitset_type_t(POWMAN_POWER_DOMAIN_COUNT) pstate_bitset_t; -#define pstate_bitset_none() ({ pstate_bitset_t bitset; bitset_init(&bitset, pstate_bitset_t, POWMAN_POWER_DOMAIN_COUNT, 0); bitset; }) -#define pstate_bitset_all() ({ pstate_bitset_t bitset; bitset_init(&bitset, pstate_bitset_t, POWMAN_POWER_DOMAIN_COUNT, 1); bitset; }) +#define pstate_bitset_none() bitset_with_value(pstate_bitset_t, POWMAN_POWER_DOMAIN_COUNT, 0) +#define pstate_bitset_all() bitset_with_value(pstate_bitset_t, POWMAN_POWER_DOMAIN_COUNT, 1) static inline pstate_bitset_t *pstate_bitset_clear(pstate_bitset_t *domains) { bitset_clear(&domains->bitset); From d249a90cbc5c3941beb187fd32598ae588486cd6 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 10 Mar 2026 14:00:28 +0000 Subject: [PATCH 071/127] Rename clock_dest_set_... to clock_dest_bitset_... to avoid confusing function names (eg clock_dest_set_all) --- src/rp2_common/hardware_clocks/clocks.c | 4 +- .../hardware_clocks/include/hardware/clocks.h | 18 +++---- .../pico_low_power/include/pico/low_power.h | 12 ++--- src/rp2_common/pico_low_power/low_power.c | 52 +++++++++---------- test/hello_sleep/hello_sleep_gpio.c | 8 +-- 5 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/rp2_common/hardware_clocks/clocks.c b/src/rp2_common/hardware_clocks/clocks.c index 8870a9478..8243b6e73 100644 --- a/src/rp2_common/hardware_clocks/clocks.c +++ b/src/rp2_common/hardware_clocks/clocks.c @@ -443,14 +443,14 @@ bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_out, uint *postdiv1_out, u } -void clock_get_sleep_en_gate(clock_dest_set_t *dests) { +void clock_get_sleep_en_gate(clock_dest_bitset_t *dests) { static_assert(CLOCKS_SLEEP_EN1_OFFSET == CLOCKS_SLEEP_EN0_OFFSET + 4, ""); for(uint i=0;i < bitset_word_size(&dests->bitset); i++) { bitset_write_word(&dests->bitset, i, clocks_hw->sleep_en[i]); } } -void clock_gate_sleep_en(const clock_dest_set_t *dests) { +void clock_gate_sleep_en(const clock_dest_bitset_t *dests) { static_assert(CLOCKS_SLEEP_EN1_OFFSET == CLOCKS_SLEEP_EN0_OFFSET + 4, ""); for(uint i=0;i < bitset_word_size(&dests->bitset); i++) { clocks_hw->sleep_en[i] = bitset_read_word(&dests->bitset, i); diff --git a/src/rp2_common/hardware_clocks/include/hardware/clocks.h b/src/rp2_common/hardware_clocks/include/hardware/clocks.h index 48738d230..397d8b82a 100644 --- a/src/rp2_common/hardware_clocks/include/hardware/clocks.h +++ b/src/rp2_common/hardware_clocks/include/hardware/clocks.h @@ -580,32 +580,32 @@ static inline bool set_sys_clock_khz(uint32_t freq_khz, bool required) { #include "pico/util/bitset.h" -typedef bitset_type_t(NUM_CLOCK_DESTINATIONS) clock_dest_set_t; -#define clock_dest_set_none() bitset_with_value(clock_dest_set_t, NUM_CLOCK_DESTINATIONS, 0) -#define clock_dest_set_all() bitset_with_value(clock_dest_set_t, NUM_CLOCK_DESTINATIONS, 1) +typedef bitset_type_t(NUM_CLOCK_DESTINATIONS) clock_dest_bitset_t; +#define clock_dest_bitset_none() bitset_with_value(clock_dest_bitset_t, NUM_CLOCK_DESTINATIONS, 0) +#define clock_dest_bitset_all() bitset_with_value(clock_dest_bitset_t, NUM_CLOCK_DESTINATIONS, 1) -static inline clock_dest_set_t *clock_dest_set_clear(clock_dest_set_t *dests) { +static inline clock_dest_bitset_t *clock_dest_bitset_clear(clock_dest_bitset_t *dests) { bitset_clear(&dests->bitset); return dests; } -static inline clock_dest_set_t *clock_dest_set_add_all(clock_dest_set_t *dests) { +static inline clock_dest_bitset_t *clock_dest_bitset_add_all(clock_dest_bitset_t *dests) { bitset_set_all(&dests->bitset); return dests; } -static inline clock_dest_set_t *clock_dest_set_add(clock_dest_set_t *dests, clock_dest_num_t dest) { +static inline clock_dest_bitset_t *clock_dest_bitset_add(clock_dest_bitset_t *dests, clock_dest_num_t dest) { bitset_set_bit(&dests->bitset, dest); return dests; } -static inline clock_dest_set_t *clock_dest_set_remove(clock_dest_set_t *dests, clock_dest_num_t dest) { +static inline clock_dest_bitset_t *clock_dest_bitset_remove(clock_dest_bitset_t *dests, clock_dest_num_t dest) { bitset_clear_bit(&dests->bitset, dest); return dests; } -void clock_get_sleep_en_gate(clock_dest_set_t *clocks); -void clock_gate_sleep_en(const clock_dest_set_t *clocks); +void clock_get_sleep_en_gate(clock_dest_bitset_t *clocks); +void clock_gate_sleep_en(const clock_dest_bitset_t *clocks); #define GPIO_TO_GPOUT_CLOCK_HANDLE_RP2040(gpio, default_clk_handle) \ ((gpio) == 21 ? clk_gpout0 : \ diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 35c2ed91e..d26c9ab8d 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -87,7 +87,7 @@ typedef void (*low_power_pstate_resume_func)(pstate_bitset_t *pstate); * \param keep_enabled The clocks to keep enabled during sleep. * \return 0 on success, non-zero on error. */ -int low_power_sleep_until_irq(const clock_dest_set_t *keep_enabled); +int low_power_sleep_until_irq(const clock_dest_bitset_t *keep_enabled); /*! \brief Sleep until time using timer * \ingroup pico_low_power @@ -100,7 +100,7 @@ int low_power_sleep_until_irq(const clock_dest_set_t *keep_enabled); * \param exclusive Whether to only listen for the timer interrupt, or other interrupts. * \return 0 on success, non-zero on error. */ -int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, const clock_dest_set_t *keep_enabled, bool exclusive); +int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, const clock_dest_bitset_t *keep_enabled, bool exclusive); /*! \brief Sleep until time using default timer * \ingroup pico_low_power @@ -111,7 +111,7 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, const * \param exclusive Whether to only listen for the timer interrupt, or other interrupts. * \return 0 on success, non-zero on error. */ -static inline int low_power_sleep_until_default_timer(absolute_time_t until, const clock_dest_set_t *keep_enabled, bool exclusive) { +static inline int low_power_sleep_until_default_timer(absolute_time_t until, const clock_dest_bitset_t *keep_enabled, bool exclusive) { return low_power_sleep_until_timer(PICO_DEFAULT_TIMER_INSTANCE(), until, keep_enabled, exclusive); } @@ -128,7 +128,7 @@ static inline int low_power_sleep_until_default_timer(absolute_time_t until, con * \param exclusive Whether to only listen for the GPIO interrupt, or other interrupts. * \return 0 on success, non-zero on error. */ -int low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_set_t *keep_enabled, bool exclusive); +int low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_bitset_t *keep_enabled, bool exclusive); /*! \brief Go dormant until time using AON timer * \ingroup pico_low_power @@ -147,7 +147,7 @@ int low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const c * \param keep_enabled The clocks to keep enabled during dormant. * \return 0 on success, non-zero on error. */ -int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_source_t dormant_clock_source, uint src_hz, uint gpio_pin, const clock_dest_set_t *keep_enabled); +int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_source_t dormant_clock_source, uint src_hz, uint gpio_pin, const clock_dest_bitset_t *keep_enabled); /*! \brief Go dormant until pin state changes * \ingroup pico_low_power @@ -166,7 +166,7 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_sourc * \param keep_enabled The clocks to keep enabled during dormant. * \return 0 on success, non-zero on error. */ -int low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_set_t *keep_enabled); +int low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_bitset_t *keep_enabled); #if HAS_POWMAN_TIMER /*! \brief Go to Pstate until time using AON timer diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 35bb857c2..7736eeadf 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -54,7 +54,7 @@ static void prepare_for_clock_gating(void) { static void post_clock_gating(void) { // restore all clocks in sleep mode, to prevent other __wfi from causing issues - clock_dest_set_t all = clock_dest_set_all(); + clock_dest_bitset_t all = clock_dest_bitset_all(); clock_gate_sleep_en(&all); } @@ -150,25 +150,25 @@ static void low_power_wakeup_gpio(__unused uint gpio, __unused uint32_t event_ma low_power_wakeup(); } -static void replace_null_enable_values(const clock_dest_set_t *keep_enabled, - clock_dest_set_t *local_keep_enabled) { +static void replace_null_enable_values(const clock_dest_bitset_t *keep_enabled, + clock_dest_bitset_t *local_keep_enabled) { if (keep_enabled) { *local_keep_enabled = *keep_enabled; } else { // default to keep nothing on - *local_keep_enabled = clock_dest_set_none(); + *local_keep_enabled = clock_dest_bitset_none(); } } -static void add_library_clocks(clock_dest_set_t *local_keep_enabled) { +static void add_library_clocks(clock_dest_bitset_t *local_keep_enabled) { #if LIB_PICO_STDIO_USB || LIB_TINYUSB_HOST || LIB_TINYUSB_DEVICE // this is necessary to prevent dropping the connection #if PICO_RP2040 - clock_dest_set_add(local_keep_enabled, CLK_DEST_SYS_USBCTRL); - clock_dest_set_add(local_keep_enabled, CLK_DEST_USB_USBCTRL); + clock_dest_bitset_add(local_keep_enabled, CLK_DEST_SYS_USBCTRL); + clock_dest_bitset_add(local_keep_enabled, CLK_DEST_USB_USBCTRL); #elif PICO_RP2350 - clock_dest_set_add(local_keep_enabled, CLK_DEST_SYS_USBCTRL); - clock_dest_set_add(local_keep_enabled, CLK_DEST_USB); + clock_dest_bitset_add(local_keep_enabled, CLK_DEST_SYS_USBCTRL); + clock_dest_bitset_add(local_keep_enabled, CLK_DEST_USB); #else #error Unknown processor #endif @@ -176,8 +176,8 @@ static void add_library_clocks(clock_dest_set_t *local_keep_enabled) { #if LIB_PICO_STDIO_UART // this is only needed to prevent losing stdin while sleeping - clock_dest_set_add(local_keep_enabled, PICO_DEFAULT_UART ? CLK_DEST_PERI_UART1 : CLK_DEST_PERI_UART0); - clock_dest_set_add(local_keep_enabled, PICO_DEFAULT_UART ? CLK_DEST_SYS_UART1 : CLK_DEST_SYS_UART0); + clock_dest_bitset_add(local_keep_enabled, PICO_DEFAULT_UART ? CLK_DEST_PERI_UART1 : CLK_DEST_PERI_UART0); + clock_dest_bitset_add(local_keep_enabled, PICO_DEFAULT_UART ? CLK_DEST_SYS_UART1 : CLK_DEST_SYS_UART0); #endif } @@ -202,8 +202,8 @@ static void restore_other_interrupts(void) { } } -int low_power_sleep_until_irq(const clock_dest_set_t *keep_enabled) { - clock_dest_set_t local_keep_enabled; +int low_power_sleep_until_irq(const clock_dest_bitset_t *keep_enabled) { + clock_dest_bitset_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); add_library_clocks(&local_keep_enabled); @@ -224,7 +224,7 @@ int low_power_sleep_until_irq(const clock_dest_set_t *keep_enabled) { // only the deep_sleep variant of this, as DORMANT cannot wake from TIMER int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, - const clock_dest_set_t *keep_enabled, bool exclusive) { + const clock_dest_bitset_t *keep_enabled, bool exclusive) { int alarm_num = timer_hardware_alarm_claim_unused(timer, false); if (alarm_num < 0) return PICO_ERROR_INSUFFICIENT_RESOURCES; @@ -236,13 +236,13 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, return 0; } - clock_dest_set_t local_keep_enabled; + clock_dest_bitset_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); #if PICO_RP2040 - clock_dest_set_add(&local_keep_enabled, CLK_DEST_SYS_TIMER); + clock_dest_bitset_add(&local_keep_enabled, CLK_DEST_SYS_TIMER); #elif PICO_RP2350 - clock_dest_set_add(&local_keep_enabled, timer_get_index(timer) ? CLK_DEST_SYS_TIMER1 : CLK_DEST_SYS_TIMER0); - clock_dest_set_add(&local_keep_enabled, CLK_DEST_REF_TICKS); + clock_dest_bitset_add(&local_keep_enabled, timer_get_index(timer) ? CLK_DEST_SYS_TIMER1 : CLK_DEST_SYS_TIMER0); + clock_dest_bitset_add(&local_keep_enabled, CLK_DEST_REF_TICKS); #else #error Unknown processor #endif @@ -277,11 +277,11 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, } int low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, - const clock_dest_set_t *keep_enabled, bool exclusive) { + const clock_dest_bitset_t *keep_enabled, bool exclusive) { event_happened = false; - clock_dest_set_t local_keep_enabled; + clock_dest_bitset_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); add_library_clocks(&local_keep_enabled); @@ -444,16 +444,16 @@ void low_power_go_dormant(dormant_clock_source_t dormant_clock_source) { int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_source_t dormant_clock_source, uint src_hz, uint gpio_pin, - const clock_dest_set_t *keep_enabled) { + const clock_dest_bitset_t *keep_enabled) { low_power_setup_clocks_for_dormant(dormant_clock_source); - clock_dest_set_t local_keep_enabled; + clock_dest_bitset_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); #if PICO_RP2040 // The RTC must be run from an external source, since the dormant source will be inactive rtc_run_from_external_source(src_hz, gpio_pin); - clock_dest_set_add(&local_keep_enabled, CLK_DEST_RTC_RTC); + clock_dest_bitset_add(&local_keep_enabled, CLK_DEST_RTC_RTC); #elif PICO_RP2350 ((void)src_hz); ((void)gpio_pin); @@ -462,7 +462,7 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, else return PICO_ERROR_INVALID_ARG; - clock_dest_set_add(&local_keep_enabled, CLK_DEST_REF_POWMAN); + clock_dest_bitset_add(&local_keep_enabled, CLK_DEST_REF_POWMAN); #else #error Unknown processor #endif @@ -491,11 +491,11 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, int low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, - const clock_dest_set_t *keep_enabled) { + const clock_dest_bitset_t *keep_enabled) { low_power_setup_clocks_for_dormant(dormant_clock_source); - clock_dest_set_t local_keep_enabled; + clock_dest_bitset_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); // Configure the appropriate IRQ at IO bank 0 diff --git a/test/hello_sleep/hello_sleep_gpio.c b/test/hello_sleep/hello_sleep_gpio.c index f2789f618..335199b1e 100644 --- a/test/hello_sleep/hello_sleep_gpio.c +++ b/test/hello_sleep/hello_sleep_gpio.c @@ -94,12 +94,12 @@ int main() { printf("Going to non-exclusive sleep until GPIO wakeup\n"); // need to keep the timer running - clock_dest_set_t keep_enabled = clock_dest_set_none(); + clock_dest_bitset_t keep_enabled = clock_dest_bitset_none(); #if PICO_RP2040 - clock_dest_set_add(&keep_enabled, CLK_DEST_SYS_TIMER); + clock_dest_bitset_add(&keep_enabled, CLK_DEST_SYS_TIMER); #else - clock_dest_set_add(&keep_enabled, CLK_DEST_SYS_TIMER0); - clock_dest_set_add(&keep_enabled, CLK_DEST_REF_TICKS); + clock_dest_bitset_add(&keep_enabled, CLK_DEST_SYS_TIMER0); + clock_dest_bitset_add(&keep_enabled, CLK_DEST_REF_TICKS); #endif low_power_sleep_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, &keep_enabled, false); From b6589e7d1998979ca5c4427e08a10b8dc51de17a Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 10 Mar 2026 14:10:45 +0000 Subject: [PATCH 072/127] Update copyright years --- src/common/pico_util/include/pico/util/bitset.h | 2 +- src/rp2_common/hardware_rosc/include/hardware/rosc.h | 2 +- src/rp2_common/hardware_rosc/rosc.c | 2 +- src/rp2_common/pico_low_power/include/pico/low_power.h | 2 +- src/rp2_common/pico_low_power/low_power.c | 2 +- test/hello_sleep/hello_sleep.c | 2 +- test/hello_sleep/hello_sleep_gpio.c | 2 +- test/hello_sleep/rtc_clksrc.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/common/pico_util/include/pico/util/bitset.h b/src/common/pico_util/include/pico/util/bitset.h index 269d3142d..4327607af 100644 --- a/src/common/pico_util/include/pico/util/bitset.h +++ b/src/common/pico_util/include/pico/util/bitset.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * Copyright (c) 2026 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/src/rp2_common/hardware_rosc/include/hardware/rosc.h b/src/rp2_common/hardware_rosc/include/hardware/rosc.h index 499bb9cbb..814c0fbdf 100644 --- a/src/rp2_common/hardware_rosc/include/hardware/rosc.h +++ b/src/rp2_common/hardware_rosc/include/hardware/rosc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * Copyright (c) 2026 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/src/rp2_common/hardware_rosc/rosc.c b/src/rp2_common/hardware_rosc/rosc.c index a6e3ee51f..0ebc57f53 100644 --- a/src/rp2_common/hardware_rosc/rosc.c +++ b/src/rp2_common/hardware_rosc/rosc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * Copyright (c) 2026 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index d26c9ab8d..e5d87b3fe 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * Copyright (c) 2026 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 7736eeadf..edfa19203 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * Copyright (c) 2026 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index 538a273d2..bea59ee02 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * Copyright (c) 2026 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/test/hello_sleep/hello_sleep_gpio.c b/test/hello_sleep/hello_sleep_gpio.c index 335199b1e..00492d284 100644 --- a/test/hello_sleep/hello_sleep_gpio.c +++ b/test/hello_sleep/hello_sleep_gpio.c @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * Copyright (c) 2026 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/test/hello_sleep/rtc_clksrc.c b/test/hello_sleep/rtc_clksrc.c index 287903b65..cda603b02 100644 --- a/test/hello_sleep/rtc_clksrc.c +++ b/test/hello_sleep/rtc_clksrc.c @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * Copyright (c) 2026 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ From 50a241b1c8da68efb565f12f5bb544a7cdb27d98 Mon Sep 17 00:00:00 2001 From: will-v-pi <108662275+will-v-pi@users.noreply.github.com> Date: Tue, 10 Mar 2026 14:25:04 +0000 Subject: [PATCH 073/127] Apply some suggestions from code review Co-authored-by: Andrew Scheller --- src/rp2_common/hardware_irq/irq.c | 2 +- src/rp2_common/hardware_powman/include/hardware/powman.h | 1 + src/rp2_common/hardware_rosc/include/hardware/rosc.h | 4 ++-- src/rp2_common/hardware_rosc/rosc.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/rp2_common/hardware_irq/irq.c b/src/rp2_common/hardware_irq/irq.c index 698bb3f7a..2bdc1f656 100644 --- a/src/rp2_common/hardware_irq/irq.c +++ b/src/rp2_common/hardware_irq/irq.c @@ -121,7 +121,7 @@ static inline uint32_t irq_get_mask_n_internal(uint n) { ((void)n); return nvic_hw->iser; #else - // >32 IRQs (well this works for the bottom 32 which is all that is passed in + // >32 IRQs return nvic_hw->iser[n]; #endif } diff --git a/src/rp2_common/hardware_powman/include/hardware/powman.h b/src/rp2_common/hardware_powman/include/hardware/powman.h index 161764c12..62fea4d43 100644 --- a/src/rp2_common/hardware_powman/include/hardware/powman.h +++ b/src/rp2_common/hardware_powman/include/hardware/powman.h @@ -206,6 +206,7 @@ static inline bool pstate_bitset_none_set(pstate_bitset_t *domains) { } static inline pstate_bitset_t *pstate_bitset_from_powman_power_state(pstate_bitset_t *domains, powman_power_state pstate) { + static_assert(sizeof(powman_power_state) <= sizeof(uint32_t)); bitset_write_word(&domains->bitset, 0, pstate); return domains; } diff --git a/src/rp2_common/hardware_rosc/include/hardware/rosc.h b/src/rp2_common/hardware_rosc/include/hardware/rosc.h index 814c0fbdf..4deac0532 100644 --- a/src/rp2_common/hardware_rosc/include/hardware/rosc.h +++ b/src/rp2_common/hardware_rosc/include/hardware/rosc.h @@ -52,7 +52,7 @@ void rosc_disable(void); /*! \brief Put Ring Oscillator in to dormant mode. * \ingroup hardware_rosc * - * The ROSC supports a dormant mode,which stops oscillation until woken up up by an asynchronous interrupt. + * The ROSC supports a dormant mode, which stops oscillation until woken up up by an asynchronous interrupt. * This can either come from the RTC, being clocked by an external clock, or a GPIO pin going high or low. * If no IRQ is configured before going into dormant mode the ROSC will never restart. * @@ -61,7 +61,7 @@ void rosc_disable(void); void rosc_set_dormant(void); /*! \brief Re-enable the ring oscillator so that the processor cores can wake up after sleep/dormant mode - \ingroup hardware_sleep + \ingroup hardware_rosc This must be called at the end of the sleeping period (e.g., in an interrupt service routine) */ diff --git a/src/rp2_common/hardware_rosc/rosc.c b/src/rp2_common/hardware_rosc/rosc.c index 0ebc57f53..4a20bd856 100644 --- a/src/rp2_common/hardware_rosc/rosc.c +++ b/src/rp2_common/hardware_rosc/rosc.c @@ -66,7 +66,7 @@ void rosc_set_dormant(void) { void rosc_restart(void) { //Re-enable the rosc - rosc_write(&rosc_hw->ctrl, ROSC_CTRL_ENABLE_BITS); + rosc_write(&rosc_hw->ctrl, ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB); //Wait for it to become stable once restarted while (!(rosc_hw->status & ROSC_STATUS_STABLE_BITS)); From 97705aaf89ccbf535cc8decc34ddcb617362d48f Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 10 Mar 2026 14:56:10 +0000 Subject: [PATCH 074/127] Improve rosc docs, and add RP2350 notes/asserts --- .../hardware_rosc/include/hardware/rosc.h | 40 +++++++++++++++++-- src/rp2_common/hardware_rosc/rosc.c | 8 +++- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/rp2_common/hardware_rosc/include/hardware/rosc.h b/src/rp2_common/hardware_rosc/include/hardware/rosc.h index 4deac0532..5868236ca 100644 --- a/src/rp2_common/hardware_rosc/include/hardware/rosc.h +++ b/src/rp2_common/hardware_rosc/include/hardware/rosc.h @@ -20,7 +20,7 @@ extern "C" { * Ring Oscillator (ROSC) API * * A Ring Oscillator is an on-chip oscillator that requires no external crystal. Instead, the output is generated from a series of - * inverters that are chained together to create a feedback loop. RP2040 boots from the ring oscillator initially, meaning the + * inverters that are chained together to create a feedback loop. RP2 chips boot from the ring oscillator initially, meaning the * first stages of the bootrom, including booting from SPI flash, will be clocked by the ring oscillator. If your design has a * crystal oscillator, you’ll likely want to switch to this as your reference clock as soon as possible, because the frequency is * more accurate than the ring oscillator. @@ -29,7 +29,7 @@ extern "C" { /*! \brief Set frequency of the Ring Oscillator * \ingroup hardware_rosc * - * \param code The drive strengths. See the RP2040 datasheet for information on this value. + * \param code The drive strengths. See the datasheet for information on this value. */ void rosc_set_freq(uint32_t code); @@ -67,8 +67,15 @@ void rosc_set_dormant(void); */ void rosc_restart(void); -// FIXME: Add doxygen - +/*! \brief Get the next ROSC freq code + * \ingroup hardware_rosc + * + * Given a ROSC freq code, return the next-numerically-higher code. + * Top result bit is set when called on maximum ROSC code. + * + * \param code The current ROSC freq code. + * \return The next ROSC freq code. + */ uint32_t next_rosc_code(uint32_t code); /*! \brief Set the frequency of the Ring Oscillator within a range @@ -89,6 +96,23 @@ uint rosc_find_freq_mhz(uint32_t low_mhz, uint32_t high_mhz); */ uint rosc_measure_freq_khz(void); +/*! \brief Set the output divider of the Ring Oscillator + * \ingroup hardware_rosc + * + * \if rp2040_specific + * div = 0 divides by 32 + * div = 1-31 divides by div + * any other value sets div=31 + * \endif + * + * \if rp2350_specific + * div = 0 divides by 128 + * div = 1-127 divides by div + * any other value sets div=128 + * \endif + * + * \param div The output divider. + */ void rosc_set_div(uint32_t div); inline static void rosc_clear_bad_write(void) { @@ -99,6 +123,14 @@ inline static bool rosc_write_okay(void) { return !(rosc_hw->status & ROSC_STATUS_BADWRITE_BITS); } +/*! \brief Checked write to a Ring Oscillator register + * \ingroup hardware_rosc + * + * Clears the bad write flag and asserts that the write is okay. + * + * \param addr The register address. + * \param value The value to write. + */ inline static void rosc_write(io_rw_32 *addr, uint32_t value) { rosc_clear_bad_write(); assert(rosc_write_okay()); diff --git a/src/rp2_common/hardware_rosc/rosc.c b/src/rp2_common/hardware_rosc/rosc.c index 4a20bd856..d24415e53 100644 --- a/src/rp2_common/hardware_rosc/rosc.c +++ b/src/rp2_common/hardware_rosc/rosc.c @@ -34,13 +34,17 @@ uint rosc_measure_freq_khz(void) { } void rosc_set_div(uint32_t div) { - assert(div <= 31 && div >= 1); +#if PICO_RP2040 + assert(div <= 31 && div >= 0); +#else + assert(div <= 127 && div >= 0); +#endif rosc_write(&rosc_hw->div, ROSC_DIV_VALUE_PASS + div); } void rosc_set_freq(uint32_t code) { rosc_write(&rosc_hw->freqa, (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB) | (code & 0xffffu)); - rosc_write(&rosc_hw->freqb, (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB) | (code >> 16u)); + rosc_write(&rosc_hw->freqb, (ROSC_FREQB_PASSWD_VALUE_PASS << ROSC_FREQB_PASSWD_LSB) | (code >> 16u)); } void rosc_set_range(uint range) { From 8b9d9ec6389ee3b3bfbddfa8c86153c6d80ca273 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 19 Mar 2026 10:25:06 +0000 Subject: [PATCH 075/127] Rename standard_scripts and platform_scripts to script_include --- src/rp2040/pico_platform_link/BUILD.bazel | 16 ++++++++-------- .../BUILD.bazel | 0 .../default_locations.ld | 0 .../section_copy_to_ram_text.ld | 0 .../section_default_text.ld | 0 .../section_no_flash_text.ld | 0 .../section_platform_end.ld | 0 src/rp2350/pico_platform_link/BUILD.bazel | 12 ++++++------ .../BUILD.bazel | 0 .../default_locations.ld | 0 .../section_platform_end.ld | 0 src/rp2_common/pico_standard_link/CMakeLists.txt | 6 +++--- .../BUILD.bazel | 0 .../memmap_copy_to_ram.ld | 0 .../memmap_default.ld | 0 .../memmap_no_flash.ld | 0 .../memory_aliases_default.ld | 0 .../memory_aliases_no_flash.ld | 0 .../memory_flash.ld | 0 .../memory_ram.ld | 0 .../memory_scratch.ld | 0 .../memory_xip_ram.ld | 0 .../section_copy_to_ram_data.ld | 0 .../section_copy_to_ram_text.ld | 0 .../section_default_data.ld | 0 .../section_default_rodata_excludes.ld | 0 .../section_default_text.ld | 0 .../section_default_text_excludes.ld | 0 .../section_end.ld | 0 .../section_flash_end.ld | 0 .../section_heap.ld | 0 .../section_no_flash_data.ld | 0 .../section_no_flash_text.ld | 0 .../section_scratch.ld | 0 .../sections_copy_to_ram.ld | 0 .../sections_default.ld | 0 .../sections_no_flash.ld | 0 .../set_memory_locations.ld | 0 38 files changed, 17 insertions(+), 17 deletions(-) rename src/rp2040/pico_platform_link/{platform_scripts => script_include}/BUILD.bazel (100%) rename src/rp2040/pico_platform_link/{platform_scripts => script_include}/default_locations.ld (100%) rename src/rp2040/pico_platform_link/{platform_scripts => script_include}/section_copy_to_ram_text.ld (100%) rename src/rp2040/pico_platform_link/{platform_scripts => script_include}/section_default_text.ld (100%) rename src/rp2040/pico_platform_link/{platform_scripts => script_include}/section_no_flash_text.ld (100%) rename src/rp2040/pico_platform_link/{platform_scripts => script_include}/section_platform_end.ld (100%) rename src/rp2350/pico_platform_link/{platform_scripts => script_include}/BUILD.bazel (100%) rename src/rp2350/pico_platform_link/{platform_scripts => script_include}/default_locations.ld (100%) rename src/rp2350/pico_platform_link/{platform_scripts => script_include}/section_platform_end.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/BUILD.bazel (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/memmap_copy_to_ram.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/memmap_default.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/memmap_no_flash.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/memory_aliases_default.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/memory_aliases_no_flash.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/memory_flash.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/memory_ram.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/memory_scratch.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/memory_xip_ram.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/section_copy_to_ram_data.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/section_copy_to_ram_text.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/section_default_data.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/section_default_rodata_excludes.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/section_default_text.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/section_default_text_excludes.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/section_end.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/section_flash_end.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/section_heap.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/section_no_flash_data.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/section_no_flash_text.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/section_scratch.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/sections_copy_to_ram.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/sections_default.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/sections_no_flash.ld (100%) rename src/rp2_common/pico_standard_link/{standard_scripts => script_include}/set_memory_locations.ld (100%) diff --git a/src/rp2040/pico_platform_link/BUILD.bazel b/src/rp2040/pico_platform_link/BUILD.bazel index 0a3556242..d35bfaf1d 100644 --- a/src/rp2040/pico_platform_link/BUILD.bazel +++ b/src/rp2040/pico_platform_link/BUILD.bazel @@ -38,8 +38,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2040/pico_platform_link/platform_scripts:rp2040_linker_scripts", - "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", + "//src/rp2040/pico_platform_link/script_include:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_default.ld", "memmap_default_args", @@ -53,8 +53,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2040/pico_platform_link/platform_scripts:rp2040_linker_scripts", - "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", + "//src/rp2040/pico_platform_link/script_include:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_blocked_ram.ld", "memmap_blocked_ram_args", @@ -68,8 +68,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2040/pico_platform_link/platform_scripts:rp2040_linker_scripts", - "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", + "//src/rp2040/pico_platform_link/script_include:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_copy_to_ram.ld", "memmap_copy_to_ram_args", @@ -83,8 +83,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2040/pico_platform_link/platform_scripts:rp2040_linker_scripts", - "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", + "//src/rp2040/pico_platform_link/script_include:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", "memmap_no_flash.ld", "memmap_no_flash_args", ], diff --git a/src/rp2040/pico_platform_link/platform_scripts/BUILD.bazel b/src/rp2040/pico_platform_link/script_include/BUILD.bazel similarity index 100% rename from src/rp2040/pico_platform_link/platform_scripts/BUILD.bazel rename to src/rp2040/pico_platform_link/script_include/BUILD.bazel diff --git a/src/rp2040/pico_platform_link/platform_scripts/default_locations.ld b/src/rp2040/pico_platform_link/script_include/default_locations.ld similarity index 100% rename from src/rp2040/pico_platform_link/platform_scripts/default_locations.ld rename to src/rp2040/pico_platform_link/script_include/default_locations.ld diff --git a/src/rp2040/pico_platform_link/platform_scripts/section_copy_to_ram_text.ld b/src/rp2040/pico_platform_link/script_include/section_copy_to_ram_text.ld similarity index 100% rename from src/rp2040/pico_platform_link/platform_scripts/section_copy_to_ram_text.ld rename to src/rp2040/pico_platform_link/script_include/section_copy_to_ram_text.ld diff --git a/src/rp2040/pico_platform_link/platform_scripts/section_default_text.ld b/src/rp2040/pico_platform_link/script_include/section_default_text.ld similarity index 100% rename from src/rp2040/pico_platform_link/platform_scripts/section_default_text.ld rename to src/rp2040/pico_platform_link/script_include/section_default_text.ld diff --git a/src/rp2040/pico_platform_link/platform_scripts/section_no_flash_text.ld b/src/rp2040/pico_platform_link/script_include/section_no_flash_text.ld similarity index 100% rename from src/rp2040/pico_platform_link/platform_scripts/section_no_flash_text.ld rename to src/rp2040/pico_platform_link/script_include/section_no_flash_text.ld diff --git a/src/rp2040/pico_platform_link/platform_scripts/section_platform_end.ld b/src/rp2040/pico_platform_link/script_include/section_platform_end.ld similarity index 100% rename from src/rp2040/pico_platform_link/platform_scripts/section_platform_end.ld rename to src/rp2040/pico_platform_link/script_include/section_platform_end.ld diff --git a/src/rp2350/pico_platform_link/BUILD.bazel b/src/rp2350/pico_platform_link/BUILD.bazel index d3aae9161..31bc624f4 100644 --- a/src/rp2350/pico_platform_link/BUILD.bazel +++ b/src/rp2350/pico_platform_link/BUILD.bazel @@ -37,8 +37,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2350/pico_platform_link/platform_scripts:rp2350_linker_scripts", - "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", + "//src/rp2350/pico_platform_link/script_include:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_default.ld", "memmap_default_args", @@ -52,8 +52,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2350/pico_platform_link/platform_scripts:rp2350_linker_scripts", - "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", + "//src/rp2350/pico_platform_link/script_include:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", "memmap_copy_to_ram.ld", "memmap_copy_to_ram_args", @@ -67,8 +67,8 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2350/pico_platform_link/platform_scripts:rp2350_linker_scripts", - "//src/rp2_common/pico_standard_link/standard_scripts:rp2_linker_scripts", + "//src/rp2350/pico_platform_link/script_include:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", "memmap_no_flash.ld", "memmap_no_flash_args", ], diff --git a/src/rp2350/pico_platform_link/platform_scripts/BUILD.bazel b/src/rp2350/pico_platform_link/script_include/BUILD.bazel similarity index 100% rename from src/rp2350/pico_platform_link/platform_scripts/BUILD.bazel rename to src/rp2350/pico_platform_link/script_include/BUILD.bazel diff --git a/src/rp2350/pico_platform_link/platform_scripts/default_locations.ld b/src/rp2350/pico_platform_link/script_include/default_locations.ld similarity index 100% rename from src/rp2350/pico_platform_link/platform_scripts/default_locations.ld rename to src/rp2350/pico_platform_link/script_include/default_locations.ld diff --git a/src/rp2350/pico_platform_link/platform_scripts/section_platform_end.ld b/src/rp2350/pico_platform_link/script_include/section_platform_end.ld similarity index 100% rename from src/rp2350/pico_platform_link/platform_scripts/section_platform_end.ld rename to src/rp2350/pico_platform_link/script_include/section_platform_end.ld diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index d1ae1cd2a..af51a69ea 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -158,11 +158,11 @@ if (NOT TARGET pico_standard_link) target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_BINARY_DIR}") # add include path for main linker script sections - target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}/platform_scripts") - target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_CURRENT_LIST_DIR}/standard_scripts") + target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}/script_include") + target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_CURRENT_LIST_DIR}/script_include") # add default locations script, so they can be referenced by pico_set_linker_script_var variables - target_link_options(pico_standard_link INTERFACE "LINKER:--script=${PICO_LINKER_SCRIPT_PATH}/platform_scripts/default_locations.ld") + target_link_options(pico_standard_link INTERFACE "LINKER:--script=${PICO_LINKER_SCRIPT_PATH}/script_include/default_locations.ld") # add variables set by pico_set_linker_script_var function target_link_options(pico_standard_link INTERFACE "LINKER:$,,>") diff --git a/src/rp2_common/pico_standard_link/standard_scripts/BUILD.bazel b/src/rp2_common/pico_standard_link/script_include/BUILD.bazel similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/BUILD.bazel rename to src/rp2_common/pico_standard_link/script_include/BUILD.bazel diff --git a/src/rp2_common/pico_standard_link/standard_scripts/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/memmap_copy_to_ram.ld rename to src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/memmap_default.ld b/src/rp2_common/pico_standard_link/script_include/memmap_default.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/memmap_default.ld rename to src/rp2_common/pico_standard_link/script_include/memmap_default.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/memmap_no_flash.ld rename to src/rp2_common/pico_standard_link/script_include/memmap_no_flash.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/memory_aliases_default.ld b/src/rp2_common/pico_standard_link/script_include/memory_aliases_default.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/memory_aliases_default.ld rename to src/rp2_common/pico_standard_link/script_include/memory_aliases_default.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/memory_aliases_no_flash.ld b/src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/memory_aliases_no_flash.ld rename to src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/memory_flash.ld b/src/rp2_common/pico_standard_link/script_include/memory_flash.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/memory_flash.ld rename to src/rp2_common/pico_standard_link/script_include/memory_flash.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/memory_ram.ld b/src/rp2_common/pico_standard_link/script_include/memory_ram.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/memory_ram.ld rename to src/rp2_common/pico_standard_link/script_include/memory_ram.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/memory_scratch.ld b/src/rp2_common/pico_standard_link/script_include/memory_scratch.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/memory_scratch.ld rename to src/rp2_common/pico_standard_link/script_include/memory_scratch.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/memory_xip_ram.ld b/src/rp2_common/pico_standard_link/script_include/memory_xip_ram.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/memory_xip_ram.ld rename to src/rp2_common/pico_standard_link/script_include/memory_xip_ram.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_copy_to_ram_data.ld b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/section_copy_to_ram_data.ld rename to src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_copy_to_ram_text.ld b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/section_copy_to_ram_text.ld rename to src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_default_data.ld b/src/rp2_common/pico_standard_link/script_include/section_default_data.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/section_default_data.ld rename to src/rp2_common/pico_standard_link/script_include/section_default_data.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_default_rodata_excludes.ld b/src/rp2_common/pico_standard_link/script_include/section_default_rodata_excludes.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/section_default_rodata_excludes.ld rename to src/rp2_common/pico_standard_link/script_include/section_default_rodata_excludes.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_default_text.ld b/src/rp2_common/pico_standard_link/script_include/section_default_text.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/section_default_text.ld rename to src/rp2_common/pico_standard_link/script_include/section_default_text.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_default_text_excludes.ld b/src/rp2_common/pico_standard_link/script_include/section_default_text_excludes.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/section_default_text_excludes.ld rename to src/rp2_common/pico_standard_link/script_include/section_default_text_excludes.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_end.ld b/src/rp2_common/pico_standard_link/script_include/section_end.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/section_end.ld rename to src/rp2_common/pico_standard_link/script_include/section_end.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_flash_end.ld b/src/rp2_common/pico_standard_link/script_include/section_flash_end.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/section_flash_end.ld rename to src/rp2_common/pico_standard_link/script_include/section_flash_end.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_heap.ld b/src/rp2_common/pico_standard_link/script_include/section_heap.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/section_heap.ld rename to src/rp2_common/pico_standard_link/script_include/section_heap.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_no_flash_data.ld b/src/rp2_common/pico_standard_link/script_include/section_no_flash_data.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/section_no_flash_data.ld rename to src/rp2_common/pico_standard_link/script_include/section_no_flash_data.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_no_flash_text.ld b/src/rp2_common/pico_standard_link/script_include/section_no_flash_text.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/section_no_flash_text.ld rename to src/rp2_common/pico_standard_link/script_include/section_no_flash_text.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/section_scratch.ld b/src/rp2_common/pico_standard_link/script_include/section_scratch.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/section_scratch.ld rename to src/rp2_common/pico_standard_link/script_include/section_scratch.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/sections_copy_to_ram.ld b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/sections_copy_to_ram.ld rename to src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/sections_default.ld b/src/rp2_common/pico_standard_link/script_include/sections_default.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/sections_default.ld rename to src/rp2_common/pico_standard_link/script_include/sections_default.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/sections_no_flash.ld b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/sections_no_flash.ld rename to src/rp2_common/pico_standard_link/script_include/sections_no_flash.ld diff --git a/src/rp2_common/pico_standard_link/standard_scripts/set_memory_locations.ld b/src/rp2_common/pico_standard_link/script_include/set_memory_locations.ld similarity index 100% rename from src/rp2_common/pico_standard_link/standard_scripts/set_memory_locations.ld rename to src/rp2_common/pico_standard_link/script_include/set_memory_locations.ld From 91c3a9a2d735eb11d9e312cc14402a4f02d65424 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 19 Mar 2026 10:38:36 +0000 Subject: [PATCH 076/127] Move pico_platform_link stuff into pico_plaftorm --- src/cmake/rp2_common.cmake | 1 - src/rp2040/pico_platform/BUILD.bazel | 100 ++++++++++++++++++ src/rp2040/pico_platform/CMakeLists.txt | 6 ++ .../memmap_blocked_ram.ld | 0 .../memmap_copy_to_ram.ld | 0 .../memmap_default.ld | 0 .../memmap_no_flash.ld | 0 .../script_include/BUILD.bazel | 0 .../script_include/default_locations.ld | 0 .../section_copy_to_ram_text.ld | 0 .../script_include/section_default_text.ld | 0 .../script_include/section_no_flash_text.ld | 0 .../script_include/section_platform_end.ld | 0 src/rp2040/pico_platform_link/BUILD.bazel | 91 ---------------- src/rp2040/pico_platform_link/CMakeLists.txt | 6 -- src/rp2350/pico_platform/BUILD.bazel | 81 ++++++++++++++ src/rp2350/pico_platform/CMakeLists.txt | 7 ++ .../memmap_copy_to_ram.ld | 0 .../memmap_default.ld | 0 .../memmap_no_flash.ld | 0 .../script_include/BUILD.bazel | 0 .../script_include/default_locations.ld | 0 .../script_include/section_platform_end.ld | 0 src/rp2350/pico_platform_link/BUILD.bazel | 75 ------------- src/rp2350/pico_platform_link/CMakeLists.txt | 6 -- src/rp2_common/pico_standard_link/BUILD.bazel | 14 +-- 26 files changed, 201 insertions(+), 186 deletions(-) rename src/rp2040/{pico_platform_link => pico_platform}/memmap_blocked_ram.ld (100%) rename src/rp2040/{pico_platform_link => pico_platform}/memmap_copy_to_ram.ld (100%) rename src/rp2040/{pico_platform_link => pico_platform}/memmap_default.ld (100%) rename src/rp2040/{pico_platform_link => pico_platform}/memmap_no_flash.ld (100%) rename src/rp2040/{pico_platform_link => pico_platform}/script_include/BUILD.bazel (100%) rename src/rp2040/{pico_platform_link => pico_platform}/script_include/default_locations.ld (100%) rename src/rp2040/{pico_platform_link => pico_platform}/script_include/section_copy_to_ram_text.ld (100%) rename src/rp2040/{pico_platform_link => pico_platform}/script_include/section_default_text.ld (100%) rename src/rp2040/{pico_platform_link => pico_platform}/script_include/section_no_flash_text.ld (100%) rename src/rp2040/{pico_platform_link => pico_platform}/script_include/section_platform_end.ld (100%) delete mode 100644 src/rp2040/pico_platform_link/BUILD.bazel delete mode 100644 src/rp2040/pico_platform_link/CMakeLists.txt rename src/rp2350/{pico_platform_link => pico_platform}/memmap_copy_to_ram.ld (100%) rename src/rp2350/{pico_platform_link => pico_platform}/memmap_default.ld (100%) rename src/rp2350/{pico_platform_link => pico_platform}/memmap_no_flash.ld (100%) rename src/rp2350/{pico_platform_link => pico_platform}/script_include/BUILD.bazel (100%) rename src/rp2350/{pico_platform_link => pico_platform}/script_include/default_locations.ld (100%) rename src/rp2350/{pico_platform_link => pico_platform}/script_include/section_platform_end.ld (100%) delete mode 100644 src/rp2350/pico_platform_link/BUILD.bazel delete mode 100644 src/rp2350/pico_platform_link/CMakeLists.txt diff --git a/src/cmake/rp2_common.cmake b/src/cmake/rp2_common.cmake index f608e5c05..273839f70 100644 --- a/src/cmake/rp2_common.cmake +++ b/src/cmake/rp2_common.cmake @@ -28,7 +28,6 @@ pico_add_subdirectory(common/hardware_claim) # # RP2040/RP2350 specific From standard build variants pico_add_subdirectory(${RP2_VARIANT_DIR}/pico_platform) -pico_add_subdirectory(${RP2_VARIANT_DIR}/pico_platform_link) pico_add_subdirectory(${RP2_VARIANT_DIR}/hardware_regs) pico_add_subdirectory(${RP2_VARIANT_DIR}/hardware_structs) pico_add_subdirectory(${RP2_VARIANT_DIR}/boot_stage2) diff --git a/src/rp2040/pico_platform/BUILD.bazel b/src/rp2040/pico_platform/BUILD.bazel index dd4412b02..2af1c7750 100644 --- a/src/rp2040/pico_platform/BUILD.bazel +++ b/src/rp2040/pico_platform/BUILD.bazel @@ -54,3 +54,103 @@ cc_library( "//src/rp2_common/pico_standard_link", ], ) + +load("//bazel/util:pico_linker_scripts.bzl", "use_linker_script_file") + +exports_files( + [ + "memmap_blocked_ram.ld", + "memmap_copy_to_ram.ld", + "memmap_default.ld", + "memmap_no_flash.ld", + ], +) + +use_linker_script_file( + name = "memmap_default_args", + script = "memmap_default.ld", +) + +use_linker_script_file( + name = "memmap_blocked_ram_args", + script = "memmap_blocked_ram.ld", +) + +use_linker_script_file( + name = "memmap_copy_to_ram_args", + script = "memmap_copy_to_ram.ld", +) + +use_linker_script_file( + name = "memmap_no_flash_args", + script = "memmap_no_flash.ld", +) + +cc_library( + name = "default_linker_script", + target_compatible_with = ["//bazel/constraint:rp2040"], + visibility = [ + "//src/rp2_common/pico_standard_link:__pkg__", + ], + deps = [ + "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2040/pico_platform/script_include:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", + "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_default.ld", + "memmap_default_args", + ], +) + +# PICO_BUILD_DEFINE: PICO_USE_BLOCKED_RAM, whether this is a 'blocked_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link +cc_library( + name = "blocked_ram_linker_script", + defines = ["PICO_USE_BLOCKED_RAM=1"], + target_compatible_with = ["//bazel/constraint:rp2040"], + visibility = [ + "//src/rp2_common/pico_standard_link:__pkg__", + ], + deps = [ + "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2040/pico_platform/script_include:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", + "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_blocked_ram.ld", + "memmap_blocked_ram_args", + ], +) + +# PICO_BUILD_DEFINE: PICO_COPY_TO_RAM, whether this is a 'copy_to_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link +cc_library( + name = "copy_to_ram_linker_script", + defines = ["PICO_COPY_TO_RAM=1"], + target_compatible_with = ["//bazel/constraint:rp2040"], + visibility = [ + "//src/rp2_common/pico_standard_link:__pkg__", + ], + deps = [ + "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2040/pico_platform/script_include:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", + "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_copy_to_ram.ld", + "memmap_copy_to_ram_args", + ], +) + +# PICO_BUILD_DEFINE: PICO_NO_FLASH, whether this is a 'no_flash' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link +cc_library( + name = "no_flash_linker_script", + defines = ["PICO_NO_FLASH=1"], + target_compatible_with = ["//bazel/constraint:rp2040"], + visibility = [ + "//src/rp2_common/pico_standard_link:__pkg__", + ], + deps = [ + "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2040/pico_platform/script_include:rp2040_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", + "memmap_no_flash.ld", + "memmap_no_flash_args", + ], +) diff --git a/src/rp2040/pico_platform/CMakeLists.txt b/src/rp2040/pico_platform/CMakeLists.txt index 9c91df3ea..5fcba5a44 100644 --- a/src/rp2040/pico_platform/CMakeLists.txt +++ b/src/rp2040/pico_platform/CMakeLists.txt @@ -22,6 +22,12 @@ if (NOT TARGET pico_platform) pico_platform_panic pico_platform_sections ) + + pico_register_common_scope_var(PICO_LINKER_SCRIPT_PATH) + if (NOT PICO_LINKER_SCRIPT_PATH) + set(PICO_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_LIST_DIR}) + endif() + pico_promote_common_scope_vars() endif() function(pico_add_platform_library TARGET) diff --git a/src/rp2040/pico_platform_link/memmap_blocked_ram.ld b/src/rp2040/pico_platform/memmap_blocked_ram.ld similarity index 100% rename from src/rp2040/pico_platform_link/memmap_blocked_ram.ld rename to src/rp2040/pico_platform/memmap_blocked_ram.ld diff --git a/src/rp2040/pico_platform_link/memmap_copy_to_ram.ld b/src/rp2040/pico_platform/memmap_copy_to_ram.ld similarity index 100% rename from src/rp2040/pico_platform_link/memmap_copy_to_ram.ld rename to src/rp2040/pico_platform/memmap_copy_to_ram.ld diff --git a/src/rp2040/pico_platform_link/memmap_default.ld b/src/rp2040/pico_platform/memmap_default.ld similarity index 100% rename from src/rp2040/pico_platform_link/memmap_default.ld rename to src/rp2040/pico_platform/memmap_default.ld diff --git a/src/rp2040/pico_platform_link/memmap_no_flash.ld b/src/rp2040/pico_platform/memmap_no_flash.ld similarity index 100% rename from src/rp2040/pico_platform_link/memmap_no_flash.ld rename to src/rp2040/pico_platform/memmap_no_flash.ld diff --git a/src/rp2040/pico_platform_link/script_include/BUILD.bazel b/src/rp2040/pico_platform/script_include/BUILD.bazel similarity index 100% rename from src/rp2040/pico_platform_link/script_include/BUILD.bazel rename to src/rp2040/pico_platform/script_include/BUILD.bazel diff --git a/src/rp2040/pico_platform_link/script_include/default_locations.ld b/src/rp2040/pico_platform/script_include/default_locations.ld similarity index 100% rename from src/rp2040/pico_platform_link/script_include/default_locations.ld rename to src/rp2040/pico_platform/script_include/default_locations.ld diff --git a/src/rp2040/pico_platform_link/script_include/section_copy_to_ram_text.ld b/src/rp2040/pico_platform/script_include/section_copy_to_ram_text.ld similarity index 100% rename from src/rp2040/pico_platform_link/script_include/section_copy_to_ram_text.ld rename to src/rp2040/pico_platform/script_include/section_copy_to_ram_text.ld diff --git a/src/rp2040/pico_platform_link/script_include/section_default_text.ld b/src/rp2040/pico_platform/script_include/section_default_text.ld similarity index 100% rename from src/rp2040/pico_platform_link/script_include/section_default_text.ld rename to src/rp2040/pico_platform/script_include/section_default_text.ld diff --git a/src/rp2040/pico_platform_link/script_include/section_no_flash_text.ld b/src/rp2040/pico_platform/script_include/section_no_flash_text.ld similarity index 100% rename from src/rp2040/pico_platform_link/script_include/section_no_flash_text.ld rename to src/rp2040/pico_platform/script_include/section_no_flash_text.ld diff --git a/src/rp2040/pico_platform_link/script_include/section_platform_end.ld b/src/rp2040/pico_platform/script_include/section_platform_end.ld similarity index 100% rename from src/rp2040/pico_platform_link/script_include/section_platform_end.ld rename to src/rp2040/pico_platform/script_include/section_platform_end.ld diff --git a/src/rp2040/pico_platform_link/BUILD.bazel b/src/rp2040/pico_platform_link/BUILD.bazel deleted file mode 100644 index d35bfaf1d..000000000 --- a/src/rp2040/pico_platform_link/BUILD.bazel +++ /dev/null @@ -1,91 +0,0 @@ -load("@rules_cc//cc:cc_library.bzl", "cc_library") - -package(default_visibility = ["//visibility:public"]) - -load("//bazel/util:pico_linker_scripts.bzl", "use_linker_script_file") - -exports_files( - [ - "memmap_blocked_ram.ld", - "memmap_copy_to_ram.ld", - "memmap_default.ld", - "memmap_no_flash.ld", - ], -) - -use_linker_script_file( - name = "memmap_default_args", - script = "memmap_default.ld", -) - -use_linker_script_file( - name = "memmap_blocked_ram_args", - script = "memmap_blocked_ram.ld", -) - -use_linker_script_file( - name = "memmap_copy_to_ram_args", - script = "memmap_copy_to_ram.ld", -) - -use_linker_script_file( - name = "memmap_no_flash_args", - script = "memmap_no_flash.ld", -) - -cc_library( - name = "default_linker_script", - target_compatible_with = ["//bazel/constraint:rp2040"], - deps = [ - "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2040/pico_platform_link/script_include:rp2040_linker_scripts", - "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", - "//src/rp2_common/pico_standard_link:default_flash_region", - "memmap_default.ld", - "memmap_default_args", - ], -) - -# PICO_BUILD_DEFINE: PICO_USE_BLOCKED_RAM, whether this is a 'blocked_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link -cc_library( - name = "blocked_ram_linker_script", - defines = ["PICO_USE_BLOCKED_RAM=1"], - target_compatible_with = ["//bazel/constraint:rp2040"], - deps = [ - "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2040/pico_platform_link/script_include:rp2040_linker_scripts", - "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", - "//src/rp2_common/pico_standard_link:default_flash_region", - "memmap_blocked_ram.ld", - "memmap_blocked_ram_args", - ], -) - -# PICO_BUILD_DEFINE: PICO_COPY_TO_RAM, whether this is a 'copy_to_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link -cc_library( - name = "copy_to_ram_linker_script", - defines = ["PICO_COPY_TO_RAM=1"], - target_compatible_with = ["//bazel/constraint:rp2040"], - deps = [ - "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2040/pico_platform_link/script_include:rp2040_linker_scripts", - "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", - "//src/rp2_common/pico_standard_link:default_flash_region", - "memmap_copy_to_ram.ld", - "memmap_copy_to_ram_args", - ], -) - -# PICO_BUILD_DEFINE: PICO_NO_FLASH, whether this is a 'no_flash' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link -cc_library( - name = "no_flash_linker_script", - defines = ["PICO_NO_FLASH=1"], - target_compatible_with = ["//bazel/constraint:rp2040"], - deps = [ - "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2040/pico_platform_link/script_include:rp2040_linker_scripts", - "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", - "memmap_no_flash.ld", - "memmap_no_flash_args", - ], -) diff --git a/src/rp2040/pico_platform_link/CMakeLists.txt b/src/rp2040/pico_platform_link/CMakeLists.txt deleted file mode 100644 index af6943ebd..000000000 --- a/src/rp2040/pico_platform_link/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -pico_register_common_scope_var(PICO_LINKER_SCRIPT_PATH) -if (NOT PICO_LINKER_SCRIPT_PATH) - set(PICO_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_LIST_DIR}) -endif() - -pico_promote_common_scope_vars() \ No newline at end of file diff --git a/src/rp2350/pico_platform/BUILD.bazel b/src/rp2350/pico_platform/BUILD.bazel index f6182b90a..3e5dfde8d 100644 --- a/src/rp2350/pico_platform/BUILD.bazel +++ b/src/rp2350/pico_platform/BUILD.bazel @@ -54,3 +54,84 @@ cc_library( "//src/rp2_common/pico_standard_link", ], ) + +load("//bazel/util:pico_linker_scripts.bzl", "use_linker_script_file") + +exports_files( + [ + "memmap_copy_to_ram.ld", + "memmap_default.ld", + "memmap_no_flash.ld", + ], +) + +use_linker_script_file( + name = "memmap_default_args", + script = "memmap_default.ld", +) + +use_linker_script_file( + name = "memmap_blocked_ram_args", + script = "memmap_blocked_ram.ld", +) + +use_linker_script_file( + name = "memmap_copy_to_ram_args", + script = "memmap_copy_to_ram.ld", +) + +use_linker_script_file( + name = "memmap_no_flash_args", + script = "memmap_no_flash.ld", +) + +cc_library( + name = "default_linker_script", + target_compatible_with = ["//bazel/constraint:rp2350"], + visibility = [ + "//src/rp2_common/pico_standard_link:__pkg__", + ], + deps = [ + "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2350/pico_platform/script_include:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", + "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_default.ld", + "memmap_default_args", + ], +) + +# PICO_BUILD_DEFINE: PICO_COPY_TO_RAM, whether this is a 'copy_to_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link +cc_library( + name = "copy_to_ram_linker_script", + defines = ["PICO_COPY_TO_RAM=1"], + target_compatible_with = ["//bazel/constraint:rp2350"], + visibility = [ + "//src/rp2_common/pico_standard_link:__pkg__", + ], + deps = [ + "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2350/pico_platform/script_include:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", + "//src/rp2_common/pico_standard_link:default_flash_region", + "memmap_copy_to_ram.ld", + "memmap_copy_to_ram_args", + ], +) + +# PICO_BUILD_DEFINE: PICO_NO_FLASH, whether this is a 'no_flash' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link +cc_library( + name = "no_flash_linker_script", + defines = ["PICO_NO_FLASH=1"], + target_compatible_with = ["//bazel/constraint:rp2350"], + visibility = [ + "//src/rp2_common/pico_standard_link:__pkg__", + ], + deps = [ + "//src/rp2_common/pico_crt0:no_warn_rwx_flag", + "//src/rp2350/pico_platform/script_include:rp2350_linker_scripts", + "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", + "memmap_no_flash.ld", + "memmap_no_flash_args", + ], +) diff --git a/src/rp2350/pico_platform/CMakeLists.txt b/src/rp2350/pico_platform/CMakeLists.txt index 7f875bf32..0877c0ddb 100644 --- a/src/rp2350/pico_platform/CMakeLists.txt +++ b/src/rp2350/pico_platform/CMakeLists.txt @@ -33,6 +33,13 @@ if (NOT TARGET pico_platform) if (PICO_RISCV) pico_mirrored_target_link_libraries(pico_platform INTERFACE hardware_hazard3) endif() + + pico_register_common_scope_var(PICO_LINKER_SCRIPT_PATH) + if (NOT PICO_LINKER_SCRIPT_PATH) + set(PICO_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_LIST_DIR}) + endif() + + pico_promote_common_scope_vars() endif() function(pico_add_platform_library TARGET) diff --git a/src/rp2350/pico_platform_link/memmap_copy_to_ram.ld b/src/rp2350/pico_platform/memmap_copy_to_ram.ld similarity index 100% rename from src/rp2350/pico_platform_link/memmap_copy_to_ram.ld rename to src/rp2350/pico_platform/memmap_copy_to_ram.ld diff --git a/src/rp2350/pico_platform_link/memmap_default.ld b/src/rp2350/pico_platform/memmap_default.ld similarity index 100% rename from src/rp2350/pico_platform_link/memmap_default.ld rename to src/rp2350/pico_platform/memmap_default.ld diff --git a/src/rp2350/pico_platform_link/memmap_no_flash.ld b/src/rp2350/pico_platform/memmap_no_flash.ld similarity index 100% rename from src/rp2350/pico_platform_link/memmap_no_flash.ld rename to src/rp2350/pico_platform/memmap_no_flash.ld diff --git a/src/rp2350/pico_platform_link/script_include/BUILD.bazel b/src/rp2350/pico_platform/script_include/BUILD.bazel similarity index 100% rename from src/rp2350/pico_platform_link/script_include/BUILD.bazel rename to src/rp2350/pico_platform/script_include/BUILD.bazel diff --git a/src/rp2350/pico_platform_link/script_include/default_locations.ld b/src/rp2350/pico_platform/script_include/default_locations.ld similarity index 100% rename from src/rp2350/pico_platform_link/script_include/default_locations.ld rename to src/rp2350/pico_platform/script_include/default_locations.ld diff --git a/src/rp2350/pico_platform_link/script_include/section_platform_end.ld b/src/rp2350/pico_platform/script_include/section_platform_end.ld similarity index 100% rename from src/rp2350/pico_platform_link/script_include/section_platform_end.ld rename to src/rp2350/pico_platform/script_include/section_platform_end.ld diff --git a/src/rp2350/pico_platform_link/BUILD.bazel b/src/rp2350/pico_platform_link/BUILD.bazel deleted file mode 100644 index 31bc624f4..000000000 --- a/src/rp2350/pico_platform_link/BUILD.bazel +++ /dev/null @@ -1,75 +0,0 @@ -load("@rules_cc//cc:cc_library.bzl", "cc_library") - -package(default_visibility = ["//visibility:public"]) - -load("//bazel/util:pico_linker_scripts.bzl", "use_linker_script_file") - -exports_files( - [ - "memmap_copy_to_ram.ld", - "memmap_default.ld", - "memmap_no_flash.ld", - ], -) - -use_linker_script_file( - name = "memmap_default_args", - script = "memmap_default.ld", -) - -use_linker_script_file( - name = "memmap_blocked_ram_args", - script = "memmap_blocked_ram.ld", -) - -use_linker_script_file( - name = "memmap_copy_to_ram_args", - script = "memmap_copy_to_ram.ld", -) - -use_linker_script_file( - name = "memmap_no_flash_args", - script = "memmap_no_flash.ld", -) - -cc_library( - name = "default_linker_script", - target_compatible_with = ["//bazel/constraint:rp2350"], - deps = [ - "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2350/pico_platform_link/script_include:rp2350_linker_scripts", - "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", - "//src/rp2_common/pico_standard_link:default_flash_region", - "memmap_default.ld", - "memmap_default_args", - ], -) - -# PICO_BUILD_DEFINE: PICO_COPY_TO_RAM, whether this is a 'copy_to_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link -cc_library( - name = "copy_to_ram_linker_script", - defines = ["PICO_COPY_TO_RAM=1"], - target_compatible_with = ["//bazel/constraint:rp2350"], - deps = [ - "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2350/pico_platform_link/script_include:rp2350_linker_scripts", - "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", - "//src/rp2_common/pico_standard_link:default_flash_region", - "memmap_copy_to_ram.ld", - "memmap_copy_to_ram_args", - ], -) - -# PICO_BUILD_DEFINE: PICO_NO_FLASH, whether this is a 'no_flash' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link -cc_library( - name = "no_flash_linker_script", - defines = ["PICO_NO_FLASH=1"], - target_compatible_with = ["//bazel/constraint:rp2350"], - deps = [ - "//src/rp2_common/pico_crt0:no_warn_rwx_flag", - "//src/rp2350/pico_platform_link/script_include:rp2350_linker_scripts", - "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", - "memmap_no_flash.ld", - "memmap_no_flash_args", - ], -) diff --git a/src/rp2350/pico_platform_link/CMakeLists.txt b/src/rp2350/pico_platform_link/CMakeLists.txt deleted file mode 100644 index af6943ebd..000000000 --- a/src/rp2350/pico_platform_link/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -pico_register_common_scope_var(PICO_LINKER_SCRIPT_PATH) -if (NOT PICO_LINKER_SCRIPT_PATH) - set(PICO_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_LIST_DIR}) -endif() - -pico_promote_common_scope_vars() \ No newline at end of file diff --git a/src/rp2_common/pico_standard_link/BUILD.bazel b/src/rp2_common/pico_standard_link/BUILD.bazel index 924358d50..8817018a8 100644 --- a/src/rp2_common/pico_standard_link/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/BUILD.bazel @@ -30,8 +30,8 @@ generated_pico_flash_region( alias( name = "default_linker_script", actual = select({ - "//bazel/constraint:rp2040": "//src/rp2040/pico_platform_link:default_linker_script", - "//bazel/constraint:rp2350": "//src/rp2350/pico_platform_link:default_linker_script", + "//bazel/constraint:rp2040": "//src/rp2040/pico_platform:default_linker_script", + "//bazel/constraint:rp2350": "//src/rp2350/pico_platform:default_linker_script", "//conditions:default": "//bazel:incompatible_cc_lib", }), ) @@ -39,7 +39,7 @@ alias( alias( name = "blocked_ram_linker_script", actual = select({ - "//bazel/constraint:rp2040": "//src/rp2040/pico_platform_link:blocked_ram_linker_script", + "//bazel/constraint:rp2040": "//src/rp2040/pico_platform:blocked_ram_linker_script", "//conditions:default": "//bazel:incompatible_cc_lib", }), ) @@ -47,8 +47,8 @@ alias( alias( name = "copy_to_ram_linker_script", actual = select({ - "//bazel/constraint:rp2040": "//src/rp2040/pico_platform_link:copy_to_ram_linker_script", - "//bazel/constraint:rp2350": "//src/rp2350/pico_platform_link:copy_to_ram_linker_script", + "//bazel/constraint:rp2040": "//src/rp2040/pico_platform:copy_to_ram_linker_script", + "//bazel/constraint:rp2350": "//src/rp2350/pico_platform:copy_to_ram_linker_script", "//conditions:default": "//bazel:incompatible_cc_lib", }), ) @@ -56,8 +56,8 @@ alias( alias( name = "no_flash_linker_script", actual = select({ - "//bazel/constraint:rp2040": "//src/rp2040/pico_platform_link:no_flash_linker_script", - "//bazel/constraint:rp2350": "//src/rp2350/pico_platform_link:no_flash_linker_script", + "//bazel/constraint:rp2040": "//src/rp2040/pico_platform:no_flash_linker_script", + "//bazel/constraint:rp2350": "//src/rp2350/pico_platform:no_flash_linker_script", "//conditions:default": "//bazel:incompatible_cc_lib", }), ) From 614f7f064fb7df5d740eef966d89c840325ba161 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 19 Mar 2026 11:20:03 +0000 Subject: [PATCH 077/127] Remove rigidity from linker include paths Add PICO_LINKER_SCRIPT_INCLUDE_DIRS and PICO_LINKER_DEFAULT_LOCATIONS_PATH, instead of hardcoded paths under PICO_LINKER_SCRIPT_PATH Also improve pico_set_linker_script_var and pico_add_linker_script_override_path to better utilise generator expressions --- src/rp2040/pico_platform/CMakeLists.txt | 9 +++++++ src/rp2350/pico_platform/CMakeLists.txt | 8 ++++++ .../pico_standard_link/CMakeLists.txt | 27 +++++++++++++------ 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/rp2040/pico_platform/CMakeLists.txt b/src/rp2040/pico_platform/CMakeLists.txt index 5fcba5a44..d43f96b91 100644 --- a/src/rp2040/pico_platform/CMakeLists.txt +++ b/src/rp2040/pico_platform/CMakeLists.txt @@ -27,6 +27,15 @@ if (NOT TARGET pico_platform) if (NOT PICO_LINKER_SCRIPT_PATH) set(PICO_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_LIST_DIR}) endif() + + pico_register_common_scope_var(PICO_LINKER_DEFAULT_LOCATIONS_PATH) + if (NOT PICO_LINKER_DEFAULT_LOCATIONS_PATH) + set(PICO_LINKER_DEFAULT_LOCATIONS_PATH ${CMAKE_CURRENT_LIST_DIR}/script_include/default_locations.ld) + endif() + + pico_register_common_scope_var(PICO_LINKER_SCRIPT_INCLUDE_DIRS) + list(APPEND PICO_LINKER_SCRIPT_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/script_include) + pico_promote_common_scope_vars() endif() diff --git a/src/rp2350/pico_platform/CMakeLists.txt b/src/rp2350/pico_platform/CMakeLists.txt index 0877c0ddb..636f3fe83 100644 --- a/src/rp2350/pico_platform/CMakeLists.txt +++ b/src/rp2350/pico_platform/CMakeLists.txt @@ -39,6 +39,14 @@ if (NOT TARGET pico_platform) set(PICO_LINKER_SCRIPT_PATH ${CMAKE_CURRENT_LIST_DIR}) endif() + pico_register_common_scope_var(PICO_LINKER_DEFAULT_LOCATIONS_PATH) + if (NOT PICO_LINKER_DEFAULT_LOCATIONS_PATH) + set(PICO_LINKER_DEFAULT_LOCATIONS_PATH ${CMAKE_CURRENT_LIST_DIR}/script_include/default_locations.ld) + endif() + + pico_register_common_scope_var(PICO_LINKER_SCRIPT_INCLUDE_DIRS) + list(APPEND PICO_LINKER_SCRIPT_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/script_include) + pico_promote_common_scope_vars() endif() diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index af51a69ea..9db70b1e6 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -5,6 +5,11 @@ if (NOT TARGET pico_standard_link) target_link_libraries(pico_standard_link INTERFACE boot_stage2_headers) endif() + pico_register_common_scope_var(PICO_LINKER_SCRIPT_INCLUDE_DIRS) + + # add the default linker script include directories + list(APPEND PICO_LINKER_SCRIPT_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/script_include) + # pico_add_link_depend(TARGET dependency) # \brief\ Add a link time dependency to the target # @@ -76,7 +81,7 @@ if (NOT TARGET pico_standard_link) # \param\ NAME Name of variable to set # \param\ VALUE Value of variable to set function(pico_set_linker_script_var TARGET NAME VALUE) - set_property(TARGET ${TARGET} APPEND PROPERTY PICO_TARGET_LINKER_SCRIPT_VARS "--defsym=${NAME}=${VALUE}") + set_property(TARGET ${TARGET} APPEND PROPERTY PICO_TARGET_LINKER_SCRIPT_VARS "${NAME}=${VALUE}") endfunction() # pico_add_linker_script_override_path(TARGET PATH) @@ -89,6 +94,7 @@ if (NOT TARGET pico_standard_link) # include the custom files first, overriding the default ones. # # Must be called before target_link_libraries, otherwise it will not override the default linker scripts. + # It will also not override prior paths set by pico_add_linker_script_override_path. # # \param\ TARGET The target to add the linker script override path to # \param\ PATH The path containing the overriding linker scripts @@ -97,7 +103,7 @@ if (NOT TARGET pico_standard_link) if (OUT) message(WARNING "pico_add_linker_script_override_path does not work when called after target_link_libraries") endif() - target_link_options(${TARGET} PRIVATE "LINKER:-L${PATH}") + set_property(TARGET ${TARGET} APPEND PROPERTY PICO_TARGET_LINKER_SCRIPT_OVERRIDE_PATHS "${PATH}") endfunction() # pico_set_binary_type(TARGET TYPE) @@ -155,17 +161,22 @@ if (NOT TARGET pico_standard_link) set(PICO_FLASH_SIZE_BYTES_STRING "${PICO_FLASH_SIZE_BYTES}") configure_file(${CMAKE_CURRENT_LIST_DIR}/pico_flash_region.template.ld ${CMAKE_BINARY_DIR}/pico_flash_region.ld) # add include path for linker scripts to find it - target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_BINARY_DIR}") + list(APPEND PICO_LINKER_SCRIPT_INCLUDE_DIRS ${CMAKE_BINARY_DIR}) + pico_promote_common_scope_vars() + + # add override paths from PICO_TARGET_LINKER_SCRIPT_OVERRIDE_PATHS + target_link_options(pico_standard_link INTERFACE "LINKER:$<$>:-L$,,-L>>") - # add include path for main linker script sections - target_link_options(pico_standard_link INTERFACE "LINKER:-L${PICO_LINKER_SCRIPT_PATH}/script_include") - target_link_options(pico_standard_link INTERFACE "LINKER:-L${CMAKE_CURRENT_LIST_DIR}/script_include") + # add include paths from PICO_LINKER_SCRIPT_INCLUDE_DIRS + foreach(DIR IN LISTS PICO_LINKER_SCRIPT_INCLUDE_DIRS) + target_link_options(pico_standard_link INTERFACE "LINKER:-L${DIR}") + endforeach() # add default locations script, so they can be referenced by pico_set_linker_script_var variables - target_link_options(pico_standard_link INTERFACE "LINKER:--script=${PICO_LINKER_SCRIPT_PATH}/script_include/default_locations.ld") + target_link_options(pico_standard_link INTERFACE "LINKER:--script=${PICO_LINKER_DEFAULT_LOCATIONS_PATH}") # add variables set by pico_set_linker_script_var function - target_link_options(pico_standard_link INTERFACE "LINKER:$,,>") + target_link_options(pico_standard_link INTERFACE "LINKER:$<$>:--defsym=$,,--defsym=>>") # LINKER script will be PICO_TARGET_LINKER_SCRIPT if set on target, or ${CMAKE_CURRENT_LIST_DIR}/memmap_foo.ld # if PICO_TARGET_BINARY_TYPE is set to foo on the target, otherwise ${CMAKE_CURRENT_LIST_DIR}/memmap_${PICO_DEFAULT_BINARY_TYPE).ld From da23cf426a434fc997f609daaf408e40a117e740 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 19 Mar 2026 11:46:06 +0000 Subject: [PATCH 078/127] Rename all linker scripts intended to be included to .incl Required changes to the way bazel views these files --- .../pico_platform/memmap_blocked_ram.ld | 2 +- .../pico_platform/memmap_copy_to_ram.ld | 2 +- src/rp2040/pico_platform/memmap_default.ld | 2 +- src/rp2040/pico_platform/memmap_no_flash.ld | 2 +- .../pico_platform/script_include/BUILD.bazel | 20 +++--- ..._text.ld => section_copy_to_ram_text.incl} | 0 ...ault_text.ld => section_default_text.incl} | 4 +- ...ash_text.ld => section_no_flash_text.incl} | 0 ...tform_end.ld => section_platform_end.incl} | 0 .../pico_platform/memmap_copy_to_ram.ld | 2 +- src/rp2350/pico_platform/memmap_default.ld | 2 +- src/rp2350/pico_platform/memmap_no_flash.ld | 2 +- .../pico_platform/script_include/BUILD.bazel | 14 +++-- ...tform_end.ld => section_platform_end.incl} | 0 .../script_include/BUILD.bazel | 61 +++---------------- ...map_default.ld => memmap_copy_to_ram.incl} | 12 ++-- ...map_copy_to_ram.ld => memmap_default.incl} | 12 ++-- ...emmap_no_flash.ld => memmap_no_flash.incl} | 10 +-- ...default.ld => memory_aliases_default.incl} | 0 ..._flash.ld => memory_aliases_no_flash.incl} | 0 .../{memory_flash.ld => memory_flash.incl} | 0 .../{memory_ram.ld => memory_ram.incl} | 0 ...{memory_scratch.ld => memory_scratch.incl} | 0 ...{memory_xip_ram.ld => memory_xip_ram.incl} | 0 ..._data.ld => section_copy_to_ram_data.incl} | 0 ..._text.ld => section_copy_to_ram_text.incl} | 0 ...ault_data.ld => section_default_data.incl} | 0 ...d => section_default_rodata_excludes.incl} | 0 ...ault_text.ld => section_default_text.incl} | 4 +- ....ld => section_default_text_excludes.incl} | 0 .../{section_end.ld => section_end.incl} | 0 ...on_flash_end.ld => section_flash_end.incl} | 0 .../{section_heap.ld => section_heap.incl} | 0 ...ash_data.ld => section_no_flash_data.incl} | 0 ...ash_text.ld => section_no_flash_text.incl} | 0 ...ection_scratch.ld => section_scratch.incl} | 0 .../script_include/sections_copy_to_ram.incl | 7 +++ .../script_include/sections_copy_to_ram.ld | 7 --- .../script_include/sections_default.incl | 7 +++ .../script_include/sections_default.ld | 7 --- .../script_include/sections_no_flash.incl | 6 ++ .../script_include/sections_no_flash.ld | 6 -- ...locations.ld => set_memory_locations.incl} | 0 .../sections_default.incl | 19 ++++++ .../sections_default.ld | 19 ------ ...tions_default.ld => sections_default.incl} | 14 ++--- 46 files changed, 98 insertions(+), 145 deletions(-) rename src/rp2040/pico_platform/script_include/{section_copy_to_ram_text.ld => section_copy_to_ram_text.incl} (100%) rename src/rp2040/pico_platform/script_include/{section_default_text.ld => section_default_text.incl} (96%) rename src/rp2040/pico_platform/script_include/{section_no_flash_text.ld => section_no_flash_text.incl} (100%) rename src/rp2040/pico_platform/script_include/{section_platform_end.ld => section_platform_end.incl} (100%) rename src/rp2350/pico_platform/script_include/{section_platform_end.ld => section_platform_end.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{memmap_default.ld => memmap_copy_to_ram.incl} (51%) rename src/rp2_common/pico_standard_link/script_include/{memmap_copy_to_ram.ld => memmap_default.incl} (52%) rename src/rp2_common/pico_standard_link/script_include/{memmap_no_flash.ld => memmap_no_flash.incl} (59%) rename src/rp2_common/pico_standard_link/script_include/{memory_aliases_default.ld => memory_aliases_default.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{memory_aliases_no_flash.ld => memory_aliases_no_flash.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{memory_flash.ld => memory_flash.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{memory_ram.ld => memory_ram.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{memory_scratch.ld => memory_scratch.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{memory_xip_ram.ld => memory_xip_ram.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{section_copy_to_ram_data.ld => section_copy_to_ram_data.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{section_copy_to_ram_text.ld => section_copy_to_ram_text.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{section_default_data.ld => section_default_data.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{section_default_rodata_excludes.ld => section_default_rodata_excludes.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{section_default_text.ld => section_default_text.incl} (97%) rename src/rp2_common/pico_standard_link/script_include/{section_default_text_excludes.ld => section_default_text_excludes.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{section_end.ld => section_end.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{section_flash_end.ld => section_flash_end.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{section_heap.ld => section_heap.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{section_no_flash_data.ld => section_no_flash_data.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{section_no_flash_text.ld => section_no_flash_text.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{section_scratch.ld => section_scratch.incl} (100%) create mode 100644 src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl delete mode 100644 src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.ld create mode 100644 src/rp2_common/pico_standard_link/script_include/sections_default.incl delete mode 100644 src/rp2_common/pico_standard_link/script_include/sections_default.ld create mode 100644 src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl delete mode 100644 src/rp2_common/pico_standard_link/script_include/sections_no_flash.ld rename src/rp2_common/pico_standard_link/script_include/{set_memory_locations.ld => set_memory_locations.incl} (100%) create mode 100644 test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.incl delete mode 100644 test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.ld rename test/kitchen_sink/kitchen_sink_simple_overlay_scripts/{sections_default.ld => sections_default.incl} (57%) diff --git a/src/rp2040/pico_platform/memmap_blocked_ram.ld b/src/rp2040/pico_platform/memmap_blocked_ram.ld index a4a528950..26955f209 100644 --- a/src/rp2040/pico_platform/memmap_blocked_ram.ld +++ b/src/rp2040/pico_platform/memmap_blocked_ram.ld @@ -1,4 +1,4 @@ /* Use blocked ram */ RAM_ORIGIN = 0x21000000; -INCLUDE "memmap_default.ld" +INCLUDE "memmap_default.incl" diff --git a/src/rp2040/pico_platform/memmap_copy_to_ram.ld b/src/rp2040/pico_platform/memmap_copy_to_ram.ld index cd51ceeaa..f0eb74d9f 100644 --- a/src/rp2040/pico_platform/memmap_copy_to_ram.ld +++ b/src/rp2040/pico_platform/memmap_copy_to_ram.ld @@ -1 +1 @@ -INCLUDE "memmap_copy_to_ram.ld" +INCLUDE "memmap_copy_to_ram.incl" diff --git a/src/rp2040/pico_platform/memmap_default.ld b/src/rp2040/pico_platform/memmap_default.ld index c256a9071..ddb81aae3 100644 --- a/src/rp2040/pico_platform/memmap_default.ld +++ b/src/rp2040/pico_platform/memmap_default.ld @@ -1 +1 @@ -INCLUDE "memmap_default.ld" +INCLUDE "memmap_default.incl" diff --git a/src/rp2040/pico_platform/memmap_no_flash.ld b/src/rp2040/pico_platform/memmap_no_flash.ld index 3e5be9e01..cbc400e66 100644 --- a/src/rp2040/pico_platform/memmap_no_flash.ld +++ b/src/rp2040/pico_platform/memmap_no_flash.ld @@ -1 +1 @@ -INCLUDE "memmap_no_flash.ld" +INCLUDE "memmap_no_flash.incl" diff --git a/src/rp2040/pico_platform/script_include/BUILD.bazel b/src/rp2040/pico_platform/script_include/BUILD.bazel index 337252e6c..afb7fb221 100644 --- a/src/rp2040/pico_platform/script_include/BUILD.bazel +++ b/src/rp2040/pico_platform/script_include/BUILD.bazel @@ -4,14 +4,11 @@ package(default_visibility = ["//visibility:public"]) load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") -exports_files( - [ - "default_locations.ld", - "section_copy_to_ram_text.ld", - "section_default_text.ld", - "section_no_flash_text.ld", - "section_platform_end.ld", - ] +filegroup( + name = "rp2040_linker_script_incls", + srcs = glob([ + "*.incl", + ]), ) include_linker_script_dir( @@ -24,10 +21,9 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "default_locations.ld", - "section_copy_to_ram_text.ld", - "section_default_text.ld", - "section_no_flash_text.ld", - "section_platform_end.ld", "rp2040_linker_script_args", ], + additional_linker_inputs = [ + "rp2040_linker_script_incls", + ], ) \ No newline at end of file diff --git a/src/rp2040/pico_platform/script_include/section_copy_to_ram_text.ld b/src/rp2040/pico_platform/script_include/section_copy_to_ram_text.incl similarity index 100% rename from src/rp2040/pico_platform/script_include/section_copy_to_ram_text.ld rename to src/rp2040/pico_platform/script_include/section_copy_to_ram_text.incl diff --git a/src/rp2040/pico_platform/script_include/section_default_text.ld b/src/rp2040/pico_platform/script_include/section_default_text.incl similarity index 96% rename from src/rp2040/pico_platform/script_include/section_default_text.ld rename to src/rp2040/pico_platform/script_include/section_default_text.incl index 2f25a1d4d..6ea15e65c 100644 --- a/src/rp2040/pico_platform/script_include/section_default_text.ld +++ b/src/rp2040/pico_platform/script_include/section_default_text.incl @@ -37,7 +37,7 @@ SECTIONS /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from * FLASH ... we will include any thing excluded here in .data below by default */ *(.init) - INCLUDE "section_default_text_excludes.ld" + INCLUDE "section_default_text_excludes.incl" *(.fini) /* Pull all c'tors into .text */ *crtbegin.o(.ctors) @@ -78,7 +78,7 @@ SECTIONS } > FLASH .rodata : { - INCLUDE "section_default_rodata_excludes.ld" + INCLUDE "section_default_rodata_excludes.incl" . = ALIGN(4); *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) . = ALIGN(4); diff --git a/src/rp2040/pico_platform/script_include/section_no_flash_text.ld b/src/rp2040/pico_platform/script_include/section_no_flash_text.incl similarity index 100% rename from src/rp2040/pico_platform/script_include/section_no_flash_text.ld rename to src/rp2040/pico_platform/script_include/section_no_flash_text.incl diff --git a/src/rp2040/pico_platform/script_include/section_platform_end.ld b/src/rp2040/pico_platform/script_include/section_platform_end.incl similarity index 100% rename from src/rp2040/pico_platform/script_include/section_platform_end.ld rename to src/rp2040/pico_platform/script_include/section_platform_end.incl diff --git a/src/rp2350/pico_platform/memmap_copy_to_ram.ld b/src/rp2350/pico_platform/memmap_copy_to_ram.ld index cd51ceeaa..f0eb74d9f 100644 --- a/src/rp2350/pico_platform/memmap_copy_to_ram.ld +++ b/src/rp2350/pico_platform/memmap_copy_to_ram.ld @@ -1 +1 @@ -INCLUDE "memmap_copy_to_ram.ld" +INCLUDE "memmap_copy_to_ram.incl" diff --git a/src/rp2350/pico_platform/memmap_default.ld b/src/rp2350/pico_platform/memmap_default.ld index c256a9071..ddb81aae3 100644 --- a/src/rp2350/pico_platform/memmap_default.ld +++ b/src/rp2350/pico_platform/memmap_default.ld @@ -1 +1 @@ -INCLUDE "memmap_default.ld" +INCLUDE "memmap_default.incl" diff --git a/src/rp2350/pico_platform/memmap_no_flash.ld b/src/rp2350/pico_platform/memmap_no_flash.ld index 3e5be9e01..cbc400e66 100644 --- a/src/rp2350/pico_platform/memmap_no_flash.ld +++ b/src/rp2350/pico_platform/memmap_no_flash.ld @@ -1 +1 @@ -INCLUDE "memmap_no_flash.ld" +INCLUDE "memmap_no_flash.incl" diff --git a/src/rp2350/pico_platform/script_include/BUILD.bazel b/src/rp2350/pico_platform/script_include/BUILD.bazel index 5b234a016..64e844b56 100644 --- a/src/rp2350/pico_platform/script_include/BUILD.bazel +++ b/src/rp2350/pico_platform/script_include/BUILD.bazel @@ -4,11 +4,11 @@ package(default_visibility = ["//visibility:public"]) load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") -exports_files( - [ - "default_locations.ld", - "section_platform_end.ld", - ] +filegroup( + name = "rp2350_linker_script_incls", + srcs = glob([ + "*.incl", + ]), ) include_linker_script_dir( @@ -21,7 +21,9 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ "default_locations.ld", - "section_platform_end.ld", "rp2350_linker_script_args", ], + additional_linker_inputs = [ + "rp2350_linker_script_incls", + ], ) \ No newline at end of file diff --git a/src/rp2350/pico_platform/script_include/section_platform_end.ld b/src/rp2350/pico_platform/script_include/section_platform_end.incl similarity index 100% rename from src/rp2350/pico_platform/script_include/section_platform_end.ld rename to src/rp2350/pico_platform/script_include/section_platform_end.incl diff --git a/src/rp2_common/pico_standard_link/script_include/BUILD.bazel b/src/rp2_common/pico_standard_link/script_include/BUILD.bazel index ba56b59d3..4afcce951 100644 --- a/src/rp2_common/pico_standard_link/script_include/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/script_include/BUILD.bazel @@ -4,34 +4,11 @@ load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") package(default_visibility = ["//visibility:public"]) -exports_files( - [ - "memory_aliases_default.ld", - "memory_aliases_no_flash.ld", - "memory_flash.ld", - "memory_ram.ld", - "memory_scratch.ld", - "memory_xip_ram.ld", - "section_copy_to_ram_data.ld", - "section_copy_to_ram_text.ld", - "section_default_data.ld", - "section_default_text.ld", - "section_default_text_excludes.ld", - "section_default_rodata_excludes.ld", - "section_end.ld", - "section_flash_end.ld", - "section_heap.ld", - "section_no_flash_data.ld", - "section_no_flash_text.ld", - "sections_copy_to_ram.ld", - "section_scratch.ld", - "sections_default.ld", - "sections_no_flash.ld", - "set_memory_locations.ld", - "memmap_default.ld", - "memmap_no_flash.ld", - "memmap_copy_to_ram.ld", - ] +filegroup( + name = "rp2_linker_script_incls", + srcs = glob([ + "*.incl", + ]), ) include_linker_script_dir( @@ -43,30 +20,8 @@ cc_library( target_compatible_with = compatible_with_rp2(), deps = [ "rp2_linker_script_args", - "memory_aliases_default.ld", - "memory_aliases_no_flash.ld", - "memory_flash.ld", - "memory_ram.ld", - "memory_scratch.ld", - "memory_xip_ram.ld", - "section_copy_to_ram_data.ld", - "section_copy_to_ram_text.ld", - "section_default_data.ld", - "section_default_text.ld", - "section_default_text_excludes.ld", - "section_default_rodata_excludes.ld", - "section_end.ld", - "section_flash_end.ld", - "section_heap.ld", - "section_no_flash_data.ld", - "section_no_flash_text.ld", - "sections_copy_to_ram.ld", - "section_scratch.ld", - "sections_default.ld", - "sections_no_flash.ld", - "set_memory_locations.ld", - "memmap_default.ld", - "memmap_no_flash.ld", - "memmap_copy_to_ram.ld", ], + additional_linker_inputs = [ + "rp2_linker_script_incls", + ] ) \ No newline at end of file diff --git a/src/rp2_common/pico_standard_link/script_include/memmap_default.ld b/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl similarity index 51% rename from src/rp2_common/pico_standard_link/script_include/memmap_default.ld rename to src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl index 04acbefbb..f2b8e7159 100644 --- a/src/rp2_common/pico_standard_link/script_include/memmap_default.ld +++ b/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl @@ -1,16 +1,16 @@ /* Include platform memory locations */ -INCLUDE "set_memory_locations.ld" +INCLUDE "set_memory_locations.incl" /* Include memory regions used */ -INCLUDE "memory_flash.ld" -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" +INCLUDE "memory_flash.incl" +INCLUDE "memory_ram.incl" +INCLUDE "memory_scratch.incl" /* Include aliases for storage memory regions */ -INCLUDE "memory_aliases_default.ld" +INCLUDE "memory_aliases_default.incl" /* Define entry point symbol */ ENTRY(_entry_point) /* Include default sections */ -INCLUDE "sections_default.ld" +INCLUDE "sections_copy_to_ram.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/script_include/memmap_default.incl similarity index 52% rename from src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.ld rename to src/rp2_common/pico_standard_link/script_include/memmap_default.incl index eb2c5ffd9..791d4ef2b 100644 --- a/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.ld +++ b/src/rp2_common/pico_standard_link/script_include/memmap_default.incl @@ -1,16 +1,16 @@ /* Include platform memory locations */ -INCLUDE "set_memory_locations.ld" +INCLUDE "set_memory_locations.incl" /* Include memory regions used */ -INCLUDE "memory_flash.ld" -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" +INCLUDE "memory_flash.incl" +INCLUDE "memory_ram.incl" +INCLUDE "memory_scratch.incl" /* Include aliases for storage memory regions */ -INCLUDE "memory_aliases_default.ld" +INCLUDE "memory_aliases_default.incl" /* Define entry point symbol */ ENTRY(_entry_point) /* Include default sections */ -INCLUDE "sections_copy_to_ram.ld" +INCLUDE "sections_default.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.incl similarity index 59% rename from src/rp2_common/pico_standard_link/script_include/memmap_no_flash.ld rename to src/rp2_common/pico_standard_link/script_include/memmap_no_flash.incl index 958915a71..e9578be46 100644 --- a/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.ld +++ b/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.incl @@ -1,15 +1,15 @@ /* Include platform memory locations */ -INCLUDE "set_memory_locations.ld" +INCLUDE "set_memory_locations.incl" /* Include memory regions used */ -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" +INCLUDE "memory_ram.incl" +INCLUDE "memory_scratch.incl" /* Include aliases for no_flash storage memory regions (alias to themselves) */ -INCLUDE "memory_aliases_no_flash.ld" +INCLUDE "memory_aliases_no_flash.incl" /* Define entry point symbol */ ENTRY(_entry_point) /* Include no_flash sections */ -INCLUDE "sections_no_flash.ld" +INCLUDE "sections_no_flash.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/memory_aliases_default.ld b/src/rp2_common/pico_standard_link/script_include/memory_aliases_default.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/memory_aliases_default.ld rename to src/rp2_common/pico_standard_link/script_include/memory_aliases_default.incl diff --git a/src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.ld b/src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.ld rename to src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.incl diff --git a/src/rp2_common/pico_standard_link/script_include/memory_flash.ld b/src/rp2_common/pico_standard_link/script_include/memory_flash.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/memory_flash.ld rename to src/rp2_common/pico_standard_link/script_include/memory_flash.incl diff --git a/src/rp2_common/pico_standard_link/script_include/memory_ram.ld b/src/rp2_common/pico_standard_link/script_include/memory_ram.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/memory_ram.ld rename to src/rp2_common/pico_standard_link/script_include/memory_ram.incl diff --git a/src/rp2_common/pico_standard_link/script_include/memory_scratch.ld b/src/rp2_common/pico_standard_link/script_include/memory_scratch.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/memory_scratch.ld rename to src/rp2_common/pico_standard_link/script_include/memory_scratch.incl diff --git a/src/rp2_common/pico_standard_link/script_include/memory_xip_ram.ld b/src/rp2_common/pico_standard_link/script_include/memory_xip_ram.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/memory_xip_ram.ld rename to src/rp2_common/pico_standard_link/script_include/memory_xip_ram.incl diff --git a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.ld b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.ld rename to src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.incl diff --git a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.ld b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.ld rename to src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.incl diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_data.ld b/src/rp2_common/pico_standard_link/script_include/section_default_data.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_default_data.ld rename to src/rp2_common/pico_standard_link/script_include/section_default_data.incl diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_rodata_excludes.ld b/src/rp2_common/pico_standard_link/script_include/section_default_rodata_excludes.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_default_rodata_excludes.ld rename to src/rp2_common/pico_standard_link/script_include/section_default_rodata_excludes.incl diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_text.ld b/src/rp2_common/pico_standard_link/script_include/section_default_text.incl similarity index 97% rename from src/rp2_common/pico_standard_link/script_include/section_default_text.ld rename to src/rp2_common/pico_standard_link/script_include/section_default_text.incl index ab86ade78..49c113db4 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_default_text.ld +++ b/src/rp2_common/pico_standard_link/script_include/section_default_text.incl @@ -27,7 +27,7 @@ SECTIONS * FLASH ... we will include any thing excluded here in .data below by default */ *(.init) *libgcc.a:cmse_nonsecure_call.o - INCLUDE "section_default_text_excludes.ld" + INCLUDE "section_default_text_excludes.incl" *(.fini) /* Pull all c'tors into .text */ *crtbegin.o(.ctors) @@ -89,7 +89,7 @@ SECTIONS "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") .rodata : { - INCLUDE "section_default_rodata_excludes.ld" + INCLUDE "section_default_rodata_excludes.incl" *(.srodata*) . = ALIGN(4); *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_text_excludes.ld b/src/rp2_common/pico_standard_link/script_include/section_default_text_excludes.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_default_text_excludes.ld rename to src/rp2_common/pico_standard_link/script_include/section_default_text_excludes.incl diff --git a/src/rp2_common/pico_standard_link/script_include/section_end.ld b/src/rp2_common/pico_standard_link/script_include/section_end.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_end.ld rename to src/rp2_common/pico_standard_link/script_include/section_end.incl diff --git a/src/rp2_common/pico_standard_link/script_include/section_flash_end.ld b/src/rp2_common/pico_standard_link/script_include/section_flash_end.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_flash_end.ld rename to src/rp2_common/pico_standard_link/script_include/section_flash_end.incl diff --git a/src/rp2_common/pico_standard_link/script_include/section_heap.ld b/src/rp2_common/pico_standard_link/script_include/section_heap.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_heap.ld rename to src/rp2_common/pico_standard_link/script_include/section_heap.incl diff --git a/src/rp2_common/pico_standard_link/script_include/section_no_flash_data.ld b/src/rp2_common/pico_standard_link/script_include/section_no_flash_data.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_no_flash_data.ld rename to src/rp2_common/pico_standard_link/script_include/section_no_flash_data.incl diff --git a/src/rp2_common/pico_standard_link/script_include/section_no_flash_text.ld b/src/rp2_common/pico_standard_link/script_include/section_no_flash_text.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_no_flash_text.ld rename to src/rp2_common/pico_standard_link/script_include/section_no_flash_text.incl diff --git a/src/rp2_common/pico_standard_link/script_include/section_scratch.ld b/src/rp2_common/pico_standard_link/script_include/section_scratch.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_scratch.ld rename to src/rp2_common/pico_standard_link/script_include/section_scratch.incl diff --git a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl new file mode 100644 index 000000000..397311e63 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl @@ -0,0 +1,7 @@ +INCLUDE "section_copy_to_ram_text.incl" +INCLUDE "section_copy_to_ram_data.incl" +INCLUDE "section_heap.incl" +INCLUDE "section_scratch.incl" +INCLUDE "section_flash_end.incl" +INCLUDE "section_end.incl" +INCLUDE "section_platform_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.ld b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.ld deleted file mode 100644 index fe7caf546..000000000 --- a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.ld +++ /dev/null @@ -1,7 +0,0 @@ -INCLUDE "section_copy_to_ram_text.ld" -INCLUDE "section_copy_to_ram_data.ld" -INCLUDE "section_heap.ld" -INCLUDE "section_scratch.ld" -INCLUDE "section_flash_end.ld" -INCLUDE "section_end.ld" -INCLUDE "section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_default.incl b/src/rp2_common/pico_standard_link/script_include/sections_default.incl new file mode 100644 index 000000000..e00725155 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/sections_default.incl @@ -0,0 +1,7 @@ +INCLUDE "section_default_text.incl" +INCLUDE "section_default_data.incl" +INCLUDE "section_heap.incl" +INCLUDE "section_scratch.incl" +INCLUDE "section_flash_end.incl" +INCLUDE "section_end.incl" +INCLUDE "section_platform_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_default.ld b/src/rp2_common/pico_standard_link/script_include/sections_default.ld deleted file mode 100644 index f22558a9f..000000000 --- a/src/rp2_common/pico_standard_link/script_include/sections_default.ld +++ /dev/null @@ -1,7 +0,0 @@ -INCLUDE "section_default_text.ld" -INCLUDE "section_default_data.ld" -INCLUDE "section_heap.ld" -INCLUDE "section_scratch.ld" -INCLUDE "section_flash_end.ld" -INCLUDE "section_end.ld" -INCLUDE "section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl new file mode 100644 index 000000000..2a043dfe3 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl @@ -0,0 +1,6 @@ +INCLUDE "section_no_flash_text.incl" +INCLUDE "section_no_flash_data.incl" +INCLUDE "section_heap.incl" +INCLUDE "section_scratch.incl" +INCLUDE "section_end.incl" +INCLUDE "section_platform_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_no_flash.ld b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.ld deleted file mode 100644 index 77bad234e..000000000 --- a/src/rp2_common/pico_standard_link/script_include/sections_no_flash.ld +++ /dev/null @@ -1,6 +0,0 @@ -INCLUDE "section_no_flash_text.ld" -INCLUDE "section_no_flash_data.ld" -INCLUDE "section_heap.ld" -INCLUDE "section_scratch.ld" -INCLUDE "section_end.ld" -INCLUDE "section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/script_include/set_memory_locations.ld b/src/rp2_common/pico_standard_link/script_include/set_memory_locations.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/set_memory_locations.ld rename to src/rp2_common/pico_standard_link/script_include/set_memory_locations.incl diff --git a/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.incl b/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.incl new file mode 100644 index 000000000..2bc78925a --- /dev/null +++ b/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.incl @@ -0,0 +1,19 @@ +INCLUDE "section_default_text.incl" +INCLUDE "section_default_data.incl" + +SECTIONS +{ + .extra_data : { + __extra_data_start__ = .; + *(.extra_data*) + . = ALIGN(4); + __extra_data_end__ = .; + } > RAM AT> RAM_STORE + __extra_data_source__ = LOADADDR(.extra_data); +} + +INCLUDE "section_heap.incl" +INCLUDE "section_scratch.incl" +INCLUDE "section_flash_end.incl" +INCLUDE "section_end.incl" +INCLUDE "section_platform_end.incl" \ No newline at end of file diff --git a/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.ld b/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.ld deleted file mode 100644 index 9ffef1a28..000000000 --- a/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.ld +++ /dev/null @@ -1,19 +0,0 @@ -INCLUDE "section_default_text.ld" -INCLUDE "section_default_data.ld" - -SECTIONS -{ - .extra_data : { - __extra_data_start__ = .; - *(.extra_data*) - . = ALIGN(4); - __extra_data_end__ = .; - } > RAM AT> RAM_STORE - __extra_data_source__ = LOADADDR(.extra_data); -} - -INCLUDE "section_heap.ld" -INCLUDE "section_scratch.ld" -INCLUDE "section_flash_end.ld" -INCLUDE "section_end.ld" -INCLUDE "section_platform_end.ld" \ No newline at end of file diff --git a/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.ld b/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.incl similarity index 57% rename from test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.ld rename to test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.incl index 9a69c883a..9e3060e70 100644 --- a/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.ld +++ b/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.incl @@ -1,5 +1,5 @@ -INCLUDE "section_default_text.ld" -INCLUDE "section_default_data.ld" +INCLUDE "section_default_text.incl" +INCLUDE "section_default_data.incl" SECTIONS { @@ -17,8 +17,8 @@ SECTIONS PROVIDE(__overlays_end__ = .); } -INCLUDE "section_heap.ld" -INCLUDE "section_scratch.ld" -INCLUDE "section_flash_end.ld" -INCLUDE "section_end.ld" -INCLUDE "section_platform_end.ld" +INCLUDE "section_heap.incl" +INCLUDE "section_scratch.incl" +INCLUDE "section_flash_end.incl" +INCLUDE "section_end.incl" +INCLUDE "section_platform_end.incl" From 780c05e254a546968ab29ae8978f5c6284d5f709 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 19 Mar 2026 13:01:34 +0000 Subject: [PATCH 079/127] Separate into section_... files which do only contain one section, and sections_... which contain multiple Only exceptions are section_..._data and section_bss, as these contain data/bss and tdata/tbss - these are kept together as they are treated as a single section --- .../script_include/section_boot2.incl | 16 +++ .../section_copy_to_ram_text.incl | 101 ---------------- .../script_include/section_default_text.incl | 109 ------------------ .../sections_copy_to_ram_text.incl | 9 ++ .../script_include/sections_default_text.incl | 8 ++ src/rp2350/pico_platform/BUILD.bazel | 5 - ...udes.incl => default_rodata_excludes.incl} | 0 ...cludes.incl => default_text_excludes.incl} | 0 .../memory_aliases_default.incl | 1 + .../memory_aliases_no_flash.incl | 1 + .../script_include/section_binary_info.incl | 13 +++ .../script_include/section_boot2.incl | 23 ++++ .../script_include/section_bss.incl | 24 ++++ .../section_copy_to_ram_data.incl | 26 +---- .../section_copy_to_ram_flashtext.incl | 23 ++++ .../section_copy_to_ram_rodata.incl | 8 ++ .../section_copy_to_ram_text.incl | 92 +-------------- .../script_include/section_default_data.incl | 35 +----- .../section_default_rodata.incl | 10 ++ .../script_include/section_default_text.incl | 60 +--------- .../script_include/section_flash_begin.incl | 6 + .../script_include/section_flash_end.incl | 2 +- .../script_include/section_no_flash_data.incl | 26 ----- .../section_no_flash_rodata.incl | 11 ++ .../script_include/section_no_flash_text.incl | 32 ----- .../section_ram_vector_table.incl | 6 + .../section_uninitialized_data.incl | 7 ++ .../script_include/sections_arm_ex.incl | 14 +++ .../script_include/sections_copy_to_ram.incl | 6 +- .../sections_copy_to_ram_data.incl | 2 + .../sections_copy_to_ram_text.incl | 9 ++ .../script_include/sections_default.incl | 6 +- .../script_include/sections_default_data.incl | 4 + .../script_include/sections_default_text.incl | 6 + .../script_include/sections_no_flash.incl | 6 +- .../sections_no_flash_data.incl | 3 + .../sections_no_flash_text.incl | 4 + ...ion_scratch.incl => sections_scratch.incl} | 0 .../sections_default.incl | 6 +- .../sections_default.incl | 6 +- 40 files changed, 231 insertions(+), 495 deletions(-) create mode 100644 src/rp2040/pico_platform/script_include/section_boot2.incl delete mode 100644 src/rp2040/pico_platform/script_include/section_copy_to_ram_text.incl delete mode 100644 src/rp2040/pico_platform/script_include/section_default_text.incl create mode 100644 src/rp2040/pico_platform/script_include/sections_copy_to_ram_text.incl create mode 100644 src/rp2040/pico_platform/script_include/sections_default_text.incl rename src/rp2_common/pico_standard_link/script_include/{section_default_rodata_excludes.incl => default_rodata_excludes.incl} (100%) rename src/rp2_common/pico_standard_link/script_include/{section_default_text_excludes.incl => default_text_excludes.incl} (100%) create mode 100644 src/rp2_common/pico_standard_link/script_include/section_binary_info.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_boot2.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_bss.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_flashtext.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_rodata.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_default_rodata.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_flash_begin.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_no_flash_rodata.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_ram_vector_table.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_uninitialized_data.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_text.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/sections_default_data.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/sections_default_text.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/sections_no_flash_text.incl rename src/rp2_common/pico_standard_link/script_include/{section_scratch.incl => sections_scratch.incl} (100%) diff --git a/src/rp2040/pico_platform/script_include/section_boot2.incl b/src/rp2040/pico_platform/script_include/section_boot2.incl new file mode 100644 index 000000000..b6afc3763 --- /dev/null +++ b/src/rp2040/pico_platform/script_include/section_boot2.incl @@ -0,0 +1,16 @@ +SECTIONS +{ + /* Second stage bootloader is prepended to the image. It must be 256 bytes big + and checksummed. It is usually built by the boot_stage2 target + in the Raspberry Pi Pico SDK + */ + + .boot2 : { + __boot2_start__ = .; + KEEP (*(.boot2)) + __boot2_end__ = .; + } > TEXT_STORE + + ASSERT(__boot2_end__ - __boot2_start__ == 256, + "ERROR: Pico second stage bootloader must be 256 bytes in size") +} diff --git a/src/rp2040/pico_platform/script_include/section_copy_to_ram_text.incl b/src/rp2040/pico_platform/script_include/section_copy_to_ram_text.incl deleted file mode 100644 index 77a45941b..000000000 --- a/src/rp2040/pico_platform/script_include/section_copy_to_ram_text.incl +++ /dev/null @@ -1,101 +0,0 @@ -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .flashtext : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - } - - .rodata : { - /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - /* Vector table goes first in RAM, to avoid large alignment hole */ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .text : { - __ram_text_start__ = .; - *(.init) - *(.text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - . = ALIGN(4); - __ram_text_end__ = .; - } > RAM AT> FLASH - __ram_text_source__ = LOADADDR(.text); - . = ALIGN(4); -} diff --git a/src/rp2040/pico_platform/script_include/section_default_text.incl b/src/rp2040/pico_platform/script_include/section_default_text.incl deleted file mode 100644 index 6ea15e65c..000000000 --- a/src/rp2040/pico_platform/script_include/section_default_text.incl +++ /dev/null @@ -1,109 +0,0 @@ -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .text : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - /* TODO revisit this now memset/memcpy/float in ROM */ - /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from - * FLASH ... we will include any thing excluded here in .data below by default */ - *(.init) - INCLUDE "section_default_text_excludes.incl" - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.eh_frame*) - . = ALIGN(4); - } > FLASH - - .rodata : { - INCLUDE "section_default_rodata_excludes.incl" - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); -} diff --git a/src/rp2040/pico_platform/script_include/sections_copy_to_ram_text.incl b/src/rp2040/pico_platform/script_include/sections_copy_to_ram_text.incl new file mode 100644 index 000000000..0fdd197b8 --- /dev/null +++ b/src/rp2040/pico_platform/script_include/sections_copy_to_ram_text.incl @@ -0,0 +1,9 @@ +INCLUDE "section_flash_begin.incl" +INCLUDE "section_boot2.incl" +INCLUDE "section_copy_to_ram_flashtext.incl" +INCLUDE "section_copy_to_ram_rodata.incl" +INCLUDE "sections_arm_ex.incl" +INCLUDE "section_binary_info.incl" +INCLUDE "section_ram_vector_table.incl" +INCLUDE "section_uninitialized_data.incl" +INCLUDE "section_copy_to_ram_text.incl" diff --git a/src/rp2040/pico_platform/script_include/sections_default_text.incl b/src/rp2040/pico_platform/script_include/sections_default_text.incl new file mode 100644 index 000000000..af0bce686 --- /dev/null +++ b/src/rp2040/pico_platform/script_include/sections_default_text.incl @@ -0,0 +1,8 @@ +# This swaps section_boot2 and section_default_text, because RP2040 binaries must begin with boot2 + +INCLUDE "section_flash_begin.incl" +INCLUDE "section_boot2.incl" +INCLUDE "section_default_text.incl" +INCLUDE "section_default_rodata.incl" +INCLUDE "sections_arm_ex.incl" +INCLUDE "section_binary_info.incl" diff --git a/src/rp2350/pico_platform/BUILD.bazel b/src/rp2350/pico_platform/BUILD.bazel index 3e5dfde8d..e2e2c382d 100644 --- a/src/rp2350/pico_platform/BUILD.bazel +++ b/src/rp2350/pico_platform/BUILD.bazel @@ -70,11 +70,6 @@ use_linker_script_file( script = "memmap_default.ld", ) -use_linker_script_file( - name = "memmap_blocked_ram_args", - script = "memmap_blocked_ram.ld", -) - use_linker_script_file( name = "memmap_copy_to_ram_args", script = "memmap_copy_to_ram.ld", diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_rodata_excludes.incl b/src/rp2_common/pico_standard_link/script_include/default_rodata_excludes.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_default_rodata_excludes.incl rename to src/rp2_common/pico_standard_link/script_include/default_rodata_excludes.incl diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_text_excludes.incl b/src/rp2_common/pico_standard_link/script_include/default_text_excludes.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_default_text_excludes.incl rename to src/rp2_common/pico_standard_link/script_include/default_text_excludes.incl diff --git a/src/rp2_common/pico_standard_link/script_include/memory_aliases_default.incl b/src/rp2_common/pico_standard_link/script_include/memory_aliases_default.incl index 7c56254bd..4c16d41be 100644 --- a/src/rp2_common/pico_standard_link/script_include/memory_aliases_default.incl +++ b/src/rp2_common/pico_standard_link/script_include/memory_aliases_default.incl @@ -1,3 +1,4 @@ +REGION_ALIAS("TEXT_STORE", FLASH); REGION_ALIAS("RAM_STORE", FLASH); REGION_ALIAS("SCRATCH_X_STORE", FLASH); REGION_ALIAS("SCRATCH_Y_STORE", FLASH); diff --git a/src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.incl b/src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.incl index 063b5b6fc..9190b32ab 100644 --- a/src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.incl +++ b/src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.incl @@ -1,3 +1,4 @@ +REGION_ALIAS("TEXT_STORE", RAM); REGION_ALIAS("RAM_STORE", RAM); REGION_ALIAS("SCRATCH_X_STORE", SCRATCH_X); REGION_ALIAS("SCRATCH_Y_STORE", SCRATCH_Y); diff --git a/src/rp2_common/pico_standard_link/script_include/section_binary_info.incl b/src/rp2_common/pico_standard_link/script_include/section_binary_info.incl new file mode 100644 index 000000000..f7238d09a --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_binary_info.incl @@ -0,0 +1,13 @@ +SECTIONS +{ + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > TEXT_STORE + __binary_info_end = .; + . = ALIGN(4); +} diff --git a/src/rp2_common/pico_standard_link/script_include/section_boot2.incl b/src/rp2_common/pico_standard_link/script_include/section_boot2.incl new file mode 100644 index 000000000..14e362776 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_boot2.incl @@ -0,0 +1,23 @@ +SECTIONS +{ + /* Note the boot2 section is optional, and should be discarded if there is + no reference to it *inside* the binary, as it is not called by the + bootrom. (The bootrom performs a simple best-effort XIP setup and + leaves it to the binary to do anything more sophisticated.) However + there is still a size limit of 256 bytes, to ensure the boot2 can be + stored in boot RAM. + + Really this is a "XIP setup function" -- the name boot2 is historic and + refers to its dual-purpose on RP2040, where it also handled vectoring + from the bootrom into the user image. + */ + + .boot2 : { + __boot2_start__ = .; + *(.boot2) + __boot2_end__ = .; + } > TEXT_STORE + + ASSERT(__boot2_end__ - __boot2_start__ <= 256, + "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") +} diff --git a/src/rp2_common/pico_standard_link/script_include/section_bss.incl b/src/rp2_common/pico_standard_link/script_include/section_bss.incl new file mode 100644 index 000000000..172436df6 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_bss.incl @@ -0,0 +1,24 @@ +SECTIONS +{ + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + __tls_base = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + + __tls_end = .; + } > RAM + + .bss (NOLOAD) : { + . = ALIGN(4); + __tbss_end = .; + + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + PROVIDE(__global_pointer$ = . + 2K); + *(.sbss*) + . = ALIGN(4); + __bss_end__ = .; + } > RAM +} diff --git a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.incl b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.incl index 19082589c..82084a70b 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.incl @@ -46,38 +46,16 @@ SECTIONS *(.jcr) . = ALIGN(4); - } > RAM AT> FLASH + } > RAM AT> RAM_STORE .tdata : { . = ALIGN(4); *(.tdata .tdata.* .gnu.linkonce.td.*) /* All data end */ __tdata_end = .; - } > RAM AT> FLASH + } > RAM AT> RAM_STORE PROVIDE(__data_end__ = .); /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM } diff --git a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_flashtext.incl b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_flashtext.incl new file mode 100644 index 000000000..a0c794eb9 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_flashtext.incl @@ -0,0 +1,23 @@ +SECTIONS +{ + /* The bootrom will enter the image at the point indicated in your + IMAGE_DEF, which is usually the reset handler of your vector table. + + The debugger will use the ELF entry point, which is the _entry_point + symbol, and in our case is *different from the bootrom's entry point.* + This is used to go back through the bootrom on debugger launches only, + to perform the same initial flash setup that would be performed on a + cold boot. + */ + + .flashtext : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.embedded_block)) + __embedded_block_end = .; + KEEP (*(.reset)) + . = ALIGN(4); + } > TEXT_STORE +} diff --git a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_rodata.incl b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_rodata.incl new file mode 100644 index 000000000..a6de46efc --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_rodata.incl @@ -0,0 +1,8 @@ +SECTIONS +{ + .rodata : { + /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > TEXT_STORE +} diff --git a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.incl b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.incl index d35f7209e..7d6eb9d17 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.incl @@ -1,95 +1,5 @@ SECTIONS { - /* On Arm, the bootrom expects a VT at the start of the - image by default; on RISC-V, the default is to enter the image at its - lowest address, so an IMAGE_DEF item is required to specify the - nondefault entry point. */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - /* The bootrom will enter the image at the point indicated in your - IMAGE_DEF, which is usually the reset handler of your vector table. - - The debugger will use the ELF entry point, which is the _entry_point - symbol, and in our case is *different from the bootrom's entry point.* - This is used to go back through the bootrom on debugger launches only, - to perform the same initial flash setup that would be performed on a - cold boot. - */ - - .flashtext : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - . = ALIGN(4); - } > FLASH - - /* Note the boot2 section is optional, and should be discarded if there is - no reference to it *inside* the binary, as it is not called by the - bootrom. (The bootrom performs a simple best-effort XIP setup and - leaves it to the binary to do anything more sophisticated.) However - there is still a size limit of 256 bytes, to ensure the boot2 can be - stored in boot RAM. - - Really this is a "XIP setup function" -- the name boot2 is historic and - refers to its dual-purpose on RP2040, where it also handled vectoring - from the bootrom into the user image. - */ - - .boot2 : { - __boot2_start__ = .; - *(.boot2) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ <= 256, - "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") - - .rodata : { - /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - /* Vector table goes first in RAM, to avoid large alignment hole */ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - .text : { __ram_text_start__ = .; *(.init) @@ -111,7 +21,7 @@ SECTIONS *(.eh_frame*) . = ALIGN(4); __ram_text_end__ = .; - } > RAM AT> FLASH + } > RAM AT> RAM_STORE __ram_text_source__ = LOADADDR(.text); . = ALIGN(4); } diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_data.incl b/src/rp2_common/pico_standard_link/script_include/section_default_data.incl index 5bd1cf569..a1f759b39 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_default_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_default_data.incl @@ -1,14 +1,5 @@ SECTIONS { - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - .data : { __data_start__ = .; *(vtable) @@ -35,38 +26,16 @@ SECTIONS *(.jcr) . = ALIGN(4); - } > RAM AT> FLASH + } > RAM AT> RAM_STORE .tdata : { . = ALIGN(4); *(.tdata .tdata.* .gnu.linkonce.td.*) /* All data end */ __tdata_end = .; - } > RAM AT> FLASH + } > RAM AT> RAM_STORE PROVIDE(__data_end__ = .); /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM } diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_rodata.incl b/src/rp2_common/pico_standard_link/script_include/section_default_rodata.incl new file mode 100644 index 000000000..2df23bbf2 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_default_rodata.incl @@ -0,0 +1,10 @@ +SECTIONS +{ + .rodata : { + INCLUDE "default_rodata_excludes.incl" + *(.srodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > TEXT_STORE +} diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_text.incl b/src/rp2_common/pico_standard_link/script_include/section_default_text.incl index 49c113db4..63905474b 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_default_text.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_default_text.incl @@ -1,9 +1,5 @@ SECTIONS { - .flash_begin : { - __flash_binary_start = .; - } > FLASH - /* The bootrom will enter the image at the point indicated in your IMAGE_DEF, which is usually the reset handler of your vector table. @@ -27,7 +23,7 @@ SECTIONS * FLASH ... we will include any thing excluded here in .data below by default */ *(.init) *libgcc.a:cmse_nonsecure_call.o - INCLUDE "section_default_text_excludes.incl" + INCLUDE "default_text_excludes.incl" *(.fini) /* Pull all c'tors into .text */ *crtbegin.o(.ctors) @@ -65,57 +61,5 @@ SECTIONS *(.eh_frame*) . = ALIGN(4); - } > FLASH - - /* Note the boot2 section is optional, and should be discarded if there is - no reference to it *inside* the binary, as it is not called by the - bootrom. (The bootrom performs a simple best-effort XIP setup and - leaves it to the binary to do anything more sophisticated.) However - there is still a size limit of 256 bytes, to ensure the boot2 can be - stored in boot RAM. - - Really this is a "XIP setup function" -- the name boot2 is historic and - refers to its dual-purpose on RP2040, where it also handled vectoring - from the bootrom into the user image. - */ - - .boot2 : { - __boot2_start__ = .; - *(.boot2) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ <= 256, - "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") - - .rodata : { - INCLUDE "section_default_rodata_excludes.incl" - *(.srodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); + } > TEXT_STORE } diff --git a/src/rp2_common/pico_standard_link/script_include/section_flash_begin.incl b/src/rp2_common/pico_standard_link/script_include/section_flash_begin.incl new file mode 100644 index 000000000..fdff1ad09 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_flash_begin.incl @@ -0,0 +1,6 @@ +SECTIONS +{ + .flash_begin : { + __flash_binary_start = .; + } > TEXT_STORE +} diff --git a/src/rp2_common/pico_standard_link/script_include/section_flash_end.incl b/src/rp2_common/pico_standard_link/script_include/section_flash_end.incl index 8591406ff..92a3e7dff 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_flash_end.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_flash_end.incl @@ -3,5 +3,5 @@ SECTIONS .flash_end : { KEEP(*(.embedded_end_block*)) PROVIDE(__flash_binary_end = .); - } > FLASH =0xaa + } > TEXT_STORE =0xaa } diff --git a/src/rp2_common/pico_standard_link/script_include/section_no_flash_data.incl b/src/rp2_common/pico_standard_link/script_include/section_no_flash_data.incl index 5658d8a4b..e1c5ee909 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_no_flash_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_no_flash_data.incl @@ -51,32 +51,6 @@ SECTIONS } > RAM PROVIDE(__data_end__ = .); - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM } diff --git a/src/rp2_common/pico_standard_link/script_include/section_no_flash_rodata.incl b/src/rp2_common/pico_standard_link/script_include/section_no_flash_rodata.incl new file mode 100644 index 000000000..9e5ae119d --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_no_flash_rodata.incl @@ -0,0 +1,11 @@ +SECTIONS +{ + .rodata : { + . = ALIGN(4); + *(.rodata*) + *(.srodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } > RAM +} diff --git a/src/rp2_common/pico_standard_link/script_include/section_no_flash_text.incl b/src/rp2_common/pico_standard_link/script_include/section_no_flash_text.incl index 833d8c42b..912aa13d2 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_no_flash_text.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_no_flash_text.incl @@ -38,36 +38,4 @@ SECTIONS *(.eh_frame*) } > RAM - - .rodata : { - . = ALIGN(4); - *(.rodata*) - *(.srodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > RAM - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > RAM - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > RAM - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > RAM - __binary_info_end = .; - . = ALIGN(4); } diff --git a/src/rp2_common/pico_standard_link/script_include/section_ram_vector_table.incl b/src/rp2_common/pico_standard_link/script_include/section_ram_vector_table.incl new file mode 100644 index 000000000..1e5818110 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_ram_vector_table.incl @@ -0,0 +1,6 @@ +SECTIONS +{ + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } > RAM +} diff --git a/src/rp2_common/pico_standard_link/script_include/section_uninitialized_data.incl b/src/rp2_common/pico_standard_link/script_include/section_uninitialized_data.incl new file mode 100644 index 000000000..6167314be --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_uninitialized_data.incl @@ -0,0 +1,7 @@ +SECTIONS +{ + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } > RAM +} diff --git a/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl b/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl new file mode 100644 index 000000000..6b6ee8d0a --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl @@ -0,0 +1,14 @@ +SECTIONS +{ + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > TEXT_STORE + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > TEXT_STORE + __exidx_end = .; +} diff --git a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl index 397311e63..beb231348 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl @@ -1,7 +1,7 @@ -INCLUDE "section_copy_to_ram_text.incl" -INCLUDE "section_copy_to_ram_data.incl" +INCLUDE "sections_copy_to_ram_text.incl" +INCLUDE "sections_copy_to_ram_data.incl" INCLUDE "section_heap.incl" -INCLUDE "section_scratch.incl" +INCLUDE "sections_scratch.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl new file mode 100644 index 000000000..b0de72ede --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl @@ -0,0 +1,2 @@ +INCLUDE "section_copy_to_ram_data.incl" +INCLUDE "section_bss.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_text.incl b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_text.incl new file mode 100644 index 000000000..f19c1aab3 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_text.incl @@ -0,0 +1,9 @@ +INCLUDE "section_flash_begin.incl" +INCLUDE "section_copy_to_ram_flashtext.incl" +INCLUDE "section_boot2.incl" +INCLUDE "section_copy_to_ram_rodata.incl" +INCLUDE "sections_arm_ex.incl" +INCLUDE "section_binary_info.incl" +INCLUDE "section_ram_vector_table.incl" +INCLUDE "section_uninitialized_data.incl" +INCLUDE "section_copy_to_ram_text.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_default.incl b/src/rp2_common/pico_standard_link/script_include/sections_default.incl index e00725155..05f09f12b 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_default.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_default.incl @@ -1,7 +1,7 @@ -INCLUDE "section_default_text.incl" -INCLUDE "section_default_data.incl" +INCLUDE "sections_default_text.incl" +INCLUDE "sections_default_data.incl" INCLUDE "section_heap.incl" -INCLUDE "section_scratch.incl" +INCLUDE "sections_scratch.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl b/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl new file mode 100644 index 000000000..e61f35527 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl @@ -0,0 +1,4 @@ +INCLUDE "section_ram_vector_table.incl" +INCLUDE "section_uninitialized_data.incl" +INCLUDE "section_default_data.incl" +INCLUDE "section_bss.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_default_text.incl b/src/rp2_common/pico_standard_link/script_include/sections_default_text.incl new file mode 100644 index 000000000..5959a5b5d --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/sections_default_text.incl @@ -0,0 +1,6 @@ +INCLUDE "section_flash_begin.incl" +INCLUDE "section_default_text.incl" +INCLUDE "section_boot2.incl" +INCLUDE "section_default_rodata.incl" +INCLUDE "sections_arm_ex.incl" +INCLUDE "section_binary_info.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl index 2a043dfe3..87760c03f 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl @@ -1,6 +1,6 @@ -INCLUDE "section_no_flash_text.incl" -INCLUDE "section_no_flash_data.incl" +INCLUDE "sections_no_flash_text.incl" +INCLUDE "sections_no_flash_data.incl" INCLUDE "section_heap.incl" -INCLUDE "section_scratch.incl" +INCLUDE "sections_scratch.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl b/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl new file mode 100644 index 000000000..084fbda4f --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl @@ -0,0 +1,3 @@ +INCLUDE "section_no_flash_data.incl" +INCLUDE "section_uninitialized_data.incl" +INCLUDE "section_bss.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_no_flash_text.incl b/src/rp2_common/pico_standard_link/script_include/sections_no_flash_text.incl new file mode 100644 index 000000000..65de1fa12 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/sections_no_flash_text.incl @@ -0,0 +1,4 @@ +INCLUDE "section_no_flash_text.incl" +INCLUDE "section_no_flash_rodata.incl" +INCLUDE "sections_arm_ex.incl" +INCLUDE "section_binary_info.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/section_scratch.incl b/src/rp2_common/pico_standard_link/script_include/sections_scratch.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/section_scratch.incl rename to src/rp2_common/pico_standard_link/script_include/sections_scratch.incl diff --git a/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.incl b/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.incl index 2bc78925a..15e94dac0 100644 --- a/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.incl +++ b/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.incl @@ -1,5 +1,5 @@ -INCLUDE "section_default_text.incl" -INCLUDE "section_default_data.incl" +INCLUDE "sections_default_text.incl" +INCLUDE "sections_default_data.incl" SECTIONS { @@ -13,7 +13,7 @@ SECTIONS } INCLUDE "section_heap.incl" -INCLUDE "section_scratch.incl" +INCLUDE "sections_scratch.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" \ No newline at end of file diff --git a/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.incl b/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.incl index 9e3060e70..00db2605d 100644 --- a/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.incl +++ b/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.incl @@ -1,5 +1,5 @@ -INCLUDE "section_default_text.incl" -INCLUDE "section_default_data.incl" +INCLUDE "sections_default_text.incl" +INCLUDE "sections_default_data.incl" SECTIONS { @@ -18,7 +18,7 @@ SECTIONS } INCLUDE "section_heap.incl" -INCLUDE "section_scratch.incl" +INCLUDE "sections_scratch.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" From 2e7ca673a003db70a19d727bf40e79910b97dcba Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 19 Mar 2026 14:44:29 +0000 Subject: [PATCH 080/127] Add section_extra files to make adding extra sections simpler --- .../script_include/section_no_flash_text.incl | 31 ------------------- .../script_include/sections_default_text.incl | 2 +- .../section_extra_post_data.incl | 3 ++ .../section_extra_post_scratch.incl | 3 ++ .../section_extra_post_text.incl | 3 ++ .../script_include/sections_copy_to_ram.incl | 4 +++ .../script_include/sections_default.incl | 4 +++ .../script_include/sections_no_flash.incl | 4 +++ .../script_include/sections_scratch.incl | 18 ----------- .../script_include/sections_stack.incl | 20 ++++++++++++ test/kitchen_sink/CMakeLists.txt | 2 ++ .../section_extra_post_data.incl | 10 ++++++ .../sections_default.incl | 19 ------------ ...ault.incl => section_extra_post_data.incl} | 9 ------ 14 files changed, 54 insertions(+), 78 deletions(-) create mode 100644 src/rp2_common/pico_standard_link/script_include/section_extra_post_data.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_extra_post_scratch.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_extra_post_text.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/sections_stack.incl create mode 100644 test/kitchen_sink/kitchen_sink_ram_section_scripts/section_extra_post_data.incl delete mode 100644 test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.incl rename test/kitchen_sink/kitchen_sink_simple_overlay_scripts/{sections_default.incl => section_extra_post_data.incl} (57%) diff --git a/src/rp2040/pico_platform/script_include/section_no_flash_text.incl b/src/rp2040/pico_platform/script_include/section_no_flash_text.incl index b4ad44ba7..43fbfa783 100644 --- a/src/rp2040/pico_platform/script_include/section_no_flash_text.incl +++ b/src/rp2040/pico_platform/script_include/section_no_flash_text.incl @@ -37,35 +37,4 @@ SECTIONS *(.eh_frame*) } > RAM - - .rodata : { - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > RAM - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > RAM - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > RAM - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > RAM - __binary_info_end = .; - . = ALIGN(4); } diff --git a/src/rp2040/pico_platform/script_include/sections_default_text.incl b/src/rp2040/pico_platform/script_include/sections_default_text.incl index af0bce686..c00c93429 100644 --- a/src/rp2040/pico_platform/script_include/sections_default_text.incl +++ b/src/rp2040/pico_platform/script_include/sections_default_text.incl @@ -1,4 +1,4 @@ -# This swaps section_boot2 and section_default_text, because RP2040 binaries must begin with boot2 +/* This swaps section_boot2 and section_default_text, because RP2040 binaries must begin with boot2 */ INCLUDE "section_flash_begin.incl" INCLUDE "section_boot2.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/section_extra_post_data.incl b/src/rp2_common/pico_standard_link/script_include/section_extra_post_data.incl new file mode 100644 index 000000000..584a11e64 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_extra_post_data.incl @@ -0,0 +1,3 @@ +/* Empty file - can be overriden + This file is included between the end of data/bss and the start of the heap +*/ diff --git a/src/rp2_common/pico_standard_link/script_include/section_extra_post_scratch.incl b/src/rp2_common/pico_standard_link/script_include/section_extra_post_scratch.incl new file mode 100644 index 000000000..b306a920e --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_extra_post_scratch.incl @@ -0,0 +1,3 @@ +/* Empty file - can be overriden + This file is included between the end of scratch and the start of the stack +*/ diff --git a/src/rp2_common/pico_standard_link/script_include/section_extra_post_text.incl b/src/rp2_common/pico_standard_link/script_include/section_extra_post_text.incl new file mode 100644 index 000000000..3d8214675 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_extra_post_text.incl @@ -0,0 +1,3 @@ +/* Empty file - can be overriden + This file is included between the end of text and the start of data +*/ diff --git a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl index beb231348..9b0ef9660 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl @@ -1,7 +1,11 @@ INCLUDE "sections_copy_to_ram_text.incl" +INCLUDE "section_extra_post_text.incl" INCLUDE "sections_copy_to_ram_data.incl" +INCLUDE "section_extra_post_data.incl" INCLUDE "section_heap.incl" INCLUDE "sections_scratch.incl" +INCLUDE "section_extra_post_scratch.incl" +INCLUDE "sections_stack.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_default.incl b/src/rp2_common/pico_standard_link/script_include/sections_default.incl index 05f09f12b..e25f8042e 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_default.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_default.incl @@ -1,7 +1,11 @@ INCLUDE "sections_default_text.incl" +INCLUDE "section_extra_post_text.incl" INCLUDE "sections_default_data.incl" +INCLUDE "section_extra_post_data.incl" INCLUDE "section_heap.incl" INCLUDE "sections_scratch.incl" +INCLUDE "section_extra_post_scratch.incl" +INCLUDE "sections_stack.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl index 87760c03f..0ab32a9a8 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl @@ -1,6 +1,10 @@ INCLUDE "sections_no_flash_text.incl" +INCLUDE "section_extra_post_text.incl" INCLUDE "sections_no_flash_data.incl" +INCLUDE "section_extra_post_data.incl" INCLUDE "section_heap.incl" INCLUDE "sections_scratch.incl" +INCLUDE "section_extra_post_scratch.incl" +INCLUDE "sections_stack.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_scratch.incl b/src/rp2_common/pico_standard_link/script_include/sections_scratch.incl index f61c39639..21f99e4e3 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_scratch.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_scratch.incl @@ -16,22 +16,4 @@ SECTIONS __scratch_y_end__ = .; } > SCRATCH_Y AT> SCRATCH_Y_STORE __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y } diff --git a/src/rp2_common/pico_standard_link/script_include/sections_stack.incl b/src/rp2_common/pico_standard_link/script_include/sections_stack.incl new file mode 100644 index 000000000..15aaa8572 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/sections_stack.incl @@ -0,0 +1,20 @@ +SECTIONS +{ + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } > SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } > SCRATCH_Y +} diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt index 245e26904..80b157736 100644 --- a/test/kitchen_sink/CMakeLists.txt +++ b/test/kitchen_sink/CMakeLists.txt @@ -226,6 +226,8 @@ if (NOT KITCHEN_SINK_NO_BINARY_TYPE_VARIANTS) add_executable(kitchen_sink_ram_section ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) pico_add_linker_script_override_path(kitchen_sink_ram_section ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_ram_section_scripts) + # Also add this directory to test that multiple override paths work (although it doesn't override anything, as it's the same file) + pico_add_linker_script_override_path(kitchen_sink_ram_section ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_simple_overlay_scripts) target_link_libraries(kitchen_sink_ram_section kitchen_sink_libs kitchen_sink_options) pico_add_extra_outputs(kitchen_sink_ram_section) target_compile_definitions(kitchen_sink_ram_section PRIVATE KITCHEN_SINK_ID="ram section binary" EXTRA_DATA_SECTION=1) diff --git a/test/kitchen_sink/kitchen_sink_ram_section_scripts/section_extra_post_data.incl b/test/kitchen_sink/kitchen_sink_ram_section_scripts/section_extra_post_data.incl new file mode 100644 index 000000000..458bd6b26 --- /dev/null +++ b/test/kitchen_sink/kitchen_sink_ram_section_scripts/section_extra_post_data.incl @@ -0,0 +1,10 @@ +SECTIONS +{ + .extra_data : { + __extra_data_start__ = .; + *(.extra_data*) + . = ALIGN(4); + __extra_data_end__ = .; + } > RAM AT> RAM_STORE + __extra_data_source__ = LOADADDR(.extra_data); +} diff --git a/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.incl b/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.incl deleted file mode 100644 index 15e94dac0..000000000 --- a/test/kitchen_sink/kitchen_sink_ram_section_scripts/sections_default.incl +++ /dev/null @@ -1,19 +0,0 @@ -INCLUDE "sections_default_text.incl" -INCLUDE "sections_default_data.incl" - -SECTIONS -{ - .extra_data : { - __extra_data_start__ = .; - *(.extra_data*) - . = ALIGN(4); - __extra_data_end__ = .; - } > RAM AT> RAM_STORE - __extra_data_source__ = LOADADDR(.extra_data); -} - -INCLUDE "section_heap.incl" -INCLUDE "sections_scratch.incl" -INCLUDE "section_flash_end.incl" -INCLUDE "section_end.incl" -INCLUDE "section_platform_end.incl" \ No newline at end of file diff --git a/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.incl b/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/section_extra_post_data.incl similarity index 57% rename from test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.incl rename to test/kitchen_sink/kitchen_sink_simple_overlay_scripts/section_extra_post_data.incl index 00db2605d..d5b3d95bd 100644 --- a/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/sections_default.incl +++ b/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/section_extra_post_data.incl @@ -1,6 +1,3 @@ -INCLUDE "sections_default_text.incl" -INCLUDE "sections_default_data.incl" - SECTIONS { PROVIDE(__overlays_start__ = .); @@ -16,9 +13,3 @@ SECTIONS } > RAM AT> RAM_STORE PROVIDE(__overlays_end__ = .); } - -INCLUDE "section_heap.incl" -INCLUDE "sections_scratch.incl" -INCLUDE "section_flash_end.incl" -INCLUDE "section_end.incl" -INCLUDE "section_platform_end.incl" From 4180427fba4e1ba5730729b09e185ef8555552e3 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 19 Mar 2026 15:59:45 +0000 Subject: [PATCH 081/127] Fix comments, and add some more extra files --- .../script_include/section_boot2.incl | 2 +- .../script_include/section_no_flash_text.incl | 7 +++ .../script_include/section_platform_end.incl | 46 ------------------- .../sections_copy_to_ram_text.incl | 2 + .../script_include/section_platform_end.incl | 2 - .../script_include/memmap_copy_to_ram.incl | 1 + .../script_include/memmap_default.incl | 1 + .../script_include/memmap_no_flash.incl | 1 + .../memory_aliases_default.incl | 2 + .../memory_aliases_no_flash.incl | 2 + .../script_include/memory_extra.incl | 17 +++++++ .../script_include/section_binary_info.incl | 4 ++ .../script_include/section_boot2.incl | 4 ++ .../script_include/section_bss.incl | 7 +++ .../section_copy_to_ram_data.incl | 10 ++++ .../section_copy_to_ram_flashtext.incl | 8 ++++ .../section_copy_to_ram_text.incl | 4 ++ .../script_include/section_default_data.incl | 6 +++ .../script_include/section_default_text.incl | 11 +++++ .../script_include/section_end.incl | 26 ++--------- .../section_extra_post_data.incl | 7 ++- .../section_extra_post_end.incl | 7 +++ .../section_extra_post_scratch.incl | 7 ++- .../section_extra_post_text.incl | 7 ++- .../script_include/section_flash_begin.incl | 4 ++ .../script_include/section_flash_end.incl | 4 ++ .../script_include/section_heap.incl | 4 ++ .../script_include/section_no_flash_data.incl | 10 ++++ .../script_include/section_no_flash_text.incl | 16 +++++-- .../script_include/sections_arm_ex.incl | 4 ++ .../script_include/sections_copy_to_ram.incl | 3 ++ .../sections_copy_to_ram_data.incl | 2 + .../sections_copy_to_ram_text.incl | 2 + .../script_include/sections_default.incl | 3 ++ .../script_include/sections_default_data.incl | 2 + .../script_include/sections_default_text.incl | 2 + .../script_include/sections_no_flash.incl | 3 ++ .../sections_no_flash_data.incl | 2 + .../sections_no_flash_text.incl | 2 + .../script_include/sections_scratch.incl | 5 ++ .../script_include/set_memory_locations.incl | 2 + 41 files changed, 180 insertions(+), 81 deletions(-) create mode 100644 src/rp2_common/pico_standard_link/script_include/memory_extra.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_extra_post_end.incl diff --git a/src/rp2040/pico_platform/script_include/section_boot2.incl b/src/rp2040/pico_platform/script_include/section_boot2.incl index b6afc3763..8a8a6bea7 100644 --- a/src/rp2040/pico_platform/script_include/section_boot2.incl +++ b/src/rp2040/pico_platform/script_include/section_boot2.incl @@ -12,5 +12,5 @@ SECTIONS } > TEXT_STORE ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") + "ERROR: Pico second stage bootloader must be exactly 256 bytes in size for RP2040") } diff --git a/src/rp2040/pico_platform/script_include/section_no_flash_text.incl b/src/rp2040/pico_platform/script_include/section_no_flash_text.incl index 43fbfa783..57cd4cfc3 100644 --- a/src/rp2040/pico_platform/script_include/section_no_flash_text.incl +++ b/src/rp2040/pico_platform/script_include/section_no_flash_text.incl @@ -1,3 +1,10 @@ +/* Defines the following symbols for use by code: + __logical_binary_start + __binary_info_header_end + __embedded_block_end + __reset_start, __reset_end +*/ + SECTIONS { /* Note in NO_FLASH builds the entry point for both the bootrom, and debugger diff --git a/src/rp2040/pico_platform/script_include/section_platform_end.incl b/src/rp2040/pico_platform/script_include/section_platform_end.incl index 2d0165aa4..cccfc262d 100644 --- a/src/rp2040/pico_platform/script_include/section_platform_end.incl +++ b/src/rp2040/pico_platform/script_include/section_platform_end.incl @@ -1,50 +1,4 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - SECTIONS { - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ } diff --git a/src/rp2040/pico_platform/script_include/sections_copy_to_ram_text.incl b/src/rp2040/pico_platform/script_include/sections_copy_to_ram_text.incl index 0fdd197b8..be47abb6f 100644 --- a/src/rp2040/pico_platform/script_include/sections_copy_to_ram_text.incl +++ b/src/rp2040/pico_platform/script_include/sections_copy_to_ram_text.incl @@ -1,3 +1,5 @@ +/* This swaps section_boot2 and section_default_text, because RP2040 binaries must begin with boot2 */ + INCLUDE "section_flash_begin.incl" INCLUDE "section_boot2.incl" INCLUDE "section_copy_to_ram_flashtext.incl" diff --git a/src/rp2350/pico_platform/script_include/section_platform_end.incl b/src/rp2350/pico_platform/script_include/section_platform_end.incl index 43cc19ecd..9503fa173 100644 --- a/src/rp2350/pico_platform/script_include/section_platform_end.incl +++ b/src/rp2350/pico_platform/script_include/section_platform_end.incl @@ -2,6 +2,4 @@ SECTIONS { ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ } diff --git a/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl b/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl index f2b8e7159..b886383ec 100644 --- a/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl +++ b/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl @@ -5,6 +5,7 @@ INCLUDE "set_memory_locations.incl" INCLUDE "memory_flash.incl" INCLUDE "memory_ram.incl" INCLUDE "memory_scratch.incl" +INCLUDE "memory_extra.incl" /* Include aliases for storage memory regions */ INCLUDE "memory_aliases_default.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/memmap_default.incl b/src/rp2_common/pico_standard_link/script_include/memmap_default.incl index 791d4ef2b..3a0fb8ea7 100644 --- a/src/rp2_common/pico_standard_link/script_include/memmap_default.incl +++ b/src/rp2_common/pico_standard_link/script_include/memmap_default.incl @@ -5,6 +5,7 @@ INCLUDE "set_memory_locations.incl" INCLUDE "memory_flash.incl" INCLUDE "memory_ram.incl" INCLUDE "memory_scratch.incl" +INCLUDE "memory_extra.incl" /* Include aliases for storage memory regions */ INCLUDE "memory_aliases_default.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.incl b/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.incl index e9578be46..294477788 100644 --- a/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.incl +++ b/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.incl @@ -4,6 +4,7 @@ INCLUDE "set_memory_locations.incl" /* Include memory regions used */ INCLUDE "memory_ram.incl" INCLUDE "memory_scratch.incl" +INCLUDE "memory_extra.incl" /* Include aliases for no_flash storage memory regions (alias to themselves) */ INCLUDE "memory_aliases_no_flash.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/memory_aliases_default.incl b/src/rp2_common/pico_standard_link/script_include/memory_aliases_default.incl index 4c16d41be..370b63ed1 100644 --- a/src/rp2_common/pico_standard_link/script_include/memory_aliases_default.incl +++ b/src/rp2_common/pico_standard_link/script_include/memory_aliases_default.incl @@ -1,3 +1,5 @@ +/* Store everything in flash */ + REGION_ALIAS("TEXT_STORE", FLASH); REGION_ALIAS("RAM_STORE", FLASH); REGION_ALIAS("SCRATCH_X_STORE", FLASH); diff --git a/src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.incl b/src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.incl index 9190b32ab..258072736 100644 --- a/src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.incl +++ b/src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.incl @@ -1,3 +1,5 @@ +/* Store everything where it came from (ram/scratch) */ + REGION_ALIAS("TEXT_STORE", RAM); REGION_ALIAS("RAM_STORE", RAM); REGION_ALIAS("SCRATCH_X_STORE", SCRATCH_X); diff --git a/src/rp2_common/pico_standard_link/script_include/memory_extra.incl b/src/rp2_common/pico_standard_link/script_include/memory_extra.incl new file mode 100644 index 000000000..cdd16166c --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/memory_extra.incl @@ -0,0 +1,17 @@ +/* Empty file + + This file can be overridden to add extra memory regions. + + For example, to add a PSRAM region, you would replace + this file with: + + MEMORY + { + PSRAM(rwx) : ORIGIN = 0x11000000, LENGTH = 8M + } + + Or to include a XIP_RAM region, you would replace + this file with: + + INCLUDE "memory_xip_ram.incl" +*/ diff --git a/src/rp2_common/pico_standard_link/script_include/section_binary_info.incl b/src/rp2_common/pico_standard_link/script_include/section_binary_info.incl index f7238d09a..7c76c03e9 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_binary_info.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_binary_info.incl @@ -1,3 +1,7 @@ +/* Defines the following symbols for use by code: + __binary_info_start, __binary_info_end +*/ + SECTIONS { /* Machine inspectable binary information */ diff --git a/src/rp2_common/pico_standard_link/script_include/section_boot2.incl b/src/rp2_common/pico_standard_link/script_include/section_boot2.incl index 14e362776..7423819c4 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_boot2.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_boot2.incl @@ -1,3 +1,7 @@ +/* Defines the following symbols for use by code: + __boot2_start__, __boot2_end__ +*/ + SECTIONS { /* Note the boot2 section is optional, and should be discarded if there is diff --git a/src/rp2_common/pico_standard_link/script_include/section_bss.incl b/src/rp2_common/pico_standard_link/script_include/section_bss.incl index 172436df6..38de94018 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_bss.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_bss.incl @@ -1,3 +1,10 @@ +/* Defines the following symbols for use by code: + __bss_start__, __bss_end__ + __tls_base, __tls_end + __tbss_end + __global_pointer$ +*/ + SECTIONS { .tbss (NOLOAD) : { diff --git a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.incl b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.incl index 82084a70b..60890c885 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_data.incl @@ -1,3 +1,13 @@ +/* Defines the following symbols for use by code: + __data_start__, __data_end__ + __mutex_array_start, __mutex_array_end + __preinit_array_start, __preinit_array_end + __init_array_start, __init_array_end + __fini_array_start, __fini_array_end + __tdata_end + __etext +*/ + SECTIONS { .data : { diff --git a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_flashtext.incl b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_flashtext.incl index a0c794eb9..12d79dbe4 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_flashtext.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_flashtext.incl @@ -1,7 +1,15 @@ +/* Defines the following symbols for use by code: + __logical_binary_start + __binary_info_header_end + __embedded_block_end +*/ + SECTIONS { /* The bootrom will enter the image at the point indicated in your IMAGE_DEF, which is usually the reset handler of your vector table. + If there is no point indicated in the IMAGE_DEF, it expects a VT at + the start of the image, and will use the entry point from that. The debugger will use the ELF entry point, which is the _entry_point symbol, and in our case is *different from the bootrom's entry point.* diff --git a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.incl b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.incl index 7d6eb9d17..a9e36bbb1 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_text.incl @@ -1,3 +1,7 @@ +/* Defines the following symbols for use by code: + __ram_text_start__, __ram_text_end__, __ram_text_source__ +*/ + SECTIONS { .text : { diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_data.incl b/src/rp2_common/pico_standard_link/script_include/section_default_data.incl index a1f759b39..114b3c493 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_default_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_default_data.incl @@ -1,3 +1,9 @@ +/* Defines the following symbols for use by code: + __data_start__, __data_end__ + __mutex_array_start, __mutex_array_end + __etext +*/ + SECTIONS { .data : { diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_text.incl b/src/rp2_common/pico_standard_link/script_include/section_default_text.incl index 63905474b..a11f7b5e4 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_default_text.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_default_text.incl @@ -1,7 +1,18 @@ +/* Defines the following symbols for use by code: + __logical_binary_start + __binary_info_header_end + __embedded_block_end + __preinit_array_start, __preinit_array_end + __init_array_start, __init_array_end + __fini_array_start, __fini_array_end +*/ + SECTIONS { /* The bootrom will enter the image at the point indicated in your IMAGE_DEF, which is usually the reset handler of your vector table. + If there is no point indicated in the IMAGE_DEF, it expects a VT at + the start of the image, and will use the entry point from that. The debugger will use the ELF entry point, which is the _entry_point symbol, and in our case is *different from the bootrom's entry point.* diff --git a/src/rp2_common/pico_standard_link/script_include/section_end.incl b/src/rp2_common/pico_standard_link/script_include/section_end.incl index 53d328174..6de5ead43 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_end.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_end.incl @@ -1,24 +1,10 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit +/* Defines the following symbols for use by code: __StackLimit - __StackTop + __StackOneTop, __StackOneBottom + __StackTop, __StackBottom __stack (== StackTop) + + Also defines additional symbols for other compilers/libcs */ SECTIONS @@ -44,6 +30,4 @@ SECTIONS /* Check if data + heap + stack exceeds RAM limit */ ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - /* todo assert on extra code */ } diff --git a/src/rp2_common/pico_standard_link/script_include/section_extra_post_data.incl b/src/rp2_common/pico_standard_link/script_include/section_extra_post_data.incl index 584a11e64..00360c637 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_extra_post_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_extra_post_data.incl @@ -1,3 +1,6 @@ -/* Empty file - can be overriden - This file is included between the end of data/bss and the start of the heap +/* Empty file + + This file is included between the end of data/bss and the start of the heap. + + It can be overridden to add extra sections into ram. */ diff --git a/src/rp2_common/pico_standard_link/script_include/section_extra_post_end.incl b/src/rp2_common/pico_standard_link/script_include/section_extra_post_end.incl new file mode 100644 index 000000000..6e28eacb4 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_extra_post_end.incl @@ -0,0 +1,7 @@ +/* Empty file + + This file is included after the section_end and section_platform_end files. + + It can be overridden to override any symbols provided by the linker scripts, + or to add custom asserts. +*/ diff --git a/src/rp2_common/pico_standard_link/script_include/section_extra_post_scratch.incl b/src/rp2_common/pico_standard_link/script_include/section_extra_post_scratch.incl index b306a920e..245c039ee 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_extra_post_scratch.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_extra_post_scratch.incl @@ -1,3 +1,6 @@ -/* Empty file - can be overriden - This file is included between the end of scratch and the start of the stack +/* Empty file + + This file is included between the end of scratch and the start of the stack. + + It can be overridden to add extra sections in the scratch memory, before the stack. */ diff --git a/src/rp2_common/pico_standard_link/script_include/section_extra_post_text.incl b/src/rp2_common/pico_standard_link/script_include/section_extra_post_text.incl index 3d8214675..e21811e4c 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_extra_post_text.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_extra_post_text.incl @@ -1,3 +1,6 @@ -/* Empty file - can be overriden - This file is included between the end of text and the start of data +/* Empty file + + This file is included between the end of text and the start of data. + + It can be overridden to add extra sections into flash. */ diff --git a/src/rp2_common/pico_standard_link/script_include/section_flash_begin.incl b/src/rp2_common/pico_standard_link/script_include/section_flash_begin.incl index fdff1ad09..48492a926 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_flash_begin.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_flash_begin.incl @@ -1,3 +1,7 @@ +/* Defines the following symbols for use by code: + __flash_binary_start +*/ + SECTIONS { .flash_begin : { diff --git a/src/rp2_common/pico_standard_link/script_include/section_flash_end.incl b/src/rp2_common/pico_standard_link/script_include/section_flash_end.incl index 92a3e7dff..38d3481d7 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_flash_end.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_flash_end.incl @@ -1,3 +1,7 @@ +/* Defines the following symbols for use by code: + __flash_binary_end +*/ + SECTIONS { .flash_end : { diff --git a/src/rp2_common/pico_standard_link/script_include/section_heap.incl b/src/rp2_common/pico_standard_link/script_include/section_heap.incl index 1cc9e0de1..240e118d4 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_heap.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_heap.incl @@ -1,3 +1,7 @@ +/* Defines the following symbols for use by code: + __HeapLimit +*/ + SECTIONS { .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): diff --git a/src/rp2_common/pico_standard_link/script_include/section_no_flash_data.incl b/src/rp2_common/pico_standard_link/script_include/section_no_flash_data.incl index e1c5ee909..57c38782f 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_no_flash_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_no_flash_data.incl @@ -1,3 +1,13 @@ +/* Defines the following symbols for use by code: + __data_start__, __data_end__ + __mutex_array_start, __mutex_array_end + __preinit_array_start, __preinit_array_end + __init_array_start, __init_array_end + __fini_array_start, __fini_array_end + __tdata_end + __etext +*/ + SECTIONS { .data : { diff --git a/src/rp2_common/pico_standard_link/script_include/section_no_flash_text.incl b/src/rp2_common/pico_standard_link/script_include/section_no_flash_text.incl index 912aa13d2..e7ec24187 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_no_flash_text.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_no_flash_text.incl @@ -1,10 +1,16 @@ +/* Defines the following symbols for use by code: + __logical_binary_start + __binary_info_header_end + __embedded_block_end + __reset_start, __reset_end +*/ + SECTIONS { - /* Note unlike RP2040, we start the image with a vector table even for - NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the - image by default; on RISC-V, the default is to enter the image at its - lowest address, so an IMAGE_DEF item is required to specify the - nondefault entry point. */ + /* On Arm, the bootrom expects a VT at the start of the image by default; + on RISC-V, the default is to enter the image at its lowest address, so + an IMAGE_DEF item is required to specify the nondefault entry point. + */ .text : { __logical_binary_start = .; diff --git a/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl b/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl index 6b6ee8d0a..cf4cb4dee 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl @@ -1,3 +1,7 @@ +/* Defines the following symbols for use by code: + __exidx_start, __exidx_end +*/ + SECTIONS { .ARM.extab : diff --git a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl index 9b0ef9660..fbebab43c 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl @@ -1,3 +1,5 @@ +/* Main section list for copy_to_ram binaries */ + INCLUDE "sections_copy_to_ram_text.incl" INCLUDE "section_extra_post_text.incl" INCLUDE "sections_copy_to_ram_data.incl" @@ -9,3 +11,4 @@ INCLUDE "sections_stack.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" +INCLUDE "section_extra_post_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl index b0de72ede..ff90005e1 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl @@ -1,2 +1,4 @@ +/* Sub-section list for read/write sections in copy_to_ram binaries */ + INCLUDE "section_copy_to_ram_data.incl" INCLUDE "section_bss.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_text.incl b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_text.incl index f19c1aab3..7dcb9c1cf 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_text.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_text.incl @@ -1,3 +1,5 @@ +/* Sub-section list for read-only sections in copy_to_ram binaries */ + INCLUDE "section_flash_begin.incl" INCLUDE "section_copy_to_ram_flashtext.incl" INCLUDE "section_boot2.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_default.incl b/src/rp2_common/pico_standard_link/script_include/sections_default.incl index e25f8042e..858c4afa6 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_default.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_default.incl @@ -1,3 +1,5 @@ +/* Main section list for default binaries */ + INCLUDE "sections_default_text.incl" INCLUDE "section_extra_post_text.incl" INCLUDE "sections_default_data.incl" @@ -9,3 +11,4 @@ INCLUDE "sections_stack.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" +INCLUDE "section_extra_post_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl b/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl index e61f35527..cfa77cb2f 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl @@ -1,3 +1,5 @@ +/* Sub-section list for read/write sections in default binaries */ + INCLUDE "section_ram_vector_table.incl" INCLUDE "section_uninitialized_data.incl" INCLUDE "section_default_data.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_default_text.incl b/src/rp2_common/pico_standard_link/script_include/sections_default_text.incl index 5959a5b5d..cc1985309 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_default_text.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_default_text.incl @@ -1,3 +1,5 @@ +/* Sub-section list for read-only sections in default binaries */ + INCLUDE "section_flash_begin.incl" INCLUDE "section_default_text.incl" INCLUDE "section_boot2.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl index 0ab32a9a8..5e1042727 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl @@ -1,3 +1,5 @@ +/* Main section list for no_flash binaries */ + INCLUDE "sections_no_flash_text.incl" INCLUDE "section_extra_post_text.incl" INCLUDE "sections_no_flash_data.incl" @@ -8,3 +10,4 @@ INCLUDE "section_extra_post_scratch.incl" INCLUDE "sections_stack.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" +INCLUDE "section_extra_post_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl b/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl index 084fbda4f..6a55a1481 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl @@ -1,3 +1,5 @@ +/* Sub-section list for read/write sections in no_flash binaries */ + INCLUDE "section_no_flash_data.incl" INCLUDE "section_uninitialized_data.incl" INCLUDE "section_bss.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_no_flash_text.incl b/src/rp2_common/pico_standard_link/script_include/sections_no_flash_text.incl index 65de1fa12..0217b33c5 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_no_flash_text.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_no_flash_text.incl @@ -1,3 +1,5 @@ +/* Sub-section list for read-only sections in no_flash binaries */ + INCLUDE "section_no_flash_text.incl" INCLUDE "section_no_flash_rodata.incl" INCLUDE "sections_arm_ex.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_scratch.incl b/src/rp2_common/pico_standard_link/script_include/sections_scratch.incl index 21f99e4e3..7505ca627 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_scratch.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_scratch.incl @@ -1,3 +1,8 @@ +/* Defines the following symbols for use by code: + __scratch_x_start__, __scratch_x_end__, __scratch_x_source__ + __scratch_y_start__, __scratch_y_end__, __scratch_y_source__ +*/ + SECTIONS { /* Start and end symbols must be word-aligned */ diff --git a/src/rp2_common/pico_standard_link/script_include/set_memory_locations.incl b/src/rp2_common/pico_standard_link/script_include/set_memory_locations.incl index a9110eb59..a2341f42a 100644 --- a/src/rp2_common/pico_standard_link/script_include/set_memory_locations.incl +++ b/src/rp2_common/pico_standard_link/script_include/set_memory_locations.incl @@ -1,3 +1,5 @@ +/* Set memory locations either to the already defined value, or to the default value from default_locations.ld */ + RAM_ORIGIN = DEFINED(RAM_ORIGIN) ? RAM_ORIGIN : RAM_ORIGIN_DEFAULT; RAM_LENGTH = DEFINED(RAM_LENGTH) ? RAM_LENGTH : RAM_LENGTH_DEFAULT; SCRATCH_X_ORIGIN = DEFINED(SCRATCH_X_ORIGIN) ? SCRATCH_X_ORIGIN : SCRATCH_X_ORIGIN_DEFAULT; From c122bf7280ba6d5ae87b7e9f0bf6f81e9647f48e Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 19 Mar 2026 16:12:49 +0000 Subject: [PATCH 082/127] Add generated override files - currently unused, but can be overridden in the future by CMake/bazel functions --- .../pico_standard_link/script_include/memmap_copy_to_ram.incl | 1 + .../pico_standard_link/script_include/memmap_default.incl | 1 + .../pico_standard_link/script_include/memmap_no_flash.incl | 1 + .../pico_standard_link/script_include/memory_generated.incl | 4 ++++ .../script_include/section_generated_post_data.incl | 4 ++++ .../script_include/section_generated_post_end.incl | 4 ++++ .../script_include/section_generated_post_scratch.incl | 4 ++++ .../script_include/section_generated_post_text.incl | 4 ++++ .../script_include/sections_copy_to_ram.incl | 4 ++++ .../pico_standard_link/script_include/sections_default.incl | 4 ++++ .../pico_standard_link/script_include/sections_no_flash.incl | 4 ++++ 11 files changed, 35 insertions(+) create mode 100644 src/rp2_common/pico_standard_link/script_include/memory_generated.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_generated_post_data.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_generated_post_end.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_generated_post_scratch.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_generated_post_text.incl diff --git a/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl b/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl index b886383ec..d16c16ed6 100644 --- a/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl +++ b/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl @@ -5,6 +5,7 @@ INCLUDE "set_memory_locations.incl" INCLUDE "memory_flash.incl" INCLUDE "memory_ram.incl" INCLUDE "memory_scratch.incl" +INCLUDE "memory_generated.incl" INCLUDE "memory_extra.incl" /* Include aliases for storage memory regions */ diff --git a/src/rp2_common/pico_standard_link/script_include/memmap_default.incl b/src/rp2_common/pico_standard_link/script_include/memmap_default.incl index 3a0fb8ea7..1367ee18e 100644 --- a/src/rp2_common/pico_standard_link/script_include/memmap_default.incl +++ b/src/rp2_common/pico_standard_link/script_include/memmap_default.incl @@ -5,6 +5,7 @@ INCLUDE "set_memory_locations.incl" INCLUDE "memory_flash.incl" INCLUDE "memory_ram.incl" INCLUDE "memory_scratch.incl" +INCLUDE "memory_generated.incl" INCLUDE "memory_extra.incl" /* Include aliases for storage memory regions */ diff --git a/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.incl b/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.incl index 294477788..c043470e9 100644 --- a/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.incl +++ b/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.incl @@ -4,6 +4,7 @@ INCLUDE "set_memory_locations.incl" /* Include memory regions used */ INCLUDE "memory_ram.incl" INCLUDE "memory_scratch.incl" +INCLUDE "memory_generated.incl" INCLUDE "memory_extra.incl" /* Include aliases for no_flash storage memory regions (alias to themselves) */ diff --git a/src/rp2_common/pico_standard_link/script_include/memory_generated.incl b/src/rp2_common/pico_standard_link/script_include/memory_generated.incl new file mode 100644 index 000000000..2060e314c --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/memory_generated.incl @@ -0,0 +1,4 @@ +/* DO NOT OVERRIDE THIS FILE + + This file is provided for the SDK to override +*/ diff --git a/src/rp2_common/pico_standard_link/script_include/section_generated_post_data.incl b/src/rp2_common/pico_standard_link/script_include/section_generated_post_data.incl new file mode 100644 index 000000000..2060e314c --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_generated_post_data.incl @@ -0,0 +1,4 @@ +/* DO NOT OVERRIDE THIS FILE + + This file is provided for the SDK to override +*/ diff --git a/src/rp2_common/pico_standard_link/script_include/section_generated_post_end.incl b/src/rp2_common/pico_standard_link/script_include/section_generated_post_end.incl new file mode 100644 index 000000000..2060e314c --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_generated_post_end.incl @@ -0,0 +1,4 @@ +/* DO NOT OVERRIDE THIS FILE + + This file is provided for the SDK to override +*/ diff --git a/src/rp2_common/pico_standard_link/script_include/section_generated_post_scratch.incl b/src/rp2_common/pico_standard_link/script_include/section_generated_post_scratch.incl new file mode 100644 index 000000000..2060e314c --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_generated_post_scratch.incl @@ -0,0 +1,4 @@ +/* DO NOT OVERRIDE THIS FILE + + This file is provided for the SDK to override +*/ diff --git a/src/rp2_common/pico_standard_link/script_include/section_generated_post_text.incl b/src/rp2_common/pico_standard_link/script_include/section_generated_post_text.incl new file mode 100644 index 000000000..2060e314c --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_generated_post_text.incl @@ -0,0 +1,4 @@ +/* DO NOT OVERRIDE THIS FILE + + This file is provided for the SDK to override +*/ diff --git a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl index fbebab43c..a4baa85aa 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl @@ -1,14 +1,18 @@ /* Main section list for copy_to_ram binaries */ INCLUDE "sections_copy_to_ram_text.incl" +INCLUDE "section_generated_post_text.incl" INCLUDE "section_extra_post_text.incl" INCLUDE "sections_copy_to_ram_data.incl" +INCLUDE "section_generated_post_data.incl" INCLUDE "section_extra_post_data.incl" INCLUDE "section_heap.incl" INCLUDE "sections_scratch.incl" +INCLUDE "section_generated_post_scratch.incl" INCLUDE "section_extra_post_scratch.incl" INCLUDE "sections_stack.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" +INCLUDE "section_generated_post_end.incl" INCLUDE "section_extra_post_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_default.incl b/src/rp2_common/pico_standard_link/script_include/sections_default.incl index 858c4afa6..0c9493e73 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_default.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_default.incl @@ -1,14 +1,18 @@ /* Main section list for default binaries */ INCLUDE "sections_default_text.incl" +INCLUDE "section_generated_post_text.incl" INCLUDE "section_extra_post_text.incl" INCLUDE "sections_default_data.incl" +INCLUDE "section_generated_post_data.incl" INCLUDE "section_extra_post_data.incl" INCLUDE "section_heap.incl" INCLUDE "sections_scratch.incl" +INCLUDE "section_generated_post_scratch.incl" INCLUDE "section_extra_post_scratch.incl" INCLUDE "sections_stack.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" +INCLUDE "section_generated_post_end.incl" INCLUDE "section_extra_post_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl index 5e1042727..941bf3121 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl @@ -1,13 +1,17 @@ /* Main section list for no_flash binaries */ INCLUDE "sections_no_flash_text.incl" +INCLUDE "section_generated_post_text.incl" INCLUDE "section_extra_post_text.incl" INCLUDE "sections_no_flash_data.incl" +INCLUDE "section_generated_post_data.incl" INCLUDE "section_extra_post_data.incl" INCLUDE "section_heap.incl" INCLUDE "sections_scratch.incl" +INCLUDE "section_generated_post_scratch.incl" INCLUDE "section_extra_post_scratch.incl" INCLUDE "sections_stack.incl" INCLUDE "section_end.incl" INCLUDE "section_platform_end.incl" +INCLUDE "section_generated_post_end.incl" INCLUDE "section_extra_post_end.incl" From ea8320b1c6d69bb2842df61203e751868b6d9658 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 19 Mar 2026 17:21:28 +0000 Subject: [PATCH 083/127] pico_add_linker_script_override_path can now be called after target_link_libraries, as it uses generator expressions Also add more checks to kitchen_sink --- src/rp2_common/pico_standard_link/CMakeLists.txt | 7 +------ test/kitchen_sink/CMakeLists.txt | 7 +++++-- test/kitchen_sink/kitchen_sink.c | 2 ++ .../section_extra_post_end.incl | 4 ++++ 4 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 test/kitchen_sink/kitchen_sink_extra_end_scripts/section_extra_post_end.incl diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index 9db70b1e6..b327c9d40 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -93,16 +93,11 @@ if (NOT TARGET pico_standard_link) # call pico_add_linker_script_override_path(TARGET ${CMAKE_CURRENT_LIST_DIR}/extra_scripts). This will # include the custom files first, overriding the default ones. # - # Must be called before target_link_libraries, otherwise it will not override the default linker scripts. - # It will also not override prior paths set by pico_add_linker_script_override_path. + # It will not override prior paths set by pico_add_linker_script_override_path. # # \param\ TARGET The target to add the linker script override path to # \param\ PATH The path containing the overriding linker scripts function(pico_add_linker_script_override_path TARGET PATH) - get_target_property(OUT ${TARGET} LINK_LIBRARIES) - if (OUT) - message(WARNING "pico_add_linker_script_override_path does not work when called after target_link_libraries") - endif() set_property(TARGET ${TARGET} APPEND PROPERTY PICO_TARGET_LINKER_SCRIPT_OVERRIDE_PATHS "${PATH}") endfunction() diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt index 80b157736..ed039d87e 100644 --- a/test/kitchen_sink/CMakeLists.txt +++ b/test/kitchen_sink/CMakeLists.txt @@ -220,14 +220,16 @@ if (NOT KITCHEN_SINK_NO_BINARY_TYPE_VARIANTS) pico_set_linker_script_var(kitchen_sink_ram_custom RAM_ORIGIN 0x20020000) pico_set_linker_script_var(kitchen_sink_ram_custom RAM_LENGTH 128k) pico_set_linker_script_var(kitchen_sink_ram_custom HEAP_LOC 0x20030000) + # Also swap scratch x and scratch y, to test using defaults + pico_set_linker_script_var(kitchen_sink_ram_custom SCRATCH_X_ORIGIN SCRATCH_Y_ORIGIN_DEFAULT) + pico_set_linker_script_var(kitchen_sink_ram_custom SCRATCH_Y_ORIGIN SCRATCH_X_ORIGIN_DEFAULT) target_link_libraries(kitchen_sink_ram_custom kitchen_sink_libs kitchen_sink_options) pico_add_extra_outputs(kitchen_sink_ram_custom) target_compile_definitions(kitchen_sink_ram_custom PRIVATE KITCHEN_SINK_ID="custom ram binary") add_executable(kitchen_sink_ram_section ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) pico_add_linker_script_override_path(kitchen_sink_ram_section ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_ram_section_scripts) - # Also add this directory to test that multiple override paths work (although it doesn't override anything, as it's the same file) - pico_add_linker_script_override_path(kitchen_sink_ram_section ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_simple_overlay_scripts) + pico_add_linker_script_override_path(kitchen_sink_ram_section ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_extra_end_scripts) target_link_libraries(kitchen_sink_ram_section kitchen_sink_libs kitchen_sink_options) pico_add_extra_outputs(kitchen_sink_ram_section) target_compile_definitions(kitchen_sink_ram_section PRIVATE KITCHEN_SINK_ID="ram section binary" EXTRA_DATA_SECTION=1) @@ -236,6 +238,7 @@ if (NOT KITCHEN_SINK_NO_BINARY_TYPE_VARIANTS) # Clang does not support overlay sections add_executable(kitchen_sink_simple_overlay ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) pico_add_linker_script_override_path(kitchen_sink_simple_overlay ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_simple_overlay_scripts) + pico_add_linker_script_override_path(kitchen_sink_simple_overlay ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_extra_end_scripts) target_link_libraries(kitchen_sink_simple_overlay kitchen_sink_libs kitchen_sink_options) pico_add_extra_outputs(kitchen_sink_simple_overlay) target_compile_definitions(kitchen_sink_simple_overlay PRIVATE KITCHEN_SINK_ID="simple overlay binary" EXTRA_DATA_SECTION=2) diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index 6a3a5fbee..ba5fe7613 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -86,6 +86,8 @@ int main(void) { hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL)); printf("%f\n", foox(1.3f, 2.6f)); #ifdef EXTRA_DATA_SECTION + extern uint32_t __extra_end_variable__; + printf("__extra_end_variable__ = %p\n", (void *)&__extra_end_variable__); #if EXTRA_DATA_SECTION > 1 extern uint32_t __overlays_start__; uint32_t stored_words; diff --git a/test/kitchen_sink/kitchen_sink_extra_end_scripts/section_extra_post_end.incl b/test/kitchen_sink/kitchen_sink_extra_end_scripts/section_extra_post_end.incl new file mode 100644 index 000000000..52fe92ddd --- /dev/null +++ b/test/kitchen_sink/kitchen_sink_extra_end_scripts/section_extra_post_end.incl @@ -0,0 +1,4 @@ +SECTIONS +{ + PROVIDE(__extra_end_variable__ = 4M); +} From ad35ad81b2ff6291c975e27a033390c4f7f8005e Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 19 Mar 2026 17:29:42 +0000 Subject: [PATCH 084/127] Add extra post_platform_end sections Intended for platform specific overrides, whereas post_end is for cross-platform overrides, similar to section_end vs section_platform_end --- .../script_include/section_extra_post_end.incl | 2 +- .../script_include/section_extra_post_platform_end.incl | 9 +++++++++ .../section_generated_post_platform_end.incl | 4 ++++ .../script_include/sections_copy_to_ram.incl | 4 +++- .../script_include/sections_default.incl | 4 +++- .../script_include/sections_no_flash.incl | 4 +++- 6 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 src/rp2_common/pico_standard_link/script_include/section_extra_post_platform_end.incl create mode 100644 src/rp2_common/pico_standard_link/script_include/section_generated_post_platform_end.incl diff --git a/src/rp2_common/pico_standard_link/script_include/section_extra_post_end.incl b/src/rp2_common/pico_standard_link/script_include/section_extra_post_end.incl index 6e28eacb4..24a964de1 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_extra_post_end.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_extra_post_end.incl @@ -1,6 +1,6 @@ /* Empty file - This file is included after the section_end and section_platform_end files. + This file is included after the section_end file. It can be overridden to override any symbols provided by the linker scripts, or to add custom asserts. diff --git a/src/rp2_common/pico_standard_link/script_include/section_extra_post_platform_end.incl b/src/rp2_common/pico_standard_link/script_include/section_extra_post_platform_end.incl new file mode 100644 index 000000000..7be81fcd5 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_extra_post_platform_end.incl @@ -0,0 +1,9 @@ +/* Empty file + + This file is included after the section_platform_end file. + + It can be overridden to override any symbols provided by the linker scripts, + or to add custom asserts. + + It is intended to be used for platform specific overrides. +*/ diff --git a/src/rp2_common/pico_standard_link/script_include/section_generated_post_platform_end.incl b/src/rp2_common/pico_standard_link/script_include/section_generated_post_platform_end.incl new file mode 100644 index 000000000..2060e314c --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_generated_post_platform_end.incl @@ -0,0 +1,4 @@ +/* DO NOT OVERRIDE THIS FILE + + This file is provided for the SDK to override +*/ diff --git a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl index a4baa85aa..0c3c7d42e 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl @@ -13,6 +13,8 @@ INCLUDE "section_extra_post_scratch.incl" INCLUDE "sections_stack.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" -INCLUDE "section_platform_end.incl" INCLUDE "section_generated_post_end.incl" INCLUDE "section_extra_post_end.incl" +INCLUDE "section_platform_end.incl" +INCLUDE "section_generated_post_platform_end.incl" +INCLUDE "section_extra_post_platform_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_default.incl b/src/rp2_common/pico_standard_link/script_include/sections_default.incl index 0c9493e73..4e07b3968 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_default.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_default.incl @@ -13,6 +13,8 @@ INCLUDE "section_extra_post_scratch.incl" INCLUDE "sections_stack.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" -INCLUDE "section_platform_end.incl" INCLUDE "section_generated_post_end.incl" INCLUDE "section_extra_post_end.incl" +INCLUDE "section_platform_end.incl" +INCLUDE "section_generated_post_platform_end.incl" +INCLUDE "section_extra_post_platform_end.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl index 941bf3121..e9ba353df 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl @@ -12,6 +12,8 @@ INCLUDE "section_generated_post_scratch.incl" INCLUDE "section_extra_post_scratch.incl" INCLUDE "sections_stack.incl" INCLUDE "section_end.incl" -INCLUDE "section_platform_end.incl" INCLUDE "section_generated_post_end.incl" INCLUDE "section_extra_post_end.incl" +INCLUDE "section_platform_end.incl" +INCLUDE "section_generated_post_platform_end.incl" +INCLUDE "section_extra_post_platform_end.incl" From 8e3aca507c2f413d0484251bb33746f96d6821a8 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 19 Mar 2026 17:47:00 +0000 Subject: [PATCH 085/127] review fixups --- .../script_include/section_copy_to_ram_flashtext.incl | 6 +++--- .../script_include/section_default_text.incl | 6 +++--- .../pico_standard_link/script_include/section_end.incl | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_flashtext.incl b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_flashtext.incl index 12d79dbe4..8c0792d0e 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_flashtext.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_copy_to_ram_flashtext.incl @@ -6,10 +6,10 @@ SECTIONS { - /* The bootrom will enter the image at the point indicated in your + /* The bootrom will enter the image at the entry point indicated in your IMAGE_DEF, which is usually the reset handler of your vector table. - If there is no point indicated in the IMAGE_DEF, it expects a VT at - the start of the image, and will use the entry point from that. + If there is no entry point indicated in the IMAGE_DEF, it expects a VT + at the start of the image, and will use the entry point from that. The debugger will use the ELF entry point, which is the _entry_point symbol, and in our case is *different from the bootrom's entry point.* diff --git a/src/rp2_common/pico_standard_link/script_include/section_default_text.incl b/src/rp2_common/pico_standard_link/script_include/section_default_text.incl index a11f7b5e4..911cafab2 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_default_text.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_default_text.incl @@ -9,10 +9,10 @@ SECTIONS { - /* The bootrom will enter the image at the point indicated in your + /* The bootrom will enter the image at the entry point indicated in your IMAGE_DEF, which is usually the reset handler of your vector table. - If there is no point indicated in the IMAGE_DEF, it expects a VT at - the start of the image, and will use the entry point from that. + If there is no entry point indicated in the IMAGE_DEF, it expects a VT + at the start of the image, and will use the entry point from that. The debugger will use the ELF entry point, which is the _entry_point symbol, and in our case is *different from the bootrom's entry point.* diff --git a/src/rp2_common/pico_standard_link/script_include/section_end.incl b/src/rp2_common/pico_standard_link/script_include/section_end.incl index 6de5ead43..3ffddcabd 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_end.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_end.incl @@ -2,7 +2,7 @@ __StackLimit __StackOneTop, __StackOneBottom __StackTop, __StackBottom - __stack (== StackTop) + __stack (== __StackTop) Also defines additional symbols for other compilers/libcs */ From e9e9a09b2d7ce73275ad3ea64f22c8d5159dcc65 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 20 Mar 2026 11:18:30 +0000 Subject: [PATCH 086/127] Fix bazel PICO_DEFAULT_LINKER_SCRIPT comment --- src/rp2_common/pico_standard_link/BUILD.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rp2_common/pico_standard_link/BUILD.bazel b/src/rp2_common/pico_standard_link/BUILD.bazel index 8817018a8..eceb5f25e 100644 --- a/src/rp2_common/pico_standard_link/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/BUILD.bazel @@ -22,7 +22,7 @@ generated_pico_flash_region( # # Setting globally: # * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT to point to your -# desired linker script (eg @pico-sdk//src/pico_standard_link:no_flash_linker_script) +# desired linker script (eg @pico-sdk//src/rp2_common/pico_standard_link:no_flash_linker_script) # # Setting per-binary: # * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT=@pico-sdk//bazel:empty_cc_lib From 519544e4384b7ff178812515fb21e87005c0f784 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 20 Mar 2026 14:10:30 +0000 Subject: [PATCH 087/127] Add PICO_DEFAULT_BINARY_TYPE to Bazel Existing method of just setting the linker script didn't work, because the PICO_NO_FLASH/PICO_COPY_TO_RAM define was only available in pico_platform, but needed to be propogated to things that only use pico_base_headers --- bazel/config/BUILD.bazel | 12 ++++ bazel/constraint/BUILD.bazel | 15 +++++ src/common/pico_base_headers/BUILD.bazel | 5 ++ src/rp2040/pico_platform/BUILD.bazel | 3 - src/rp2350/pico_platform/BUILD.bazel | 2 - src/rp2_common/pico_standard_link/BUILD.bazel | 12 +++- .../pico_standard_link/CMakeLists.txt | 1 + tools/bazel_build.py | 64 +++++++++++++++++++ 8 files changed, 106 insertions(+), 8 deletions(-) diff --git a/bazel/config/BUILD.bazel b/bazel/config/BUILD.bazel index 6b5b1f7c8..468e5a2ec 100644 --- a/bazel/config/BUILD.bazel +++ b/bazel/config/BUILD.bazel @@ -217,6 +217,18 @@ string_flag( build_setting_default = "Debug", ) +# PICO_BAZEL_CONFIG: PICO_DEFAULT_BINARY_TYPE, [Bazel only] The default binary type to use, type=string, default=default, group=build +string_flag( + name = "PICO_DEFAULT_BINARY_TYPE", + build_setting_default = "default", + values = [ + "default", + "no_flash", + "copy_to_ram", + "blocked_ram", + ], +) + # PICO_BAZEL_CONFIG: PICO_DEFAULT_LINKER_SCRIPT, [Bazel only] The library that provides a linker script to link into all binaries, default=//src/rp2_common/pico_standard_link:default_linker_script, group=pico_standard_link label_flag( name = "PICO_DEFAULT_LINKER_SCRIPT", diff --git a/bazel/constraint/BUILD.bazel b/bazel/constraint/BUILD.bazel index acd112469..de2154473 100644 --- a/bazel/constraint/BUILD.bazel +++ b/bazel/constraint/BUILD.bazel @@ -273,3 +273,18 @@ config_setting( name = "pico_compilation_no_fastbuild_args_set", flag_values = {"//bazel/config:PICO_COMPILATION_NO_FASTBUILD_ARGS": "True"}, ) + +config_setting( + name = "pico_binary_type_no_flash", + flag_values = {"//bazel/config:PICO_DEFAULT_BINARY_TYPE": "no_flash"}, +) + +config_setting( + name = "pico_binary_type_copy_to_ram", + flag_values = {"//bazel/config:PICO_DEFAULT_BINARY_TYPE": "copy_to_ram"}, +) + +config_setting( + name = "pico_binary_type_blocked_ram", + flag_values = {"//bazel/config:PICO_DEFAULT_BINARY_TYPE": "blocked_ram"}, +) diff --git a/src/common/pico_base_headers/BUILD.bazel b/src/common/pico_base_headers/BUILD.bazel index d7058ee85..4a859a3f2 100644 --- a/src/common/pico_base_headers/BUILD.bazel +++ b/src/common/pico_base_headers/BUILD.bazel @@ -74,6 +74,11 @@ cc_library( "//bazel/constraint:rp2040": ["PICO_RP2040=1"], "//bazel/constraint:rp2350": ["PICO_RP2350=1"], "//conditions:default": [], + }) + select({ + "//bazel/constraint:pico_binary_type_no_flash": ["PICO_NO_FLASH=1"], + "//bazel/constraint:pico_binary_type_copy_to_ram": ["PICO_COPY_TO_RAM=1"], + "//bazel/constraint:pico_binary_type_blocked_ram": ["PICO_USE_BLOCKED_RAM=1"], + "//conditions:default": [], }), ) diff --git a/src/rp2040/pico_platform/BUILD.bazel b/src/rp2040/pico_platform/BUILD.bazel index 2af1c7750..8014f4a11 100644 --- a/src/rp2040/pico_platform/BUILD.bazel +++ b/src/rp2040/pico_platform/BUILD.bazel @@ -105,7 +105,6 @@ cc_library( # PICO_BUILD_DEFINE: PICO_USE_BLOCKED_RAM, whether this is a 'blocked_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link cc_library( name = "blocked_ram_linker_script", - defines = ["PICO_USE_BLOCKED_RAM=1"], target_compatible_with = ["//bazel/constraint:rp2040"], visibility = [ "//src/rp2_common/pico_standard_link:__pkg__", @@ -123,7 +122,6 @@ cc_library( # PICO_BUILD_DEFINE: PICO_COPY_TO_RAM, whether this is a 'copy_to_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link cc_library( name = "copy_to_ram_linker_script", - defines = ["PICO_COPY_TO_RAM=1"], target_compatible_with = ["//bazel/constraint:rp2040"], visibility = [ "//src/rp2_common/pico_standard_link:__pkg__", @@ -141,7 +139,6 @@ cc_library( # PICO_BUILD_DEFINE: PICO_NO_FLASH, whether this is a 'no_flash' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link cc_library( name = "no_flash_linker_script", - defines = ["PICO_NO_FLASH=1"], target_compatible_with = ["//bazel/constraint:rp2040"], visibility = [ "//src/rp2_common/pico_standard_link:__pkg__", diff --git a/src/rp2350/pico_platform/BUILD.bazel b/src/rp2350/pico_platform/BUILD.bazel index e2e2c382d..13522b452 100644 --- a/src/rp2350/pico_platform/BUILD.bazel +++ b/src/rp2350/pico_platform/BUILD.bazel @@ -99,7 +99,6 @@ cc_library( # PICO_BUILD_DEFINE: PICO_COPY_TO_RAM, whether this is a 'copy_to_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link cc_library( name = "copy_to_ram_linker_script", - defines = ["PICO_COPY_TO_RAM=1"], target_compatible_with = ["//bazel/constraint:rp2350"], visibility = [ "//src/rp2_common/pico_standard_link:__pkg__", @@ -117,7 +116,6 @@ cc_library( # PICO_BUILD_DEFINE: PICO_NO_FLASH, whether this is a 'no_flash' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link cc_library( name = "no_flash_linker_script", - defines = ["PICO_NO_FLASH=1"], target_compatible_with = ["//bazel/constraint:rp2350"], visibility = [ "//src/rp2_common/pico_standard_link:__pkg__", diff --git a/src/rp2_common/pico_standard_link/BUILD.bazel b/src/rp2_common/pico_standard_link/BUILD.bazel index eceb5f25e..7f345bb8a 100644 --- a/src/rp2_common/pico_standard_link/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/BUILD.bazel @@ -20,16 +20,22 @@ generated_pico_flash_region( # It's possible to set linker scripts globally or on a per-binary basis. # -# Setting globally: +# Setting globally to a custom linker script: # * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT to point to your -# desired linker script (eg @pico-sdk//src/rp2_common/pico_standard_link:no_flash_linker_script) +# custom linker script - do not use this for SDK linker scripts, you must +# use PICO_DEFAULT_BINARY_TYPE instead # -# Setting per-binary: +# Setting per-binary to a custom linker script: # * Set --@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT=@pico-sdk//bazel:empty_cc_lib # * Manually add your desired linker script to each cc_binary. alias( name = "default_linker_script", actual = select({ + # Handle selection based on PICO_DEFAULT_BINARY_TYPE here + "//bazel/constraint:pico_binary_type_no_flash": "//src/rp2_common/pico_standard_link:no_flash_linker_script", + "//bazel/constraint:pico_binary_type_copy_to_ram": "//src/rp2_common/pico_standard_link:copy_to_ram_linker_script", + "//bazel/constraint:pico_binary_type_blocked_ram": "//src/rp2_common/pico_standard_link:blocked_ram_linker_script", + # Then for the default type "//bazel/constraint:rp2040": "//src/rp2040/pico_platform:default_linker_script", "//bazel/constraint:rp2350": "//src/rp2350/pico_platform:default_linker_script", "//conditions:default": "//bazel:incompatible_cc_lib", diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index b327c9d40..ff8e83220 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -109,6 +109,7 @@ if (NOT TARGET pico_standard_link) set_target_properties(${TARGET} PROPERTIES PICO_TARGET_BINARY_TYPE ${TYPE}) endfunction() + # PICO_CMAKE_CONFIG: PICO_DEFAULT_BINARY_TYPE, The default binary type to use, type=string, default=default, group=pico_standard_link # slightly messy as we support both the preferred PICO_DEFAULT_BINARY_TYPE and the individual variables if (NOT PICO_DEFAULT_BINARY_TYPE) if (PICO_NO_FLASH) diff --git a/tools/bazel_build.py b/tools/bazel_build.py index 522f28310..24e4e4a47 100755 --- a/tools/bazel_build.py +++ b/tools/bazel_build.py @@ -161,6 +161,70 @@ ) ), }, + { + "name": "rp2040 no_flash", + "args": ("--platforms=//bazel/platform:rp2040", "--@pico-sdk//bazel/config:PICO_DEFAULT_BINARY_TYPE=no_flash"), + "extra_targets": (), + "exclusions": frozenset( + ( + "//test/kitchen_sink:kitchen_sink_lwip_poll", + "//test/kitchen_sink:kitchen_sink_lwip_background", + # Host only. + "//test/pico_float_test:hazard3_test_gen", + # No RISC-V on RP2040. + "//test/pico_float_test:pico_float_test_hazard3", + # hardware_sha256 doesn't appear to work on RP2040. + "//test/pico_sha256_test:pico_sha256_test", + ) + ), + }, + { + "name": "rp2350 no_flash", + "args": ("--platforms=//bazel/platform:rp2350", "--@pico-sdk//bazel/config:PICO_DEFAULT_BINARY_TYPE=no_flash"), + "extra_targets": (), + "exclusions": frozenset( + ( + "//test/kitchen_sink:kitchen_sink_lwip_poll", + "//test/kitchen_sink:kitchen_sink_lwip_background", + # Host only. + "//test/pico_float_test:hazard3_test_gen", + # TODO: RISC-V support. + "//test/pico_float_test:pico_float_test_hazard3", + ) + ), + }, + { + "name": "rp2040 copy_to_ram", + "args": ("--platforms=//bazel/platform:rp2040", "--@pico-sdk//bazel/config:PICO_DEFAULT_BINARY_TYPE=copy_to_ram"), + "extra_targets": (), + "exclusions": frozenset( + ( + "//test/kitchen_sink:kitchen_sink_lwip_poll", + "//test/kitchen_sink:kitchen_sink_lwip_background", + # Host only. + "//test/pico_float_test:hazard3_test_gen", + # No RISC-V on RP2040. + "//test/pico_float_test:pico_float_test_hazard3", + # hardware_sha256 doesn't appear to work on RP2040. + "//test/pico_sha256_test:pico_sha256_test", + ) + ), + }, + { + "name": "rp2350 copy_to_ram", + "args": ("--platforms=//bazel/platform:rp2350", "--@pico-sdk//bazel/config:PICO_DEFAULT_BINARY_TYPE=copy_to_ram"), + "extra_targets": (), + "exclusions": frozenset( + ( + "//test/kitchen_sink:kitchen_sink_lwip_poll", + "//test/kitchen_sink:kitchen_sink_lwip_background", + # Host only. + "//test/pico_float_test:hazard3_test_gen", + # TODO: RISC-V support. + "//test/pico_float_test:pico_float_test_hazard3", + ) + ), + }, ) From 3f0615d0a2002ccafd438802597e7699fb821eec Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Fri, 20 Mar 2026 15:15:29 +0000 Subject: [PATCH 088/127] Fix PICO_DEFAULT_BINARY_TYPE descriptions --- bazel/config/BUILD.bazel | 2 +- src/rp2_common/pico_standard_link/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bazel/config/BUILD.bazel b/bazel/config/BUILD.bazel index 468e5a2ec..56b39e4a1 100644 --- a/bazel/config/BUILD.bazel +++ b/bazel/config/BUILD.bazel @@ -217,7 +217,7 @@ string_flag( build_setting_default = "Debug", ) -# PICO_BAZEL_CONFIG: PICO_DEFAULT_BINARY_TYPE, [Bazel only] The default binary type to use, type=string, default=default, group=build +# PICO_BAZEL_CONFIG: PICO_DEFAULT_BINARY_TYPE, The default binary type to use, type=string, default=default, group=build string_flag( name = "PICO_DEFAULT_BINARY_TYPE", build_setting_default = "default", diff --git a/src/rp2_common/pico_standard_link/CMakeLists.txt b/src/rp2_common/pico_standard_link/CMakeLists.txt index ff8e83220..6ebcd4d3d 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -109,7 +109,7 @@ if (NOT TARGET pico_standard_link) set_target_properties(${TARGET} PROPERTIES PICO_TARGET_BINARY_TYPE ${TYPE}) endfunction() - # PICO_CMAKE_CONFIG: PICO_DEFAULT_BINARY_TYPE, The default binary type to use, type=string, default=default, group=pico_standard_link + # PICO_CMAKE_CONFIG: PICO_DEFAULT_BINARY_TYPE, The default binary type to use, type=string, default=default, group=build # slightly messy as we support both the preferred PICO_DEFAULT_BINARY_TYPE and the individual variables if (NOT PICO_DEFAULT_BINARY_TYPE) if (PICO_NO_FLASH) From a26a42b1dbee1d1df72546ac85a4b60c4e13d885 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 25 Mar 2026 10:39:28 +0000 Subject: [PATCH 089/127] Add azel pico_set_binary_type transition, to allow setting binary type for individual binaries Can remove full no_flash etc test builds, as there can now be kitchen_sink_no_flash etc builds like in CMake --- bazel/util/transition.bzl | 15 +++++++ test/kitchen_sink/BUILD.bazel | 51 +++++++++++++++++++++++- tools/bazel_build.py | 73 +++++------------------------------ 3 files changed, 74 insertions(+), 65 deletions(-) diff --git a/bazel/util/transition.bzl b/bazel/util/transition.bzl index d01046358..9abe9749b 100644 --- a/bazel/util/transition.bzl +++ b/bazel/util/transition.bzl @@ -167,3 +167,18 @@ extra_copts_for_all_deps = declare_transtion( "//command_line_option:copt": "extra_copts", }, ) + +# This transition sets the binary type +pico_set_binary_type = declare_transtion( + attrs = { + "binary_type": attr.string(), + # This could be shared, but we don't in order to make it clearer that + # a transition is in use. + "_allowlist_function_transition": attr.label( + default = "@bazel_tools//tools/allowlists/function_transition_allowlist", + ), + }, + flag_overrides = { + "@pico-sdk//bazel/config:PICO_DEFAULT_BINARY_TYPE": "binary_type", + }, +) diff --git a/test/kitchen_sink/BUILD.bazel b/test/kitchen_sink/BUILD.bazel index fd0dd5ef9..325dc0d86 100644 --- a/test/kitchen_sink/BUILD.bazel +++ b/test/kitchen_sink/BUILD.bazel @@ -1,7 +1,7 @@ load("@rules_cc//cc:cc_binary.bzl", "cc_binary") load("@rules_cc//cc:cc_library.bzl", "cc_library") load("//bazel:defs.bzl", "compatible_with_rp2", "pico_generate_pio_header") -load("//bazel/util:transition.bzl", "kitchen_sink_test_binary") +load("//bazel/util:transition.bzl", "kitchen_sink_test_binary", "pico_set_binary_type") package(default_visibility = ["//visibility:public"]) @@ -108,6 +108,55 @@ cc_binary( deps = [":kitchen_sink_common"], ) +cc_binary( + name = "kitchen_sink_copy_to_ram_actual", + testonly = True, + srcs = ["kitchen_sink.c"], + tags = ["manual"], # Built via kitchen_sink_copy_to_ram + deps = [":kitchen_sink_common"], +) + +cc_binary( + name = "kitchen_sink_no_flash_actual", + testonly = True, + srcs = ["kitchen_sink.c"], + tags = ["manual"], # Built via kitchen_sink_no_flash + deps = [":kitchen_sink_common"], +) + +cc_binary( + name = "kitchen_sink_blocked_ram_actual", + testonly = True, + srcs = ["kitchen_sink.c"], + tags = ["manual"], # Built via kitchen_sink_blocked_ram + deps = [":kitchen_sink_common"], +) + +pico_set_binary_type( + name = "kitchen_sink_copy_to_ram", + testonly = True, + src = ":kitchen_sink_copy_to_ram_actual", + binary_type = "copy_to_ram", + target_compatible_with = compatible_with_rp2(), +) + +pico_set_binary_type( + name = "kitchen_sink_no_flash", + testonly = True, + src = ":kitchen_sink_no_flash_actual", + binary_type = "no_flash", + target_compatible_with = compatible_with_rp2(), +) + +pico_set_binary_type( + name = "kitchen_sink_blocked_ram", + testonly = True, + src = ":kitchen_sink_blocked_ram_actual", + binary_type = "blocked_ram", + target_compatible_with = ["//bazel/constraint:rp2040"], +) + + cc_binary( name = "kitchen_sink_lwip_poll_actual", testonly = True, diff --git a/tools/bazel_build.py b/tools/bazel_build.py index 24e4e4a47..391e53861 100755 --- a/tools/bazel_build.py +++ b/tools/bazel_build.py @@ -37,6 +37,9 @@ "//test/hardware_sync_spin_lock_test:hardware_sync_spin_lock_test", "//test/kitchen_sink:kitchen_sink", "//test/kitchen_sink:kitchen_sink_cpp", + "//test/kitchen_sink:kitchen_sink_copy_to_ram", + "//test/kitchen_sink:kitchen_sink_no_flash", + "//test/kitchen_sink:kitchen_sink_blocked_ram", "//test/kitchen_sink:kitchen_sink_lwip_poll", "//test/kitchen_sink:kitchen_sink_lwip_background", "//test/pico_divider_test:pico_divider_test", @@ -84,6 +87,8 @@ "//test/kitchen_sink:kitchen_sink_lwip_background", # Host only. "//test/pico_float_test:hazard3_test_gen", + # RP2040 only + "//test/kitchen_sink:kitchen_sink_blocked_ram", # TODO: RISC-V support. "//test/pico_float_test:pico_float_test_hazard3", ) @@ -122,6 +127,8 @@ "//test/kitchen_sink:kitchen_sink_lwip_background", # Host only. "//test/pico_float_test:hazard3_test_gen", + # RP2040 only + "//test/kitchen_sink:kitchen_sink_blocked_ram", # TODO: RISC-V support. "//test/pico_float_test:pico_float_test_hazard3", ) @@ -156,70 +163,8 @@ ( # Host only. "//test/pico_float_test:hazard3_test_gen", - # No RISC-V on RP2040. - "//test/pico_float_test:pico_float_test_hazard3", - ) - ), - }, - { - "name": "rp2040 no_flash", - "args": ("--platforms=//bazel/platform:rp2040", "--@pico-sdk//bazel/config:PICO_DEFAULT_BINARY_TYPE=no_flash"), - "extra_targets": (), - "exclusions": frozenset( - ( - "//test/kitchen_sink:kitchen_sink_lwip_poll", - "//test/kitchen_sink:kitchen_sink_lwip_background", - # Host only. - "//test/pico_float_test:hazard3_test_gen", - # No RISC-V on RP2040. - "//test/pico_float_test:pico_float_test_hazard3", - # hardware_sha256 doesn't appear to work on RP2040. - "//test/pico_sha256_test:pico_sha256_test", - ) - ), - }, - { - "name": "rp2350 no_flash", - "args": ("--platforms=//bazel/platform:rp2350", "--@pico-sdk//bazel/config:PICO_DEFAULT_BINARY_TYPE=no_flash"), - "extra_targets": (), - "exclusions": frozenset( - ( - "//test/kitchen_sink:kitchen_sink_lwip_poll", - "//test/kitchen_sink:kitchen_sink_lwip_background", - # Host only. - "//test/pico_float_test:hazard3_test_gen", - # TODO: RISC-V support. - "//test/pico_float_test:pico_float_test_hazard3", - ) - ), - }, - { - "name": "rp2040 copy_to_ram", - "args": ("--platforms=//bazel/platform:rp2040", "--@pico-sdk//bazel/config:PICO_DEFAULT_BINARY_TYPE=copy_to_ram"), - "extra_targets": (), - "exclusions": frozenset( - ( - "//test/kitchen_sink:kitchen_sink_lwip_poll", - "//test/kitchen_sink:kitchen_sink_lwip_background", - # Host only. - "//test/pico_float_test:hazard3_test_gen", - # No RISC-V on RP2040. - "//test/pico_float_test:pico_float_test_hazard3", - # hardware_sha256 doesn't appear to work on RP2040. - "//test/pico_sha256_test:pico_sha256_test", - ) - ), - }, - { - "name": "rp2350 copy_to_ram", - "args": ("--platforms=//bazel/platform:rp2350", "--@pico-sdk//bazel/config:PICO_DEFAULT_BINARY_TYPE=copy_to_ram"), - "extra_targets": (), - "exclusions": frozenset( - ( - "//test/kitchen_sink:kitchen_sink_lwip_poll", - "//test/kitchen_sink:kitchen_sink_lwip_background", - # Host only. - "//test/pico_float_test:hazard3_test_gen", + # RP2040 only + "//test/kitchen_sink:kitchen_sink_blocked_ram", # TODO: RISC-V support. "//test/pico_float_test:pico_float_test_hazard3", ) From df68b1e2c63ea99e3bb0b4e86cfffe77dd1d0724 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 25 Mar 2026 12:34:50 +0000 Subject: [PATCH 090/127] Refactor bazel functionality following review Now uses single linker_scripts function to allow both including and linking scripts Returns DefaultInfo with all necessary files Prepends ctx.label.workspace_root to link_include_dir Gets link_include_dir directly from the include_scripts passed in --- bazel/util/pico_linker_scripts.bzl | 49 +++++++------------ src/rp2040/pico_platform/BUILD.bazel | 38 +++++++------- .../pico_platform/script_include/BUILD.bazel | 22 +++------ src/rp2350/pico_platform/BUILD.bazel | 29 +++++------ .../pico_platform/script_include/BUILD.bazel | 15 +++--- .../script_include/BUILD.bazel | 19 ++----- 6 files changed, 66 insertions(+), 106 deletions(-) diff --git a/bazel/util/pico_linker_scripts.bzl b/bazel/util/pico_linker_scripts.bzl index f453b0761..563f96dd6 100644 --- a/bazel/util/pico_linker_scripts.bzl +++ b/bazel/util/pico_linker_scripts.bzl @@ -1,48 +1,37 @@ load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "use_cpp_toolchain") -def _include_linker_script_dir_impl(ctx): - link_include_dir = str(ctx.label.package) - depset_direct = ["-L" + str(link_include_dir)] - if len(ctx.files.use_scripts): - for script in ctx.files.use_scripts: - depset_direct.append("-T" + str(script.path)) +def _linker_scripts_impl(ctx): + link_flags = [] + for script in ctx.attr.include_scripts: + link_include_dir = script.label.package + if ctx.label.workspace_root: + link_include_dir = "/".join((ctx.label.workspace_root, link_include_dir)) + link_flag = "-L" + str(link_include_dir) + if not (link_flag in link_flags): + link_flags.append(link_flag) - linking_inputs = cc_common.create_linker_input( - owner = ctx.label, - user_link_flags = depset( - direct = depset_direct, - ), - ) - return [ - CcInfo(linking_context = cc_common.create_linking_context(linker_inputs = depset(direct = [linking_inputs]))), - ] - -include_linker_script_dir = rule( - implementation = _include_linker_script_dir_impl, - attrs = { - "use_scripts": attr.label_list(allow_files = [".ld"]), - }, - toolchains = use_cpp_toolchain(), - fragments = ["cpp"], -) + for script in ctx.files.link_scripts: + link_flags.append("-T" + str(script.path)) -def _use_linker_script_file_impl(ctx): - link_file = ctx.file.script.path + all_scripts = ctx.files.link_scripts + ctx.files.include_scripts linking_inputs = cc_common.create_linker_input( owner = ctx.label, user_link_flags = depset( - direct = ["-T" + str(link_file)], + direct = link_flags, ), + additional_inputs = depset(direct = all_scripts), ) return [ + DefaultInfo(files = depset(direct = all_scripts)), CcInfo(linking_context = cc_common.create_linking_context(linker_inputs = depset(direct = [linking_inputs]))), ] -use_linker_script_file = rule( - implementation = _use_linker_script_file_impl, +linker_scripts = rule( + implementation = _linker_scripts_impl, attrs = { - "script": attr.label(mandatory = True, allow_single_file = [".ld"]), + "link_scripts": attr.label_list(allow_files = [".ld"], doc = "List of scripts to explicitly link"), + "include_scripts": attr.label_list(allow_files = [".incl"], doc = "List of scripts to include"), }, toolchains = use_cpp_toolchain(), fragments = ["cpp"], diff --git a/src/rp2040/pico_platform/BUILD.bazel b/src/rp2040/pico_platform/BUILD.bazel index 8014f4a11..f32f300bb 100644 --- a/src/rp2040/pico_platform/BUILD.bazel +++ b/src/rp2040/pico_platform/BUILD.bazel @@ -55,7 +55,7 @@ cc_library( ], ) -load("//bazel/util:pico_linker_scripts.bzl", "use_linker_script_file") +load("//bazel/util:pico_linker_scripts.bzl", "linker_scripts") exports_files( [ @@ -66,24 +66,24 @@ exports_files( ], ) -use_linker_script_file( - name = "memmap_default_args", - script = "memmap_default.ld", +linker_scripts( + name = "memmap_default", + link_scripts = ["memmap_default.ld"], ) -use_linker_script_file( - name = "memmap_blocked_ram_args", - script = "memmap_blocked_ram.ld", +linker_scripts( + name = "memmap_blocked_ram", + link_scripts = ["memmap_blocked_ram.ld"], ) -use_linker_script_file( - name = "memmap_copy_to_ram_args", - script = "memmap_copy_to_ram.ld", +linker_scripts( + name = "memmap_copy_to_ram", + link_scripts = ["memmap_copy_to_ram.ld"], ) -use_linker_script_file( - name = "memmap_no_flash_args", - script = "memmap_no_flash.ld", +linker_scripts( + name = "memmap_no_flash", + link_scripts = ["memmap_no_flash.ld"], ) cc_library( @@ -97,8 +97,7 @@ cc_library( "//src/rp2040/pico_platform/script_include:rp2040_linker_scripts", "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", - "memmap_default.ld", - "memmap_default_args", + "memmap_default", ], ) @@ -114,8 +113,7 @@ cc_library( "//src/rp2040/pico_platform/script_include:rp2040_linker_scripts", "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", - "memmap_blocked_ram.ld", - "memmap_blocked_ram_args", + "memmap_blocked_ram", ], ) @@ -131,8 +129,7 @@ cc_library( "//src/rp2040/pico_platform/script_include:rp2040_linker_scripts", "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", - "memmap_copy_to_ram.ld", - "memmap_copy_to_ram_args", + "memmap_copy_to_ram", ], ) @@ -147,7 +144,6 @@ cc_library( "//src/rp2_common/pico_crt0:no_warn_rwx_flag", "//src/rp2040/pico_platform/script_include:rp2040_linker_scripts", "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", - "memmap_no_flash.ld", - "memmap_no_flash_args", + "memmap_no_flash", ], ) diff --git a/src/rp2040/pico_platform/script_include/BUILD.bazel b/src/rp2040/pico_platform/script_include/BUILD.bazel index afb7fb221..fd89a12a8 100644 --- a/src/rp2040/pico_platform/script_include/BUILD.bazel +++ b/src/rp2040/pico_platform/script_include/BUILD.bazel @@ -2,28 +2,18 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library") package(default_visibility = ["//visibility:public"]) -load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") +load("//bazel/util:pico_linker_scripts.bzl", "linker_scripts") -filegroup( - name = "rp2040_linker_script_incls", - srcs = glob([ - "*.incl", - ]), -) - -include_linker_script_dir( - name = "rp2040_linker_script_args", - use_scripts = ["default_locations.ld"], +linker_scripts( + name = "rp2040_linker_script_includes", + link_scripts = ["default_locations.ld"], + include_scripts = glob(["*.incl"]), ) cc_library( name = "rp2040_linker_scripts", target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ - "default_locations.ld", - "rp2040_linker_script_args", - ], - additional_linker_inputs = [ - "rp2040_linker_script_incls", + "rp2040_linker_script_includes", ], ) \ No newline at end of file diff --git a/src/rp2350/pico_platform/BUILD.bazel b/src/rp2350/pico_platform/BUILD.bazel index 13522b452..7a69d0004 100644 --- a/src/rp2350/pico_platform/BUILD.bazel +++ b/src/rp2350/pico_platform/BUILD.bazel @@ -55,7 +55,7 @@ cc_library( ], ) -load("//bazel/util:pico_linker_scripts.bzl", "use_linker_script_file") +load("//bazel/util:pico_linker_scripts.bzl", "linker_scripts") exports_files( [ @@ -65,19 +65,19 @@ exports_files( ], ) -use_linker_script_file( - name = "memmap_default_args", - script = "memmap_default.ld", +linker_scripts( + name = "memmap_default", + link_scripts = ["memmap_default.ld"], ) -use_linker_script_file( - name = "memmap_copy_to_ram_args", - script = "memmap_copy_to_ram.ld", +linker_scripts( + name = "memmap_copy_to_ram", + link_scripts = ["memmap_copy_to_ram.ld"], ) -use_linker_script_file( - name = "memmap_no_flash_args", - script = "memmap_no_flash.ld", +linker_scripts( + name = "memmap_no_flash", + link_scripts = ["memmap_no_flash.ld"], ) cc_library( @@ -91,8 +91,7 @@ cc_library( "//src/rp2350/pico_platform/script_include:rp2350_linker_scripts", "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", - "memmap_default.ld", - "memmap_default_args", + "memmap_default", ], ) @@ -108,8 +107,7 @@ cc_library( "//src/rp2350/pico_platform/script_include:rp2350_linker_scripts", "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", "//src/rp2_common/pico_standard_link:default_flash_region", - "memmap_copy_to_ram.ld", - "memmap_copy_to_ram_args", + "memmap_copy_to_ram", ], ) @@ -124,7 +122,6 @@ cc_library( "//src/rp2_common/pico_crt0:no_warn_rwx_flag", "//src/rp2350/pico_platform/script_include:rp2350_linker_scripts", "//src/rp2_common/pico_standard_link/script_include:rp2_linker_scripts", - "memmap_no_flash.ld", - "memmap_no_flash_args", + "memmap_no_flash", ], ) diff --git a/src/rp2350/pico_platform/script_include/BUILD.bazel b/src/rp2350/pico_platform/script_include/BUILD.bazel index 64e844b56..543824c4a 100644 --- a/src/rp2350/pico_platform/script_include/BUILD.bazel +++ b/src/rp2350/pico_platform/script_include/BUILD.bazel @@ -2,7 +2,7 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library") package(default_visibility = ["//visibility:public"]) -load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") +load("//bazel/util:pico_linker_scripts.bzl", "linker_scripts") filegroup( name = "rp2350_linker_script_incls", @@ -11,19 +11,16 @@ filegroup( ]), ) -include_linker_script_dir( - name = "rp2350_linker_script_args", - use_scripts = ["default_locations.ld"], +linker_scripts( + name = "rp2350_linker_script_includes", + link_scripts = ["default_locations.ld"], + include_scripts = glob(["*.incl"]), ) cc_library( name = "rp2350_linker_scripts", target_compatible_with = ["//bazel/constraint:rp2350"], deps = [ - "default_locations.ld", - "rp2350_linker_script_args", - ], - additional_linker_inputs = [ - "rp2350_linker_script_incls", + "rp2350_linker_script_includes", ], ) \ No newline at end of file diff --git a/src/rp2_common/pico_standard_link/script_include/BUILD.bazel b/src/rp2_common/pico_standard_link/script_include/BUILD.bazel index 4afcce951..0cc69e0d6 100644 --- a/src/rp2_common/pico_standard_link/script_include/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/script_include/BUILD.bazel @@ -1,27 +1,18 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library") load("//bazel:defs.bzl", "compatible_with_rp2") -load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") +load("//bazel/util:pico_linker_scripts.bzl", "linker_scripts") package(default_visibility = ["//visibility:public"]) -filegroup( - name = "rp2_linker_script_incls", - srcs = glob([ - "*.incl", - ]), -) - -include_linker_script_dir( - name = "rp2_linker_script_args", +linker_scripts( + name = "rp2_linker_script_includes", + include_scripts = glob(["*.incl"]), ) cc_library( name = "rp2_linker_scripts", target_compatible_with = compatible_with_rp2(), deps = [ - "rp2_linker_script_args", + "rp2_linker_script_includes", ], - additional_linker_inputs = [ - "rp2_linker_script_incls", - ] ) \ No newline at end of file From 41fd36e42fbfe8d6a8a854e17c76dcbc060bf263 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 25 Mar 2026 12:36:55 +0000 Subject: [PATCH 091/127] Add kitchen_sink_ram_section and kitchen_sink_simple_overlay tests to bazel Also adds pico_set_linker_script transition to set linker script for individual binaries --- bazel/util/transition.bzl | 15 +++++ test/kitchen_sink/BUILD.bazel | 56 ++++++++++++++++++- test/kitchen_sink/kitchen_sink.c | 1 + .../BUILD.bazel | 8 +++ .../BUILD.bazel | 8 +++ .../BUILD.bazel | 8 +++ tools/bazel_build.py | 6 ++ 7 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 test/kitchen_sink/kitchen_sink_extra_end_scripts/BUILD.bazel create mode 100644 test/kitchen_sink/kitchen_sink_ram_section_scripts/BUILD.bazel create mode 100644 test/kitchen_sink/kitchen_sink_simple_overlay_scripts/BUILD.bazel diff --git a/bazel/util/transition.bzl b/bazel/util/transition.bzl index 9abe9749b..654a3e413 100644 --- a/bazel/util/transition.bzl +++ b/bazel/util/transition.bzl @@ -182,3 +182,18 @@ pico_set_binary_type = declare_transtion( "@pico-sdk//bazel/config:PICO_DEFAULT_BINARY_TYPE": "binary_type", }, ) + +# This transition sets the binary type +pico_set_linker_script = declare_transtion( + attrs = { + "linker_script": attr.string(), + # This could be shared, but we don't in order to make it clearer that + # a transition is in use. + "_allowlist_function_transition": attr.label( + default = "@bazel_tools//tools/allowlists/function_transition_allowlist", + ), + }, + flag_overrides = { + "@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT": "linker_script", + }, +) diff --git a/test/kitchen_sink/BUILD.bazel b/test/kitchen_sink/BUILD.bazel index 325dc0d86..e4e9df23b 100644 --- a/test/kitchen_sink/BUILD.bazel +++ b/test/kitchen_sink/BUILD.bazel @@ -1,7 +1,7 @@ load("@rules_cc//cc:cc_binary.bzl", "cc_binary") load("@rules_cc//cc:cc_library.bzl", "cc_library") -load("//bazel:defs.bzl", "compatible_with_rp2", "pico_generate_pio_header") -load("//bazel/util:transition.bzl", "kitchen_sink_test_binary", "pico_set_binary_type") +load("//bazel:defs.bzl", "compatible_with_rp2", "pico_generate_pio_header", "incompatible_with_config") +load("//bazel/util:transition.bzl", "kitchen_sink_test_binary", "pico_set_binary_type", "pico_set_linker_script") package(default_visibility = ["//visibility:public"]) @@ -156,6 +156,58 @@ pico_set_binary_type( target_compatible_with = ["//bazel/constraint:rp2040"], ) +cc_binary( + name = "kitchen_sink_ram_section_actual", + testonly = True, + srcs = ["kitchen_sink.c"], + tags = ["manual"], # Built via kitchen_sink_ram_section + deps = [":kitchen_sink_common"], + defines = ["EXTRA_DATA_SECTION=1"] +) + +cc_library( + name = "kitchen_sink_ram_section_linker_script", + deps = [ + "//test/kitchen_sink/kitchen_sink_ram_section_scripts:kitchen_sink_ram_section_scripts", + "//test/kitchen_sink/kitchen_sink_extra_end_scripts:kitchen_sink_extra_end_scripts", + "//src/rp2_common/pico_standard_link:default_linker_script", + ], +) + +pico_set_linker_script( + name = "kitchen_sink_ram_section", + testonly = True, + src = ":kitchen_sink_ram_section_actual", + linker_script = "//test/kitchen_sink:kitchen_sink_ram_section_linker_script", + target_compatible_with = compatible_with_rp2(), +) + +cc_binary( + name = "kitchen_sink_simple_overlay_actual", + testonly = True, + srcs = ["kitchen_sink.c"], + tags = ["manual"], # Built via kitchen_sink_simple_overlay + deps = [":kitchen_sink_common"], + defines = ["EXTRA_DATA_SECTION=2"] +) + +cc_library( + name = "kitchen_sink_simple_overlay_linker_script", + deps = [ + "//test/kitchen_sink/kitchen_sink_simple_overlay_scripts:kitchen_sink_simple_overlay_scripts", + "//test/kitchen_sink/kitchen_sink_extra_end_scripts:kitchen_sink_extra_end_scripts", + "//src/rp2_common/pico_standard_link:default_linker_script", + ], +) + +pico_set_linker_script( + name = "kitchen_sink_simple_overlay", + testonly = True, + src = ":kitchen_sink_simple_overlay_actual", + linker_script = "//test/kitchen_sink:kitchen_sink_simple_overlay_linker_script", + # Clang does not support overlay sections + target_compatible_with = compatible_with_rp2() + incompatible_with_config("//bazel/constraint:pico_toolchain_clang_enabled"), +) cc_binary( name = "kitchen_sink_lwip_poll_actual", diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index ba5fe7613..0b712a220 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -5,6 +5,7 @@ */ #include +#include #ifndef KITCHEN_SINK_INCLUDE_HEADER // provided for backwards compatibility for non CMake build systems - just includes enough to compile diff --git a/test/kitchen_sink/kitchen_sink_extra_end_scripts/BUILD.bazel b/test/kitchen_sink/kitchen_sink_extra_end_scripts/BUILD.bazel new file mode 100644 index 000000000..9c83da183 --- /dev/null +++ b/test/kitchen_sink/kitchen_sink_extra_end_scripts/BUILD.bazel @@ -0,0 +1,8 @@ +load("//bazel/util:pico_linker_scripts.bzl", "linker_scripts") + +package(default_visibility = ["//test/kitchen_sink:__pkg__"]) + +linker_scripts( + name = "kitchen_sink_extra_end_scripts", + include_scripts = glob(["*.incl"]), +) diff --git a/test/kitchen_sink/kitchen_sink_ram_section_scripts/BUILD.bazel b/test/kitchen_sink/kitchen_sink_ram_section_scripts/BUILD.bazel new file mode 100644 index 000000000..584890b69 --- /dev/null +++ b/test/kitchen_sink/kitchen_sink_ram_section_scripts/BUILD.bazel @@ -0,0 +1,8 @@ +load("//bazel/util:pico_linker_scripts.bzl", "linker_scripts") + +package(default_visibility = ["//test/kitchen_sink:__pkg__"]) + +linker_scripts( + name = "kitchen_sink_ram_section_scripts", + include_scripts = glob(["*.incl"]), +) diff --git a/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/BUILD.bazel b/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/BUILD.bazel new file mode 100644 index 000000000..6bb2e84dd --- /dev/null +++ b/test/kitchen_sink/kitchen_sink_simple_overlay_scripts/BUILD.bazel @@ -0,0 +1,8 @@ +load("//bazel/util:pico_linker_scripts.bzl", "linker_scripts") + +package(default_visibility = ["//test/kitchen_sink:__pkg__"]) + +linker_scripts( + name = "kitchen_sink_simple_overlay_scripts", + include_scripts = glob(["*.incl"]), +) diff --git a/tools/bazel_build.py b/tools/bazel_build.py index 391e53861..e2177b44f 100755 --- a/tools/bazel_build.py +++ b/tools/bazel_build.py @@ -42,6 +42,8 @@ "//test/kitchen_sink:kitchen_sink_blocked_ram", "//test/kitchen_sink:kitchen_sink_lwip_poll", "//test/kitchen_sink:kitchen_sink_lwip_background", + "//test/kitchen_sink:kitchen_sink_ram_section", + "//test/kitchen_sink:kitchen_sink_simple_overlay", "//test/pico_divider_test:pico_divider_test", "//test/pico_divider_test:pico_divider_nesting_test", "//test/pico_float_test:pico_double_test", @@ -111,6 +113,8 @@ "//test/pico_float_test:pico_float_test_hazard3", # hardware_sha256 doesn't appear to work on RP2040. "//test/pico_sha256_test:pico_sha256_test", + # not supported by clang + "//test/kitchen_sink:kitchen_sink_simple_overlay", ) ), }, @@ -131,6 +135,8 @@ "//test/kitchen_sink:kitchen_sink_blocked_ram", # TODO: RISC-V support. "//test/pico_float_test:pico_float_test_hazard3", + # not supported by clang + "//test/kitchen_sink:kitchen_sink_simple_overlay", ) ), }, From ea9b1143b29a83b1ad5a4ed93319d25ed881fb5c Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 25 Mar 2026 17:04:19 +0000 Subject: [PATCH 092/127] Some tidyups Remove whitespace, and rename memory_aliases_default to memory_aliases_flash, as it applies to copy_to_ram too --- bazel/util/pico_linker_scripts.bzl | 2 +- .../pico_standard_link/script_include/memmap_copy_to_ram.incl | 2 +- .../pico_standard_link/script_include/memmap_default.incl | 2 +- .../{memory_aliases_default.incl => memory_aliases_flash.incl} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename src/rp2_common/pico_standard_link/script_include/{memory_aliases_default.incl => memory_aliases_flash.incl} (100%) diff --git a/bazel/util/pico_linker_scripts.bzl b/bazel/util/pico_linker_scripts.bzl index 563f96dd6..8bdc18e9c 100644 --- a/bazel/util/pico_linker_scripts.bzl +++ b/bazel/util/pico_linker_scripts.bzl @@ -4,7 +4,7 @@ def _linker_scripts_impl(ctx): link_flags = [] for script in ctx.attr.include_scripts: link_include_dir = script.label.package - if ctx.label.workspace_root: + if ctx.label.workspace_root: link_include_dir = "/".join((ctx.label.workspace_root, link_include_dir)) link_flag = "-L" + str(link_include_dir) if not (link_flag in link_flags): diff --git a/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl b/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl index d16c16ed6..f54a3e833 100644 --- a/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl +++ b/src/rp2_common/pico_standard_link/script_include/memmap_copy_to_ram.incl @@ -9,7 +9,7 @@ INCLUDE "memory_generated.incl" INCLUDE "memory_extra.incl" /* Include aliases for storage memory regions */ -INCLUDE "memory_aliases_default.incl" +INCLUDE "memory_aliases_flash.incl" /* Define entry point symbol */ ENTRY(_entry_point) diff --git a/src/rp2_common/pico_standard_link/script_include/memmap_default.incl b/src/rp2_common/pico_standard_link/script_include/memmap_default.incl index 1367ee18e..4f3233509 100644 --- a/src/rp2_common/pico_standard_link/script_include/memmap_default.incl +++ b/src/rp2_common/pico_standard_link/script_include/memmap_default.incl @@ -9,7 +9,7 @@ INCLUDE "memory_generated.incl" INCLUDE "memory_extra.incl" /* Include aliases for storage memory regions */ -INCLUDE "memory_aliases_default.incl" +INCLUDE "memory_aliases_flash.incl" /* Define entry point symbol */ ENTRY(_entry_point) diff --git a/src/rp2_common/pico_standard_link/script_include/memory_aliases_default.incl b/src/rp2_common/pico_standard_link/script_include/memory_aliases_flash.incl similarity index 100% rename from src/rp2_common/pico_standard_link/script_include/memory_aliases_default.incl rename to src/rp2_common/pico_standard_link/script_include/memory_aliases_flash.incl From 09e2857e00567f8abeeb74ef646182668c6eb05c Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 26 Mar 2026 12:41:59 +0000 Subject: [PATCH 093/127] Fixup merge Commits on this branch are very messy due to being on top of changing linker scripts, so definitely need squashing before final merge --- .../pico_crt0/rp2040/scripts/BUILD.bazel | 31 ----- .../rp2040/scripts/default_locations.ld | 8 -- .../scripts/section_copy_to_ram_text.ld | 101 --------------- .../rp2040/scripts/section_default_text.ld | 109 ---------------- .../rp2040/scripts/section_no_flash_text.ld | 71 ---------- .../rp2040/scripts/section_platform_end.ld | 50 -------- .../pico_crt0/rp2350/scripts/BUILD.bazel | 31 ----- .../rp2350/scripts/default_locations.ld | 8 -- .../scripts/section_copy_to_ram_text.ld | 117 ----------------- .../rp2350/scripts/section_default_text.ld | 121 ------------------ .../rp2350/scripts/section_no_flash_text.ld | 73 ----------- .../rp2350/scripts/section_platform_end.ld | 7 - .../section_persistent_data.incl | 9 ++ .../sections_copy_to_ram_data.incl | 1 + .../script_include/sections_default_data.incl | 1 + .../sections_no_flash_data.incl | 1 + .../pico_standard_link/scripts/BUILD.bazel | 61 --------- .../scripts/memory_aliases_default.ld | 3 - .../scripts/memory_aliases_no_flash.ld | 3 - .../scripts/memory_flash.ld | 4 - .../pico_standard_link/scripts/memory_ram.ld | 4 - .../scripts/memory_scratch.ld | 5 - .../scripts/memory_xip_ram.ld | 4 - .../scripts/rp2_common/memmap_copy_to_ram.ld | 16 --- .../scripts/rp2_common/memmap_default.ld | 16 --- .../scripts/rp2_common/memmap_no_flash.ld | 15 --- .../scripts/section_copy_to_ram_data.ld | 90 ------------- .../scripts/section_default_data.ld | 79 ------------ .../pico_standard_link/scripts/section_end.ld | 49 ------- .../scripts/section_flash_end.ld | 7 - .../scripts/section_heap.ld | 12 -- .../scripts/section_no_flash_data.ld | 89 ------------- .../scripts/section_scratch.ld | 37 ------ .../scripts/sections_copy_to_ram.ld | 7 - .../scripts/sections_default.ld | 7 - .../scripts/sections_no_flash.ld | 6 - .../scripts/set_memory_locations.ld | 8 -- 37 files changed, 12 insertions(+), 1249 deletions(-) delete mode 100644 src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel delete mode 100644 src/rp2_common/pico_crt0/rp2040/scripts/default_locations.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/scripts/section_copy_to_ram_text.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/scripts/section_default_text.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/scripts/section_no_flash_text.ld delete mode 100644 src/rp2_common/pico_crt0/rp2040/scripts/section_platform_end.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel delete mode 100644 src/rp2_common/pico_crt0/rp2350/scripts/default_locations.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/scripts/section_copy_to_ram_text.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/scripts/section_default_text.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/scripts/section_no_flash_text.ld delete mode 100644 src/rp2_common/pico_crt0/rp2350/scripts/section_platform_end.ld create mode 100644 src/rp2_common/pico_standard_link/script_include/section_persistent_data.incl delete mode 100644 src/rp2_common/pico_standard_link/scripts/BUILD.bazel delete mode 100644 src/rp2_common/pico_standard_link/scripts/memory_aliases_default.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/memory_aliases_no_flash.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/memory_flash.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/memory_ram.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/memory_scratch.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/memory_xip_ram.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_data.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/section_default_data.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/section_end.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/section_flash_end.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/section_heap.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/section_no_flash_data.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/section_scratch.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/sections_default.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld delete mode 100644 src/rp2_common/pico_standard_link/scripts/set_memory_locations.ld diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel b/src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel deleted file mode 100644 index 492842565..000000000 --- a/src/rp2_common/pico_crt0/rp2040/scripts/BUILD.bazel +++ /dev/null @@ -1,31 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") - -exports_files( - [ - "default_locations.ld", - "section_copy_to_ram_text.ld", - "section_default_text.ld", - "section_no_flash_text.ld", - "section_platform_end.ld", - ] -) - -include_linker_script_dir( - name = "rp2040_linker_script_args", - use_scripts = ["default_locations.ld"], -) - -cc_library( - name = "rp2040_linker_scripts", - target_compatible_with = ["//bazel/constraint:rp2040"], - deps = [ - "default_locations.ld", - "section_copy_to_ram_text.ld", - "section_default_text.ld", - "section_no_flash_text.ld", - "section_platform_end.ld", - "rp2040_linker_script_args", - ], -) \ No newline at end of file diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/default_locations.ld b/src/rp2_common/pico_crt0/rp2040/scripts/default_locations.ld deleted file mode 100644 index 03144ea07..000000000 --- a/src/rp2_common/pico_crt0/rp2040/scripts/default_locations.ld +++ /dev/null @@ -1,8 +0,0 @@ -RAM_ORIGIN_DEFAULT = 0x20000000; -RAM_LENGTH_DEFAULT = 256k; -SCRATCH_X_ORIGIN_DEFAULT = 0x20040000; -SCRATCH_X_LENGTH_DEFAULT = 4k; -SCRATCH_Y_ORIGIN_DEFAULT = 0x20041000; -SCRATCH_Y_LENGTH_DEFAULT = 4k; -XIP_RAM_ORIGIN_DEFAULT = 0x15000000; -XIP_RAM_LENGTH_DEFAULT = 16k; diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/section_copy_to_ram_text.ld b/src/rp2_common/pico_crt0/rp2040/scripts/section_copy_to_ram_text.ld deleted file mode 100644 index 77a45941b..000000000 --- a/src/rp2_common/pico_crt0/rp2040/scripts/section_copy_to_ram_text.ld +++ /dev/null @@ -1,101 +0,0 @@ -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .flashtext : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - } - - .rodata : { - /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - /* Vector table goes first in RAM, to avoid large alignment hole */ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .text : { - __ram_text_start__ = .; - *(.init) - *(.text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - . = ALIGN(4); - __ram_text_end__ = .; - } > RAM AT> FLASH - __ram_text_source__ = LOADADDR(.text); - . = ALIGN(4); -} diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/section_default_text.ld b/src/rp2_common/pico_crt0/rp2040/scripts/section_default_text.ld deleted file mode 100644 index 7aa5c9399..000000000 --- a/src/rp2_common/pico_crt0/rp2040/scripts/section_default_text.ld +++ /dev/null @@ -1,109 +0,0 @@ -SECTIONS -{ - /* Second stage bootloader is prepended to the image. It must be 256 bytes big - and checksummed. It is usually built by the boot_stage2 target - in the Raspberry Pi Pico SDK - */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - "ERROR: Pico second stage bootloader must be 256 bytes in size") - - /* The second stage will always enter the image at the start of .text. - The debugger will use the ELF entry point, which is the _entry_point - symbol if present, otherwise defaults to start of .text. - This can be used to transfer control back to the bootrom on debugger - launches only, to perform proper flash setup. - */ - - .text : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - /* TODO revisit this now memset/memcpy/float in ROM */ - /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from - * FLASH ... we will include any thing excluded here in .data below by default */ - *(.init) - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.eh_frame*) - . = ALIGN(4); - } > FLASH - - .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); -} diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/section_no_flash_text.ld b/src/rp2_common/pico_crt0/rp2040/scripts/section_no_flash_text.ld deleted file mode 100644 index b4ad44ba7..000000000 --- a/src/rp2_common/pico_crt0/rp2040/scripts/section_no_flash_text.ld +++ /dev/null @@ -1,71 +0,0 @@ -SECTIONS -{ - /* Note in NO_FLASH builds the entry point for both the bootrom, and debugger - entry (ELF entry point), are *first* in the image, and the vector table - follows immediately afterward. This is because the bootrom enters RAM - binaries directly at their lowest address (preferring main RAM over XIP - cache-as-SRAM if both are used). - */ - - .text : { - __logical_binary_start = .; - __reset_start = .; - KEEP (*(.reset)) - __reset_end = .; - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - . = ALIGN(256); - KEEP (*(.vectors)) - *(.text*) - . = ALIGN(4); - *(.init) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - } > RAM - - .rodata : { - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > RAM - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > RAM - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > RAM - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > RAM - __binary_info_end = .; - . = ALIGN(4); -} diff --git a/src/rp2_common/pico_crt0/rp2040/scripts/section_platform_end.ld b/src/rp2_common/pico_crt0/rp2040/scripts/section_platform_end.ld deleted file mode 100644 index 2d0165aa4..000000000 --- a/src/rp2_common/pico_crt0/rp2040/scripts/section_platform_end.ld +++ /dev/null @@ -1,50 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel b/src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel deleted file mode 100644 index 9c9aa7329..000000000 --- a/src/rp2_common/pico_crt0/rp2350/scripts/BUILD.bazel +++ /dev/null @@ -1,31 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") - -exports_files( - [ - "default_locations.ld", - "section_copy_to_ram_text.ld", - "section_default_text.ld", - "section_no_flash_text.ld", - "section_platform_end.ld", - ] -) - -include_linker_script_dir( - name = "rp2350_linker_script_args", - use_scripts = ["default_locations.ld"], -) - -cc_library( - name = "rp2350_linker_scripts", - target_compatible_with = ["//bazel/constraint:rp2350"], - deps = [ - "default_locations.ld", - "section_copy_to_ram_text.ld", - "section_default_text.ld", - "section_no_flash_text.ld", - "section_platform_end.ld", - "rp2350_linker_script_args", - ], -) \ No newline at end of file diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/default_locations.ld b/src/rp2_common/pico_crt0/rp2350/scripts/default_locations.ld deleted file mode 100644 index 15ddc7374..000000000 --- a/src/rp2_common/pico_crt0/rp2350/scripts/default_locations.ld +++ /dev/null @@ -1,8 +0,0 @@ -RAM_ORIGIN_DEFAULT = 0x20000000; -RAM_LENGTH_DEFAULT = 512k; -SCRATCH_X_ORIGIN_DEFAULT = 0x20080000; -SCRATCH_X_LENGTH_DEFAULT = 4k; -SCRATCH_Y_ORIGIN_DEFAULT = 0x20081000; -SCRATCH_Y_LENGTH_DEFAULT = 4k; -XIP_RAM_ORIGIN_DEFAULT = 0x13FFC000; -XIP_RAM_LENGTH_DEFAULT = 16k; diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/section_copy_to_ram_text.ld b/src/rp2_common/pico_crt0/rp2350/scripts/section_copy_to_ram_text.ld deleted file mode 100644 index d35f7209e..000000000 --- a/src/rp2_common/pico_crt0/rp2350/scripts/section_copy_to_ram_text.ld +++ /dev/null @@ -1,117 +0,0 @@ -SECTIONS -{ - /* On Arm, the bootrom expects a VT at the start of the - image by default; on RISC-V, the default is to enter the image at its - lowest address, so an IMAGE_DEF item is required to specify the - nondefault entry point. */ - - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - /* The bootrom will enter the image at the point indicated in your - IMAGE_DEF, which is usually the reset handler of your vector table. - - The debugger will use the ELF entry point, which is the _entry_point - symbol, and in our case is *different from the bootrom's entry point.* - This is used to go back through the bootrom on debugger launches only, - to perform the same initial flash setup that would be performed on a - cold boot. - */ - - .flashtext : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - . = ALIGN(4); - } > FLASH - - /* Note the boot2 section is optional, and should be discarded if there is - no reference to it *inside* the binary, as it is not called by the - bootrom. (The bootrom performs a simple best-effort XIP setup and - leaves it to the binary to do anything more sophisticated.) However - there is still a size limit of 256 bytes, to ensure the boot2 can be - stored in boot RAM. - - Really this is a "XIP setup function" -- the name boot2 is historic and - refers to its dual-purpose on RP2040, where it also handled vectoring - from the bootrom into the user image. - */ - - .boot2 : { - __boot2_start__ = .; - *(.boot2) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ <= 256, - "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") - - .rodata : { - /* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */ - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); - - /* Vector table goes first in RAM, to avoid large alignment hole */ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .text : { - __ram_text_start__ = .; - *(.init) - *(.text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - . = ALIGN(4); - __ram_text_end__ = .; - } > RAM AT> FLASH - __ram_text_source__ = LOADADDR(.text); - . = ALIGN(4); -} diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/section_default_text.ld b/src/rp2_common/pico_crt0/rp2350/scripts/section_default_text.ld deleted file mode 100644 index fdd963321..000000000 --- a/src/rp2_common/pico_crt0/rp2350/scripts/section_default_text.ld +++ /dev/null @@ -1,121 +0,0 @@ -SECTIONS -{ - .flash_begin : { - __flash_binary_start = .; - } > FLASH - - /* The bootrom will enter the image at the point indicated in your - IMAGE_DEF, which is usually the reset handler of your vector table. - - The debugger will use the ELF entry point, which is the _entry_point - symbol, and in our case is *different from the bootrom's entry point.* - This is used to go back through the bootrom on debugger launches only, - to perform the same initial flash setup that would be performed on a - cold boot. - */ - - .text : { - __logical_binary_start = .; - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - KEEP (*(.reset)) - /* TODO revisit this now memset/memcpy/float in ROM */ - /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from - * FLASH ... we will include any thing excluded here in .data below by default */ - *(.init) - *libgcc.a:cmse_nonsecure_call.o - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.eh_frame*) - . = ALIGN(4); - } > FLASH - - /* Note the boot2 section is optional, and should be discarded if there is - no reference to it *inside* the binary, as it is not called by the - bootrom. (The bootrom performs a simple best-effort XIP setup and - leaves it to the binary to do anything more sophisticated.) However - there is still a size limit of 256 bytes, to ensure the boot2 can be - stored in boot RAM. - - Really this is a "XIP setup function" -- the name boot2 is historic and - refers to its dual-purpose on RP2040, where it also handled vectoring - from the bootrom into the user image. - */ - - .boot2 : { - __boot2_start__ = .; - *(.boot2) - __boot2_end__ = .; - } > FLASH - - ASSERT(__boot2_end__ - __boot2_start__ <= 256, - "ERROR: Pico second stage bootloader must be no more than 256 bytes in size") - - .rodata : { - *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) - *(.srodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > FLASH - __binary_info_end = .; - . = ALIGN(4); -} diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/section_no_flash_text.ld b/src/rp2_common/pico_crt0/rp2350/scripts/section_no_flash_text.ld deleted file mode 100644 index 833d8c42b..000000000 --- a/src/rp2_common/pico_crt0/rp2350/scripts/section_no_flash_text.ld +++ /dev/null @@ -1,73 +0,0 @@ -SECTIONS -{ - /* Note unlike RP2040, we start the image with a vector table even for - NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the - image by default; on RISC-V, the default is to enter the image at its - lowest address, so an IMAGE_DEF item is required to specify the - nondefault entry point. */ - - .text : { - __logical_binary_start = .; - /* Vectors require 512-byte alignment on v8-M when >48 IRQs are used, - so we would waste RAM if the vector table were not at the - start. */ - KEEP (*(.vectors)) - KEEP (*(.binary_info_header)) - __binary_info_header_end = .; - KEEP (*(.embedded_block)) - __embedded_block_end = .; - __reset_start = .; - KEEP (*(.reset)) - __reset_end = .; - *(.text*) - . = ALIGN(4); - *(.init) - *(.fini) - /* Pull all c'tors into .text */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - /* Followed by destructors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.eh_frame*) - } > RAM - - .rodata : { - . = ALIGN(4); - *(.rodata*) - *(.srodata*) - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) - . = ALIGN(4); - } > RAM - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > RAM - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > RAM - __exidx_end = .; - - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > RAM - __binary_info_end = .; - . = ALIGN(4); -} diff --git a/src/rp2_common/pico_crt0/rp2350/scripts/section_platform_end.ld b/src/rp2_common/pico_crt0/rp2350/scripts/section_platform_end.ld deleted file mode 100644 index 43cc19ecd..000000000 --- a/src/rp2_common/pico_crt0/rp2350/scripts/section_platform_end.ld +++ /dev/null @@ -1,7 +0,0 @@ -SECTIONS -{ - ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") - ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") - - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_standard_link/script_include/section_persistent_data.incl b/src/rp2_common/pico_standard_link/script_include/section_persistent_data.incl new file mode 100644 index 000000000..33b449df7 --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_persistent_data.incl @@ -0,0 +1,9 @@ +SECTIONS +{ + .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { + __persistent_data_start__ = .; + *(.persistent_data*) + . = ALIGN(4); + } + PROVIDE(__persistent_data_end__ = .); +} \ No newline at end of file diff --git a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl index ff90005e1..c8940112f 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl @@ -2,3 +2,4 @@ INCLUDE "section_copy_to_ram_data.incl" INCLUDE "section_bss.incl" +INCLUDE "section_persistent_data.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl b/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl index cfa77cb2f..6af190cc6 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl @@ -4,3 +4,4 @@ INCLUDE "section_ram_vector_table.incl" INCLUDE "section_uninitialized_data.incl" INCLUDE "section_default_data.incl" INCLUDE "section_bss.incl" +INCLUDE "section_persistent_data.incl" diff --git a/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl b/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl index 6a55a1481..037cd3f64 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl @@ -3,3 +3,4 @@ INCLUDE "section_no_flash_data.incl" INCLUDE "section_uninitialized_data.incl" INCLUDE "section_bss.incl" +INCLUDE "section_persistent_data.incl" diff --git a/src/rp2_common/pico_standard_link/scripts/BUILD.bazel b/src/rp2_common/pico_standard_link/scripts/BUILD.bazel deleted file mode 100644 index ac6239a11..000000000 --- a/src/rp2_common/pico_standard_link/scripts/BUILD.bazel +++ /dev/null @@ -1,61 +0,0 @@ -load("//bazel:defs.bzl", "compatible_with_rp2") -load("//bazel/util:pico_linker_scripts.bzl", "include_linker_script_dir") - -package(default_visibility = ["//visibility:public"]) - -exports_files( - [ - "memory_aliases_default.ld", - "memory_aliases_no_flash.ld", - "memory_flash.ld", - "memory_ram.ld", - "memory_scratch.ld", - "memory_xip_ram.ld", - "section_copy_to_ram_data.ld", - "section_default_data.ld", - "section_end.ld", - "section_flash_end.ld", - "section_heap.ld", - "section_no_flash_data.ld", - "sections_copy_to_ram.ld", - "section_scratch.ld", - "sections_default.ld", - "sections_no_flash.ld", - "set_memory_locations.ld", - "rp2_common/memmap_default.ld", - "rp2_common/memmap_no_flash.ld", - "rp2_common/memmap_copy_to_ram.ld", - ] -) - -include_linker_script_dir( - name = "rp2_linker_script_args", -) - -cc_library( - name = "rp2_linker_scripts", - target_compatible_with = compatible_with_rp2(), - deps = [ - "rp2_linker_script_args", - "memory_aliases_default.ld", - "memory_aliases_no_flash.ld", - "memory_flash.ld", - "memory_ram.ld", - "memory_scratch.ld", - "memory_xip_ram.ld", - "section_copy_to_ram_data.ld", - "section_default_data.ld", - "section_end.ld", - "section_flash_end.ld", - "section_heap.ld", - "section_no_flash_data.ld", - "sections_copy_to_ram.ld", - "section_scratch.ld", - "sections_default.ld", - "sections_no_flash.ld", - "set_memory_locations.ld", - "rp2_common/memmap_default.ld", - "rp2_common/memmap_no_flash.ld", - "rp2_common/memmap_copy_to_ram.ld", - ], -) \ No newline at end of file diff --git a/src/rp2_common/pico_standard_link/scripts/memory_aliases_default.ld b/src/rp2_common/pico_standard_link/scripts/memory_aliases_default.ld deleted file mode 100644 index 7c56254bd..000000000 --- a/src/rp2_common/pico_standard_link/scripts/memory_aliases_default.ld +++ /dev/null @@ -1,3 +0,0 @@ -REGION_ALIAS("RAM_STORE", FLASH); -REGION_ALIAS("SCRATCH_X_STORE", FLASH); -REGION_ALIAS("SCRATCH_Y_STORE", FLASH); diff --git a/src/rp2_common/pico_standard_link/scripts/memory_aliases_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/memory_aliases_no_flash.ld deleted file mode 100644 index 063b5b6fc..000000000 --- a/src/rp2_common/pico_standard_link/scripts/memory_aliases_no_flash.ld +++ /dev/null @@ -1,3 +0,0 @@ -REGION_ALIAS("RAM_STORE", RAM); -REGION_ALIAS("SCRATCH_X_STORE", SCRATCH_X); -REGION_ALIAS("SCRATCH_Y_STORE", SCRATCH_Y); diff --git a/src/rp2_common/pico_standard_link/scripts/memory_flash.ld b/src/rp2_common/pico_standard_link/scripts/memory_flash.ld deleted file mode 100644 index 669fe00e3..000000000 --- a/src/rp2_common/pico_standard_link/scripts/memory_flash.ld +++ /dev/null @@ -1,4 +0,0 @@ -MEMORY -{ - INCLUDE "pico_flash_region.ld" -} diff --git a/src/rp2_common/pico_standard_link/scripts/memory_ram.ld b/src/rp2_common/pico_standard_link/scripts/memory_ram.ld deleted file mode 100644 index 2b8a88a06..000000000 --- a/src/rp2_common/pico_standard_link/scripts/memory_ram.ld +++ /dev/null @@ -1,4 +0,0 @@ -MEMORY -{ - RAM(rwx) : ORIGIN = RAM_ORIGIN, LENGTH = RAM_LENGTH -} diff --git a/src/rp2_common/pico_standard_link/scripts/memory_scratch.ld b/src/rp2_common/pico_standard_link/scripts/memory_scratch.ld deleted file mode 100644 index 7ba5d2172..000000000 --- a/src/rp2_common/pico_standard_link/scripts/memory_scratch.ld +++ /dev/null @@ -1,5 +0,0 @@ -MEMORY -{ - SCRATCH_X(rwx) : ORIGIN = SCRATCH_X_ORIGIN, LENGTH = SCRATCH_X_LENGTH - SCRATCH_Y(rwx) : ORIGIN = SCRATCH_Y_ORIGIN, LENGTH = SCRATCH_Y_LENGTH -} diff --git a/src/rp2_common/pico_standard_link/scripts/memory_xip_ram.ld b/src/rp2_common/pico_standard_link/scripts/memory_xip_ram.ld deleted file mode 100644 index 636e90137..000000000 --- a/src/rp2_common/pico_standard_link/scripts/memory_xip_ram.ld +++ /dev/null @@ -1,4 +0,0 @@ -MEMORY -{ - XIP_RAM(rwx) : ORIGIN = XIP_RAM_ORIGIN, LENGTH = XIP_RAM_LENGTH -} diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld deleted file mode 100644 index eb2c5ffd9..000000000 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_copy_to_ram.ld +++ /dev/null @@ -1,16 +0,0 @@ -/* Include platform memory locations */ -INCLUDE "set_memory_locations.ld" - -/* Include memory regions used */ -INCLUDE "memory_flash.ld" -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -/* Include aliases for storage memory regions */ -INCLUDE "memory_aliases_default.ld" - -/* Define entry point symbol */ -ENTRY(_entry_point) - -/* Include default sections */ -INCLUDE "sections_copy_to_ram.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld deleted file mode 100644 index 04acbefbb..000000000 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_default.ld +++ /dev/null @@ -1,16 +0,0 @@ -/* Include platform memory locations */ -INCLUDE "set_memory_locations.ld" - -/* Include memory regions used */ -INCLUDE "memory_flash.ld" -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -/* Include aliases for storage memory regions */ -INCLUDE "memory_aliases_default.ld" - -/* Define entry point symbol */ -ENTRY(_entry_point) - -/* Include default sections */ -INCLUDE "sections_default.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld deleted file mode 100644 index 958915a71..000000000 --- a/src/rp2_common/pico_standard_link/scripts/rp2_common/memmap_no_flash.ld +++ /dev/null @@ -1,15 +0,0 @@ -/* Include platform memory locations */ -INCLUDE "set_memory_locations.ld" - -/* Include memory regions used */ -INCLUDE "memory_ram.ld" -INCLUDE "memory_scratch.ld" - -/* Include aliases for no_flash storage memory regions (alias to themselves) */ -INCLUDE "memory_aliases_no_flash.ld" - -/* Define entry point symbol */ -ENTRY(_entry_point) - -/* Include no_flash sections */ -INCLUDE "sections_no_flash.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_data.ld b/src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_data.ld deleted file mode 100644 index a05a00334..000000000 --- a/src/rp2_common/pico_standard_link/scripts/section_copy_to_ram_data.ld +++ /dev/null @@ -1,90 +0,0 @@ -SECTIONS -{ - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - . = ALIGN(4); - *(.rodata*) - *(.srodata*) - . = ALIGN(4); - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { - __persistent_data_start__ = .; - *(.persistent_data*) - . = ALIGN(4); - } - PROVIDE(__persistent_data_end__ = .); -} diff --git a/src/rp2_common/pico_standard_link/scripts/section_default_data.ld b/src/rp2_common/pico_standard_link/scripts/section_default_data.ld deleted file mode 100644 index ca2f5d7de..000000000 --- a/src/rp2_common/pico_standard_link/scripts/section_default_data.ld +++ /dev/null @@ -1,79 +0,0 @@ -SECTIONS -{ - .ram_vector_table (NOLOAD): { - *(.ram_vector_table) - } > RAM - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ - *(.text*) - . = ALIGN(4); - *(.rodata*) - . = ALIGN(4); - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM AT> FLASH - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM AT> FLASH - PROVIDE(__data_end__ = .); - - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { - __persistent_data_start__ = .; - *(.persistent_data*) - . = ALIGN(4); - } - PROVIDE(__persistent_data_end__ = .); -} diff --git a/src/rp2_common/pico_standard_link/scripts/section_end.ld b/src/rp2_common/pico_standard_link/scripts/section_end.ld deleted file mode 100644 index 53d328174..000000000 --- a/src/rp2_common/pico_standard_link/scripts/section_end.ld +++ /dev/null @@ -1,49 +0,0 @@ -/* Based on GCC ARM embedded samples. - Defines the following symbols for use by code: - __exidx_start - __exidx_end - __etext - __data_start__ - __preinit_array_start - __preinit_array_end - __init_array_start - __init_array_end - __fini_array_start - __fini_array_end - __data_end__ - __bss_start__ - __bss_end__ - __end__ - end - __HeapLimit - __StackLimit - __StackTop - __stack (== StackTop) -*/ - -SECTIONS -{ - /* stack limit is poorly named, but historically is maximum heap ptr */ - __StackLimit = ORIGIN(RAM) + LENGTH(RAM); - __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); - __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); - __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); - __StackBottom = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - /* picolibc and LLVM */ - PROVIDE (__heap_start = __end__); - PROVIDE (__heap_end = __HeapLimit); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - - /* llvm-libc */ - PROVIDE (_end = __end__); - PROVIDE (__llvm_libc_heap_limit = __HeapLimit); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") - - /* todo assert on extra code */ -} diff --git a/src/rp2_common/pico_standard_link/scripts/section_flash_end.ld b/src/rp2_common/pico_standard_link/scripts/section_flash_end.ld deleted file mode 100644 index 8591406ff..000000000 --- a/src/rp2_common/pico_standard_link/scripts/section_flash_end.ld +++ /dev/null @@ -1,7 +0,0 @@ -SECTIONS -{ - .flash_end : { - KEEP(*(.embedded_end_block*)) - PROVIDE(__flash_binary_end = .); - } > FLASH =0xaa -} diff --git a/src/rp2_common/pico_standard_link/scripts/section_heap.ld b/src/rp2_common/pico_standard_link/scripts/section_heap.ld deleted file mode 100644 index 1cc9e0de1..000000000 --- a/src/rp2_common/pico_standard_link/scripts/section_heap.ld +++ /dev/null @@ -1,12 +0,0 @@ -SECTIONS -{ - .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): - { - __end__ = .; - end = __end__; - KEEP(*(.heap*)) - } > RAM - /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however - to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ - __HeapLimit = DEFINED(HEAP_LIMIT) ? HEAP_LIMIT : ORIGIN(RAM) + LENGTH(RAM); -} diff --git a/src/rp2_common/pico_standard_link/scripts/section_no_flash_data.ld b/src/rp2_common/pico_standard_link/scripts/section_no_flash_data.ld deleted file mode 100644 index 35325db6e..000000000 --- a/src/rp2_common/pico_standard_link/scripts/section_no_flash_data.ld +++ /dev/null @@ -1,89 +0,0 @@ -SECTIONS -{ - .data : { - __data_start__ = .; - *(vtable) - - *(.time_critical*) - - *(.data*) - *(.sdata*) - - . = ALIGN(4); - *(.after_data.*) - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__mutex_array_start = .); - KEEP(*(SORT(.mutex_array.*))) - KEEP(*(.mutex_array)) - PROVIDE_HIDDEN (__mutex_array_end = .); - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(SORT(.preinit_array.*))) - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) - PROVIDE_HIDDEN (__fini_array_end = .); - - *(.jcr) - . = ALIGN(4); - } > RAM - - .tdata : { - . = ALIGN(4); - *(.tdata .tdata.* .gnu.linkonce.td.*) - /* All data end */ - __tdata_end = .; - } > RAM - PROVIDE(__data_end__ = .); - - .uninitialized_data (NOLOAD): { - . = ALIGN(4); - *(.uninitialized_data*) - } > RAM - /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ - __etext = LOADADDR(.data); - - .tbss (NOLOAD) : { - . = ALIGN(4); - __bss_start__ = .; - __tls_base = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon) - - __tls_end = .; - } > RAM - - .bss (NOLOAD) : { - . = ALIGN(4); - __tbss_end = .; - - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) - *(COMMON) - PROVIDE(__global_pointer$ = . + 2K); - *(.sbss*) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { - __persistent_data_start__ = .; - *(.persistent_data*) - . = ALIGN(4); - } - PROVIDE(__persistent_data_end__ = .); -} diff --git a/src/rp2_common/pico_standard_link/scripts/section_scratch.ld b/src/rp2_common/pico_standard_link/scripts/section_scratch.ld deleted file mode 100644 index f61c39639..000000000 --- a/src/rp2_common/pico_standard_link/scripts/section_scratch.ld +++ /dev/null @@ -1,37 +0,0 @@ -SECTIONS -{ - /* Start and end symbols must be word-aligned */ - .scratch_x : { - __scratch_x_start__ = .; - *(.scratch_x.*) - . = ALIGN(4); - __scratch_x_end__ = .; - } > SCRATCH_X AT> SCRATCH_X_STORE - __scratch_x_source__ = LOADADDR(.scratch_x); - - .scratch_y : { - __scratch_y_start__ = .; - *(.scratch_y.*) - . = ALIGN(4); - __scratch_y_end__ = .; - } > SCRATCH_Y AT> SCRATCH_Y_STORE - __scratch_y_source__ = LOADADDR(.scratch_y); - - /* .stack*_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later - * - * stack1 section may be empty/missing if platform_launch_core1 is not used */ - - /* by default we put core 0 stack at the end of scratch Y, so that if core 1 - * stack is not used then all of SCRATCH_X is free. - */ - .stack1_dummy (NOLOAD): - { - *(.stack1*) - } > SCRATCH_X - .stack_dummy (NOLOAD): - { - KEEP(*(.stack*)) - } > SCRATCH_Y -} diff --git a/src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld b/src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld deleted file mode 100644 index fe7caf546..000000000 --- a/src/rp2_common/pico_standard_link/scripts/sections_copy_to_ram.ld +++ /dev/null @@ -1,7 +0,0 @@ -INCLUDE "section_copy_to_ram_text.ld" -INCLUDE "section_copy_to_ram_data.ld" -INCLUDE "section_heap.ld" -INCLUDE "section_scratch.ld" -INCLUDE "section_flash_end.ld" -INCLUDE "section_end.ld" -INCLUDE "section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/sections_default.ld b/src/rp2_common/pico_standard_link/scripts/sections_default.ld deleted file mode 100644 index f22558a9f..000000000 --- a/src/rp2_common/pico_standard_link/scripts/sections_default.ld +++ /dev/null @@ -1,7 +0,0 @@ -INCLUDE "section_default_text.ld" -INCLUDE "section_default_data.ld" -INCLUDE "section_heap.ld" -INCLUDE "section_scratch.ld" -INCLUDE "section_flash_end.ld" -INCLUDE "section_end.ld" -INCLUDE "section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld b/src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld deleted file mode 100644 index 77bad234e..000000000 --- a/src/rp2_common/pico_standard_link/scripts/sections_no_flash.ld +++ /dev/null @@ -1,6 +0,0 @@ -INCLUDE "section_no_flash_text.ld" -INCLUDE "section_no_flash_data.ld" -INCLUDE "section_heap.ld" -INCLUDE "section_scratch.ld" -INCLUDE "section_end.ld" -INCLUDE "section_platform_end.ld" diff --git a/src/rp2_common/pico_standard_link/scripts/set_memory_locations.ld b/src/rp2_common/pico_standard_link/scripts/set_memory_locations.ld deleted file mode 100644 index a9110eb59..000000000 --- a/src/rp2_common/pico_standard_link/scripts/set_memory_locations.ld +++ /dev/null @@ -1,8 +0,0 @@ -RAM_ORIGIN = DEFINED(RAM_ORIGIN) ? RAM_ORIGIN : RAM_ORIGIN_DEFAULT; -RAM_LENGTH = DEFINED(RAM_LENGTH) ? RAM_LENGTH : RAM_LENGTH_DEFAULT; -SCRATCH_X_ORIGIN = DEFINED(SCRATCH_X_ORIGIN) ? SCRATCH_X_ORIGIN : SCRATCH_X_ORIGIN_DEFAULT; -SCRATCH_X_LENGTH = DEFINED(SCRATCH_X_LENGTH) ? SCRATCH_X_LENGTH : SCRATCH_X_LENGTH_DEFAULT; -SCRATCH_Y_ORIGIN = DEFINED(SCRATCH_Y_ORIGIN) ? SCRATCH_Y_ORIGIN : SCRATCH_Y_ORIGIN_DEFAULT; -SCRATCH_Y_LENGTH = DEFINED(SCRATCH_Y_LENGTH) ? SCRATCH_Y_LENGTH : SCRATCH_Y_LENGTH_DEFAULT; -XIP_RAM_ORIGIN = DEFINED(XIP_RAM_ORIGIN) ? XIP_RAM_ORIGIN : XIP_RAM_ORIGIN_DEFAULT; -XIP_RAM_LENGTH = DEFINED(XIP_RAM_LENGTH) ? XIP_RAM_LENGTH : XIP_RAM_LENGTH_DEFAULT; From b4d9929a1285cd16b189be2e8c1896a7862b91ca Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Mon, 6 Apr 2026 18:10:32 -0500 Subject: [PATCH 094/127] some bitset cleanup --- src/common/pico_util/CMakeLists.txt | 1 + src/common/pico_util/fixed_bitset.c | 26 ++ .../pico_util/include/pico/util/bitset.h | 234 --------------- .../include/pico/util/fixed_bitset.h | 283 ++++++++++++++++++ src/rp2_common/hardware_clocks/clocks.c | 8 +- .../hardware_clocks/include/hardware/clocks.h | 14 +- .../hardware_powman/include/hardware/powman.h | 25 +- src/rp2_common/hardware_rosc/rosc.c | 4 +- src/rp2_common/pico_low_power/low_power.c | 2 +- test/CMakeLists.txt | 1 + test/fixed_bitset_test/BUILD.bazel | 10 + test/fixed_bitset_test/CMakeLists.txt | 4 + test/fixed_bitset_test/fixed_bitset_test.c | 37 +++ test/kitchen_sink/kitchen_sink.c | 10 - .../panic_function_test/panic_function_test.c | 6 + test/pico_stdlib_test/pico_stdlib_test.c | 2 +- 16 files changed, 395 insertions(+), 272 deletions(-) create mode 100644 src/common/pico_util/fixed_bitset.c delete mode 100644 src/common/pico_util/include/pico/util/bitset.h create mode 100644 src/common/pico_util/include/pico/util/fixed_bitset.h create mode 100644 test/fixed_bitset_test/BUILD.bazel create mode 100644 test/fixed_bitset_test/CMakeLists.txt create mode 100644 test/fixed_bitset_test/fixed_bitset_test.c diff --git a/src/common/pico_util/CMakeLists.txt b/src/common/pico_util/CMakeLists.txt index 86921dd4e..cff7766a0 100644 --- a/src/common/pico_util/CMakeLists.txt +++ b/src/common/pico_util/CMakeLists.txt @@ -8,6 +8,7 @@ if (NOT TARGET pico_util) pico_add_impl_library(pico_util) target_sources(pico_util INTERFACE ${CMAKE_CURRENT_LIST_DIR}/datetime.c + ${CMAKE_CURRENT_LIST_DIR}/fixed_bitset.c ${CMAKE_CURRENT_LIST_DIR}/pheap.c ${CMAKE_CURRENT_LIST_DIR}/queue.c ) diff --git a/src/common/pico_util/fixed_bitset.c b/src/common/pico_util/fixed_bitset.c new file mode 100644 index 000000000..0981062df --- /dev/null +++ b/src/common/pico_util/fixed_bitset.c @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2026 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "include/pico/util/fixed_bitset.h" + +fixed_bitset_t *fixed_bitset_flip_all(fixed_bitset_t *bitset) { + check_fixed_bitset(bitset); + for (uint i=0;iword_size;i++) { + bitset->words[i] = ~bitset->words[i]; + } + return bitset; +} + +bool fixed_bitset_is_empty(fixed_bitset_t *bitset) { + check_fixed_bitset(bitset); + uint i=0; + for (i=0;iword_size-1;i++) { + if (bitset->words[i]) return false; + } + // we don't guarantee that bits above the size aren't set, so mask them off + return !(i && (bitset->words[i] << (32u -(bitset->size & 31u)))); +} + diff --git a/src/common/pico_util/include/pico/util/bitset.h b/src/common/pico_util/include/pico/util/bitset.h deleted file mode 100644 index 4327607af..000000000 --- a/src/common/pico_util/include/pico/util/bitset.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2026 Raspberry Pi (Trading) Ltd. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef _PICO_UTIL_BITSET_H -#define _PICO_UTIL_BITSET_H - -#include "pico.h" - -/** \file bitset.h - * \defgroup bitset bitset - * \brief Simple bitset implementation - * - * \ingroup pico_util - */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - uint16_t size; \ - uint16_t word_size; \ - uint32_t words[]; -} generic_bitset_t; - -/*! \brief Macro used to define a bitset type - * \ingroup pico_util - * This macro is used to define a bitset type. It is used as follows: - * ``` - * typedef bitset_type_t(32) my_bitset_t; - * ``` - * will define a new bitset type called `my_bitset_t` that can hold 32 bits. - * - * The type can be used as `my_bitset_t bitset;` to declare a new bitset. - * - * \param N the number of bits in the bitset - */ -#define bitset_type_t(N) union { \ - generic_bitset_t bitset; \ - struct { \ - uint16_t size; \ - uint16_t word_size; \ - uint32_t words[((N) + 31) / 32]; \ - } sized_bitset; \ -} -#define bitset_sizeof_for(N) ((((N) + 63u) / 32u) * 4u) - -/*! \brief Macro used to create a bitset with all bits set to a value - * \ingroup pico_util - * \param type the type of the bitset - * \param N the number of bits in the bitset - * \param value the value to set the bits to (0 or 1) - * \return the bitset - */ -#define bitset_with_value(type, N, value) ({ type bitset; bitset_init(&bitset, type, N, value); bitset; }) - -// Quick test that the bitset macros give the correct size -extern bitset_type_t(32) __not_real_bitset32; -extern bitset_type_t(33) __not_real_bitset33; -static_assert(sizeof(__not_real_bitset32) == bitset_sizeof_for(1),""); -static_assert(sizeof(__not_real_bitset33) == bitset_sizeof_for(37), ""); - -/*! \brief Initialize a bitset - * \ingroup pico_util - * \param ptr the bitset to initialize - * \param type the type of the bitset - * \param N the number of bits in the bitset - * \param fill the value to fill the bitset with (0 or 1) - */ -#define bitset_init(ptr, type, N, fill) ({ \ - assert(sizeof(type) == bitset_sizeof_for(N)); \ - __unused type *type_check = ptr; \ - __builtin_memset(ptr, (fill) ? 0xff : 0, sizeof(type)); \ - (ptr)->bitset.size = N; \ - (ptr)->bitset.word_size = ((N) + 31u) / 32u; \ -}) - -/*! \brief Get the size of the bitset - * \ingroup pico_util - * \param bitset the bitset to get the size of - * \return the size of the bitset - */ -static inline uint bitset_size(const generic_bitset_t *bitset) { - return bitset->size; -} - -/*! \brief Get the size of the bitset in words - * \ingroup pico_util - * \param bitset the bitset to get the size of - * \return the size of the bitset in words - */ -static inline uint bitset_word_size(const generic_bitset_t *bitset) { - return bitset->word_size; -} - -/*! \brief Check that the bitset is valid - * \ingroup pico_util - * This function will assert if the bitset is not valid. - * \param bitset the bitset to check - */ -static inline void check_bitset(const generic_bitset_t *bitset) { - assert(bitset->word_size == (bitset->size + 31) / 32); -} - -/*! \brief Write a word in the bitset - * \ingroup pico_util - * \param bitset the bitset to write to - * \param word_num the word number to write to - * \param value the value to write to the word - * \return the bitset - */ -static inline generic_bitset_t *bitset_write_word(generic_bitset_t *bitset, uint word_num, uint32_t value) { - check_bitset(bitset); - if (word_num < bitset_word_size(bitset)) { - bitset->words[word_num] = value; - } - return bitset; -} - -/*! \brief Read a word in the bitset - * \ingroup pico_util - * \param bitset the bitset to read from - * \param word_num the word number to read from - * \return the value of the word - */ -static inline uint32_t bitset_read_word(const generic_bitset_t *bitset, uint word_num) { - check_bitset(bitset); - if (word_num < bitset_word_size(bitset)) { - return bitset->words[word_num]; - } - return 0; -} - -/*! \brief Clear all bits in the bitset - * \ingroup pico_util - * \param bitset the bitset to clear - * \return the bitset - */ -static inline generic_bitset_t *bitset_clear(generic_bitset_t *bitset) { - check_bitset(bitset); - __builtin_memset(bitset->words, 0, bitset->word_size * sizeof(uint32_t)); - return bitset; -} - -/*! \brief Set all bits in the bitset - * \ingroup pico_util - * \param bitset the bitset to set - * \return the bitset - */ -static inline generic_bitset_t *bitset_set_all(generic_bitset_t *bitset) { - check_bitset(bitset); - __builtin_memset(bitset->words, 0xff, bitset->word_size * sizeof(uint32_t)); - return bitset; -} - -/*! \brief Set a single bit in the bitset - * \ingroup pico_util - * \param bitset the bitset to set - * \param bit the bit to set - * \return the bitset - */ -static inline generic_bitset_t *bitset_set_bit(generic_bitset_t *bitset, uint bit) { - check_bitset(bitset); - if (bit < bitset->size) { - bitset->words[bit / 32u] |= 1u << (bit % 32u); - } - return bitset; -} - -/*! \brief Clear a single bit in the bitset - * \ingroup pico_util - * \param bitset the bitset to clear - * \param bit the bit to clear - * \return the bitset - */ -static inline generic_bitset_t *bitset_clear_bit(generic_bitset_t *bitset, uint bit) { - check_bitset(bitset); - if (bit < bitset->size) { - bitset->words[bit / 32u] &= ~(1u << (bit % 32u)); - } - return bitset; -} - -/*! \brief Get the value of a single bit in the bitset - * \ingroup pico_util - * \param bitset the bitset to get the value of - * \param bit the bit to get the value of - * \return the value of the bit - */ -static inline bool bitset_get_bit(generic_bitset_t *bitset, uint bit) { - check_bitset(bitset); - assert(bit < bitset->size); -// if (bit < bitset->size) { - return bitset->words[bit / 32u] & (1u << (bit % 32u)); -// } - return false; -} - -/*! \brief Check if two bitsets are equal - * \ingroup pico_util - * \param bitset1 the first bitset to check - * \param bitset2 the second bitset to check - * \return true if the bitsets are equal, false otherwise - */ -static inline bool bitset_equal(const generic_bitset_t *bitset1, const generic_bitset_t *bitset2) { - check_bitset(bitset1); - check_bitset(bitset2); - assert(bitset1->size == bitset2->size); - return __builtin_memcmp(bitset1->words, bitset2->words, bitset1->word_size * sizeof(uint32_t)) == 0; -} - -typedef uint32_t tiny_encoded_bitset_t; -typedef uint64_t encoded_bitset_t; - -#define encoded_bitset_empty() 0 -#define encoded_bitset_of1(v) (1u | ((v) << 8)) -#define encoded_bitset_of2(v1, v2) (2u | ((v1) << 8) | ((v2) << 16)) -#define encoded_bitset_of3(v1, v2, v3) (3u | ((v1) << 8) | ((v2) << 16) | (((v3) << 24))) -#define encoded_bitset_of4(v1, v2, v3, v4) (4u | ((v1) << 8) | ((v2) << 16) | (((v3) << 24)) | (((uint64_t)(v4)) << 32)) -#define encoded_bitset_of5(v1, v2, v3, v4, v5) (5u | ((v1) << 8) | ((v2) << 16) | (((v3) << 24)) | (((uint64_t)((v4) | ((v5)<<8u))) << 32)) - -#define encoded_bitset_foreach(bitset, x) ({ \ - for(uint _i=0;_i<((bitset)&0xffu);_i++) { \ - uint bit = (uint8_t)((bitset) >> (8 * _i)); \ - x; \ - } \ -}) -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/common/pico_util/include/pico/util/fixed_bitset.h b/src/common/pico_util/include/pico/util/fixed_bitset.h new file mode 100644 index 000000000..9696c5cf8 --- /dev/null +++ b/src/common/pico_util/include/pico/util/fixed_bitset.h @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2026 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _PICO_UTIL_FIXED_BITSET_H +#define _PICO_UTIL_FIXED_BITSET_H + +#include "pico.h" + +/** \file fixed_bitset.h + * \defgroup fixed_bitset fixed_bitset + * \brief Simple fixed-size bitset implementation + * + * \ingroup pico_util + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint16_t size; \ + uint16_t word_size; \ + uint32_t words[]; +} fixed_bitset_t; + +/*! \brief Macro used to define a fixed-size bitset of a given size + * \ingroup fixed_bitset + * This macro is used to declare the type of a fixed-size bitset. It is used as follows: + * ``` + * typedef fixed_bitset_type_t(17) my_bitset_t; + * ``` + * will define a new bitset type called `my_bitset_t` that can hold 17 boolean values. + * + * The type can be used as `my_bitset_t bitset;` to declare a new bitset. + * + * \param N the number of boolean values in the bitset + */ +#define fixed_bitset_type(N) union { \ + fixed_bitset_t bitset; \ + struct { \ + uint16_t size; \ + uint16_t word_size; \ + uint32_t words[((N) + 31) / 32]; \ + } sized_bitset; \ +} +#define fixed_bitset_sizeof_for(N) ((((N) + 63u) / 32u) * 4u) + +/*! \brief Macro used to create a bitset with all bits set to a value + * \ingroup fixed_bitset + * \param type the type of the bitset + * \param N the number of bits in the bitset + * \param fill the value to set the bits to (0 or 1) + * \return the bitset + */ +#define fixed_bitset_with_fill(type, N, fill) ({ type bitset; fixed_bitset_init(&bitset, type, N, fill); bitset; }) + +// Quick test that the bitset macros give the correct size +extern fixed_bitset_type(32) __not_real_bitset32; +extern fixed_bitset_type(33) __not_real_bitset33; +static_assert(sizeof(__not_real_bitset32) == fixed_bitset_sizeof_for(1),""); +static_assert(sizeof(__not_real_bitset33) == fixed_bitset_sizeof_for(37), ""); +static_assert(sizeof(__not_real_bitset33) != fixed_bitset_sizeof_for(1), ""); + +/*! \brief Initialize a bitset + * \ingroup fixed_bitset + * \param ptr the bitset to initialize + * \param type the type of the bitset + * \param N the number of bits in the bitset + * \param fill the value to fill the bitset with (0 or 1) + */ +#define fixed_bitset_init(ptr, type, N, fill) ({ \ + assert(sizeof(type) == fixed_bitset_sizeof_for(N)); \ + __unused type *type_check = ptr; \ + (ptr)->bitset.size = N; \ + (ptr)->bitset.word_size = ((N) + 31u) / 32u; \ + __builtin_memset(&(ptr)->bitset.words, (fill) ? 0xff : 0, (ptr)->bitset.word_size * sizeof(uint32_t)); \ +}) + +/*! \brief Get the size of the bitset + * \ingroup fixed_bitset + * \param bitset the bitset to get the size of + * \return the size of the bitset + */ +static inline uint fixed_bitset_size(const fixed_bitset_t *bitset) { + return bitset->size; +} + +/*! \brief Get the size of the bitset in words + * \ingroup fixed_bitset + * \param bitset the bitset to get the size of + * \return the size of the bitset in words + */ +static inline uint fixed_bitset_word_size(const fixed_bitset_t *bitset) { + return bitset->word_size; +} + +/*! \brief Check that the bitset is valid + * \ingroup fixed_bitset + * This function will assert if the bitset is not valid. + * \param bitset the bitset to check + */ +static inline void check_fixed_bitset(const fixed_bitset_t *bitset) { + assert(bitset->word_size == (bitset->size + 31) / 32); +} + +/*! \brief Write a word in the bitset + * \ingroup fixed_bitset + * \param bitset the bitset to write to + * \param word_num the word number to write to + * \param value the value to write to the word + * \return the bitset + */ +static inline fixed_bitset_t *fixed_bitset_write_word(fixed_bitset_t *bitset, uint word_num, uint32_t value) { + check_fixed_bitset(bitset); + if (word_num < fixed_bitset_word_size(bitset)) { + bitset->words[word_num] = value; + } + return bitset; +} + +/*! \brief Read a word in the bitset + * \ingroup fixed_bitset + * \param bitset the bitset + * \param word_num the word number to read from + * \return the value of the word + */ +static inline uint32_t fixed_bitset_read_word(const fixed_bitset_t *bitset, uint word_num) { + check_fixed_bitset(bitset); + if (word_num < fixed_bitset_word_size(bitset)) { + return bitset->words[word_num]; + } + return 0; +} + +/*! \brief Clear all bits in the bitset + * \ingroup fixed_bitset + * \param bitset the bitset + * \return the bitset + */ +static inline fixed_bitset_t *fixed_bitset_clear_all(fixed_bitset_t *bitset) { + check_fixed_bitset(bitset); + __builtin_memset(bitset->words, 0, bitset->word_size * sizeof(uint32_t)); + return bitset; +} + +/*! \brief Set all bits in the bitset + * \ingroup fixed_bitset + * \param bitset the bitset + * \return the bitset + */ +static inline fixed_bitset_t *bitset_set_all(fixed_bitset_t *bitset) { + check_fixed_bitset(bitset); + __builtin_memset(bitset->words, 0xff, bitset->word_size * sizeof(uint32_t)); + return bitset; +} + +/*! \brief Flip all bits in the bitset + * \ingroup fixed_bitset + * \param bitset the bitset + * \return the bitset + */ +fixed_bitset_t *fixed_bitset_flip_all(fixed_bitset_t *bitset); + +/*! \brief Determine if bitset is empty + * \ingroup fixed_bitset + * \param bitset the bitset + * \return true if not bits are set + */ +bool fixed_bitset_is_empty(fixed_bitset_t *bitset); + +/*! \brief Set a single bit in the bitset + * \ingroup fixed_bitset + * \param bitset the bitset + * \param bit_index the bit to set + * \return the bitset + */ +static inline fixed_bitset_t *fixed_bitset_set(fixed_bitset_t *bitset, uint bit_index) { + check_fixed_bitset(bitset); + if (bit_index < bitset->size) { + bitset->words[bit_index / 32u] |= 1u << (bit_index % 32u); + } + return bitset; +} + +/*! \brief Clear a single bit in the bitset + * \ingroup fixed_bitset + * \param bitset the bitset + * \param bit_index the bit to clear + * \return the bitset + */ +static inline fixed_bitset_t *fixed_bitset_clear(fixed_bitset_t *bitset, uint bit_index) { + check_fixed_bitset(bitset); + if (bit_index < bitset->size) { + bitset->words[bit_index / 32u] &= ~(1u << (bit_index % 32u)); + } + return bitset; +} + +/*! \brief Flip a single bit in the bitset + * \ingroup fixed_bitset + * \param bitset the bitset + * \param bit_index the bit to flip + * \return the bitset + */ +static inline fixed_bitset_t *fixed_bitset_flip(fixed_bitset_t *bitset, uint bit_index) { + check_fixed_bitset(bitset); + if (bit_index < bitset->size) { + bitset->words[bit_index / 32u] ^= 1u << (bit_index % 32u); + } + return bitset; +} + + +/*! \brief Get the value of a single bit in the bitset + * \ingroup fixed_bitset + * \param bitset the bitset + * \param bit_index the bit to get the value of + * \return the value of the bit + */ +static inline bool fixed_bitset_get(const fixed_bitset_t *bitset, uint bit_index) { + check_fixed_bitset(bitset); + assert(bit_index < bitset->size); +// if (bit < bitset->size) { + return bitset->words[bit_index / 32u] & (1u << (bit_index % 32u)); +// } + return false; +} + +/*! \brief Check if two bitsets are equal + * \ingroup fixed_bitset + * \param bitset1 the first bitset to check + * \param bitset2 the second bitset to check + * \return true if the bitsets are equal, false otherwise + */ +static inline bool fixed_bitset_equal(const fixed_bitset_t *bitset1, const fixed_bitset_t *bitset2) { + check_fixed_bitset(bitset1); + check_fixed_bitset(bitset2); + assert(bitset1->size == bitset2->size); + return __builtin_memcmp(bitset1->words, bitset2->words, bitset1->word_size * sizeof(uint32_t)) == 0; +} + +#if 0 // not currently used +typedef uint32_t tiny_ordinal_list_t; // ordinals must be 0->255 +typedef uint64_t small_ordinal_list_t; // ordinals must be 0->255 +#define ordinal_list_empty() 0 +#define ordinal_list_of1(v) (1u | ((v) << 8)) +#define ordinal_list_of2(v1, v2) (2u | ((v1) << 8) | ((v2) << 16)) +#define ordinal_list_of3(v1, v2, v3) (3u | ((v1) << 8) | ((v2) << 16) | (((v3) << 24))) +#define ordinal_list_of4(v1, v2, v3, v4) (4u | ((v1) << 8) | ((v2) << 16) | (((v3) << 24)) | (((uint64_t)(v4)) << 32)) +#define ordinal_list_of5(v1, v2, v3, v4, v5) (5u | ((v1) << 8) | ((v2) << 16) | (((v3) << 24)) | (((uint64_t)((v4) | ((v5)<<8u))) << 32)) + +#define small_ordinal_list_foreach(bitarray, x) ({ \ + for(uint _i=1;_i<=((bitarray)&0xffu);_i++) { \ + uint bit = (uint8_t)((bitarray) >> (8 * _i)); \ + x; \ + } \ +}) + +static inline fixed_bitset_t *fixed_bitset_set_bits(fixed_bitset_t *bitset, small_ordinal_list_t list) { + small_ordinal_list_foreach(list, fixed_bitset_set(bitset, bit)); + return bitset; +} + +static inline fixed_bitset_t *fixed_bitset_clear_bits(fixed_bitset_t *bitset, small_ordinal_list_t list) { + small_ordinal_list_foreach(list, fixed_bitset_clear(bitset, bit)); + return bitset; +} + + +#define fixed_bitset_init_with_bits(ptr, type, N, list) ({ \ + /* not this performs checks */ \ + fixed_bitset_init(ptr, type, N, 0); \ + fixed_bitset_set_bits(&(ptr)->bitset, list); \ +}) + +#endif +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/rp2_common/hardware_clocks/clocks.c b/src/rp2_common/hardware_clocks/clocks.c index 8243b6e73..3bc61b692 100644 --- a/src/rp2_common/hardware_clocks/clocks.c +++ b/src/rp2_common/hardware_clocks/clocks.c @@ -445,14 +445,14 @@ bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_out, uint *postdiv1_out, u void clock_get_sleep_en_gate(clock_dest_bitset_t *dests) { static_assert(CLOCKS_SLEEP_EN1_OFFSET == CLOCKS_SLEEP_EN0_OFFSET + 4, ""); - for(uint i=0;i < bitset_word_size(&dests->bitset); i++) { - bitset_write_word(&dests->bitset, i, clocks_hw->sleep_en[i]); + for(uint i=0;i < fixed_bitset_word_size(&dests->bitset); i++) { + fixed_bitset_write_word(&dests->bitset, i, clocks_hw->sleep_en[i]); } } void clock_gate_sleep_en(const clock_dest_bitset_t *dests) { static_assert(CLOCKS_SLEEP_EN1_OFFSET == CLOCKS_SLEEP_EN0_OFFSET + 4, ""); - for(uint i=0;i < bitset_word_size(&dests->bitset); i++) { - clocks_hw->sleep_en[i] = bitset_read_word(&dests->bitset, i); + for(uint i=0;i < fixed_bitset_word_size(&dests->bitset); i++) { + clocks_hw->sleep_en[i] = fixed_bitset_read_word(&dests->bitset, i); } } diff --git a/src/rp2_common/hardware_clocks/include/hardware/clocks.h b/src/rp2_common/hardware_clocks/include/hardware/clocks.h index 397d8b82a..1f83984fd 100644 --- a/src/rp2_common/hardware_clocks/include/hardware/clocks.h +++ b/src/rp2_common/hardware_clocks/include/hardware/clocks.h @@ -578,14 +578,14 @@ static inline bool set_sys_clock_khz(uint32_t freq_khz, bool required) { return false; } -#include "pico/util/bitset.h" +#include "pico/util/fixed_bitset.h" -typedef bitset_type_t(NUM_CLOCK_DESTINATIONS) clock_dest_bitset_t; -#define clock_dest_bitset_none() bitset_with_value(clock_dest_bitset_t, NUM_CLOCK_DESTINATIONS, 0) -#define clock_dest_bitset_all() bitset_with_value(clock_dest_bitset_t, NUM_CLOCK_DESTINATIONS, 1) +typedef fixed_bitset_type(NUM_CLOCK_DESTINATIONS) clock_dest_bitset_t; +#define clock_dest_bitset_none() fixed_bitset_with_fill(clock_dest_bitset_t, NUM_CLOCK_DESTINATIONS, 0) +#define clock_dest_bitset_all() fixed_bitset_with_fill(clock_dest_bitset_t, NUM_CLOCK_DESTINATIONS, 1) static inline clock_dest_bitset_t *clock_dest_bitset_clear(clock_dest_bitset_t *dests) { - bitset_clear(&dests->bitset); + fixed_bitset_clear_all(&dests->bitset); return dests; } @@ -595,12 +595,12 @@ static inline clock_dest_bitset_t *clock_dest_bitset_add_all(clock_dest_bitset_t } static inline clock_dest_bitset_t *clock_dest_bitset_add(clock_dest_bitset_t *dests, clock_dest_num_t dest) { - bitset_set_bit(&dests->bitset, dest); + fixed_bitset_set(&dests->bitset, dest); return dests; } static inline clock_dest_bitset_t *clock_dest_bitset_remove(clock_dest_bitset_t *dests, clock_dest_num_t dest) { - bitset_clear_bit(&dests->bitset, dest); + fixed_bitset_clear(&dests->bitset, dest); return dests; } diff --git a/src/rp2_common/hardware_powman/include/hardware/powman.h b/src/rp2_common/hardware_powman/include/hardware/powman.h index 25c5a6397..1ed7b548a 100644 --- a/src/rp2_common/hardware_powman/include/hardware/powman.h +++ b/src/rp2_common/hardware_powman/include/hardware/powman.h @@ -9,7 +9,7 @@ #include "pico.h" #include "hardware/structs/powman.h" -#include "pico/util/bitset.h" +#include "pico/util/fixed_bitset.h" #ifdef __cplusplus extern "C" { @@ -172,12 +172,12 @@ typedef enum powman_power_domains powman_power_domain_t; typedef uint32_t powman_power_state; -typedef bitset_type_t(POWMAN_POWER_DOMAIN_COUNT) pstate_bitset_t; -#define pstate_bitset_none() bitset_with_value(pstate_bitset_t, POWMAN_POWER_DOMAIN_COUNT, 0) -#define pstate_bitset_all() bitset_with_value(pstate_bitset_t, POWMAN_POWER_DOMAIN_COUNT, 1) +typedef fixed_bitset_type(POWMAN_POWER_DOMAIN_COUNT) pstate_bitset_t; +#define pstate_bitset_none() fixed_bitset_with_fill(pstate_bitset_t, POWMAN_POWER_DOMAIN_COUNT, 0) +#define pstate_bitset_all() fixed_bitset_with_fill(pstate_bitset_t, POWMAN_POWER_DOMAIN_COUNT, 1) -static inline pstate_bitset_t *pstate_bitset_clear(pstate_bitset_t *domains) { - bitset_clear(&domains->bitset); +static inline pstate_bitset_t *pstate_bitset_remove_all(pstate_bitset_t *domains) { + fixed_bitset_clear_all(&domains->bitset); return domains; } @@ -187,32 +187,31 @@ static inline pstate_bitset_t *pstate_bitset_add_all(pstate_bitset_t *domains) { } static inline pstate_bitset_t *pstate_bitset_add(pstate_bitset_t *domains, powman_power_domain_t domain) { - bitset_set_bit(&domains->bitset, domain); + fixed_bitset_set(&domains->bitset, domain); return domains; } static inline pstate_bitset_t *pstate_bitset_remove(pstate_bitset_t *domains, powman_power_domain_t domain) { - bitset_clear_bit(&domains->bitset, domain); + fixed_bitset_clear(&domains->bitset, domain); return domains; } static inline bool pstate_bitset_is_set(pstate_bitset_t *domains, powman_power_domain_t domain) { - return bitset_get_bit(&domains->bitset, domain); + return fixed_bitset_get(&domains->bitset, domain); } static inline bool pstate_bitset_none_set(pstate_bitset_t *domains) { - pstate_bitset_t none = pstate_bitset_none(); - return bitset_equal(&domains->bitset, &none.bitset); + return fixed_bitset_is_empty(&domains->bitset); } static inline pstate_bitset_t *pstate_bitset_from_powman_power_state(pstate_bitset_t *domains, powman_power_state pstate) { static_assert(sizeof(powman_power_state) <= sizeof(uint32_t)); - bitset_write_word(&domains->bitset, 0, pstate); + fixed_bitset_write_word(&domains->bitset, 0, pstate); return domains; } static inline powman_power_state pstate_bitset_to_powman_power_state(pstate_bitset_t *domains) { - return bitset_read_word(&domains->bitset, 0); + return fixed_bitset_read_word(&domains->bitset, 0); } /*! \brief Get the current power state diff --git a/src/rp2_common/hardware_rosc/rosc.c b/src/rp2_common/hardware_rosc/rosc.c index d24415e53..9cf9318b9 100644 --- a/src/rp2_common/hardware_rosc/rosc.c +++ b/src/rp2_common/hardware_rosc/rosc.c @@ -35,9 +35,9 @@ uint rosc_measure_freq_khz(void) { void rosc_set_div(uint32_t div) { #if PICO_RP2040 - assert(div <= 31 && div >= 0); + assert(div <= 31); #else - assert(div <= 127 && div >= 0); + assert(div <= 127); #endif rosc_write(&rosc_hw->div, ROSC_DIV_VALUE_PASS + div); } diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index edfa19203..91114db53 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -546,7 +546,7 @@ pstate_bitset_t *low_power_pstate_get(pstate_bitset_t *pstate) { } pstate_bitset_t *low_power_persistent_pstate_get(pstate_bitset_t *pstate) { - pstate_bitset_clear(pstate); + pstate_bitset_remove_all(pstate); if ((uint32_t)__persistent_data_start__ == (uint32_t)__persistent_data_end__) { // No persistent data, so power down everything diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3cef961d3..2943a8bfc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,6 +4,7 @@ add_subdirectory(pico_stdlib_test) add_subdirectory(pico_stdio_test) add_subdirectory(pico_time_test) add_subdirectory(pico_divider_test) +add_subdirectory(fixed_bitset_test) if (PICO_ON_DEVICE) add_subdirectory(panic_function_test) add_subdirectory(pico_float_test) diff --git a/test/fixed_bitset_test/BUILD.bazel b/test/fixed_bitset_test/BUILD.bazel new file mode 100644 index 000000000..9e96248db --- /dev/null +++ b/test/fixed_bitset_test/BUILD.bazel @@ -0,0 +1,10 @@ +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("//bazel:defs.bzl", "compatible_with_rp2") + +# TODO: Add these tests to the Bazel build. +filegroup( + name = "unsupported_tests", + srcs = [ + "fixed_bitset_test.c", + ], +) diff --git a/test/fixed_bitset_test/CMakeLists.txt b/test/fixed_bitset_test/CMakeLists.txt new file mode 100644 index 000000000..b39b6868a --- /dev/null +++ b/test/fixed_bitset_test/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(fixed_bitset_test fixed_bitset_test.c) + +target_link_libraries(fixed_bitset_test PRIVATE pico_stdlib pico_util) +pico_add_extra_outputs(fixed_bitset_test) diff --git a/test/fixed_bitset_test/fixed_bitset_test.c b/test/fixed_bitset_test/fixed_bitset_test.c new file mode 100644 index 000000000..1a82033bb --- /dev/null +++ b/test/fixed_bitset_test/fixed_bitset_test.c @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2026 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "pico/stdlib.h" +#include "pico/util/fixed_bitset.h" + +#define CHECK(b, message, ...) ({ if (!(b)) { printf("FAILED: " message "\n", ##__VA_ARGS__); exit(1); } }) + +typedef fixed_bitset_type(47) bitset47_t; + +int main() { + stdio_init_all(); + + bitset47_t b47; + fixed_bitset_init(&b47, bitset47_t, 47, 0); + for (int i=0;i<47;i++) { + CHECK(!fixed_bitset_get(&b47.bitset, i), "Bit %d should be clear", i); + } + + fixed_bitset_init(&b47, bitset47_t, 47, 1); + for (int i=0;i<47;i++) { + CHECK(fixed_bitset_get(&b47.bitset, i), "Bit %d should be set", i); + } + for (int i=46;i>=0;i--) { + CHECK(fixed_bitset_get(&b47.bitset, i), "Bit %d should be set", i); + fixed_bitset_clear(&b47.bitset, i); + CHECK(!fixed_bitset_get(&b47.bitset, i), "Bit %d should be clear", i); + CHECK(!i == fixed_bitset_is_empty(&b47.bitset), "Bitset should be empty once last bit is cleared"); + } + + puts("PASSED"); +} \ No newline at end of file diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index 22a453d5a..cc92333d3 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -89,16 +89,6 @@ int main(void) { hard_assert(!mutex_try_enter(&mutex, NULL)); hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL)); hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL)); - typedef bitset_type_t(47) foop_t; -//#define WOOP encoded_bitset_of3(1, 27, 32) -#define WOOP encoded_bitset_of5(1, 27, 32, 40, 3) - encoded_bitset_foreach(WOOP, printf("Flarn %d\n", bit)); - foop_t fooper; - bitset_init(&fooper, foop_t, 47, 0); - encoded_bitset_foreach(WOOP, bitset_set_bit(&fooper.bitset, bit)); - for(uint i=0;i #include diff --git a/test/pico_stdlib_test/pico_stdlib_test.c b/test/pico_stdlib_test/pico_stdlib_test.c index 11f1f7900..d8f1238e9 100644 --- a/test/pico_stdlib_test/pico_stdlib_test.c +++ b/test/pico_stdlib_test/pico_stdlib_test.c @@ -101,5 +101,5 @@ int main() { printf("%" PRIu64 "\n", to_us_since_boot(get_absolute_time())); until = delayed_by_us(until, 500000); } - puts("DONE"); + puts("PASSED"); } From 500de3cf0739faac2a94813a0d2ceb200f4e90d2 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Mon, 6 Apr 2026 18:11:10 -0500 Subject: [PATCH 095/127] oops --- src/common/pico_util/BUILD.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/pico_util/BUILD.bazel b/src/common/pico_util/BUILD.bazel index a7a70c4aa..55c8afd3e 100644 --- a/src/common/pico_util/BUILD.bazel +++ b/src/common/pico_util/BUILD.bazel @@ -11,7 +11,7 @@ cc_library( "queue.c", ], hdrs = [ - "include/pico/util/bitset.h", + "include/pico/util/fixed_bitset.h", "include/pico/util/datetime.h", "include/pico/util/pheap.h", "include/pico/util/queue.h", From 64639f79a9a2804f88837b7d1ac69db28f0f8314 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Mon, 6 Apr 2026 18:21:31 -0500 Subject: [PATCH 096/127] more cleanup --- src/common/pico_util/include/pico/util/fixed_bitset.h | 2 +- src/rp2_common/hardware_clocks/CMakeLists.txt | 1 + src/rp2_common/hardware_clocks/include/hardware/clocks.h | 5 ++--- src/rp2_common/hardware_powman/include/hardware/powman.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common/pico_util/include/pico/util/fixed_bitset.h b/src/common/pico_util/include/pico/util/fixed_bitset.h index 9696c5cf8..2720b7e34 100644 --- a/src/common/pico_util/include/pico/util/fixed_bitset.h +++ b/src/common/pico_util/include/pico/util/fixed_bitset.h @@ -151,7 +151,7 @@ static inline fixed_bitset_t *fixed_bitset_clear_all(fixed_bitset_t *bitset) { * \param bitset the bitset * \return the bitset */ -static inline fixed_bitset_t *bitset_set_all(fixed_bitset_t *bitset) { +static inline fixed_bitset_t *fixed_bitset_set_all(fixed_bitset_t *bitset) { check_fixed_bitset(bitset); __builtin_memset(bitset->words, 0xff, bitset->word_size * sizeof(uint32_t)); return bitset; diff --git a/src/rp2_common/hardware_clocks/CMakeLists.txt b/src/rp2_common/hardware_clocks/CMakeLists.txt index 95b16c2f3..575081b8c 100644 --- a/src/rp2_common/hardware_clocks/CMakeLists.txt +++ b/src/rp2_common/hardware_clocks/CMakeLists.txt @@ -10,6 +10,7 @@ pico_mirrored_target_link_libraries(hardware_clocks INTERFACE hardware_vreg hardware_watchdog hardware_xosc + pico_util ) if (PICO_USE_FASTEST_SUPPORTED_CLOCK) diff --git a/src/rp2_common/hardware_clocks/include/hardware/clocks.h b/src/rp2_common/hardware_clocks/include/hardware/clocks.h index 1f83984fd..cc6911caa 100644 --- a/src/rp2_common/hardware_clocks/include/hardware/clocks.h +++ b/src/rp2_common/hardware_clocks/include/hardware/clocks.h @@ -9,6 +9,7 @@ #include "pico.h" #include "hardware/structs/clocks.h" +#include "pico/util/fixed_bitset.h" #ifdef __cplusplus extern "C" { @@ -578,8 +579,6 @@ static inline bool set_sys_clock_khz(uint32_t freq_khz, bool required) { return false; } -#include "pico/util/fixed_bitset.h" - typedef fixed_bitset_type(NUM_CLOCK_DESTINATIONS) clock_dest_bitset_t; #define clock_dest_bitset_none() fixed_bitset_with_fill(clock_dest_bitset_t, NUM_CLOCK_DESTINATIONS, 0) #define clock_dest_bitset_all() fixed_bitset_with_fill(clock_dest_bitset_t, NUM_CLOCK_DESTINATIONS, 1) @@ -590,7 +589,7 @@ static inline clock_dest_bitset_t *clock_dest_bitset_clear(clock_dest_bitset_t * } static inline clock_dest_bitset_t *clock_dest_bitset_add_all(clock_dest_bitset_t *dests) { - bitset_set_all(&dests->bitset); + fixed_bitset_set_all(&dests->bitset); return dests; } diff --git a/src/rp2_common/hardware_powman/include/hardware/powman.h b/src/rp2_common/hardware_powman/include/hardware/powman.h index 1ed7b548a..3c195aa94 100644 --- a/src/rp2_common/hardware_powman/include/hardware/powman.h +++ b/src/rp2_common/hardware_powman/include/hardware/powman.h @@ -182,7 +182,7 @@ static inline pstate_bitset_t *pstate_bitset_remove_all(pstate_bitset_t *domains } static inline pstate_bitset_t *pstate_bitset_add_all(pstate_bitset_t *domains) { - bitset_set_all(&domains->bitset); + fixed_bitset_set_all(&domains->bitset); return domains; } From d1cdadb60c06002330a1bfc26001ddb474626832 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Mon, 6 Apr 2026 18:24:33 -0500 Subject: [PATCH 097/127] argh --- src/common/pico_util/fixed_bitset.c | 2 +- test/fixed_bitset_test/fixed_bitset_test.c | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/common/pico_util/fixed_bitset.c b/src/common/pico_util/fixed_bitset.c index 0981062df..7e46ccd6d 100644 --- a/src/common/pico_util/fixed_bitset.c +++ b/src/common/pico_util/fixed_bitset.c @@ -16,7 +16,7 @@ fixed_bitset_t *fixed_bitset_flip_all(fixed_bitset_t *bitset) { bool fixed_bitset_is_empty(fixed_bitset_t *bitset) { check_fixed_bitset(bitset); - uint i=0; + int i=0; for (i=0;iword_size-1;i++) { if (bitset->words[i]) return false; } diff --git a/test/fixed_bitset_test/fixed_bitset_test.c b/test/fixed_bitset_test/fixed_bitset_test.c index 1a82033bb..fe09df992 100644 --- a/test/fixed_bitset_test/fixed_bitset_test.c +++ b/test/fixed_bitset_test/fixed_bitset_test.c @@ -26,6 +26,7 @@ int main() { for (int i=0;i<47;i++) { CHECK(fixed_bitset_get(&b47.bitset, i), "Bit %d should be set", i); } + for (int i=46;i>=0;i--) { CHECK(fixed_bitset_get(&b47.bitset, i), "Bit %d should be set", i); fixed_bitset_clear(&b47.bitset, i); @@ -33,5 +34,15 @@ int main() { CHECK(!i == fixed_bitset_is_empty(&b47.bitset), "Bitset should be empty once last bit is cleared"); } + fixed_bitset_init(&b47, bitset47_t, 47, 1); + for (int i=0;i<47;i++) { + CHECK(fixed_bitset_get(&b47.bitset, i), "Bit %d should be set", i); + } + for (int i=0;i<47;i++) { + CHECK(fixed_bitset_get(&b47.bitset, i), "Bit %d should be set", i); + fixed_bitset_clear(&b47.bitset, i); + CHECK(!fixed_bitset_get(&b47.bitset, i), "Bit %d should be clear", i); + CHECK((i==46) == fixed_bitset_is_empty(&b47.bitset), "Bitset should be empty once last bit is cleared"); + } puts("PASSED"); } \ No newline at end of file From 24d575f01957eed9124b8b51ebc5840d02e56791 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 7 Apr 2026 11:41:20 +0100 Subject: [PATCH 098/127] Add note about accuracy to rosc functions Also update note about DORMANT_CLOCK_SOURCE_LPOSC for pin state, to clarify that you should use DORMANT_CLOCK_SOURCE_ROSC instead --- src/rp2_common/hardware_rosc/include/hardware/rosc.h | 3 +++ src/rp2_common/pico_low_power/include/pico/low_power.h | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/rp2_common/hardware_rosc/include/hardware/rosc.h b/src/rp2_common/hardware_rosc/include/hardware/rosc.h index 5868236ca..b1e664d7a 100644 --- a/src/rp2_common/hardware_rosc/include/hardware/rosc.h +++ b/src/rp2_common/hardware_rosc/include/hardware/rosc.h @@ -82,6 +82,7 @@ uint32_t next_rosc_code(uint32_t code); * \ingroup hardware_rosc * * This function will set the frequency of the Ring Oscillator to the first frequency within the range. + * This will only be accurate if clk_ref is currently running from an accurate source (eg the XOSC). * * \param low_mhz The bottom of the range to search for. * \param high_mhz The top of the range to search for. @@ -92,6 +93,8 @@ uint rosc_find_freq_mhz(uint32_t low_mhz, uint32_t high_mhz); /*! \brief Measure the frequency of the Ring Oscillator * \ingroup hardware_rosc * + * This will only be accurate if clk_ref is currently running from an accurate source (eg the XOSC). + * * \return The frequency of the Ring Oscillator in kHz. */ uint rosc_measure_freq_khz(void); diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index e5d87b3fe..c444972f7 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -156,7 +156,8 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_sourc * * \if (!rp2040_specific) * If the clock source is set to DORMANT_CLOCK_SOURCE_LPOSC, clk_sys will be run from the ROSC while dormant so - * it can be stopped, while clk_ref will be run from the LPOSC so that continues running for the GPIO interrupt. + * it can be stopped, while clk_ref will be run from the LPOSC. For the lowest power consumption, you should use + * DORMANT_CLOCK_SOURCE_ROSC instead, as the GPIO interrupt does not require a clock. * \endif * * \param gpio_pin The GPIO pin to use. From 34a6c3a3a17e0b9ead01b7b27c8487accb32e763 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 7 Apr 2026 11:43:58 +0100 Subject: [PATCH 099/127] Update memmap annotations Now include persistent data section --- src/rp2040/pico_platform/memmap_blocked_ram.ld | 3 ++- src/rp2040/pico_platform/memmap_copy_to_ram.ld | 3 ++- src/rp2040/pico_platform/memmap_default.ld | 3 ++- src/rp2040/pico_platform/memmap_no_flash.ld | 3 ++- src/rp2350/pico_platform/memmap_copy_to_ram.ld | 3 ++- src/rp2350/pico_platform/memmap_default.ld | 3 ++- src/rp2350/pico_platform/memmap_no_flash.ld | 3 ++- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/rp2040/pico_platform/memmap_blocked_ram.ld b/src/rp2040/pico_platform/memmap_blocked_ram.ld index 7dfa94c33..345036962 100644 --- a/src/rp2040/pico_platform/memmap_blocked_ram.ld +++ b/src/rp2040/pico_platform/memmap_blocked_ram.ld @@ -33,7 +33,8 @@ INCLUDE "memmap_default.incl" * │ ├── section_ram_vector_table.incl rp2_common/pico_standard_link * │ ├── section_uninitialized_data.incl rp2_common/pico_standard_link * │ ├── section_default_data.incl rp2_common/pico_standard_link - * │ └── section_bss.incl rp2_common/pico_standard_link + * │ ├── section_bss.incl rp2_common/pico_standard_link + * │ └── section_persistent_data.incl rp2_common/pico_standard_link * ├── section_generated_post_data.incl rp2_common/pico_standard_link * ├── section_extra_post_data.incl rp2_common/pico_standard_link * ├── section_heap.incl rp2_common/pico_standard_link diff --git a/src/rp2040/pico_platform/memmap_copy_to_ram.ld b/src/rp2040/pico_platform/memmap_copy_to_ram.ld index 411b62d48..a9e541e8d 100644 --- a/src/rp2040/pico_platform/memmap_copy_to_ram.ld +++ b/src/rp2040/pico_platform/memmap_copy_to_ram.ld @@ -29,7 +29,8 @@ INCLUDE "memmap_copy_to_ram.incl" * ├── section_extra_post_text.incl rp2_common/pico_standard_link * ├── sections_copy_to_ram_data.incl rp2_common/pico_standard_link * │ ├── section_copy_to_ram_data.incl rp2_common/pico_standard_link - * │ └── section_bss.incl rp2_common/pico_standard_link + * │ ├── section_bss.incl rp2_common/pico_standard_link + * │ └── section_persistent_data.incl rp2_common/pico_standard_link * ├── section_generated_post_data.incl rp2_common/pico_standard_link * ├── section_extra_post_data.incl rp2_common/pico_standard_link * ├── section_heap.incl rp2_common/pico_standard_link diff --git a/src/rp2040/pico_platform/memmap_default.ld b/src/rp2040/pico_platform/memmap_default.ld index 3b6e09409..f7e561e7c 100644 --- a/src/rp2040/pico_platform/memmap_default.ld +++ b/src/rp2040/pico_platform/memmap_default.ld @@ -30,7 +30,8 @@ INCLUDE "memmap_default.incl" * │ ├── section_ram_vector_table.incl rp2_common/pico_standard_link * │ ├── section_uninitialized_data.incl rp2_common/pico_standard_link * │ ├── section_default_data.incl rp2_common/pico_standard_link - * │ └── section_bss.incl rp2_common/pico_standard_link + * │ ├── section_bss.incl rp2_common/pico_standard_link + * │ └── section_persistent_data.incl rp2_common/pico_standard_link * ├── section_generated_post_data.incl rp2_common/pico_standard_link * ├── section_extra_post_data.incl rp2_common/pico_standard_link * ├── section_heap.incl rp2_common/pico_standard_link diff --git a/src/rp2040/pico_platform/memmap_no_flash.ld b/src/rp2040/pico_platform/memmap_no_flash.ld index 00a434989..9e86b518d 100644 --- a/src/rp2040/pico_platform/memmap_no_flash.ld +++ b/src/rp2040/pico_platform/memmap_no_flash.ld @@ -24,7 +24,8 @@ INCLUDE "memmap_no_flash.incl" * ├── sections_no_flash_data.incl rp2_common/pico_standard_link * │ ├── section_no_flash_data.incl rp2_common/pico_standard_link * │ ├── section_uninitialized_data.incl rp2_common/pico_standard_link - * │ └── section_bss.incl rp2_common/pico_standard_link + * │ ├── section_bss.incl rp2_common/pico_standard_link + * │ └── section_persistent_data.incl rp2_common/pico_standard_link * ├── section_generated_post_data.incl rp2_common/pico_standard_link * ├── section_extra_post_data.incl rp2_common/pico_standard_link * ├── section_heap.incl rp2_common/pico_standard_link diff --git a/src/rp2350/pico_platform/memmap_copy_to_ram.ld b/src/rp2350/pico_platform/memmap_copy_to_ram.ld index 2a534b940..d8c1d8bec 100644 --- a/src/rp2350/pico_platform/memmap_copy_to_ram.ld +++ b/src/rp2350/pico_platform/memmap_copy_to_ram.ld @@ -29,7 +29,8 @@ INCLUDE "memmap_copy_to_ram.incl" * ├── section_extra_post_text.incl rp2_common/pico_standard_link * ├── sections_copy_to_ram_data.incl rp2_common/pico_standard_link * │ ├── section_copy_to_ram_data.incl rp2_common/pico_standard_link - * │ └── section_bss.incl rp2_common/pico_standard_link + * │ ├── section_bss.incl rp2_common/pico_standard_link + * │ └── section_persistent_data.incl rp2_common/pico_standard_link * ├── section_generated_post_data.incl rp2_common/pico_standard_link * ├── section_extra_post_data.incl rp2_common/pico_standard_link * ├── section_heap.incl rp2_common/pico_standard_link diff --git a/src/rp2350/pico_platform/memmap_default.ld b/src/rp2350/pico_platform/memmap_default.ld index 965541bd5..b1d5121df 100644 --- a/src/rp2350/pico_platform/memmap_default.ld +++ b/src/rp2350/pico_platform/memmap_default.ld @@ -30,7 +30,8 @@ INCLUDE "memmap_default.incl" * │ ├── section_ram_vector_table.incl rp2_common/pico_standard_link * │ ├── section_uninitialized_data.incl rp2_common/pico_standard_link * │ ├── section_default_data.incl rp2_common/pico_standard_link - * │ └── section_bss.incl rp2_common/pico_standard_link + * │ ├── section_bss.incl rp2_common/pico_standard_link + * │ └── section_persistent_data.incl rp2_common/pico_standard_link * ├── section_generated_post_data.incl rp2_common/pico_standard_link * ├── section_extra_post_data.incl rp2_common/pico_standard_link * ├── section_heap.incl rp2_common/pico_standard_link diff --git a/src/rp2350/pico_platform/memmap_no_flash.ld b/src/rp2350/pico_platform/memmap_no_flash.ld index 67acac37c..34b3a33e7 100644 --- a/src/rp2350/pico_platform/memmap_no_flash.ld +++ b/src/rp2350/pico_platform/memmap_no_flash.ld @@ -24,7 +24,8 @@ INCLUDE "memmap_no_flash.incl" * ├── sections_no_flash_data.incl rp2_common/pico_standard_link * │ ├── section_no_flash_data.incl rp2_common/pico_standard_link * │ ├── section_uninitialized_data.incl rp2_common/pico_standard_link - * │ └── section_bss.incl rp2_common/pico_standard_link + * │ ├── section_bss.incl rp2_common/pico_standard_link + * │ └── section_persistent_data.incl rp2_common/pico_standard_link * ├── section_generated_post_data.incl rp2_common/pico_standard_link * ├── section_extra_post_data.incl rp2_common/pico_standard_link * ├── section_heap.incl rp2_common/pico_standard_link From 95e8a9cd38146eab07f7c8721cc332fb66487027 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 7 Apr 2026 11:57:36 +0100 Subject: [PATCH 100/127] Fix the rename from bitset.h to fixed_bitset.h Also add __unused to check_fixed_bitset to fix release builds --- src/common/pico_util/BUILD.bazel | 1 + src/common/pico_util/include/pico/util/fixed_bitset.h | 2 +- test/kitchen_sink/kitchen_sink.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/common/pico_util/BUILD.bazel b/src/common/pico_util/BUILD.bazel index 55c8afd3e..8095e7560 100644 --- a/src/common/pico_util/BUILD.bazel +++ b/src/common/pico_util/BUILD.bazel @@ -6,6 +6,7 @@ package(default_visibility = ["//visibility:public"]) cc_library( name = "pico_util", srcs = [ + "fixed_bitset.c", "datetime.c", "pheap.c", "queue.c", diff --git a/src/common/pico_util/include/pico/util/fixed_bitset.h b/src/common/pico_util/include/pico/util/fixed_bitset.h index 2720b7e34..f0ccfe925 100644 --- a/src/common/pico_util/include/pico/util/fixed_bitset.h +++ b/src/common/pico_util/include/pico/util/fixed_bitset.h @@ -102,7 +102,7 @@ static inline uint fixed_bitset_word_size(const fixed_bitset_t *bitset) { * This function will assert if the bitset is not valid. * \param bitset the bitset to check */ -static inline void check_fixed_bitset(const fixed_bitset_t *bitset) { +static inline void check_fixed_bitset(__unused const fixed_bitset_t *bitset) { assert(bitset->word_size == (bitset->size + 31) / 32); } diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index cc92333d3..7a3cd7ae3 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -12,7 +12,7 @@ #include "hardware/dma.h" #include "pico/sync.h" #include "pico/stdlib.h" -#include "pico/util/bitset.h" +#include "pico/util/fixed_bitset.h" #if LIB_PICO_BINARY_INFO #include "pico/binary_info.h" #endif From 925e79b9cc274709647d2c3bc7632ed67d96ed53 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 8 Apr 2026 13:13:29 +0100 Subject: [PATCH 101/127] Remove unused hardware_rosc functions Also allow setting PICO_ALLOW_EXAMPLE_KEYS as a property, and allow it for test/ directory --- .../hardware_rosc/include/hardware/rosc.h | 59 ------------------- src/rp2_common/hardware_rosc/rosc.c | 37 ------------ test/CMakeLists.txt | 2 + tools/CMakeLists.txt | 10 ++++ 4 files changed, 12 insertions(+), 96 deletions(-) diff --git a/src/rp2_common/hardware_rosc/include/hardware/rosc.h b/src/rp2_common/hardware_rosc/include/hardware/rosc.h index b1e664d7a..3ef5180fa 100644 --- a/src/rp2_common/hardware_rosc/include/hardware/rosc.h +++ b/src/rp2_common/hardware_rosc/include/hardware/rosc.h @@ -26,23 +26,6 @@ extern "C" { * more accurate than the ring oscillator. */ -/*! \brief Set frequency of the Ring Oscillator - * \ingroup hardware_rosc - * - * \param code The drive strengths. See the datasheet for information on this value. - */ -void rosc_set_freq(uint32_t code); - -/*! \brief Set range of the Ring Oscillator - * \ingroup hardware_rosc - * - * Frequency range. Frequencies will vary with Process, Voltage & Temperature (PVT). - * Clock output will not glitch when changing the range up one step at a time. - * - * \param range 0x01 Low, 0x02 Medium, 0x03 High, 0x04 Too High. - */ -void rosc_set_range(uint range); - /*! \brief Disable the Ring Oscillator * \ingroup hardware_rosc * @@ -67,29 +50,6 @@ void rosc_set_dormant(void); */ void rosc_restart(void); -/*! \brief Get the next ROSC freq code - * \ingroup hardware_rosc - * - * Given a ROSC freq code, return the next-numerically-higher code. - * Top result bit is set when called on maximum ROSC code. - * - * \param code The current ROSC freq code. - * \return The next ROSC freq code. - */ -uint32_t next_rosc_code(uint32_t code); - -/*! \brief Set the frequency of the Ring Oscillator within a range - * \ingroup hardware_rosc - * - * This function will set the frequency of the Ring Oscillator to the first frequency within the range. - * This will only be accurate if clk_ref is currently running from an accurate source (eg the XOSC). - * - * \param low_mhz The bottom of the range to search for. - * \param high_mhz The top of the range to search for. - * \return The frequency of the Ring Oscillator within the range in MHz, or 0 if no frequency within the range is found. - */ -uint rosc_find_freq_mhz(uint32_t low_mhz, uint32_t high_mhz); - /*! \brief Measure the frequency of the Ring Oscillator * \ingroup hardware_rosc * @@ -99,25 +59,6 @@ uint rosc_find_freq_mhz(uint32_t low_mhz, uint32_t high_mhz); */ uint rosc_measure_freq_khz(void); -/*! \brief Set the output divider of the Ring Oscillator - * \ingroup hardware_rosc - * - * \if rp2040_specific - * div = 0 divides by 32 - * div = 1-31 divides by div - * any other value sets div=31 - * \endif - * - * \if rp2350_specific - * div = 0 divides by 128 - * div = 1-127 divides by div - * any other value sets div=128 - * \endif - * - * \param div The output divider. - */ -void rosc_set_div(uint32_t div); - inline static void rosc_clear_bad_write(void) { hw_clear_bits(&rosc_hw->status, ROSC_STATUS_BADWRITE_BITS); } diff --git a/src/rp2_common/hardware_rosc/rosc.c b/src/rp2_common/hardware_rosc/rosc.c index 9cf9318b9..e1eafdfc9 100644 --- a/src/rp2_common/hardware_rosc/rosc.c +++ b/src/rp2_common/hardware_rosc/rosc.c @@ -10,48 +10,11 @@ #include "hardware/clocks.h" #include "hardware/rosc.h" -// Given a ROSC delay stage code, return the next-numerically-higher code. -// Top result bit is set when called on maximum ROSC code. -uint32_t next_rosc_code(uint32_t code) { - return ((code | 0x08888888u) + 1u) & 0xf7777777u; -} - -uint rosc_find_freq_mhz(uint32_t low_mhz, uint32_t high_mhz) { - // TODO: This could be a lot better - rosc_set_div(1); - for (uint32_t code = 0; code <= 0x77777777u; code = next_rosc_code(code)) { - rosc_set_freq(code); - uint rosc_mhz = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC) / 1000; - if ((rosc_mhz >= low_mhz) && (rosc_mhz <= high_mhz)) { - return rosc_mhz; - } - } - return 0; -} uint rosc_measure_freq_khz(void) { return frequency_count_khz(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC); } -void rosc_set_div(uint32_t div) { -#if PICO_RP2040 - assert(div <= 31); -#else - assert(div <= 127); -#endif - rosc_write(&rosc_hw->div, ROSC_DIV_VALUE_PASS + div); -} - -void rosc_set_freq(uint32_t code) { - rosc_write(&rosc_hw->freqa, (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB) | (code & 0xffffu)); - rosc_write(&rosc_hw->freqb, (ROSC_FREQB_PASSWD_VALUE_PASS << ROSC_FREQB_PASSWD_LSB) | (code >> 16u)); -} - -void rosc_set_range(uint range) { - // Range should use enumvals from the headers and thus have the password correct - rosc_write(&rosc_hw->ctrl, (ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB) | range); -} - void rosc_disable(void) { uint32_t tmp = rosc_hw->ctrl; tmp &= (~ROSC_CTRL_ENABLE_BITS); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2943a8bfc..453951a62 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,7 @@ add_subdirectory(pico_test) +set_directory_properties(PROPERTIES PICO_ALLOW_EXAMPLE_KEYS 1) + add_subdirectory(pico_stdlib_test) add_subdirectory(pico_stdio_test) add_subdirectory(pico_time_test) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 6849c1778..d9c8b2dd5 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -107,6 +107,12 @@ define_property(TARGET BRIEF_DOCS "Ensure a load map is added" FULL_DOCS "Ensure a load map is added" ) +define_property(TARGET + PROPERTY PICO_ALLOW_EXAMPLE_KEYS + INHERITED + BRIEF_DOCS "Allow use of example keys" + FULL_DOCS "Allow use of example keys" +) # Check pioasm is installed, or build it if not installed function(pico_init_pioasm) @@ -648,6 +654,10 @@ function(picotool_postprocess_binary TARGET) PICOTOOL_PROCESSING_CONFIGURED true ) + if (NOT DEFINED PICO_ALLOW_EXAMPLE_KEYS) + get_target_property(PICO_ALLOW_EXAMPLE_KEYS ${TARGET} PICO_ALLOW_EXAMPLE_KEYS) + endif() + # PICO_CMAKE_CONFIG: PICO_ALLOW_EXAMPLE_KEYS, Don't raise a warning when using default signing/encryption keys, type=bool, default=0, group=build if (NOT PICO_ALLOW_EXAMPLE_KEYS) picotool_check_default_keys(${TARGET}) From 032be3fc10cc1e17154c794012e1cc3ef526fae4 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 8 Apr 2026 13:20:17 +0100 Subject: [PATCH 102/127] Update example privateaes.bin file Use a key, rather than a key share, to prevent warnings about hamming weights when building hello_sleep_encrypted Keep old file too, for picotool_check_default_keys --- tools/CMakeLists.txt | 1 + tools/example_keys/privateaes.bin | Bin 128 -> 32 bytes tools/example_keys/privateaes_old.bin | Bin 0 -> 128 bytes 3 files changed, 1 insertion(+) create mode 100644 tools/example_keys/privateaes_old.bin diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index d9c8b2dd5..e8e0bd27d 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -221,6 +221,7 @@ function(picotool_check_default_keys TARGET) picotool_compare_keys(${TARGET} ${picotool_sigfile} private.pem "signing") get_target_property(picotool_aesfile ${TARGET} PICOTOOL_AESFILE) picotool_compare_keys(${TARGET} ${picotool_aesfile} privateaes.bin "encryption") + picotool_compare_keys(${TARGET} ${picotool_aesfile} privateaes_old.bin "encryption") get_target_property(picotool_enc_sigfile ${TARGET} PICOTOOL_ENC_SIGFILE) picotool_compare_keys(${TARGET} ${picotool_enc_sigfile} private.pem "encrypted signing") endfunction() diff --git a/tools/example_keys/privateaes.bin b/tools/example_keys/privateaes.bin index 21a47756d7b947b1e8a7c3a74b0ef5edc3984f87..533d79266aef638f0d6b46d802bb3ee7eeeee85c 100644 GIT binary patch literal 32 qcmV+*0N?-02300uj&6@wq{#_77}A@P%@z~0b)C4ehnJ#qtLX6SJ`gYf literal 128 zcmV-`0Du26w%8aWE_-~VvA2+WFG12#wF6?-Aq=&R7v|M#4Tp^@bfmhu6m^K31uZgB z!8HkZyKTa|re2kzDKa!$EYtX1;$I`{C#21=j`VJnh8dGO*q3D~C0Auh1OCS8i=%!k iQ-EmQ1rQg?!>9y}60g}wscn#avtv&-#Q?Q&bmp4XE<5l5 diff --git a/tools/example_keys/privateaes_old.bin b/tools/example_keys/privateaes_old.bin new file mode 100644 index 0000000000000000000000000000000000000000..21a47756d7b947b1e8a7c3a74b0ef5edc3984f87 GIT binary patch literal 128 zcmV-`0Du26w%8aWE_-~VvA2+WFG12#wF6?-Aq=&R7v|M#4Tp^@bfmhu6m^K31uZgB z!8HkZyKTa|re2kzDKa!$EYtX1;$I`{C#21=j`VJnh8dGO*q3D~C0Auh1OCS8i=%!k iQ-EmQ1rQg?!>9y}60g}wscn#avtv&-#Q?Q&bmp4XE<5l5 literal 0 HcmV?d00001 From bedcb6468532d785638810d939d1f5a3c4e719b4 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 21 Apr 2026 14:12:47 +0100 Subject: [PATCH 103/127] Fix fixed_bitset_is_empty Would always return true for bitsets of word_size 1 --- src/common/pico_util/fixed_bitset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/pico_util/fixed_bitset.c b/src/common/pico_util/fixed_bitset.c index 7e46ccd6d..39f15bc35 100644 --- a/src/common/pico_util/fixed_bitset.c +++ b/src/common/pico_util/fixed_bitset.c @@ -21,6 +21,6 @@ bool fixed_bitset_is_empty(fixed_bitset_t *bitset) { if (bitset->words[i]) return false; } // we don't guarantee that bits above the size aren't set, so mask them off - return !(i && (bitset->words[i] << (32u -(bitset->size & 31u)))); + return !(bitset->words[i] << (32u -(bitset->size & 31u))); } From eff5d8191577856729cc874aad527465bf709645 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 21 Apr 2026 14:18:16 +0100 Subject: [PATCH 104/127] Review fixups low_power_xx_until_pin_state -> low_power_xx_until_gpio_pin_state Make internal functions static in low_power.c fixed_bitset_type_t -> fixed_bitset_type in usage example --- .../include/pico/util/fixed_bitset.h | 2 +- .../pico_low_power/include/pico/low_power.h | 12 +++---- src/rp2_common/pico_low_power/low_power.c | 33 ++++++++++--------- test/hello_sleep/hello_sleep_gpio.c | 10 +++--- 4 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/common/pico_util/include/pico/util/fixed_bitset.h b/src/common/pico_util/include/pico/util/fixed_bitset.h index f0ccfe925..01418d566 100644 --- a/src/common/pico_util/include/pico/util/fixed_bitset.h +++ b/src/common/pico_util/include/pico/util/fixed_bitset.h @@ -30,7 +30,7 @@ typedef struct { * \ingroup fixed_bitset * This macro is used to declare the type of a fixed-size bitset. It is used as follows: * ``` - * typedef fixed_bitset_type_t(17) my_bitset_t; + * typedef fixed_bitset_type(17) my_bitset_t; * ``` * will define a new bitset type called `my_bitset_t` that can hold 17 boolean values. * diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index c444972f7..79ad3f588 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -116,7 +116,7 @@ static inline int low_power_sleep_until_default_timer(absolute_time_t until, con } -/*! \brief Sleep until pin state changes +/*! \brief Sleep until GPIO pin state changes * \ingroup pico_low_power * Sleep until the given GPIO pin changes state. The clocks specified in keep_enabled will be kept enabled during sleep. * If exclusive is true, only the GPIO interrupt will be listened for, otherwise other interrupts will also be listened for. @@ -128,7 +128,7 @@ static inline int low_power_sleep_until_default_timer(absolute_time_t until, con * \param exclusive Whether to only listen for the GPIO interrupt, or other interrupts. * \return 0 on success, non-zero on error. */ -int low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_bitset_t *keep_enabled, bool exclusive); +int low_power_sleep_until_gpio_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_bitset_t *keep_enabled, bool exclusive); /*! \brief Go dormant until time using AON timer * \ingroup pico_low_power @@ -149,7 +149,7 @@ int low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, const c */ int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_source_t dormant_clock_source, uint src_hz, uint gpio_pin, const clock_dest_bitset_t *keep_enabled); -/*! \brief Go dormant until pin state changes +/*! \brief Go dormant until GPIO pin state changes * \ingroup pico_low_power * Go dormant until the given GPIO pin changes state. * The clocks specified in keep_enabled will be kept enabled during dormant, but XOSC and ROSC will be stopped. @@ -167,7 +167,7 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_sourc * \param keep_enabled The clocks to keep enabled during dormant. * \return 0 on success, non-zero on error. */ -int low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_bitset_t *keep_enabled); +int low_power_dormant_until_gpio_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_bitset_t *keep_enabled); #if HAS_POWMAN_TIMER /*! \brief Go to Pstate until time using AON timer @@ -188,7 +188,7 @@ int low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, dorma */ int low_power_pstate_until_aon_timer(absolute_time_t until, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func); -/*! \brief Go to Pstate until pin state changes +/*! \brief Go to Pstate until GPIO pin state changes * \ingroup pico_low_power * Go to Pstate until the given GPIO pin changes state. The function specified in resume_func will be called on reboot, * with the low power Pstate passed to it. @@ -204,7 +204,7 @@ int low_power_pstate_until_aon_timer(absolute_time_t until, pstate_bitset_t *pst * \param resume_func The function to call on reboot. * \return 0 on success, non-zero on error. */ -int low_power_pstate_until_pin_state(uint gpio_pin, bool edge, bool high, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func); +int low_power_pstate_until_gpio_pin_state(uint gpio_pin, bool edge, bool high, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func); /*! \brief Get Pstate which keeps persistent data powered on * \ingroup pico_low_power diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 91114db53..14d3ccbed 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -118,7 +118,7 @@ static void post_pstate_change(void) { } #endif -void low_power_enable_processor_deep_sleep(void) { +static void low_power_enable_processor_deep_sleep(void) { // Enable deep sleep at the proc #ifdef __riscv uint32_t bits = RVCSR_MSLEEP_POWERDOWN_BITS; @@ -132,7 +132,7 @@ void low_power_enable_processor_deep_sleep(void) { #endif } -void low_power_disable_processor_deep_sleep(void) { +static void low_power_disable_processor_deep_sleep(void) { #ifdef __riscv riscv_clear_csr(RVCSR_MSLEEP_OFFSET, RVCSR_MSLEEP_POWERDOWN_BITS | RVCSR_MSLEEP_DEEPSLEEP_BITS); #else @@ -276,7 +276,7 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, return 0; } -int low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, +int low_power_sleep_until_gpio_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_bitset_t *keep_enabled, bool exclusive) { event_happened = false; @@ -325,7 +325,7 @@ int low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high, // In order to go into dormant mode we need to be running from a stoppable clock source: // either the xosc or rosc with no PLLs running. This means we disable the USB and ADC clocks // and all PLLs -void low_power_setup_clocks_for_dormant(dormant_clock_source_t dormant_source) { +static void low_power_setup_clocks_for_dormant(dormant_clock_source_t dormant_source) { prepare_for_clock_switch(); uint clk_ref_src_hz; @@ -415,7 +415,7 @@ void low_power_setup_clocks_for_dormant(dormant_clock_source_t dormant_source) { } //To be called after waking up from sleep/dormant mode to restore system clocks properly -void low_power_wake_from_dormant(void) { +static void low_power_wake_from_dormant(void) { //Re-enable the ring oscillator, which will essentially kickstart the proc rosc_restart(); @@ -426,7 +426,7 @@ void low_power_wake_from_dormant(void) { post_clock_switch(); } -void low_power_go_dormant(dormant_clock_source_t dormant_clock_source) { +static void low_power_go_dormant(dormant_clock_source_t dormant_clock_source) { assert( dormant_clock_source == DORMANT_CLOCK_SOURCE_XOSC || dormant_clock_source == DORMANT_CLOCK_SOURCE_ROSC #if !PICO_RP2040 @@ -445,6 +445,10 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_source_t dormant_clock_source, uint src_hz, uint gpio_pin, const clock_dest_bitset_t *keep_enabled) { + if (!aon_timer_is_running()) { + return PICO_ERROR_PRECONDITION_NOT_MET; + } + low_power_setup_clocks_for_dormant(dormant_clock_source); clock_dest_bitset_t local_keep_enabled; @@ -489,7 +493,7 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, return 0; } -int low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, +int low_power_dormant_until_gpio_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_bitset_t *keep_enabled) { @@ -534,13 +538,7 @@ int low_power_dormant_until_pin_state(uint gpio_pin, bool edge, bool high, extern unsigned char __persistent_data_start__[]; extern unsigned char __persistent_data_end__[]; -int low_power_pstate_set(pstate_bitset_t *pstate) { - invalid_params_if(PICO_LOW_POWER, !pstate_bitset_is_set(pstate, POWMAN_POWER_DOMAIN_SWITCHED_CORE)); - - return powman_set_power_state(pstate_bitset_to_powman_power_state(pstate)); -} - -pstate_bitset_t *low_power_pstate_get(pstate_bitset_t *pstate) { +static pstate_bitset_t *low_power_pstate_get(pstate_bitset_t *pstate) { pstate_bitset_from_powman_power_state(pstate, powman_get_power_state()); return pstate; } @@ -570,7 +568,7 @@ pstate_bitset_t *low_power_persistent_pstate_get(pstate_bitset_t *pstate) { return pstate; } -int low_power_go_pstate(pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func) { +static int low_power_go_pstate(pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func) { pstate_bitset_t default_pstate = pstate_bitset_none(); if (pstate == NULL) { pstate = &default_pstate; @@ -613,12 +611,15 @@ int low_power_go_pstate(pstate_bitset_t *pstate, low_power_pstate_resume_func re } int low_power_pstate_until_aon_timer(absolute_time_t until, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func) { + if (!aon_timer_is_running()) { + return PICO_ERROR_PRECONDITION_NOT_MET; + } powman_enable_alarm_wakeup_at_ms(to_ms_since_boot(until)); return low_power_go_pstate(pstate, resume_func); } -int low_power_pstate_until_pin_state(uint gpio_pin, bool edge, bool high, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func) { +int low_power_pstate_until_gpio_pin_state(uint gpio_pin, bool edge, bool high, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func) { powman_enable_gpio_wakeup(0, gpio_pin, edge, high); return low_power_go_pstate(pstate, resume_func); diff --git a/test/hello_sleep/hello_sleep_gpio.c b/test/hello_sleep/hello_sleep_gpio.c index 00492d284..9c2c20324 100644 --- a/test/hello_sleep/hello_sleep_gpio.c +++ b/test/hello_sleep/hello_sleep_gpio.c @@ -87,7 +87,7 @@ int main() { printf("Going to sleep until GPIO wakeup\n"); - low_power_sleep_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, NULL, true); + low_power_sleep_until_gpio_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, NULL, true); printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); @@ -102,7 +102,7 @@ int main() { clock_dest_bitset_add(&keep_enabled, CLK_DEST_REF_TICKS); #endif - low_power_sleep_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, &keep_enabled, false); + low_power_sleep_until_gpio_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, &keep_enabled, false); printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); @@ -119,16 +119,16 @@ int main() { printf("Going DORMANT until GPIO wakeup\n"); - low_power_dormant_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, DORMANT_CLOCK_SOURCE_ROSC, NULL); + low_power_dormant_until_gpio_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, DORMANT_CLOCK_SOURCE_ROSC, NULL); printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); #if HAS_POWMAN_TIMER printf("Going to PSTATE until GPIO wakeup\n"); - ret = low_power_pstate_until_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, NULL, pstate_resume_func); + ret = low_power_pstate_until_gpio_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, NULL, pstate_resume_func); - printf("%d low_power_pstate_until_pin_state returned\n", ret); + printf("%d low_power_pstate_until_gpio_pin_state returned\n", ret); while (true) { printf("Waiting\n"); busy_wait_ms(1000); From c8f755a6d284a46a60b52fdcfd876f8cce47d2d9 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 21 Apr 2026 14:27:18 +0100 Subject: [PATCH 105/127] Ensure debugger does not prevent pstate Call `powman_set_debug_power_request_ignored(true)` in `low_power_go_pstate`, to prevent debugger keeping the chip running when it's supposed to power down --- src/rp2_common/pico_low_power/low_power.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 14d3ccbed..95df904f8 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -595,6 +595,9 @@ static int low_power_go_pstate(pstate_bitset_t *pstate, low_power_pstate_resume_ powman_hw->scratch[6] = pstate_bitset_to_powman_power_state(pstate); powman_hw->scratch[7] = (uint32_t)resume_func; + // Ensure debugger does not prevent power down + powman_set_debug_power_request_ignored(true); + // Switch to required power state int rc = powman_set_power_state(pstate_bitset_to_powman_power_state(pstate)); if (rc != PICO_OK) { From 42c5ae721d08bba7071db3cb2edf94dcdb6f2302 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 21 Apr 2026 15:27:03 +0100 Subject: [PATCH 106/127] Check external source is running before going dormant on RTC --- .../hardware_rtc/include/hardware/rtc.h | 8 +++ src/rp2_common/hardware_rtc/rtc.c | 28 ++++++++- .../pico_low_power/include/pico/low_power.h | 3 + src/rp2_common/pico_low_power/low_power.c | 19 ++---- .../pico_runtime_init/CMakeLists.txt | 3 + .../pico_runtime_init/runtime_init_clocks.c | 12 +--- test/hello_sleep/hello_sleep.c | 58 ++++++++++++++----- 7 files changed, 93 insertions(+), 38 deletions(-) diff --git a/src/rp2_common/hardware_rtc/include/hardware/rtc.h b/src/rp2_common/hardware_rtc/include/hardware/rtc.h index 6b5576c7f..7457f72d4 100644 --- a/src/rp2_common/hardware_rtc/include/hardware/rtc.h +++ b/src/rp2_common/hardware_rtc/include/hardware/rtc.h @@ -10,6 +10,12 @@ #include "pico.h" #if HAS_RP2040_RTC #include "hardware/structs/rtc.h" + +// The RTC clock frequency is 48MHz divided by power of 2 (to ensure an integer +// division ratio will be used in the clocks block). A divisor of 1024 generates +// an RTC clock tick of 46875Hz. This frequency is relatively close to the +// customary 32 or 32.768kHz 'slow clock' crystals and provides good timing resolution. +#define RTC_CLOCK_FREQ_HZ (USB_CLK_HZ / 1024) #endif /** \file hardware/rtc.h @@ -93,6 +99,8 @@ void rtc_disable_alarm(void); /*! \brief Run the RTC from an external clock source through GPIO * \ingroup hardware_sleep * + * \note This function will return false if the external clock source is not running. + * * \param src_hz The frequency of the external clock source * \param gpio_pin The input pin providing the external clock (GP20 or GP22) * \return true if it is possible to run the RTC from the external clock frequency, false otherwise. diff --git a/src/rp2_common/hardware_rtc/rtc.c b/src/rp2_common/hardware_rtc/rtc.c index faba578c3..56df707cd 100644 --- a/src/rp2_common/hardware_rtc/rtc.c +++ b/src/rp2_common/hardware_rtc/rtc.c @@ -190,5 +190,31 @@ void rtc_disable_alarm(void) { } bool rtc_run_from_external_source(uint32_t src_hz, uint gpio_pin) { - return clock_configure_gpin(clk_rtc, gpio_pin, src_hz, 46875); + bool success = clock_configure_gpin(clk_rtc, gpio_pin, src_hz, RTC_CLOCK_FREQ_HZ); + if (success) { + // Ensure external source is actually running + uint32_t rtc_freq = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_RTC); + if (rtc_freq < ((RTC_CLOCK_FREQ_HZ / KHZ) - 1) || rtc_freq > ((RTC_CLOCK_FREQ_HZ / KHZ) + 1)) { + // Frequency is not within 1kHz of the expected frequency + success = false; + // reconfigure the clock to the default configuration + #if (USB_CLK_HZ % RTC_CLOCK_FREQ_HZ == 0) + // this doesn't pull in 64 bit arithmetic + clock_configure_int_divider(clk_rtc, + 0, // No GLMUX + CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, + USB_CLK_HZ, + USB_CLK_HZ / RTC_CLOCK_FREQ_HZ); + + #else + clock_configure(clk_rtc, + 0, // No GLMUX + CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, + USB_CLK_HZ, + RTC_CLOCK_FREQ_HZ); + + #endif + } + } + return success; } \ No newline at end of file diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 79ad3f588..1ee535fae 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -62,6 +62,9 @@ extern "C" { #endif #include "hardware/clocks.h" +#if HAS_RP2040_RTC +#include "hardware/rtc.h" +#endif #if HAS_POWMAN_TIMER #include "hardware/powman.h" #endif diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 95df904f8..34b42299d 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -382,16 +382,7 @@ static void low_power_setup_clocks_for_dormant(dormant_clock_source_t dormant_so #endif #if HAS_RP2040_RTC - // CLK RTC = ideally XOSC (12MHz) / 256 = 46875Hz but could be rosc - uint clk_rtc_src = (dormant_source == DORMANT_CLOCK_SOURCE_XOSC) ? - CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC : - CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH; - - clock_configure(clk_rtc, - 0, // No GLMUX - clk_rtc_src, - clk_sys_src_hz, - 46875); + // RTC should already be configured to run from the external source #endif // CLK PERI = clk_sys. Used as reference clock for Peripherals. No dividers so just select and enable @@ -449,14 +440,14 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, return PICO_ERROR_PRECONDITION_NOT_MET; } - low_power_setup_clocks_for_dormant(dormant_clock_source); - clock_dest_bitset_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); #if PICO_RP2040 // The RTC must be run from an external source, since the dormant source will be inactive - rtc_run_from_external_source(src_hz, gpio_pin); + if (!rtc_run_from_external_source(src_hz, gpio_pin)) { + return PICO_ERROR_PRECONDITION_NOT_MET; + } clock_dest_bitset_add(&local_keep_enabled, CLK_DEST_RTC_RTC); #elif PICO_RP2350 ((void)src_hz); @@ -471,6 +462,8 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, #error Unknown processor #endif + low_power_setup_clocks_for_dormant(dormant_clock_source); + // todo catch race condition here (or just plain in the past) struct timespec ts; us_to_timespec(to_us_since_boot(until), &ts); diff --git a/src/rp2_common/pico_runtime_init/CMakeLists.txt b/src/rp2_common/pico_runtime_init/CMakeLists.txt index 60d1833e0..f8f1daa6a 100644 --- a/src/rp2_common/pico_runtime_init/CMakeLists.txt +++ b/src/rp2_common/pico_runtime_init/CMakeLists.txt @@ -21,6 +21,9 @@ endif() if (TARGET hardware_vreg) pico_mirrored_target_link_libraries(pico_runtime_init INTERFACE hardware_vreg) endif() +if (TARGET hardware_rtc) + pico_mirrored_target_link_libraries(pico_runtime_init INTERFACE hardware_rtc) +endif() # pico/runtime_init.h includes pico/runtime.h target_link_libraries(pico_runtime_init_headers INTERFACE pico_runtime_headers) \ No newline at end of file diff --git a/src/rp2_common/pico_runtime_init/runtime_init_clocks.c b/src/rp2_common/pico_runtime_init/runtime_init_clocks.c index a86fe8052..b812843cf 100644 --- a/src/rp2_common/pico_runtime_init/runtime_init_clocks.c +++ b/src/rp2_common/pico_runtime_init/runtime_init_clocks.c @@ -13,16 +13,8 @@ #include "hardware/timer.h" #include "hardware/vreg.h" #include "hardware/xosc.h" -#if PICO_RP2040 -#include "hardware/regs/rtc.h" -#endif - -#if PICO_RP2040 -// The RTC clock frequency is 48MHz divided by power of 2 (to ensure an integer -// division ratio will be used in the clocks block). A divisor of 1024 generates -// an RTC clock tick of 46875Hz. This frequency is relatively close to the -// customary 32 or 32.768kHz 'slow clock' crystals and provides good timing resolution. -#define RTC_CLOCK_FREQ_HZ (USB_CLK_HZ / 1024) +#if HAS_RP2040_RTC +#include "hardware/rtc.h" #endif static void start_all_ticks(void) { diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index bea59ee02..31faff33f 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -17,6 +17,13 @@ #define RTC_GPIO 22 // must support clock input, see the GPIO function table in the datasheet. +// Set to 1 to continue after an error, 0 to exit +#if 0 +#define EXIT_TEST +#else +#define EXIT_TEST return -1 +#endif + bool repeater(repeating_timer_t *timer) { if (aon_timer_is_running()) { printf(" Repeating timer %d at %dms (aon: %dms)", *(uint32_t*)timer->user_data, to_ms_since_boot(get_absolute_time()), to_ms_since_boot(aon_timer_get_absolute_time())); @@ -142,12 +149,16 @@ int main() { start_time = get_absolute_time(); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); - low_power_sleep_until_timer(timer_hw, wakeup_time, NULL, true); + ret = low_power_sleep_until_timer(timer_hw, wakeup_time, NULL, true); + if (ret != PICO_OK) { + printf("ERROR: %d returned by low_power_sleep_until_timer\n", ret); + EXIT_TEST; + } diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); printf("Woken up now @%dus since target\n", (int)diff); if (diff < 0) { printf("ERROR: Woke up too soon\n"); - return -1; + EXIT_TEST; } printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); @@ -159,12 +170,16 @@ int main() { start_time = get_absolute_time(); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); - low_power_sleep_until_timer(timer_hw, wakeup_time, NULL, false); + ret = low_power_sleep_until_timer(timer_hw, wakeup_time, NULL, false); + if (ret != PICO_OK) { + printf("ERROR: %d returned by low_power_sleep_until_timer\n", ret); + EXIT_TEST; + } diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); printf("Woken up now @%dus since target\n", (int)diff); if (diff < 0) { printf("ERROR: Woke up too soon\n"); - return -1; + EXIT_TEST; } printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); @@ -180,13 +195,22 @@ int main() { aon_timer_start(&ts); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); - low_power_dormant_until_aon_timer(wakeup_time, + ret = low_power_dormant_until_aon_timer(wakeup_time, #if PICO_RP2040 - DORMANT_CLOCK_SOURCE_XOSC, 46875, + DORMANT_CLOCK_SOURCE_XOSC, RTC_CLOCK_FREQ_HZ, #else DORMANT_CLOCK_SOURCE_LPOSC, XOSC_HZ, #endif RTC_GPIO, NULL); + if (ret != PICO_OK) { + printf("ERROR: %d returned by low_power_dormant_until_aon_timer\n", ret); + #if PICO_RP2040 + if (ret == PICO_ERROR_PRECONDITION_NOT_MET) { + printf("ERROR: RTC clock source is not running - connect a device running rtc_clksrc to GPIO %d\n", RTC_GPIO); + } + #endif + EXIT_TEST; + } // need to use the AON timer for checking time, since the other timer is unclocked diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); if (diff > -1000000 @@ -214,7 +238,7 @@ int main() { if (my_number != 12345) { printf("ERROR: my_number is %d not 12345 - initialisation issue?\n", my_number); - return -1; + EXIT_TEST; } my_number = 67890; @@ -223,7 +247,10 @@ int main() { wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); ret = low_power_pstate_until_aon_timer(wakeup_time, NULL, pstate_resume_func); - printf("%d low_power_pstate_until_aon_timer returned\n", ret); + if (ret != PICO_OK) { + printf("ERROR: %d returned by low_power_pstate_until_aon_timer\n", ret); + EXIT_TEST; + } while (true) { printf("Waiting\n"); busy_wait_ms(1000); @@ -242,12 +269,12 @@ int main() { #endif ) { printf("ERROR: Woke up more than %d seconds late\n", (int)(diff / 1000000)); - return -1; + EXIT_TEST; } if (my_number != 67890) { printf("ERROR: my_number is %d not 67890 - SRAM has been re-loaded\n", my_number); - return -1; + EXIT_TEST; } else { printf("my_number in sram: %d\n", my_number); } @@ -269,7 +296,10 @@ int main() { pstate = pstate_bitset_none(); ret = low_power_pstate_until_aon_timer(wakeup_time, &pstate, pstate_resume_func); - printf("%d low_power_pstate_until_aon_timer returned\n", ret); + if (ret != PICO_OK) { + printf("ERROR: %d returned by low_power_pstate_until_aon_timer\n", ret); + EXIT_TEST; + } while (true) { printf("Waiting\n"); busy_wait_ms(1000); @@ -290,12 +320,12 @@ int main() { #endif ) { printf("ERROR: Woke up more than %d seconds late\n", (int)(diff / 1000000)); - return -1; + EXIT_TEST; } if (my_number != 34567) { printf("ERROR: my_number is %d not 34567 - SRAM has not been re-loaded\n", my_number); - return -1; + EXIT_TEST; } else { printf("my_number in sram: %d\n", my_number); } @@ -305,7 +335,7 @@ int main() { if (powman_hw->scratch[3] != 2) { printf("ERROR: number of POWMAN reboots was %d not 2\n", powman_hw->scratch[3]); - return -1; + EXIT_TEST; } #endif From ff432147eee75015ec15cd751ec793ccaadd93db Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 22 Apr 2026 09:35:40 +0100 Subject: [PATCH 107/127] Delete unused code in fixed_bitset.h --- .../include/pico/util/fixed_bitset.h | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/src/common/pico_util/include/pico/util/fixed_bitset.h b/src/common/pico_util/include/pico/util/fixed_bitset.h index 01418d566..7eea75734 100644 --- a/src/common/pico_util/include/pico/util/fixed_bitset.h +++ b/src/common/pico_util/include/pico/util/fixed_bitset.h @@ -242,41 +242,6 @@ static inline bool fixed_bitset_equal(const fixed_bitset_t *bitset1, const fixed return __builtin_memcmp(bitset1->words, bitset2->words, bitset1->word_size * sizeof(uint32_t)) == 0; } -#if 0 // not currently used -typedef uint32_t tiny_ordinal_list_t; // ordinals must be 0->255 -typedef uint64_t small_ordinal_list_t; // ordinals must be 0->255 -#define ordinal_list_empty() 0 -#define ordinal_list_of1(v) (1u | ((v) << 8)) -#define ordinal_list_of2(v1, v2) (2u | ((v1) << 8) | ((v2) << 16)) -#define ordinal_list_of3(v1, v2, v3) (3u | ((v1) << 8) | ((v2) << 16) | (((v3) << 24))) -#define ordinal_list_of4(v1, v2, v3, v4) (4u | ((v1) << 8) | ((v2) << 16) | (((v3) << 24)) | (((uint64_t)(v4)) << 32)) -#define ordinal_list_of5(v1, v2, v3, v4, v5) (5u | ((v1) << 8) | ((v2) << 16) | (((v3) << 24)) | (((uint64_t)((v4) | ((v5)<<8u))) << 32)) - -#define small_ordinal_list_foreach(bitarray, x) ({ \ - for(uint _i=1;_i<=((bitarray)&0xffu);_i++) { \ - uint bit = (uint8_t)((bitarray) >> (8 * _i)); \ - x; \ - } \ -}) - -static inline fixed_bitset_t *fixed_bitset_set_bits(fixed_bitset_t *bitset, small_ordinal_list_t list) { - small_ordinal_list_foreach(list, fixed_bitset_set(bitset, bit)); - return bitset; -} - -static inline fixed_bitset_t *fixed_bitset_clear_bits(fixed_bitset_t *bitset, small_ordinal_list_t list) { - small_ordinal_list_foreach(list, fixed_bitset_clear(bitset, bit)); - return bitset; -} - - -#define fixed_bitset_init_with_bits(ptr, type, N, list) ({ \ - /* not this performs checks */ \ - fixed_bitset_init(ptr, type, N, 0); \ - fixed_bitset_set_bits(&(ptr)->bitset, list); \ -}) - -#endif #ifdef __cplusplus } #endif From b38af21dab0c7800c1ec1f0cf7f26b4815d576d0 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 22 Apr 2026 11:29:58 +0100 Subject: [PATCH 108/127] Improve powman timer functions Add new powman_timer_pause function which sets the timer to restart from the current time, rather than the previously set time Use _pause instead of _stop in the powman functions that aren't supposed to change the time Add PICO_POWMAN_CALIBRATE_LPOSC_FROM_OTP (default 1) to use OTP frequency value for the LPOSC frequency, otherwise (or if OTP ECC read is 0) uses the reset value of the registers Only pause & start the timer when it's required due to changing the frequency in _set_1khz_tick_source_xxx_with_hz functions --- .../hardware_powman/include/hardware/powman.h | 20 +++++- src/rp2_common/hardware_powman/powman.c | 66 ++++++++++++++----- 2 files changed, 67 insertions(+), 19 deletions(-) diff --git a/src/rp2_common/hardware_powman/include/hardware/powman.h b/src/rp2_common/hardware_powman/include/hardware/powman.h index 3c195aa94..d31228d83 100644 --- a/src/rp2_common/hardware_powman/include/hardware/powman.h +++ b/src/rp2_common/hardware_powman/include/hardware/powman.h @@ -27,14 +27,21 @@ extern "C" { #define PARAM_ASSERTIONS_ENABLED_HARDWARE_POWMAN 0 #endif +// PICO_CONFIG: PICO_POWMAN_CALIBRATE_LPOSC_FROM_OTP, Use the OTP calibration value for the low power oscillator frequency, type=bool, default=1, group=hardware_powman +#ifndef PICO_POWMAN_CALIBRATE_LPOSC_FROM_OTP +#define PICO_POWMAN_CALIBRATE_LPOSC_FROM_OTP 1 +#endif + /*! \brief Use the ~32KHz low power oscillator as the powman timer source * \ingroup hardware_powman + * \note The frequency is set to the value stored in the OTP, or the reset value if + * there is no OTP value set or PICO_POWMAN_CALIBRATE_LPOSC_FROM_OTP is 0 */ void powman_timer_set_1khz_tick_source_lposc(void); /*! \brief Use the low power oscillator (specifying frequency) as the powman timer source * \ingroup hardware_powman - * \param lposc_freq_hz specify an exact lposc freq to trim it + * \param lposc_freq_hz specify an exact lposc freq to trim it, or 0 to use the reset values */ void powman_timer_set_1khz_tick_source_lposc_with_hz(uint32_t lposc_freq_hz); @@ -136,11 +143,22 @@ static inline bool powman_timer_is_running(void) { /*! \brief Stop the powman timer * \ingroup hardware_powman + * \note On the next start, the timer will resume from the last set time, + * so if you want to pause the timer and resume from the current time, you + * should use \ref powman_timer_pause */ static inline void powman_timer_stop(void) { powman_clear_bits(&powman_hw->timer, POWMAN_TIMER_RUN_BITS); } +/*! \brief Pause the powman timer + * \ingroup hardware_powman + */ + static inline void powman_timer_pause(void) { + powman_clear_bits(&powman_hw->timer, POWMAN_TIMER_RUN_BITS); + powman_timer_set_ms(powman_timer_get_ms()); +} + /*! \brief Start the powman timer * \ingroup hardware_powman */ diff --git a/src/rp2_common/hardware_powman/powman.c b/src/rp2_common/hardware_powman/powman.c index 4af59f502..f0899bc92 100644 --- a/src/rp2_common/hardware_powman/powman.c +++ b/src/rp2_common/hardware_powman/powman.c @@ -12,6 +12,9 @@ #include "hardware/gpio.h" #include "hardware/powman.h" +#if PICO_POWMAN_CALIBRATE_LPOSC_FROM_OTP +#include "hardware/regs/otp_data.h" +#endif #ifndef PICO_POWMAN_DEBUG #define PICO_POWMAN_DEBUG 0 @@ -62,20 +65,38 @@ uint64_t powman_timer_get_ms(void) { } void powman_timer_set_1khz_tick_source_lposc(void) { - powman_timer_set_1khz_tick_source_lposc_with_hz(32768); +#if PICO_POWMAN_CALIBRATE_LPOSC_FROM_OTP + uint16_t* lposc_calib_data = (uint16_t*)OTP_DATA_BASE + OTP_DATA_LPOSC_CALIB_ROW; + if (*lposc_calib_data == 0) { + powman_timer_set_1khz_tick_source_lposc_with_hz(0); + } else { + powman_timer_set_1khz_tick_source_lposc_with_hz(*lposc_calib_data); + } +#else + powman_timer_set_1khz_tick_source_lposc_with_hz(0); +#endif } void powman_timer_set_1khz_tick_source_lposc_with_hz(uint32_t lposc_freq_hz) { bool was_running = powman_timer_is_running(); - if (was_running) powman_timer_stop(); - uint32_t lposc_freq_khz = lposc_freq_hz / 1000; - uint32_t lposc_freq_khz_frac16 = (lposc_freq_hz % 1000) * 65536 / 1000; - powman_write(&powman_hw->lposc_freq_khz_int, lposc_freq_khz); - powman_write(&powman_hw->lposc_freq_khz_frac, lposc_freq_khz_frac16); - powman_set_bits(&powman_hw->timer, POWMAN_TIMER_USE_LPOSC_BITS); - if (was_running) { - powman_timer_start(); - while(!(powman_hw->timer & POWMAN_TIMER_USING_LPOSC_BITS)); + uint32_t lposc_freq_khz = lposc_freq_hz == 0 ? POWMAN_LPOSC_FREQ_KHZ_INT_RESET : lposc_freq_hz / 1000; + uint32_t lposc_freq_khz_frac16 = lposc_freq_hz == 0 ? POWMAN_LPOSC_FREQ_KHZ_FRAC_RESET : (lposc_freq_hz % 1000) * 65536 / 1000; + if (lposc_freq_khz != powman_hw->lposc_freq_khz_int || lposc_freq_khz_frac16 != powman_hw->lposc_freq_khz_frac) { + // Frequency change needed, so need to stop the timer, set the frequency, and start the timer with USE_LPOSC + if (was_running) powman_timer_pause(); + powman_write(&powman_hw->lposc_freq_khz_int, lposc_freq_khz); + powman_write(&powman_hw->lposc_freq_khz_frac, lposc_freq_khz_frac16); + powman_set_bits(&powman_hw->timer, POWMAN_TIMER_USE_LPOSC_BITS); + if (was_running) { + powman_timer_start(); + while(!(powman_hw->timer & POWMAN_TIMER_USING_LPOSC_BITS)); + } + } else { + // No frequency change needed, so can just set USE_LPOSC while running + powman_set_bits(&powman_hw->timer, POWMAN_TIMER_USE_LPOSC_BITS); + if (was_running) { + while(!(powman_hw->timer & POWMAN_TIMER_USING_LPOSC_BITS)); + } } } @@ -85,15 +106,24 @@ void powman_timer_set_1khz_tick_source_xosc(void) { void powman_timer_set_1khz_tick_source_xosc_with_hz(uint32_t xosc_freq_hz) { bool was_running = powman_timer_is_running(); - if (was_running) powman_timer_stop(); uint32_t xosc_freq_khz = xosc_freq_hz / 1000; uint32_t xosc_freq_khz_frac16 = (xosc_freq_hz % 1000) * 65536 / 1000; - powman_write(&powman_hw->xosc_freq_khz_int, xosc_freq_khz); - powman_write(&powman_hw->xosc_freq_khz_frac, xosc_freq_khz_frac16); - powman_set_bits(&powman_hw->timer, POWMAN_TIMER_USE_XOSC_BITS); - if (was_running) { - powman_timer_start(); - while(!(powman_hw->timer & POWMAN_TIMER_USING_XOSC_BITS)); + if (xosc_freq_khz != powman_hw->xosc_freq_khz_int || xosc_freq_khz_frac16 != powman_hw->xosc_freq_khz_frac) { + // Frequency change needed, so need to stop the timer, set the frequency, and start the timer with USE_XOSC + if (was_running) powman_timer_pause(); + powman_write(&powman_hw->xosc_freq_khz_int, xosc_freq_khz); + powman_write(&powman_hw->xosc_freq_khz_frac, xosc_freq_khz_frac16); + powman_set_bits(&powman_hw->timer, POWMAN_TIMER_USE_XOSC_BITS); + if (was_running) { + powman_timer_start(); + while(!(powman_hw->timer & POWMAN_TIMER_USING_XOSC_BITS)); + } + } else { + // No frequency change needed, so can just set USE_XOSC while running + powman_set_bits(&powman_hw->timer, POWMAN_TIMER_USE_XOSC_BITS); + if (was_running) { + while(!(powman_hw->timer & POWMAN_TIMER_USING_XOSC_BITS)); + } } } @@ -112,7 +142,7 @@ static inline uint32_t gpio_to_powman_ext_time_ref_source(uint gpio, uint32_t de static void powman_timer_use_gpio(uint32_t gpio, uint32_t use, uint32_t using) { bool was_running = powman_timer_is_running(); - if (was_running) powman_timer_stop(); + if (was_running) powman_timer_pause(); uint32_t source = gpio_to_powman_ext_time_ref_source(gpio, 0); gpio_set_input_enabled(gpio, true); powman_write(&powman_hw->ext_time_ref, source); From 8e813f7ee3e6294c231801a7e9f2cb518cfa937f Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 22 Apr 2026 11:52:15 +0100 Subject: [PATCH 109/127] Fix Bazel build pico_runtime_init now depends on hardware_rtc --- src/rp2_common/BUILD.bazel | 1 + src/rp2_common/hardware_rtc/BUILD.bazel | 2 +- src/rp2_common/pico_runtime_init/BUILD.bazel | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/rp2_common/BUILD.bazel b/src/rp2_common/BUILD.bazel index d5ccf6555..92a23da25 100644 --- a/src/rp2_common/BUILD.bazel +++ b/src/rp2_common/BUILD.bazel @@ -71,6 +71,7 @@ alias( "//src/rp2_common/hardware_base:__pkg__", "//src/rp2_common/hardware_irq:__pkg__", "//src/rp2_common/hardware_pll:__pkg__", + "//src/rp2_common/hardware_rtc:__pkg__", "//src/rp2_common/hardware_vreg:__pkg__", "//src/rp2_common/hardware_watchdog:__pkg__", "//src/rp2_common/hardware_rosc:__pkg__", diff --git a/src/rp2_common/hardware_rtc/BUILD.bazel b/src/rp2_common/hardware_rtc/BUILD.bazel index f239f8d8f..a13d1e4b9 100644 --- a/src/rp2_common/hardware_rtc/BUILD.bazel +++ b/src/rp2_common/hardware_rtc/BUILD.bazel @@ -11,7 +11,7 @@ cc_library( target_compatible_with = ["//bazel/constraint:rp2040"], deps = [ "//src/rp2_common:hardware_structs", - "//src/rp2_common:pico_platform", + "//src/rp2_common:pico_platform_internal", "//src/rp2_common/hardware_clocks", "//src/rp2_common/hardware_irq", "//src/rp2_common/hardware_resets", diff --git a/src/rp2_common/pico_runtime_init/BUILD.bazel b/src/rp2_common/pico_runtime_init/BUILD.bazel index 0af3b23fe..d6108fb1b 100644 --- a/src/rp2_common/pico_runtime_init/BUILD.bazel +++ b/src/rp2_common/pico_runtime_init/BUILD.bazel @@ -18,6 +18,15 @@ cc_library( ], ) +alias( + name = "pico_runtime_init_extra_link", + actual = select({ + "//bazel/constraint:rp2040": "//src/rp2_common/hardware_rtc", + "//conditions:default": "//bazel:empty_cc_lib", + }), + visibility = ["//visibility:private"], +) + cc_library( name = "pico_runtime_init_link", srcs = [ @@ -39,6 +48,7 @@ cc_library( "//src/rp2_common/hardware_vreg", "//src/rp2_common/pico_bootrom", "//src/rp2_common/pico_runtime", + "pico_runtime_init_extra_link", ], alwayslink = True, ) From 4c54ce31241537d9598c1242a28073754afb4860 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 22 Apr 2026 12:18:11 +0100 Subject: [PATCH 110/127] Fixups to low_power.c and low_power.h Replace assertions with invalid_params_if or invalid_params_if_and_return, and fix invalid assertion that event happened when leaving dormant Prevent races on entry to dormant & pstate by defining a minimum time allowed Switch powman_timer back to XOSC after low_power_dormant_until_aon_timer --- .../pico_low_power/include/pico/low_power.h | 14 ++++++++++ src/rp2_common/pico_low_power/low_power.c | 28 ++++++++++++++----- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 1ee535fae..17753e303 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -61,6 +61,20 @@ extern "C" { #define PARAM_ASSERTIONS_ENABLED_PICO_LOW_POWER 0 #endif +// PICO_CONFIG: PICO_LOW_POWER_MIN_DORMANT_TIME_MS, Minimum supported time to spend dormant in milliseconds, type=int, default=2000 on RP2040, 10 otherwise, group=pico_low_power +#ifndef PICO_LOW_POWER_MIN_DORMANT_TIME_MS +#if PICO_RP2040 +#define PICO_LOW_POWER_MIN_DORMANT_TIME_MS 2000 +#else +#define PICO_LOW_POWER_MIN_DORMANT_TIME_MS 10 +#endif +#endif + +// PICO_CONFIG: PICO_LOW_POWER_MIN_PSTATE_TIME_MS, Minimum supported time to spend in Pstate in milliseconds, type=int, default=10, group=pico_low_power +#ifndef PICO_LOW_POWER_MIN_PSTATE_TIME_MS +#define PICO_LOW_POWER_MIN_PSTATE_TIME_MS 10 +#endif + #include "hardware/clocks.h" #if HAS_RP2040_RTC #include "hardware/rtc.h" diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 34b42299d..1106e9e18 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -279,6 +279,7 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, int low_power_sleep_until_gpio_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_bitset_t *keep_enabled, bool exclusive) { + invalid_params_if_and_return(PICO_LOW_POWER, gpio_pin >= NUM_BANK0_GPIOS, PICO_ERROR_INVALID_ARG); event_happened = false; clock_dest_bitset_t local_keep_enabled; @@ -287,7 +288,6 @@ int low_power_sleep_until_gpio_pin_state(uint gpio_pin, bool edge, bool high, add_library_clocks(&local_keep_enabled); // Configure the appropriate IRQ at IO bank 0 - assert(gpio_pin < NUM_BANK0_GPIOS); uint32_t event = 0; @@ -418,7 +418,7 @@ static void low_power_wake_from_dormant(void) { } static void low_power_go_dormant(dormant_clock_source_t dormant_clock_source) { - assert( + invalid_params_if(PICO_LOW_POWER, dormant_clock_source == DORMANT_CLOCK_SOURCE_XOSC || dormant_clock_source == DORMANT_CLOCK_SOURCE_ROSC #if !PICO_RP2040 || dormant_clock_source == DORMANT_CLOCK_SOURCE_LPOSC @@ -440,6 +440,12 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, return PICO_ERROR_PRECONDITION_NOT_MET; } + if (to_ms_since_boot(aon_timer_get_absolute_time()) + PICO_LOW_POWER_MIN_DORMANT_TIME_MS > to_ms_since_boot(until)) { + // Prevent race condition where the timer fires before we can go dormant + // by setting a minimum time for dormant + return PICO_ERROR_INVALID_ARG; + } + clock_dest_bitset_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); @@ -464,11 +470,10 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, low_power_setup_clocks_for_dormant(dormant_clock_source); - // todo catch race condition here (or just plain in the past) struct timespec ts; us_to_timespec(to_us_since_boot(until), &ts); event_happened = false; - aon_timer_enable_alarm(&ts, (aon_timer_alarm_handler_t)low_power_wakeup, true); + aon_timer_enable_alarm(&ts, NULL, true); prepare_for_clock_gating(); // gate clocks @@ -479,10 +484,13 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, //Go dormant low_power_go_dormant(dormant_clock_source); - - assert(event_happened); low_power_wake_from_dormant(); +#if PICO_RP2350 + if (dormant_clock_source == DORMANT_CLOCK_SOURCE_LPOSC) + powman_timer_set_1khz_tick_source_xosc(); +#endif + return 0; } @@ -490,13 +498,14 @@ int low_power_dormant_until_gpio_pin_state(uint gpio_pin, bool edge, bool high, dormant_clock_source_t dormant_clock_source, const clock_dest_bitset_t *keep_enabled) { + invalid_params_if_and_return(PICO_LOW_POWER, gpio_pin >= NUM_BANK0_GPIOS, PICO_ERROR_INVALID_ARG); + low_power_setup_clocks_for_dormant(dormant_clock_source); clock_dest_bitset_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); // Configure the appropriate IRQ at IO bank 0 - assert(gpio_pin < NUM_BANK0_GPIOS); uint32_t event = 0; @@ -610,6 +619,11 @@ int low_power_pstate_until_aon_timer(absolute_time_t until, pstate_bitset_t *pst if (!aon_timer_is_running()) { return PICO_ERROR_PRECONDITION_NOT_MET; } + if (to_ms_since_boot(aon_timer_get_absolute_time()) + PICO_LOW_POWER_MIN_PSTATE_TIME_MS > to_ms_since_boot(until)) { + // Prevent race condition where the timer fires before we can go to pstate + // by setting a minimum time for pstate + return PICO_ERROR_INVALID_ARG; + } powman_enable_alarm_wakeup_at_ms(to_ms_since_boot(until)); return low_power_go_pstate(pstate, resume_func); From 61f1e455b34e1cd4ad03c3e3a9c398f9bf13d891 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 22 Apr 2026 12:45:34 +0100 Subject: [PATCH 111/127] Add more sizes to fixed_bitset_test Add 4 and 77 sized bitsets --- test/fixed_bitset_test/fixed_bitset_test.c | 62 ++++++++++++---------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/test/fixed_bitset_test/fixed_bitset_test.c b/test/fixed_bitset_test/fixed_bitset_test.c index fe09df992..28f3ff1ff 100644 --- a/test/fixed_bitset_test/fixed_bitset_test.c +++ b/test/fixed_bitset_test/fixed_bitset_test.c @@ -11,38 +11,46 @@ #define CHECK(b, message, ...) ({ if (!(b)) { printf("FAILED: " message "\n", ##__VA_ARGS__); exit(1); } }) +typedef fixed_bitset_type(4) bitset4_t; typedef fixed_bitset_type(47) bitset47_t; +typedef fixed_bitset_type(77) bitset77_t; int main() { stdio_init_all(); - bitset47_t b47; - fixed_bitset_init(&b47, bitset47_t, 47, 0); - for (int i=0;i<47;i++) { - CHECK(!fixed_bitset_get(&b47.bitset, i), "Bit %d should be clear", i); - } +#define FIXED_BITSET_TESTS(name, type, n)\ + type name;\ + fixed_bitset_init(&name, type, n, 0);\ + for (int i=0;i=0;i--) {\ + CHECK(fixed_bitset_get(&name.bitset, i), "Bit %d should be set", i);\ + fixed_bitset_clear(&name.bitset, i);\ + CHECK(!fixed_bitset_get(&name.bitset, i), "Bit %d should be clear", i);\ + CHECK(!i == fixed_bitset_is_empty(&name.bitset), "Bitset should be empty once last bit is cleared");\ + }\ + \ + fixed_bitset_init(&name, type, n, 1);\ + for (int i=0;i=0;i--) {\ + CHECK(fixed_bitset_get(&name.bitset, i), "Bit %d should be set", i);\ + fixed_bitset_clear(&name.bitset, i);\ + CHECK(!fixed_bitset_get(&name.bitset, i), "Bit %d should be clear", i);\ + CHECK(!i == fixed_bitset_is_empty(&name.bitset), "Bitset should be empty once last bit is cleared");\ + }\ + + FIXED_BITSET_TESTS(b4, bitset4_t, 4); + FIXED_BITSET_TESTS(b47, bitset47_t, 47); + FIXED_BITSET_TESTS(b77, bitset77_t, 77); - fixed_bitset_init(&b47, bitset47_t, 47, 1); - for (int i=0;i<47;i++) { - CHECK(fixed_bitset_get(&b47.bitset, i), "Bit %d should be set", i); - } - - for (int i=46;i>=0;i--) { - CHECK(fixed_bitset_get(&b47.bitset, i), "Bit %d should be set", i); - fixed_bitset_clear(&b47.bitset, i); - CHECK(!fixed_bitset_get(&b47.bitset, i), "Bit %d should be clear", i); - CHECK(!i == fixed_bitset_is_empty(&b47.bitset), "Bitset should be empty once last bit is cleared"); - } - - fixed_bitset_init(&b47, bitset47_t, 47, 1); - for (int i=0;i<47;i++) { - CHECK(fixed_bitset_get(&b47.bitset, i), "Bit %d should be set", i); - } - for (int i=0;i<47;i++) { - CHECK(fixed_bitset_get(&b47.bitset, i), "Bit %d should be set", i); - fixed_bitset_clear(&b47.bitset, i); - CHECK(!fixed_bitset_get(&b47.bitset, i), "Bit %d should be clear", i); - CHECK((i==46) == fixed_bitset_is_empty(&b47.bitset), "Bitset should be empty once last bit is cleared"); - } puts("PASSED"); } \ No newline at end of file From 633628fff75323e0e79a1df7533f7fcb16366c0c Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 22 Apr 2026 14:08:22 +0100 Subject: [PATCH 112/127] Fix setting PICO_OPAQUE_ABSOLUTE_TIME_T --- src/common/pico_base_headers/include/pico/types.h | 6 +++--- test/kitchen_sink/CMakeLists.txt | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/common/pico_base_headers/include/pico/types.h b/src/common/pico_base_headers/include/pico/types.h index 010181eef..68f7a804e 100644 --- a/src/common/pico_base_headers/include/pico/types.h +++ b/src/common/pico_base_headers/include/pico/types.h @@ -50,7 +50,7 @@ typedef uint64_t absolute_time_t; * \ingroup timestamp */ static inline uint64_t to_us_since_boot(absolute_time_t t) { -#ifdef PICO_DEBUG_ABSOLUTE_TIME_T +#if PICO_OPAQUE_ABSOLUTE_TIME_T return t._private_us_since_boot; #else return t; @@ -65,7 +65,7 @@ static inline uint64_t to_us_since_boot(absolute_time_t t) { * \ingroup timestamp */ static inline void update_us_since_boot(absolute_time_t *t, uint64_t us_since_boot) { -#ifdef PICO_DEBUG_ABSOLUTE_TIME_T +#if PICO_OPAQUE_ABSOLUTE_TIME_T assert(us_since_boot <= INT64_MAX); t->_private_us_since_boot = us_since_boot; #else @@ -85,7 +85,7 @@ static inline absolute_time_t from_us_since_boot(uint64_t us_since_boot) { return t; } -#ifdef NDEBUG +#if !PICO_OPAQUE_ABSOLUTE_TIME_T #define ABSOLUTE_TIME_INITIALIZED_VAR(name, value) name = value #else #define ABSOLUTE_TIME_INITIALIZED_VAR(name, value) name = {value} diff --git a/test/kitchen_sink/CMakeLists.txt b/test/kitchen_sink/CMakeLists.txt index a2a30609b..9562dc137 100644 --- a/test/kitchen_sink/CMakeLists.txt +++ b/test/kitchen_sink/CMakeLists.txt @@ -194,6 +194,11 @@ target_link_libraries(kitchen_sink_printf_none kitchen_sink_libs kitchen_sink_op pico_add_extra_outputs(kitchen_sink_printf_none) pico_set_printf_implementation(kitchen_sink_printf_none none) +add_executable(kitchen_sink_opaque_absolute_time ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) +target_link_libraries(kitchen_sink_opaque_absolute_time kitchen_sink_libs kitchen_sink_options) +pico_add_extra_outputs(kitchen_sink_opaque_absolute_time) +target_compile_definitions(kitchen_sink_opaque_absolute_time PRIVATE KITCHEN_SINK_ID="opaque absolute_time binary" PICO_OPAQUE_ABSOLUTE_TIME_T=1) + if (NOT KITCHEN_SINK_NO_BINARY_TYPE_VARIANTS) add_executable(kitchen_sink_copy_to_ram ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c) pico_set_binary_type(kitchen_sink_copy_to_ram copy_to_ram) From 5815ebf28d1ba9cb338293b41eab01f9009263b4 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 22 Apr 2026 16:01:06 +0100 Subject: [PATCH 113/127] Add low_power_sleep_until_aon_timer and to_ms_64_since_boot --- src/common/pico_time/include/pico/time.h | 12 ++++ .../hardware_powman/include/hardware/powman.h | 2 +- .../pico_low_power/include/pico/low_power.h | 21 ++++++ src/rp2_common/pico_low_power/low_power.c | 56 +++++++++++++++- test/hello_sleep/hello_sleep.c | 66 +++++++++++++++++-- test/hello_sleep/hello_sleep_gpio.c | 2 +- 6 files changed, 149 insertions(+), 10 deletions(-) diff --git a/src/common/pico_time/include/pico/time.h b/src/common/pico_time/include/pico/time.h index 43d5ed7a9..d05ce83f6 100644 --- a/src/common/pico_time/include/pico/time.h +++ b/src/common/pico_time/include/pico/time.h @@ -89,6 +89,18 @@ static inline uint32_t to_ms_since_boot(absolute_time_t t) { return us_to_ms(us); } +/*! fn to_ms_64_since_boot + * \ingroup timestamp + * \brief Convert a timestamp into a number of 64-bit milliseconds since boot. + * \param t an absolute_time_t value to convert + * \return the number of milliseconds since boot represented by t + * \sa to_us_since_boot() + */ + static inline uint64_t to_ms_64_since_boot(absolute_time_t t) { + uint64_t us = to_us_since_boot(t); + return us / 1000ull; +} + /*! \brief Return a timestamp value obtained by adding a number of microseconds to another timestamp * \ingroup timestamp * diff --git a/src/rp2_common/hardware_powman/include/hardware/powman.h b/src/rp2_common/hardware_powman/include/hardware/powman.h index d31228d83..48fc471d4 100644 --- a/src/rp2_common/hardware_powman/include/hardware/powman.h +++ b/src/rp2_common/hardware_powman/include/hardware/powman.h @@ -154,7 +154,7 @@ static inline void powman_timer_stop(void) { /*! \brief Pause the powman timer * \ingroup hardware_powman */ - static inline void powman_timer_pause(void) { +static inline void powman_timer_pause(void) { powman_clear_bits(&powman_hw->timer, POWMAN_TIMER_RUN_BITS); powman_timer_set_ms(powman_timer_get_ms()); } diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 17753e303..a35627c26 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -61,6 +61,15 @@ extern "C" { #define PARAM_ASSERTIONS_ENABLED_PICO_LOW_POWER 0 #endif +// PICO_CONFIG: PICO_LOW_POWER_MIN_AON_SLEEP_TIME_MS, Minimum supported time to spend in sleep using the AON timer in milliseconds, type=int, default=2000 on RP2040, 10 otherwise, group=pico_low_power +#ifndef PICO_LOW_POWER_MIN_AON_SLEEP_TIME_MS +#if PICO_RP2040 +#define PICO_LOW_POWER_MIN_AON_SLEEP_TIME_MS 2000 +#else +#define PICO_LOW_POWER_MIN_AON_SLEEP_TIME_MS 10 +#endif +#endif + // PICO_CONFIG: PICO_LOW_POWER_MIN_DORMANT_TIME_MS, Minimum supported time to spend dormant in milliseconds, type=int, default=2000 on RP2040, 10 otherwise, group=pico_low_power #ifndef PICO_LOW_POWER_MIN_DORMANT_TIME_MS #if PICO_RP2040 @@ -132,6 +141,18 @@ static inline int low_power_sleep_until_default_timer(absolute_time_t until, con return low_power_sleep_until_timer(PICO_DEFAULT_TIMER_INSTANCE(), until, keep_enabled, exclusive); } +/*! \brief Sleep until time using AON timer + * \ingroup pico_low_power + * Sleep until the AON timer reaches the specified value. The clocks specified in keep_enabled will be kept enabled during sleep, along with clocks required + * for the AON timer. If exclusive is true, only the AON timer interrupt will be listened for, otherwise other interrupts will also be listened for. + * + * \param until The time to sleep until. + * \param keep_enabled The clocks to keep enabled during sleep. + * \param exclusive Whether to only listen for the AON timer interrupt, or other interrupts. + * \return 0 on success, non-zero on error. + */ +int low_power_sleep_until_aon_timer(absolute_time_t until, const clock_dest_bitset_t *keep_enabled, bool exclusive); + /*! \brief Sleep until GPIO pin state changes * \ingroup pico_low_power diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 1106e9e18..18d0e5626 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -276,6 +276,56 @@ int low_power_sleep_until_timer(timer_hw_t *timer, absolute_time_t until, return 0; } +int low_power_sleep_until_aon_timer(absolute_time_t until, + const clock_dest_bitset_t *keep_enabled, bool exclusive) { + if (!aon_timer_is_running()) { + return PICO_ERROR_PRECONDITION_NOT_MET; + } + + if (to_ms_64_since_boot(aon_timer_get_absolute_time()) + PICO_LOW_POWER_MIN_AON_SLEEP_TIME_MS > to_ms_64_since_boot(until)) { + // Prevent race condition where the timer fires before we can go to sleep + // by setting a minimum time for sleep + return PICO_ERROR_INVALID_ARG; + } + + clock_dest_bitset_t local_keep_enabled; + replace_null_enable_values(keep_enabled, &local_keep_enabled); + +#if PICO_RP2040 + clock_dest_bitset_add(&local_keep_enabled, CLK_DEST_RTC_RTC); +#elif PICO_RP2350 + clock_dest_bitset_add(&local_keep_enabled, CLK_DEST_REF_POWMAN); +#else + #error Unknown processor +#endif + + add_library_clocks(&local_keep_enabled); + + struct timespec ts; + us_to_timespec(to_us_since_boot(until), &ts); + event_happened = false; + aon_timer_enable_alarm(&ts, low_power_wakeup, false); + + if (exclusive) save_and_disable_other_interrupts(aon_timer_get_irq_num()); + + prepare_for_clock_gating(); + // gate clocks + clock_gate_sleep_en(&local_keep_enabled); + + low_power_enable_processor_deep_sleep(); + // Go to sleep until the wakeup event happens (note it may have happened already) + while (!event_happened) __wfi(); + low_power_disable_processor_deep_sleep(); + + aon_timer_disable_alarm(); + + post_clock_gating(); + + if (exclusive) restore_other_interrupts(); + + return 0; +} + int low_power_sleep_until_gpio_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_bitset_t *keep_enabled, bool exclusive) { @@ -440,7 +490,7 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, return PICO_ERROR_PRECONDITION_NOT_MET; } - if (to_ms_since_boot(aon_timer_get_absolute_time()) + PICO_LOW_POWER_MIN_DORMANT_TIME_MS > to_ms_since_boot(until)) { + if (to_ms_64_since_boot(aon_timer_get_absolute_time()) + PICO_LOW_POWER_MIN_DORMANT_TIME_MS > to_ms_64_since_boot(until)) { // Prevent race condition where the timer fires before we can go dormant // by setting a minimum time for dormant return PICO_ERROR_INVALID_ARG; @@ -619,12 +669,12 @@ int low_power_pstate_until_aon_timer(absolute_time_t until, pstate_bitset_t *pst if (!aon_timer_is_running()) { return PICO_ERROR_PRECONDITION_NOT_MET; } - if (to_ms_since_boot(aon_timer_get_absolute_time()) + PICO_LOW_POWER_MIN_PSTATE_TIME_MS > to_ms_since_boot(until)) { + if (to_ms_64_since_boot(aon_timer_get_absolute_time()) + PICO_LOW_POWER_MIN_PSTATE_TIME_MS > to_ms_64_since_boot(until)) { // Prevent race condition where the timer fires before we can go to pstate // by setting a minimum time for pstate return PICO_ERROR_INVALID_ARG; } - powman_enable_alarm_wakeup_at_ms(to_ms_since_boot(until)); + powman_enable_alarm_wakeup_at_ms(to_ms_64_since_boot(until)); return low_power_go_pstate(pstate, resume_func); } diff --git a/test/hello_sleep/hello_sleep.c b/test/hello_sleep/hello_sleep.c index 31faff33f..ada5e1e08 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/hello_sleep/hello_sleep.c @@ -186,14 +186,70 @@ int main() { - // dormant - printf("Going DORMANT for %d seconds via AON TIMER\n", SLEEP_TIME_S); - - // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync + // start the AON timer start_time = get_absolute_time(); - us_to_timespec(start_time, &ts); + us_to_timespec(to_us_since_boot(start_time), &ts); aon_timer_start(&ts); + printf("AON timer started @%dus\n", to_us_since_boot(aon_timer_get_absolute_time())); + + + + // exclusive sleep using the AON timer + printf("Going to sleep for %d seconds via AON timer\n", SLEEP_TIME_S); + + start_time = aon_timer_get_absolute_time(); + wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); + ret = low_power_sleep_until_aon_timer(wakeup_time, NULL, true); + if (ret != PICO_OK) { + printf("ERROR: %d returned by low_power_sleep_until_aon_timer\n", ret); + EXIT_TEST; + } + diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); + printf("Woken up now @%dus since target\n", (int)diff); + if (diff < 0) { + printf("ERROR: Woke up too soon\n"); + EXIT_TEST; + } + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); + + + + // non-exclusive sleep using the AON timer + printf("Going to non-exclusive sleep for %d seconds via AON timer\n", SLEEP_TIME_S); + + // leave the system timer running + clock_dest_bitset_t keep_enabled = clock_dest_bitset_none(); +#if PICO_RP2040 + clock_dest_bitset_add(&keep_enabled, CLK_DEST_SYS_TIMER); +#else + clock_dest_bitset_add(&keep_enabled, CLK_DEST_SYS_TIMER0); + clock_dest_bitset_add(&keep_enabled, CLK_DEST_REF_TICKS); +#endif + + start_time = aon_timer_get_absolute_time(); + wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); + ret = low_power_sleep_until_aon_timer(wakeup_time, &keep_enabled, false); + if (ret != PICO_OK) { + printf("ERROR: %d returned by low_power_sleep_until_aon_timer\n", ret); + EXIT_TEST; + } + diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); + printf("Woken up now @%dus since target\n", (int)diff); + if (diff < 0) { + printf("ERROR: Woke up too soon\n"); + EXIT_TEST; + } + printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + busy_wait_ms(SLEEP_TIME_MS); + + + + // dormant + printf("Going DORMANT for %d seconds via AON TIMER\n", SLEEP_TIME_S); + + start_time = aon_timer_get_absolute_time(); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); ret = low_power_dormant_until_aon_timer(wakeup_time, #if PICO_RP2040 diff --git a/test/hello_sleep/hello_sleep_gpio.c b/test/hello_sleep/hello_sleep_gpio.c index 9c2c20324..958e81f3b 100644 --- a/test/hello_sleep/hello_sleep_gpio.c +++ b/test/hello_sleep/hello_sleep_gpio.c @@ -114,7 +114,7 @@ int main() { // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync start_time = get_absolute_time(); - us_to_timespec(start_time, &ts); + us_to_timespec(to_us_since_boot(start_time), &ts); aon_timer_start(&ts); printf("Going DORMANT until GPIO wakeup\n"); From 24f7e7718155400a58d39266a815bb8bbb937921 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 22 Apr 2026 18:04:46 +0100 Subject: [PATCH 114/127] Add helper functions for easier sleeping Add low_power_xx_for_ms functions, which handle starting AON timer if necessary Add low_power_set_external_clock_source function to avoid the need to have src_hz and gpio_pin in the arguments passed to low_power_dormant_until_aon_timer, and for RP2040 you just need to call low_power_set_external_clock_source beforehand (no-op on RP2350) Add DORMANT_CLOCK_SOURCE_DEFAULT and DORMANT_CLOCK_HZ_DEFAULT, so you don't need `#if PICO_RP2040` in user code --- src/rp2_common/hardware_powman/powman.c | 4 +- .../pico_aon_timer/include/pico/aon_timer.h | 11 ++ .../pico_low_power/include/pico/low_power.h | 124 ++++++++++++++++- src/rp2_common/pico_low_power/low_power.c | 40 +++++- test/CMakeLists.txt | 2 +- test/hello_sleep/CMakeLists.txt | 121 ---------------- .../BUILD.bazel | 8 +- test/pico_low_power_test/CMakeLists.txt | 131 ++++++++++++++++++ .../low_power_test_gpio.c} | 0 .../low_power_test_simple.c | 50 +++++++ .../low_power_test_timers.c} | 13 +- .../rtc_clksrc.c | 0 12 files changed, 357 insertions(+), 147 deletions(-) delete mode 100644 test/hello_sleep/CMakeLists.txt rename test/{hello_sleep => pico_low_power_test}/BUILD.bazel (84%) create mode 100644 test/pico_low_power_test/CMakeLists.txt rename test/{hello_sleep/hello_sleep_gpio.c => pico_low_power_test/low_power_test_gpio.c} (100%) create mode 100644 test/pico_low_power_test/low_power_test_simple.c rename test/{hello_sleep/hello_sleep.c => pico_low_power_test/low_power_test_timers.c} (96%) rename test/{hello_sleep => pico_low_power_test}/rtc_clksrc.c (100%) diff --git a/src/rp2_common/hardware_powman/powman.c b/src/rp2_common/hardware_powman/powman.c index f0899bc92..a4f782fca 100644 --- a/src/rp2_common/hardware_powman/powman.c +++ b/src/rp2_common/hardware_powman/powman.c @@ -182,7 +182,7 @@ powman_power_state powman_get_power_state(void) { int powman_set_power_state(powman_power_state state) { // Clear req ignored in case it has been set powman_clear_bits(&powman_hw->state, POWMAN_STATE_REQ_IGNORED_BITS); - powman_debug("powman: Requesting state %x\n", state); + powman_debug("powman: Requesting state %"PRIx32"\n", state); powman_write(&powman_hw->state, (~state << POWMAN_STATE_REQ_LSB) & POWMAN_STATE_REQ_BITS); // Has it been ignored? @@ -219,7 +219,7 @@ int powman_set_power_state(powman_power_state state) { // Wait while the state is changing then return true as we will be in the new state powman_debug("powman: waiting for state change\n"); while(powman_hw->state & POWMAN_STATE_CHANGING_BITS) tight_loop_contents(); - powman_debug("powman: state changed to %x\n", state); + powman_debug("powman: state changed to %"PRIx32"\n", state); return PICO_OK; } diff --git a/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h b/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h index f78b617dd..ef7d32c64 100644 --- a/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h +++ b/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h @@ -9,6 +9,7 @@ #include "pico.h" #include +#include "pico/time.h" #include "pico/util/datetime.h" #include "hardware/regs/intctrl.h" @@ -187,6 +188,16 @@ bool aon_timer_get_time_calendar(struct tm *tm); */ absolute_time_t aon_timer_get_absolute_time(void); +/*! \brief Convenience method to get the timestamp a number of milliseconds from the current time of the AON timer + * \ingroup pico_aon_timer + * + * \param ms the number of milliseconds to add to the current timestamp + * \return the future timestamp + */ + static inline absolute_time_t aon_timer_make_timeout_time_ms(uint32_t ms) { + return delayed_by_ms(aon_timer_get_absolute_time(), ms); +} + /** * \brief Get the resolution of the AON timer * \ingroup pico_aon_timer diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index a35627c26..104308e17 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -9,6 +9,8 @@ #include "pico.h" #include "hardware/timer.h" +#include "pico/time.h" +#include "pico/aon_timer.h" #ifdef __cplusplus extern "C" { @@ -101,6 +103,18 @@ typedef enum { NUM_DORMANT_CLOCK_SOURCES } dormant_clock_source_t; +#if PICO_RP2040 +#define DORMANT_CLOCK_SOURCE_DEFAULT DORMANT_CLOCK_SOURCE_XOSC +#else +#define DORMANT_CLOCK_SOURCE_DEFAULT DORMANT_CLOCK_SOURCE_LPOSC +#endif + +#if PICO_RP2040 +#define DORMANT_CLOCK_HZ_DEFAULT RTC_CLOCK_FREQ_HZ +#else +#define DORMANT_CLOCK_HZ_DEFAULT 0 // ignored +#endif + #if HAS_POWMAN_TIMER typedef void (*low_power_pstate_resume_func)(pstate_bitset_t *pstate); #endif @@ -168,11 +182,32 @@ int low_power_sleep_until_aon_timer(absolute_time_t until, const clock_dest_bits */ int low_power_sleep_until_gpio_pin_state(uint gpio_pin, bool edge, bool high, const clock_dest_bitset_t *keep_enabled, bool exclusive); +/*! \brief Set the external clock source for the AON timer + * \ingroup pico_low_power + * Set the external clock source for the AON timer. This is only used on RP2040. + * + * \param src_hz The frequency of the external clock source. + * \param gpio_pin The GPIO pin to use for the external clock source. + * \return 0 on success, non-zero on error. + */ +#if PICO_RP2040 +int low_power_set_external_clock_source(uint src_hz, uint gpio_pin); +#else +static inline int low_power_set_external_clock_source(__unused uint src_hz, __unused uint gpio_pin) { + return PICO_OK; +} +#endif + /*! \brief Go dormant until time using AON timer * \ingroup pico_low_power * Go dormant until the given AON timer reaches the specified value. * The clocks specified in keep_enabled will be kept enabled during dormant, but XOSC and ROSC will be stopped. * + * \if rp2040_specific + * This requires an external clock source to be set using \ref low_power_set_external_clock_source before calling this function. + * If the external clock source is not set, or it is not running, this will return PICO_ERROR_PRECONDITION_NOT_MET. + * \endif + * * \if (!rp2040_specific) * If the clock source is set to DORMANT_CLOCK_SOURCE_LPOSC, clk_sys will be switched to the ROSC while dormant so * it can be stopped, while clk_ref will be run from the LPOSC so that it continues running for the timer. @@ -180,12 +215,10 @@ int low_power_sleep_until_gpio_pin_state(uint gpio_pin, bool edge, bool high, co * * \param until The time to go dormant until. * \param dormant_clock_source The clock source to use for dormant. Must be DORMANT_CLOCK_SOURCE_LPOSC on RP2350. - * \param src_hz The frequency of the external RTC clock source on RP2040. Ignored on RP2350. - * \param gpio_pin The GPIO pin to use for the external RTC clock source on RP2040. Ignored on RP2350. * \param keep_enabled The clocks to keep enabled during dormant. * \return 0 on success, non-zero on error. */ -int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_source_t dormant_clock_source, uint src_hz, uint gpio_pin, const clock_dest_bitset_t *keep_enabled); +int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_source_t dormant_clock_source, const clock_dest_bitset_t *keep_enabled); /*! \brief Go dormant until GPIO pin state changes * \ingroup pico_low_power @@ -253,6 +286,91 @@ int low_power_pstate_until_gpio_pin_state(uint gpio_pin, bool edge, bool high, p pstate_bitset_t *low_power_persistent_pstate_get(pstate_bitset_t *pstate); #endif + +// Convenience functions to avoid needing the correct absolute_time_t + +/*! \brief Start the AON timer at a specific time in milliseconds + * \ingroup pico_low_power + * See \ref aon_timer_start for more information. + * + * \param ms The time in milliseconds to start the AON timer at. + * \return true on success, false on failure. + */ +static inline bool low_power_start_aon_timer_at_time_ms(uint64_t ms) { + struct timespec ts; + ms_to_timespec(ms, &ts); + return aon_timer_start(&ts); +} + +/*! \brief Start the AON timer at the current system time + * \ingroup pico_low_power + * See \ref aon_timer_start for more information. + * + * \return true on success, false on failure. + */ +static inline bool low_power_start_aon_timer(void) { + struct timespec ts; + ms_to_timespec(to_ms_64_since_boot(get_absolute_time()), &ts); + return aon_timer_start(&ts); +} + +/*! \brief Sleep for a number of microseconds + * \ingroup pico_low_power + * See \ref low_power_sleep_until_default_timer for more information. + * + * \param us The number of microseconds to sleep. + * \param keep_enabled The clocks to keep enabled during sleep. + * \param exclusive Whether to only listen for the timer interrupt, or other interrupts. + * \return 0 on success, non-zero on error. + */ +static inline int low_power_sleep_for_us(timer_hw_t *timer, uint64_t us, const clock_dest_bitset_t *keep_enabled, bool exclusive) { + return low_power_sleep_until_timer(timer, make_timeout_time_us(us), keep_enabled, exclusive); +} + +/*! \brief Sleep for a number of milliseconds + * \ingroup pico_low_power + * See \ref low_power_sleep_until_default_timer for more information. + * + * \param ms The number of milliseconds to sleep. + * \param keep_enabled The clocks to keep enabled during sleep. + * \param exclusive Whether to only listen for the timer interrupt, or other interrupts. + * \return 0 on success, non-zero on error. + */ +static inline int low_power_sleep_for_ms(uint32_t ms, const clock_dest_bitset_t *keep_enabled, bool exclusive) { + return low_power_sleep_until_default_timer(make_timeout_time_ms(ms), keep_enabled, exclusive); +} + +/*! \brief Go dormant for a number of milliseconds + + * \ingroup pico_low_power + * See \ref low_power_dormant_until_aon_timer for more information. + * + * \param ms The number of milliseconds to go dormant for. + * \param dormant_clock_source The clock source to use for dormant. + * \param keep_enabled The clocks to keep enabled during dormant. + * \return 0 on success, non-zero on error. + */ +static inline int low_power_dormant_for_ms(uint32_t ms, dormant_clock_source_t dormant_clock_source, const clock_dest_bitset_t *keep_enabled) { + if (!aon_timer_is_running()) low_power_start_aon_timer(); + return low_power_dormant_until_aon_timer(aon_timer_make_timeout_time_ms(ms), dormant_clock_source, keep_enabled); +} + +#if HAS_POWMAN_TIMER +/*! \brief Go to Pstate for a number of milliseconds + * \ingroup pico_low_power + * See \ref low_power_pstate_until_aon_timer for more information. + * + * \param ms The number of milliseconds to go to Pstate for. + * \param pstate The Pstate to use. + * \param resume_func The function to call on reboot. + * \return 0 on success, non-zero on error. + */ +static inline int low_power_pstate_for_ms(uint32_t ms, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func) { + if (!aon_timer_is_running()) low_power_start_aon_timer(); + return low_power_pstate_until_aon_timer(aon_timer_make_timeout_time_ms(ms), pstate, resume_func); +} +#endif + #ifdef __cplusplus } #endif diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 18d0e5626..923ddb99e 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -58,6 +58,10 @@ static void post_clock_gating(void) { clock_gate_sleep_en(&all); } +static bool is_timestamp_from_aon_timer(absolute_time_t timestamp) { + return to_us_since_boot(timestamp) % 1000 == 0; +} + static uint32_t interrupt_flags; #if LIB_TINYUSB_DEVICE @@ -112,6 +116,8 @@ static void post_clock_switch(void) { #if HAS_POWMAN_TIMER static void prepare_for_pstate_change(void) { prepare_for_clock_switch(); + // Ensure debugger does not prevent power down + powman_set_debug_power_request_ignored(true); } static void post_pstate_change(void) { @@ -202,6 +208,16 @@ static void restore_other_interrupts(void) { } } +#if PICO_RP2040 +static uint dormant_rtc_src_hz = 0; +static uint dormant_rtc_gpio_pin; +int low_power_set_external_clock_source(uint src_hz, uint gpio_pin) { + dormant_rtc_src_hz = src_hz; + dormant_rtc_gpio_pin = gpio_pin; + return PICO_OK; +} +#endif // inline in header for other platforms + int low_power_sleep_until_irq(const clock_dest_bitset_t *keep_enabled) { clock_dest_bitset_t local_keep_enabled; replace_null_enable_values(keep_enabled, &local_keep_enabled); @@ -282,6 +298,10 @@ int low_power_sleep_until_aon_timer(absolute_time_t until, return PICO_ERROR_PRECONDITION_NOT_MET; } + if (!is_timestamp_from_aon_timer(until)) { + return PICO_ERROR_INVALID_DATA; + } + if (to_ms_64_since_boot(aon_timer_get_absolute_time()) + PICO_LOW_POWER_MIN_AON_SLEEP_TIME_MS > to_ms_64_since_boot(until)) { // Prevent race condition where the timer fires before we can go to sleep // by setting a minimum time for sleep @@ -484,12 +504,15 @@ static void low_power_go_dormant(dormant_clock_source_t dormant_clock_source) { int low_power_dormant_until_aon_timer(absolute_time_t until, dormant_clock_source_t dormant_clock_source, - uint src_hz, uint gpio_pin, const clock_dest_bitset_t *keep_enabled) { if (!aon_timer_is_running()) { return PICO_ERROR_PRECONDITION_NOT_MET; } + if (!is_timestamp_from_aon_timer(until)) { + return PICO_ERROR_INVALID_DATA; + } + if (to_ms_64_since_boot(aon_timer_get_absolute_time()) + PICO_LOW_POWER_MIN_DORMANT_TIME_MS > to_ms_64_since_boot(until)) { // Prevent race condition where the timer fires before we can go dormant // by setting a minimum time for dormant @@ -500,14 +523,15 @@ int low_power_dormant_until_aon_timer(absolute_time_t until, replace_null_enable_values(keep_enabled, &local_keep_enabled); #if PICO_RP2040 + if (dormant_rtc_src_hz == 0) { + return PICO_ERROR_PRECONDITION_NOT_MET; + } // The RTC must be run from an external source, since the dormant source will be inactive - if (!rtc_run_from_external_source(src_hz, gpio_pin)) { + if (!rtc_run_from_external_source(dormant_rtc_src_hz, dormant_rtc_gpio_pin)) { return PICO_ERROR_PRECONDITION_NOT_MET; } clock_dest_bitset_add(&local_keep_enabled, CLK_DEST_RTC_RTC); #elif PICO_RP2350 - ((void)src_hz); - ((void)gpio_pin); if (dormant_clock_source == DORMANT_CLOCK_SOURCE_LPOSC) powman_timer_set_1khz_tick_source_lposc(); else @@ -647,9 +671,6 @@ static int low_power_go_pstate(pstate_bitset_t *pstate, low_power_pstate_resume_ powman_hw->scratch[6] = pstate_bitset_to_powman_power_state(pstate); powman_hw->scratch[7] = (uint32_t)resume_func; - // Ensure debugger does not prevent power down - powman_set_debug_power_request_ignored(true); - // Switch to required power state int rc = powman_set_power_state(pstate_bitset_to_powman_power_state(pstate)); if (rc != PICO_OK) { @@ -669,6 +690,11 @@ int low_power_pstate_until_aon_timer(absolute_time_t until, pstate_bitset_t *pst if (!aon_timer_is_running()) { return PICO_ERROR_PRECONDITION_NOT_MET; } + + if (!is_timestamp_from_aon_timer(until)) { + return PICO_ERROR_INVALID_DATA; + } + if (to_ms_64_since_boot(aon_timer_get_absolute_time()) + PICO_LOW_POWER_MIN_PSTATE_TIME_MS > to_ms_64_since_boot(until)) { // Prevent race condition where the timer fires before we can go to pstate // by setting a minimum time for pstate diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 453951a62..03b2abafc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -17,6 +17,6 @@ if (PICO_ON_DEVICE) add_subdirectory(cmsis_test) add_subdirectory(pico_sem_test) add_subdirectory(pico_sha256_test) - add_subdirectory(hello_sleep) + add_subdirectory(pico_low_power_test) add_subdirectory(pico_async_context_test) endif() diff --git a/test/hello_sleep/CMakeLists.txt b/test/hello_sleep/CMakeLists.txt deleted file mode 100644 index 093ec60a3..000000000 --- a/test/hello_sleep/CMakeLists.txt +++ /dev/null @@ -1,121 +0,0 @@ -add_executable(hello_sleep - hello_sleep.c - ) - -target_link_libraries(hello_sleep pico_stdlib pico_low_power pico_status_led) - -# create map/bin/hex file etc. -pico_add_extra_outputs(hello_sleep) - - -add_executable(hello_sleep_usb - hello_sleep.c - ) - -target_link_libraries(hello_sleep_usb pico_stdlib pico_low_power pico_status_led) - -pico_enable_stdio_usb(hello_sleep_usb 1) - -# create map/bin/hex file etc. -pico_add_extra_outputs(hello_sleep_usb) - - -add_executable(hello_sleep_sram1 - hello_sleep.c - ) - -target_link_libraries(hello_sleep_sram1 pico_stdlib pico_low_power pico_status_led) - -if (NOT PICO_RP2040) - pico_set_persistent_data_loc(hello_sleep_sram1 0x20040000) -endif() - -# create map/bin/hex file etc. -pico_add_extra_outputs(hello_sleep_sram1) - -if (NOT PICO_RP2040) - if (NOT PICO_RISCV) - add_executable(hello_sleep_encrypted - hello_sleep.c - ) - - target_link_libraries(hello_sleep_encrypted pico_stdlib pico_low_power pico_status_led) - - pico_set_binary_type(hello_sleep_encrypted no_flash) - pico_package_uf2_output(hello_sleep_encrypted) - pico_sign_binary(hello_sleep_encrypted ${CMAKE_SOURCE_DIR}/tools/example_keys/private.pem) - pico_encrypt_binary(hello_sleep_encrypted ${CMAKE_SOURCE_DIR}/tools/example_keys/privateaes.bin ${CMAKE_SOURCE_DIR}/tools/example_keys/ivsalt.bin EMBED NO_CLEAR) - - # create map/bin/hex file etc. - pico_add_extra_outputs(hello_sleep_encrypted) - endif() - - - add_executable(hello_sleep_xip_sram - hello_sleep.c - ) - - target_link_libraries(hello_sleep_xip_sram pico_stdlib pico_low_power pico_status_led) - - pico_set_persistent_data_loc(hello_sleep_xip_sram 0x13ffc000) - - # create map/bin/hex file etc. - pico_add_extra_outputs(hello_sleep_xip_sram) - - - add_executable(hello_sleep_xip_sram_no_flash - hello_sleep.c - ) - - target_link_libraries(hello_sleep_xip_sram_no_flash pico_stdlib pico_low_power pico_status_led) - - pico_set_persistent_data_loc(hello_sleep_xip_sram_no_flash 0x13ffc000) - - pico_set_binary_type(hello_sleep_xip_sram_no_flash no_flash) - pico_package_uf2_output(hello_sleep_xip_sram_no_flash) - - # create map/bin/hex file etc. - pico_add_extra_outputs(hello_sleep_xip_sram_no_flash) -endif() - -if (PICO_RP2040) - add_executable(rtc_clksrc - rtc_clksrc.c - ) - - target_link_libraries(rtc_clksrc pico_stdlib pico_status_led) - - # create map/bin/hex file etc. - pico_add_extra_outputs(rtc_clksrc) -endif() - -add_executable(hello_sleep_gpio - hello_sleep_gpio.c - ) - -target_link_libraries(hello_sleep_gpio pico_stdlib pico_low_power pico_status_led) - -# create map/bin/hex file etc. -pico_add_extra_outputs(hello_sleep_gpio) - - -add_executable(hello_sleep_gpio_usb - hello_sleep_gpio.c - ) - -target_link_libraries(hello_sleep_gpio_usb pico_stdlib pico_low_power pico_status_led) - -pico_enable_stdio_usb(hello_sleep_gpio_usb 1) - -# create map/bin/hex file etc. -pico_add_extra_outputs(hello_sleep_gpio_usb) - - -add_custom_target(hello_sleep_examples) -get_directory_property(targets BUILDSYSTEM_TARGETS DIRECTORY ${CMAKE_CURRENT_LIST_DIR}) -foreach(target IN LISTS targets) - get_target_property(type ${target} TYPE) - if(type STREQUAL "EXECUTABLE") - add_dependencies(hello_sleep_examples ${target}) - endif() -endforeach() diff --git a/test/hello_sleep/BUILD.bazel b/test/pico_low_power_test/BUILD.bazel similarity index 84% rename from test/hello_sleep/BUILD.bazel rename to test/pico_low_power_test/BUILD.bazel index 2c007c6bc..b2b1eee49 100644 --- a/test/hello_sleep/BUILD.bazel +++ b/test/pico_low_power_test/BUILD.bazel @@ -3,9 +3,9 @@ load("//bazel:defs.bzl", "compatible_with_rp2") package(default_visibility = ["//visibility:public"]) cc_binary( - name = "hello_sleep", + name = "low_power_test_timers", testonly = True, - srcs = ["hello_sleep.c"], + srcs = ["low_power_test_timers.c"], target_compatible_with = compatible_with_rp2(), deps = [ "//src/rp2_common/pico_stdlib", @@ -15,9 +15,9 @@ cc_binary( ) cc_binary( - name = "hello_sleep_gpio", + name = "low_power_test_gpio", testonly = True, - srcs = ["hello_sleep_gpio.c"], + srcs = ["low_power_test_gpio.c"], target_compatible_with = compatible_with_rp2(), deps = [ "//src/rp2_common/pico_stdlib", diff --git a/test/pico_low_power_test/CMakeLists.txt b/test/pico_low_power_test/CMakeLists.txt new file mode 100644 index 000000000..f26c37069 --- /dev/null +++ b/test/pico_low_power_test/CMakeLists.txt @@ -0,0 +1,131 @@ +add_executable(low_power_test_timers + low_power_test_timers.c + ) + +target_link_libraries(low_power_test_timers pico_stdlib pico_low_power pico_status_led) + +# create map/bin/hex file etc. +pico_add_extra_outputs(low_power_test_timers) + + +add_executable(low_power_test_timers_usb + low_power_test_timers.c + ) + +target_link_libraries(low_power_test_timers_usb pico_stdlib pico_low_power pico_status_led) + +pico_enable_stdio_usb(low_power_test_timers_usb 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(low_power_test_timers_usb) + + +add_executable(low_power_test_timers_sram1 + low_power_test_timers.c + ) + +target_link_libraries(low_power_test_timers_sram1 pico_stdlib pico_low_power pico_status_led) + +if (NOT PICO_RP2040) + pico_set_persistent_data_loc(low_power_test_timers_sram1 0x20040000) +endif() + +# create map/bin/hex file etc. +pico_add_extra_outputs(low_power_test_timers_sram1) + +if (NOT PICO_RP2040) + if (NOT PICO_RISCV) + add_executable(low_power_test_timers_encrypted + low_power_test_timers.c + ) + + target_link_libraries(low_power_test_timers_encrypted pico_stdlib pico_low_power pico_status_led) + + pico_set_binary_type(low_power_test_timers_encrypted no_flash) + pico_package_uf2_output(low_power_test_timers_encrypted) + pico_sign_binary(low_power_test_timers_encrypted ${CMAKE_SOURCE_DIR}/tools/example_keys/private.pem) + pico_encrypt_binary(low_power_test_timers_encrypted ${CMAKE_SOURCE_DIR}/tools/example_keys/privateaes.bin ${CMAKE_SOURCE_DIR}/tools/example_keys/ivsalt.bin EMBED NO_CLEAR) + + # create map/bin/hex file etc. + pico_add_extra_outputs(low_power_test_timers_encrypted) + endif() + + + add_executable(low_power_test_timers_xip_sram + low_power_test_timers.c + ) + + target_link_libraries(low_power_test_timers_xip_sram pico_stdlib pico_low_power pico_status_led) + + pico_set_persistent_data_loc(low_power_test_timers_xip_sram 0x13ffc000) + + # create map/bin/hex file etc. + pico_add_extra_outputs(low_power_test_timers_xip_sram) + + + add_executable(low_power_test_timers_xip_sram_no_flash + low_power_test_timers.c + ) + + target_link_libraries(low_power_test_timers_xip_sram_no_flash pico_stdlib pico_low_power pico_status_led) + + pico_set_persistent_data_loc(low_power_test_timers_xip_sram_no_flash 0x13ffc000) + + pico_set_binary_type(low_power_test_timers_xip_sram_no_flash no_flash) + pico_package_uf2_output(low_power_test_timers_xip_sram_no_flash) + + # create map/bin/hex file etc. + pico_add_extra_outputs(low_power_test_timers_xip_sram_no_flash) +endif() + +if (PICO_RP2040) + add_executable(rtc_clksrc + rtc_clksrc.c + ) + + target_link_libraries(rtc_clksrc pico_stdlib pico_status_led) + + # create map/bin/hex file etc. + pico_add_extra_outputs(rtc_clksrc) +endif() + +add_executable(low_power_test_gpio + low_power_test_gpio.c + ) + +target_link_libraries(low_power_test_gpio pico_stdlib pico_low_power pico_status_led) + +# create map/bin/hex file etc. +pico_add_extra_outputs(low_power_test_gpio) + + +add_executable(low_power_test_gpio_usb + low_power_test_gpio.c + ) + +target_link_libraries(low_power_test_gpio_usb pico_stdlib pico_low_power pico_status_led) + +pico_enable_stdio_usb(low_power_test_gpio_usb 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(low_power_test_gpio_usb) + + +add_executable(low_power_test_simple + low_power_test_simple.c + ) + +target_link_libraries(low_power_test_simple pico_stdlib pico_low_power pico_status_led) + +# create map/bin/hex file etc. +pico_add_extra_outputs(low_power_test_simple) + + +add_custom_target(low_power_tests) +get_directory_property(targets BUILDSYSTEM_TARGETS DIRECTORY ${CMAKE_CURRENT_LIST_DIR}) +foreach(target IN LISTS targets) + get_target_property(type ${target} TYPE) + if(type STREQUAL "EXECUTABLE") + add_dependencies(low_power_tests ${target}) + endif() +endforeach() diff --git a/test/hello_sleep/hello_sleep_gpio.c b/test/pico_low_power_test/low_power_test_gpio.c similarity index 100% rename from test/hello_sleep/hello_sleep_gpio.c rename to test/pico_low_power_test/low_power_test_gpio.c diff --git a/test/pico_low_power_test/low_power_test_simple.c b/test/pico_low_power_test/low_power_test_simple.c new file mode 100644 index 000000000..17f2d36fe --- /dev/null +++ b/test/pico_low_power_test/low_power_test_simple.c @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2026 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "pico/stdlib.h" +#include "pico/status_led.h" +#include "pico/low_power.h" + +#define SLEEP_TIME_S 2 +#define SLEEP_TIME_MS SLEEP_TIME_S * 1000 + +#define RTC_GPIO 22 // must support clock input, see the GPIO function table in the datasheet. + +bool repeater(repeating_timer_t *timer) { + printf(" Repeating timer at %dms\n", to_ms_since_boot(get_absolute_time())); + status_led_set_state(!status_led_get_state()); + return true; +} + +int main() { + stdio_init_all(); + status_led_init(); + + low_power_set_external_clock_source(DORMANT_CLOCK_HZ_DEFAULT, RTC_GPIO); + + static int __persistent_data(num_runs); + for (num_runs++; num_runs < 5; num_runs++) { // start at 1 to prove the persistent data is working + printf("Run %d\n", num_runs); + + printf("Going to sleep for %d seconds\n", SLEEP_TIME_S); + low_power_sleep_for_ms(SLEEP_TIME_MS, NULL, true); + printf("Woken up\n"); + + // printf("Going dormant for %d seconds\n", SLEEP_TIME_S); + // low_power_dormant_for_ms(SLEEP_TIME_MS, DORMANT_CLOCK_SOURCE_DEFAULT, NULL); + // printf("Woken up\n"); + +#if HAS_POWMAN_TIMER + printf("Going to Pstate for %d seconds\n", SLEEP_TIME_S); + int ret = low_power_pstate_for_ms(SLEEP_TIME_MS, NULL, NULL); + printf("%d ERROR: low_power_pstate_for_ms returned\n", ret); +#endif + } + + printf("SUCCESS\n"); + return 0; +} diff --git a/test/hello_sleep/hello_sleep.c b/test/pico_low_power_test/low_power_test_timers.c similarity index 96% rename from test/hello_sleep/hello_sleep.c rename to test/pico_low_power_test/low_power_test_timers.c index ada5e1e08..d0a7150a5 100644 --- a/test/hello_sleep/hello_sleep.c +++ b/test/pico_low_power_test/low_power_test_timers.c @@ -8,7 +8,6 @@ #include #include "pico/stdlib.h" #include "pico/low_power.h" -#include "pico/aon_timer.h" #include "pico/status_led.h" #include "hardware/structs/xip_ctrl.h" @@ -142,6 +141,8 @@ int main() { struct timespec ts; int ret; + low_power_set_external_clock_source(DORMANT_CLOCK_HZ_DEFAULT, RTC_GPIO); + // exclusive sleep @@ -191,7 +192,7 @@ int main() { us_to_timespec(to_us_since_boot(start_time), &ts); aon_timer_start(&ts); - printf("AON timer started @%dus\n", to_us_since_boot(aon_timer_get_absolute_time())); + printf("AON timer started @%dms\n", to_ms_since_boot(aon_timer_get_absolute_time())); @@ -251,13 +252,7 @@ int main() { start_time = aon_timer_get_absolute_time(); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); - ret = low_power_dormant_until_aon_timer(wakeup_time, - #if PICO_RP2040 - DORMANT_CLOCK_SOURCE_XOSC, RTC_CLOCK_FREQ_HZ, - #else - DORMANT_CLOCK_SOURCE_LPOSC, XOSC_HZ, - #endif - RTC_GPIO, NULL); + ret = low_power_dormant_until_aon_timer(wakeup_time, DORMANT_CLOCK_SOURCE_DEFAULT, NULL); if (ret != PICO_OK) { printf("ERROR: %d returned by low_power_dormant_until_aon_timer\n", ret); #if PICO_RP2040 diff --git a/test/hello_sleep/rtc_clksrc.c b/test/pico_low_power_test/rtc_clksrc.c similarity index 100% rename from test/hello_sleep/rtc_clksrc.c rename to test/pico_low_power_test/rtc_clksrc.c From 81d2a2df970f9d135f0d73b09f07aa3749eb7ddd Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 22 Apr 2026 18:19:53 +0100 Subject: [PATCH 115/127] Fix bazel build --- test/pico_low_power_test/BUILD.bazel | 12 ++++++++++++ tools/bazel_build.py | 13 +++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/test/pico_low_power_test/BUILD.bazel b/test/pico_low_power_test/BUILD.bazel index b2b1eee49..598d7cc81 100644 --- a/test/pico_low_power_test/BUILD.bazel +++ b/test/pico_low_power_test/BUILD.bazel @@ -26,6 +26,18 @@ cc_binary( ], ) +cc_binary( + name = "low_power_test_simple", + testonly = True, + srcs = ["low_power_test_simple.c"], + target_compatible_with = compatible_with_rp2(), + deps = [ + "//src/rp2_common/pico_stdlib", + "//src/rp2_common/pico_low_power", + "//src/rp2_common/pico_status_led", + ], +) + cc_binary( name = "rtc_clksrc", testonly = True, diff --git a/tools/bazel_build.py b/tools/bazel_build.py index eb9752ac5..ad4f607dd 100755 --- a/tools/bazel_build.py +++ b/tools/bazel_build.py @@ -52,9 +52,10 @@ "//test/pico_sha256_test:pico_sha256_test", "//test/pico_stdio_test:pico_stdio_test", "//test/pico_time_test:pico_time_test", - "//test/hello_sleep:hello_sleep", - "//test/hello_sleep:hello_sleep_gpio", - "//test/hello_sleep:rtc_clksrc", + "//test/pico_low_power_test:low_power_test_timers", + "//test/pico_low_power_test:low_power_test_gpio", + "//test/pico_low_power_test:low_power_test_simple", + "//test/pico_low_power_test:rtc_clksrc", "//test/pico_async_context_test:pico_async_context_test", # Pretty much only Picotool and pioasm build on Windows. @@ -95,7 +96,7 @@ "//test/pico_float_test:hazard3_test_gen", # RP2040 only "//test/kitchen_sink:kitchen_sink_blocked_ram", - "//test/hello_sleep:rtc_clksrc", + "//test/pico_low_power_test:rtc_clksrc", # TODO: RISC-V support. "//test/pico_float_test:pico_float_test_hazard3", ) @@ -138,7 +139,7 @@ "//test/pico_float_test:hazard3_test_gen", # RP2040 only "//test/kitchen_sink:kitchen_sink_blocked_ram", - "//test/hello_sleep:rtc_clksrc", + "//test/pico_low_power_test:rtc_clksrc", # TODO: RISC-V support. "//test/pico_float_test:pico_float_test_hazard3", # not supported by clang @@ -177,7 +178,7 @@ "//test/pico_float_test:hazard3_test_gen", # RP2040 only "//test/kitchen_sink:kitchen_sink_blocked_ram", - "//test/hello_sleep:rtc_clksrc", + "//test/pico_low_power_test:rtc_clksrc", # TODO: RISC-V support. "//test/pico_float_test:pico_float_test_hazard3", ) From 7157446420fde9c8ab26608bd0fca69be95e824f Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 23 Apr 2026 11:04:49 +0100 Subject: [PATCH 116/127] Improve low_power_test_simple Also increase powman_set_power_state timeout when waiting for POWMAN_STATE_WAITING_BITS, as it was sometimes timing out --- src/rp2_common/hardware_powman/powman.c | 2 +- .../low_power_test_simple.c | 36 ++++++++++++------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/rp2_common/hardware_powman/powman.c b/src/rp2_common/hardware_powman/powman.c index a4f782fca..893e29146 100644 --- a/src/rp2_common/hardware_powman/powman.c +++ b/src/rp2_common/hardware_powman/powman.c @@ -206,7 +206,7 @@ int powman_set_power_state(powman_power_state state) { // Note if the powerdown is being blocked by a pending pwrup request we will break out of this and return a failure // Clk pow is slow so can take a few clk_pow cycles for waiting to turn up - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 500; i++) { if (powman_hw->state & POWMAN_STATE_WAITING_BITS) { return PICO_OK; } diff --git a/test/pico_low_power_test/low_power_test_simple.c b/test/pico_low_power_test/low_power_test_simple.c index 17f2d36fe..0e715dd3f 100644 --- a/test/pico_low_power_test/low_power_test_simple.c +++ b/test/pico_low_power_test/low_power_test_simple.c @@ -9,8 +9,7 @@ #include "pico/status_led.h" #include "pico/low_power.h" -#define SLEEP_TIME_S 2 -#define SLEEP_TIME_MS SLEEP_TIME_S * 1000 +#define SLEEP_TIME_MS 1000 #define RTC_GPIO 22 // must support clock input, see the GPIO function table in the datasheet. @@ -26,22 +25,35 @@ int main() { low_power_set_external_clock_source(DORMANT_CLOCK_HZ_DEFAULT, RTC_GPIO); + int ret; static int __persistent_data(num_runs); for (num_runs++; num_runs < 5; num_runs++) { // start at 1 to prove the persistent data is working printf("Run %d\n", num_runs); - printf("Going to sleep for %d seconds\n", SLEEP_TIME_S); - low_power_sleep_for_ms(SLEEP_TIME_MS, NULL, true); - printf("Woken up\n"); - - // printf("Going dormant for %d seconds\n", SLEEP_TIME_S); - // low_power_dormant_for_ms(SLEEP_TIME_MS, DORMANT_CLOCK_SOURCE_DEFAULT, NULL); - // printf("Woken up\n"); + printf("Going to sleep for %dms\n", SLEEP_TIME_MS); + ret = low_power_sleep_for_ms(SLEEP_TIME_MS, NULL, true); + if (ret != PICO_OK) { + printf("ERROR: low_power_sleep_for_ms returned %d\n", ret); + } else { + printf("Woken up\n"); + } + + printf("Going dormant for %dms\n", SLEEP_TIME_MS); + ret = low_power_dormant_for_ms(SLEEP_TIME_MS, DORMANT_CLOCK_SOURCE_DEFAULT, NULL); + if (ret != PICO_OK) { + printf("ERROR: low_power_dormant_for_ms returned %d\n", ret); + } else { + printf("Woken up\n"); + } #if HAS_POWMAN_TIMER - printf("Going to Pstate for %d seconds\n", SLEEP_TIME_S); - int ret = low_power_pstate_for_ms(SLEEP_TIME_MS, NULL, NULL); - printf("%d ERROR: low_power_pstate_for_ms returned\n", ret); + printf("Going to Pstate for %dms\n", SLEEP_TIME_MS); + ret = low_power_pstate_for_ms(SLEEP_TIME_MS, NULL, NULL); + if (ret != PICO_OK) { + printf("%d ERROR: low_power_pstate_for_ms returned\n", ret); + } else { + printf("ERROR: Woken up from Pstate\n"); + } #endif } From 5b97da4c42b8a57b52f1b02b6c827b5f1b8db432 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 23 Apr 2026 11:15:42 +0100 Subject: [PATCH 117/127] Switch powman timer between lposc and xosc explicitly when going pstate This writes the calibrated frequency for the LPOSC to improve the accuracy, and switches it back to the default XOSC when waking up --- src/rp2_common/pico_low_power/low_power.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/rp2_common/pico_low_power/low_power.c b/src/rp2_common/pico_low_power/low_power.c index 923ddb99e..d622846d3 100644 --- a/src/rp2_common/pico_low_power/low_power.c +++ b/src/rp2_common/pico_low_power/low_power.c @@ -118,6 +118,8 @@ static void prepare_for_pstate_change(void) { prepare_for_clock_switch(); // Ensure debugger does not prevent power down powman_set_debug_power_request_ignored(true); + // Switch powman timer to lposc explicitly, which will also use the calibrated frequency + powman_timer_set_1khz_tick_source_lposc(); } static void post_pstate_change(void) { @@ -724,6 +726,8 @@ void __weak runtime_init_low_power_reboot_check(void) { powman_hw->scratch[6] = 0; powman_hw->scratch[7] = 0; } + // Switch powman timer back to xosc + powman_timer_set_1khz_tick_source_xosc(); } } #endif From 441e93f8fd9528c1c0d00f0720fe2a6bf30b02fa Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 23 Apr 2026 11:31:54 +0100 Subject: [PATCH 118/127] Don't check BADWRITE when doing ROSC writes It is unreliable, see RP2040-E10 --- .../hardware_rosc/include/hardware/rosc.h | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/rp2_common/hardware_rosc/include/hardware/rosc.h b/src/rp2_common/hardware_rosc/include/hardware/rosc.h index 3ef5180fa..53f2bee53 100644 --- a/src/rp2_common/hardware_rosc/include/hardware/rosc.h +++ b/src/rp2_common/hardware_rosc/include/hardware/rosc.h @@ -59,27 +59,29 @@ void rosc_restart(void); */ uint rosc_measure_freq_khz(void); -inline static void rosc_clear_bad_write(void) { - hw_clear_bits(&rosc_hw->status, ROSC_STATUS_BADWRITE_BITS); -} +// ROSC BADWRITE is not reliable, see RP2040-E10 +// inline static void rosc_clear_bad_write(void) { +// hw_clear_bits(&rosc_hw->status, ROSC_STATUS_BADWRITE_BITS); +// } -inline static bool rosc_write_okay(void) { - return !(rosc_hw->status & ROSC_STATUS_BADWRITE_BITS); -} +// inline static bool rosc_write_okay(void) { +// return !(rosc_hw->status & ROSC_STATUS_BADWRITE_BITS); +// } /*! \brief Checked write to a Ring Oscillator register * \ingroup hardware_rosc * - * Clears the bad write flag and asserts that the write is okay. + * This would normally clear the bad write flag and asserts that the write is okay. + * However, ROSC BADWRITE is not reliable (see RP2040-E10) so we don't do this. * * \param addr The register address. * \param value The value to write. */ inline static void rosc_write(io_rw_32 *addr, uint32_t value) { - rosc_clear_bad_write(); - assert(rosc_write_okay()); + // rosc_clear_bad_write(); + // assert(rosc_write_okay()); *addr = value; - assert(rosc_write_okay()); + // assert(rosc_write_okay()); }; #ifdef __cplusplus From 2f3f4204d3c79984ca5124b6c309ad1fd9aea4e8 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 23 Apr 2026 15:01:19 +0100 Subject: [PATCH 119/127] Print PASSED at end of tests in preparation for #2897 --- test/pico_low_power_test/low_power_test_gpio.c | 2 +- test/pico_low_power_test/low_power_test_simple.c | 2 +- test/pico_low_power_test/low_power_test_timers.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/pico_low_power_test/low_power_test_gpio.c b/test/pico_low_power_test/low_power_test_gpio.c index 958e81f3b..db218ba11 100644 --- a/test/pico_low_power_test/low_power_test_gpio.c +++ b/test/pico_low_power_test/low_power_test_gpio.c @@ -140,7 +140,7 @@ int main() { busy_wait_ms(SLEEP_TIME_MS); #endif - printf("SUCCESS\n"); + printf("PASSED\n"); return 0; } \ No newline at end of file diff --git a/test/pico_low_power_test/low_power_test_simple.c b/test/pico_low_power_test/low_power_test_simple.c index 0e715dd3f..aab838c3f 100644 --- a/test/pico_low_power_test/low_power_test_simple.c +++ b/test/pico_low_power_test/low_power_test_simple.c @@ -57,6 +57,6 @@ int main() { #endif } - printf("SUCCESS\n"); + printf("PASSED\n"); return 0; } diff --git a/test/pico_low_power_test/low_power_test_timers.c b/test/pico_low_power_test/low_power_test_timers.c index d0a7150a5..6b5473569 100644 --- a/test/pico_low_power_test/low_power_test_timers.c +++ b/test/pico_low_power_test/low_power_test_timers.c @@ -390,7 +390,7 @@ int main() { } #endif - printf("SUCCESS\n"); + printf("PASSED\n"); return 0; } \ No newline at end of file From 355aea5bc3f55fd3c1b041822ac700b5dc3e3280 Mon Sep 17 00:00:00 2001 From: will-v-pi <108662275+will-v-pi@users.noreply.github.com> Date: Fri, 24 Apr 2026 16:57:18 +0100 Subject: [PATCH 120/127] Increase frequency tolerance in rtc_run_from_external_source --- src/rp2_common/hardware_rtc/rtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rp2_common/hardware_rtc/rtc.c b/src/rp2_common/hardware_rtc/rtc.c index 56df707cd..6eb53a49d 100644 --- a/src/rp2_common/hardware_rtc/rtc.c +++ b/src/rp2_common/hardware_rtc/rtc.c @@ -194,7 +194,7 @@ bool rtc_run_from_external_source(uint32_t src_hz, uint gpio_pin) { if (success) { // Ensure external source is actually running uint32_t rtc_freq = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_RTC); - if (rtc_freq < ((RTC_CLOCK_FREQ_HZ / KHZ) - 1) || rtc_freq > ((RTC_CLOCK_FREQ_HZ / KHZ) + 1)) { + if (rtc_freq < ((RTC_CLOCK_FREQ_HZ / KHZ) - 5) || rtc_freq > ((RTC_CLOCK_FREQ_HZ / KHZ) + 5)) { // Frequency is not within 1kHz of the expected frequency success = false; // reconfigure the clock to the default configuration From b0bcf96a061ef2c1360df7ed9cbbc9ce9acddf00 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 27 Apr 2026 15:24:55 +0100 Subject: [PATCH 121/127] Use time 0 for low_power_start_aon_timer Also use low_power_start_aon_timer_at_time_ms in low power tests --- .../pico_low_power/include/pico/low_power.h | 15 ++++++++++----- test/pico_low_power_test/low_power_test_gpio.c | 9 ++------- test/pico_low_power_test/low_power_test_timers.c | 15 ++++++--------- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/rp2_common/pico_low_power/include/pico/low_power.h b/src/rp2_common/pico_low_power/include/pico/low_power.h index 104308e17..0fd3ead78 100644 --- a/src/rp2_common/pico_low_power/include/pico/low_power.h +++ b/src/rp2_common/pico_low_power/include/pico/low_power.h @@ -293,6 +293,9 @@ pstate_bitset_t *low_power_persistent_pstate_get(pstate_bitset_t *pstate); * \ingroup pico_low_power * See \ref aon_timer_start for more information. * + * If the AON timer is already running, this function will restart it + * from the specified time. + * * \param ms The time in milliseconds to start the AON timer at. * \return true on success, false on failure. */ @@ -304,14 +307,16 @@ static inline bool low_power_start_aon_timer_at_time_ms(uint64_t ms) { /*! \brief Start the AON timer at the current system time * \ingroup pico_low_power + * * See \ref aon_timer_start for more information. * + * If the AON timer is already running, this function will not restart it. + * * \return true on success, false on failure. */ static inline bool low_power_start_aon_timer(void) { - struct timespec ts; - ms_to_timespec(to_ms_64_since_boot(get_absolute_time()), &ts); - return aon_timer_start(&ts); + if (aon_timer_is_running()) return true; + return low_power_start_aon_timer_at_time_ms(0); } /*! \brief Sleep for a number of microseconds @@ -351,7 +356,7 @@ static inline int low_power_sleep_for_ms(uint32_t ms, const clock_dest_bitset_t * \return 0 on success, non-zero on error. */ static inline int low_power_dormant_for_ms(uint32_t ms, dormant_clock_source_t dormant_clock_source, const clock_dest_bitset_t *keep_enabled) { - if (!aon_timer_is_running()) low_power_start_aon_timer(); + low_power_start_aon_timer(); return low_power_dormant_until_aon_timer(aon_timer_make_timeout_time_ms(ms), dormant_clock_source, keep_enabled); } @@ -366,7 +371,7 @@ static inline int low_power_dormant_for_ms(uint32_t ms, dormant_clock_source_t d * \return 0 on success, non-zero on error. */ static inline int low_power_pstate_for_ms(uint32_t ms, pstate_bitset_t *pstate, low_power_pstate_resume_func resume_func) { - if (!aon_timer_is_running()) low_power_start_aon_timer(); + low_power_start_aon_timer(); return low_power_pstate_until_aon_timer(aon_timer_make_timeout_time_ms(ms), pstate, resume_func); } #endif diff --git a/test/pico_low_power_test/low_power_test_gpio.c b/test/pico_low_power_test/low_power_test_gpio.c index db218ba11..681539ab1 100644 --- a/test/pico_low_power_test/low_power_test_gpio.c +++ b/test/pico_low_power_test/low_power_test_gpio.c @@ -81,8 +81,6 @@ int main() { printf("Waiting %d seconds\n", SLEEP_TIME_S); // so we can see some repeat printfs busy_wait_ms(SLEEP_TIME_MS); - absolute_time_t start_time; - struct timespec ts; int ret; printf("Going to sleep until GPIO wakeup\n"); @@ -112,10 +110,7 @@ int main() { printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); - // todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync - start_time = get_absolute_time(); - us_to_timespec(to_us_since_boot(start_time), &ts); - aon_timer_start(&ts); + low_power_start_aon_timer_at_time_ms(0); printf("Going DORMANT until GPIO wakeup\n"); @@ -143,4 +138,4 @@ int main() { printf("PASSED\n"); return 0; -} \ No newline at end of file +} diff --git a/test/pico_low_power_test/low_power_test_timers.c b/test/pico_low_power_test/low_power_test_timers.c index 6b5473569..9e8fb62b2 100644 --- a/test/pico_low_power_test/low_power_test_timers.c +++ b/test/pico_low_power_test/low_power_test_timers.c @@ -138,7 +138,6 @@ int main() { absolute_time_t start_time; static absolute_time_t __persistent_data(wakeup_time); int64_t diff; - struct timespec ts; int ret; low_power_set_external_clock_source(DORMANT_CLOCK_HZ_DEFAULT, RTC_GPIO); @@ -188,10 +187,7 @@ int main() { // start the AON timer - start_time = get_absolute_time(); - us_to_timespec(to_us_since_boot(start_time), &ts); - aon_timer_start(&ts); - + low_power_start_aon_timer_at_time_ms(0); printf("AON timer started @%dms\n", to_ms_since_boot(aon_timer_get_absolute_time())); @@ -251,6 +247,7 @@ int main() { printf("Going DORMANT for %d seconds via AON TIMER\n", SLEEP_TIME_S); start_time = aon_timer_get_absolute_time(); + absolute_time_t system_time_before = get_absolute_time(); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); ret = low_power_dormant_until_aon_timer(wakeup_time, DORMANT_CLOCK_SOURCE_DEFAULT, NULL); if (ret != PICO_OK) { @@ -262,14 +259,14 @@ int main() { #endif EXIT_TEST; } - // need to use the AON timer for checking time, since the other timer is unclocked - diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); - if (diff > -1000000 + // check the system timer was stopped while dormant + diff = absolute_time_diff_us(system_time_before, get_absolute_time()); + if (diff > 50 * 1000 // 50ms #ifdef PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS + (PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS * 1000) #endif ) { - printf("ERROR: doesn't seem like timer was stopped\n"); + printf("ERROR: doesn't seem like timer was stopped: diff %lldus\n", diff); return - 1; } diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); From 22989fd0030c267ebf6d197d58432555efd9f316 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 27 Apr 2026 16:32:43 +0100 Subject: [PATCH 122/127] Improve persistent data locating so it works when other sections are placed between bss and heap Default section_persistent_data.incl now goes into RAM, and you need to override the file to put it at a specific address, to ensure HEAP_LOC is always set correctly in that case --- src/rp2_common/pico_low_power/CMakeLists.txt | 20 ++++--- .../section_persistent_data.incl.template | 9 +++ .../script_include/section_heap.incl | 5 ++ .../section_persistent_data.incl | 8 ++- test/pico_low_power_test/CMakeLists.txt | 59 +++++++------------ 5 files changed, 52 insertions(+), 49 deletions(-) create mode 100644 src/rp2_common/pico_low_power/section_persistent_data.incl.template diff --git a/src/rp2_common/pico_low_power/CMakeLists.txt b/src/rp2_common/pico_low_power/CMakeLists.txt index a29748177..dac8473ee 100644 --- a/src/rp2_common/pico_low_power/CMakeLists.txt +++ b/src/rp2_common/pico_low_power/CMakeLists.txt @@ -19,6 +19,11 @@ pico_mirrored_target_link_libraries(pico_low_power INTERFACE pico_stdio ) +# To work around lack of support for ${CMAKE_CURRENT_FUNCTION_LIST_DIR} in CMake <3.17 +set(PICO_LOW_POWER_CURRENT_PATH ${CMAKE_CURRENT_LIST_DIR}) +pico_register_common_scope_var(PICO_LOW_POWER_CURRENT_PATH) +pico_promote_common_scope_vars() + # pico_set_persistent_data_loc(TARGET PERSISTENT_DATA_LOC) # \brief\ Set the persistent data location for the target # @@ -27,27 +32,26 @@ pico_mirrored_target_link_libraries(pico_low_power INTERFACE # to the appropriate values based on the persistent data location. # # It also sets PICO_CRT0_PIN_XIP_SRAM=1 to pin the XIP_SRAM, -# if the persistent data is stored in XIP_SRAM on RP2350. +# if the persistent data is stored in XIP_SRAM. # # \param\ PERSISTENT_DATA_LOC The persistent data location to set function(pico_set_persistent_data_loc TARGET PERSISTENT_DATA_LOC) - if (NOT PICO_RP2350) - message(FATAL_ERROR "pico_set_persistent_data_loc is only supported on RP2350") + if (PICO_RP2040) + message(FATAL_ERROR "pico_set_persistent_data_loc is not supported on RP2040") endif() - pico_set_linker_script_var(${TARGET} PERSISTENT_DATA_LOC ${PERSISTENT_DATA_LOC}) + # Configure override section_persistent_data.incl for the target + configure_file(${PICO_LOW_POWER_CURRENT_PATH}/section_persistent_data.incl.template ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}/section_persistent_data.incl @ONLY) + pico_add_linker_script_override_path(${TARGET} ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}) if (PERSISTENT_DATA_LOC LESS 0x20000000) - # XIP_SRAM, so heap should come after bss - pico_set_linker_script_var(${TARGET} HEAP_LOC __bss_end__) - # Also pin the XIP_SRAM + # XIP_SRAM, so pin the XIP_SRAM target_compile_definitions(${TARGET} PRIVATE PICO_CRT0_PIN_XIP_SRAM=1) elseif (PERSISTENT_DATA_LOC LESS 0x20040000) # SRAM0, so heap should come after persistent data pico_set_linker_script_var(${TARGET} HEAP_LOC __persistent_data_end__) elseif(PERSISTENT_DATA_LOC LESS 0x20080000) # SRAM1, so heap should come before persistent data - pico_set_linker_script_var(${TARGET} HEAP_LOC __bss_end__) pico_set_linker_script_var(${TARGET} HEAP_LIMIT ${PERSISTENT_DATA_LOC}) else() # Not supported in scratch, as the linker script will overwrite persistent data with scratch data diff --git a/src/rp2_common/pico_low_power/section_persistent_data.incl.template b/src/rp2_common/pico_low_power/section_persistent_data.incl.template new file mode 100644 index 000000000..6f5916939 --- /dev/null +++ b/src/rp2_common/pico_low_power/section_persistent_data.incl.template @@ -0,0 +1,9 @@ +SECTIONS +{ + .persistent_data @PERSISTENT_DATA_LOC@ (NOLOAD) : { + __persistent_data_start__ = .; + *(.persistent_data*) + . = ALIGN(4); + } + PROVIDE(__persistent_data_end__ = .); +} \ No newline at end of file diff --git a/src/rp2_common/pico_standard_link/script_include/section_heap.incl b/src/rp2_common/pico_standard_link/script_include/section_heap.incl index 240e118d4..1f7983432 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_heap.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_heap.incl @@ -4,6 +4,11 @@ SECTIONS { + .dummy_pre_heap (NOLOAD): + { + /* Dummy section to make sure we're back in normal RAM for the heap when HEAP_LOC isn't defined */ + . = .; + } > RAM .heap DEFINED(HEAP_LOC) ? HEAP_LOC : . (NOLOAD): { __end__ = .; diff --git a/src/rp2_common/pico_standard_link/script_include/section_persistent_data.incl b/src/rp2_common/pico_standard_link/script_include/section_persistent_data.incl index 33b449df7..fa41535ed 100644 --- a/src/rp2_common/pico_standard_link/script_include/section_persistent_data.incl +++ b/src/rp2_common/pico_standard_link/script_include/section_persistent_data.incl @@ -1,9 +1,13 @@ +/* Defines the following symbols for use by code: + __persistent_data_start__, __persistent_data_end__ +*/ + SECTIONS { - .persistent_data DEFINED(PERSISTENT_DATA_LOC) ? PERSISTENT_DATA_LOC : . (NOLOAD) : { + .persistent_data (NOLOAD) : { __persistent_data_start__ = .; *(.persistent_data*) . = ALIGN(4); - } + } > RAM PROVIDE(__persistent_data_end__ = .); } \ No newline at end of file diff --git a/test/pico_low_power_test/CMakeLists.txt b/test/pico_low_power_test/CMakeLists.txt index f26c37069..f0a47107b 100644 --- a/test/pico_low_power_test/CMakeLists.txt +++ b/test/pico_low_power_test/CMakeLists.txt @@ -1,9 +1,7 @@ add_executable(low_power_test_timers low_power_test_timers.c ) - target_link_libraries(low_power_test_timers pico_stdlib pico_low_power pico_status_led) - # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_timers) @@ -11,54 +9,50 @@ pico_add_extra_outputs(low_power_test_timers) add_executable(low_power_test_timers_usb low_power_test_timers.c ) - target_link_libraries(low_power_test_timers_usb pico_stdlib pico_low_power pico_status_led) - pico_enable_stdio_usb(low_power_test_timers_usb 1) - # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_timers_usb) -add_executable(low_power_test_timers_sram1 - low_power_test_timers.c - ) - -target_link_libraries(low_power_test_timers_sram1 pico_stdlib pico_low_power pico_status_led) - -if (NOT PICO_RP2040) - pico_set_persistent_data_loc(low_power_test_timers_sram1 0x20040000) -endif() - -# create map/bin/hex file etc. -pico_add_extra_outputs(low_power_test_timers_sram1) - if (NOT PICO_RP2040) if (NOT PICO_RISCV) add_executable(low_power_test_timers_encrypted low_power_test_timers.c ) - target_link_libraries(low_power_test_timers_encrypted pico_stdlib pico_low_power pico_status_led) - pico_set_binary_type(low_power_test_timers_encrypted no_flash) pico_package_uf2_output(low_power_test_timers_encrypted) - pico_sign_binary(low_power_test_timers_encrypted ${CMAKE_SOURCE_DIR}/tools/example_keys/private.pem) - pico_encrypt_binary(low_power_test_timers_encrypted ${CMAKE_SOURCE_DIR}/tools/example_keys/privateaes.bin ${CMAKE_SOURCE_DIR}/tools/example_keys/ivsalt.bin EMBED NO_CLEAR) - + pico_sign_binary(low_power_test_timers_encrypted ${PICO_SDK_PATH}/tools/example_keys/private.pem) + pico_encrypt_binary(low_power_test_timers_encrypted ${PICO_SDK_PATH}/tools/example_keys/privateaes.bin ${PICO_SDK_PATH}/tools/example_keys/ivsalt.bin EMBED NO_CLEAR) # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_timers_encrypted) endif() - add_executable(low_power_test_timers_xip_sram + add_executable(low_power_test_timers_sram0 low_power_test_timers.c ) + target_link_libraries(low_power_test_timers_sram0 pico_stdlib pico_low_power pico_status_led) + pico_set_persistent_data_loc(low_power_test_timers_sram0 0x20020000) + # create map/bin/hex file etc. + pico_add_extra_outputs(low_power_test_timers_sram0) - target_link_libraries(low_power_test_timers_xip_sram pico_stdlib pico_low_power pico_status_led) - pico_set_persistent_data_loc(low_power_test_timers_xip_sram 0x13ffc000) + add_executable(low_power_test_timers_sram1 + low_power_test_timers.c + ) + target_link_libraries(low_power_test_timers_sram1 pico_stdlib pico_low_power pico_status_led) + pico_set_persistent_data_loc(low_power_test_timers_sram1 0x20040000) + # create map/bin/hex file etc. + pico_add_extra_outputs(low_power_test_timers_sram1) + + add_executable(low_power_test_timers_xip_sram + low_power_test_timers.c + ) + target_link_libraries(low_power_test_timers_xip_sram pico_stdlib pico_low_power pico_status_led) + pico_set_persistent_data_loc(low_power_test_timers_xip_sram 0x13ffc000) # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_timers_xip_sram) @@ -66,14 +60,10 @@ if (NOT PICO_RP2040) add_executable(low_power_test_timers_xip_sram_no_flash low_power_test_timers.c ) - target_link_libraries(low_power_test_timers_xip_sram_no_flash pico_stdlib pico_low_power pico_status_led) - pico_set_persistent_data_loc(low_power_test_timers_xip_sram_no_flash 0x13ffc000) - pico_set_binary_type(low_power_test_timers_xip_sram_no_flash no_flash) pico_package_uf2_output(low_power_test_timers_xip_sram_no_flash) - # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_timers_xip_sram_no_flash) endif() @@ -82,9 +72,7 @@ if (PICO_RP2040) add_executable(rtc_clksrc rtc_clksrc.c ) - target_link_libraries(rtc_clksrc pico_stdlib pico_status_led) - # create map/bin/hex file etc. pico_add_extra_outputs(rtc_clksrc) endif() @@ -92,9 +80,7 @@ endif() add_executable(low_power_test_gpio low_power_test_gpio.c ) - target_link_libraries(low_power_test_gpio pico_stdlib pico_low_power pico_status_led) - # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_gpio) @@ -102,11 +88,8 @@ pico_add_extra_outputs(low_power_test_gpio) add_executable(low_power_test_gpio_usb low_power_test_gpio.c ) - target_link_libraries(low_power_test_gpio_usb pico_stdlib pico_low_power pico_status_led) - pico_enable_stdio_usb(low_power_test_gpio_usb 1) - # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_gpio_usb) @@ -114,9 +97,7 @@ pico_add_extra_outputs(low_power_test_gpio_usb) add_executable(low_power_test_simple low_power_test_simple.c ) - target_link_libraries(low_power_test_simple pico_stdlib pico_low_power pico_status_led) - # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_simple) From 62cb6e93f618fef100cd22ff7429a8662a625ae1 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 28 Apr 2026 13:31:40 +0100 Subject: [PATCH 123/127] Update to work with hwtests Use external_sleep_timer to check sleeps are actually 2s, and use that instead of rtc_clksrc --- test/CMakeLists.txt | 2 +- test/pico_low_power_test/BUILD.bazel | 34 +++++---- test/pico_low_power_test/CMakeLists.txt | 72 +++++++++++++----- .../external_sleep_timer.c | 76 +++++++++++++++++++ .../low_power_test_common.h | 41 ++++++++++ .../pico_low_power_test/low_power_test_gpio.c | 42 +++++----- .../low_power_test_simple.c | 20 ++--- .../low_power_test_timers.c | 35 +++++---- test/pico_low_power_test/rtc_clksrc.c | 33 -------- tools/bazel_build.py | 5 +- 10 files changed, 248 insertions(+), 112 deletions(-) create mode 100644 test/pico_low_power_test/external_sleep_timer.c create mode 100644 test/pico_low_power_test/low_power_test_common.h delete mode 100644 test/pico_low_power_test/rtc_clksrc.c diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 80c193bff..d3996654d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -37,7 +37,7 @@ if (PICO_TEST_FILE_GENERATOR AND EXISTS ${PICO_TEST_FILE_GENERATOR}) # - PICO_TEST_FAILURE_STRING: Failure string for the test (default is "FAILURE_STRING") # Can be used to force failure even when the test prints the success string # - PICO_TEST_BUDDY_FILE: File to run on buddy device for the test (default is NONE) - # For example, low power dormant tests on RP2040 require rtc_clksrc running on the buddy device + # For example, low power tests use external_sleep_timer running on the buddy device # This can either be a path relative to the test target, or an absolute path # - PICO_TEST_SKIP_IN_CI: Whether to skip the test in ci (default is FALSE) # If TRUE, the test is not included in the ci test suite diff --git a/test/pico_low_power_test/BUILD.bazel b/test/pico_low_power_test/BUILD.bazel index 598d7cc81..7483faf5a 100644 --- a/test/pico_low_power_test/BUILD.bazel +++ b/test/pico_low_power_test/BUILD.bazel @@ -1,16 +1,27 @@ +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") load("//bazel:defs.bzl", "compatible_with_rp2") package(default_visibility = ["//visibility:public"]) +cc_library( + name = "low_power_test_common", + hdrs = ["low_power_test_common.h"], + includes = ["."], + deps = [ + "//src/rp2_common/pico_stdlib", + "//src/rp2_common/pico_low_power", + "//src/rp2_common/pico_status_led", + ], +) + cc_binary( name = "low_power_test_timers", testonly = True, srcs = ["low_power_test_timers.c"], target_compatible_with = compatible_with_rp2(), deps = [ - "//src/rp2_common/pico_stdlib", - "//src/rp2_common/pico_low_power", - "//src/rp2_common/pico_status_led", + "low_power_test_common", ], ) @@ -20,9 +31,7 @@ cc_binary( srcs = ["low_power_test_gpio.c"], target_compatible_with = compatible_with_rp2(), deps = [ - "//src/rp2_common/pico_stdlib", - "//src/rp2_common/pico_low_power", - "//src/rp2_common/pico_status_led", + "low_power_test_common", ], ) @@ -32,19 +41,16 @@ cc_binary( srcs = ["low_power_test_simple.c"], target_compatible_with = compatible_with_rp2(), deps = [ - "//src/rp2_common/pico_stdlib", - "//src/rp2_common/pico_low_power", - "//src/rp2_common/pico_status_led", + "low_power_test_common", ], ) cc_binary( - name = "rtc_clksrc", + name = "external_sleep_timer", testonly = True, - srcs = ["rtc_clksrc.c"], - target_compatible_with = ["//bazel/constraint:rp2040"], + srcs = ["external_sleep_timer.c"], + target_compatible_with = compatible_with_rp2(), deps = [ - "//src/rp2_common/pico_stdlib", - "//src/rp2_common/pico_status_led", + "low_power_test_common", ], ) diff --git a/test/pico_low_power_test/CMakeLists.txt b/test/pico_low_power_test/CMakeLists.txt index f0a47107b..452c64e1f 100644 --- a/test/pico_low_power_test/CMakeLists.txt +++ b/test/pico_low_power_test/CMakeLists.txt @@ -1,7 +1,14 @@ +add_library(low_power_test_common INTERFACE) +target_link_libraries(low_power_test_common INTERFACE pico_stdlib pico_low_power pico_status_led) +target_include_directories(low_power_test_common INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + add_executable(low_power_test_timers low_power_test_timers.c ) -target_link_libraries(low_power_test_timers pico_stdlib pico_low_power pico_status_led) +target_link_libraries(low_power_test_timers low_power_test_common) +set_target_properties(low_power_test_timers PROPERTIES PICO_TEST_TIMEOUT 35) +set_target_properties(low_power_test_timers PROPERTIES PICO_TEST_FAILURE_STRING "ERROR:") +set_target_properties(low_power_test_timers PROPERTIES PICO_TEST_BUDDY_FILE external_sleep_timer.elf) # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_timers) @@ -9,8 +16,11 @@ pico_add_extra_outputs(low_power_test_timers) add_executable(low_power_test_timers_usb low_power_test_timers.c ) -target_link_libraries(low_power_test_timers_usb pico_stdlib pico_low_power pico_status_led) +target_link_libraries(low_power_test_timers_usb low_power_test_common) pico_enable_stdio_usb(low_power_test_timers_usb 1) +set_target_properties(low_power_test_timers_usb PROPERTIES PICO_TEST_TIMEOUT 35) +set_target_properties(low_power_test_timers_usb PROPERTIES PICO_TEST_FAILURE_STRING "ERROR:") +set_target_properties(low_power_test_timers_usb PROPERTIES PICO_TEST_BUDDY_FILE external_sleep_timer.elf) # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_timers_usb) @@ -20,11 +30,14 @@ if (NOT PICO_RP2040) add_executable(low_power_test_timers_encrypted low_power_test_timers.c ) - target_link_libraries(low_power_test_timers_encrypted pico_stdlib pico_low_power pico_status_led) + target_link_libraries(low_power_test_timers_encrypted low_power_test_common) pico_set_binary_type(low_power_test_timers_encrypted no_flash) pico_package_uf2_output(low_power_test_timers_encrypted) pico_sign_binary(low_power_test_timers_encrypted ${PICO_SDK_PATH}/tools/example_keys/private.pem) pico_encrypt_binary(low_power_test_timers_encrypted ${PICO_SDK_PATH}/tools/example_keys/privateaes.bin ${PICO_SDK_PATH}/tools/example_keys/ivsalt.bin EMBED NO_CLEAR) + set_target_properties(low_power_test_timers_encrypted PROPERTIES PICO_TEST_TIMEOUT 35) + set_target_properties(low_power_test_timers_encrypted PROPERTIES PICO_TEST_FAILURE_STRING "ERROR:") + set_target_properties(low_power_test_timers_encrypted PROPERTIES PICO_TEST_BUDDY_FILE external_sleep_timer.elf) # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_timers_encrypted) endif() @@ -33,54 +46,71 @@ if (NOT PICO_RP2040) add_executable(low_power_test_timers_sram0 low_power_test_timers.c ) - target_link_libraries(low_power_test_timers_sram0 pico_stdlib pico_low_power pico_status_led) + target_link_libraries(low_power_test_timers_sram0 low_power_test_common) pico_set_persistent_data_loc(low_power_test_timers_sram0 0x20020000) # create map/bin/hex file etc. + set_target_properties(low_power_test_timers_sram0 PROPERTIES PICO_TEST_TIMEOUT 35) + set_target_properties(low_power_test_timers_sram0 PROPERTIES PICO_TEST_FAILURE_STRING "ERROR:") + set_target_properties(low_power_test_timers_sram0 PROPERTIES PICO_TEST_BUDDY_FILE external_sleep_timer.elf) pico_add_extra_outputs(low_power_test_timers_sram0) add_executable(low_power_test_timers_sram1 low_power_test_timers.c ) - target_link_libraries(low_power_test_timers_sram1 pico_stdlib pico_low_power pico_status_led) + target_link_libraries(low_power_test_timers_sram1 low_power_test_common) pico_set_persistent_data_loc(low_power_test_timers_sram1 0x20040000) # create map/bin/hex file etc. + set_target_properties(low_power_test_timers_sram1 PROPERTIES PICO_TEST_TIMEOUT 35) + set_target_properties(low_power_test_timers_sram1 PROPERTIES PICO_TEST_FAILURE_STRING "ERROR:") + set_target_properties(low_power_test_timers_sram1 PROPERTIES PICO_TEST_BUDDY_FILE external_sleep_timer.elf) pico_add_extra_outputs(low_power_test_timers_sram1) add_executable(low_power_test_timers_xip_sram low_power_test_timers.c ) - target_link_libraries(low_power_test_timers_xip_sram pico_stdlib pico_low_power pico_status_led) + target_link_libraries(low_power_test_timers_xip_sram low_power_test_common) pico_set_persistent_data_loc(low_power_test_timers_xip_sram 0x13ffc000) # create map/bin/hex file etc. + set_target_properties(low_power_test_timers_xip_sram PROPERTIES PICO_TEST_TIMEOUT 35) + set_target_properties(low_power_test_timers_xip_sram PROPERTIES PICO_TEST_FAILURE_STRING "ERROR:") + set_target_properties(low_power_test_timers_xip_sram PROPERTIES PICO_TEST_BUDDY_FILE external_sleep_timer.elf) pico_add_extra_outputs(low_power_test_timers_xip_sram) add_executable(low_power_test_timers_xip_sram_no_flash low_power_test_timers.c ) - target_link_libraries(low_power_test_timers_xip_sram_no_flash pico_stdlib pico_low_power pico_status_led) + target_link_libraries(low_power_test_timers_xip_sram_no_flash low_power_test_common) pico_set_persistent_data_loc(low_power_test_timers_xip_sram_no_flash 0x13ffc000) pico_set_binary_type(low_power_test_timers_xip_sram_no_flash no_flash) pico_package_uf2_output(low_power_test_timers_xip_sram_no_flash) # create map/bin/hex file etc. + set_target_properties(low_power_test_timers_xip_sram_no_flash PROPERTIES PICO_TEST_TIMEOUT 35) + set_target_properties(low_power_test_timers_xip_sram_no_flash PROPERTIES PICO_TEST_FAILURE_STRING "ERROR:") + set_target_properties(low_power_test_timers_xip_sram_no_flash PROPERTIES PICO_TEST_BUDDY_FILE external_sleep_timer.elf) pico_add_extra_outputs(low_power_test_timers_xip_sram_no_flash) endif() -if (PICO_RP2040) - add_executable(rtc_clksrc - rtc_clksrc.c - ) - target_link_libraries(rtc_clksrc pico_stdlib pico_status_led) - # create map/bin/hex file etc. - pico_add_extra_outputs(rtc_clksrc) -endif() + +add_executable(external_sleep_timer + external_sleep_timer.c + ) +target_link_libraries(external_sleep_timer low_power_test_common) +# This is a buddy program, not a test +set_target_properties(external_sleep_timer PROPERTIES PICO_TEST_SKIP_IN_CI TRUE) +# create map/bin/hex file etc. +pico_add_extra_outputs(external_sleep_timer) + add_executable(low_power_test_gpio low_power_test_gpio.c ) -target_link_libraries(low_power_test_gpio pico_stdlib pico_low_power pico_status_led) +target_link_libraries(low_power_test_gpio low_power_test_common) +set_target_properties(low_power_test_gpio PROPERTIES PICO_TEST_TIMEOUT 25) +set_target_properties(low_power_test_gpio PROPERTIES PICO_TEST_FAILURE_STRING "ERROR:") +set_target_properties(low_power_test_gpio PROPERTIES PICO_TEST_BUDDY_FILE external_sleep_timer.elf) # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_gpio) @@ -88,8 +118,11 @@ pico_add_extra_outputs(low_power_test_gpio) add_executable(low_power_test_gpio_usb low_power_test_gpio.c ) -target_link_libraries(low_power_test_gpio_usb pico_stdlib pico_low_power pico_status_led) +target_link_libraries(low_power_test_gpio_usb low_power_test_common) pico_enable_stdio_usb(low_power_test_gpio_usb 1) +set_target_properties(low_power_test_gpio_usb PROPERTIES PICO_TEST_TIMEOUT 25) +set_target_properties(low_power_test_gpio_usb PROPERTIES PICO_TEST_FAILURE_STRING "ERROR:") +set_target_properties(low_power_test_gpio_usb PROPERTIES PICO_TEST_BUDDY_FILE external_sleep_timer.elf) # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_gpio_usb) @@ -97,7 +130,10 @@ pico_add_extra_outputs(low_power_test_gpio_usb) add_executable(low_power_test_simple low_power_test_simple.c ) -target_link_libraries(low_power_test_simple pico_stdlib pico_low_power pico_status_led) +target_link_libraries(low_power_test_simple low_power_test_common) +set_target_properties(low_power_test_simple PROPERTIES PICO_TEST_TIMEOUT 25) +set_target_properties(low_power_test_simple PROPERTIES PICO_TEST_FAILURE_STRING "ERROR:") +set_target_properties(low_power_test_simple PROPERTIES PICO_TEST_BUDDY_FILE external_sleep_timer.elf) # create map/bin/hex file etc. pico_add_extra_outputs(low_power_test_simple) diff --git a/test/pico_low_power_test/external_sleep_timer.c b/test/pico_low_power_test/external_sleep_timer.c new file mode 100644 index 000000000..1d18464bf --- /dev/null +++ b/test/pico_low_power_test/external_sleep_timer.c @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2026 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "pico/stdlib.h" +#include "pico/sync.h" +#include "hardware/clocks.h" + +#include "low_power_test_common.h" + +#if PICO_RP2040 +#define TOLERANCE_MS 1000 // The resolution of the AON timer is 1s on RP2040 +#else +#define TOLERANCE_MS 50 +#endif +#define MIN_SLEEP_TIME_MS SLEEP_TIME_MS - TOLERANCE_MS +#define MAX_SLEEP_TIME_MS SLEEP_TIME_MS + TOLERANCE_MS + +uint32_t wakeup_time_ms = 0; +uint32_t sleep_time_ms = 0; +bool good_sleep_done = false; + +int64_t wake_up_gpio(__unused alarm_id_t id, __unused void *param) { + gpio_put(WAKE_UP_PIN, 0); + return 0; +} + +static alarm_id_t wake_up_alarm_id; + +void gpio_callback(uint gpio, uint32_t events) { + if (events & GPIO_IRQ_EDGE_RISE) { + wakeup_time_ms = to_ms_since_boot(get_absolute_time()); + printf("Woke up at %dms\n", wakeup_time_ms); + gpio_put(WAKE_UP_PIN, 1); + } else if (events & GPIO_IRQ_EDGE_FALL) { + sleep_time_ms = to_ms_since_boot(get_absolute_time()); + printf("Went to sleep at %dms\n", sleep_time_ms); + wake_up_alarm_id = add_alarm_in_ms(SLEEP_TIME_MS, wake_up_gpio, NULL, false); + } + if (wakeup_time_ms > sleep_time_ms) { + uint32_t diff = wakeup_time_ms - sleep_time_ms; + if (good_sleep_done && (diff < MIN_SLEEP_TIME_MS || diff > MAX_SLEEP_TIME_MS)) { + printf("ERROR: Was asleep for %dms, expected between %dms and %dms\n", diff, MIN_SLEEP_TIME_MS, MAX_SLEEP_TIME_MS); + } else if (diff >= MIN_SLEEP_TIME_MS && diff <= MAX_SLEEP_TIME_MS){ + printf("Was asleep for %dms\n", diff); + good_sleep_done = true; + } + } +} + + +int main() { + stdio_init_all(); + +#if PICO_RP2040 + printf("Outputting RTC clock to GPIO %d\n", RTC_GPIO_OUT); + clock_gpio_init(RTC_GPIO_OUT, CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_VALUE_CLK_RTC, 1); +#endif + + printf("Monitoring for sleep events on GPIO %d\n", SLEEP_MONITOR_PIN); + gpio_init(SLEEP_MONITOR_PIN); + gpio_pull_up(SLEEP_MONITOR_PIN); + gpio_set_irq_enabled_with_callback(SLEEP_MONITOR_PIN, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback); + + printf("Waking up device on GPIO %d\n", WAKE_UP_PIN); + gpio_init(WAKE_UP_PIN); + gpio_set_dir(WAKE_UP_PIN, GPIO_OUT); + gpio_put(WAKE_UP_PIN, 1); + + while (true) __wfi(); + + return 0; +} \ No newline at end of file diff --git a/test/pico_low_power_test/low_power_test_common.h b/test/pico_low_power_test/low_power_test_common.h new file mode 100644 index 000000000..d09e5c077 --- /dev/null +++ b/test/pico_low_power_test/low_power_test_common.h @@ -0,0 +1,41 @@ +#ifndef LOW_POWER_TEST_COMMON_H +#define LOW_POWER_TEST_COMMON_H + +#include +#include +#include "pico/stdlib.h" +#include "pico/low_power.h" +#include "pico/aon_timer.h" +#include "pico/status_led.h" +#include "hardware/structs/xip_ctrl.h" + +#define SLEEP_TIME_S 2 +#define SLEEP_TIME_MS SLEEP_TIME_S * 1000 + +// Use default I2C pins as that should be connected to the other board's I2C pins +#define SLEEP_MONITOR_PIN PICO_DEFAULT_I2C_SDA_PIN +#define WAKE_UP_PIN PICO_DEFAULT_I2C_SCL_PIN + +// On RP2040 this must be a GPIO that supports clock input, see the GPIO function table in the datasheet. +#define RTC_GPIO_IN 22 + +// On RP2040 this must be a GPIO that supports clock output, see the GPIO function table in the datasheet. +#define RTC_GPIO_OUT 21 + + +static inline void init_external_gpios(void) { + gpio_init(SLEEP_MONITOR_PIN); + gpio_set_dir(SLEEP_MONITOR_PIN, GPIO_OUT); + gpio_put(SLEEP_MONITOR_PIN, 1); + gpio_init(WAKE_UP_PIN); + gpio_pull_up(WAKE_UP_PIN); +} + +#if HAS_POWMAN_TIMER +static inline void init_powman_ext_ctrl(void) { + powman_hw->ext_ctrl[0] = POWMAN_EXT_CTRL0_LP_EXIT_STATE_BITS | POWMAN_EXT_CTRL0_INIT_STATE_BITS | SLEEP_MONITOR_PIN; + hw_set_bits(&powman_hw->ext_ctrl[0], POWMAN_EXT_CTRL0_INIT_BITS); +} +#endif + +#endif // LOW_POWER_TEST_COMMON_H \ No newline at end of file diff --git a/test/pico_low_power_test/low_power_test_gpio.c b/test/pico_low_power_test/low_power_test_gpio.c index 681539ab1..080deec80 100644 --- a/test/pico_low_power_test/low_power_test_gpio.c +++ b/test/pico_low_power_test/low_power_test_gpio.c @@ -4,15 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#include -#include -#include "pico/stdlib.h" -#include "pico/low_power.h" -#include "pico/aon_timer.h" -#include "pico/status_led.h" - -#define SLEEP_TIME_S 2 -#define SLEEP_TIME_MS SLEEP_TIME_S * 1000 +#include "low_power_test_common.h" bool repeater(repeating_timer_t *timer) { if (aon_timer_is_running()) { @@ -63,6 +55,7 @@ int main() { stdio_init_all(); status_led_init(); printf("Hello Sleep!\n"); + init_external_gpios(); // use a repeating timer; it should be gated // during our sleep (todo not sure how it affects power!) repeating_timer_t repeat; @@ -85,7 +78,9 @@ int main() { printf("Going to sleep until GPIO wakeup\n"); - low_power_sleep_until_gpio_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, NULL, true); + gpio_put(SLEEP_MONITOR_PIN, 0); + low_power_sleep_until_gpio_pin_state(WAKE_UP_PIN, true, false, NULL, true); + gpio_put(SLEEP_MONITOR_PIN, 1); printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); @@ -100,30 +95,41 @@ int main() { clock_dest_bitset_add(&keep_enabled, CLK_DEST_REF_TICKS); #endif - low_power_sleep_until_gpio_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, &keep_enabled, false); + gpio_put(SLEEP_MONITOR_PIN, 0); + low_power_sleep_until_gpio_pin_state(WAKE_UP_PIN, true, false, &keep_enabled, false); + gpio_put(SLEEP_MONITOR_PIN, 1); printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); - printf("Going to sleep until any wakeup (expecting stdin characters)\n"); + // Skip this test as it requires stdin characters + // printf("Going to sleep until any wakeup (expecting stdin characters)\n"); - low_power_sleep_until_irq(NULL); - printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); - busy_wait_ms(SLEEP_TIME_MS); + // gpio_put(SLEEP_MONITOR_PIN, 0); + // low_power_sleep_until_irq(NULL); + // gpio_put(SLEEP_MONITOR_PIN, 1); + // printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); + // busy_wait_ms(SLEEP_TIME_MS); low_power_start_aon_timer_at_time_ms(0); printf("Going DORMANT until GPIO wakeup\n"); - low_power_dormant_until_gpio_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, DORMANT_CLOCK_SOURCE_ROSC, NULL); + gpio_put(SLEEP_MONITOR_PIN, 0); + low_power_dormant_until_gpio_pin_state(WAKE_UP_PIN, true, false, DORMANT_CLOCK_SOURCE_ROSC, NULL); + gpio_put(SLEEP_MONITOR_PIN, 1); printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S); busy_wait_ms(SLEEP_TIME_MS); #if HAS_POWMAN_TIMER printf("Going to PSTATE until GPIO wakeup\n"); - ret = low_power_pstate_until_gpio_pin_state(PICO_DEFAULT_UART_RX_PIN, true, false, NULL, pstate_resume_func); + // Setup ext_ctrl0 to output on the SLEEP_MONITOR_PIN + init_powman_ext_ctrl(); + + gpio_put(SLEEP_MONITOR_PIN, 0); + ret = low_power_pstate_until_gpio_pin_state(WAKE_UP_PIN, true, false, NULL, pstate_resume_func); - printf("%d low_power_pstate_until_gpio_pin_state returned\n", ret); + printf("ERROR: %d returned by low_power_pstate_until_gpio_pin_state\n", ret); while (true) { printf("Waiting\n"); busy_wait_ms(1000); diff --git a/test/pico_low_power_test/low_power_test_simple.c b/test/pico_low_power_test/low_power_test_simple.c index aab838c3f..4599c65c9 100644 --- a/test/pico_low_power_test/low_power_test_simple.c +++ b/test/pico_low_power_test/low_power_test_simple.c @@ -4,14 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#include -#include "pico/stdlib.h" -#include "pico/status_led.h" -#include "pico/low_power.h" - -#define SLEEP_TIME_MS 1000 - -#define RTC_GPIO 22 // must support clock input, see the GPIO function table in the datasheet. +#include "low_power_test_common.h" bool repeater(repeating_timer_t *timer) { printf(" Repeating timer at %dms\n", to_ms_since_boot(get_absolute_time())); @@ -23,7 +16,9 @@ int main() { stdio_init_all(); status_led_init(); - low_power_set_external_clock_source(DORMANT_CLOCK_HZ_DEFAULT, RTC_GPIO); + init_external_gpios(); + + low_power_set_external_clock_source(DORMANT_CLOCK_HZ_DEFAULT, RTC_GPIO_IN); int ret; static int __persistent_data(num_runs); @@ -31,7 +26,9 @@ int main() { printf("Run %d\n", num_runs); printf("Going to sleep for %dms\n", SLEEP_TIME_MS); + gpio_put(SLEEP_MONITOR_PIN, 0); ret = low_power_sleep_for_ms(SLEEP_TIME_MS, NULL, true); + gpio_put(SLEEP_MONITOR_PIN, 1); if (ret != PICO_OK) { printf("ERROR: low_power_sleep_for_ms returned %d\n", ret); } else { @@ -39,7 +36,9 @@ int main() { } printf("Going dormant for %dms\n", SLEEP_TIME_MS); + gpio_put(SLEEP_MONITOR_PIN, 0); ret = low_power_dormant_for_ms(SLEEP_TIME_MS, DORMANT_CLOCK_SOURCE_DEFAULT, NULL); + gpio_put(SLEEP_MONITOR_PIN, 1); if (ret != PICO_OK) { printf("ERROR: low_power_dormant_for_ms returned %d\n", ret); } else { @@ -48,6 +47,9 @@ int main() { #if HAS_POWMAN_TIMER printf("Going to Pstate for %dms\n", SLEEP_TIME_MS); + // Setup ext_ctrl0 to output on the SLEEP_MONITOR_PIN + init_powman_ext_ctrl(); + gpio_put(SLEEP_MONITOR_PIN, 0); ret = low_power_pstate_for_ms(SLEEP_TIME_MS, NULL, NULL); if (ret != PICO_OK) { printf("%d ERROR: low_power_pstate_for_ms returned\n", ret); diff --git a/test/pico_low_power_test/low_power_test_timers.c b/test/pico_low_power_test/low_power_test_timers.c index 9e8fb62b2..c3f981b64 100644 --- a/test/pico_low_power_test/low_power_test_timers.c +++ b/test/pico_low_power_test/low_power_test_timers.c @@ -4,17 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#include -#include -#include "pico/stdlib.h" -#include "pico/low_power.h" -#include "pico/status_led.h" -#include "hardware/structs/xip_ctrl.h" - -#define SLEEP_TIME_S 2 -#define SLEEP_TIME_MS SLEEP_TIME_S * 1000 - -#define RTC_GPIO 22 // must support clock input, see the GPIO function table in the datasheet. +#include "low_power_test_common.h" // Set to 1 to continue after an error, 0 to exit #if 0 @@ -95,6 +85,8 @@ int main() { status_led_init(); printf("Hello Sleep!\n"); + init_external_gpios(); + // use a repeating timer on the same TIMER instance; it should be disabled // during exclusive sleep (todo not sure how it affects power!) repeating_timer_t repeat; @@ -140,13 +132,14 @@ int main() { int64_t diff; int ret; - low_power_set_external_clock_source(DORMANT_CLOCK_HZ_DEFAULT, RTC_GPIO); + low_power_set_external_clock_source(DORMANT_CLOCK_HZ_DEFAULT, RTC_GPIO_IN); // exclusive sleep printf("Going to sleep for %d seconds via TIMER\n", SLEEP_TIME_S); + gpio_put(SLEEP_MONITOR_PIN, 0); start_time = get_absolute_time(); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); ret = low_power_sleep_until_timer(timer_hw, wakeup_time, NULL, true); @@ -154,6 +147,7 @@ int main() { printf("ERROR: %d returned by low_power_sleep_until_timer\n", ret); EXIT_TEST; } + gpio_put(SLEEP_MONITOR_PIN, 1); diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); printf("Woken up now @%dus since target\n", (int)diff); if (diff < 0) { @@ -168,6 +162,7 @@ int main() { // non-exclusive sleep printf("Going to non-exclusive sleep for %d seconds via TIMER\n", SLEEP_TIME_S); + gpio_put(SLEEP_MONITOR_PIN, 0); start_time = get_absolute_time(); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); ret = low_power_sleep_until_timer(timer_hw, wakeup_time, NULL, false); @@ -175,6 +170,7 @@ int main() { printf("ERROR: %d returned by low_power_sleep_until_timer\n", ret); EXIT_TEST; } + gpio_put(SLEEP_MONITOR_PIN, 1); diff = absolute_time_diff_us(wakeup_time, get_absolute_time()); printf("Woken up now @%dus since target\n", (int)diff); if (diff < 0) { @@ -195,6 +191,7 @@ int main() { // exclusive sleep using the AON timer printf("Going to sleep for %d seconds via AON timer\n", SLEEP_TIME_S); + gpio_put(SLEEP_MONITOR_PIN, 0); start_time = aon_timer_get_absolute_time(); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); ret = low_power_sleep_until_aon_timer(wakeup_time, NULL, true); @@ -202,6 +199,7 @@ int main() { printf("ERROR: %d returned by low_power_sleep_until_aon_timer\n", ret); EXIT_TEST; } + gpio_put(SLEEP_MONITOR_PIN, 1); diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); printf("Woken up now @%dus since target\n", (int)diff); if (diff < 0) { @@ -225,6 +223,7 @@ int main() { clock_dest_bitset_add(&keep_enabled, CLK_DEST_REF_TICKS); #endif + gpio_put(SLEEP_MONITOR_PIN, 0); start_time = aon_timer_get_absolute_time(); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); ret = low_power_sleep_until_aon_timer(wakeup_time, &keep_enabled, false); @@ -232,6 +231,7 @@ int main() { printf("ERROR: %d returned by low_power_sleep_until_aon_timer\n", ret); EXIT_TEST; } + gpio_put(SLEEP_MONITOR_PIN, 1); diff = absolute_time_diff_us(wakeup_time, aon_timer_get_absolute_time()); printf("Woken up now @%dus since target\n", (int)diff); if (diff < 0) { @@ -246,6 +246,7 @@ int main() { // dormant printf("Going DORMANT for %d seconds via AON TIMER\n", SLEEP_TIME_S); + gpio_put(SLEEP_MONITOR_PIN, 0); start_time = aon_timer_get_absolute_time(); absolute_time_t system_time_before = get_absolute_time(); wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); @@ -254,11 +255,12 @@ int main() { printf("ERROR: %d returned by low_power_dormant_until_aon_timer\n", ret); #if PICO_RP2040 if (ret == PICO_ERROR_PRECONDITION_NOT_MET) { - printf("ERROR: RTC clock source is not running - connect a device running rtc_clksrc to GPIO %d\n", RTC_GPIO); + printf("ERROR: RTC clock source is not running - connect a device running external_sleep_timer to GPIO %d\n", RTC_GPIO_IN); } #endif EXIT_TEST; } + gpio_put(SLEEP_MONITOR_PIN, 1); // check the system timer was stopped while dormant diff = absolute_time_diff_us(system_time_before, get_absolute_time()); if (diff > 50 * 1000 // 50ms @@ -284,14 +286,17 @@ int main() { // pstate with sram0 on printf("Going to PSTATE with persistent data on for %d seconds\n", SLEEP_TIME_S); + // Setup ext_ctrl0 to output on the SLEEP_MONITOR_PIN + init_powman_ext_ctrl(); + if (my_number != 12345) { printf("ERROR: my_number is %d not 12345 - initialisation issue?\n", my_number); EXIT_TEST; } my_number = 67890; + gpio_put(SLEEP_MONITOR_PIN, 0); start_time = aon_timer_get_absolute_time(); - wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); ret = low_power_pstate_until_aon_timer(wakeup_time, NULL, pstate_resume_func); @@ -335,8 +340,8 @@ int main() { // pstate with sram off printf("Going to PSTATE with SRAM off for %d seconds\n", SLEEP_TIME_S); + gpio_put(SLEEP_MONITOR_PIN, 0); start_time = aon_timer_get_absolute_time(); - wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS); // store in scratch, as not persisting memory over this reboot powman_hw->scratch[0] = to_us_since_boot(wakeup_time) & 0xFFFFFFFF; diff --git a/test/pico_low_power_test/rtc_clksrc.c b/test/pico_low_power_test/rtc_clksrc.c deleted file mode 100644 index cda603b02..000000000 --- a/test/pico_low_power_test/rtc_clksrc.c +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2026 Raspberry Pi (Trading) Ltd. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include "pico/stdlib.h" -#include "pico/status_led.h" -#include "pico/sync.h" -#include "hardware/clocks.h" - -#define RTC_GPIO 21 - -bool repeater(repeating_timer_t *timer) { - printf(" Repeating timer at %dms\n", to_ms_since_boot(get_absolute_time())); - status_led_set_state(!status_led_get_state()); - return true; -} - -int main() { - stdio_init_all(); - status_led_init(); - - clock_gpio_init(RTC_GPIO, CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_VALUE_CLK_RTC, 1); - - repeating_timer_t repeat; - add_repeating_timer_ms(500, repeater, NULL, &repeat); - - while (true) __wfi(); - - return 0; -} \ No newline at end of file diff --git a/tools/bazel_build.py b/tools/bazel_build.py index ad4f607dd..7aa18173b 100755 --- a/tools/bazel_build.py +++ b/tools/bazel_build.py @@ -55,7 +55,7 @@ "//test/pico_low_power_test:low_power_test_timers", "//test/pico_low_power_test:low_power_test_gpio", "//test/pico_low_power_test:low_power_test_simple", - "//test/pico_low_power_test:rtc_clksrc", + "//test/pico_low_power_test:external_sleep_timer", "//test/pico_async_context_test:pico_async_context_test", # Pretty much only Picotool and pioasm build on Windows. @@ -96,7 +96,6 @@ "//test/pico_float_test:hazard3_test_gen", # RP2040 only "//test/kitchen_sink:kitchen_sink_blocked_ram", - "//test/pico_low_power_test:rtc_clksrc", # TODO: RISC-V support. "//test/pico_float_test:pico_float_test_hazard3", ) @@ -139,7 +138,6 @@ "//test/pico_float_test:hazard3_test_gen", # RP2040 only "//test/kitchen_sink:kitchen_sink_blocked_ram", - "//test/pico_low_power_test:rtc_clksrc", # TODO: RISC-V support. "//test/pico_float_test:pico_float_test_hazard3", # not supported by clang @@ -178,7 +176,6 @@ "//test/pico_float_test:hazard3_test_gen", # RP2040 only "//test/kitchen_sink:kitchen_sink_blocked_ram", - "//test/pico_low_power_test:rtc_clksrc", # TODO: RISC-V support. "//test/pico_float_test:pico_float_test_hazard3", ) From 65782d2b1b91c96d0afb2cdcf275f7f79b8d57ce Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 28 Apr 2026 15:06:41 +0100 Subject: [PATCH 124/127] Fix kitchen_sink to complete with aon_timer The aon_timer test had an infinite while loop --- test/kitchen_sink/kitchen_sink.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index 104b20bb8..5a82a1672 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -72,6 +72,14 @@ void svc_call(void) { exit(0); } +#if LIB_PICO_AON_TIMER +static bool aon_timer_done = false; +void spoop(void) { + printf("XXXX YARGLE XXXX\n"); + aon_timer_done = true; +} +#endif + int main(void) { spiggle(); @@ -137,15 +145,14 @@ int main(void) { #endif #if LIB_PICO_AON_TIMER aon_timer_start_with_timeofday(); - void spoop(void); struct timespec ts; - ts.tv_sec = 6; + ts.tv_sec = 2; ts.tv_nsec = 1000000000 / 2; aon_timer_enable_alarm(&ts, spoop, false); - while (true) { + while (!aon_timer_done) { aon_timer_get_time(&ts); printf("%ld %ld\n", (long)ts.tv_sec, ts.tv_nsec); - busy_wait_ms(4000); + busy_wait_ms(500); } #endif #ifndef __riscv @@ -156,9 +163,3 @@ int main(void) { puts("PASSED"); #endif } - -#if LIB_PICO_AON_TIMER -void spoop(void) { - printf("XXXX YARGLE XXXX\n"); -} -#endif From 30c9e31ace2bcbaf5aaf7b29bcf92ec527c912b9 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 29 Apr 2026 10:25:49 +0100 Subject: [PATCH 125/127] Add more tolerance into external_sleep_timer --- test/pico_low_power_test/external_sleep_timer.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/test/pico_low_power_test/external_sleep_timer.c b/test/pico_low_power_test/external_sleep_timer.c index 1d18464bf..3aabbdb6c 100644 --- a/test/pico_low_power_test/external_sleep_timer.c +++ b/test/pico_low_power_test/external_sleep_timer.c @@ -14,10 +14,11 @@ #if PICO_RP2040 #define TOLERANCE_MS 1000 // The resolution of the AON timer is 1s on RP2040 #else -#define TOLERANCE_MS 50 +#define TOLERANCE_MS 100 #endif #define MIN_SLEEP_TIME_MS SLEEP_TIME_MS - TOLERANCE_MS #define MAX_SLEEP_TIME_MS SLEEP_TIME_MS + TOLERANCE_MS +#define RESET_SLEEP_TIME_MS MAX_SLEEP_TIME_MS * 3 uint32_t wakeup_time_ms = 0; uint32_t sleep_time_ms = 0; @@ -40,13 +41,20 @@ void gpio_callback(uint gpio, uint32_t events) { printf("Went to sleep at %dms\n", sleep_time_ms); wake_up_alarm_id = add_alarm_in_ms(SLEEP_TIME_MS, wake_up_gpio, NULL, false); } - if (wakeup_time_ms > sleep_time_ms) { + if (wakeup_time_ms > sleep_time_ms && sleep_time_ms) { uint32_t diff = wakeup_time_ms - sleep_time_ms; - if (good_sleep_done && (diff < MIN_SLEEP_TIME_MS || diff > MAX_SLEEP_TIME_MS)) { + if (diff > RESET_SLEEP_TIME_MS) { + printf("Resetting due to long sleep of %dms\n", diff); + good_sleep_done = false; + } else if (diff < TOLERANCE_MS) { + printf("Ignoring sleep of %dms\n", diff); + } else if (good_sleep_done && (diff < MIN_SLEEP_TIME_MS || diff > MAX_SLEEP_TIME_MS)) { printf("ERROR: Was asleep for %dms, expected between %dms and %dms\n", diff, MIN_SLEEP_TIME_MS, MAX_SLEEP_TIME_MS); } else if (diff >= MIN_SLEEP_TIME_MS && diff <= MAX_SLEEP_TIME_MS){ printf("Was asleep for %dms\n", diff); good_sleep_done = true; + } else { + printf("Ignoring sleep of %dms as haven't had good sleep yet\n", diff); } } } From 8fee9a7a3c00e5522a51a84d88a9c2894fd97233 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 29 Apr 2026 15:43:01 +0100 Subject: [PATCH 126/127] Revert short/long sleep handling, and use better tolerances --- test/pico_low_power_test/external_sleep_timer.c | 14 ++++---------- test/pico_low_power_test/low_power_test_timers.c | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/test/pico_low_power_test/external_sleep_timer.c b/test/pico_low_power_test/external_sleep_timer.c index 3aabbdb6c..fe3c655e1 100644 --- a/test/pico_low_power_test/external_sleep_timer.c +++ b/test/pico_low_power_test/external_sleep_timer.c @@ -13,12 +13,13 @@ #if PICO_RP2040 #define TOLERANCE_MS 1000 // The resolution of the AON timer is 1s on RP2040 +#elif PICO_RISCV +#define TOLERANCE_MS 200 // Can take longer to wake up that Arm #else #define TOLERANCE_MS 100 #endif #define MIN_SLEEP_TIME_MS SLEEP_TIME_MS - TOLERANCE_MS #define MAX_SLEEP_TIME_MS SLEEP_TIME_MS + TOLERANCE_MS -#define RESET_SLEEP_TIME_MS MAX_SLEEP_TIME_MS * 3 uint32_t wakeup_time_ms = 0; uint32_t sleep_time_ms = 0; @@ -41,20 +42,13 @@ void gpio_callback(uint gpio, uint32_t events) { printf("Went to sleep at %dms\n", sleep_time_ms); wake_up_alarm_id = add_alarm_in_ms(SLEEP_TIME_MS, wake_up_gpio, NULL, false); } - if (wakeup_time_ms > sleep_time_ms && sleep_time_ms) { + if (wakeup_time_ms > sleep_time_ms) { uint32_t diff = wakeup_time_ms - sleep_time_ms; - if (diff > RESET_SLEEP_TIME_MS) { - printf("Resetting due to long sleep of %dms\n", diff); - good_sleep_done = false; - } else if (diff < TOLERANCE_MS) { - printf("Ignoring sleep of %dms\n", diff); - } else if (good_sleep_done && (diff < MIN_SLEEP_TIME_MS || diff > MAX_SLEEP_TIME_MS)) { + if (good_sleep_done && (diff < MIN_SLEEP_TIME_MS || diff > MAX_SLEEP_TIME_MS)) { printf("ERROR: Was asleep for %dms, expected between %dms and %dms\n", diff, MIN_SLEEP_TIME_MS, MAX_SLEEP_TIME_MS); } else if (diff >= MIN_SLEEP_TIME_MS && diff <= MAX_SLEEP_TIME_MS){ printf("Was asleep for %dms\n", diff); good_sleep_done = true; - } else { - printf("Ignoring sleep of %dms as haven't had good sleep yet\n", diff); } } } diff --git a/test/pico_low_power_test/low_power_test_timers.c b/test/pico_low_power_test/low_power_test_timers.c index c3f981b64..b82804305 100644 --- a/test/pico_low_power_test/low_power_test_timers.c +++ b/test/pico_low_power_test/low_power_test_timers.c @@ -263,7 +263,7 @@ int main() { gpio_put(SLEEP_MONITOR_PIN, 1); // check the system timer was stopped while dormant diff = absolute_time_diff_us(system_time_before, get_absolute_time()); - if (diff > 50 * 1000 // 50ms + if (diff > 200 * 1000 // 200ms #ifdef PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS + (PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS * 1000) #endif From e95756e739011c8a41a79a2494ce5b3aabd0805a Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 29 Apr 2026 16:41:32 +0100 Subject: [PATCH 127/127] Switch default of SRAM clearing with picotool encrypt back Passes --no-clear arg when not clearing, rather than --clear when clearing, as older picotool doesn't have a --clear flag This will break the build of low_power_test_timers_encrypted unless you use the xip-sram branch of picotool --- tools/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index e8e0bd27d..85553bb7c 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -740,8 +740,8 @@ function(picotool_postprocess_binary TARGET) # Encryption if (picotool_aesfile AND picotool_ivfile) get_target_property(enc_no_clear ${TARGET} PICOTOOL_ENC_NO_CLEAR) - if (NOT enc_no_clear) - list(APPEND picotool_encrypt_args "--clear") + if (enc_no_clear) + list(APPEND picotool_encrypt_args "--no-clear") endif() get_target_property(picotool_embed_decryption ${TARGET} PICOTOOL_EMBED_DECRYPTION)