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

debug bootloader for thread examples

Hi,

I wonder if there exists a debug bootloader for thread examples. There is a bootloader in the secure DFU example, but it is not for debugging. "examples/thread/dfu/bootloader" . I appreciate if you can point me to the right direction.

Best regards,

Ozan

  • Hello,

    I am sorry. At this point in time there are no Thread Bootloader examples. I don't know whether you want to debug the bootloader or the actual application, but you may be able to disable the CRC check in the bootloader project if you want to debug the application. I have not tried this in the Thread Bootloader, so I wouldn't know exactly how to do it, but please specify what you are looking for, and we can see if we can find a usable approach.

    Best regards,

    Edvin

  • Hi Edvin,

    Thanks for the reply! I want to debug the actual application. I'm adding DFU feature to my application and using the following example as basis

    https://www.nordicsemi.com/DocLib/Content/SDK_Doc/Thread_SDK/v2-0-0/thread_example_dfu

    At that point, I can't debug my app because of the bootloader. As I understand I need to recompile the bootloader in the example above with no-CRC check. Right? Can you tell me how to do that please?

    Best wishes

  • Hello,

    I have not tested,  but yes, that is the correct approach.

    If you don't need to debug anything in the bootloader, you may try to just comment out the two lines in main() of the bootloader's main.c file:

    ret_val = nrf_bootloader_init(dfu_observer);
    APP_ERROR_CHECK(ret_val);

    As I mentioned, I haven't tested it, but it may be a bit more complex than that, but as long as the bootloader is flashed, it should run into nrf_bootloader_app_start() if there is nothing wrong with the app (which is checked inside nrf_bootloader_init().

    Alternatively, if this doesn't work, look at nrf_bootloader_init() in nrf_bootloader.c:

    In the switch (activation result), just make sure that dfu_enter is set to false before if (dfu_enter). If this is false, it will run the application. I believe that this should work.

    Best regards,

    Edvin

  • Thank you,  Edvin. I will let you know when I apply & test your suggestions. 

    Best wishes

  • Hi Edvin,

    I made some tests, but no success with bootloader in debug mode. Anyways, I continue to work on DFU. The thing is that DFU update library gives fatal error and resets the device. I appreciate if you can check the following log:

    <info> COAP_DFU: DFU trigger request received
    <info> background_dfu: DFU trigger: init (sz=140, crc=3CE37F4) image (sz=357152, crc=76D6FA45)
    <info> background_dfu: state=DFU_DOWNLOAD_TRIG event=DFU_EVENT_TRANSFER_COMPLETE
    <warning> background_dfu: Installed image CRC is different
    <error> nrf_dfu_validation: Failed to decode init packet
    <error> background_dfu: Init commad has changed
    <info> background_dfu: Init complete. Multicast Mode.
    <info> background_dfu: state=DFU_DOWNLOAD_INIT_CMD event=DFU_EVENT_TRANSFER_CONTINUE
    <info> COAP_DFU: DFU trigger request received
    <error> background_dfu: Validate trigger: DFU already in progress (s:DFU_DOWNLOAD_INIT_CMD).
    <info> COAP_DFU: DFU trigger request received
    <error> background_dfu: Validate trigger: DFU already in progress (s:DFU_DOWNLOAD_INIT_CMD).
    <info> background_dfu: Storing block (b:0 c:0).
    <info> background_dfu: state=DFU_DOWNLOAD_INIT_CMD event=DFU_EVENT_TRANSFER_CONTINUE
    <info> background_dfu: Storing block (b:1 c:1).
    <info> background_dfu: state=DFU_DOWNLOAD_INIT_CMD event=DFU_EVENT_TRANSFER_CONTINUE
    <info> background_dfu: Storing block (b:2 c:2).
    <info> nrf_dfu_validation: Signature required. Checking signature.
    <info> nrf_dfu_validation: Calculating init packet hash (init packet len: 63)
    <info> nrf_dfu_validation: Verify signature
    <info> nrf_dfu_validation: Image verified
    <info> background_dfu: state=DFU_DOWNLOAD_INIT_CMD event=DFU_EVENT_TRANSFER_COMPLETE
    <info> background_dfu: state=DFU_DOWNLOAD_FIRMWARE event=DFU_EVENT_TRANSFER_CONTINUE
    <info> background_dfu: Storing block (b:0 c:0).
    
    <info> app: Thread version: OPENTHREAD/20180926-00368-gf01e3f34; NRF52840; Feb 28 2019 11:11:40
    <info> COAP_DFU: Endpoints initialized
    <info> background_dfu: Current DFU Diag version: Mar 18 2019 16:39:48, 0x99E68F38
    <warning> COAP_DFU: Image data received in invalid state: (m:0 s:5).
    <warning> COAP_DFU: Image data received in invalid state: (m:0 s:5).
    <warning> COAP_DFU: Image data received in invalid state: (m:0 s:5).
    <warning> COAP_DFU: Image data received in invalid state: (m:0 s:5).
    <warning> COAP_DFU: Image data received in invalid state: (m:0 s:5).
    <warning> COAP_DFU: Image data received in invalid state: (m:0 s:5).
    <warning> COAP_DFU: Image data received in invalid state: (m:0 s:5).
    <warning> COAP_DFU: Image data received in invalid state: (m:0 s:5).
    <warning> COAP_DFU: Image data received in invalid state: (m:0 s:5).
    

    I followed the steps in the thread dfu example

    #initial client
    nrfutil settings generate --family NRF52840 --application tnode.hex --application-version 1 --bootloader-version 1 --bl-settings-version 1 settings.hex
    mergehex -m tnode.hex settings.hex -o dfu_client.hex
    
    nrfjprog -f nrf52 -r --program dfu_data/mbr.hex --snr 683612867 --chiperase
    nrfjprog -f nrf52 -r --program dfu_data/bootloader.hex --snr 683612867 --sectoranduicrerase
    nrfjprog -f nrf52 -r --program ./dfu_client.hex --snr 683612867 --sectorerase
    
    #new firmware
    nrfutil pkg generate --hw-version 52 --sd-req 0x00 --application-version 2 --application tnode.hex --key-file dfu_data/priv.pem app_dfu_package_2.zip
    nrfutil --output /dev/stdout dfu thread -pkg app_dfu_package_2.zip -p /dev/ttyACM1 -r 10 -rs 5000 -a FF03::1 -sp 5685
    

    Related parts of the project file:

    c_preprocessor_definitions="BOARD_PCA10056;CONFIG_GPIO_AS_PINRESET;FLOAT_ABI_HARD;FREERTOS;INITIALIZE_USER_SECTIONS;NO_VTOR_CONFIG;NRF52840_XXAA;NRF_DFU_NO_TRANSPORT;NRF_DFU_SETTINGS_VERSION=1;OPENTHREAD_ENABLE_APPLICATION_COAP;SVC_INTERFACE_CALL_AS_NORMAL_FUNCTION;SWI_DISABLE0;uECC_ENABLE_VLI_API=0;uECC_OPTIMIZATION_LEVEL=3;uECC_SQUARE_FUNC=0;uECC_SUPPORT_COMPRESSED_POINT=0;uECC_VLI_NATIVE_LITTLE_ENDIAN=1;"
    
      <configuration
        Name="Release"
        linker_section_placement_file="flash_placement-release.xml"
        linker_section_placement_macros="FLASH_PH_START=0x0;FLASH_PH_SIZE=0x100000;RAM_PH_START=0x20000000;RAM_PH_SIZE=0x40000;FLASH_START=0x1000;FLASH_SIZE=0xfb000;RAM_START=0x20000008;RAM_SIZE=0x3fff8"
        linker_section_placements_segments="FLASH RX 0x0 0x100000;RAM RWX 0x20000000 0x40000;ot_flash_data RX 0x000f4000 0x4000;uicr_bootloader_start_address RX 0x10001014 0x4;bootloader_settings_page RX 0x000FF000 0x1000;uicr_mbr_params_page RX 0x10001018 0x4;mbr_params_page RX 0x000FE000 0x1000"
        c_preprocessor_definitions="NDEBUG"
        gcc_optimization_level="Optimize For Size" />

    And flash placement file (not the same with the example since I added different components in to the project, but merged):

    <!DOCTYPE Linker_Placement_File>
    <Root name="Flash Section Placement">
      <MemorySegment name="FLASH" start="$(FLASH_PH_START)" size="$(FLASH_PH_SIZE)">
        <ProgramSection load="no" name=".reserved_flash" start="$(FLASH_PH_START)" size="$(FLASH_START)-$(FLASH_PH_START)" />
        <ProgramSection alignment="0x100" load="Yes" name=".vectors" start="$(FLASH_START)" />
        <ProgramSection alignment="4" load="Yes" name=".init" />
        <ProgramSection alignment="4" load="Yes" name=".init_rodata" />
        <ProgramSection alignment="4" load="Yes" name=".text" />
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".crypto_data" inputsections="*(SORT(.crypto_data*))" address_symbol="__start_crypto_data" end_symbol="__stop_crypto_data" />
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".nrf_queue" inputsections="*(.nrf_queue*)" address_symbol="__start_nrf_queue" end_symbol="__stop_nrf_queue" />
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".log_const_data" inputsections="*(SORT(.log_const_data*))" address_symbol="__start_log_const_data" end_symbol="__stop_log_const_data" />
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".log_backends" inputsections="*(SORT(.log_backends*))" address_symbol="__start_log_backends" end_symbol="__stop_log_backends" />
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".nrf_balloc" inputsections="*(.nrf_balloc*)" address_symbol="__start_nrf_balloc" end_symbol="__stop_nrf_balloc" />
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".dfu_trans" inputsections="*(SORT(.dfu_trans*))" address_symbol="__start_dfu_trans" end_symbol="__stop_dfu_trans" />
        <ProgramSection alignment="4" keep="Yes" load="No" name=".nrf_sections" address_symbol="__start_nrf_sections" />
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".fs_data"  inputsections="*(.fs_data*)" runin=".fs_data_run"/>
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".log_dynamic_data"  inputsections="*(SORT(.log_dynamic_data*))" runin=".log_dynamic_data_run"/>
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".log_filter_data"  inputsections="*(SORT(.log_filter_data*))" runin=".log_filter_data_run"/>
        <ProgramSection alignment="4" load="Yes" name=".dtors" />
        <ProgramSection alignment="4" load="Yes" name=".ctors" />
        <ProgramSection alignment="4" load="Yes" name=".rodata" />
        <ProgramSection alignment="4" load="Yes" name=".ARM.exidx" address_symbol="__exidx_start" end_symbol="__exidx_end" />
        <ProgramSection alignment="4" load="Yes" runin=".fast_run" name=".fast" />
        <ProgramSection alignment="4" load="Yes" runin=".data_run" name=".data" />
        <ProgramSection alignment="4" load="Yes" runin=".tdata_run" name=".tdata" />
        <ProgramSection alignment="4" load="No"  name=".mev_data" start="0xf3000" size="0x1000" />
      </MemorySegment>
      <MemorySegment name="RAM" start="$(RAM_PH_START)" size="$(RAM_PH_SIZE)">
        <ProgramSection load="no" name=".reserved_ram" start="$(RAM_PH_START)" size="$(RAM_START)-$(RAM_PH_START)" />
        <ProgramSection alignment="0x100" load="No" name=".vectors_ram" start="$(RAM_START)" address_symbol="__app_ram_start__"/>
        <ProgramSection alignment="4" keep="Yes" load="No" name=".nrf_sections_run" address_symbol="__start_nrf_sections_run" />
        <ProgramSection alignment="4" keep="Yes" load="No" name=".fs_data_run" address_symbol="__start_fs_data" end_symbol="__stop_fs_data" />
        <ProgramSection alignment="4" keep="Yes" load="No" name=".log_dynamic_data_run" address_symbol="__start_log_dynamic_data" end_symbol="__stop_log_dynamic_data" />
        <ProgramSection alignment="4" keep="Yes" load="No" name=".log_filter_data_run" address_symbol="__start_log_filter_data" end_symbol="__stop_log_filter_data" />
        <ProgramSection alignment="4" keep="Yes" load="No" name=".nrf_sections_run_end" address_symbol="__end_nrf_sections_run" />
        <ProgramSection alignment="4" load="No" name=".fast_run" />
        <ProgramSection alignment="4" load="No" name=".data_run" />
        <ProgramSection alignment="4" load="No" name=".tdata_run" />
        <ProgramSection alignment="4" load="No" name=".bss" />
        <ProgramSection alignment="4" load="No" name=".tbss" />
        <ProgramSection alignment="4" load="No" name=".non_init" />
        <ProgramSection alignment="4" size="__HEAPSIZE__" load="No" name=".heap" />
        <ProgramSection alignment="8" size="__STACKSIZE__" load="No" place_from_segment_end="Yes" name=".stack"  address_symbol="__StackLimit" end_symbol="__StackTop"/>
        <ProgramSection alignment="8" size="__STACKSIZE_PROCESS__" load="No" name=".stack_process" />
      </MemorySegment>
      <MemorySegment name="ot_flash_data" start="0x000f4000" size="0x4000">
        <ProgramSection alignment="4" keep="Yes" load="No" name=".ot_flash_data" address_symbol="__start_ot_flash_data" end_symbol="__stop_ot_flash_data" start = "0x000f4000" size="0x4000" />
      </MemorySegment>
      <MemorySegment name="bootloader_settings_page" start="0x000FF000" size="0x1000">
        <ProgramSection alignment="4" keep="Yes" load="No" name=".bootloader_settings_page" address_symbol="__start_bootloader_settings_page" end_symbol="__stop_bootloader_settings_page" start = "0x000FF000" size="0x1000" />
      </MemorySegment>
      <MemorySegment name="mbr_params_page" start="0x000FE000" size="0x1000">
        <ProgramSection alignment="4" keep="Yes" load="No" name=".mbr_params_page" address_symbol="__start_mbr_params_page" end_symbol="__stop_mbr_params_page" start = "0x000FE000" size="0x1000" />
      </MemorySegment>
      <MemorySegment name="uicr_bootloader_start_address" start="0x10001014" size="0x4">
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".uicr_bootloader_start_address" address_symbol="__start_uicr_bootloader_start_address" end_symbol="__stop_uicr_bootloader_start_address" start = "0x10001014" size="0x4" />
      </MemorySegment>
      <MemorySegment name="uicr_mbr_params_page" start="0x10001018" size="0x4">
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".uicr_mbr_params_page" address_symbol="__start_uicr_mbr_params_page" end_symbol="__stop_uicr_mbr_params_page" start = "0x10001018" size="0x4" />
      </MemorySegment>
    </Root>

    And the code where DFU monitored and processed:

    static void thread_stack_task(void * arg)
    {
        UNUSED_PARAMETER(arg);
    
        uint32_t now, before = otPlatAlarmMilliGetNow();
    
        while (1)
        {
    #ifdef NDEBUG
            coap_dfu_process();
            thread_process();
    
            now = otPlatAlarmMilliGetNow();
            if (now - before > 1000)
            {
                coap_time_tick();
                before = now;
            }
    
            if (m_app.trigger_dfu)
            {
                m_app.trigger_dfu = false;
                coap_dfu_trigger(NULL);
            }
    #else
            thread_process();
    #endif
    
            UNUSED_VARIABLE(ulTaskNotifyTake(pdTRUE, portMAX_DELAY));
        }
    }
    

    Any help is highly appreciated! I think I am doing wrong with the flash placement, but I just merged the example with my current version of placement file.

    I know that this info may not be enough to pinpoint the problem, but if you can give me some clues/checkpoints then I can continue. 

    Best regards,

    Vedat

Related