nRF52840 DK board developed off Hardware files v3.0.3 would like to get the on-board SEGGER J-Link debugger flashed on the board

Hi,

We had a nRF52840 DK board developed off Hardware files v3.0.3 build.  The manufacturer didn't have any of the MCU or SEGGER J-Link debugger files on the device.  We are using SDK 3.0.2.

The board built is exactly like the nRF52840. 

What has been tried

  • Is the j-link-ob-sam3u128-v2-nordicsemi-170724.bin the file to put on the board.
    • Tried to do the hold reset and turn on the board power , hold reset and over usb a storage device will show up and the above .bin needed to be moved to the storage devicer and the MCU would program.   The LED only blinked and turned off and the storage device didn't show up.
      docs.nordicsemi.com/.../if_mcu.html
  • Connected the nordic nRF52840 DK Debug out (10 pin) to the nRF52840 DK build board Debug in.  The board didn't show up . (had previously done with a Fanstel and it worked)

So which steps need to be done to get the MCU / SEGGER J-Link debugger flashed / programmed onto the nRF52840 board .  Do we need to purchase a J-Link SEGGER programmer? 

  • If so which model of J-Link SEGGER programmer ?
  • How would the J-Link SEGGER be connected to the board?

Can the nRF52840 DK (nordic) be used to Flash the MCU / SEGGER J-Link debugger onto the nRF52840 DK (build) ?

Would prefer the simplest and reproducible method as will need to use in production.

The basic question is have build an nRF53840 board and need to get the MCU and the SEGGER J-Link debugger on the boards.

Input appreciated

Parents
  • The SEGGER OBD code is not available for external use. If you want access to this then you will need to buy the SW and license from SEGGER. 

    All the Nordic DKs are sold as development kits and also certified as this.Development kits have different rules than end products so if you plan to include it in an end product then you will need to certify it yourself.

    All of the restrictions on use of the Nordic DKs are in licensing agreements. 

    Second option for you is as Turbo J said, use an open source alternative instead. No guarantees that this will work with Nordic SW tools as these are built around SEGGER JLINK support.

  • There looks to be issues  with our approach (please correct me if I am wrong)

    1.  Need to buy the SW and license from SEGGER

    2. Need to have ability to licence and flash Nordic fw so as to be able to load the SEGGER SW

    3. Need to license the hardware design from Nordic

    4. Need to license the Nordic Firmware (which Nordic does not provide the firmware).

    Also is there a link to the Nordic DKs licensing agreements?

  • Hi there,

    So, WHy would you want to use the DK that way? What's the END goal here?
    I recall a while back , Someone was shipping the Sniffer setup on the Dongle as part of their end product.

    I don't recall reading anything about Licensing needed if doing it that way. I'm pretty sure they made up a UF2 file to drag and drop onto the dongle prior to shipping it. Which makes it a dedicated device?

    HTH

    GL :-) PJ :v:

  • Nod,  we are looking into options.  We could have a dongle be a dedicated sniffer. 

    We were looking into seeing if the DK board could be a sniffer or be re-flashed to do advertisements. 

    Also, we have some software running on the DK board what we would like to have field up-gradable (thus reflash) , basically bug fixes and feature updates. 

    With the dongle from my understanding you need to hit the reset button to force an upgrade (I have not done the dongle update, only have done updates with the DK boards). Unless there is a way to update.

  • Remember that someone doing something doesn't mean it is legally allowed....

    The nRF5840 DONGLE can be updated without using the button. There is a specific USB service in the nRF5 SDK named something along "DFU Trigger". This sets up an additional USB endpoint that if accessed in the correct way will trigger the DFU action. This is used by nRF Connect or Desktop to trigger DFU when you use Nordic code in the Dongle. You can add this to your own code if you want to. Not sure if this code is present in nRF Connect SDK but you can check if this seems like a solution for you.

  • Thank-you , The nRF52840 DFU Trigger would solve many of our issues if it will allow for re-flashing the dongle.  


    I grepped the sdk-nrf code and see /tests/subsys/dfu/...and /samples/dfu/duf_target ... is this along the right track?

    also found this 

    https://docs.contiki-ng.org/en/develop/_api/usb-dfu-trigger_8c.html#details

  • Based on the device support it looks like not it.

    Basically the nRF5 SDK solution adds a USB end point (so will only work with USB capable devices) and accessing this will trigger a reboot which will stay in DFU mode. This is done by pulling the GPIO pin on the nRF52840 connected to the RESET pin low.

    If you embedd code in your project that pulls this pin low then you will always go to DFU mode so you can achieve this in whatever way you want.

Reply
  • Based on the device support it looks like not it.

    Basically the nRF5 SDK solution adds a USB end point (so will only work with USB capable devices) and accessing this will trigger a reboot which will stay in DFU mode. This is done by pulling the GPIO pin on the nRF52840 connected to the RESET pin low.

    If you embedd code in your project that pulls this pin low then you will always go to DFU mode so you can achieve this in whatever way you want.

Children
  • If the sniffer is programmed on the nRF52840 is there a way to access the GPIO?  Or would the reset need to be pushed to enter the programming mode?  I see a path forward for the advertisement updates,  yet not a method of programming the sniffer then moving towards the advertizement code and back?

  • The GPIO feature must be built into the program. I don't know if the sniffer SW includes it but to test you program the sniffer code and then try to use the Dongle with the nRF Connect for Desktop programmer or RSSI apps. If it has the DFU trigger library then you can program the board without using the reset button. If you need to use the reset button then it doesn't.

    For code you build yourself then you will need to add the feature to the code.

  • Thank-you PaKa,


    Completed an example of how to use the GPIO pin to put the nRF52840 Dongle into DFU mode.

    (to bad cannot change the title as it eventually became how to program the nRF52840 dongle).

    Used the following command to convert the hex to zip
    nrfutil pkg generate --hw-version 52 --sd-req=0x00 --application zephyr.hex --application-version 1 app.zip

    This command to flash
    nrfutil device program --firmware app.zip --traits nordicDfu

    src/main.c

    /*
     * USB Serial with argc/argv style command parsing
     */
    #include <zephyr/kernel.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/usb/usb_device.h>
    #include <zephyr/drivers/uart.h>
    #include <zephyr/drivers/gpio.h>
    #include <string.h>
    
    BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart),
                 "Console device is not ACM CDC UART device");
    
    const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
    
    #define DFU_PIN 19
    #define LED_RED   8
    #define LED_GREEN 6
    #define LED_BLUE  12
    
    #define MAX_CMD_LEN 64
    #define MAX_ARGS    8
    
    static char cmd_buffer[MAX_CMD_LEN];
    static char *argv[MAX_ARGS];
    static int argc = 0;
    static uint8_t cmd_idx = 0;          // ← Fixed: was missing
    
    static bool blink_red = false, blink_green = false, blink_blue = false;
    static uint32_t blink_counter = 0;
    static uint32_t blink_interval = 25;        // medium
    
    const struct device *gpio0 = DEVICE_DT_GET(DT_NODELABEL(gpio0));
    
    void set_led(int pin, bool on)
    {
        gpio_pin_configure(gpio0, pin, GPIO_OUTPUT);
        gpio_pin_set(gpio0, pin, !on);
    }
    
    static void parse_command(void)
    {
        char *saveptr;
        char *token;
        argc = 0;
    
        token = strtok_r(cmd_buffer, " \t\r\n", &saveptr);
        while (token && argc < MAX_ARGS) {
            argv[argc++] = token;
            token = strtok_r(NULL, " \t\r\n", &saveptr);
        }
    }
    
    void enter_dfu_mode(void)
    {
        printk("\r\n\r\n>>> Entering DFU Bootloader mode <<<\r\n");
        gpio_pin_configure(gpio0, DFU_PIN, GPIO_OUTPUT);
        gpio_pin_set(gpio0, DFU_PIN, 0);
        k_sleep(K_MSEC(500));
        NVIC_SystemReset();
    }
    
    void normal_reset(void)
    {
        printk("\r\n\r\n>>> Normal Reset <<<\r\n");
        k_sleep(K_MSEC(100));
        NVIC_SystemReset();
    }
    
    void update_blinking(void)
    {
        blink_counter++;
        if (blink_counter % blink_interval == 0) {
            bool state = (blink_counter / blink_interval) % 2;
            if (blink_red)   set_led(LED_RED, state);
            if (blink_green) set_led(LED_GREEN, state);
            if (blink_blue)  set_led(LED_BLUE, state);
        }
    }
    
    int main(void)
    {
        uint32_t dtr = 0;
    
        if (usb_enable(NULL)) return 0;
    
        while (!dtr) {
            uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr);
            k_sleep(K_MSEC(100));
        }
    
        gpio_pin_configure(gpio0, DFU_PIN, GPIO_OUTPUT);
        gpio_pin_set(gpio0, DFU_PIN, 1);
        set_led(LED_RED, false);
        set_led(LED_GREEN, false);
        set_led(LED_BLUE, false);
    
        printk("\r\n=== nRF52840 Dongle Ready ===\r\n");
        printk("argc/argv style command parsing enabled\r\n");
        printk("Examples:\r\n");
        printk("  led red on\r\n");
        printk("  led all blink\r\n");
        printk("  led speed fast\r\n");
        printk("  dfu | reset\r\n> ");
    
        while (1) {
            uint8_t ch;
    
            update_blinking();
    
            if (uart_poll_in(dev, &ch) == 0) {
                printk("%c", ch);
    
                if (ch == '\r' || ch == '\n') {
                    cmd_buffer[cmd_idx] = '\0';
    
                    if (cmd_idx > 0) {
                        parse_command();
    
                        if (argc > 0) {
                            if (strcmp(argv[0], "dfu") == 0) {
                                enter_dfu_mode();
                            }
                            else if (strcmp(argv[0], "reset") == 0) {
                                normal_reset();
                            }
                            else if (strcmp(argv[0], "led") == 0 && argc >= 2) {
                                if (strcmp(argv[1], "red") == 0 && argc >= 3) {
                                    if (strcmp(argv[2], "on") == 0)      { blink_red = false; set_led(LED_RED, true); }
                                    else if (strcmp(argv[2], "off") == 0) { blink_red = false; set_led(LED_RED, false); }
                                    else if (strcmp(argv[2], "blink") == 0) blink_red = true;
                                }
                                else if (strcmp(argv[1], "all") == 0 && argc >= 3) {
                                    if (strcmp(argv[2], "on") == 0) {
                                        blink_red = blink_green = blink_blue = false;
                                        set_led(LED_RED, true); set_led(LED_GREEN, true); set_led(LED_BLUE, true);
                                    }
                                    else if (strcmp(argv[2], "off") == 0) {
                                        blink_red = blink_green = blink_blue = false;
                                        set_led(LED_RED, false); set_led(LED_GREEN, false); set_led(LED_BLUE, false);
                                    }
                                    else if (strcmp(argv[2], "blink") == 0) {
                                        blink_red = blink_green = blink_blue = true;
                                    }
                                }
                                else if (strcmp(argv[1], "speed") == 0 && argc >= 3) {
                                    if (strcmp(argv[2], "fast") == 0)   blink_interval = 8;
                                    else if (strcmp(argv[2], "medium") == 0) blink_interval = 25;
                                    else if (strcmp(argv[2], "slow") == 0)   blink_interval = 60;
                                }
                            }
                        }
                    }
    
                    cmd_idx = 0;
                    printk("\r\n> ");
                }
                else if (cmd_idx < MAX_CMD_LEN - 1) {
                    cmd_buffer[cmd_idx++] = (char)ch;
                }
            }
    
            k_sleep(K_MSEC(10));
        }
    }

    app.overlay 

    	};
    

    prj.conf

    CONFIG_USB_DEVICE_STACK=y
    CONFIG_USB_DEVICE_PRODUCT="nRF52840 Dongle"
    CONFIG_USB_DEVICE_PID=0x0004
    CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n
    
    CONFIG_SERIAL=y
    CONFIG_CONSOLE=y
    CONFIG_UART_CONSOLE=y
    CONFIG_UART_LINE_CTRL=y
    CONFIG_UART_INTERRUPT_DRIVEN=y
    CONFIG_GPIO=y

Related