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

DFU_APP_DATA_RESERVED not working

nrf51822_AA rev3, SDK8.0.0, S110 8.0.0

My application has the max number of bonds set to 24 with a size of 128bytes each. So that's 3 pages. Plus one page for saving user/state information. So, I'd like to save a total of 4 pages when DFUing.

I set DFU_APP_DATA_RESERVED to 0x1000, but it has no effect.

I printf'ed a bunch of defines to try to figure out the problem, but I think everything looks right:

NRF_UICR_BOOT_START_ADDRESS = 0x10001014
CODE_REGION_1_START = 0x00018000
SOFTDEVICE_REGION_START = 0x00001000
BOOTLOADER_REGION_START = 0x0003C000
BOOTLOADER_SETTINGS_ADDRESS = 0x0003FC00
DFU_REGION_TOTAL_SIZE = 0x00024000
DFU_APP_DATA_RESERVED = 0x00001000
DFU_BANK_PADDING = 0x00000000
DFU_IMAGE_MAX_SIZE_FULL = 0x00023000
DFU_IMAGE_MAX_SIZE_BANKED = 0x00011800
DFU_BL_IMAGE_MAX_SIZE = 0x00003C00
DFU_BANK_0_REGION_START = 0x00018000
DFU_BANK_1_REGION_START = 0x00029800

PSTORAGE_DATA_START_ADDR = 0x0003AC00
PSTORAGE_DATA_END_ADDR = 0x0003BC00

I can read back the memory using "nrfjprog.exe --memrd 0x0003AC00 --n 4096" and I can see the bond and state information, but after DFUing it's all gone.

bootloader flash settings:
IROM1: 0x3C000 / 0x3C00
IRAM1: 0x20002000 / 0x1F80
IRAM2: 0x20003F80 / 0X80 (no init)

application flash settings:
IROM1: 0x18000 / 0x28000
IRAM1: 0x20002000 / 0x2000

Help...thanks!

  • @Chris: I assume the PSTORAGE_DATA_START_ADDR calculated to be 0x0003AC00 was the setting in your application. Note that the area from 0x3AC00 to the start address of the bootloader BOOTLOADER_REGION_START (0x3C000) is 0x1400 = 5 pages. There is 1 page extra because of the swap page. So if you simply set the DFU_APP_DATA_RESERVED = 0x1000. This may not be enough. And you first page will be erased when the bootloader erases DFU Bank 1.

    Could you try to set it to 0x1400 ?

  • @Hung: I actually tried 0x2000 the other day and 0x1400 just now and neither worked.

    My bootloader and application are separate Keil projects and so each has its own pstorage_platform.h. I believe this is correct, or should they be the same?

    Bootloader pstorage_platform.h:
    #define PSTORAGE_FLASH_PAGE_SIZE    ((uint16_t)NRF_FICR->CODEPAGESIZE)
    #define PSTORAGE_FLASH_EMPTY_MASK   0xFFFFFFFF
    #define PSTORAGE_FLASH_PAGE_END     NRF_FICR->CODESIZE
    #define PSTORAGE_MAX_APPLICATIONS   1
    #define PSTORAGE_MIN_BLOCK_SIZE     0x0010
    #define PSTORAGE_DATA_START_ADDR    ((PSTORAGE_FLASH_PAGE_END - PSTORAGE_MAX_APPLICATIONS) * PSTORAGE_FLASH_PAGE_SIZE)
    #define PSTORAGE_DATA_END_ADDR      (PSTORAGE_FLASH_PAGE_END * PSTORAGE_FLASH_PAGE_SIZE)
    #define PSTORAGE_SWAP_ADDR          PSTORAGE_DATA_END_ADDR
    #define PSTORAGE_MAX_BLOCK_SIZE     PSTORAGE_FLASH_PAGE_SIZE
    #define PSTORAGE_CMD_QUEUE_SIZE     10
    

    Application pstorage_platform.h:
    static __INLINE uint16_t pstorage_flash_page_size()
    {
      return (uint16_t)NRF_FICR->CODEPAGESIZE;
    }
    
    #define PSTORAGE_FLASH_PAGE_SIZE     pstorage_flash_page_size()
    #define PSTORAGE_FLASH_EMPTY_MASK    0xFFFFFFFF
    
    static __INLINE uint32_t pstorage_flash_page_end()
    {
       uint32_t bootloader_addr = NRF_UICR->BOOTLOADERADDR;
      
       return ((bootloader_addr != PSTORAGE_FLASH_EMPTY_MASK) ?
               (bootloader_addr/ PSTORAGE_FLASH_PAGE_SIZE) : NRF_FICR->CODESIZE);
    }
    
    #define PSTORAGE_FLASH_PAGE_END pstorage_flash_page_end()
    #define PSTORAGE_MAX_APPLICATIONS   2 //1 for device manager and 1 for application
    #define PSTORAGE_MIN_BLOCK_SIZE     0x0010
    #define PSTORAGE_PAGES_FOR_BONDS    2 //2 'extra' pages to store a total of 24 bonds. Each bond is set to 128 bytes.
    #define PSTORAGE_DATA_START_ADDR    ((PSTORAGE_FLASH_PAGE_END - PSTORAGE_MAX_APPLICATIONS - 1 - PSTORAGE_PAGES_FOR_BONDS) * PSTORAGE_FLASH_PAGE_SIZE)
    #define PSTORAGE_DATA_END_ADDR      ((PSTORAGE_FLASH_PAGE_END - 1) * PSTORAGE_FLASH_PAGE_SIZE)
    #define PSTORAGE_SWAP_ADDR          PSTORAGE_DATA_END_ADDR
    #define PSTORAGE_MAX_BLOCK_SIZE     PSTORAGE_FLASH_PAGE_SIZE
    #define PSTORAGE_CMD_QUEUE_SIZE     10
    

    Thanks for the help.

  • @Chris: Yes, they are separated project and pstorage_platform.h files doesn't have to be the same or related.

    Could you check: DFU_BANK_1_REGION_START and DFU_IMAGE_MAX_SIZE_BANKED after the modification ?

    The sum of them shouldn't exceed 0x3AC00.

    Last time they was 0x00029800 and 0x00011800 and the sum was 0x3B000.

    0x0029800->0x3B000 is the swap area, and will be erased when the bootloader starts.

    You can also add breakpoint in the bootloader and check when your bond information is erased. The process of erasing flash is explained in this presentation.

    Btw, next time please update your question instead of creating an answer if you want to add more information or update.

  • I figured it out. I was storing the user state in the reset_prepare function, but not waiting for it to finish. So, I guess the application data was corrupted before it even reset into the bootloader. Once I removed the storing, everything worked.

    The bonds were not being saved because I was short a page like you said.

    This should probably be a separate question: Since pstorage uses its own event handler, what is the best way to 'wait' for it to finish before continuing? I am not using a scheduler.

  • @Chris: You should register a callback handler when calling pstorage_register() and wait for the callback even (with PSTORAGE_STORE_OP_CODE for example) and check the result. You can set a flag in the callback handler and wait for that flag in the main code be for proceed.

Related