MCP7940 device tree implementation

Hi I am receiving the error "Linking C executable zephyr\zephyr_pre0.elf FAILED:" which I have found is linked to the mcp7940 device tree node through the error code " undefined reference to `__device_dts_ord_57'" in the device_generated.h file. I want to include in the device tree the interrupt that the mcp7940  on gpio 0 21 of the NRF52805 but I'm not sure if this is best practice or not. How do I solve this error and include the gpio interrupt in the device tree?

Here is the device tree node for the MCP7940n and the corresponding device tree binding.

Device Tree node

&i2c0 {
    status = "okay";
    pinctrl-0 =<&i2c0_default>;
    pinctrl-1 =<&i2c0_sleep>;
    pinctrl-names = "default","sleep";
    clock-frequency = <100000>;
    
    mcp7940n: mcp7940n@6f {
        compatible = "microchip,mcp7940n";
        reg = <0x6f>;
        label = "MCP7940N_RTC";
        //int-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;  // Use actual GPIO pin where interrupt is connected
    };
};

.yaml binding

#
# Copyright (c) 2021 Laird Connectivity
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0
#

description: Microchip MCP7940N I2C RTC with battery-backed SRAM

compatible: "microchip,mcp7940n"

include: i2c-device.yaml

properties:
  reg:
    type: array
    description: |
      The I2C address of the device 0x6F
      

  • I am using the nrf connect SDK 2.6.1 and here is my proj.conf file

    CONFIG_RTT_CONSOLE=y
    CONFIG_I2C=y
    CONFIG_LOG=y
    

    and the custom board defconfig file

     Copyright (c) 2024 Nordic Semiconductor ASA
    # SPDX-License-Identifier: Apache-2.0
    
    CONFIG_SOC_SERIES_NRF52X=y
    CONFIG_SOC_NRF52805_CAAA=y
    CONFIG_BOARD_CESSADK_NRF52805=y
    
    # Enable MPU
    CONFIG_ARM_MPU=y
    
    # Enable hardware stack protection
    CONFIG_HW_STACK_PROTECTION=y
    
    # enable GPIO
    CONFIG_GPIO=y
    
    # enable console
    CONFIG_CONSOLE=y
    
    # enable RTT console
    CONFIG_USE_SEGGER_RTT=y
    
    # additional board options
    CONFIG_GPIO_AS_PINRESET=n
    
    CONFIG_PINCTRL=y
    
    # enable internal oscillator
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_500PPM=y
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION=y
    CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_LF_ALWAYS_ON=y
    

    here is the main.c code

    /*
     * Copyright (c) 2016 Intel Corporation
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/gpio.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/drivers/i2c.h>
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS   1000
    
    /* The devicetree node identifier for the "led0" alias. */
    #define LED0_NODE DT_ALIAS(led0)
    #define RTC_NODE DT_NODELABEL(mcp7940n)
    
    #define MCP7940_ADDR 0x6F
    #define RTCSEC_ADDR 0x00
    #define RTCMIN_ADDR 0x01
    #define RTCSHOUR_ADDR 0x02
    #define RTCWKD_ADDR 0x03
    /*
     * A build error on this line means your board is unsupported.
     * See the sample documentation for information on how to fix this.
     */
    LOG_MODULE_REGISTER(maindev, LOG_LEVEL_DBG);
    static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
    
    
    
    int main(void)
    {
    	const struct device *rtc_dev; 
    	rtc_dev = DEVICE_DT_GET(RTC_NODE);
    	uint8_t write_msg = 0x00; 
    	uint8_t read_sec_msg = 255; 
    	uint8_t read_wkd_msg = 0;
    	
    	int ret;
        // Get the I2C device
    	
    
        if (!device_is_ready(rtc_dev)) {
            LOG_ERR("I2C device not ready");
            return 0;
        }
    	if (!gpio_is_ready_dt(&led)) {
    		LOG_ERR("LED not ready");
    		return 0;
    	}
    
    	//load the rtc sec register with 0 while the osc is disabled
    	ret = i2c_reg_write_byte(rtc_dev, MCP7940_ADDR,RTCSEC_ADDR, 0);
    	
    	if(ret){
    		LOG_ERR("write to osc start bit failed error = %d",ret);
    	}
    
    	write_msg |= 0x80; //SET THE START OSCILLATOR BIT 
    
    	//write to the start bit of the oscillator
    	ret = i2c_reg_write_byte(rtc_dev, MCP7940_ADDR,RTCSEC_ADDR,write_msg);
    	
    	if(ret){
    		LOG_ERR("write to rtc second register failed error = %d",ret);
    	}
    
    	//wait three seconds
    	k_msleep(1000);
    	k_msleep(1000);
    	k_msleep(1000);
    
    	//read the sec register after waiting 3 seconds
    	ret = i2c_reg_read_byte(rtc_dev,MCP7940_ADDR, RTCSEC_ADDR,&read_sec_msg);
    
    	if(ret){
    		LOG_ERR("read to rtc second register failed error = %d",ret);
    	}
    
    
    	//read the rtc second address to see if one second has passed
    	ret = i2c_reg_read_byte(rtc_dev,MCP7940_ADDR, RTCWKD_ADDR,&read_wkd_msg);
    	
    	
    	if(ret){
    		LOG_ERR("read to rtc second register failed error = %d",ret);
    	}
    	
    	LOG_INF("here is the read message: 0x%02X", read_sec_msg);
    	LOG_INF("here is the wkd register contents: 0x%02X", read_wkd_msg);
    	
    
    	ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
    	if (ret < 0) {
    		return 0;
    	}
    
    	while (1) {
    		ret = gpio_pin_toggle_dt(&led);
    		if (ret < 0) {
    			return 0;
    		}
    		k_msleep(SLEEP_TIME_MS);
    	}
    	return 0;
    }
    

  • Hi

    So, the device_dts_ord_xx error in itself doesn't tell us much other than that the device tree structure (dts) is missing something. Please check out the file in build\zephyr\include\generated\devicetree_generated.h and check what the number 57 corresponds to. You can check out the DevAcademy lesson on troubleshooting the devicetree here: https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-2-debugging/topic/troubleshooting-the-devicetree/ 

    Best regards,

    Simon

  • Hi Simon, I did check line 57 and it said it corresponded to the MCP7940 RTC. I ended up scrapping the custom driver and just used the generic i2c driver api.

Related