- 
                Notifications
    You must be signed in to change notification settings 
- Fork 1.4k
NSIB: Cleanup RAM fixes and tests - nRF54L #25136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
          
     Merged
      
      
            tomchy
  merged 2 commits into
  nrfconnect:main
from
ahasztag:NCSDK-34936_enable_SB_CLEANUP_RAM
  
      
      
   
  Oct 28, 2025 
      
    
  
     Merged
                    Changes from all commits
      Commits
    
    
            Show all changes
          
          
            2 commits
          
        
        Select commit
          Hold shift + click to select a range
      
      
    File filter
Filter by extension
Conversations
          Failed to load comments.   
        
        
          
      Loading
        
  Jump to
        
          Jump to file
        
      
      
          Failed to load files.   
        
        
          
      Loading
        
  Diff view
Diff view
          Some comments aren't visible on the classic Files Changed page.
        
There are no files selected for viewing
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # | ||
| # Copyright (c) 2025 Nordic Semiconductor | ||
| # | ||
| # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
| # | ||
|  | ||
| cmake_minimum_required(VERSION 3.20.0) | ||
|  | ||
| find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) | ||
| project(b0_ram_cleanup) | ||
|  | ||
| FILE(GLOB app_sources src/*.c) | ||
| target_sources(app PRIVATE ${app_sources}) | ||
| target_include_directories(app PRIVATE .) | 
        
          
  
    
      
          
            7 changes: 7 additions & 0 deletions
          
          7 
        
  tests/subsys/bootloader/b0_ram_cleanup/boards/nrf54l15dk_nrf54l15_cpuapp.overlay
  
  
      
      
   
        
      
      
    
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| /* | ||
| * Copyright (c) 2025 Nordic Semiconductor ASA | ||
| * | ||
| * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
| */ | ||
|  | ||
| #include "../nrf54l15dk_nrf54l15_cpuapp_common.dtsi" | 
        
          
  
    
      
          
            10 changes: 10 additions & 0 deletions
          
          10 
        
  tests/subsys/bootloader/b0_ram_cleanup/modules/b0_cleanup_ram_test_prepare/CMakeLists.txt
  
  
      
      
   
        
      
      
    
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| # | ||
| # Copyright (c) 2025 Nordic Semiconductor | ||
| # | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this in a zephyr sub folder? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By mistake, moved | ||
| # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
| # | ||
|  | ||
| cmake_minimum_required(VERSION 3.20.0) | ||
|  | ||
| zephyr_library() | ||
| zephyr_library_sources(src/b0_cleanup_ram_test_prepare.c) | ||
        
          
  
    
      
          
            71 changes: 71 additions & 0 deletions
          
          71 
        
  ...ader/b0_ram_cleanup/modules/b0_cleanup_ram_test_prepare/src/b0_cleanup_ram_test_prepare.c
  
  
      
      
   
        
      
      
    
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| /* | ||
| * Copyright (c) 2025 Nordic Semiconductor ASA | ||
| * | ||
| * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
| */ | ||
|  | ||
| #include <zephyr/init.h> | ||
| #include <zephyr/device.h> | ||
| #include <zephyr/sys/printk.h> | ||
| #include <hal/nrf_timer.h> | ||
| #include <zephyr/linker/linker-defs.h> | ||
| #include <zephyr/drivers/retained_mem.h> | ||
|  | ||
| #define CLEANUP_RAM_GAP_START ((uint32_t)__ramfunc_start) | ||
| #define CLEANUP_RAM_GAP_END ((uint32_t) __ramfunc_end) | ||
|  | ||
| /* Only the RAM outside of the defined linker sections will be populated, | ||
| * as modifying the defined linker sections could lead to NSIB malfunction. | ||
| */ | ||
| #define RAM_TO_POPULATE_START ((uint32_t) _image_ram_end) | ||
| #define RAM_TO_POPULATE_END (CONFIG_SRAM_SIZE * 1024) | ||
| #define VALUE_TO_POPULATE 0xDEADBEAF | ||
|  | ||
| /* As peripheral registers are not cleared during RAM cleanup, we can | ||
| * use a register of a peripheral unused by NSIB to save data which can then | ||
| * be read by the application. | ||
| * We use this trick to save the start and end addresses of the RAMFUNC region. | ||
| * This region is not erased during the RAM cleanup, as it contains the code responsible | ||
| * for performing the RAM cleanup, so it must be skipped when checking if the RAM cleanup | ||
| * has been successfully performed. | ||
| * The TIMER00 is not used by NSIB, and is therefore its CC[0] and CC[1] registers | ||
| * are used for this purpose. | ||
| */ | ||
| #define RAMFUNC_START_SAVE_REGISTER NRF_TIMER00->CC[0] | ||
| #define RAMFUNC_END_SAVE_REGISTER NRF_TIMER00->CC[1] | ||
|  | ||
| #define RETAINED_DATA "RETAINED" | ||
|  | ||
| static int populate_ram(void) | ||
| { | ||
| RAMFUNC_START_SAVE_REGISTER = CLEANUP_RAM_GAP_START; | ||
| RAMFUNC_END_SAVE_REGISTER = CLEANUP_RAM_GAP_END; | ||
|  | ||
| for (uint32_t addr = RAM_TO_POPULATE_START; addr < RAM_TO_POPULATE_END; | ||
| addr += sizeof(uint32_t)) { | ||
| *(uint32_t *) addr = VALUE_TO_POPULATE; | ||
| } | ||
|  | ||
| #if DT_HAS_COMPAT_STATUS_OKAY(zephyr_retained_ram) | ||
| const struct device *retained_mem_dev = | ||
| DEVICE_DT_GET(DT_INST(0, zephyr_retained_ram)); | ||
| size_t retained_size; | ||
|  | ||
| if (!device_is_ready(retained_mem_dev)) { | ||
| printk("Retained memory device is not ready"); | ||
| return -ENODEV; | ||
| } | ||
|  | ||
| retained_size = retained_mem_size(retained_mem_dev); | ||
|  | ||
| if (retained_size < strlen(RETAINED_DATA)) { | ||
| printk("Retained memory size is too small"); | ||
| return -EINVAL; | ||
| } | ||
|  | ||
| retained_mem_write(retained_mem_dev, 0, RETAINED_DATA, strlen(RETAINED_DATA)); | ||
| #endif | ||
| return 0; | ||
| } | ||
|  | ||
| SYS_INIT(populate_ram, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); | 
        
          
  
    
      
          
            2 changes: 2 additions & 0 deletions
          
          2 
        
  tests/subsys/bootloader/b0_ram_cleanup/modules/b0_cleanup_ram_test_prepare/zephyr/module.yml
  
  
      
      
   
        
      
      
    
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| build: | ||
| cmake: . | 
        
          
  
    
      
          
            29 changes: 29 additions & 0 deletions
          
          29 
        
  tests/subsys/bootloader/b0_ram_cleanup/nrf54l15dk_nrf54l15_cpuapp_common.dtsi
  
  
      
      
   
        
      
      
    
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| /* | ||
| * Copyright (c) 2025 Nordic Semiconductor ASA | ||
| * | ||
| * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
| */ | ||
|  | ||
| / { | ||
| cpuapp_sram@2003FFF0 { | ||
|         
                  nordicjm marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| compatible = "zephyr,memory-region", "mmio-sram"; | ||
| reg = <0x2003FFF0 0x10>; | ||
| zephyr,memory-region = "RetainedMem"; | ||
| status = "okay"; | ||
|  | ||
| retainedmem { | ||
|         
                  nordicjm marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| compatible = "zephyr,retained-ram"; | ||
| status = "okay"; | ||
| #address-cells = <1>; | ||
| #size-cells = <1>; | ||
|  | ||
| test_retention_area: test_retention_area@0 { | ||
| compatible = "zephyr,retention"; | ||
| status = "okay"; | ||
| reg = <0x0 0x10>; | ||
| prefix = [0B 01]; | ||
| checksum = <4>; | ||
| }; | ||
| }; | ||
| }; | ||
| }; | ||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| # | ||
| # Copyright (c) 2025 Nordic Semiconductor ASA | ||
| # | ||
| # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
| # | ||
| CONFIG_ZTEST=y | ||
| CONFIG_ARM_MPU=n | ||
| CONFIG_SOC_EARLY_RESET_HOOK=y | ||
|  | ||
| CONFIG_RETAINED_MEM=y | ||
| CONFIG_RETAINED_MEM_ZEPHYR_RAM=y | ||
| CONFIG_RETAINED_MEM_NRF_GPREGRET=n | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,149 @@ | ||
| /* | ||
| * Copyright (c) 2025 Nordic Semiconductor ASA | ||
| * | ||
| * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
| */ | ||
|  | ||
| #include <zephyr/ztest.h> | ||
| #include <hal/nrf_timer.h> | ||
| #include <zephyr/drivers/retained_mem.h> | ||
|  | ||
| /* As peripheral registers are not cleared during RAM cleanup, we can | ||
| * use a register of a peripheral unused by NSIB to save data which can then | ||
| * be read by the application. | ||
| * We use this trick to save the start and end addresses of the RAMFUNC region. | ||
| * This region is not cleared during the RAM cleanup, as it contains the code responsible | ||
| * for performing the RAM cleanup, so it must be skipped when checking if the RAM cleanup | ||
| * has been successfully performed. | ||
| * The TIMER00 is not used by NSIB, and is therefore its CC[0] and CC[1] registers | ||
| * are used for this purpose. | ||
| */ | ||
| #define RAMFUNC_START_SAVE_REGISTER NRF_TIMER00->CC[0] | ||
| #define RAMFUNC_END_SAVE_REGISTER NRF_TIMER00->CC[1] | ||
|  | ||
| /* Using 2-byte magic values allows to load the whole value with movw */ | ||
| #define RAM_CLEANUP_SUCCESS_MAGIC 0x5678 | ||
| #define RAM_CLEANUP_FAILURE_MAGIC 0x4321 | ||
|  | ||
| static uint32_t __noinit ram_cleanup_result; | ||
| static uint32_t __noinit uncleared_address; | ||
| static uint32_t __noinit uncleared_value; | ||
|  | ||
| #define EXPECTED_RETAINED_DATA "RETAINED" | ||
|  | ||
| /** | ||
| * This hook needs to have the attribute __attribute__((naked)), | ||
| * as otherwise the stack would be modified when calling it, leading to | ||
| * test failure, as part of the RAM in which the stack resides wouldn't | ||
| * be zeroed. | ||
| */ | ||
| __attribute__((naked)) void soc_early_reset_hook(void) | ||
| { | ||
| __asm__ volatile ( | ||
| /* Load zero (value used to clear memory) into r0 */ | ||
| " mov r0, #0\n" | ||
| /* Explicitly clear the ram_cleanup_result variable */ | ||
| " mov r2, %6\n" | ||
| " str r0, [r2]\n" | ||
| /* Load the location of the saved ram func start address to r1 */ | ||
| " mov r1, %0\n" | ||
| /* Load the ram func start address to r2 */ | ||
| " ldr r2, [r1]\n" | ||
| /* Load the location of the saved ram func end address to r1 */ | ||
| " mov r1, %1\n" | ||
| /* Load the ram func end address to r3*/ | ||
| " ldr r3, [r1]\n" | ||
| /* Clear memory from ram func start to ram func end. | ||
| * The area is skipped during the RAM cleanup, | ||
| * so it is not cleared. | ||
| * Simply cleaning it up here is quicker | ||
| * than verifying if the current address is within the gap | ||
| * in each iteration of the loop. | ||
| */ | ||
| "ram_func_zero_loop:\n" | ||
| " cmp r2, r3\n" | ||
| " bge ram_func_zero_loop_done\n" | ||
| " str r0, [r2]\n" | ||
| /* Increment the address by 4 (word size) */ | ||
| " add r2, r2, #4\n" | ||
| " b ram_func_zero_loop\n" | ||
| "ram_func_zero_loop_done:\n" | ||
| /* Verify that all of the RAM memory has been cleared */ | ||
| /* Load SRAM base address to r1 */ | ||
| " mov r1, %2\n" | ||
| /* Load SRAM size to r2 */ | ||
| " mov r2, %3\n" | ||
| /* Calculate SRAM end address (base + size) */ | ||
| " add r2, r1, r2\n" | ||
| "verify_ram_loop:\n" | ||
| " cmp r1, r2\n" | ||
| " bge verify_ram_done\n" | ||
| /* Load value at current address and verify if it equals 0 */ | ||
| " ldr r3, [r1]\n" | ||
| " cmp r3, #0\n" | ||
| " bne ram_cleanup_failed\n" | ||
| /* Increment the address by 4 (word size) */ | ||
| " add r1, r1, #4\n" | ||
| " b verify_ram_loop\n" | ||
| "ram_cleanup_failed:\n" | ||
| /* Load RAM_CLEANUP_FAILURE_MAGIC into r0 */ | ||
| " movw r0, %4\n" | ||
| /* Save the uncleared address in uncleared_address variable */ | ||
| " mov r2, %7\n" | ||
| " str r1, [r2]\n" | ||
| /* Save the uncleared value in uncleared_value variable */ | ||
| " mov r2, %8\n" | ||
| " str r3, [r2]\n" | ||
| " b verification_done\n" | ||
| "verify_ram_done:\n" | ||
| /* Load RAM_CLEANUP_SUCCESS_MAGIC */ | ||
| " movw r0, %5\n" | ||
| "verification_done:\n" | ||
| /* Store result in ram_cleanup_result variable */ | ||
| " mov r2, %6\n" | ||
| " str r0, [r2]\n" | ||
| /* __attribute__((naked)) requires manual branching */ | ||
| " bx lr\n" | ||
| : | ||
| : "r" (&RAMFUNC_START_SAVE_REGISTER), | ||
| "r" (&RAMFUNC_END_SAVE_REGISTER), | ||
| "r" (CONFIG_SRAM_BASE_ADDRESS), | ||
| "r" (CONFIG_SRAM_SIZE * 1024), | ||
| "i" (RAM_CLEANUP_FAILURE_MAGIC), | ||
| "i" (RAM_CLEANUP_SUCCESS_MAGIC), | ||
| "r" (&ram_cleanup_result), | ||
| "r" (&uncleared_address), | ||
| "r" (&uncleared_value) | ||
| : "r0", "r1", "r2", "r3", "lr", "memory" | ||
| ); | ||
| } | ||
|  | ||
| ZTEST(b0_ram_cleanup, test_ram_cleanup) | ||
| { | ||
| zassert_true((ram_cleanup_result == RAM_CLEANUP_SUCCESS_MAGIC) || | ||
| (ram_cleanup_result == RAM_CLEANUP_FAILURE_MAGIC), | ||
| "RAM cleanup result should be either success or failure"); | ||
| zassert_equal(ram_cleanup_result, RAM_CLEANUP_SUCCESS_MAGIC, | ||
| "Uncleared word detected at address %p, value 0x%x", uncleared_address, | ||
| uncleared_value); | ||
|  | ||
| #if DT_HAS_COMPAT_STATUS_OKAY(zephyr_retained_ram) | ||
| const struct device *retained_mem_dev = | ||
| DEVICE_DT_GET(DT_INST(0, zephyr_retained_ram)); | ||
| size_t retained_size; | ||
| uint8_t buffer[strlen(EXPECTED_RETAINED_DATA)+1]; | ||
|  | ||
| zassert_true(device_is_ready(retained_mem_dev), "Retained memory device is not ready"); | ||
|  | ||
| retained_size = retained_mem_size(retained_mem_dev); | ||
|  | ||
| zassert_true(retained_size >= strlen(EXPECTED_RETAINED_DATA), | ||
| "Retained memory size is too small"); | ||
|  | ||
| retained_mem_read(retained_mem_dev, 0, buffer, strlen(EXPECTED_RETAINED_DATA)); | ||
| zassert_mem_equal(buffer, EXPECTED_RETAINED_DATA, strlen(EXPECTED_RETAINED_DATA), | ||
| "Retained data is not correct"); | ||
| #endif | ||
| } | ||
|  | ||
| ZTEST_SUITE(b0_ram_cleanup, NULL, NULL, NULL, NULL, NULL); | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| # | ||
| # Copyright (c) 2025 Nordic Semiconductor | ||
| # | ||
| # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
| # | ||
|  | ||
| # Adding a module to b0 is needed as a way to inject source code into | ||
| # the non-default sysbuild image (in this case b0). | ||
| set(b0_EXTRA_ZEPHYR_MODULES ${CMAKE_CURRENT_LIST_DIR}/modules/b0_cleanup_ram_test_prepare CACHE INTERNAL "") | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # | ||
| # Copyright (c) 2025 Nordic Semiconductor | ||
| # | ||
| # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
| # | ||
|  | ||
| SB_CONFIG_SECURE_BOOT_APPCORE=y | ||
| SB_CONFIG_SECURE_BOOT_GENERATE_DEFAULT_KMU_KEYFILE=y | 
      
      Oops, something went wrong.
        
    
  
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
Uh oh!
There was an error while loading. Please reload this page.