TA的每日心情 | 怒 2019-11-20 15:22 |
|---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
0 J6 @- N+ p+ F+ r+ u
与前一节添加GPIO Controller的步骤一样,进入虚拟机中的关于SOC的设备树文件目录openrisc-3.1\arch\openrisc\boot\dts添加关于板子上I2C器件的设备描述
. }; c9 \, k# K
- K& Q* J6 t& W9 R
( H u3 t" O6 F
0 n- Z s1 {1 N9 @ open之,在其中加入关于板子上的I2C器件的描述,例如我板子上有个AT24c08,所以我就添加eeprom设备,形式如下:& u: }. L1 g& w6 \, x) o
/ I1 m5 W' {6 F! G' p0 f, b/ c- i2c0: ocores@93000000 {
- compatible = "opencores,i2c-ocores";
- reg = <0x93000000 0x8>;
- interrupts = <5>;
- regstep = <1>;
- clock-frequency = <40000000>;
- #address-cells = <1>;
- #size-cells = <0>;
- eeprom@54 {
- compatible = "at24";
- reg = <0x54>;
- };
- };
|& n* o, C+ q ' ^. Y9 G4 A& x+ \$ ~8 A
至于关于其中编写方法后述。
; x' P( ]6 E& G6 k! h Q; o0 W5 [9 ]# b
然后,在命令行中进入linux源码目录,然后需要配置内核加入上面添加的I2C的总线驱动,这是因为关于这个ipcore的驱动社区上的大虾已经编写好,现在先熟悉和使用,在后面再去详细分析这个总线驱动如何编写。
9 a: r" w) l' \! W; k
4 {4 ?1 [: d3 s) J0 x& u
/ n9 a) A* `+ H0 w% ~/ @6 q6 _! ]/ b1 @% h: w0 _8 V
内核配置,进入General setup项# R. u& v3 \+ j
7 `1 h* \% l" M1 ?6 g
% E# R7 _9 z; Q4 q- X1 @2 O: f# ^" s
0 c* Y- Z9 l- g( _- n( E
将Prompt for development and/or incomplete code/drivers打开) c# U: y) `4 m8 [/ Q: h1 \1 L
+ h+ ~, w$ g q: Z8 f1 g
# ~2 B; b! Q( b+ b4 Z; M. H
5 J# i' j [. g/ ^: M- W Exit后,到Device Drivers项中 J: f7 A$ B* w$ @/ G- K
~; N8 J7 r5 P' G# g3 Y
w8 p! B2 ?" _' i# O4 p3 M
4 e% K; ]% x: x& G 将I2C support选择编入内核中 C. Z! }4 x* ^% Y7 y1 |& F
6 u0 v; a# @- H
" y! q) T8 v) \. v, N- M8 u1 Y9 E* W
进入,将I2C device inteRFace选中编入内核,我们第一个应用层的测试文件就基于内核编写好的设备接口文件来写
- ]& V) `. v5 g6 Y* U" q( L% {7 v. P7 H
d) n, }6 d" Z) ^7 E0 D, p- K9 l1 z( r* `$ Z! s
然后选择I2C Hardware Bus support中
* R- o B$ |* r
9 ` D+ O% t1 i1 _( l+ w
2 N/ b* r$ l9 ~! S+ I- l2 H6 K6 L: f- d; i' b
将OpenCores I2C Controller选择编入内核
! \* g- E" `. G2 y
0 r6 Q2 k. o, r& t Q% `- ]
+ D; k: E7 | Y; [ {& v# t5 C' \- [
好,最后exit出来选择保存,重新make
) d# p: J b# v
8 U( E. G y) M2 Q3 @9 B/ Y
, d" Z: K% q% V* U3 d1 {
0 [/ C; k& m, D) @4 j5 | 之后的步骤按照之前移植linux的步骤一样,生成uImage镜像,然后下载到开发板上面即可。
* o& @ ~0 z2 Q7 B2 X& b: H5 g/ E9 Z% S
然后在boot linux的过程和进入/dev目录下可以看到i2c bus driver和生成设备文件i2c-x7 w8 q: S' u' D- d9 s8 g2 c
5 ^! p+ \; [5 d
% k& l: O+ G) m( |
/ h1 F3 M# V! _) W5 c& x8 e 至此,i2c的总线驱动就添加到内核了。
* a( J. _. l! E! v' v+ W; V/ Q8 Y/ c
根据我自己的理解:! j* i% g. S8 d: A2 w2 u+ b
- m6 F# z2 e( y& R 1.对于i2c controller来说,编写的驱动程序称为总线驱动,例如上面在or1200_soc中添加的i2c控制器ipcore,为之编写的驱动程序就是总线驱动。% I- E' m" G% A; k+ i
: r# b$ F. z/ `% h8 T8 w p5 t 2.对于挂在i2c总线上的slave device来说,为之编写的驱动程序称为设备驱动,例如我板子上挂在这个ipcore上的AT24c08的eeprom。! T' U! Q: I1 P; n% s, c! R, D b
& K$ F2 m9 ~4 h# i$ Q- Q( M7 k! o* Q
3.linux下的i2c子系统中还有一个i2c核心模块来为总线驱动和设备驱动服务,完成注册,删除······功能。
; R9 N7 G" _6 Q4 u1 P& K' T. @! p: C
现在说明一下:在openrisc-3.1\drivers\i2c\busses目录下的i2c-ocores.c文件为soc上添加的i2c controller提供了总线驱动,即在刚才的内核配置中已经选择编入了内核,所以可以略过总线驱动的编写,在下节我们着重分析这个总线驱动。
+ Q* D8 O1 D( f* p' T% M, u+ S c/ ~; @
0 k8 S" T0 X, u, L9 K+ C# D. [: B; R0 i* x" W7 m3 X- ^
现在可以先打开这个文件,里面的comment中就有关于device-tree文件如何加入i2c device描述的说明 B, M& G% y% D- F+ [0 y
% H" d) C! ^- t7 ]7 ?+ b- /*
- * Device tree configuration:
- *
- * Required properties:
- * - compatible : "opencores,i2c-ocores"
- * - reg : bus address start and address range size of device
- * - interrupts : interrupt number
- * - regstep : size of device registers in bytes
- * - clock-frequency : frequency of bus clock in Hz
- *
- * Example:
- *
- * i2c0: ocores@a0000000 {
- * compatible = "opencores,i2c-ocores";
- * reg = <0xa0000000 0x8>;
- * interrupts = <10>;
- *
- * regstep = <1>;
- * clock-frequency = <20000000>;
- *
- * -- Devices connected on this I2C bus get
- * -- defined here; address- and size-cells
- * -- apply to these child devices
- *
- * #address-cells = <1>;
- * #size-cells = <0>;
- *
- * dummy@60 {
- * compatible = "dummy";
- * reg = <60>;
- * };
- * };
- *
- */
$ f6 O* d R' ~% C' C ) G: D: t6 }7 F$ p2 _; _% H
1 M1 P9 q# _) K3 }* r5 u2 H$ x* f3 z1 d$ d$ j7 S
在openrisc-3.1\drivers\i2c目录下的i2c-dev.c文件中,linux为我们提供了虚拟的统一的设备文件接口,如果我们懒得去编写设备驱动程序时,可以利用这个接口直接在应用层上完成对i2c总线的slave device操作。* }* f* k, o" e R6 U& m6 Z
$ z5 J" p2 q# v; o2 X
0 g2 l3 G" v, M" z; W; d' r1 V7 `$ ^. V! D' ^
所以在这一节当中,我们不编写总线驱动和设备驱动,先运用系统提供的文件接口进行操作,具体的代码主要参考hongtao_liu老师提供的代码。( {" Z- u8 `( b
5 z) t1 c: V1 v; `+ R. x, u4 a- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <fcntl.h> // open()
- #include <sys/ioctl.h>
- #include <unistd.h> // read() write() close() usleep()
- #include <linux/types.h>
- #include <linux/i2c.h> // i2c_msg
- #include <linux/i2c-dev.h> // i2c_rdwr_ioctl_data
- #define DEVICE_NAME "/dev/i2c-0"
- #define MAX_MSG 2
- #define EEPROM_ADDR 0x54
- //--------------------------------------------- main -----------------------------------------------------
- int main(){
- int fd;
- int ret;
- struct i2c_rdwr_ioctl_data eeprom_data;
- /* open device file */
- printf("\nstart simple_i2c application test ! \n");
- fd = open(DEVICE_NAME, O_RDWR);
- if (fd == -1){
- printf("open device %s error !\n",DEVICE_NAME);
- }
- else
- printf("open device file successful, fd = %d\n",fd);
- /* set parameter for msg */
- eeprom_data.nmsgs = MAX_MSG;
- eeprom_data.msgs=(struct i2c_msg *)malloc(eeprom_data.nmsgs * sizeof(struct i2c_msg));
- if( !eeprom_data.msgs ){
- printf("malloc error...\n");
- return -1;
- }
- /* timeout & retry */
- ioctl(fd, I2C_TIMEOUT, 1);
- ioctl(fd, I2C_RETRIES, 2);
- /* write data to eeprom */
- eeprom_data.nmsgs = 1;
- (eeprom_data.msgs[0]).len = 2;
- (eeprom_data.msgs[0]).addr = EEPROM_ADDR;
- (eeprom_data.msgs[0]).flags = 0;
- (eeprom_data.msgs[0]).buf = (unsigned char*)malloc(2);
- (eeprom_data.msgs[0]).buf[0] = 0x10;
- (eeprom_data.msgs[0]).buf[1] = 0x50;
- ret = ioctl(fd, I2C_RDWR, (unsigned long)&eeprom_data);
- if(ret < 0){
- printf("ioctl error...\n");
- }
- /* read data from eeprom */
- eeprom_data.nmsgs = 2;
- (eeprom_data.msgs[0]).len = 1;
- (eeprom_data.msgs[0]).addr = EEPROM_ADDR;
- (eeprom_data.msgs[0]).flags = 0;
- (eeprom_data.msgs[0]).buf[0] = 0x10;
- (eeprom_data.msgs[1]).len = 1;
- (eeprom_data.msgs[1]).addr = EEPROM_ADDR;
- (eeprom_data.msgs[1]).flags = I2C_M_RD;
- (eeprom_data.msgs[1]).buf = (unsigned char*)malloc(1);
- (eeprom_data.msgs[1]).buf[0] = 0;
- ret = ioctl(fd, I2C_RDWR, (unsigned long)&eeprom_data);
- if(ret < 0){
- printf("ioctl error...\n");
- }
- printf("buff[0]=%x\n",(eeprom_data.msgs[1]).buf[0]);
- /* close device file */
- ret = close(fd);
- printf ("ret=%d\n",ret);
- printf ("end simple_i2c test...\n");
- /* */
- return 0;
- }
$ j* u: q1 Z! |1 | $ o3 R W( T" f" N! p
8 L9 C) w& u8 X1 D$ o _
% [9 W. Y) i6 ?% }* R$ M ]
2 @* v7 Y1 m& P/ T. I 编写完后在虚拟机上编译,老规矩,在板子上lrz后修改文件属性
. |8 E: |! Z6 f6 e6 }$ f6 a* ^1 ]% Q. r: e& A* l9 R+ w: Y h4 ]
Z8 x. H6 O: S( V2 Q+ A# ~$ Y( L% a# W/ I, {; R; W9 [* A4 A
然后可以多次修改其中写入地址和数据的代码,看看是否能正确读写 r4 p) V3 Q( V$ G. a9 @9 i7 \
9 }* z% `) |% j) N# \7 {! M6 w& u
5 j) ~$ L+ L+ Q9 ~& ]4 p
" M) |" i# p/ e0 e7 O. p& h: H
至此,有时间修改一下这个测试文件成比较实用的文件,下节对这个ipcore的i2c bus driver的分析,即对openrisc-3.1\drivers\i2c\busses目录下的i2c-ocores.c的总线驱动稍作分析,当是学习如何编写总线驱动。% e/ N ^+ X% j+ B, g, B4 i2 I" X" q
|
|