Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Buttonless DFU works on dev kits but not on custom board

Hello,

I’m using the secure bootloader for serial DFU (UART, not USB). To enter bootloader mode from the application, I write 0xB1 to GPREGRET, then call NVIC_SystemReset(). On the dev boards I have (PCA10056 and Particle Boron), this works to reboot into DFU mode. However, on my custom board, it doesn’t work. The device appears to boot immediately into the application code.

I have made a custom board file that looks like this

#define LEDS_NUMBER    2

#define LED_1          NRF_GPIO_PIN_MAP(0,15)
#define LED_2          NRF_GPIO_PIN_MAP(0,18)
#define LED_START      LED_1
#define LED_STOP       LED_2

#define LEDS_ACTIVE_STATE 1

#define LEDS_LIST { LED_1, LED_2 }

#define LEDS_INV_MASK  LEDS_MASK

#define BSP_LED_0      NRF_GPIO_PIN_MAP(0,15)
#define BSP_LED_1      NRF_GPIO_PIN_MAP(0,18)

#define BUTTONS_NUMBER 0

#define RX_PIN_NUMBER  NRF_GPIO_PIN_MAP(0,23)
#define TX_PIN_NUMBER  NRF_GPIO_PIN_MAP(0,24)
#define CTS_PIN_NUMBER NRF_GPIO_PIN_MAP(0,30)
#define RTS_PIN_NUMBER NRF_GPIO_PIN_MAP(0,31) 
#define HWFC           false

I’ve already read some advice including checking the LF crystal, and checking the UART pins. These don’t appear to be causing my problem, so I’m not really sure what to try next. I am open to debugging the bootloader, but I’m not sure how that will help since the device just enters the application code. Any guidance would be greatly appreciated

Thank you,

Carlos

  • Hi Carlos

    It could be that the bootloader start address is not added correctly to the UICR, which the bootloader will not run without. 

    In order to check this, could you run the following command when you have a debugger connected to your board, and let me know what you get in return?

    nrfjprog --memrd 0x10001014

    Best regards
    Torbjørn

  • Unfortunately I can't use a JLink device with this board. I would have to make a special breakout adapter for that. I flash/debug through an FT2232H with OpenOCD and GDB.

    When I read the contents of that register with GDB the result is:

    (gdb) p/x *0x10001014
    $3 = 0xf8000

    That matches the start address from secure_bootloader_gcc_nrf52.ld:

    MEMORY
    {
      FLASH (rx) : ORIGIN = 0xf8000, LENGTH = 0x6000
      RAM (rwx) :  ORIGIN = 0x20000008, LENGTH = 0x3fff8
      uicr_bootloader_start_address (r) : ORIGIN = 0x10001014, LENGTH = 0x4
      bootloader_settings_page (r) : ORIGIN = 0x000FF000, LENGTH = 0x1000
      uicr_mbr_params_page (r) : ORIGIN = 0x10001018, LENGTH = 0x4
      mbr_params_page (r) : ORIGIN = 0x000FE000, LENGTH = 0x1000
    }

    Here is the memory layout from the linker script I use for the application code:

    MEMORY
    {
      FLASH (rx) : ORIGIN = 0x1000, LENGTH = 0xff000
      RAM (rwx) :  ORIGIN = 0x20000008, LENGTH = 0x3fff8
    }

  • Hello,

    Torbjørn asked me to follow up on this.

    Thanks for confirming the that the bootloader start address was set correctly. The MBR knows a bootloader is present when this register is set, see Master boot record and SoftDevice reset procedure for details. So this means the bootloader should executing  before the application on startup. The problem might be that it fails to enter DFU mode for some reason.

    Could you try to start a GDB session with the bootloader project and see if it reaches main()?

    Edit: you may also want to place breakpoints in the fault handlers in main.c to catch any code assertions.

  • Sure, I have a question about this though. I read on a different thread that I would have to turn off optimization for the bootloader, and this would make it too big to fit in flash at the address designated by the linker script. What address should I place the bootloader at for this to work with optimization set to 0?

    Also, for the breakpoints do you recommend using NRF_BREAKPOINT?

  • It’s not a requirement to turn off optimization for more simple debugging like this, so I’d suggest to leave it as is for now. 

    For breakpoints I would recommend to use the breakpoint command in GDB. E.g. breakpoint main.c:<insert line number> Or breakpoint main to break on main(). Using the NRF_BREAKPOINT macro is also an option, but note that it will halt the CPU even when you are not debugging.

Related