EDA365电子论坛网

标题: linux学习之路_or1200下linux简单gpio字符设备驱动(上) [打印本页]

作者: mutougeda    时间: 2021-7-26 13:28
标题: linux学习之路_or1200下linux简单gpio字符设备驱动(上)
# R; T2 m$ B* n
        前几次我们把linux给boot通了,这所谓的移植也只是个名头而且,真正的移植有时间可以去看看\arch\openrisc下的移植代码,强调我现在也是在用而已,按我的理解的话不是真正意义的开发。
; [7 B& _5 K# [9 K9 w  @1 S# ?  [. D9 A' K4 u* o, m; Q+ |
        那就继续先用这吧,好,现在回来《or1200软件环境搭建》的过程来,那时我们在虚拟机cross compile了lrz和lsz文件,这是因为什么,因为现在我们只是boot通了内核,除了UART这个外设之外我们在内核或模块程序中有关于ipcores的驱动,所以,我们想在这个最简单的内核上调试程序的时,至少在网卡调通之前我们能用串口下载程序代码,不幸中的万幸了,基于串口的通信协议来传输文件,而lrz和lsz就是串口的z-mode协议的实现。! i+ y- [+ U( b. d- z% y
$ g  F: I$ U0 R" F! y8 C
        好,既然如此,把lrz和lsz扔到openrisc-3.1\arch\openrisc\support\initramfs\bin目录下0 _8 Q, Y$ a: N, I, ~' a
# M+ \7 N7 q1 u; b

* x! K2 m/ C( Z+ H8 i
  I& `- w8 ^+ f* z; o# }        回到ipcores上面,在opencores的网站上找到simple_gpio这个工程,下载下来。6 X+ P$ j) j2 F& Y5 _3 v; h
* o8 ]8 ~8 D- W. S0 p/ b

0 s8 E6 s7 B. W
& S2 p* i4 I& j: N0 A* f        添加到SOC上,按照我自己做的SOC,地址设置为0x91000000/ F- y8 ?' G2 `, {0 N; y, b# K

+ Q6 a9 g( H6 |! M( z. g6 }
; @; c; }+ M6 r- C9 J5 i
$ O9 ^/ {" `$ C* x8 k        千万千万记得,把板上的LED灯资源绑到GPIO Controller的端口上6 e- S9 G6 D& h' E  [8 O
: `! C" x7 w" q

! x7 M! {& D( L% @7 Y5 S/ m1 }! c( S$ Q! l
        Tcl脚本文件- j/ W- [( z) E9 m9 F# Q
- j( D3 D9 k0 z2 n  ^7 L2 q7 X) Q

' b/ v4 N% b& M7 ?( }  L$ A: |: n) F& W  @0 e( Z6 B+ I2 \
        现在打开openrisc目录下device-tree文件openrisc-3.1\arch\openrisc\boot\dts,
; Z/ w/ E# v- E! Z8 }- F8 Z3 l! }$ b0 F; W6 I. H4 ]

( R# o- \! }, R0 c2 g, W) W
& Y* ~" C, S2 E4 j        把最后关于simple_gpio的设备描述加上去
2 |( \% O! |8 O& E3 _: E" H; g: |; t; K  w( s3 Z  W; `
        然后,按照《or1200移植linux》的过程重新编译linux源码,生成uImage即可。
; \  w1 w) y/ U- [" _5 _  d7 u  e0 U
$ l6 h" Q, F9 K" c        重新download uImage启动之后,可在\bin目录下找到lrz和lsz
2 n3 G1 n6 r' w, S% h
  J9 X6 E8 M; Q) ^
* C9 p# D; B5 V: E1 I0 j0 h
  |' O; `5 A8 W* S9 n8 V) R        当输出lrz的时候会弹出传输文件框2 b8 [2 v+ Q- i3 C
; Y/ |/ o' q! M: g& f$ i8 {& R
  F6 o2 v$ Z% G0 r

3 D+ \/ |7 G4 W1 u2 i( C* f        现在可以随意找个文件测试一下板子的当前设置的baudrate下能不能无错传输。
. K5 b# `: v' F% z& P5 I7 A* x- m' P+ Y9 _* \7 ]/ _- J* b& f
        对了,又想起一件事,上一届来公司的应届的学生,来了十几个,也就是我们这批了,有个兄弟前几天跟我说他辞职回桂林了,然后我就问题辞职你要干嘛,他就说回去跟一个小研发团队做项目创业去~估计3月底就撤了~至于什么项目这里就帮他保密一下了,但是我觉得做出来,推得早的话还蛮有市场的,这里也预祝下小朱能升级到朱总,哪天想起我就把我招过去当小弟就够了~呵呵~~~
9 K+ H& ~3 H. \5 t. d& n8 b5 Q# a
$ V( |( W5 q  l2 G8 U, ^' Q, Y        好,基本步骤就此为止,现在转入到gpio字符驱动代码当中去。8 i* \4 a5 a9 J/ C6 n
9 `$ F4 n( ~' T' a- i
        参考宋宝华老师的《Linux设备驱动开发详解》第6章——字符设备驱动。  U) s# W7 o3 M3 Z6 `3 i( _

! I1 C. F  G8 U) ]2 u" N, O2 W& f8 U$ t6 T9 W
+ s6 J, u1 r$ m2 q& q& O
        根据我自己的理解总结一下编写字符驱动模块的一般步骤:+ o% f! \+ y. m& ?6 ?
8 [; J! ~# E8 v. B0 q6 |
        1.根据自己编程习惯选择包含cdev的自定义结构体或直接使用cdev结构体。4 ]1 F2 u6 P: |2 Q; J8 g+ w8 f

* I4 Q# c* T. h0 M' w4 K7 g8 ~        2.例化file_operations结构体,然后填充文件操作的有关成员函数,并根据自己要求编写有关成员函数操作。0 t; }; J* z" m3 m" z
  W* M  N2 K6 O' Q1 O2 ^
        3.编写模块加载函数,包括io资源申请注册,中断号申请注册,设备号申请注册,内存申请,注册字符设备,
+ ]1 m( g) G2 q' x6 w" k! h
7 s4 R5 L7 A, v5 r        4.编写模块卸装函数,加载模块的逆操作。! S. O. c. d( o: g
1 }1 L( `' x8 ?1 A
        5.封装成2.6内核的驱动设备模型platform机制,包括编写platform_driver模块加载函数和卸装函数,填充platform_driver结构体的probe,remove,suspend,resume等成员,编写各成员函数。
6 p+ M; [5 T7 e, n3 h, _# A; G
        6.编写应用层的测试代码。
. Z1 \! l- S3 P3 U" A- ]! ]  O# v
2 P* n3 ~8 ~/ d; p4 [        好,到资源栏下载我自己编写的simple gpio controller的字符驱动,对照一面的一般步骤一步步看代码' H) U( s; @( E3 R. L" F4 R
7 w/ g' Q( R8 N! W  |% Y
2 b" K' a4 ^  h; Q  N/ a" e1 h1 j% I
; n4 u5 d0 }: F+ h' i/ Y& F
        1.cdev结构体,这里我选择编写包含cdev的自定义结构体
- }* z2 j, t7 @& S. E- O% k! m3 z* o5 Y, n4 F+ v

" h4 T/ Z9 f  R! V- k
! Q$ G4 y( \" W: x% N5 z6 {6 \/ m1 ^        2.file_operations结构体
1 w9 z! V+ j) S0 S* T0 E8 s  ]
7 ?6 U, i" A: O( a, |" k. j        例化file_operations类,gpio controller operation
( ]: Z5 @' {0 A% W. F# W6 A1 E8 A& J' d0 a& g- b, L# p- B9 C

: L3 H4 f  g; {0 }- @1 H( `! D
. x- w5 P/ G7 G" m, n' v. \        编写file_operation成员函数,只实现open和ioctl函数
/ M* |2 _* O; Z* S7 Q! o+ f- O
0 u& Q5 A/ u& `+ F# o     # ^6 u3 `* X: d* Y: O

3 Q; G- A! J6 [; l& n& J        3.模块加载函数& {0 Z' f  S3 n
# A, `; [* v0 l* u- C
        这里说明下,函数大部分流程我放在platform driver的probe函数中实现
6 R) h/ N  q' b- R; b
$ W) j2 ^9 ^/ t& e  U5 z9 ?, j8 y" K$ l' W* A5 ?! d7 u

& d$ \! f, Z6 ~) q. W8 k3 E" H/ U# s3 f9 {* m. F: U
        4.模块卸装函数2 G1 q) x5 V- Q6 R  J1 X+ P9 s) c# h
# o( U. F- D* b+ S  C
        与加载函数相同,流程放在platform driver的remove函数中实现% g2 w+ }! `7 k# z$ g

& L: p; `5 j: Q6 a8 k0 O
$ n1 R9 }# t  E/ _/ Z7 x9 {. V3 N! Z0 g$ H% Y
        5.封装成platform机制
2 x) o8 X4 k/ n$ J. O# U4 X6 V3 O- A! Z
        对于这个步骤,基本上是一个固定的格式,个人理解就是通用的字符设备驱动套进去platform机制,至于这个机制,很多blog都有解释,这里就不详细再说明了,主要是platform_device,platform_driver,bus三者之间的关系,platform_driver有一系列的操作函数,platform_device对设备的属性描述。
$ l- `! m7 E( ^2 @3 ?
3 G$ g4 u8 v# Y& v
! r6 a8 ~0 B+ r; g0 S& S6 r" E& |

3 G2 ^+ L) V; ?( P! [6 c6 J3 X3 }        6.测试文件
( h% q) R. @+ z2 W
' g- ]7 ?+ `4 s/ ^% C  F        在linux应用层去做文件打开、读写、关闭操作相信学C的时候就应该有深刻的理解,这里的我们在驱动上没有实现read和write函数的具体操作,只实现了ioctl的操作,所以测试文件很简单,目的是看到LED灯闪烁的现象,所以只是简单打开设备文件,执行在驱动中定义好的命令而已。! V$ `9 O$ y% Z1 Q# ~6 I( [
1 o4 y& I, F: w

3 ]+ b1 Y9 t- G- C/ ^
8 o  I. |4 }! i- q2 L        至于代码中有少量的注释,或者大家可以自己理解理解,当是自学的过程,主要还是参考宋宝华老师的书,有问题的话留言大家交流交流。
作者: yin123    时间: 2021-7-26 14:50
or1200下linux简单gpio字符设备驱动
作者: xiaogegepcb    时间: 2021-7-26 14:50
or1200下linux简单gpio字符设备驱动
作者: Lindberge4    时间: 2021-7-26 14:51
or1200下linux简单gpio字符设备驱动




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2