Search code examples
zephyr-rtosnrf52840

BL654_DVK vs nrf52840 with Zephyr blinky project troubles


I'm trying to make friends with Zephyr. I have a BL654_DVK board and I can compile and program the blinky example. I kinda understand the dts/overlay files (or at least I think I do). The sample source code is clear. If I build and flash the blinky, the led blinks. I have tried to create another board, just a plain nrf52840 (this is what's on the dvk), set up gpios, add a led, get a handle in the code and try to blink it, but it does not blink. What I have tried so far:

  • changed the blinky not to use alias just for the simplicity's sake, it's using a label, and verified that it works
  • I use the very same source code with zero changes in project to with the nrf52840 target
  • I have tried to move everything over from the bl654_dvk dts file to my dts file but no luck
  • I have tried to move over everything from the prj.conf and the bl654_dvk_devconf files
  • I have tried to use the config from the build/zephyr/.config file in the second project. Essentially that is the output of the nRF Kconfig GUI (or whatever other config one uses)

My understanding is that the bl654_dvk is an nrf52840 with buses, buttons and led added to the device tree. If I only want to blink led1, I could set up an nrf52840 and add an led to the device tree and that should be enough.

Here is the main.c that works in both projects:

#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>

#define SLEEP_TIME_MS   500

static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_NODELABEL(led1_label), gpios);

int main(void) {

    if (!gpio_is_ready_dt(&led)) return 0;

    if (gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE) != 0) return 0;

    while (1) {
        if (gpio_pin_toggle_dt(&led) != 0) return 0;
        k_msleep(SLEEP_TIME_MS);
    }
    return 0;
}

Here is the dts file I try to use in the project that does not work:

/dts-v1/;
#include <nordic/nrf52840_qiaa.dtsi>

/ {
    model = "blah_board";
    compatible = "company,blah_board";

    chosen {
        zephyr,sram = &sram0;
        zephyr,flash = &flash0;
        zephyr,code-partition = &slot0_partition;
    };

    leds {
        compatible = "gpio-leds";
        led1_label: led1 {
            gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
            label = "Blue led1";
        };
    };

};

&flash0 {
    partitions {
        compatible = "fixed-partitions";
        #address-cells = <1>;
        #size-cells = <1>;

        boot_partition: partition@0 {
            label = "mcuboot";
            reg = <0x0 0xc000>;
        };
        slot0_partition: partition@c000 {
            label = "image-0";
            reg = <0xc000 0x72000>;
        };
        slot1_partition: partition@7e000 {
            label = "image-1";
            reg = <0x7e000 0x72000>;
        };
        scratch_partition: partition@f0000 {
            label = "image-scratch";
            reg = <0xf0000 0xa000>;
        };
        storage_partition: partition@fa000 {
            label = "storage";
            reg = <0xfa000 0x6000>;
        };
    };
};


&gpio0 {
    status = "okay";
};

&gpio1 {
    status = "okay";
};

The prj.config has only CONFIG_GPIO=y in it.

The CMakeLists.txt files are identical except the project name:

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})

project(test_3)

target_sources(app PRIVATE src/main.c)

I have no other ideas. Any ideas why my led doesn't blink?


Solution

  • Thank you for this excellent question, surely everybody was waiting for it! The answer is (as always): RTFM!

    One might ask now: Yes yes RTFM, but which one!?

    This one! The answer is on page 19. in the note section. Basically for some strange reason the nRF SDK has a default config to use the XTAL option for nRF52 SoC's as 32KHz clock source. The BL654 (as the nRF52840) does not have an external 32Khz crystal by default, so it has to be configured to use the onboard RC clock by:

    # 32kHz clock source
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_500PPM=y
    

    in the prj.conf file. (These lines are actually in the .defconfig file of the BL654_DVK - the dev. board for the BL654)

    Some might ask: This is all fine, but what do we care for the 32KHz clock source, the primary clock source is a 32MHz crystal oscillator! The answer to that would be in another manual: the 32KHz clock is used in StandByDoze (and DeepSleep) mode to save power. StandByDoze mode is the standby "on" mode which happens in every application - in the blinky too.