|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
14.1 本章导读7 C* V; O% t2 G% d+ D- \& B
本节实验介绍一个完整的 GPIO 驱动,以后在 Linux 中需要处理 GPIO 驱动都可以仿照或+ @$ O! p7 G% H$ g7 b
者移植这个驱动。: ~3 \$ L- w) v2 o9 P/ m
14.1.1 工具4 B2 c2 Z- N: c4 Q
14.1.1.1 硬件工具9 p* w- A- Y3 {0 J4 y' U
1)iTOP4412 开发板
9 ]+ G6 _8 ?) e3 `" m5 G2)U 盘或者 TF 卡* B; m3 M% ?5 G; i
3)PC 机
) a; `- K7 H6 J- o! L- N( H4)串口
4 m) K7 \9 I' s8 f: q14.1.1.2 软件工具- v" o) `( k6 o" L2 c
1)虚拟机 Vmware
6 l% j7 X) x2 j1 D) y, e' f- f/ B2)Ubuntu12.04.28 f1 o4 U" {& I, E& \0 ~5 `5 V; |
3)超级终端(串口助手); [; M* _1 y3 c& Q; ^
4)源码文件夹“leds”
+ b8 R3 ?' \% O2 Z6 \5 B" O/ V4 F14.1.2 预备课程
* @2 t. W: `3 a7 Z' t# v& {/ i实验 12_物理地址虚拟地址8 \) M# G3 V2 f3 ~
实验 13_GPIO 初始化9 w- ~( [, t: h' N4 x6 Z# K
14.1.3 视频资源
3 _. ~* A, `* }% x) Z8 g本节配套视频为“视频 14 LEDS 驱动一”9 D7 m% `' W3 F7 T* I2 d
14.2 学习目标
, W0 F: q) o$ I本章需要学习以下内容:
- }1 q9 {1 a8 I% o$ K( S! oLed 硬件原理简单介绍/ r) Z m# z2 T0 i* L( L' B; W
Led 管脚的调用、赋值以及配置
" u- K+ r/ \% n6 |编写简单应用调用 LED 管脚,并测试' |$ E2 h5 l, n6 k) x# b
14.3 Led 硬件原理简单介绍: Y( ]3 I8 R9 \6 H* p8 m
Led 的电路比较简单,一般是使用三极管搭建一个控制电路。
# H% Q Z2 f- J# z. `如下图所示,是原理图中两个 Led 的控制电路。KP_COL0 和 VDD50_EN 网络控制 Led的通断。
; r, Y/ T# P! d & m, X1 ~' r% X( b
如上图所示。
) A- t' O( u( t6 ^! y. T2 g当 KP_COL0 和 VDD50_EN 网络时高电平的时候,三极管 L9014 的 BE 导通,CE 导通,相当于 5V 的 VSYS 电压加到 1K 和 Led 小灯上,小灯就会亮。( w6 h6 }% s3 Y5 {$ r/ q
当 KP_COL0 和 VDD50_EN 网络时低电平的时候,三极管 L9014 的 BE 会截止,CE 截止,相当于 5V 的 VSYS 电压加到 1K、Led 小灯和一个无限大的电阻上,电流为零,小灯就会灭。
- |7 m$ S' r& I- {. E3 e14.4 Led 管脚的调用、赋值以及配置
; {/ q6 M2 Z" o0 f本节给大家介绍一部分涉及 GPIO 调用、赋值以及配置的函数。+ w3 m, ?7 t3 Q3 [9 Y
14.4.1 GPIO 申请和释放函数
! |3 ~/ M) ], b" D5 {1 W! z想用使用任何一个 GPIO 都必须先申请。* L! @( I/ N* v4 N
在头文件“include/linux/gpio.h”中有 Linux 默认的 GPIO 申请函数,这个头文件是属于嵌入式 Linux 平台,任何一个嵌入式 Linux 内核都可以这么使用。
c0 q' q, Y- T1 p如下图所示,在源码目录中使用命令“vim include/linux/gpio.h”打开该文件。
" J. @% ?1 X% ` . t2 u: c9 ~( C8 Z G
如下图所示,就是本节实验中需要用到的函数 gpio_request。
C. M" B) \7 M! k , ^5 N- s( ~. n! H
如上图所示,简单介绍一下 gpio_request 函数。
: F4 E1 r; C. e/ c$ \4 c5 x: q: ?首先这个函数有一个重要的“检测”功能,就是如果其它地方申请了这个 IO,那么这里就会返回错误,提示已经被占用了,这是 Linux 中的一个标准用法。3 `: F0 ^; V: w9 t7 y# E
gpio_request 函数有两个参数
* A2 v2 _5 ]" u, K$ funsigned gpio,申请的那个 GPIO,一般是 GPIO 对应的宏定义
; I J. z0 T6 w% B- d/ o4 F: u. Uconst char *label,为 GPIO 取个名字,便于阅读 ]3 x3 v8 s' L5 f, Y, Q4 [
如下图所示,和 gpio_request 函数对应的是 gpio_free 函数。
# y' ~% ~- S" n- h* ~ ^% B w![]()
- ~) ^ R% _0 {( q$ r F5 e在调用 gpio_request 函数之后,向系统表明这个 IO 已经被占用了,在卸载驱动的时候一般需要调用 gpio_free 函数将其释放。2 U3 t p5 F2 b$ l2 o
gpio_free 函数的参数比较简单,只有一个 GPIO 参数,使用 GPIO 对应的宏定义即可。
& S8 \# z p9 E/ f如下图所示,还有一个赋值函数 gpio_set_value。
& K/ ~# t% F" ]( [ " y J# R. a2 }! Q. |
在将 GPIO 配置为输出模式之后,还需要给 GPIO 赋值,一般就是高电平和低电平两种。1 b# A& ]2 u* E/ A0 v E% \5 d
两个参数分别为
0 R$ g& l5 e! m, W9 }/ lunsigned gpio,GPIO8 G. v0 O0 h7 s" M$ k9 V" t
int value,高电平 1 和低电平 0。
* R: {. ?6 \1 n6 m T0 E3 b14.4.2 GPIO 配置参数宏定义
, g3 @7 L# s- J1 c/ o. H) m* |' QGPIO 在 Linux 初始化,进行映射之后调用 GPIO 操作函数对 GPIO 宏定义进行操作就是对 GPIO 的操作。8 G, V) a& ]( E1 W3 f; A% _6 c
这个 GPIO 宏定义文件都是由原厂提供,肯定是已经做好的,属于 BSP 板级开发包。+ V; m" ]* t) f9 L7 O4 E7 }4 e
如下图所示,在源码目录中使用命令# J5 T3 d) K6 C, X
“vim arch/ARM/mach-exynos/include/mach/gpio-exynos4.h”打开该文件。1 X5 S3 Y& Z3 x5 t, I' c
![]()
9 c8 `; [/ @/ m如下图所示,可以看到所有的 GPIO 都已经定义了。
8 q: l# m3 d+ F1 Q3 S! i![]()
% M1 \+ S2 J0 U4 q在原理图中查找 KP_COL0、VDD50_EN 网络,最终连接到 4412 上的部分如下图所示。
( p; Q% o1 P$ P8 m* G![]()
: N' Z" o2 f. K9 T( m如上图所示,则两个 Led 的宏定义为 EXYNOS4_GPL2(0),EXYNOS4_GPK1(1)。8 v! r ~; H. t, F5 J
14.4.3 GPIO 配置函数和参数( a1 z7 G! P% [' @& g( B( t
在 Linux 中,对 GPIO 的配置函数以及参数都已经集成到三星板级开发包中。. S+ V: ~0 ?2 K% ?# s
先来看一下配置函数,如下图所示,在源码目录中使用命令# [# @1 S X' K8 r* b2 C' ~$ p
“vim arch/arm/plat-samsung/include/plat/gpio-cfg.h”打开该文件。! I% ^% T4 f& t8 g& ?7 ^
![]()
9 p0 O& f7 O+ h. f( U0 G1 ^1 K如下图所示,s3c_gpio_cfgpin 函数就是本节实验需要的。0 \" Q% r$ w; T5 p0 F
) C7 U% K: u: Z* k5 ?
如上图所示,函数 extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to);7 }$ |6 r+ U5 Q2 n' a. ?' S7 A
一般来说带有 s3cxxx 的函数就是三星平台能够通用的函数。( U) ` W( A6 ^$ C- U; o( b& u9 j
s3c_gpio_cfgpin 管脚配置函数有两个参数7 k1 Z" ?/ I. Q2 \, R
参数 unsigned int pin,管脚
7 G* @# U' E4 d参数 unsigned int to,配置参数。0 s9 e" ^( C- H/ e( ]5 d
再来看一下配置参数,如下图所示,在源码目录中使用命令
' J" v( O- \' T# c“vim arch/arm/plat-samsung/include/plat/gpio-cfg.h”打开该文件,配置参数和函数是在同一个函数中。
5 y& L/ Q8 l" z* W0 C4 c$ S" {& {+ t![]()
4 u+ G9 k8 M! b6 t1 l如下图所示,对于 GPIO 需要将其配置为输出模式,对应 S3C_GPIO_OUTPUT 宏定义。
3 K1 |6 {5 p: P ; Z& d5 E! Y/ G* W# k
14.5 编写简单应用调用 LED 管脚,并测试
2 l9 P5 z0 M ^在前面的 devicenode_linux_module.c 文件上添加代码,首先将文件名devicenode_linux_module.c 改为 leds.c。
" J" \/ [ x$ T7 b3 w6 k& B5 i( x先处理一下编译文件 Makefile,如下图所示,将 devicenode_linux_module 改为leds。0 r$ t+ E3 Z; M
% d6 P+ Y: G! b4 y4 k# o9 b
接着修改 leds.c 文件。- D, S$ u* q% V X5 R) J
首先添加需要的头文件,如下图所示,分别是申请 GPIO、配置函数、配置参数、GPIO宏定义等的头文件。然后将设备节点名称由 hello_ctl123 修改为 hello_ctl
1 C/ e0 T8 z0 }! M! T* a8 | / }( F2 K5 e3 t' y
然后需要修改的就是 probe 函数,一般说来 GPIO 的初始化都是在 probe 中。如下图所示,调用配置函数以及配置函数。- N! n; y% X! Z# s( c3 O: r
/ D2 r+ k- k; p# F# _7 j8 X
然后就是修改一下 ioctl 函数,在 Linux 中对 GPIO 的控制一般是使用 ioctl,虽然 write函数也可以实现类似的功能,但是 ioctl 函数的效率高一些。如下图所示,根据应用传入的参数给 GPIO 赋值。' y" c# G* M3 ?1 J0 m7 w. p
" S/ Q( P& ?6 x& O2 u0 ]/ H
如上图所示,先对于参数做一个简单的判断,然后给 led 赋值。
. g- [; G/ v( h接着再来看一下应用,如下图所示,应用比较简单,调用延时函数,首先将 Led 点亮三秒,然后再灭掉三秒,再点亮。6 \$ {9 Z1 X0 \/ }. N- k3 _% y
- |9 X* d: t) t% A7 r
在 Ubuntu 系统下新建 leds 文件夹,将写好的 leds 和编译脚本拷贝到 leds 文件夹下,使用 Makefile 命令编译驱动,使用
9 k) d, T4 _& C6 @6 Y0 \“arm-none-linux-gnueabi-gcc -o invoke_leds invoke_leds.c -static”命令编译应用。如下图所示
: m) }: G) x V ) Y8 l& t! n/ t3 t, G7 h5 e o! I
将上图中的文件 invoke_leds 和 leds.ko 拷贝到 U 盘。
2 q% Z: i0 l) X! b启动开发板,将 U 盘插入开发板,使用命令“ mount /dev/sda1 /mnt/udisk/”加载 U盘符,' [ t6 m- v4 H9 y
使用命令“ insmod /mnt/udisk/leds.ko ”加载驱动 leds.ko,5 M5 C H% N4 i u6 h( O
使用命令“./mnt/udisk/invoke_leds”运行小应用 invoke_leds,如下图所示。2 u/ g( U/ C) O5 P( C
2 J' P& \7 M0 i6 |- m5 j6 [. M
经过上面的操作可观察到 led 小灯会一亮一灭一亮,中间大概间隔三秒钟。5 I: o+ }& N& v, }$ V
4 l u D3 y% z( i
![]()
5 J4 z+ P H5 r |
|