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

How to prevent the application project to write to a defined memory segment

H,

I am using the SDK 15.0.0 and Segger Embedded Studio for ARM V3.40.

I have been successfully defining a flash memory section for data exchange between the bootloader project and the application project.

The flash memory section is the following
btldr_app_exchange R 0x0007D000 0x1000

Currently the bootloader project can write to this memory section. The problem I am facing is that the application project writes at run time to this very memory segment at the address 0x0007D000 to 0x0007D007(below)

When I define a different memory segment (btldr_app_exchange R 0x0007D08 0xFF8) the exact same behaviour is observed (the application project writes at run time at the address 0x0007D000 to 0x0007D007 and only at this address)

1/ How can I prevent the application project to write at as given memory segment?

2/ Is the address x0007D000 to 0x0007D007 specific and shall not be used to exchange data between the bootloader and the application?

For the moment, I have decided to exclude address x0007D000 to 0x0007D007 from my memory segment (btldr_app_exchange R 0x0007D08 0xFF8)

Thanks in advance for your support.

M Nayrolles

Parents
  • Hello,

    The flash area that is written to here is an FDS page (Flash Data Storage). Is your application using FDS? Perhaps the peer manager is included? Search for fds_init() in your application project. 

    Why do you want to keep the application from writing to this page? In case you are using the FDS either directly, or indirectly (through the peer manager) you would want that module to access this area.

    Best regards,

    Edvin

  • Hello,

    Thank a lot for the feedback.

    Yes I include the peer manager (calling pm_init) in the application project. I can see that a storage instance m_fs is defined in fds.c through the call of the NRF_FSTORAGE_DEF macro:

    NRF_FSTORAGE_DEF(nrf_fstorage_t m_fs) =
    {
        // The flash area boundaries are set in fds_init().
        .evt_handler = fs_event_handler,
            /* These below are the boundaries of the flash space assigned to this instance of fstorage.
         * You must set these manually, even at runtime, before nrf_fstorage_init() is called.
         * The function nrf5_flash_end_addr_get() can be used to retrieve the last address on the
         * last page of flash available to write data. */
        .start_addr = 0x0007F000,
        .end_addr   = 0x0007FFFF,
    };

    I defined an additional storage instance m_btldr_app_exchange_data_fs (as below) both in the application and the bootloader project

    NRF_FSTORAGE_DEF(nrf_fstorage_t m_btldr_app_exchange_data_fs) =
    {
        .evt_handler = NULL,
        .start_addr  = 0x0007D000,
        .end_addr    = 0x0007DFFF
    };

    I do not want the application to write at the location defined by m_btldr_app_exchange_data_fs because only the bootloader should use it to pass information to the application. Is it unacceptable to have two storage instance defined (m_cuciniale_btldr_app_exchange_data_fs &m_fs) as I did in my application project?

    Anyway what I want to achieve is to define a memory space that will be written to by the bootloader (Which I was able to do for the address 0x0007D000 to 0x0007DFFF using storage instance). What shall I do in the application project to prevent the application to write in this memory space (0x0007D000 to 0x0007DFFF)? Shall use a different memory space? Which one ?

    Best regards, 

    Marlène

  • Hello Marlène,

    So I guess the peer manager uses FDS with 3 pages, and not 1, as you pasted here? You need a bare minimum of 2 for FDS to work at all.

    The custom flash area, m_btldr_app_exchange_data_fs, do you intend to use fds for this as well? Or "bare metal" fstorage? In case you consider fstorage, are you familiar with the way that updating flash content works? (you need to erase an entire page before you can write to an address that is already written to).

    Is there a reason for why you don't put the custom flash area next to the one used for FDS? 

    My suggestion for you is to just use FDS for everything, and keep the default settings of 3 pages.The peer manager has reserved all records with file IDs from 0xC000 to 0xFFFE.

    This means you can use file IDs 0x0001 to 0xBFFF. It is perfectly fine to have two instances using the same FDS area. The records are organized by FDS, and you can write, update and delete records. FDS will take care of positioning, updating and garbage collection (moving valid records to a new page, and deleting the old ones).

    Best regards,

    Edvin

  • Hello Edvin,

    So I guess the peer manager uses FDS with 3 pages, and not 1, as you pasted here? You need a bare minimum of 2 for FDS to work at all.

    I am probably missing something, but why would you assume, from the information I gave, that the peer manager I defined would use FDS with 1 page only?

    The custom flash area, m_btldr_app_exchange_data_fs, do you intend to use fds for this as well? Or "bare metal" fstorage? In case you consider fstorage, are you familiar with the way that updating flash content works? (you need to erase an entire page before you can write to an address that is already written to).

    Here I used "bare metal" fstorage in the bootloader project by calling data_exchange_btldr_init(false) in main below (which successfully copied the bootloader information to the given memory address from m_btldr_app_exchange_data_fs)

    ret_code_t data_exchange_btldr_init(bool sd_irq_initialized)
    {
        NRF_LOG_DEBUG("Calling cdata_exchange_btldr_init()...");
        btldr_app_exchange_data_t s_btldr_app_exchange_data_flash={0x0, "Unknown" } ;
        ret_code_t rc = data_exchange_btldr_flash_init(sd_irq_initialized);
        if (rc != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("data_exchange_btldr_flash_init() failed with error: %x", rc);
            return NRF_ERROR_INTERNAL;
        }
    
        if(btldr_version_read(s_btldr_app_exchange_data_flash)==NRF_SUCCESS)
          if(s_btldr_app_exchange_data_flash.btldr_version==s_btldr_app_exchange_data.btldr_version)
          return NRF_SUCCESS;
    
        // Reached if the page is erased or CRC is wrong.
        NRF_LOG_DEBUG("Resetting btldr_app_exchange.");
    
    #if IS_BTLDER_SW    
     
        rc = btldr_version_write(NULL);
        if (rc != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("nrf_dfu_flash_write() failed with error: %x", rc);
            return NRF_ERROR_INTERNAL;
        }
    #else
      memcpy(btldr_version , 
              (uint8_t *)s_btldr_app_exchange_data.btldr_version,
              sizeof(s_btldr_app_exchange_data.btldr_version)); 
    #endif
        return NRF_SUCCESS;
    }
    Is there a reason for why you don't put the custom flash area next to the one used for FDS? 

    Yes. The memory space 0x7e000 to 0x7efff is for mbr_parms_page as defined in my bootloader project, that is why my custom flash area is not next to the one used for FDS. I do not mind using another memory section (does not have to be part of the FDS area as defined in the application project) for the bootloader record. It just shouldn't be erased by the application project. 

    Thanks again & best regards,

    Edvin

  • Hello,

    Marlene said:
    I am probably missing something, but why would you assume, from the information I gave, that the peer manager I defined would use FDS with 1 page only?

     Because you mentioned NRF_FSTORAGE_DEF(nrf_fstorage_t m_fs) with .start_addr = 0x0007F000 and .end_addr = 0x0007FFFF (this is one page = 0x1000 = 4096 bytes). 

    fds.c doesn't specify these addresses directly, so I assumed you had changed these. Please correct me if I am wrong here. 

    fds.c's definition of NRF_FSTORAGE_DEF() in sdk 15.0.0 looks like this:

    NRF_FSTORAGE_DEF(nrf_fstorage_t m_fs) =
    {
        // The flash area boundaries are set in fds_init().
        .evt_handler = fs_event_handler,
    };

    the .start_addr and .end_addr is set dynamically dependent on whether there is a bootloader present or not, inside flash_bounds_set(). 

    Please note that the bootloader will typically be located between 0x78000 and 0x7DFFF:

    So if you have a bootloader you should not use the 0x7D000 area.

    If you also have FDS, you should also not touch the area that is set between .start_addr and .end_addr that is set in flash_bounds_set(). The flash pages after .end_addr is used by the bootloader, so you shouldn't use these either.

    I don't understand whether your 

    m_btldr_app_exchange_data_fs

    is fetching data that the bootloader writes (by default, and not something that you have added yourself), or if it is custom data. If it is custom data, then you should place it below the FDS pages that you are using. That is, the page directly below FDS' .start_addr.

    In your: // Reached if the page is erased or CRC is wrong

    please consider what happens if something goes wrong here. E.g. if you erase the page and then loose power (which may happen if your battery is running low and this is running close to the start of the application. You can expect some gliching of the input voltage). What happens if this is reached and the page is blank or corrupted? This is why we recommend FDS, because it will always write the new record before invalidating the old one. But it may be fine in your case. 

    To "protect" a flash area, please look at how the bootloader does this:

    ret_val = nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR, BOOTLOADER_SIZE, false);

    Remember that you can't delete the flash area here if this is called. Also, to make sure that the bootloader doesn't touch this area while performing a DFU, make sure that you set DFU_APP_DATA_RESERVED to the number of pages that you want to protect from the bootloader.

    Best regards,

    Edvin

    Best regards,

    Edvin

  • Hi Edvin,


    Thank again.

    It now works (I made the mistake that I merged an incorrect bootloader file using the merge command from the nrfutil sorry for that...). Below I try to summarise what I did, I I still have a problem at described at the end of this post. I can still close the case because it seems to be a different issue. 

    I have been using the flash area at address 0x77000 (size 0x1000) 

    in the .emProject file, I added btldr_app_exchange in both project files (application and bootloader)

    secure_bootloader.emProject:

    
    
    linker_section_placements_segments="FLASH RX 0x0 0x80000;RAM RWX 0x20000000 0x10000;uicr_mbr_params_page RX 0x10001018 0x4;mbr_params_page RX 0x0007E000 0x1000;btldr_app_exchange RWX 0x00077000 0x1000;bootloader_settings_page RX 0x0007F000 0x1000;uicr_bootloader_start_address RX 0x10001014 0x4"

    my_application.emProject:

    
    
    linker_section_placements_segments="FLASH RX 0x0 0x80000;RAM RWX 0x20000000 0x10000;btldr_app_exchange R 0x00077000 0x1000"

    I defined as below the page for the flash storage btldr_app_exchange_data both in the bootloader project and the application project: 

    
    
    NRF_FSTORAGE_DEF(nrf_fstorage_t m_btldr_app_exchange_data_fs) =
    {
        .evt_handler = NULL,
        .start_addr  = 0x00077000,
        .end_addr    = 0x00077FFF
    };
    
    #define BTLDR_APP_EXCHANGE_PAGE_SIZE 1000
    
    
    
    /**@brief   This variable reserves a page in flash for btldr_app_exchange_data (including the Bootloader version)
     *          to ensure the linker doesn't place any code or variables at this location.
     */
    #if defined (__CC_ARM )
    
        uint8_t m_btldr_app_exchange_data_buffer[BTLDR_APP_EXCHANGE_PAGE_SIZE]
            __attribute__((at(BOOTLOADER_SETTINGS_ADDRESS)))
            __attribute__((used));
    
    #elif defined ( __GNUC__ ) || defined ( __SES_ARM )
    
        uint8_t m_btldr_app_exchange_data_buffer[CBTLDR_APP_EXCHANGE_PAGE_SIZE]
            __attribute__((section(".btldr_app_exchange")))
            __attribute__((used));
    
    #elif defined ( __ICCARM__ )
    
        __no_init __root uint8_t m__btldr_app_exchange_data_buffer[BTLDR_APP_EXCHANGE_PAGE_SIZE]
            @ BOOTLOADER_SETTINGS_ADDRESS;
    
    #else
    
        #error Not a valid compiler/linker for m_dfu_settings placement.
    
    #endif // Compiler specific

    I then used "bare metal" fstorage in the bootloader project as I said in my last post and I was able to both to write to the defined flash area from the bootloader project and then read from it from the application project

    My only concern now is that the bootloader project will not compile in Debug configuration giving following error message

    error: section .tdata overlaps absolute placed section .reserved_flash_tail

    Best regards Marlene

  • I am not 100% certain, but I suggest you open the bootloader's flash_placement.xml file (right click the project name and select "Edit Section Placement"). Check if there are any hard coded flash addressess that needs to be updated there.

    Also, I am not sure whether you need to worry about the "Debug" build in your bootloader. I believe you would want to go with the "Release" version.

    BR,

    Edvin

Reply
  • I am not 100% certain, but I suggest you open the bootloader's flash_placement.xml file (right click the project name and select "Edit Section Placement"). Check if there are any hard coded flash addressess that needs to be updated there.

    Also, I am not sure whether you need to worry about the "Debug" build in your bootloader. I believe you would want to go with the "Release" version.

    BR,

    Edvin

Children
No Data
Related