当前位置: 首页 > news >正文

OrangePi Zero 3学习笔记(Android篇)9 - I2C和从设备

目录

1. Ubuntu X86中实现

1. 1 编译内核

1.2 ko的方式(首选)

1.3 I2C设备的匹配

1.3.1 ACPI方式

1.3.2 new_device/delete_device

1.4 验证

2. Android ARM上实现

2.1 内核配置

​编辑

2.2 修改设备树

2.3 修改权限

3. Android AT24C32支持


通过FT4232H的i2c接口驱动OLED,作为系统console的屏幕显示(失败)。最后是使用EEPROM验证。

1. Ubuntu X86中实现

1. 1 编译内核

先在X86虚拟机里面驱动OLED(SSD1307)128x64单色屏作为屏幕显示。

下载好Linux的源代码,

uname -r
apt-cache search linux-source
sudo apt-get install linux-source-6.5.0

净化内核源码

sudo make mrproper

将现有的内核版本的config配置信息复制到现在目录下的 .config里面

cp /boot/config-6.8.0-49-generic ./.config

配置选择Device Drivers > Graphics support > Frame buffer Devices -> Solomon SSD1307 framebuffer support

安装缺失的库(把debian文件夹拷贝到源代码文件夹内),编译

sudo make
sudo make bzImage
sudo make install
sudo make modules_install

切换内核的步骤,先执行:

sudo update-initramfs -c -k 6.5.13

这里的6.5.13是新编译的Linux内核版本号,可以看modules_install输出信息,例如:INSTALL /lib/modules/6.5.13/kernel/ubuntu/ubuntu-host/ubuntu-host.ko

然后更新grub

sudo update-grub

系统复位按ESC,进Advance...菜单(第二个),选择6.5.13内核

1.2 ko的方式(首选)

为了避免编译内核,可以将内核源码中的linux-source-6.5.0/drivers/video/fbdev/ssd1307fb.c文件拷贝出来,新建一个makefile文件

ifeq ($(KERNELRELEASE), )
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
default:$(MAKE) -C $(KERNELDIR)  M=$(PWD)  
clean:rm -rf *.mk .tmp_versions Module.symvers *.mod.c *.o *.ko .*.cmd Module.markers modules.order *.a *.mod
load:insmod ssd1307fb.ko
unload:rmmod ssd1307fb
install: defaultrmmod ssd1307fb || true
#	insmod ssd1307fb.ko || truemkdir -p /lib/modules/$(shell uname -r)/kernel/drivers/video/fbdev/ || truecp -f ./ssd1307fb.ko /lib/modules/$(shell uname -r)/kernel/drivers/video/fbdev/ || truemodprobe ssd1307fb || true
#	depmod -a
uninstall:rmmod ssd1307fb || truerm -rf /lib/modules/$(shell uname -r)/kernel/drivers/video/fbdev/ssd1307fb.ko || true
#	depmod -a
elseobj-m := ssd1307fb.o
endif

编译make,安装sudo make install,安装后可以查看是否有对应的驱动(驱动名为ssd1307fb)

1.3 I2C设备的匹配

1.3.1 ACPI方式

对于X86/AMD64平台,匹配机制采用的是ACPI(Advanced Configuration and Power Interface)匹配表

参考文档:基于 ACPI 的设备枚举 — Linux 内核文档

不过这种方式资料好少,没找到具体怎么改的。

1.3.2 new_device/delete_device

参考文档:linux源码中的文档Documentation/i2c/slave-eeprom-backend.rst

例如在i2c-1下挂载了AT24C32(使用FT4232H的i2c接AT24C32,比OLED实现要简单的多),地址为0x50,新增这个设备的命令:

echo slave-24c32 0x1050 | sudo tee /sys/bus/i2c/devices/i2c-1/new_device

执行完这个后可以在/sys/bus/i2c/devices里面新增这个设备

pq@pq-VirtualBox:/sys/bus/i2c/devices$ ls
1-1050  i2c-0  i2c-1  i2c-2  i2c-3  i2c-4

但是在1-1050里面没有eeprom。

删除这个设备

echo 0x1050 | sudo tee /sys/bus/i2c/devices/i2c-1/delete_device

参考at24.c里面的at24_ids数组,里面字符串"24c32"为关键字。重新添加

echo 24c32 0x50 | sudo tee /sys/bus/i2c/devices/i2c-1/new_device

这时候在1-0050下可以看到eeprom

:/sys/bus/i2c/devices/1-0050$ ls
1-00501  eeprom    name   subsystem                       uevent
driver   modalias  power  supplier:regulator:regulator.0

写数据到EEPROM:

sudo sh -c 'echo "Hello World!" > /sys/bus/i2c/devices/1-0050/eeprom'

读回来保存到bin文件中

sudo cat eeprom >> ~/1.bin

所以对于ssd1306 oled来说,方法虽然类似,不过会出错,需要改源代码中数组ssd1307fb_i2c_id

static const struct i2c_device_id ssd1307fb_i2c_id[] = {{ "ssd1305fb", (kernel_ulong_t)&ssd1307fb_ssd1305_deviceinfo },{ "ssd1306fb", (kernel_ulong_t)&ssd1307fb_ssd1306_deviceinfo },{ "ssd1307fb", (kernel_ulong_t)&ssd1307fb_ssd1307_deviceinfo },{ "ssd1309fb", (kernel_ulong_t)&ssd1307fb_ssd1309_deviceinfo },{ }
};

编译安装新驱动后,新增设备

echo ssd1306fb 0x3c | sudo tee /sys/bus/i2c/devices/i2c-1/new_device

由于ssd1307fb.c里面只实现了设备树的方式匹配I2C,所以需要添加这种方式的方式,否则会出现错误,添加失败。参考at24.c

#include <linux/of_device.h>struct device_node *of_node = dev->of_node;
const struct i2c_device_id *id;id = i2c_match_id(ssd1307fb_i2c_id, to_i2c_client(dev));//par->device_info = device_get_match_data(dev);
if (of_node && of_match_device(ssd1307fb_of_match, dev))par->device_info = of_device_get_match_data(dev);
else if (id)par->device_info = (void *)id->driver_data;
elsepar->device_info =acpi_device_get_match_data(dev);
if(!par->device_info) {dev_err(dev, "failed to get device info\n");goto fb_alloc_error;
}

1.4 验证

 先改变用户组,改完后重启系统

sudo usermod -aG video $USER

写入数据

cat /dev/urandom | sudo tee /dev/fb1 > /dev/null

提示"tee: /dev/fb1: 无效的参数",不知道如何解决。

2. Android ARM上实现

一般arm上实现,需要使用设备树的方式。

2.1 内核配置

除了和X86方式一样的配置,应该还需要打开Framebuffer Console Support.

2.2 修改设备树

在编译内核信息部分,可以找到dts对应的位置

不过文件夹内没有这个board.dts文件

:~/Project/H618-Android12-Src/longan/kernel/linux-5.4/arch/arm64/boot/dts/sunxi$ ls
Makefile  sun50iw10p1.dtsi  sun50iw9.dtsi

在运行soure build/envsetup.sh的提示信息可以看到:

cbd                  -- goto longan/device/config/chips/{ic}/configs/{board} dir

执行命令cbd,进入文件夹/longan/device/config/chips/h618/configs/p2,可以看到文件board.dts。里面的配置信息能对应OrangePi Zero3

	model = "Orange Pi Zero 3";compatible = "allwinner,h616", "arm,sun50iw9p1";

另外,全志SOC对i2c总线命名为twi(n),对于OrangePi Zero3,开放给用户使用的i2c为i2c3

用到的IO口为PH4和PH5,在H618-Android12-Src/longan/device/config/chips/h618/configs/p2/board.dts找到twi3,

&twi3 {clock-frequency = <400000>;pinctrl-0 = <&twi3_pins_a>;pinctrl-1 = <&twi3_pins_b>;pinctrl-names = "default", "sleep";twi_drv_used = <1>;status = "okay";
};

然后再找一下twi3_pins_a,可以对应上板子的信息

    twi3_pins_a: twi3@0 {pins = "PH4", "PH5";function = "twi3";drive-strength = <10>;bias-pull-up;};

在twi3里面添加ssd1306的设备信息:

        ssd1306: oled@3c {compatible = "solomon,ssd1306fb-i2c";reg = <0x3c>;solomon,height = <64>;solomon,width = <128>;};

@3c和reg = <0x3c>表示该oled的i2c地址为0x3c(7位地址)

compatible是关键字,配合ssd1307fb.c中ssd1307fb_of_match数组,当一致时获取后面的属性数组,例如这里的配置和下面的属性是对应的。

{.compatible = "solomon,ssd1306fb-i2c",.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
},

属性width和height表示屏幕的宽和高。 其他属性可以参考代码中的ssd1307fb_probe函数。编译内核烧录后进入系统可以看到多了对应的设备:

console:/sys/bus/i2c/devices/3-003c $ ls
modalias  name  of_node  power  subsystem  uevent  waiting_for_supplier
console:/sys/bus/i2c/devices/3-003c $ cat name
ssd1306fb-i2c

然后设备树中找到disp分支,按照屏幕修改参数

	fb1_format               = <0>;fb1_width                = <128>;fb1_height               = <64>;

2.3 修改权限

修改i2c-3的权限,在文件device/softwinner/apollo/common/system/ueventd.sun50iw9p1.rc中添加:

/dev/i2c-3                  0777    system      system
/dev/fb1                    0770    system      system

不过dev下找不到fd1这个设备,似乎现在android上不支持framebuffer,需要使用drm的方式实现。

3. Android AT24C32支持

内核里面选择NVMe Support(这一步和Linux下不同)

和I2C EEPROMs

然后在设备数twi3里面添加新的从设备

	at24c32: eeprom@50 {status = "okay";compatible = "atmel,24c32";reg = <0x50>;};

此时可以在设备下看到这个设备

console:/ $ ls /sys/bus/i2c/devices/
3-003c  3-0050  5-0036  i2c-3  i2c-5

但是在android端需要通过nvmem读写这个设备

console:/sys/bus/nvmem/devices/3-00500 $ ls
nvmem  of_node  power  subsystem  type  uevent  waiting_for_supplier

添加这个设备的权限,在文件device/softwinner/apollo/common/system/init.sun50iw9p1.rc中的“on post-fs-data”里面添加:

chmod 0644 /sys/bus/nvmem/devices/3-00500/nvmem

相关文章:

  • C++类和对象--高阶
  • 【C++】类与对象【下】
  • “智”造升级:金众诚如何赋能重型机械企业高效项目管理?
  • 【Deepseek 学cuda】CUTLASS: Fast Linear Algebra in CUDA C++
  • 【Python】普通方法、类方法和静态方法的区分
  • Vue百日学习计划Day1-3天详细计划-Gemini版
  • Socket API 核心函数详解
  • 万字解析:Java字符串
  • Three.js知识框架
  • rhel8.1 无法安装应用(提示需要注册系统)
  • 多线程与线程互斥
  • sip协议栈--sip结构分析
  • 一文理解扩散模型(生成式AI模型)(2)
  • 编程的本质, 就是创造工具
  • 架构设计不合理,如何优化系统结构
  • 【Linux】多路转接epoll、Linux高并发I/O多路复用
  • 【Linux】基础指令(Ⅱ)
  • 第十九次博客打卡
  • 可变形卷积简介(Deformable Convolution)
  • vLLM - SamplingParams 参数
  • 钕铁硼永磁材料龙头瞄准人形机器人,正海磁材:已向下游客户完成小批量供货
  • 爱德华多·阿拉纳宣誓就任秘鲁新总理
  • 蚊媒传染病、手足口病……上海疾控发布近期防病提示
  • 特朗普开启第二任期首次外访:中东行主打做生意,不去以色列
  • 中国恒大:清盘人向香港高等法院申请撤回股份转让
  • 外交部:中方愿根据当事方意愿,为化解乌克兰危机发挥建设性作用