ubuntu20.04系统下更新Raspberry Pi4的DTB

如果我们想要在ubuntu20.04系统下开发rasp的i2c设备驱动程序,那我们需要在相应的i2c设备树节点里添加设备的node信息。我们先看/boot下有哪些信息:

# ls /boot/ -l
total 42275
-rw-r--r-- 1 root root 233406 Apr 14 17:42 config-5.11.0-1007-raspi lrwxrwxrwx 1 root root 44 Apr 21 20:37 dtb -> dtbs/5.11.0-1007-raspi/./bcm2711-rpi-4-b.dtb lrwxrwxrwx 1 root root 44 Apr 21 20:37 dtb-5.11.0-1007-raspi -> dtbs/5.11.0-1007-raspi/./bcm2711-rpi-4-b.dtb drwxr-xr-x 3 root root 4096 Apr 21 20:25 dtbs drwxr-xr-x 3 root root 7168 Dec 31 1969 firmware drwxr-xr-x 2 root root 4096 Aug 12 23:56 grub lrwxrwxrwx 1 root root 28 Apr 21 20:33 initrd.img -> initrd.img-5.11.0-1007-raspi -rw-r--r-- 1 root root 28470360 Apr 21 20:37 initrd.img-5.11.0-1007-raspi lrwxrwxrwx 1 root root 28 Apr 21 20:01 initrd.img.old -> initrd.img-5.11.0-1007-raspi -rw------- 1 root root 5099714 Apr 14 17:42 System.map-5.11.0-1007-raspi lrwxrwxrwx 1 root root 25 Apr 21 20:33 vmlinuz -> vmlinuz-5.11.0-1007-raspi -rw------- 1 root root 9464117 Apr 14 17:42 vmlinuz-5.11.0-1007-raspi

发现/boot下的dtb软连接到dtbs/5.11.0-1007-raspi/./bcm2711-rpi-4-b.dtb,不要被这个假象迷惑,因为kernel启动时不是加载这里的dtb,本人亲测过!!!

实际上kernel启动时加载的dtb的文件为 /boot/firmware/bcm2711-rpi-4-b.dtb。

反编译dtb,生成dts

dtc -I dtb -O dts -o bcm2711-rpi-4-b.dts bcm2711-rpi-4-b.dtb

然后我们就可以打开 bcm2711-rpi-4-b.dts进行快乐的编辑了。

比如我们想在i2c-1适配器的节点下添加一个slave地址为0x38的设备节点,添加内容如下:

 

 

编译dts,生成dtb

添加完i2c从设备的node以后,我们需要再把dts编译成dtb文件,从而使我们的修改生效。

dtc -I dts -O dtb -o bcm2711-rpi-4-b.dtb bcm2711-rpi-4-b.dts

reboot 树莓派板子,dts的修改就会生效了。

 

i2c设备驱动demo

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/i2c.h>
#include <linux/cdev.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>


struct dummy_dev {
        unsigned char *data;
        struct i2c_client *client;
        struct mutex dummy_mutex;
        struct cdev cdev;
        struct class *dummy_cls;
};


static int mypdrv_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
        int err, index;
        struct dummy_dev *dummy_device = NULL;
        struct device *dev = &client->dev;
        unsigned char read_buf[32] = {0x0};
        unsigned char write_buf[5] = {0x00, 0x12, 0x34, 0x56, 0x78};

        pr_info("[%s] i2c slave address: 0x%.2X irq: %d\n", __func__, client->addr, client->irq);

        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BLOCK_DATA))
                pr_err("I2C_FUNC_SMBUS_WRITE_BLOCK_DATA is not support\n");

      /* 判断client的adapter(适配器)驱动支持
I2C_FUNC_SMBUS_READ_BLOCK_DATA功能, 不是所有的适配器驱动程序都支持这一点;它通过I2C消息传递进行模拟,依赖于可能没有实现的特定机制(I2C_M_RECV_LEN)。Raspberry Pi4就不支持*/
  
     if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BLOCK_DATA))
                pr_err("I2C_FUNC_SMBUS_READ_BLOCK_DATA is not support\n");


        //write_buf[0] = 0x4;
        //err = i2c_smbus_write_i2c_block_data(client, 0x29, 5, write_buf);
        i2c_smbus_write_block_data(client, 0x29, 4, write_buf);
     //err = i2c_smbus_read_block_data(client, 0x29, read_buf); //不支持这个api!!!!
        err = i2c_smbus_read_i2c_block_data(client, 0x29, 5, read_buf);
        if (err < 0) {
                pr_err("i2c smbus read block faild, err=%d\n", err);
                return err;
        }
        pr_info("err=%d; read_buf[0-6]: %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",\
                        err, read_buf[0], read_buf[1], read_buf[2],\
                        read_buf[3], read_buf[4], read_buf[5], read_buf[6]);

      dummy_device->client = client;
      client->addr = 0x38; /* if the slave addr from dts is not correct, hardcode it with the right addr */
      mutex_init(&dummy_device->dummy_mutex);
      i2c_set_clientdata(client, dummy_device);

     .............. 
  

    return 0; } static int mypdrv_remove(struct i2c_client *client) { struct dummy_dev *dummy_device = i2c_get_clientdata(client); pr_info("[%s] i2c slave addr=0x%.2x\n", __func__, client->addr); mutex_destroy(&dummy_device->dummy_mutex); kfree(dummy_device); return 0; } /* 如果使用OF匹配表匹配,i2c_driver.id_table必须存在,即使为空 */ static const struct i2c_device_id i2c_id_table[] = { {} }; MODULE_DEVICE_TABLE(i2c, i2c_id_table); static const struct of_device_id mypdrv_dt_ids[] = { {.compatible = "ti,tps65987",}, {} }; MODULE_DEVICE_TABLE(of, mypdrv_dt_ids); static struct i2c_driver mypdrv = { .driver = { .name = "123", .owner = THIS_MODULE, .of_match_table = of_match_ptr(mypdrv_dt_ids), }, .probe = mypdrv_probe, .remove = mypdrv_remove, .id_table = i2c_id_table, }; module_i2c_driver(mypdrv); MODULE_DESCRIPTION("i2c driver demo"); MODULE_AUTHOR("xxx"); MODULE_LICENSE("GPL");

 

posted @ 2021-08-13 19:03  闹闹爸爸  阅读(825)  评论(0编辑  收藏  举报