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

FS_ERR_UNALIGNED_ADDR with Buttonless DFU

Hi, I'm working on porting my application from SDK 11.0 to 12.2.0 and I have a problem initializing the buttonless DFU service. I've flashed the secure bootloader and appropriate settings. The bootloader itself is working correctly (I can upload a Nordic test image just fine).

If I add the BLE DFU service during services_init() the device resets. I've narrowed the fault down to this portion of the nrf_dfu_settings.c:

void nrf_dfu_settings_init(void)
{
    NRF_LOG_INFO("running nrf_dfu_settings_init\r\n");

    volatile uint32_t crc;

    flash_operation_pending = false;

    // Copy the DFU settings out of flash and into a buffer in RAM.
    memcpy((void*)&s_dfu_settings, &m_dfu_settings_buffer[0], sizeof(nrf_dfu_settings_t));

    if(s_dfu_settings.crc != 0xFFFFFFFF)
    {
        // CRC is set. Content must be valid
        crc = nrf_dfu_settings_calculate_crc();
        if(crc == s_dfu_settings.crc)
        {
            return;
        }
    }

    // Reached if nothing is configured or if CRC was wrong
    NRF_LOG_INFO("!!!!!!!!!!!!!!! Resetting bootloader settings !!!!!!!!!!!\r\n");
    memset(&s_dfu_settings, 0x00, sizeof(nrf_dfu_settings_t));
    s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION;
    APP_ERROR_CHECK(nrf_dfu_settings_write(NULL));
}


ret_code_t nrf_dfu_settings_write(dfu_flash_callback_t callback)
{
    ret_code_t err_code = FS_SUCCESS;
    NRF_LOG_INFO("Erasing old settings at: 0x%08x\r\n", (uint32_t)&m_dfu_settings_buffer[0]);

    // Wait for any ongoing operation (because of multiple calls to nrf_dfu_settings_write)
    wait_for_pending();
    
    flash_operation_pending = true;
    m_callback = callback;
    
    do 
    {
        wait_for_queue();
        
        // Not setting the callback function because ERASE is required before STORE
        // Only report completion on successful STORE.
        err_code = nrf_dfu_flash_erase((uint32_t*)&m_dfu_settings_buffer[0], 1, NULL);
        
    } while (err_code == FS_ERR_QUEUE_FULL);
    
    
    if (err_code != FS_SUCCESS)
    {
        NRF_LOG_ERROR("Erasing from flash memory failed.\r\n");
        flash_operation_pending = false;
        return NRF_ERROR_INTERNAL;
    }

    s_dfu_settings.crc = nrf_dfu_settings_calculate_crc();

    NRF_LOG_INFO("Writing 0x%08x words\r\n", sizeof(nrf_dfu_settings_t)/4);

    static nrf_dfu_settings_t temp_dfu_settings;
    memcpy(&temp_dfu_settings, &s_dfu_settings, sizeof(nrf_dfu_settings_t));

    do 
    {
        wait_for_queue();
        
        err_code = nrf_dfu_flash_store((uint32_t*)&m_dfu_settings_buffer[0],
                                       (uint32_t*)&temp_dfu_settings,
                                       sizeof(nrf_dfu_settings_t)/4,
                                       dfu_settings_write_callback);

    } while (err_code == FS_ERR_QUEUE_FULL);
    
    if (err_code != FS_SUCCESS)
    {
        NRF_LOG_ERROR("Storing to flash memory failed.\r\n");
        flash_operation_pending = false;
        return NRF_ERROR_INTERNAL;
    }

    NRF_LOG_INFO("Writing settings...\r\n");
    return NRF_SUCCESS;
}

The stored CRC is just 0, so it does not match the calculated one. Thus the application resets the bootloader settings. This alarms me since nrfutil reports a CRC when I generate the settings hex file.

But anyway, the value returned by this line:

err_code = nrf_dfu_flash_erase((uint32_t*)&m_dfu_settings_buffer[0], 1, NULL);

is FS_ERR_UNALIGNED_ADDR, and I'm not quite sure what's going on. The bootloader settings address is configured as 0x0007F000, which should be aligned with a a page boundary.

  • Hi Dingari,

    Could you explain a little bit more on your porting ? Do you plan to also DFU update the bootloader from SDK v11 to SDK v12 (from legacy bootloader to secure bootloader ? )

    "The stored CRC is just 0" Do you mean it's the initial CRC, if that what you meant then it's normal. If you already flashed the bootlaoder setting hex you generate, then the CRC when the bootloader start should be the same as the bootloader setting's CRC.

    Regarding the issue with nrf_dfu_flash_erase() could you step into the code and check if the destination p_page_addr actually address 0x0007F000?

    I would recommend to switch to DFU bootloader in SDK v13. In this latest version we don't write to flash but use retention RAM, which in my view, cleaner and simpler.

  • Hi Hung Bui, I'm moving from the legacy bootloader to the new secure bootloader.

    I've flashed the settings hex file so there seems to be something wrong if the CRC is zero. I'll double check this.

    I'll try stepping in and verifying the address.

    Is the SDK 13 stable now? I didn't want to use the alpha version.

  • Hmm. I've just now checked with the debugger. The address of m_dfu_settings_buffer is 0x20002cf4. What can be the cause of this?

  • SDK v13 released 2 days ago is in production grade.

    m_dfu_settings_buffer at 0x20002cf4 telling it's pointing to RAM, not Flash. It should point to Flash as how it's declared at nrf_dfu_settings.c using the "attribute" declare. Which compiler are you using ?

    You may want to test with the ble_app_buttonless_dfu example or switch to SDK v13.

  • Hi Hung Bui. I've figured out what was causing this. I'm using GCC as my compiler. I followed the experimental_ble_app_buttonless_dfu closely. The linker script provided with the example doesn't declare the .bootloaderSettings section so when the compiler reaches the part of nrf_dfu_settings.c where it allocates m_dfu_settings_buffer, it can't find the section. (I was also under the impression that the compiler was entering the #if defined (__CC_ARM ) section, but instead it enters #elif defined ( __GNUC__ )).

    Declaring the section in the application linker script, the application boots normally. This was also what was causing the CRC to be zero on boot.

Related