Undefined reference to __device_dts_ord_75 when trying to use PWM

Hello and thank you in advance (also happy holidays). Im currently working with an NRF5340, and have basically everything working except PWM.

When I try to compile, I get an error during the linking stage: ../src/LED.c:38: undefined reference to `__device_dts_ord_75'

I have set both CONFIG_PWM and CONFIG_TIMER to y in the .conf file.

The offending line of code is

pwm_set_dt(&pwm_led_r, max_period, max_period / 2U)

and pwm_led_r is defined as:

static const struct pwm_dt_spec pwm_led_r = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led0));

Please let me know what files (if any) you need to help you with this.

Thank you!

  • Hi there,

    1. What nRF Connect SDK version are you using?
    2. Which nRF5340 board are you building for, cpu app?
    3. Have you remembered to set pwm_led0 node as 'okay' in the status field?
    4. Can you share your dts and project config, include overlay if used as well.

    regards

    Jared 

  • Hello, and thank you for your reply.

    I am using SDK 2.5.0

    I am building for a CPU app, and it is a custom board, although I can also test with the 5340-DK.

    pwm_led0 status is indeed set to okay:

    &pwm0 {
    	status = "okay";
    };
    
    &sw_pwm {
    	status = "okay";
    	channel-gpios = <&gpio0 24 PWM_POLARITY_NORMAL>;
    };
    
    &pwm_led0 {
        status = "okay";
    	pwms = <&sw_pwm 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
    };

    Please find below my dts, project config and overlay files:

    #GPIO
    CONFIG_GPIO=y
    CONFIG_PINCTRL=y
    
    #UART & SERIAL
    CONFIG_SERIAL=y
    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
    
    #SYSTEM & CLOCK
    CONFIG_SOC_HFXO_CAP_EXTERNAL=y
    CONFIG_SOC_HFXO_CAP_INTERNAL=n
    # CONFIG_SOC_ENABLE_LFXO=n
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
    CONFIG_MAIN_STACK_SIZE=8192
    
    #CPP
    CONFIG_CPP=y
    CONFIG_REQUIRES_FULL_LIBCPP=y
    CONFIG_STD_CPP20=y
    
    #i2C
    CONFIG_I2C=y
    
    #spi
    CONFIG_SPI=y
    
    #flash
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_NVS=y
    CONFIG_MPU_ALLOW_FLASH_WRITE=y
    CONFIG_FILE_SYSTEM=y
    CONFIG_SOC_FLASH_NRF=y
    
    #math
    CONFIG_CMSIS_DSP=y
    CONFIG_NEWLIB_LIBC=y
    # CONFIG_FPU=y
    # CONFIG_CMSIS_DSP_TRANSFORM=y
    # CONFIG_TFM_ENABLE_CP10CP11=y
    CONFIG_CMSIS_DSP_FILTERING=y
    
    #BLE
    CONFIG_BT=y
    CONFIG_BT_GATT_CLIENT=y
    CONFIG_BT_PERIPHERAL=y
    CONFIG_BT_DEVICE_NAME="BAR"
    
    #BT BATTERY SERVICE (BAS)
    CONFIG_BT_BAS=y
    
    #DIS
    CONFIG_BT_DIS=y
    CONFIG_BT_DIS_PNP=y
    CONFIG_BT_DIS_MANUF="FOO"
    CONFIG_BT_DIS_PNP_VID_SRC=2
    CONFIG_BT_DIS_PNP_VID=0x1915
    CONFIG_BT_DIS_PNP_PID=0xEEEE
    CONFIG_BT_DIS_PNP_VER=0x0100
    
    #BT HID
    CONFIG_NCS_SAMPLES_DEFAULTS=y
    
    CONFIG_BT_DEBUG_LOG=y
    CONFIG_BT_MAX_CONN=1
    CONFIG_BT_MAX_PAIRED=1
    CONFIG_BT_SMP=y
    CONFIG_BT_L2CAP_TX_BUF_COUNT=5
    CONFIG_BT_DEVICE_APPEARANCE=962
    CONFIG_BT_HIDS=y
    CONFIG_BT_HIDS_MAX_CLIENT_COUNT=1
    CONFIG_BT_HIDS_DEFAULT_PERM_RW_ENCRYPT=y
    CONFIG_BT_GATT_UUID16_POOL_SIZE=40
    CONFIG_BT_GATT_CHRC_POOL_SIZE=20
    CONFIG_BT_CONN_CTX=y
    
    #2MEG PHY & MTU
    CONFIG_BT_CTLR_PHY_2M=y
    CONFIG_BT_AUTO_PHY_UPDATE=y
    CONFIG_BT_USER_PHY_UPDATE=y
    
    CONFIG_BT_BUF_ACL_RX_SIZE=251
    CONFIG_BT_L2CAP_TX_MTU=247
    
    CONFIG_BT_PERIPHERAL_PREF_MIN_INT=6
    CONFIG_BT_PERIPHERAL_PREF_MAX_INT=24
    CONFIG_BT_PERIPHERAL_PREF_LATENCY=0
    CONFIG_BT_PERIPHERAL_PREF_TIMEOUT=400
    
    #ADC
    CONFIG_ADC=y
    CONFIG_ADC_ASYNC=y
    
    #PWM
    CONFIG_PWM=y
    CONFIG_TIMER=y
    CONFIG_PWM_LOG_LEVEL_DBG=y

    // To get started, press Ctrl+Space to bring up the completion menu and view the available nodes.
    
    // You can also use the buttons in the sidebar to perform actions on nodes.
    // Actions currently available include:
    
    // * Enabling / disabling the node
    // * Adding the bus to a bus
    // * Removing the node
    // * Connecting ADC channels
    
    // For more help, browse the DeviceTree documentation at https://docs.zephyrproject.org/latest/guides/dts/index.html
    // You can also visit the nRF DeviceTree extension documentation at https://nrfconnect.github.io/vscode-nrf-connect/devicetree/nrfdevicetree.html
    &i2c1 {
        status = "okay";
        lms303agr_acc: lms303agr_acc@19 {
            compatible = "i2c-device";
            label = "lsm303 accelerometer";
            reg = <0x19>;
            status = "okay";
        };
        lms303agr_mag: lms303agr_mag@1E {
            compatible = "i2c-device";
            label = "lsm303 magnetometer";
            reg = <0x1E>;
            status = "okay";
        };
    };
    
    /{
    	zephyr,user {
    	   io-channels = <&adc 6>; //Select which ADC you are using here
    	};
    };
    
    &pwm0 {
    	status = "okay";
    };
    
    &sw_pwm {
    	status = "okay";
    	channel-gpios = <&gpio0 24 PWM_POLARITY_NORMAL>;
    };
    
    &pwm_led0 {
        status = "okay";
    	pwms = <&sw_pwm 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
    };

    #include "nrf5340_cpuapp_common-pinctrl.dtsi"
    #include <zephyr/dt-bindings/input/input-event-codes.h>
    
    / {
    
    	chosen {
    		zephyr,console = &uart0;
    		zephyr,shell-uart = &uart0;
    		zephyr,uart-mcumgr = &uart0;
    		zephyr,bt-mon-uart = &uart0;
    		zephyr,bt-c2h-uart = &uart0;
    		zephyr,bt-hci-rpmsg-ipc = &ipc0;
    		nordic,802154-spinel-ipc = &ipc0;
    		zephyr,ieee802154 = &ieee802154;
    	};
    
    	leds {
    		compatible = "gpio-leds";
    		// led0: led_0 {
    		// 	gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
    		// 	label = "Green LED 0";
    		// };
    		// led1: led_1 {
    		// 	gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
    		// 	label = "Green LED 1";
    		// };
    		// led2: led_2 {
    		// 	gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;
    		// 	label = "Green LED 2";
    		// };
    		// led3: led_3 {
    		// 	gpios = <&gpio0 31 GPIO_ACTIVE_LOW>;
    		// 	label = "Green LED 3";
    		// };
    
    		testgpio1: testgpio1 {
    			gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
    			label = "TEST GPIO 1";
    		};
    		testgpio2: testgpio2 {
    			gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
    			label = "TEST GPIO 2";
    		};
    		testgpio3: testgpio3 {
    			gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>;
    			label = "TEST GPIO 3";
    		};
    		testgpio4: testgpio4 {
    			gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
    			label = "TEST GPIO 4";
    		};
    		testgpio5: testgpio5 {
    			gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
    			label = "TEST GPIO 5";
    		};
    
    		usbiset: usbiset {
    			gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
    			label = "Set usb current limit";
    		};
    		neopixled: neopixled {
    			gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
    			label = "RGB LED DIN";
    		};
    		rst1: rst1 {
    			gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
    			label = "reset pin for extnernal ICs";
    		};
    		battmonen: battmonen {
    			gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
    			label = "En battery monitoring";
    		};
    		mode: mode {
    			gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
    			label = "DC DC converter";
    		};
    		adscs: adscs {
    			gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>;
    			label = "ADS SPI CS";
    		};
    	};
    
    	pwmleds {
    		compatible = "pwm-leds";
    		pwm_led0: pwm_led_0 {
    			pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
    		};
    	};
    
    	buttons {
    		compatible = "gpio-keys";
    		// button0: button_0 {
    		// 	gpios = <&gpio0 23 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    		// 	label = "Push button 1";
    		// 	zephyr,code = <INPUT_KEY_0>;
    		// };
    		// button1: button_1 {
    		// 	gpios = <&gpio0 24 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    		// 	label = "Push button 2";
    		// 	zephyr,code = <INPUT_KEY_1>;
    		// };
    		// button2: button_2 {
    		// 	gpios = <&gpio0 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    		// 	label = "Push button 3";
    		// 	zephyr,code = <INPUT_KEY_2>;
    		// };
    		// button3: button_3 {
    		// 	gpios = <&gpio0 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    		// 	label = "Push button 4";
    		// 	zephyr,code = <INPUT_KEY_3>;
    		// };
    
    		imudrdy: imudrdy {
    			gpios = <&gpio0 5 (GPIO_ACTIVE_LOW)>;
    			label = "imu data ready";
    			zephyr,code = <INPUT_KEY_3>;
    		};
    		adsdrdy: adsdrdy {
    			gpios = <&gpio0 4 (GPIO_ACTIVE_LOW)>;
    			label = "ADS data ready";
    			zephyr,code = <INPUT_KEY_3>;
    		};
    
    		caseclosed: caseclosed {
    			gpios = <&gpio0 23 (GPIO_ACTIVE_LOW)>;
    			label = "case open/closed sensor";
    			zephyr,code = <INPUT_KEY_3>;
    		};
    
    		lowbatt: lowbatt {
    			gpios = <&gpio1 10 (GPIO_ACTIVE_LOW)>;
    			label = "low battery warning";
    			zephyr,code = <INPUT_KEY_3>;
    		};
    		batterr: batterr {
    			gpios = <&gpio0 28 (GPIO_ACTIVE_LOW)>;
    			label = "Battery charger error";
    			zephyr,code = <INPUT_KEY_3>;
    		};
    		charge: charge {
    			gpios = <&gpio0 30 (GPIO_ACTIVE_LOW)>;
    			label = "Battery charger charging";
    			zephyr,code = <INPUT_KEY_3>;
    		};
    		battmon: battmon {
    			gpios = <&gpio1 8 (GPIO_ACTIVE_LOW)>;
    			label = "Battery monitoring signal";
    			zephyr,code = <INPUT_KEY_3>;
    		};
    
    		adsmiso: adsmiso {
    			gpios = <&gpio0 10 (GPIO_ACTIVE_HIGH)>;
    			label = "ADS MISO";
    			zephyr,code = <INPUT_KEY_3>;
    		};
    	};
    
    	arduino_header: connector {
    		compatible = "arduino-header-r3";
    		#gpio-cells = <2>;
    		gpio-map-mask = <0xffffffff 0xffffffc0>;
    		gpio-map-pass-thru = <0 0x3f>;
    		gpio-map = <0 0 &gpio0 4 0>,	/* A0 */
    			   <1 0 &gpio0 5 0>,	/* A1 */
    			   <2 0 &gpio0 6 0>,	/* A2 */
    			   <3 0 &gpio0 7 0>,	/* A3 */
    			   <4 0 &gpio0 25 0>,	/* A4 */
    			   <5 0 &gpio0 26 0>,	/* A5 */
    			   <6 0 &gpio1 0 0>,	/* D0 */
    			   <7 0 &gpio1 1 0>,	/* D1 */
    			   <8 0 &gpio1 4 0>,	/* D2 */
    			   <9 0 &gpio1 5 0>,	/* D3 */
    			   <10 0 &gpio1 6 0>,	/* D4 */
    			   <11 0 &gpio1 7 0>,	/* D5 */
    			   <12 0 &gpio1 8 0>,	/* D6 */
    			   <13 0 &gpio1 9 0>,	/* D7 */
    			   <14 0 &gpio1 10 0>,	/* D8 */
    			   <15 0 &gpio1 11 0>,	/* D9 */
    			   <16 0 &gpio1 12 0>,	/* D10 */
    			   <17 0 &gpio1 13 0>,	/* D11 */
    			   <18 0 &gpio1 14 0>,	/* D12 */
    			   <19 0 &gpio1 15 0>,	/* D13 */
    			   <20 0 &gpio1 2 0>,	/* D14 */
    			   <21 0 &gpio1 3 0>;	/* D15 */
    	};
    
    	arduino_adc: analog-connector {
    		compatible = "arduino,uno-adc";
    		#io-channel-cells = <1>;
    		io-channel-map = <0 &adc 0>,	/* A0 = P0.4 = AIN0 */
    				 <1 &adc 1>,	/* A1 = P0.5 = AIN1 */
    				 <2 &adc 2>,	/* A2 = P0.6 = AIN2 */
    				 <3 &adc 3>,	/* A3 = P0.7 = AIN3 */
    				 <4 &adc 4>,	/* A4 = P0.25 = AIN4 */
    				 <5 &adc 5>;	/* A5 = P0.26 = AIN5 */
    	};
    
    	gpio_fwd: nrf-gpio-forwarder {
    		compatible = "nordic,nrf-gpio-forwarder";
    		status = "okay";
    		uart {
    			gpios = <&gpio1 1 0>, <&gpio1 0 0>, <&gpio0 2 0>, <&gpio0 3 0>;
    		};
    	};
    
    	/* These aliases are provided for compatibility with samples */
    	aliases {
    		testgpio1 = &testgpio1;
    		testgpio2 = &testgpio2;
    		testgpio3 = &testgpio3;
    		testgpio4 = &testgpio4;
    		testgpio5 = &testgpio5;
    
    		usbiset 	= &usbiset;
    		neopixled 	= &neopixled;
    		rst1 		= &rst1;
    		battmonen	= &battmonen;
    		mode 		= &mode;
    		
    		imudrdy 	= &imudrdy;
    		adsdrdy		= &adsdrdy;
    		adscs		= &adscs;
    		caseclosed	= &caseclosed;
    		lowbatt		= &lowbatt; 
    		batterr		= &batterr;
    		charge		= &charge;
    		battmon		= &battmon;
    		adsmiso		= &adsmiso;
    		
    		// led0 = &led0;
    		// led1 = &led1;
    		// led2 = &led2;
    		// led3 = &led3;
    		pwm-led0 = &pwm_led0;
    		// sw0 = &button0;
    		// sw1 = &button1;
    		// sw2 = &button2;
    		// sw3 = &button3;
    		// bootloader-led0 = &led0;
    		// mcuboot-button0 = &button0;
    		// mcuboot-led0 = &led0;
    		watchdog0 = &wdt0;
    		// spi-flash0 = &mx25r64;
    	};
    };
    
    &adc {
    	status = "okay";
    };
    
    &gpiote {
    	status = "okay";
    };
    
    &gpio0 {
    	status = "okay";
    };
    
    &gpio1 {
    	status = "okay";
    };
    
    &i2c1 {
    	compatible = "nordic,nrf-twim";
    	status = "okay";
    	pinctrl-0 = <&i2c1_default>;
    	pinctrl-1 = <&i2c1_sleep>;
    	pinctrl-names = "default", "sleep";
    };
    
    &uart0 {
    	status = "okay";
    	current-speed = <115200>;
    	pinctrl-0 = <&uart0_default>;
    	pinctrl-1 = <&uart0_sleep>;
    	pinctrl-names = "default", "sleep";
    };
    
    &pwm0 {
    	status = "okay";
    	pinctrl-0 = <&pwm0_default>;
    	pinctrl-1 = <&pwm0_sleep>;
    	pinctrl-names = "default", "sleep";
    };
    
    // &qspi {
    // 	status = "okay";
    // 	pinctrl-0 = <&qspi_default>;
    // 	pinctrl-1 = <&qspi_sleep>;
    // 	pinctrl-names = "default", "sleep";
    // 	mx25r64: mx25r6435f@0 {
    // 		compatible = "nordic,qspi-nor";
    // 		reg = <0>;
    // 		/* MX25R64 supports only pp and pp4io */
    // 		writeoc = "pp4io";
    // 		/* MX25R64 supports all readoc options */
    // 		readoc = "read4io";
    // 		sck-frequency = <8000000>;
    // 		jedec-id = [c2 28 17];
    // 		sfdp-bfp = [
    // 			e5 20 f1 ff  ff ff ff 03  44 eb 08 6b  08 3b 04 bb
    // 			ee ff ff ff  ff ff 00 ff  ff ff 00 ff  0c 20 0f 52
    // 			10 d8 00 ff  23 72 f5 00  82 ed 04 cc  44 83 68 44
    // 			30 b0 30 b0  f7 c4 d5 5c  00 be 29 ff  f0 d0 ff ff
    // 		];
    // 		size = <67108864>;
    // 		has-dpd;
    // 		t-enter-dpd = <10000>;
    // 		t-exit-dpd = <35000>;
    // 	};
    // };
    
    arduino_serial: &uart1 {
    	compatible = "nordic,nrf-uarte";
    	current-speed = <115200>;
    	pinctrl-0 = <&uart1_default>;
    	pinctrl-1 = <&uart1_sleep>;
    	pinctrl-names = "default", "sleep";
    };
    
    arduino_i2c: &i2c1 {};
    
    arduino_spi: &spi4 {
    	compatible = "nordic,nrf-spim";
    	status = "okay";
    	// cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */
    	pinctrl-0 = <&spi4_default>;
    	// pinctrl-1 = <&spi4_sleep>;
    	// pinctrl-names = "default", "sleep";
    	pinctrl-names = "default";
    };
    
    &flash0 {
    
    	partitions {
    		compatible = "fixed-partitions";
    		#address-cells = <1>;
    		#size-cells = <1>;
    
    		boot_partition: partition@0 {
    			label = "mcuboot";
    			reg = <0x00000000 0x00010000>;
    		};
    		slot0_partition: partition@10000 {
    			label = "image-0";
    		};
    		slot0_ns_partition: partition@50000 {
    			label = "image-0-nonsecure";
    		};
    		slot1_partition: partition@80000 {
    			label = "image-1";
    		};
    		slot1_ns_partition: partition@c0000 {
    			label = "image-1-nonsecure";
    		};
    		/* 0xf0000 to 0xf7fff reserved for TF-M partitions */
    		storage_partition: partition@f8000 {
    			label = "storage";
    			reg = <0x000f8000 0x00008000>;
    		};
    	};
    };
    
    &ieee802154 {
    	status = "okay";
    };
    
    zephyr_udc0: &usbd {
    	compatible = "nordic,nrf-usbd";
    	status = "okay";
    };
    
    / {
    
    	reserved-memory {
    		#address-cells = <1>;
    		#size-cells = <1>;
    		ranges;
    
    		sram0_image: image@20000000 {
    			/* Zephyr image(s) memory */
    		};
    
    		sram0_s: image_s@20000000 {
    			/* Secure image memory */
    		};
    
    		sram0_ns: image_ns@20040000 {
    			/* Non-Secure image memory */
    		};
    	};
    };
    
    /* Include partition configuration file */
    #include "nrf5340_cpuapp_partition_conf.dtsi"
    

    Thank you!

  • &sw_pwm {
        status = "okay";
        channel-gpios = <&gpio0 24 PWM_POLARITY_NORMAL>;
    };

    This node in your device tree appears related to the nrf-sw-pwm driver. Do you have the software PWM driver included? You're using nrf5340 and hardware PWM works; SW PWM is not required. If for some reason you wanted to use SW PWM anyway, I think CONFIG_PWM_NRF_SW would be needed to enable it.

    As part of the build process all the device tree fragments and overlays are assembled into a single dts file, usually found in build/zephyr/zephyr.dts. When troubleshooting this kind of problem sometimes it is helpful to look at this file to see what the tools are really working with. The dts-compiled-to-header-file also can be useful; it is in build/zephyr/include/generated/devicetree_generated.h.

    In two of the code citations above pwm_led0 is shown this way:

    &pwm_led0 {
        status = "okay";
        pwms = <&sw_pwm 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
    };

    But in the last one it is this shown way:

        pwmleds {
            compatible = "pwm-leds";
            pwm_led0: pwm_led_0 {
                pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
            };
        };

    Notice that one fragment references &sw_pwm while the other references &pwm0. I suggest you remove the first one so that pwm_led0 will reference pwm0.

    The pwm0 node references pwm0_default and pwm0_sleep but I don't see these defined. Try removing your sw_pwm node and add the following instead. I copied this from zephyr/boards/arm/nrf5340dk_nrf5340/nrf5340_cpuapp_common-pinctrl.dtsi and modified it to use gpio0.24 as per your code given earlier.

    &pinctrl {
        pwm0_default: pwm0_default {

            group1 {
                psels = <NRF_PSEL(PWM_OUT0, 0, 24)>;
            };
        };

        pwm0_sleep: pwm0_sleep {
            group1 {
                psels = <NRF_PSEL(PWM_OUT0, 0, 24)>;
                low-power-enable;
            };
        };
    };

    Also, depending on whether you want to write your own LED PWM driver versus using the one available in Zephyr, you may want CONFIG_LED_PWM=y in your prj.conf.

Related