s3c2440嵌入式linux系统LED驱动(lab2)
来源:互联网 发布:淘宝店叫什么名字好听 编辑:程序博客网 时间:2024/06/06 12:36
Lab2实验报告
我做这个实验整体过程可以分为两部分,第一部分是自己到处查找资料写的一个demo,dirver和测试程序都是demo,程序比较简单,但是也确实可以实现基本的功能,第二部分就是最终交上来的项目,是受到2.6.29自身led等驱动的启发。在与同学研究的过程中,发现原来kernel本身也是提供了一套自己的LED 驱动,不过没有实现具体的功能,但是给出了设置和读取引脚的关键函数,于是我在这个驱动的基础上,加上了file_operations接口,并按照试验的要求加上了具体的操作led灯的操作。下面分别来讲一下这两套程序。
1. Demo程序
包括demo驱动和demo测试程序两部分
1.1 Demo驱动
(1) 在这个程序里,我首先,定义了操作led的三个端口或者说寄存器,这里主要是参照手册第九章I/O ports.
定义如下:
#define GPBCON (*(volatile unsigned *)0x56000010)
#define GPBDAT (*(volatile unsigned *)0x56000014)
#define GPBUP (*(volatile unsigned *)0x56000018)
(2) 然后针对试验的要求,操作led3和led4,所以我定义了led3和led4对应的GPB7_out和GPB8_out,定义如下:
#define GPB7_out (1<<(7*2)) //LED3 GPBCON
#define GPB8_out (1<<(8*2)) //LED4 GPBCON
这里也是参照手册第九章I/O ports.
GPB7_out对应的GPBCON是[14,15],GPB8_out对应的GPBCON是[16,17]
另外,led等对应的GPBDAT正好是对应的GPBCON位数的一半,即led3对应的是第7位,led4对应的是第8位。
(3) 定义file_operations接口
File_operations接口是驱动和设备文件交互的标准接口,在这里我主要实现了其中的5个函数,定义如下:
struct file_operations GPIO_LED_ctl_ops ={
.open = GPIO_LED_open,
.read = GPIO_LED_read,
.write = GPIO_LED_write,
.ioctl = GPIO_LED_ioctl,
.release = GPIO_LED_release,
};
具体的介绍,稍后再讲,先看一下,module_init和module_exit函数
(4) module_init和module_exit函数
这两个函数分别是驱动加载(insmod)和驱动卸载(rmmod)时调用的
实现如下:
module_init(S3C2410_GPIO_LED_CTL_init);
module_exit(cleanup_GPIO_LED_ctl);
他们调用的函数分别是S3C2410_GPIO_LED_CTL_init和cleanup_GPIO_LED_ctl
S3C2410_GPIO_LED_CTL_init实现如下:
static int __init S3C2410_GPIO_LED_CTL_init(void)
{
int ret = -ENODEV;
ret = GPIO_LED_CTL_init();
if (ret)
return ret;
return 0;
}
GPIO_LED_CTL_init()中主要做了一些初始化的工作
包括初始化
GPBCON = GPB7_out | GPB8_out;
GPBUP = 0x3ff;
GPBDAT = 0x3ff;
以及调用设备注册函数
ret = register_chrdev(GPIO_LED_MAJOR, "gpio_led_ctl", &GPIO_LED_ctl_ops);
(5) 具体对led的控制
其实到目前为止,程序的大体框架就已经差不多了,剩下的就是具体对led的操作,因为在下文讲第二个版本的时候还要将,这里只简要介绍了ioctl
函数定义如下:
static int GPIO_LED_ioctl (struct inode * inode ,struct file * file, unsigned int cmd, unsigned long data){
switch (cmd)
{
case LED_ON : { GPBDAT |=(1<<8); break;}
case LED_OFF: { GPBDAT &=~(1<<8); break;}
default :
{printk ("lcd control : no cmd run [ --kernel-- ]/n"); return (-EINVAL);}
}
return 0;
}
可以看到这里其实就是对led8的亮灭的一个简单控制,按照手册的要求,实现很简单。
1.2 Demo测试程序
(1) 下面讲一下我针对这个Demo driver写的Demo测试程序。程序很简单。主体部分定义如下:
#define DEVICE_NAME "/dev/gpio_led_ctl"
//define LED STATUS
#define LED_ON 0
#define LED_OFF 1
int main(void){
int fd;
int ret;
char *i;
printf("/nstart gpio_led_driver test/n/n");
fd = open(DEVICE_NAME, O_RDWR);
printf("fd = %d/n",fd);
if (fd == -1){
printf("open device %s error/n",DEVICE_NAME);
}
else{
while(1){
ioctl(fd,LED_OFF);
sleep(1);
ioctl(fd,LED_ON);
sleep(1);
}
// close
ret = close(fd);
printf ("ret=%d/n",ret);
printf ("close gpio_led_driver test/n");
}
return 0;
}
(2) 可以看到程序的流程是先通过设备名字打开一个设备,当然设备必须先建立,建立的命令见下文。
然后每隔一秒钟间隔调用ioctl接口,分别传参数LED_OFF和LED_ON这样就可以看到led4灯每隔一秒亮灭一次。
(3) 建立设备,命令很简单,针对我在驱动里面用到的设备号
这里顺便讲一下insmod的过程
首先把生成的led.ko和test载到板子上然后:
insmod led.ko
lsmod
mknod /dev/gpio_led_ctl c 97 1 新建LED的测试设备节点
其中 /dev/gpio_led_ctl 是打开的设备名称,要和测试代码匹配
c代表字符设备
97是主设备好,与驱动程序匹配
1是从设备号 只有一个选1
最后执行./test 会看到板子上 LED交替亮灭 见隔1s
1.3存在的问题
其实这个简单的demo已经包含了led驱动编写的基本内容,不过还是存在不少缺点。第一就是功能不全(这其实没啥,本来就是写的一个demo),第二个是没有加入timer机制用的是sleep进行等待。有了demo的经验,接下来的工作方便很多。
2. 正式驱动
2.1 driver
这个驱动和同学讨论时无意中看到/drivers/leds 下面有一个leds-s3c24xx.c的文件,也就是一个实现好的简单驱动,虽然这个驱动没有做具体的事情,不过却提供了读写的接口,最终的驱动程序也就是在这个系统提供的驱动的基础上改进来的。
(1) 数据定义
static unsigned int led_table[] = {
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,
};
static unsigned int led_cfg_table[] = {
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};
具体的意义上文已经降到,这里不在赘余。
(2) 接口定义
static struct file_operations dev_fops = {
.read = s3c2440_read,
.write = s3c2440_write,
.open = s3c2440_open,
.release = s3c2440_release,};
注意,这里在demo的基础上有所改变,ioctl接口没有实现,对led的操作是直接通过read和write进行的
(3) read函数定义
static ssize_t s3c2440_read(struct file *file, char __user *buf, size_t size, loff_t *offset) {
char value = s3c2410_gpio_getpin(led_table[2]) ? 0 : 1;
return value
}
可以看到这里直接调用了系统提供的s3c2410_gpio_getpin函数接口,注意,参数传的是led_table[2],也就是S3C2410_GPB7,因此,读的是led3的信息。
(4) write函数定义
static ssize_t s3c2440_write(struct file *file, const char __user *buf, size_t size, loff_t *offset) {
char value;
ssize_t ret_val;
ret_val = copy_from_user(&value, buf, sizeof(char)) ? -EFAULT : sizeof(char);
s3c2410_gpio_setpin(led_table[2], value ? 0 : 1);
return ret_val;
}
这里直接调用了系统提供的s3c2410_gpio_setpin函数,led_table[2],也就是S3C2410_GPB7,因此是控制led3亮灭。
,其实这里的s3c2410_gpio_setpin和s3c2410_gpio_getpin函数,如果查看他们对应的源代码的话,就可以发现,其实也就是对读写端口的操作作了一个封装而已。
(5) 定时器的操作
这里的定时器也是参考了/drivers/leds下面的ledtrig-timer.c文件。这个文件中给出了timer的标准使用方法。
在本程序中,首先定了一个500毫秒的延迟。
然后定义了一个timer_list 类型的timer,这是kernel中定义的标准的定时器变量
在模块加载的时候,出了进行驱动相关的设置之外,还可以看到,定时器的操作
setup_timer(&led_timer, s3c2440_timer_fn, 1);
mod_timer(&led_timer, jiffies + msecs_to_jiffies(DELAY));
第一句是绑定timer和timer中断时的处理函数
第二句是设定timer的周期。Jiffies是一个全局变量
s3c2440_timer_fn做的事情也很简单,就是当时钟周期结束时,
调用s3c2410_gpio_setpin(led_table[3], value ? 0 : 1);并且传的参数的值和上次调用时传的参数相反,于是这样就可以实现led4灯的亮灭控制。
2.2 test程序
测试程序很简单,就是可以接收4中输入,on,控制led3亮,off,控制led3灭,s,查看led3当前状态,q,退出程序,逻辑很简单,在此就不多做解释。
3. 遇到的问题
其实在做的过程中,遇到的技术上的问题并不是很多,一是因为gpio端口的操作,张老师已经在课堂上讲了很多,只要认真听课,就不难理解,二是平时实验里搞kernel比较多,驱动编程以前也弄过,所以相关make file的写法,驱动的格式,包括装载,卸载过程等都比较熟悉,所以问题并不大,而且在完成实验的过程中也参照了kernel里led驱动和timer的应用方法,所以并没有遇到瓶颈。而且,这个实验本身也是比较简单的。
但是还是有一个问题耽误了我不少时间。我开发的过程是通过本地的rootfs启动,然后过载nfs server,nfs server在PC机上,程序的开发和编译都是在PC机上,然后通过nfs下载到arm板上。启动和挂载的过程都很正常,但是当我从nfs server上拷贝文件到arm板的时候,发现拷贝非常慢,而且过一会就会死掉,网络连接也连不上了。后来我发现在/usr/bin下面有一个ftpget,用如下的指令
ftpget -u username -p password 10.131.250.73 remote_filename local_filename
这样比较正常,基本不会断网,而且速度也还比较快。可能以后还需要抽时间查一下。
- s3c2440嵌入式linux系统LED驱动(lab2)
- 07-S3C2440驱动学习(一)嵌入式linux字符设备驱动-LED字符设备驱动
- Linux嵌入式系统开发之Led开发---驱动篇
- 嵌入式系统学习——S3C2451之linux驱动led
- s3c2440 led驱动分析
- s3c2440 LED驱动分析
- linux驱动学习笔记(S3C2440的LED驱动)
- 嵌入式linux Led驱动与程序
- s3c2440基于linux的gpio led字符设备驱动实践
- Linux驱动开发之S3C2440按键点亮LED
- s3c2440基于linux的button和led字符设备驱动
- s3c2440基于linux的gpio led字符设备驱动
- Linux驱动开发之S3C2440按键点亮LED
- 特别详细好懂的一篇文章:s3c2440 -linux-LED驱动
- Linux驱动开发之S3C2440按键点亮LED
- s3c2440基于linux的gpio led字符设备驱动实践
- 特别详细好懂的一篇文章:s3c2440 -linux-LED驱动
- S3C2440 Linux驱动移植——LED heartbeat
- flash模板 英文与中文的兼容问题
- 第一章 VSTO简介
- 时间序列形态相似性分析(二):相似性度量的一个应用实例
- Session,ViewState用法基本理论
- 每天学一点flash(68)使用Capabilities 类
- s3c2440嵌入式linux系统LED驱动(lab2)
- 对面向对象的理解
- WPF/Silverlight深度解决方案:(十八)GPU硬件加速下Silverlight超性能动画实现(下)
- ASP.NET页面之间传递值的几种方法
- 文件的创建,删除,编辑
- LED显示屏、LED照明、LED亮化展业生产--深圳利用价格的科技有限公司
- Android如何判断系统语言
- Java的多态性
- oracle10g主机首选身份证明 重新启动数据库:请指定主机和目标数据库身份证明