diff --git a/bazel/config/BUILD.bazel b/bazel/config/BUILD.bazel index ea8187924..dfb3e992a 100644 --- a/bazel/config/BUILD.bazel +++ b/bazel/config/BUILD.bazel @@ -237,6 +237,7 @@ string_flag( "no_flash", "copy_to_ram", "blocked_ram", + "xip_ram", ], ) diff --git a/bazel/constraint/BUILD.bazel b/bazel/constraint/BUILD.bazel index 8fcd1a611..211aac6eb 100644 --- a/bazel/constraint/BUILD.bazel +++ b/bazel/constraint/BUILD.bazel @@ -303,3 +303,8 @@ config_setting( name = "pico_binary_type_blocked_ram", flag_values = {"//bazel/config:PICO_DEFAULT_BINARY_TYPE": "blocked_ram"}, ) + +config_setting( + name = "pico_binary_type_xip_ram", + flag_values = {"//bazel/config:PICO_DEFAULT_BINARY_TYPE": "xip_ram"}, +) diff --git a/src/common/pico_base_headers/BUILD.bazel b/src/common/pico_base_headers/BUILD.bazel index c86234768..ad46a5f67 100644 --- a/src/common/pico_base_headers/BUILD.bazel +++ b/src/common/pico_base_headers/BUILD.bazel @@ -78,6 +78,10 @@ cc_library( "//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"], + "//bazel/constraint:pico_binary_type_xip_ram": [ + "PICO_XIP_RAM=1", + "PICO_NO_FLASH=1", + ], "//conditions:default": [], }), ) diff --git a/src/rp2040/pico_platform/memmap_blocked_ram.cmake b/src/rp2040/pico_platform/memmap_blocked_ram.cmake index 019b3963c..13fc170c9 100644 --- a/src/rp2040/pico_platform/memmap_blocked_ram.cmake +++ b/src/rp2040/pico_platform/memmap_blocked_ram.cmake @@ -37,6 +37,7 @@ function(pico_add_memmap_link_depends_internal TARGET) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_ram_vector_table.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_tls.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_uninitialized_data.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_xip_ram.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_default.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl) diff --git a/src/rp2040/pico_platform/memmap_blocked_ram.ld b/src/rp2040/pico_platform/memmap_blocked_ram.ld index 8ad9dbd67..914f35d77 100644 --- a/src/rp2040/pico_platform/memmap_blocked_ram.ld +++ b/src/rp2040/pico_platform/memmap_blocked_ram.ld @@ -45,6 +45,7 @@ INCLUDE "memmap_default.incl" * ├── section_extra_post_scratch.incl rp2_common/pico_standard_link * ├── sections_stack.incl rp2_common/pico_standard_link * ├── sections_psram.incl rp2040/pico_platform + * ├── section_xip_ram.incl rp2_common/pico_standard_link * ├── section_flash_end.incl rp2_common/pico_standard_link * ├── section_end.incl rp2_common/pico_standard_link * ├── section_generated_post_end.incl rp2_common/pico_standard_link diff --git a/src/rp2040/pico_platform/memmap_copy_to_ram.cmake b/src/rp2040/pico_platform/memmap_copy_to_ram.cmake index 170073aa7..49d3ede93 100644 --- a/src/rp2040/pico_platform/memmap_copy_to_ram.cmake +++ b/src/rp2040/pico_platform/memmap_copy_to_ram.cmake @@ -36,6 +36,7 @@ function(pico_add_memmap_link_depends_internal TARGET) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_ram_vector_table.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_tls.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_uninitialized_data.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_xip_ram.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl) diff --git a/src/rp2040/pico_platform/memmap_copy_to_ram.ld b/src/rp2040/pico_platform/memmap_copy_to_ram.ld index dfc053a5a..a162d4ac2 100644 --- a/src/rp2040/pico_platform/memmap_copy_to_ram.ld +++ b/src/rp2040/pico_platform/memmap_copy_to_ram.ld @@ -41,6 +41,7 @@ INCLUDE "memmap_copy_to_ram.incl" * ├── section_extra_post_scratch.incl rp2_common/pico_standard_link * ├── sections_stack.incl rp2_common/pico_standard_link * ├── sections_psram.incl rp2040/pico_platform + * ├── section_xip_ram.incl rp2_common/pico_standard_link * ├── section_flash_end.incl rp2_common/pico_standard_link * ├── section_end.incl rp2_common/pico_standard_link * ├── section_generated_post_end.incl rp2_common/pico_standard_link diff --git a/src/rp2040/pico_platform/memmap_default.cmake b/src/rp2040/pico_platform/memmap_default.cmake index 019b3963c..13fc170c9 100644 --- a/src/rp2040/pico_platform/memmap_default.cmake +++ b/src/rp2040/pico_platform/memmap_default.cmake @@ -37,6 +37,7 @@ function(pico_add_memmap_link_depends_internal TARGET) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_ram_vector_table.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_tls.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_uninitialized_data.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_xip_ram.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_default.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl) diff --git a/src/rp2040/pico_platform/memmap_default.ld b/src/rp2040/pico_platform/memmap_default.ld index 3912267c5..40fa181c2 100644 --- a/src/rp2040/pico_platform/memmap_default.ld +++ b/src/rp2040/pico_platform/memmap_default.ld @@ -42,6 +42,7 @@ INCLUDE "memmap_default.incl" * ├── section_extra_post_scratch.incl rp2_common/pico_standard_link * ├── sections_stack.incl rp2_common/pico_standard_link * ├── sections_psram.incl rp2040/pico_platform + * ├── section_xip_ram.incl rp2_common/pico_standard_link * ├── section_flash_end.incl rp2_common/pico_standard_link * ├── section_end.incl rp2_common/pico_standard_link * ├── section_generated_post_end.incl rp2_common/pico_standard_link diff --git a/src/rp2040/pico_platform/memmap_no_flash.cmake b/src/rp2040/pico_platform/memmap_no_flash.cmake index 8957a357c..c4756b811 100644 --- a/src/rp2040/pico_platform/memmap_no_flash.cmake +++ b/src/rp2040/pico_platform/memmap_no_flash.cmake @@ -29,6 +29,7 @@ function(pico_add_memmap_link_depends_internal TARGET) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_persistent_data.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_tls.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_uninitialized_data.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_xip_ram.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl) diff --git a/src/rp2040/pico_platform/memmap_no_flash.ld b/src/rp2040/pico_platform/memmap_no_flash.ld index 3e9109bcb..56910d22a 100644 --- a/src/rp2040/pico_platform/memmap_no_flash.ld +++ b/src/rp2040/pico_platform/memmap_no_flash.ld @@ -36,6 +36,7 @@ INCLUDE "memmap_no_flash.incl" * ├── section_extra_post_scratch.incl rp2_common/pico_standard_link * ├── sections_stack.incl rp2_common/pico_standard_link * ├── sections_psram.incl rp2040/pico_platform + * ├── section_xip_ram.incl rp2_common/pico_standard_link * ├── section_end.incl rp2_common/pico_standard_link * ├── section_generated_post_end.incl rp2_common/pico_standard_link * ├── section_extra_post_end.incl rp2_common/pico_standard_link diff --git a/src/rp2350/pico_platform/BUILD.bazel b/src/rp2350/pico_platform/BUILD.bazel index 67054882b..65a041431 100644 --- a/src/rp2350/pico_platform/BUILD.bazel +++ b/src/rp2350/pico_platform/BUILD.bazel @@ -61,6 +61,7 @@ exports_files( "memmap_copy_to_ram.ld", "memmap_default.ld", "memmap_no_flash.ld", + "memmap_xip_ram.ld", ], ) @@ -79,6 +80,11 @@ linker_scripts( link_scripts = ["memmap_no_flash.ld"], ) +linker_scripts( + name = "memmap_xip_ram", + link_scripts = ["memmap_xip_ram.ld"], +) + cc_library( name = "default_linker_script", target_compatible_with = ["//bazel/constraint:rp2350"], @@ -136,3 +142,22 @@ cc_library( "memmap_no_flash", ], ) + +# PICO_BUILD_DEFINE: PICO_XIP_RAM, whether this is a 'xip_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link +cc_library( + name = "xip_ram_linker_script", + target_compatible_with = ["//bazel/constraint:rp2350"], + visibility = [ + "//src/rp2_common/pico_standard_link:__pkg__", + ], + # The order of the linker scripts below is important. + # Prevent buildifier from reordering them. + # buildifier: leave-alone + 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_psram_region", + "memmap_xip_ram", + ], +) diff --git a/src/rp2350/pico_platform/include/pico/platform.h b/src/rp2350/pico_platform/include/pico/platform.h index 67cb80ebc..d7d46fb77 100644 --- a/src/rp2350/pico_platform/include/pico/platform.h +++ b/src/rp2350/pico_platform/include/pico/platform.h @@ -20,6 +20,12 @@ #error pico/platform.h should not be included directly; include pico.h instead #endif +// this is used by sections.h, so comes before the includes +// PICO_CONFIG: PICO_USE_XIP_CACHE_AS_RAM, Whether to use xip cache as ram, default=0, type=bool, group=pico_platform +#ifndef PICO_USE_XIP_CACHE_AS_RAM +#define PICO_USE_XIP_CACHE_AS_RAM 0 +#endif + #include "pico/platform/compiler.h" #include "pico/platform/sections.h" #include "pico/platform/panic.h" diff --git a/src/rp2350/pico_platform/memmap_copy_to_ram.cmake b/src/rp2350/pico_platform/memmap_copy_to_ram.cmake index 18de38212..e9d6dd70e 100644 --- a/src/rp2350/pico_platform/memmap_copy_to_ram.cmake +++ b/src/rp2350/pico_platform/memmap_copy_to_ram.cmake @@ -34,6 +34,7 @@ function(pico_add_memmap_link_depends_internal TARGET) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_ram_vector_table.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_tls.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_uninitialized_data.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_xip_ram.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_copy_to_ram_data.incl) diff --git a/src/rp2350/pico_platform/memmap_copy_to_ram.ld b/src/rp2350/pico_platform/memmap_copy_to_ram.ld index b2f32553a..3c4d5651f 100644 --- a/src/rp2350/pico_platform/memmap_copy_to_ram.ld +++ b/src/rp2350/pico_platform/memmap_copy_to_ram.ld @@ -41,6 +41,7 @@ INCLUDE "memmap_copy_to_ram.incl" * ├── section_extra_post_scratch.incl rp2_common/pico_standard_link * ├── sections_stack.incl rp2_common/pico_standard_link * ├── sections_psram.incl rp2_common/pico_standard_link + * ├── section_xip_ram.incl rp2_common/pico_standard_link * ├── section_flash_end.incl rp2_common/pico_standard_link * ├── section_end.incl rp2_common/pico_standard_link * ├── section_generated_post_end.incl rp2_common/pico_standard_link diff --git a/src/rp2350/pico_platform/memmap_default.cmake b/src/rp2350/pico_platform/memmap_default.cmake index 1f8ce68ea..2ff9bdae4 100644 --- a/src/rp2350/pico_platform/memmap_default.cmake +++ b/src/rp2350/pico_platform/memmap_default.cmake @@ -35,6 +35,7 @@ function(pico_add_memmap_link_depends_internal TARGET) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_ram_vector_table.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_tls.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_uninitialized_data.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_xip_ram.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_default.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_default_data.incl) diff --git a/src/rp2350/pico_platform/memmap_default.ld b/src/rp2350/pico_platform/memmap_default.ld index b63a1ae7f..78079ebfe 100644 --- a/src/rp2350/pico_platform/memmap_default.ld +++ b/src/rp2350/pico_platform/memmap_default.ld @@ -42,6 +42,7 @@ INCLUDE "memmap_default.incl" * ├── section_extra_post_scratch.incl rp2_common/pico_standard_link * ├── sections_stack.incl rp2_common/pico_standard_link * ├── sections_psram.incl rp2_common/pico_standard_link + * ├── section_xip_ram.incl rp2_common/pico_standard_link * ├── section_flash_end.incl rp2_common/pico_standard_link * ├── section_end.incl rp2_common/pico_standard_link * ├── section_generated_post_end.incl rp2_common/pico_standard_link diff --git a/src/rp2350/pico_platform/memmap_no_flash.cmake b/src/rp2350/pico_platform/memmap_no_flash.cmake index 08e664cde..a1434dea0 100644 --- a/src/rp2350/pico_platform/memmap_no_flash.cmake +++ b/src/rp2350/pico_platform/memmap_no_flash.cmake @@ -28,6 +28,7 @@ function(pico_add_memmap_link_depends_internal TARGET) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_persistent_data.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_tls.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_uninitialized_data.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_xip_ram.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl) pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl) diff --git a/src/rp2350/pico_platform/memmap_no_flash.ld b/src/rp2350/pico_platform/memmap_no_flash.ld index b2517800c..27d943b9c 100644 --- a/src/rp2350/pico_platform/memmap_no_flash.ld +++ b/src/rp2350/pico_platform/memmap_no_flash.ld @@ -36,6 +36,7 @@ INCLUDE "memmap_no_flash.incl" * ├── section_extra_post_scratch.incl rp2_common/pico_standard_link * ├── sections_stack.incl rp2_common/pico_standard_link * ├── sections_psram.incl rp2_common/pico_standard_link + * ├── section_xip_ram.incl rp2_common/pico_standard_link * ├── section_end.incl rp2_common/pico_standard_link * ├── section_generated_post_end.incl rp2_common/pico_standard_link * ├── section_extra_post_end.incl rp2_common/pico_standard_link diff --git a/src/rp2350/pico_platform/memmap_xip_ram.cmake b/src/rp2350/pico_platform/memmap_xip_ram.cmake new file mode 100644 index 000000000..c470f1164 --- /dev/null +++ b/src/rp2350/pico_platform/memmap_xip_ram.cmake @@ -0,0 +1,41 @@ +# Auto-generated by tools/memmap_annotate.py — do not edit by hand +function(pico_add_memmap_link_depends_internal TARGET) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2350/pico_platform/script_include/section_platform_end.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/memmap_no_flash.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/memmap_xip_ram.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/memory_aliases_no_flash.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/memory_extra.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/memory_generated.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/memory_psram.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/memory_ram.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/memory_scratch.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/memory_xip_ram.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_binary_info.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_end.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_extra_post_data.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_extra_post_end.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_extra_post_platform_end.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_extra_post_scratch.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_extra_post_text.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_generated_post_data.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_generated_post_end.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_generated_post_platform_end.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_generated_post_scratch.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_generated_post_text.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_heap.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_no_flash_data.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_no_flash_rodata.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_no_flash_text.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_persistent_data.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_tls.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_uninitialized_data.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/section_xip_ram.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_arm_ex.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_no_flash.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_no_flash_data.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_no_flash_text.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_psram.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_scratch.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/sections_stack.incl) + pico_add_link_depend(${TARGET} ${PICO_SDK_PATH}/src/rp2_common/pico_standard_link/script_include/set_memory_locations.incl) +endfunction() diff --git a/src/rp2350/pico_platform/memmap_xip_ram.ld b/src/rp2350/pico_platform/memmap_xip_ram.ld new file mode 100644 index 000000000..ba06c4e87 --- /dev/null +++ b/src/rp2350/pico_platform/memmap_xip_ram.ld @@ -0,0 +1,47 @@ +INCLUDE "memmap_xip_ram.incl" + +/* BEGIN_MEMMAP_INCLUDE_TREE + * This is the default include tree for this file (generated by tools/memmap_annotate.py + * and tools/memmap_include_tree.py). To override any files in this tree, see the + * pico_add_linker_script_override_path CMake function under pico_standard_link. + * + * memmap_xip_ram.ld rp2350/pico_platform + * └── memmap_xip_ram.incl rp2_common/pico_standard_link + * └── memmap_no_flash.incl rp2_common/pico_standard_link + * ├── set_memory_locations.incl rp2_common/pico_standard_link + * ├── memory_psram.incl rp2_common/pico_standard_link + * ├── memory_xip_ram.incl rp2_common/pico_standard_link + * ├── memory_ram.incl rp2_common/pico_standard_link + * ├── memory_scratch.incl rp2_common/pico_standard_link + * ├── memory_generated.incl rp2_common/pico_standard_link + * ├── memory_extra.incl rp2_common/pico_standard_link + * ├── memory_aliases_no_flash.incl rp2_common/pico_standard_link + * └── sections_no_flash.incl rp2_common/pico_standard_link + * ├── sections_no_flash_text.incl rp2_common/pico_standard_link + * │ ├── section_no_flash_text.incl rp2_common/pico_standard_link + * │ ├── section_no_flash_rodata.incl rp2_common/pico_standard_link + * │ ├── sections_arm_ex.incl rp2_common/pico_standard_link + * │ └── section_binary_info.incl rp2_common/pico_standard_link + * ├── section_generated_post_text.incl rp2_common/pico_standard_link + * ├── section_extra_post_text.incl rp2_common/pico_standard_link + * ├── 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_tls.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 + * ├── sections_scratch.incl rp2_common/pico_standard_link + * ├── section_generated_post_scratch.incl rp2_common/pico_standard_link + * ├── section_extra_post_scratch.incl rp2_common/pico_standard_link + * ├── sections_stack.incl rp2_common/pico_standard_link + * ├── sections_psram.incl rp2_common/pico_standard_link + * ├── section_xip_ram.incl rp2_common/pico_standard_link + * ├── section_end.incl rp2_common/pico_standard_link + * ├── section_generated_post_end.incl rp2_common/pico_standard_link + * ├── section_extra_post_end.incl rp2_common/pico_standard_link + * ├── section_platform_end.incl rp2350/pico_platform + * ├── section_generated_post_platform_end.incl rp2_common/pico_standard_link + * └── section_extra_post_platform_end.incl rp2_common/pico_standard_link + * END_MEMMAP_INCLUDE_TREE */ diff --git a/src/rp2_common/hardware_flash/flash.c b/src/rp2_common/hardware_flash/flash.c index 7d3b7a815..b5426f39a 100644 --- a/src/rp2_common/hardware_flash/flash.c +++ b/src/rp2_common/hardware_flash/flash.c @@ -10,6 +10,7 @@ #if PICO_RP2040 #include "hardware/structs/io_qspi.h" #include "hardware/structs/ssi.h" +#include "hardware/structs/xip.h" #else #include "hardware/structs/qmi.h" #include "hardware/regs/otp_data.h" @@ -140,7 +141,9 @@ static void __no_inline_not_in_flash_func(flash_rp2350_restore_qmi_cs1)(const fl typedef struct flash_hardware_save_state { -#if !PICO_RP2040 +#if PICO_RP2040 + uint32_t xip_ctrl; +#else flash_rp2350_qmi_save_state_t qmi_save; #endif uint32_t qspi_pads[count_of(pads_qspi_hw->io)]; @@ -152,7 +155,9 @@ static void __no_inline_not_in_flash_func(flash_save_hardware_state)(flash_hardw for (size_t i = 0; i < count_of(pads_qspi_hw->io); ++i) { state->qspi_pads[i] = pads_qspi_hw->io[i]; } -#if !PICO_RP2040 +#if PICO_RP2040 + state->xip_ctrl = xip_ctrl_hw->ctrl; +#else flash_rp2350_save_qmi_cs1(&state->qmi_save); #endif } @@ -161,7 +166,9 @@ static void __no_inline_not_in_flash_func(flash_restore_hardware_state)(flash_ha for (size_t i = 0; i < count_of(pads_qspi_hw->io); ++i) { pads_qspi_hw->io[i] = state->qspi_pads[i]; } -#if !PICO_RP2040 +#if PICO_RP2040 + xip_ctrl_hw->ctrl = state->xip_ctrl; +#else // Tail call! flash_rp2350_restore_qmi_cs1(&state->qmi_save); #endif diff --git a/src/rp2_common/hardware_riscv_platform_timer/BUILD.bazel b/src/rp2_common/hardware_riscv_platform_timer/BUILD.bazel index 790be1e40..943e0504d 100644 --- a/src/rp2_common/hardware_riscv_platform_timer/BUILD.bazel +++ b/src/rp2_common/hardware_riscv_platform_timer/BUILD.bazel @@ -1,5 +1,5 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library") -load("//bazel:defs.bzl", "compatible_with_rp2") +load("//bazel:defs.bzl", "compatible_with_rp2", "incompatible_with_config") package(default_visibility = ["//visibility:public"]) @@ -7,7 +7,7 @@ cc_library( name = "hardware_riscv_platform_timer", hdrs = ["include/hardware/riscv_platform_timer.h"], includes = ["include"], - target_compatible_with = compatible_with_rp2() + ["@platforms//cpu:riscv32"], + target_compatible_with = compatible_with_rp2() + incompatible_with_config("//bazel/constraint:rp2040"), deps = [ "//src/rp2_common:hardware_structs", "//src/rp2_common:pico_platform", diff --git a/src/rp2_common/hardware_sync_spin_lock/include/hardware/sync/spin_lock.h b/src/rp2_common/hardware_sync_spin_lock/include/hardware/sync/spin_lock.h index 83ba1e6d8..a5b383fc4 100644 --- a/src/rp2_common/hardware_sync_spin_lock/include/hardware/sync/spin_lock.h +++ b/src/rp2_common/hardware_sync_spin_lock/include/hardware/sync/spin_lock.h @@ -13,7 +13,7 @@ // PICO_CONFIG: PICO_USE_SW_SPIN_LOCKS, Use software implementation for spin locks, type=bool, default=1 on RP2350 due to errata E2, group=hardware_sync #ifndef PICO_USE_SW_SPIN_LOCKS #if PICO_RP2350 -#define PICO_USE_SW_SPIN_LOCKS 1 +#define PICO_USE_SW_SPIN_LOCKS (!PICO_XIP_RAM) #endif #endif diff --git a/src/rp2_common/pico_crt0/crt0.S b/src/rp2_common/pico_crt0/crt0.S index b2bbf0c58..f5bfcd724 100644 --- a/src/rp2_common/pico_crt0/crt0.S +++ b/src/rp2_common/pico_crt0/crt0.S @@ -11,6 +11,7 @@ #include "hardware/regs/addressmap.h" #include "hardware/regs/sio.h" +#include "hardware/regs/xip.h" #include "hardware/regs/watchdog.h" #include "pico/binary_info/defs.h" #include "boot/picobin.h" @@ -30,6 +31,11 @@ #endif #endif +// PICO_CONFIG: PICO_CRT0_NO_DATA_COPY, Whether crt0 should perform the data copies - usually copying from flash into sram, default=1 for no_flash builds, 0 otherwise, type=bool, group=pico_crt0 +#ifndef PICO_CRT0_NO_DATA_COPY +#define PICO_CRT0_NO_DATA_COPY PICO_NO_FLASH +#endif + #ifdef NDEBUG #ifndef COLLAPSE_IRQS #define COLLAPSE_IRQS @@ -486,6 +492,14 @@ hold_non_core0_in_bootrom: b _enter_vtable_in_r0 1: +#if PICO_RP2040 && PICO_USE_XIP_CACHE_AS_RAM +_disable_xip_cache: + // Disable the XIP cache on RP2040 making its SRAM available for use + ldr r0, =(REG_ALIAS_CLR_BITS + XIP_CTRL_BASE + XIP_CTRL_OFFSET) + movs r1, #XIP_CTRL_EN_BITS + str r1, [r0] +#endif + #if !PICO_RP2040 && PICO_EMBED_XIP_SETUP && !PICO_NO_FLASH // Execute boot2 on the core 0 stack (it also gets copied into BOOTRAM due // to inclusion in the data copy table below). Note the reference @@ -506,7 +520,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 !PICO_CRT0_NO_DATA_COPY adr r4, data_cpy_table // assume there is at least one entry @@ -551,13 +565,23 @@ platform_entry: // symbol for stack traces b 1b -#if !PICO_NO_FLASH +#if !PICO_CRT0_NO_DATA_COPY +#if PICO_NO_FLASH +data_cpy: + // skip copies with same source and destination + cmp r1, r2 + beq data_cpy_done +#else + // go straight into the copy + #define data_cpy_start data_cpy +#endif data_cpy_loop: ldm r1!, {r0} stm r2!, {r0} -data_cpy: +data_cpy_start: cmp r2, r3 blo data_cpy_loop +data_cpy_done: bx lr #endif @@ -589,6 +613,12 @@ data_cpy_table: .word __scratch_y_start__ .word __scratch_y_end__ +#if PICO_USE_XIP_CACHE_AS_RAM +.word __xip_ram_source__ +.word __xip_ram_start__ +.word __xip_ram_end__ +#endif + .word 0 // null terminator // ---------------------------------------------------------------------------- diff --git a/src/rp2_common/pico_crt0/crt0_riscv.S b/src/rp2_common/pico_crt0/crt0_riscv.S index 967760be3..036fcd772 100644 --- a/src/rp2_common/pico_crt0/crt0_riscv.S +++ b/src/rp2_common/pico_crt0/crt0_riscv.S @@ -35,6 +35,10 @@ #define PICO_CRT0_DEBUG_ENTRY_RESETS_VIA_BOOTROM 1 #endif +#ifndef PICO_CRT0_NO_DATA_COPY +#define PICO_CRT0_NO_DATA_COPY PICO_NO_FLASH +#endif + // If vectors are in RAM, we put them in the .data section, so that they are // preloaded by _reset_handler (assuming this is not a loaded-in-place // binary). @@ -368,7 +372,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 !PICO_CRT0_NO_DATA_COPY la a4, data_cpy_table // assume there is at least one entry @@ -407,15 +411,23 @@ platform_entry: // symbol for stack traces ebreak j 1b - -#if !PICO_NO_FLASH +#if !PICO_CRT0_NO_DATA_COPY +#if PICO_NO_FLASH +data_cpy: + // skip copies with same source and destination + beq a0, a1, data_cpy_done +#else + // go straight into the copy + #define data_cpy_start data_cpy +#endif data_cpy_loop: lw a0, (a1) sw a0, (a2) addi a1, a1, 4 addi a2, a2, 4 -data_cpy: +data_cpy_start: bltu a2, a3, data_cpy_loop +data_cpy_done: ret #endif @@ -443,6 +455,12 @@ data_cpy_table: .word __scratch_y_start__ .word __scratch_y_end__ +#if PICO_USE_XIP_CACHE_AS_RAM +.word __xip_ram_source__ +.word __xip_ram_start__ +.word __xip_ram_end__ +#endif + .word 0 // null terminator // ---------------------------------------------------------------------------- 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 000da904b..2c1cdc56f 100644 --- a/src/rp2_common/pico_crt0/embedded_start_block.inc.S +++ b/src/rp2_common/pico_crt0/embedded_start_block.inc.S @@ -39,7 +39,7 @@ #endif #ifndef PICO_CRT0_PIN_XIP_SRAM -#define PICO_CRT0_PIN_XIP_SRAM 0 +#define PICO_CRT0_PIN_XIP_SRAM (PICO_USE_XIP_CACHE_AS_RAM || PICO_XIP_RAM) #endif #if PICO_CRT0_IMAGE_TYPE_TBYB diff --git a/src/rp2_common/pico_low_power/CMakeLists.txt b/src/rp2_common/pico_low_power/CMakeLists.txt index 327d8bbf3..5438eb4e6 100644 --- a/src/rp2_common/pico_low_power/CMakeLists.txt +++ b/src/rp2_common/pico_low_power/CMakeLists.txt @@ -34,13 +34,19 @@ pico_promote_common_scope_vars() # It also sets PICO_CRT0_PIN_XIP_SRAM=1 to pin the XIP_SRAM, # if the persistent data is stored in XIP_SRAM. # -# \param\ PERSISTENT_DATA_LOC The persistent data location to set +# \param\ PERSISTENT_DATA_LOC The persistent data location to set (e.g. 0x20040000), or the memory region name (currently supports xip_ram) function(pico_set_persistent_data_loc TARGET PERSISTENT_DATA_LOC) if (PICO_RP2040) message(FATAL_ERROR "pico_set_persistent_data_loc is not supported on RP2040") endif() - if (PERSISTENT_DATA_LOC LESS 0x20000000) + if (PERSISTENT_DATA_LOC STREQUAL xip_ram) + # XIP_SRAM, so pin the XIP_SRAM + target_compile_definitions(${TARGET} PRIVATE PICO_CRT0_PIN_XIP_SRAM=1) + set(PERSISTENT_DATA_SECTION "XIP_RAM") + # Clear PERSISTENT_DATA_LOC, so the section is placed normally + unset(PERSISTENT_DATA_LOC) + elseif (PERSISTENT_DATA_LOC LESS 0x20000000) # XIP_SRAM, so pin the XIP_SRAM target_compile_definitions(${TARGET} PRIVATE PICO_CRT0_PIN_XIP_SRAM=1) set(PERSISTENT_DATA_SECTION "XIP_RAM") @@ -58,6 +64,7 @@ function(pico_set_persistent_data_loc TARGET PERSISTENT_DATA_LOC) endif() # 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} FILES section_persistent_data.incl) + set(SCRIPT_PATH ${CMAKE_BINARY_DIR}/generated/persistent_data/${TARGET}) + configure_file(${PICO_LOW_POWER_CURRENT_PATH}/section_persistent_data.incl.template ${SCRIPT_PATH}/section_persistent_data.incl @ONLY) + pico_add_linker_script_override_path(${TARGET} ${SCRIPT_PATH} FILES section_persistent_data.incl) endfunction() 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 fdafb66e8..ec703bc51 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 @@ -25,23 +25,24 @@ #define __after_data(group) __attribute__((section(".after_data." group))) #endif -/*! \brief Section attribute macro for placement not in flash (i.e in RAM) +/*! \brief Section attribute macro for placement in RAM * \ingroup pico_platform * * For example a 3 element `uint32_t` array placed in RAM (even though it is `static const`) * * static const uint32_t __not_in_flash("my_group_name") an_array[3]; * - * The section attribute is `.time_critical.` + * The section attribute is `.time_critical.`, which is used to maintain compatibility + * with older linker scripts * * \param group a string suffix to use in the section name to distinguish groups that can be linker * garbage-collected independently */ -#ifndef __not_in_flash -#define __not_in_flash(group) __attribute__((section(".time_critical." group))) +#ifndef __in_ram +#define __in_ram(group) __attribute__((section(".time_critical." group))) #endif -/*! \brief Section attribute macro for placement in the SRAM bank 4 (known as "scratch X") +/*! \brief Section attribute macro for placement in the penultimate SRAM bank (known as "scratch X") * \ingroup pico_platform * * Scratch X is commonly used for critical data and functions accessed only by one core (when only @@ -49,18 +50,30 @@ * * For example a `uint32_t` variable placed in "scratch X" * - * uint32_t __scratch_x("my_group_name") foo = 23; + * uint32_t __in_scratch_x("my_group_name") foo = 23; * * The section attribute is `.scratch_x.` * * \param group a string suffix to use in the section name to distinguish groups that can be linker * garbage-collected independently */ +#ifndef __in_scratch_x +#define __in_scratch_x(group) __attribute__((section(".scratch_x." group))) +#endif + +/*! \brief Section attribute macro for placement in the penultimate SRAM bank (known as "scratch X") + * \ingroup pico_platform + * + * Alias for \ref __in_scratch_x + * + * \param group a string suffix to use in the section name to distinguish groups that can be linker + * garbage-collected independently + */ #ifndef __scratch_x -#define __scratch_x(group) __attribute__((section(".scratch_x." group))) +#define __scratch_x(group) __in_scratch_x(group) #endif -/*! \brief Section attribute macro for placement in the SRAM bank 5 (known as "scratch Y") +/*! \brief Section attribute macro for placement in the final SRAM bank (known as "scratch Y") * \ingroup pico_platform * * Scratch Y is commonly used for critical data and functions accessed only by one core (when only @@ -75,8 +88,20 @@ * \param group a string suffix to use in the section name to distinguish groups that can be linker * garbage-collected independently */ +#ifndef __in_scratch_y +#define __in_scratch_y(group) __attribute__((section(".scratch_y." group))) +#endif + +/*! \brief Section attribute macro for placement in the final SRAM bank (known as "scratch Y") + * \ingroup pico_platform + * + * Alias for \ref __in_scratch_y + * + * \param group a string suffix to use in the section name to distinguish groups that can be linker + * garbage-collected independently + */ #ifndef __scratch_y -#define __scratch_y(group) __attribute__((section(".scratch_y." group))) +#define __scratch_y(group) __in_scratch_y(group) #endif /*! \brief Section attribute macro for placement in PSRAM @@ -101,10 +126,44 @@ #ifndef __in_psram #define __in_psram(group) __attribute__((section(".psram_initialised." group))) #endif + +/*! \brief Section attribute macro for placement in uninitialised PSRAM + * \ingroup pico_platform + * + * The version of \ref __in_psram to use for uninitialised data + * + * \param group a string suffix to use in the section name to distinguish groups that can be linker + * garbage-collected independently + */ #ifndef __uninitialized_psram #define __uninitialized_psram(group) __attribute__((section(".psram_uninitialised." group))) #endif +/*! \brief Section attribute macro for placement in XIP SRAM + * \ingroup pico_platform + * + * The XIP Cache can be used as SRAM for extra data sections, however it will give a performance + * penalty if your binary runs from Flash (e.g. the default binary type). + * + * For example a `uint32_t` variable placed in XIP SRAM + * + * uint32_t __in_xip_ram("my_group_name") foo = 23; + * + * The section attribute is `.xip_ram.` + * + * \param group a string suffix to use in the section name to distinguish groups that can be linker + * garbage-collected independently + */ +#ifndef __in_xip_ram +#if PICO_USE_XIP_CACHE_AS_RAM +#define __in_xip_ram(group) __attribute__((section(".xip_ram." group))) +#elif PICO_XIP_RAM +#define __in_xip_ram(group) __in_ram(group) +#else +#define __in_xip_ram(group) x; static_assert(false, "Must set PICO_USE_XIP_CACHE_AS_RAM=1 to use the __in_xip_ram macro"); +#endif +#endif + /*! \brief Section attribute macro for data that is to be left uninitialized * \ingroup pico_platform * @@ -166,43 +225,46 @@ #define __in_flash(group) __attribute__((section(".flashdata." group))) #endif -/*! \brief Indicates a function should not be stored in flash +/*! \brief Section attribute macro for placement not in flash * \ingroup pico_platform * - * Decorates a function name, such that the function will execute from RAM (assuming it is not inlined - * into a flash function by the compiler) + * For example a 3 element `uint32_t` array placed in RAM (even though it is `static const`) * - * For example a function called my_func taking an int parameter: + * static const uint32_t __not_in_flash("my_group_name") an_array[3]; * - * void __not_in_flash_func(my_func)(int some_arg) { + * By default, this is identical to \ref __in_ram, but this can be adjusted using the `PICO_NOT_IN_FLASH_PLACEMENT` define. + * This define can be set using the \ref pico_set_not_in_flash_placement CMake function. * - * The function is placed in the `.time_critical.` linker section + * For example, for binaries that only use core 0, there is the option to use + * `pico_set_not_in_flash_placement(TARGET scratch_x)` to place this code/data in scratch X to move it + * out of the striped SRAM. * - * \see __no_inline_not_in_flash_func + * \param group a string suffix to use in the section name to distinguish groups that can be linker + * garbage-collected independently */ -#ifndef __not_in_flash_func -#define __not_in_flash_func(func_name) __not_in_flash(__STRING(func_name)) func_name +#ifndef PICO_NOT_IN_FLASH_PLACEMENT +#define PICO_NOT_IN_FLASH_PLACEMENT __in_ram +#endif +#ifndef __not_in_flash +#define __not_in_flash(group) PICO_NOT_IN_FLASH_PLACEMENT(group) #endif -/*! \brief Indicates a function is time/latency critical and should not run from flash +/*! \brief Indicates a function should not be stored in flash * \ingroup pico_platform * * Decorates a function name, such that the function will execute from RAM (assuming it is not inlined - * into a flash function by the compiler) to avoid possible flash latency. Currently this macro is identical - * in implementation to `__not_in_flash_func`, however the semantics are distinct and a `__time_critical_func` - * may in the future be treated more specially to reduce the overhead when calling such function from a flash - * function. + * into a flash function by the compiler) * * For example a function called my_func taking an int parameter: * - * void __time_critical_func(my_func)(int some_arg) { + * void __not_in_flash_func(my_func)(int some_arg) { * - * The function is placed in the `.time_critical.` linker section + * The function is placed using \ref __not_in_flash, which defaults to \ref __in_ram * - * \see __not_in_flash_func + * \see __no_inline_not_in_flash_func */ -#ifndef __time_critical_func -#define __time_critical_func(func_name) __not_in_flash_func(func_name) +#ifndef __not_in_flash_func +#define __not_in_flash_func(func_name) __not_in_flash(__STRING(func_name)) func_name #endif /*! \brief Indicate a function should not be stored in flash and should not be inlined @@ -215,12 +277,41 @@ * * void __no_inline_not_in_flash_func(my_func)(int some_arg) { * - * The function is placed in the `.time_critical.` linker section + * The function is placed using \ref __not_in_flash, which defaults to \ref __in_ram */ #ifndef __no_inline_not_in_flash_func #define __no_inline_not_in_flash_func(func_name) __noinline __not_in_flash_func(func_name) #endif + +/*! \brief Indicates a function is time/latency critical and should not run from flash + * \ingroup pico_platform + * + * Decorates a function name, such that the function will execute from RAM to avoid possible flash latency. By default, + * this macro is identical in implementation to `__no_inline_not_in_flash_func`, however the semantics are distinct and + * a `__time_critical_func` can be treated more specially to reduce the overhead when calling such a function. + * + * For example a function called my_func taking an int parameter: + * + * void __time_critical_func(my_func)(int some_arg) { + * + * By default, the function is placed using \ref __in_ram, but this can be adjusted using the + * `PICO_TIME_CRITICAL_PLACEMENT` define. This define can be set using the \ref pico_set_time_critical_placement + * CMake function. + * + * For example, for binaries that are not executing from flash (e.g. copy_to_ram and no_flash), there is the option + * to use `pico_set_time_critical_placement(TARGET xip_ram)` to place these functions in XIP RAM, as the XIP AHB + * ports would be otherwise unused. + * + * \see __not_in_flash + */ +#ifndef __time_critical_func +#ifndef PICO_TIME_CRITICAL_PLACEMENT +#define PICO_TIME_CRITICAL_PLACEMENT __in_ram +#endif +#define __time_critical_func(func_name) __noinline PICO_TIME_CRITICAL_PLACEMENT(__STRING(func_name)) func_name +#endif + #else #ifndef RAM_SECTION_NAME 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 bcf10dce5..64f0e5732 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 @@ -450,11 +450,11 @@ void runtime_init_bootrom_locking_enable(void); #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 +#define PICO_RUNTIME_SKIP_INIT_LOW_POWER_CACHE_UNPIN (!HAS_POWMAN_TIMER || PICO_NO_FLASH || PICO_USE_XIP_CACHE_AS_RAM || !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 +#define PICO_RUNTIME_NO_INIT_LOW_POWER_CACHE_UNPIN (!HAS_POWMAN_TIMER || PICO_NO_FLASH || PICO_USE_XIP_CACHE_AS_RAM || !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 diff --git a/src/rp2_common/pico_standard_link/BUILD.bazel b/src/rp2_common/pico_standard_link/BUILD.bazel index ae0c26dde..46b750d5b 100644 --- a/src/rp2_common/pico_standard_link/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/BUILD.bazel @@ -41,6 +41,7 @@ alias( "//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", + "//bazel/constraint:pico_binary_type_xip_ram": "//src/rp2_common/pico_standard_link:xip_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", @@ -74,6 +75,14 @@ alias( }), ) +alias( + name = "xip_ram_linker_script", + actual = select({ + "//bazel/constraint:rp2350": "//src/rp2350/pico_platform:xip_ram_linker_script", + "//conditions:default": "//bazel:incompatible_cc_lib", + }), +) + 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 d0aec3512..432dc1546 100644 --- a/src/rp2_common/pico_standard_link/CMakeLists.txt +++ b/src/rp2_common/pico_standard_link/CMakeLists.txt @@ -30,7 +30,6 @@ if (NOT TARGET pico_standard_link) set_target_properties(${TARGET} PROPERTIES ${PROP} "${_LINK_DEPENDS}") endfunction() - # pico_add_memmap_link_depends(TARGET TYPE) # \brief\ Add link dependencies for the binary type to the target # @@ -159,8 +158,117 @@ if (NOT TARGET pico_standard_link) pico_add_memmap_link_depends(${TARGET} ${TYPE}) endfunction() + # pico_include_in_generated_section(TARGET SECTION FILE) + # \brief\ Append a linker script include file to a generated section of the linker script + # + # Arranges for FILE to be INCLUDEd inside the generated SECTION of the target's linker script. + # + # This is primarily intended for internal SDK use - users should instead override the + # section_extra_SECTION.incl files, using pico_add_linker_script_override_path. + # + # \param\ TARGET The target whose linker script should be modified + # \param\ SECTION The linker script section name to append to (e.g. post_text) + # \param\ FILE Path to the linker script fragment to INCLUDE + function(pico_include_in_generated_section TARGET SECTION FILE) + get_target_property(already_generated ${TARGET} PICO_TARGET_LINKER_SCRIPT_INCLUDE_${SECTION}) + set_property(TARGET ${TARGET} APPEND PROPERTY PICO_TARGET_LINKER_SCRIPT_INCLUDE_${SECTION} "${FILE}") + # Make sure directory is empty before generating files, to avoid stale overrides + file(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/generated/pico_standard_link/${TARGET}) + if (NOT already_generated) + file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/generated/pico_standard_link/${TARGET}/section_generated_${SECTION}.incl + CONTENT "INCLUDE \"$,\"\nINCLUDE \">\"" + ) + pico_add_linker_script_override_path(${TARGET} ${CMAKE_BINARY_DIR}/generated/pico_standard_link/${TARGET}) + endif() + endfunction() + + # pico_set_compile_definition(TARGET DEFINE VALUE) + # \brief\ Set a compile definition on a target, guarding against conflicting redefinitions + # + # Equivalent to target_compile_definitions(TARGET PRIVATE DEFINE=VALUE) but tracks the value + # as a target property so that a second call with the same DEFINE and the same VALUE is silently + # ignored, while a second call with a different VALUE is a fatal error. + # + # \param\ TARGET The target to add the compile definition to + # \param\ DEFINE The preprocessor symbol name + # \param\ VALUE The value to assign to the symbol + function(pico_set_compile_definition TARGET DEFINE VALUE) + get_target_property(already_set ${TARGET} PICO_TARGET_DEFINITION_${DEFINE}) + if (already_set MATCHES "NOTFOUND") + set_target_properties(${TARGET} PROPERTIES PICO_TARGET_DEFINITION_${DEFINE} ${VALUE}) + target_compile_definitions(${TARGET} PRIVATE ${DEFINE}=${VALUE}) + else() + if (NOT ${VALUE} STREQUAL ${already_set}) + message(FATAL_ERROR "Multiple calls to pico_set_compile_definition for ${DEFINE} with different values (${already_set} vs ${VALUE})") + endif() + endif() + endfunction() + + # pico_set_time_critical_placement(TARGET MEMORY) + # \brief\ Place time-critical code for the target into + # + # Configures the target to run functions marked __time_critical_func() from rather than + # normal SRAM, useful if has dedicated AHB ports which are otherwise unused. For example, + # xip_ram could be used in no_flash and copy_to_ram binaries, as the XIP AHB ports are unused. + # This sets PICO_TIME_CRITICAL_PLACEMENT=__in_, and any necessary defines required to use + # (e.g. PICO_USE_XIP_CACHE_AS_RAM=1 for xip_ram). + # + # The xip_ram memory should not be used for flash binaries, as using the XIP cache as SRAM will + # have a large performance penalty. + # + # \param\ TARGET The target whose time-critical functions should run from + # \param\ MEMORY The memory block to place the functions in (e.g. xip_ram, scratch_x, scratch_y) + function(pico_set_time_critical_placement TARGET MEMORY) + target_compile_definitions(${TARGET} PRIVATE PICO_TIME_CRITICAL_PLACEMENT=__in_${MEMORY}) + if (${MEMORY} STREQUAL "xip_ram") + pico_set_compile_definition(${TARGET} PICO_USE_XIP_CACHE_AS_RAM 1) + endif() + endfunction() + + # pico_set_not_in_flash_placement(TARGET MEMORY) + # \brief\ Place time-critical code for the target into + # + # Configures the target to place data (and code) marked __not_in_flash() in rather than + # normal SRAM, useful if has dedicated AHB ports which are otherwise unused. For example, + # xip_ram could be used in no_flash and copy_to_ram binaries, as the XIP AHB ports are unused. + # This sets PICO_NOT_IN_FLASH_PLACEMENT=__in_, and any necessary defines required to use + # (e.g. PICO_USE_XIP_CACHE_AS_RAM=1 for xip_ram). + # + # The xip_ram memory should not be used for flash binaries, as using the XIP cache as SRAM will + # have a large performance penalty. + # + # \param\ TARGET The target whose __not_in_flash data should be placed in + # \param\ MEMORY The memory block to place the data in (e.g. xip_ram, scratch_x, scratch_y) + function(pico_set_not_in_flash_placement TARGET MEMORY) + target_compile_definitions(${TARGET} PRIVATE PICO_NOT_IN_FLASH_PLACEMENT=__in_${MEMORY}) + if (${MEMORY} STREQUAL "xip_ram") + pico_set_compile_definition(${TARGET} PICO_USE_XIP_CACHE_AS_RAM 1) + endif() + endfunction() + + # pico_use_xip_cache_as_ram(TARGET) + # \brief\ Allow placing data for the target into XIP SRAM + # + # Configures the target to use the XIP Cache as SRAM, allowing data to be placed there using the + # __in_xip_ram macro. This sets PICO_USE_XIP_CACHE_AS_RAM=1. + # + # This should not be used for flash binaries, as using the XIP cache as SRAM will have a large + # performance penalty. + # + # \param\ TARGET The target which can place data into XIP SRAM + function(pico_use_xip_cache_as_ram TARGET) + pico_set_compile_definition(${TARGET} PICO_USE_XIP_CACHE_AS_RAM 1) + endfunction() + # 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 + # first check that PICO_DEFAULT_BINARY_TYPE hasn't been set along with a legacy variable + if (PICO_DEFAULT_BINARY_TYPE AND (PICO_NO_FLASH OR PICO_USE_BLOCKED_RAM OR PICO_COPY_TO_RAM)) + message(FATAL_ERROR + "Cannot specify both PICO_DEFAULT_BINARY_TYPE and PICO_NO_FLASH/PICO_USE_BLOCKED_RAM/PICO_COPY_TO_RAM - just use PICO_DEFAULT_BINARY_TYPE instead" + ) + endif() + # then propogate legacy variables to PICO_DEFAULT_BINARY_TYPE, defaulting it to `default` if (NOT PICO_DEFAULT_BINARY_TYPE) if (PICO_NO_FLASH) set(PICO_DEFAULT_BINARY_TYPE no_flash) @@ -171,23 +279,12 @@ if (NOT TARGET pico_standard_link) else() set(PICO_DEFAULT_BINARY_TYPE default) endif() - else() - # we must set the individual variables here, as they are used in generator expressions, - # but also for our checks below - if (PICO_DEFAULT_BINARY_TYPE STREQUAL no_flash) - set(PICO_NO_FLASH 1) - endif() - if (PICO_DEFAULT_BINARY_TYPE STREQUAL blocked_ram) - set(PICO_USE_BLOCKED_RAM 1) - endif() - if (PICO_DEFAULT_BINARY_TYPE STREQUAL copy_to_ram) - set(PICO_COPY_TO_RAM 1) - endif() endif() + # finally check multiple legacy variables haven't been set if ((PICO_NO_FLASH AND PICO_USE_BLOCKED_RAM) OR (PICO_USE_BLOCKED_RAM AND PICO_COPY_TO_RAM) OR (PICO_COPY_TO_RAM AND PICO_NO_FLASH)) - message(FATAL_ERROR "Conflicting binary types specified amongst PICO_DEFAULT_BINARY_TYPE, PICO_NO_FLASH, PICO_USE_BLOCKED_RAM and PICO_COPY_TO_RAM") + message(FATAL_ERROR "Conflicting binary types specified amongst PICO_NO_FLASH, PICO_USE_BLOCKED_RAM and PICO_COPY_TO_RAM") endif() # todo only needed if not using a custom linker script @@ -244,15 +341,22 @@ if (NOT TARGET pico_standard_link) pico_add_memmap_link_depends(pico_standard_link ${PICO_DEFAULT_BINARY_TYPE}) - # PICO_NO_FLASH will be set based on PICO_TARGET_BUILD_TYPE target property being equal to no_flash if set, otherwise to the value of the PICO_NO_FLASH cmake variable unless PICO_TARGET_TYPE is set to something else + set(NO_FLASH_BINARY_TYPES no_flash xip_ram) + set(COPY_TO_RAM_BINARY_TYPES copy_to_ram) + set(XIP_RAM_BINARY_TYPES xip_ram) + + # PICO_NO_FLASH will be set based on PICO_TARGET_BINARY_TYPE target property being in NO_FLASH_BINARY_TYPES if PICO_TARGET_BINARY_TYPE is set, otherwise it is set based on PICO_DEFAULT_BINARY_TYPE being in NO_FLASH_BINARY_TYPES # 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 - target_compile_definitions(pico_standard_link INTERFACE PICO_NO_FLASH=$,no_flash>,1,$,$>>>) - # PICO_USE_BLOCKED_RAM will be set based on PICO_TARGET_BUILD_TYPE target property being equal to use_blocked_ram if set, otherwise to the value of the PICO_USE_BLOCKED_RAM cmake variable unless PICO_TARGET_TYPE is set to something else + target_compile_definitions(pico_standard_link INTERFACE PICO_NO_FLASH=$,${NO_FLASH_BINARY_TYPES}>,1,$,$>>>) + # PICO_USE_BLOCKED_RAM will be set based on PICO_TARGET_BINARY_TYPE target property being equal to blocked_ram if PICO_TARGET_BINARY_TYPE is set, otherwise it is set based on PICO_DEFAULT_BINARY_TYPE being equal to blocked_ram # 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 - target_compile_definitions(pico_standard_link INTERFACE PICO_USE_BLOCKED_RAM=$,use_blocked_ram>,1,$,$>>>) - # PICO_COPY_TO_RAM will be set based on PICO_TARGET_BUILD_TYPE target property being equal to copy_to_ram if set, otherwise to the value of the PICO_COPY_TO_RAM cmake variable unless PICO_TARGET_TYPE is set to something else + target_compile_definitions(pico_standard_link INTERFACE PICO_USE_BLOCKED_RAM=$,blocked_ram>,1,$,$>>>) + # PICO_COPY_TO_RAM will be set based on PICO_TARGET_BINARY_TYPE target property being in COPY_TO_RAM_BINARY_TYPES if PICO_TARGET_BINARY_TYPE is set, otherwise it is set based on PICO_DEFAULT_BINARY_TYPE being in COPY_TO_RAM_BINARY_TYPES # 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 - target_compile_definitions(pico_standard_link INTERFACE PICO_COPY_TO_RAM=$,copy_to_ram>,1,$,$>>>) + target_compile_definitions(pico_standard_link INTERFACE PICO_COPY_TO_RAM=$,${COPY_TO_RAM_BINARY_TYPES}>,1,$,$>>>) + # PICO_XIP_RAM will be set based on PICO_TARGET_BINARY_TYPE target property being in XIP_RAM_BINARY_TYPES if PICO_TARGET_BINARY_TYPE is set, otherwise it is set based on PICO_DEFAULT_BINARY_TYPE being in XIP_RAM_BINARY_TYPES + # PICO_BUILD_DEFINE: PICO_XIP_RAM, whether this is a 'xip_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link + target_compile_definitions(pico_standard_link INTERFACE PICO_XIP_RAM=$,${XIP_RAM_BINARY_TYPES}>,1,$,$>>>) target_compile_definitions(pico_standard_link INTERFACE PICO_CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}") if (PICO_DEOPTIMIZED_DEBUG AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") @@ -261,10 +365,10 @@ if (NOT TARGET pico_standard_link) # this (arguably wrong) code is restored for 1.5.1 as setting -nostartfiles on many C++ binaries causes link errors. see issue #1368 # -nostartfiles will be added if PICO_NO_FLASH would be defined to 1 - target_link_options(pico_standard_link INTERFACE $<$,no_flash>,1,$,$>>>:-nostartfiles>) + target_link_options(pico_standard_link INTERFACE $<$,${NO_FLASH_BINARY_TYPES}>,1,$,$>>>:-nostartfiles>) # boot_stage2 will be linked if PICO_NO_FLASH would be defined to 0; note if boot_stage2 headers not present, then boot_stage2 is omitted from build anyway if (TARGET boot_stage2_headers) - target_link_libraries(pico_standard_link INTERFACE $<$,no_flash>,1,$,$>>>>:$>,$,bs2_default>_library>) + target_link_libraries(pico_standard_link INTERFACE $<$,${NO_FLASH_BINARY_TYPES}>,1,$,$>>>>:$>,$,bs2_default>_library>) endif() # PICO_CMAKE_CONFIG: PICO_USE_DEFAULT_MAX_PAGE_SIZE, Don't shrink linker max page to 4096, type=bool, default=0, advanced=true, group=pico_standard_link diff --git a/src/rp2_common/pico_standard_link/script_include/memmap_xip_ram.incl b/src/rp2_common/pico_standard_link/script_include/memmap_xip_ram.incl new file mode 100644 index 000000000..538013eac --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/memmap_xip_ram.incl @@ -0,0 +1,19 @@ +/* Allow customisation of XIP_RAM_SCRATCH_SIZE */ +/* see set_memory_locations.incl for why both these lines are needed */ +PROVIDE( XIP_RAM_SCRATCH_SIZE = 2k); +XIP_RAM_SCRATCH_SIZE = DEFINED(XIP_RAM_SCRATCH_SIZE) ? XIP_RAM_SCRATCH_SIZE : 2k; + +/* Split XIP_RAM into RAM and SCRATCH */ +RAM_ORIGIN = XIP_RAM_ORIGIN_DEFAULT; +RAM_LENGTH = XIP_RAM_LENGTH_DEFAULT - (XIP_RAM_SCRATCH_SIZE*2); +SCRATCH_X_ORIGIN = XIP_RAM_ORIGIN_DEFAULT + XIP_RAM_LENGTH_DEFAULT - (XIP_RAM_SCRATCH_SIZE*2); +SCRATCH_X_LENGTH = XIP_RAM_SCRATCH_SIZE; +SCRATCH_Y_ORIGIN = XIP_RAM_ORIGIN_DEFAULT + XIP_RAM_LENGTH_DEFAULT - XIP_RAM_SCRATCH_SIZE; +SCRATCH_Y_LENGTH = XIP_RAM_SCRATCH_SIZE; + +/* Zero XIP_RAM origin and size to prevent placement there */ +XIP_RAM_ORIGIN_DEFAULT = 0; +XIP_RAM_LENGTH_DEFAULT = 0; + +/* Now it is just a normal no_flash binary */ +INCLUDE "memmap_no_flash.incl" 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 index cdd16166c..d90993a93 100644 --- a/src/rp2_common/pico_standard_link/script_include/memory_extra.incl +++ b/src/rp2_common/pico_standard_link/script_include/memory_extra.incl @@ -2,16 +2,16 @@ This file can be overridden to add extra memory regions. - For example, to add a PSRAM region, you would replace - this file with: + For example, to add an extra flash region for the second 4MiB + of flash, you could replace this file with: MEMORY { - PSRAM(rwx) : ORIGIN = 0x11000000, LENGTH = 8M + EXTRA_FLASH(rx) : ORIGIN = 0x10400000, LENGTH = 4M } - Or to include a XIP_RAM region, you would replace - this file with: + Or to include the FLASH region in a no_flash build, you could + replace this file with: - INCLUDE "memory_xip_ram.incl" + INCLUDE "memory_flash.incl" */ diff --git a/src/rp2_common/pico_standard_link/script_include/section_xip_ram.incl b/src/rp2_common/pico_standard_link/script_include/section_xip_ram.incl new file mode 100644 index 000000000..dba2695ed --- /dev/null +++ b/src/rp2_common/pico_standard_link/script_include/section_xip_ram.incl @@ -0,0 +1,15 @@ +/* Defines the following symbols for use by code: + __xip_ram_start__, __xip_ram_end__, __xip_ram_source__ +*/ + +SECTIONS +{ + .xip_ram : { + __xip_ram_start__ = .; + . = ALIGN(4); + *(.xip_ram*) + . = ALIGN(4); + __xip_ram_end__ = .; + } > XIP_RAM AT> XIP_RAM_STORE + __xip_ram_source__ = LOADADDR(.xip_ram); +} 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 c6e586b25..52636cc54 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 @@ -12,6 +12,7 @@ INCLUDE "section_generated_post_scratch.incl" INCLUDE "section_extra_post_scratch.incl" INCLUDE "sections_stack.incl" INCLUDE "sections_psram.incl" +INCLUDE "section_xip_ram.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" INCLUDE "section_generated_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 8f15074f8..f81e48c04 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 @@ -12,6 +12,7 @@ INCLUDE "section_generated_post_scratch.incl" INCLUDE "section_extra_post_scratch.incl" INCLUDE "sections_stack.incl" INCLUDE "sections_psram.incl" +INCLUDE "section_xip_ram.incl" INCLUDE "section_flash_end.incl" INCLUDE "section_end.incl" INCLUDE "section_generated_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 a7a467e36..2e68aa234 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,7 @@ INCLUDE "section_generated_post_scratch.incl" INCLUDE "section_extra_post_scratch.incl" INCLUDE "sections_stack.incl" INCLUDE "sections_psram.incl" +INCLUDE "section_xip_ram.incl" INCLUDE "section_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_psram.incl b/src/rp2_common/pico_standard_link/script_include/sections_psram.incl index 7f986a357..6e753920e 100644 --- a/src/rp2_common/pico_standard_link/script_include/sections_psram.incl +++ b/src/rp2_common/pico_standard_link/script_include/sections_psram.incl @@ -1,3 +1,8 @@ +/* Defines the following symbols for use by code: + __psram_start__, __psram_end__ + __psram_load_start__, __psram_load_end__, __psram_load_source__ +*/ + SECTIONS { .psram_load : { 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 54d68c88a..9e92524c4 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 @@ -24,4 +24,3 @@ SCRATCH_Y_ORIGIN = DEFINED(SCRATCH_Y_ORIGIN) ? SCRATCH_Y_ORIGIN : SCRATCH_Y_ORIG 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; - diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3b22ce491..e7bb50632 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -17,6 +17,7 @@ if (PICO_ON_DEVICE) add_subdirectory(cmsis_test) add_subdirectory(pico_sem_test) add_subdirectory(pico_sha256_test) + add_subdirectory(pico_xip_sram_test) add_subdirectory(pico_low_power_test) add_subdirectory(pico_async_context_test) add_subdirectory(pico_thread_local_test) diff --git a/test/pico_xip_sram_test/BUILD.bazel b/test/pico_xip_sram_test/BUILD.bazel new file mode 100644 index 000000000..4efe290b8 --- /dev/null +++ b/test/pico_xip_sram_test/BUILD.bazel @@ -0,0 +1,69 @@ +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("//bazel:defs.bzl", "compatible_with_rp2") +load("//bazel/util:transition.bzl", "extra_copts_for_all_deps", "pico_set_binary_type") + +package(default_visibility = ["//visibility:public"]) + +alias( + name = "pico_critical_xip_sram_test_extra_link", + actual = select({ + "//bazel/constraint:rp2040": "//bazel:empty_cc_lib", + "//conditions:default": "//src/rp2_common/hardware_riscv_platform_timer", + }), + visibility = ["//visibility:private"], +) + +cc_binary( + name = "pico_critical_xip_sram_test_actual", + testonly = True, + srcs = ["pico_critical_xip_sram_test.c"], + tags = ["manual"], # Built via pico_critical_xip_sram_test + deps = [ + ":pico_critical_xip_sram_test_extra_link", + "//src/rp2_common/hardware_dma", + "//src/rp2_common/pico_multicore", + "//src/rp2_common/pico_stdlib", + "//test/pico_test", + ], +) + +pico_set_binary_type( + name = "pico_critical_xip_sram_test_typed", + testonly = True, + src = ":pico_critical_xip_sram_test_actual", + binary_type = "copy_to_ram", + target_compatible_with = compatible_with_rp2(), +) + +extra_copts_for_all_deps( + name = "pico_critical_xip_sram_test", + testonly = True, + src = ":pico_critical_xip_sram_test_typed", + extra_copts = [ + "-DPICO_TIME_CRITICAL_PLACEMENT=__in_xip_ram", + "-DPICO_USE_XIP_CACHE_AS_RAM=1", + ], + target_compatible_with = compatible_with_rp2(), +) + +# Currently doesn't fit, because bazel doesn't have a pico_minimize_runtime equivalent +exports_files(["pico_xip_sram_test.c"]) +# cc_binary( +# name = "pico_xip_sram_test_actual", +# testonly = True, +# srcs = ["pico_xip_sram_test.c"], +# tags = ["manual"], # Built via pico_xip_sram_test +# deps = [ +# "//src/rp2_common/pico_stdlib", +# "//src/rp2_common/pico_multicore", +# "//src/rp2_common/hardware_dma", +# ], +# ) +# +# pico_set_binary_type( +# name = "pico_xip_sram_test", +# testonly = True, +# src = ":pico_xip_sram_test_actual", +# binary_type = "xip_ram", +# target_compatible_with = compatible_with_rp2() + incompatible_with_config("//bazel/constraint:rp2040"), +# ) diff --git a/test/pico_xip_sram_test/CMakeLists.txt b/test/pico_xip_sram_test/CMakeLists.txt new file mode 100644 index 000000000..defdebeca --- /dev/null +++ b/test/pico_xip_sram_test/CMakeLists.txt @@ -0,0 +1,100 @@ +# Use XIP SRAM for time critical functions +add_executable(pico_critical_xip_sram_test pico_critical_xip_sram_test.c) +target_link_libraries(pico_critical_xip_sram_test PRIVATE pico_stdlib pico_multicore hardware_dma pico_test) +if (NOT PICO_RP2040) + target_link_libraries(pico_critical_xip_sram_test PRIVATE hardware_riscv_platform_timer) +endif() +pico_set_binary_type(pico_critical_xip_sram_test copy_to_ram) +pico_set_time_critical_placement(pico_critical_xip_sram_test xip_ram) +pico_enable_stdio_usb(pico_critical_xip_sram_test 1) # test with USB as that invokes flash functions +pico_add_extra_outputs(pico_critical_xip_sram_test) + +# Use Scratch X for time critical functions (should still be fast, as core1 function doesn't use stack) +add_executable(pico_critical_scratch_x_test pico_critical_xip_sram_test.c) +target_link_libraries(pico_critical_scratch_x_test PRIVATE pico_stdlib pico_multicore hardware_dma pico_test) +if (NOT PICO_RP2040) + target_link_libraries(pico_critical_scratch_x_test PRIVATE hardware_riscv_platform_timer) + target_compile_definitions(pico_critical_scratch_x_test PRIVATE + TEXT_FUNC_XIP_BASE=SRAM_SCRATCH_X_BASE + TEXT_FUNC_XIP_END=SRAM_SCRATCH_Y_BASE + ) +else() + target_compile_definitions(pico_critical_scratch_x_test PRIVATE + TEXT_FUNC_XIP_BASE=SRAM4_BASE + TEXT_FUNC_XIP_END=SRAM5_BASE + ) +endif() +pico_set_binary_type(pico_critical_scratch_x_test copy_to_ram) +pico_set_time_critical_placement(pico_critical_scratch_x_test scratch_x) +pico_add_extra_outputs(pico_critical_scratch_x_test) + +# Use Scratch Y for time critical functions (should still be fast, as this is only used by core0 stack) +add_executable(pico_critical_scratch_y_test pico_critical_xip_sram_test.c) +target_link_libraries(pico_critical_scratch_y_test PRIVATE pico_stdlib pico_multicore hardware_dma pico_test) +if (NOT PICO_RP2040) + target_link_libraries(pico_critical_scratch_y_test PRIVATE hardware_riscv_platform_timer) + target_compile_definitions(pico_critical_scratch_y_test PRIVATE + TEXT_FUNC_XIP_BASE=SRAM_SCRATCH_Y_BASE + TEXT_FUNC_XIP_END=SRAM_END + ) +else() + target_compile_definitions(pico_critical_scratch_y_test PRIVATE + TEXT_FUNC_XIP_BASE=SRAM5_BASE + TEXT_FUNC_XIP_END=SRAM_END + ) +endif() +pico_set_binary_type(pico_critical_scratch_y_test copy_to_ram) +pico_set_time_critical_placement(pico_critical_scratch_y_test scratch_y) +pico_add_extra_outputs(pico_critical_scratch_y_test) + +# Use XIP SRAM for time critical functions and scratch X for not in flash functions +add_executable(pico_critical_xip_sram_no_flash_scratch_x_test pico_critical_xip_sram_test.c) +target_link_libraries(pico_critical_xip_sram_no_flash_scratch_x_test PRIVATE pico_stdlib pico_multicore hardware_dma pico_test) +if (NOT PICO_RP2040) + target_link_libraries(pico_critical_xip_sram_no_flash_scratch_x_test PRIVATE hardware_riscv_platform_timer) + target_compile_definitions(pico_critical_xip_sram_no_flash_scratch_x_test PRIVATE + TEXT_FUNC_SRAM_BASE=SRAM_SCRATCH_X_BASE + TEXT_FUNC_SRAM_END=SRAM_SCRATCH_Y_BASE + ) +else() + target_compile_definitions(pico_critical_xip_sram_no_flash_scratch_x_test PRIVATE + TEXT_FUNC_SRAM_BASE=SRAM4_BASE + TEXT_FUNC_SRAM_END=SRAM5_BASE + ) +endif() +target_compile_definitions(pico_critical_xip_sram_no_flash_scratch_x_test PRIVATE + PICO_CORE1_STACK_SIZE=0x200 +) +pico_set_binary_type(pico_critical_xip_sram_no_flash_scratch_x_test copy_to_ram) +pico_set_not_in_flash_placement(pico_critical_xip_sram_no_flash_scratch_x_test scratch_x) +pico_set_time_critical_placement(pico_critical_xip_sram_no_flash_scratch_x_test xip_ram) +pico_enable_stdio_usb(pico_critical_xip_sram_no_flash_scratch_x_test 1) # test with USB as that invokes flash functions +pico_add_extra_outputs(pico_critical_xip_sram_no_flash_scratch_x_test) + +# Use XIP SRAM for time critical functions (no_flash build) +add_executable(pico_critical_xip_sram_test_no_flash pico_critical_xip_sram_test.c) +target_link_libraries(pico_critical_xip_sram_test_no_flash PRIVATE pico_stdlib pico_multicore hardware_dma pico_test) +if (NOT PICO_RP2040) + target_link_libraries(pico_critical_xip_sram_test_no_flash PRIVATE hardware_riscv_platform_timer) +endif() +pico_set_binary_type(pico_critical_xip_sram_test_no_flash no_flash) +pico_set_time_critical_placement(pico_critical_xip_sram_test_no_flash xip_ram) +pico_add_extra_outputs(pico_critical_xip_sram_test_no_flash) + +if (NOT PICO_RP2040 AND NOT PICO_C_COMPILER_IS_CLANG) + # XIP SRAM only binary, clang version is too big + add_executable(pico_xip_sram_test pico_xip_sram_test.c) + target_link_libraries(pico_xip_sram_test PRIVATE pico_stdlib) + pico_set_binary_type(pico_xip_sram_test xip_ram) + pico_minimize_runtime(pico_xip_sram_test INCLUDE PRINTF PRINTF_MINIMAL DEFAULT_ALARM_POOL PANIC FLOAT) + target_compile_definitions(pico_xip_sram_test PRIVATE PICO_HEAP_SIZE=0x200) + pico_add_extra_outputs(pico_xip_sram_test) + + # Low power and critical XIP SRAM + add_executable(pico_critical_xip_sram_test_low_power pico_critical_xip_sram_test.c) + target_link_libraries(pico_critical_xip_sram_test_low_power PRIVATE pico_stdlib pico_multicore hardware_dma pico_test hardware_riscv_platform_timer pico_low_power) + pico_set_binary_type(pico_critical_xip_sram_test_low_power copy_to_ram) + pico_set_time_critical_placement(pico_critical_xip_sram_test_low_power xip_ram) + pico_set_persistent_data_loc(pico_critical_xip_sram_test_low_power xip_ram) + pico_add_extra_outputs(pico_critical_xip_sram_test_low_power) +endif() \ No newline at end of file diff --git a/test/pico_xip_sram_test/pico_critical_xip_sram_test.c b/test/pico_xip_sram_test/pico_critical_xip_sram_test.c new file mode 100644 index 000000000..0fb1871f5 --- /dev/null +++ b/test/pico_xip_sram_test/pico_critical_xip_sram_test.c @@ -0,0 +1,211 @@ +#include +#include "pico/stdlib.h" +#include "pico/test.h" +#include "pico/multicore.h" +#include "hardware/dma.h" +#if PICO_RP2040 +#include "hardware/structs/systick.h" +#else +#include "hardware/riscv_platform_timer.h" +#endif +#include "hardware/structs/busctrl.h" + +#if LIB_PICO_LOW_POWER +int __persistent_data(some_data); +#endif + + +PICOTEST_MODULE_NAME("XIP_SRAM", "critical xip sram test"); + + +int __time_critical_func(test_func_xip)(void) { +#if PICO_RP2040 + systick_hw->rvr = 0x00ffffff; + systick_hw->cvr = 0; +#else + riscv_timer_set_mtimecmp(0xffffffffffffffff); + riscv_timer_set_mtime(0); +#endif + + volatile uint32_t i = 0; + i += 4; + i += i; + i += 7; + i += i; + i += i; + +#if PICO_RP2040 + return systick_hw->rvr - systick_hw->cvr; +#else + return riscv_timer_get_mtime(); +#endif +} + +int __no_inline_not_in_flash_func(test_func_sram)(void) { +#if PICO_RP2040 + systick_hw->rvr = 0x00ffffff; + systick_hw->cvr = 0; +#else + riscv_timer_set_mtimecmp(0xffffffffffffffff); + riscv_timer_set_mtime(0); +#endif + + volatile uint32_t i = 0; + i += 4; + i += i; + i += 7; + i += i; + i += i; + +#if PICO_RP2040 + return systick_hw->rvr - systick_hw->cvr; +#else + return riscv_timer_get_mtime(); +#endif +} + + +void core1_entry() { + // Just read memory from SRAM bank 0 repeatedly + // word-striped across 4 banks, so read every 16 bytes +#ifndef __riscv + pico_default_asm_volatile( + "1:\n" + "ldr r0, =%c0\n" + "ldr r1, [r0, #0]\n" + "ldr r2, [r0, #16]\n" + "ldr r3, [r0, #32]\n" + "ldr r4, [r0, #48]\n" + "adds r0, #64\n" + "ldr r1, [r0, #0]\n" + "ldr r2, [r0, #16]\n" + "ldr r3, [r0, #32]\n" + "ldr r4, [r0, #48]\n" + "adds r0, #64\n" + "ldr r1, [r0, #0]\n" + "ldr r2, [r0, #16]\n" + "ldr r3, [r0, #32]\n" + "ldr r4, [r0, #48]\n" + "b 1b\n" + : : "i" (SRAM_BASE) : "r0", "r1", "r2", "r3", "r4" + ); +#else + pico_default_asm_volatile( + "1:\n" + "li a0, %0\n" + "lw a1, 0(a0)\n" + "lw a2, 16(a0)\n" + "lw a3, 32(a0)\n" + "lw a4, 48(a0)\n" + "addi a0, a0, 64\n" + "lw a1, 0(a0)\n" + "lw a2, 16(a0)\n" + "lw a3, 32(a0)\n" + "lw a4, 48(a0)\n" + "addi a0, a0, 64\n" + "lw a1, 0(a0)\n" + "lw a2, 16(a0)\n" + "lw a3, 32(a0)\n" + "lw a4, 48(a0)\n" + "j 1b\n" + : : "i" (SRAM_BASE) : "a0", "a1", "a2", "a3", "a4" + ); +#endif +} + + +void trigger_dma(void) { + int dat[8]; + for (int i = 0; i < count_of(dat); i++) { + int chan = dma_claim_unused_channel(true); + dma_channel_config c = dma_channel_get_default_config(chan); + channel_config_set_transfer_data_size(&c, DMA_SIZE_32); + channel_config_set_read_increment(&c, true); + channel_config_set_write_increment(&c, true); + uint32_t from = SRAM_BASE; + uint32_t to = SRAM_BASE + ((SRAM4_BASE - SRAM_BASE) / 2); + uint32_t size = ((SRAM4_BASE - SRAM_BASE) / 2) / 4; + dma_channel_configure(chan, &c, (uint32_t*)to, (uint32_t*)from, dma_encode_transfer_count(size), true); + dat[i] = chan; + } + for (int i = 0; i < count_of(dat); i++) { + dma_channel_unclaim(dat[i]); + } +} + + +#ifndef TEXT_FUNC_XIP_BASE +#define TEXT_FUNC_XIP_BASE XIP_SRAM_BASE +#endif + +#ifndef TEXT_FUNC_XIP_END +#define TEXT_FUNC_XIP_END XIP_SRAM_END +#endif + +#ifndef TEXT_FUNC_SRAM_BASE +#define TEXT_FUNC_SRAM_BASE SRAM_STRIPED_BASE +#endif + +#ifndef TEXT_FUNC_SRAM_END +#define TEXT_FUNC_SRAM_END SRAM4_BASE +#endif + + +int main(void) { + stdio_init_all(); + printf("pico_xip_sram_test begins\n"); + + PICOTEST_START(); + + #if LIB_PICO_LOW_POWER + PICOTEST_START_SECTION("test_low_power") + PICOTEST_CHECK(some_data == 0, "persistent some_data is not 0"); + PICOTEST_END_SECTION() + #endif + + PICOTEST_START_SECTION("test_func_addresses") + printf("test_func_xip at %p\n", test_func_xip); + printf("test_func_sram at %p\n", test_func_sram); + + PICOTEST_CHECK((uint32_t)test_func_xip >= TEXT_FUNC_XIP_BASE && (uint32_t)test_func_xip < TEXT_FUNC_XIP_END, "test_func_xip is not in XIP SRAM"); + PICOTEST_CHECK((uint32_t)test_func_sram >= TEXT_FUNC_SRAM_BASE && (uint32_t)test_func_sram < TEXT_FUNC_SRAM_END, "test_func_sram is not in SRAM 0-3"); + PICOTEST_END_SECTION() + + multicore_launch_core1(core1_entry); + +#if PICO_RP2040 + systick_hw->csr = 0x4 | 0x1; // clock source and enable +#else + riscv_timer_set_fullspeed(true); + riscv_timer_set_enabled(true); + riscv_timer_set_mtimecmp(0xffffffffffffffff); +#endif + + // Give core1 and DMA high priority + hw_set_bits(&busctrl_hw->priority, BUSCTRL_BUS_PRIORITY_PROC1_BITS | BUSCTRL_BUS_PRIORITY_DMA_R_BITS | BUSCTRL_BUS_PRIORITY_DMA_W_BITS); + hw_clear_bits(&busctrl_hw->priority, BUSCTRL_BUS_PRIORITY_PROC0_BITS); + + PICOTEST_START_SECTION("test_func"); + int test_func_xip_cycles = 0; + int test_func_sram_cycles = 0; + for (int i = 0; i < 5; i++) { + printf("running... %d\n", i); + trigger_dma(); + int tmp = test_func_xip(); + test_func_xip_cycles += tmp; + printf("test_func_xip: %d\n", tmp); + trigger_dma(); + tmp = test_func_sram(); + test_func_sram_cycles += tmp; + printf("test_func_sram: %d\n", tmp); + sleep_ms(500); + } + +#if TEXT_FUNC_SRAM_BASE == SRAM_STRIPED_BASE + PICOTEST_CHECK(test_func_xip_cycles < test_func_sram_cycles, "test_func_xip took longer than test_func_sram"); +#endif + + PICOTEST_END_SECTION(); + + PICOTEST_END_TEST(); +} diff --git a/test/pico_xip_sram_test/pico_xip_sram_test.c b/test/pico_xip_sram_test/pico_xip_sram_test.c new file mode 100644 index 000000000..aa3610843 --- /dev/null +++ b/test/pico_xip_sram_test/pico_xip_sram_test.c @@ -0,0 +1,16 @@ +#include +#include "pico/stdlib.h" + + +int main(void) { + stdio_init_all(); + printf("pico_xip_sram_test begins\n"); + + for (int i = 0; i < 5; i++) { + printf("running... %d\n", i); + sleep_ms(500); + } + + printf("pico_xip_sram_test ends\n"); + return 0; +} diff --git a/tools/bazel_build.py b/tools/bazel_build.py index cfe8137ed..8acffca8f 100755 --- a/tools/bazel_build.py +++ b/tools/bazel_build.py @@ -60,6 +60,7 @@ "//test/pico_low_power_test:low_power_test_simple", "//test/pico_low_power_test:external_sleep_timer", "//test/pico_async_context_test:pico_async_context_test", + "//test/pico_xip_sram_test:pico_critical_xip_sram_test", # Pretty much only Picotool and pioasm build on Windows. "//..." if os.name == "nt" else "",