【RV1126】IIC驱动--EEPROM

news/2024/12/21 21:27:08/

文章目录

  • 原理图查找空闲的I2C
  • EEPROM芯片
  • 改设备树
  • 编写驱动
    • 驱动端
    • 设备端
    • 驱动端和设备端编译成驱动模块
    • 应用层的测试代码

原理图查找空闲的I2C

在这里插入图片描述在这里插入图片描述

由上面可以知道,空闲了I2C4接口,然后也引出来了。
在这里插入图片描述

再找原理图找到具体引脚:

  • I2C4_SCL:GPIO3_A0
  • I2C4_SDA:GPIO3_A1

在这里插入图片描述

EEPROM芯片

我手上这款:

  • 第一行丝印:ATMLH825
  • 第二行丝印:2ECL Y

在这里插入图片描述
由上表可知是256KB的EEPROM。

该EEPROM的IIC地址是0x50

改设备树

kernel/arch/arm/boot/dts/rongpin/rv1126_1109_common.dtsi

&i2c4 {status = "okay";eeprom@50 {status = "okay";compatible = "atmel,at24c256B";reg = <0x50>;};
};

看看顶层设备树kernel/arch/arm/boot/dts/rv1126.dtsi关于I2C4的描述,这里不用改,贴出来看看:

	i2c4: i2c@ff530000 {compatible = "rockchip,rv1126-i2c", "rockchip,rk3399-i2c";reg = <0xff530000 0x1000>;interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;#address-cells = <1>;#size-cells = <0>;clocks = <&cru CLK_I2C4>, <&cru PCLK_I2C4>;clock-names = "i2c", "pclk";pinctrl-names = "default";pinctrl-0 = <&i2c4m0_xfer>;status = "disabled";};

在这里插入图片描述

把EEPROM模块接上板子后,使用I2Cdetect测试工具进行测试:

[root@RV1126_RV1109:/mnt/nfs]# i2cdetect -y 40  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

在地址0x50有响应。

编写驱动

下面使用IIC子系统框架编写EEPROM驱动。驱动端使用杂项设备字符驱动框架。

驱动端

iic_drv.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>static struct i2c_client *eeprom_client;#define MAX_SIZE 255  //EEPROM大小
#define EEPROM_PAGE  16 //页字节大小static u8 eeprom_buff[255];
static int rv1126_open(struct inode *inode, struct file *file)
{printk("rv1126_open-->ok\n");return 0;
}static ssize_t rv1126_read(struct file *file, char __user *buf, size_t size, loff_t *seek)
{	unsigned long err;//判断位置是否超出范围if(*seek+size>MAX_SIZE){size=MAX_SIZE-*seek;}//读取数据i2c_smbus_read_i2c_block_data(eeprom_client,*seek,size,eeprom_buff);err=copy_to_user(buf,eeprom_buff,size);if(err!=0)return -1;*seek+=size;return size;
}static ssize_t rv1126_write(struct file *file, const char __user *buf, size_t size, loff_t *seek)
{size_t write_ok_cnt=0;unsigned long err;int write_byte=0;u8 *write_p=eeprom_buff;err=copy_from_user(eeprom_buff,buf,size);if(err!=0)return -1;//判断位置是否超出范围if(*seek+size>MAX_SIZE){size=MAX_SIZE-*seek;}while(1){if(size>EEPROM_PAGE){write_byte=EEPROM_PAGE;size-=EEPROM_PAGE;}else{write_byte=size;}//写数据i2c_smbus_write_i2c_block_data(eeprom_client,*seek,write_byte,write_p);*seek+=write_byte;write_p+=write_byte;write_ok_cnt+=write_byte;  //记录写成功的字节数//等待写完成msleep(10);if(write_byte==size)break; //写完毕}return write_ok_cnt;
}/*
filp:待操作的设备文件file结构体指针
off:待操作的定位偏移值(可正可负)
whence:待操作的定位起始位置
返回:返回移位后的新文件读、写位置,并且新位置总为正值
定位起始位置SEEK_SET:0,表示文件开头SEEK_CUR:1,表示当前位置SEEK_END:2,表示文件尾
*/
static loff_t rv1126_llseek(struct file *filp, loff_t offset, int whence)
{loff_t newpos = 0;switch(whence){case SEEK_SET:newpos = offset;break;case SEEK_CUR:newpos = filp->f_pos + offset;break;case SEEK_END:if(MAX_SIZE+offset>=MAX_SIZE){newpos=MAX_SIZE;}else{newpos = MAX_SIZE + offset;}break;default:return -EINVAL;//无效的参数}filp->f_pos = newpos;return newpos;
}static int rv1126_release(struct inode *inode, struct file *file)
{printk("rv1126_release-->ok\n");return 0;
}static struct file_operations fops=
{.open=rv1126_open,.read=rv1126_read,.write=rv1126_write,.release=rv1126_release,.llseek=rv1126_llseek
};/*
Linux内核管理驱动---设备号
设备号是一个unsigned int 的变量--32位。
设备号=主设备号+次设备号
*/
static struct miscdevice misc=
{.minor = MISC_DYNAMIC_MINOR,  /*次设备号填255表示自动分配     主设备号固定为10*/.name = "rv1126_eeprom",  /*/dev目录下文件名称*/.fops = &fops, /*文件操作接口*/
};static int rv1126_probe(struct i2c_client *client, const struct i2c_device_id *device_id)
{printk("probe调用成功:%#X\n",client->addr);eeprom_client=client;/*1. 杂项设备的注册函数*/misc_register(&misc);return 0;
}static int rv1126_remove(struct i2c_client *client)
{/*2. 杂项设备的注销函数*/misc_deregister(&misc);printk("remove调用成功.\n");return 0;
}static struct i2c_device_id id_table[]=
{{"eeprom", 0},{}
};
MODULE_DEVICE_TABLE(i2c, id_table);static const struct of_device_id eeprom_of_match[] = {{ .compatible = "atmel,at24c256B" },{ }
};
MODULE_DEVICE_TABLE(of, eeprom_of_match);static struct i2c_driver drv=
{.probe=rv1126_probe,.remove=rv1126_remove,.driver={.name="at24c256B",.of_match_table = of_match_ptr(eeprom_of_match),},.id_table=id_table
};static int __init rv1126_drv_init(void)
{	/*注册IIC驱动端*/i2c_add_driver(&drv);printk("IIC驱动端: 驱动安装成功\n");return 0;
}static void __exit rv1126_drv_cleanup(void)
{/*注销IIC驱动端*/i2c_del_driver(&drv);printk("IIC驱动端: 驱动卸载成功\n");
}module_init(rv1126_drv_init);    /*驱动入口--安装驱动的时候执行*/
module_exit(rv1126_drv_cleanup); /*驱动出口--卸载驱动的时候执行*/MODULE_LICENSE("GPL");  /*设置模块的许可证--GPL*/

设备端

iic_dev.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/gpio.h>static struct i2c_client *i2c_dev=NULL;
static struct i2c_adapter *adap=NULL;
static struct i2c_board_info info=
{.type="rv1126_eeprom",.addr=0x50, /*设备地址*/
};static int __init rv1126_drv_init(void)
{	/*根据总线编号获取是适配器*/adap=i2c_get_adapter(0);/*注册IIC设备端*/i2c_dev=i2c_new_device(adap,&info);printk("IIC设备端: 驱动安装成功\n");return 0;
}static void __exit rv1126_drv_cleanup(void)
{/*注销IIC设备*/i2c_unregister_device(i2c_dev);i2c_put_adapter(adap);printk("IIC设备端: 驱动卸载成功\n");
}module_init(rv1126_drv_init);    /*驱动入口--安装驱动的时候执行*/
module_exit(rv1126_drv_cleanup); /*驱动出口--卸载驱动的时候执行*/MODULE_LICENSE("GPL");  /*设置模块的许可证--GPL*/

驱动端和设备端编译成驱动模块

Makefile

KER_DRI:=/home/liefyuan/rv1126/rp_rv1126_sdk/kernel/# 定义当前目录
PWD:=$(shell pwd)all:make -C $(KER_DRI) M=$(PWD) modulesobj-m += iic_dev.o
obj-m += iic_drv.oclean:rm -rf *.order *o *.symvers *.mod.c *.mod *.ko

会得到:

  • iic_drv.ko
  • iic_dev.ko

应用层的测试代码

app.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>#define EEPROM_DEV "/dev/rv1126_eeprom"int main(int argc,char **argv)
{/*1. 打开设备文件*/int fd=open(EEPROM_DEV,O_RDWR);if(fd<0){printf("%s 设备驱动打开失败.\n",EEPROM_DEV);return 0;}/*3.读写数据*/unsigned char buff[255];int cnt;int i;for(i=0;i<255;i++)buff[i]=i;cnt=write(fd,buff,255);printf("write成功:%d Byte\n",cnt);//偏移文件指针lseek(fd,SEEK_SET,0);unsigned char buff_r[255];cnt=read(fd,buff_r,255);printf("read成功:%d Byte\n",cnt);for(i=0;i<cnt;i++){printf("%d ",buff_r[i]);}printf("\n");return 0;
}

编译:

arm-linux-gnueabihf-gcc app.c

测试记录:

[root@RV1126_RV1109:/mnt/nfs]# insmod iic_dev.ko
[ 6401.060250] IIC设备端: 驱动安装成功
[root@RV1126_RV1109:/mnt/nfs]# insmod iic_drv.ko
[ 6407.774268] probe调用成功:0X50
[root@RV1126_RV1109:/mnt/nfs]# [ 6407.776211] IIC驱动端: 驱动安装成功[root@RV1126_RV1109:/mnt/nfs]# ls /dev/
block            media0              rfkill         v4l-subdev11    video26
bus              media1              rga            v4l-subdev2     video27
char             media2              rtc            v4l-subdev3     video28
console          media3              rtc0           v4l-subdev4     video29
cpu_dma_latency  media4              rv1126_eeprom  v4l-subdev5     video3
disk             mem                 serial         v4l-subdev6     video30
dri              memory_bandwidth    shm            v4l-subdev7     video31
fb0              mmcblk0             snd            v4l-subdev8     video32
fd               mmcblk0boot0        stderr         v4l-subdev9     video33
full             mmcblk0boot1        stdin          vendor_storage  video34
galcore          mmcblk0p1           stdout         video0          video35
gpiochip0        mmcblk0p2           tty            video1          video36
gpiochip1        mmcblk0p3           ttyFIQ0        video10         video37
gpiochip2        mmcblk0p4           ttyS0          video11         video38
gpiochip3        mmcblk0p5           ttyS4          video12         video39
gpiochip4        mmcblk0p6           ttyS5          video13         video4
gpiochip5        mmcblk0p7           ttyUSB0        video14         video40
hidraw0          mmcblk0p8           ttyUSB1        video15         video41
hidraw1          mmcblk0rpmb         ttyUSB2        video16         video42
hwrng            mpp_service         ttyUSB3        video17         video43
i2c-0            network_latency     ubi_ctrl       video18         video44
i2c-1            network_throughput  uhid           video19         video5
i2c-2            null                urandom        video2          video6
i2c-3            pmsg0               usb            video20         video7
i2c-4            ppp                 usb-ffs        video21         video8
iio:device0      ptmx                v4l            video22         video9
input            ptp0                v4l-subdev0    video23         zero
kmsg             pts                 v4l-subdev1    video24         zram0
log              random              v4l-subdev10   video25
[root@RV1126_RV1109:/mnt/nfs]# ./a.out
[ 6453.425909] rv1126_open-->ok
write成功:255 Byte
read成功:255 Byte
255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
[ 6453.77834] rv1126_release-->ok[root@RV1126_RV1109:/mnt/nfs]#

OK!


http://www.ppmy.cn/news/453920.html

相关文章

宽带拨号上网连接错误720

第一步&#xff1a;找到控制面板>>>设备管理器 第二步&#xff1a;找到设备管理器中的网路适配器&#xff0c;把里面的WAN Miniport(ip)&#xff0c;点击&#xff0c;然后点击右键卸载。 第三步&#xff1a;关闭电脑&#xff0c;再开机&#xff0c;就可以了。

win10 宽带拨号上网 无法完成clash代理 解决方法

宽带拨号上网 无法完成clash代理 方法一 改宽带名称 听说改成英文名能解决 宽带连接改为pppoe 结果不行 方法二 改端口 7890端口 pppoe要占用 改为7891端口 完美解决

Ubuntu设置PPPoE拨号上网

在Ubuntu自带的设置里面&#xff0c;只能简单地设置Wi-Fi、有线等连接 1. 打开高级网络配置 若需要设置更多网络连接&#xff0c;可在应用程序菜单->工具中找到“高级网络配置” 或在终端中输入 nm-connection-editor2. 添加配置文件 打开后&#xff0c;点击左下角“…

Ubuntu16.04拨号上网

说明 实验室电脑新装了Ubuntu16.04&#xff0c;桥接模式&#xff0c;发现插了网线&#xff0c;不能上网。 由于主机win11也是拨号上网&#xff0c;所以想到虚拟机里的Ubuntu要想上网也得进行拨号连接。 这里做一个简单的记录&#xff0c;好让自己以后知道怎么解决 建立DSL连接…

宽带拨号上服务器无响应,宽带拨号服务器无响应(图文)

【导读】宽带拨号服务器无响应&#xff0c;下面就是191路由网整理的网络知识百科&#xff0c;来看看吧&#xff01; 大家好&#xff0c;我是191路由器网小编&#xff0c;上述问题将由我为大家讲解。 宽带运营商服务器未响应的原因有&#xff1a; 1、线路接错或者网线接口接触不…

宽带远程服务器无响应,宽带拨号上网服务器无响应是解决方法(图文)

【导读】宽带拨号上网服务器无响应是怎么回事&#xff0c;下面就是191路由网整理的网络知识百科&#xff0c;来看看吧&#xff01; 大家好&#xff0c;我是191路由器网小编&#xff0c;上述问题将由我为大家讲解。 宽带拨号上网服务器无响应的原因&#xff1a; 1、查看线路是否…

连接宽带提示服务器无响应,宽带拨号上网服务器无响应是怎么回事

大家好&#xff0c;我是时间财富网智能客服时间君&#xff0c;上述问题将由我为大家进行解答。 宽带拨号上网服务器无响应的原因&#xff1a; 1、查看线路是否连接正确&#xff0c;路由器的wan口和宽带猫的度lan口连接。 2、如果正确服务器没有反映可能是宽带出现故障&#xff…

你还记得远古时代的拨号上网么?快来了解拨号上网与宽带上网的区别

前言 记得特别小的时候&#xff0c;差不多04年&#xff0c;家里配了第一台大屁股显示器电脑&#xff0c;就像这种 那时还小&#xff0c;每天让父母打开用DVD看个奥特曼就乐的不行了&#xff0c;过了一阵开始流行一些网页游戏&#xff08;记得有个传奇&#xff0c;当时太小了没…