This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to place constants at know address?

Hello,

when I was working on MSP430 I used to place the firmware version constant at a known address in flash so that it can be verified which firmware version is flashed without running the application, just by reading the flash with a programmer.

With a nRF52, how could I place constants at known addresses? I guess, the answer is compiler-specific? I'm using Keil.

Thanks in advance for your help.

  • Hi,

    You can use the method shown in the Flash Write Example to write directly to addresses in flash.

    You should also check out the UICR registers, and the UICR Config Example in the SDK, which are intended for storing user specific settings in non-volatile memory.

    Best regards,

    Jørgen

  • Same here, and I went to conclusion that it is not quite simple when you do not want to use Flash Write / FDS (Flash Data Storage) module, nor the UICR registers (limited to 128B, not really scalable)

    In my case, I want to store data once at production time with a production jig, at a fixed and predetermined location that will not be overwritten during DFU / by the bootloader process. It seems that the Flash Data Storage will use the UPPER region right below the bootloader, which is located in my case at 0x73000. Since the FDS will use the same/share APP_DATA region and that FDS is used by the peer_manager which I do not have control on it, I want to make sure that my app_data will never be corrupted nor overwritten.

    When the number of pages (3) are the same, there is no room left for "real" app_data (hard written at production time), typically

    # define DFU_APP_DATA_RESERVED CODE_PAGE_SIZE  *  3
    
    # define FDS_VIRTUAL_PAGES   3
    

    Then I figured to allow (at least) one more APP_DATA page (4 | 0x4000) than what is allowed for the FDS (3 | 0x3000), and created the following macros:

    #define FDS_TOTAL_SIZE         (FDS_VIRTUAL_PAGES*FDS_VIRTUAL_PAGE_SIZE*4)
    #define APP_DATA_TOTAL_SIZE    (DFU_APP_DATA_RESERVED-FDS_TOTAL_SIZE)
    #define FS_PAGE_START_ADDR     ((uint32_t)FS_PAGE_END_ADDR - FDS_TOTAL_SIZE)
    
    #define APP_DATA_END_ADDR      (FS_PAGE_START_ADDR)
    #define APP_DATA_START_ADDR    ((uint32_t)APP_DATA_END_ADDR - APP_DATA_TOTAL_SIZE)
    

    I would have appreciated that this would have been explicitly designed and documented so this I why I took the time to share.

    Be aware that when the bootloader is not present, the macro FS_PAGE_END_ADDR returns the end of the flash (0x80000), not the (not present) bootloader address (0x73000 in my case).

    Here is some useful Iogguing code to validate what is happening at runtime:

        NRF_LOG_DEBUG("SOFTDEVICE_REGION_START              (0x%08X)\n", (uint32_t)SOFTDEVICE_REGION_START);
          
        NRF_LOG_DEBUG("CODE_REGION_1_START                  (0x%08X)\n", (uint32_t)CODE_REGION_1_START);
        
        NRF_LOG_DEBUG("BOOTLOADER_START_ADDR                (0x%08X)\n", (uint32_t)BOOTLOADER_START_ADDR);               // extern uint32_t* Image$$ER_IROM1$$Base
        
        NRF_LOG_DEBUG("NRF_MBR_PARAMS_PAGE_ADDRESS          (0x%08X)\n", (uint32_t) NRF_MBR_PARAMS_PAGE_ADDRESS);  //0x7E000
        NRF_LOG_HEXDUMP_INFO((uint32_t*)NRF_MBR_PARAMS_PAGE_ADDRESS, 64);
    
        NRF_LOG_DEBUG("BOOTLOADER_SETTINGS_ADDRESS          (0x%08X)\n", (uint32_t)BOOTLOADER_SETTINGS_ADDRESS);   //0x7F000
        NRF_LOG_HEXDUMP_INFO((uint32_t*)BOOTLOADER_SETTINGS_ADDRESS, 64);
    
        NRF_LOG_DEBUG("CODE_PAGE_SIZE                       (0x%08X)\n", (uint32_t)CODE_PAGE_SIZE);
        NRF_LOG_DEBUG("DFU_APP_DATA_RESERVED                (0x%08X)\n\n", (uint32_t)DFU_APP_DATA_RESERVED);
    
        
    
        if (APP_DATA_TOTAL_SIZE < CODE_PAGE_SIZE)
        {
            NRF_LOG_WARNING("DFU_APP_DATA_RESERVED contains only FDS_VIRTUAL_PAGES, APP_DATA WILL BE OVERWRITTEN by FDS (peer_manager)!!!!\n");
        }
        else
        {
            NRF_LOG_DEBUG("APP_DATA_START_ADDR                  (0x%08X)\n", (uint32_t)APP_DATA_START_ADDR);
            NRF_LOG_DEBUG("APP_DATA_TOTAL_SIZE                  (0x%08X)\n", (uint32_t)APP_DATA_TOTAL_SIZE);
            NRF_LOG_DEBUG("APP_DATA_END_ADDR                    (0x%08X)\n", (uint32_t)APP_DATA_END_ADDR);
            NRF_LOG_HEXDUMP_INFO((uint32_t*)APP_DATA_START_ADDR, APP_DATA_TOTAL_SIZE); 
        }
    
    
        NRF_LOG_DEBUG("FS_PAGE_START_ADDR                   (0x%08X)\n", (uint32_t)FS_PAGE_START_ADDR);
        NRF_LOG_DEBUG("FS_TOTAL_SIZE                        (0x%08X)\n", (uint32_t)FDS_TOTAL_SIZE);
        NRF_LOG_DEBUG("FS_PAGE_END_ADDR                     (0x%08X)\n", (uint32_t)FS_PAGE_END_ADDR);        
      //  NRF_LOG_HEXDUMP_INFO((uint32_t*)FS_PAGE_START_ADDR, FDS_TOTAL_SIZE);
    
        
        NRF_LOG_DEBUG("NRF_UICR_BOOTLOADER_START_ADDRESS    (0x%08X)\n", (uint32_t)NRF_UICR_BOOTLOADER_START_ADDRESS);
        NRF_LOG_DEBUG("NRF_UICR_MBR_PARAMS_PAGE_ADDRESS     (0x%08X)\n\n", (uint32_t)NRF_UICR_MBR_PARAMS_PAGE_ADDRESS);
    

    Finally, does anybody see any possible catch in my approach for reserving an APP_DATA location? Any feedback would be appreciated!

    With my best regards,

    Philippe Meilleur

Related