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

DFU Bootloader without NRF_LOG/UART

Greetings,

I'm having some trouble using the secure DFU bootloader and buttonless DFU service in my application. The code for both of these has been taken from their respective examples in the 13.0.0 SDK. Our application code has been implemented and tested using the example DFU bootloader; a bootloader settings page is generated from the application binary and CRC completes successfully, correctly beginning execution from the application start address, only entering DFU bootloader execution after the control point in the buttonless DFU service is written to.

However, our application is running on a custom board, for which we wish to disable the UART module so that the GPIO pins can be used for another purpose. I have thus modified the sdk_config.h for the bootloader to disable UART, NRF_LOG, NRF_STRERROR, etc. and masked the board support led and button functions from the bootloader code through a #define, separating the bootloader into debug and release versions.

I have repeated the process of generating a settings page and merging it with the new bootloader binary after compiling the release version, but when I flash the application, the board remains stuck in DFU bootloader mode, seemingly unable to verify that a valid application is present.

The differences between the debug and release bootloader are currently so small that I can't come up with an explanation for this behaviour. Also, as the error only occurs in the absence of nrf_log, and the bootloader is optimised by default to be quite breakpoint-unfriendly, this is incredibly difficult to debug.

Any advice would be appreciated.

  • On further experimentation, it seems to actually be the call to buttons_init(); causing the issue - if I leave it in, the bootloader behaves perfectly, if I comment it out, the application code doesn't get executed. Any ideas?

  • Well, the only thing the buttons_init function does is to configure the BOOTLOADER_BUTTON pin, i.e. pin 16 on the nRF52 as an input. Are you using pin 16 on you custom board to anything else?

    static void buttons_init(void)
    {
        nrf_gpio_cfg_sense_input(BOOTLOADER_BUTTON,
                                 BUTTON_PULL,
                                 NRF_GPIO_PIN_SENSE_LOW);
    }
    
  • Found the solution. The problem was the first condition in nrf_dfu_enter_check() inside nrf_dfu.c, which would always return true in our case - either because the pin was uninitialised or because it was being driven low.

    __WEAK bool nrf_dfu_enter_check(void)
    {
    // Condition should only be tested when BSP buttons are initialised (i.e. on Dev Kit)
        if (nrf_gpio_pin_read(BOOTLOADER_BUTTON) == 0)
        {
            return true;
        }
        if(NRF_POWER->GPREGRET == BOOTLOADER_DFU_START)
        {
            return true;
        }
    
        if (s_dfu_settings.enter_buttonless_dfu == 1)
        {
            s_dfu_settings.enter_buttonless_dfu = 0;
    
            uint32_t err_code = nrf_dfu_settings_write(NULL);
            //NRF_LOG_INFO("DFU error: %s \r\n",(uint32_t)(nrf_strerror_get (err_code)));
            APP_ERROR_CHECK(err_code);
            return true;
        }
        return false;
    }
    

    As a side question - what is the best way to override defintions of functions which are defined as __WEAK? I want to redefine nrf_dfu_enter_check() (i.e. remove the first test condition), but obviously editing files in the SDK is not a portable fix.

  • Just create a .c file, e.g. custom_functions.c, and define the nrf_dfu_enter_check() in that file, without the __weak attribute of course. Then you just have add the source file to SRC_FILES in the Makefile (based on the tags of the question I am assuming that you're using gcc and Makefiles) and run make. The linker will then override the weak implementation of nrf_dfu_enter_check and you do not have to alter the SDK files.

Related