Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nrf52832 custom simple bootloader implementation.

Hi everybody.
I know that it is complete standart question, which has many asks and solutions here.
I'm quite new to bootloader management stuff.
So asking about some targeting recommendations and solutions, some custom examples to start with.

My goal is to implement kind of bootloader (no need of heavy original one with DFU, encryption and a lot of extra bloating stuff)
I only need such functionality:
 - Have some kind of extra program (actually bootloader), starts from different memory address from original app.
 - Ability to boot to this program on some event from main app. and only thing to do is copy new FW from some flash area to main program area.
Inside of a boot program can implement simple progress of copying like LED blink stuff or so
 - After that restart app and boot to main app.

Encryption of FW doesn't needed. Let has it also on a point that FW on flash has already verified and only ready for copying to main program area.

Does it possible to make it based on some simple example, not using Softdevice and a lot of extra original bootloader implementation?
Even more, does this procedure described above actually possible at all?

King regards.
Ivan.
 

  • Here is my final code.

    //execute FW update 
    void execute_fw_update(uint8_t* fwData, uint32_t fwSize) { 
    update_fw_proc updater = (update_fw_proc) (RAM_START + 1);
    uint32_t src = (uint32_t)fw_copy_flash;
    
    memcpy((void*)RAM_START, (void *)(src & ~1), FW_FLASH_FUNC_SIZE); */
    __dsb(0xf);
    __isb(0xf);
    (updater)(FW_FLASH_START, fwData, fwSize);
    
    }
    
    //ram function code to update flash
    
    static void fw_copy_flash(uint32_t dest, uint8_t *src, uint32_t size)
    {
    int i;
    int pagesNum = FW_DATA_MAX_SIZE / NRF_FICR->CODEPAGESIZE;
    
    __disable_irq();
    
    //erase number of pages needed
    for (i = 0; i < pagesNum; i++) {
    // Enable erase.
    NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een;
    __ISB();
    __DSB();
    
    // Erase the page
    NRF_NVMC->ERASEPAGE = i * NRF_FICR->CODEPAGESIZE; 
    
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {;}
    
    NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
    __ISB();
    __DSB();
    }
    
    for (i = 0; i < size; i++)
    {
    uint32_t byte_shift = (dest + i) & (uint32_t)0x03;
    uint32_t address32 = (dest + i) & ~byte_shift; // Address to the word this byte is in.
    uint32_t value32 = (*(uint32_t*)address32 & ~((uint32_t)0xFF << (byte_shift << (uint32_t)3)));
    value32 = value32 + ((uint32_t)src[i] << (byte_shift << 3));
    
    // Enable write.
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);
    __ISB();
    __DSB();
    
    *(uint32_t*)address32 = value32;
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {;}
    
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
    __ISB();
    __DSB();
    }
    
    //reset board
    //NVIC_SystemReset();
    __DSB(); /* Ensure all outstanding memory accesses included
    buffered write are completed before reset */
    SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
    (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
    SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */
    __DSB(); /* Ensure completion of memory access */
    
    for(;;) /* wait until reset */
    {
    __NOP();
    }
    }

  • all seems without some flash functions.

    But still get device bricked after usiing it for 0x0 program flash rewrite.
    Flash write working proper way, cause I 've tested it on other region.

  • Hi,

    I didn't understood meaning of this: 

    uint32_t byte_shift = (dest + i) & (uint32_t)0x03;
    uint32_t address32 = (dest + i) & ~byte_shift; // Address to the word this byte is in.
    uint32_t value32 = (*(uint32_t*)address32 & ~((uint32_t)0xFF << (byte_shift << (uint32_t)3)));
    value32 = value32 + ((uint32_t)src[i] << (byte_shift << 3));

    The right way is to program flash word by word:

    *(uint32_t*)dest = value;
    dest += 4;


    You can look in debugger what's actually written at address 0.

  • I 've taken this from standart implementation.
    Flash copy body is ok, cause as I said I 've tested write to 0x5000.
    I get proper write and sw reset, and after reset I get same image to 0x0 at 0x5000.

  • I 've implemented flash program like on your example.
    But still bricked on 0x0 write.

Related