取消
显示结果 
搜索替代 
您的意思是: 
Highlighted
Xilinx Employee
Xilinx Employee
227 次查看
注册日期: ‎02-16-2012

[分享]U-Boot 2019.1 新I2C 接口

1.1. U-Boot 2019.1 I2C 接口

在旧版本U-Boot中,会定义CONFIG_SYS_I2C,使init_sequence_f中包含init_func_i2c,从而使init_func_i2c得到运行。开发人员可以在init_func_i2c中添加代码,初始化单板的I2C设备。

#if defined(CONFIG_SYS_I2C)
    init_func_i2c,
#endif

U-Boot 2019.1中定义CONFIG_DM_I2C,它和CONFIG_SYS_I2C彼此排斥,不能都被定义。

#ifdef CONFIG_DM_I2C
# ifdef CONFIG_SYS_I2C
#  error "Cannot define CONFIG_SYS_I2C when CONFIG_DM_I2C is used"
# endif
#endif

定义CONFIG_DM_I2C后,接口发生了改变,i2c_read()对应新接口dm_i2c_read();i2c_write()对应新接口dm_i2c_write()。具体情况可以参考cmd/i2c.c。这个文件根据系统配置,自动选择新接口,或者老接口。也可以定义CONFIG_DM_I2C_COMPAT,编译i2c-uclass-compat.c,保留i2c_read()和i2c_write()等接口。
如果不更改,也没有定义CONFIG_DM_I2C_COMPAT,使用原来接口的代码会出现编译错误"undefined reference to `i2c_read'"等。

1.2. CONFIG_DM_I2C新接口导致U-Boot死机

定义CONFIG_DM_I2C后,init_sequence_f中不再包含I2C的初始化函数。为了继续初始化单板的I2C设备,修改代码,也为CONFIG_DM_I2C添加init_func_i2c。即使用了新的CONFIG_DM_I2C接口,系统在启动运行时,也报告错误。

代码:

static int init_func_i2c(void)
{
    int ret;
    static int i=0;

    struct udevice *bus;
    struct uclass *uc;

    puts("Show all DM I2C device: \r\n");
    ret = uclass_get(UCLASS_I2C, &uc);
    if (ret)
    {   
        printf("uclass_get return %d\r\n\r\n",  ret);
        return ret;
    }
    uclass_foreach_dev(bus, uc)
        i2c_early_show_bus(bus);

    puts("uclass_get_device_by_seq:\r\n");
    ret = uclass_get_device_by_seq(UCLASS_I2C, 0, &bus);
    if (ret) {
        debug("%s: No bus %d\n", __func__, 0);
        printf("uclass_get_device_by_seq return %d\r\n\r\n",  ret);
        return ret;
    }
    puts("Done\r\n");

    return 0;
}

错误信息:

DM I2C:   
Show all DM I2C:   
uclass_get_device_by_seq return -19
initcall sequence 0000000010109d08 failed at call 000000001009753c (err=-19)
### ERROR ### Please RESET the board ###

init_sequence_f中的函数返回0表示成功,U-Boot会继续执行;返回其它值,U-Boot就会打印“initcall sequence xxx failed at call xxx (err=-xxx)”,并且停止执行。代码如下:

    ret = (*init_fnc_ptr)();
    if (ret) {
        printf("initcall sequence %p failed at call %p (err=%d)\n",
               init_sequence,
               (char *)*init_fnc_ptr - reloc_ofs, ret);
        return -1;
    }
    if (initcall_run_list(init_sequence_f_r))
    hang();

U-Boot停止执行后,只能通过其它方式更新启动文件。所以为了方便调试,即使失败,init_func_i2c( )也返回0。这样即使出错,也可以启动到Linux下,使用FTP等网络工具,更新启动文件。

static int init_func_dm_i2c(void)
{
    int ret;

    struct udevice *bus;
    struct uclass *uc;

    puts("Show all DM I2C device:\r\n");
    ret = uclass_get(UCLASS_I2C, &uc);
    if (ret)
    {   
        printf("uclass_get return %d\r\n\r\n",  ret);
        return 0;
    }
    uclass_foreach_dev(bus, uc)
        i2c_early_show_bus(bus);

    puts("uclass_get_device_by_seq:\r\n");
    ret = uclass_get_device_by_seq(UCLASS_I2C, 0, &bus);
    if (ret) {
        debug("%s: No bus %d\n", __func__, 0);
        printf("uclass_get_device_by_seq return %d\r\n\r\n",  ret);
        return 0;
    }
    puts("Done\r\n");

    return 0;
}

1.3. 使用CONFIG_DM_I2C新接口后,U-Boot的I2C设备的新初始化位置

uclass_get_device_by_seq的返回值-19代表ENODEV,表示这时系统还没有i2c设备。因此考虑把init_func_i2c的执行时间推后,研究后决定放到board_late_init( )中。这样init_func_i2c执行成功,输出信息如下:

Show all DM I2C:
Bus 0:  i2c@ff020000
   75: i2c-mux@75, offset len 1, flags 0
Bus 2:  i2c@ff020000->i2c-mux@75->i2c@0
Bus 3:  i2c@ff020000->i2c-mux@75->i2c@1
Bus 4:  i2c@ff020000->i2c-mux@75->i2c@2
Bus 1:  i2c@ff030000
   74: i2c-mux@74, offset len 1, flags 0
   75: i2c-mux@75, offset len 1, flags 0
Bus 5:  i2c@ff030000->i2c-mux@74->i2c@0
   54: eeprom@54, offset len 1, flags 0
Bus 6:  i2c@ff030000->i2c-mux@74->i2c@1
Bus 7:  i2c@ff030000->i2c-mux@74->i2c@2
Bus 8:  i2c@ff030000->i2c-mux@74->i2c@3
Bus 9:  i2c@ff030000->i2c-mux@74->i2c@4
Bus 10: i2c@ff030000->i2c-mux@74->i2c@5
Bus 11: i2c@ff030000->i2c-mux@75->i2c@0
Bus 12: i2c@ff030000->i2c-mux@75->i2c@1
Bus 13: i2c@ff030000->i2c-mux@75->i2c@2
Bus 14: i2c@ff030000->i2c-mux@75->i2c@3
Bus 15: i2c@ff030000->i2c-mux@75->i2c@4
Bus 16: i2c@ff030000->i2c-mux@75->i2c@5
Bus 17: i2c@ff030000->i2c-mux@75->i2c@6
Bus 18: i2c@ff030000->i2c-mux@75->i2c@7
uclass_get_device_by_seq:
Done