概要:上一篇我们编写了一个非常简单的字符设备框架和一个我们自己写的fops,似乎还是感觉有点索然无味,因此这篇我们搞一个能在现实世界上出现的东西,就是led亮起来
上一篇我们写了一个字符设备的框架,因此我们可以拿过来用:2—linux字符设备进阶篇
1.查看2440原理图,随便找一个led,并找出它的gpio口接在哪里
LED
2.打开s3c2440的芯片手册找出这几个gpio口的配置寄存器
在这里插入图片描述
我们根据这几个寄存器,来对io口进行操作
3.在入口函数进行地址映射
static unsigned long gpfcon; //定义全局变量
static unsigned long gpfdat; //定义全局变量
gpfcon= ioremap(0x56000000, 0x100000);
gpfdat = gpfcon + 1;
在linux中,我们不能直接访问物理地址,而是间接把物理地址映射出来再操作
ioremap(cookie,size)
cookie :映射的物理地址
size :内存大小
老规矩,有映射就有取消映射:
iounmap(gpfcon);
1
在出口函数,取消映射
4.接下来是fops编写:
static struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
};
在open函数里面我们对io口进行配置,在write进行对led的开关led操作
.open()函数
static int led_open(struct inode *inode, struct file *file)
{
*gpfcon &= ~((0x3<<(4*2)) | (0x3<<(5*2)) | (0x3<<(6*2)));
*gpfcon |= ((0x1<<(4*2)) | (0x1<<(5*2)) | (0x1<<(6*2)));
return 0;
}
初始化gpf 4 5 6,配置为输出模式。
.write()函数
static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
int val;
copy_from_user(&val, buf, count);
if (val == 1)
{
*gpfdat &= ~((1<<4) | (1<<5) | (1<<6));
}
else
{
*gpfdat |= (1<<4) | (1<<5) | (1<<6);
}
return 0;
}
当用户空间write的数据val为1时,灯灭。val为0时,灯亮
我们不能直接使用buf,需要用copy_from_user()函数,从用户空间拷贝
copy_from_user(to,from,count);
to : 目的
from:源
count :大小
有从用户空间拷贝,自然就有拷贝到用户空间
copy_to_user(to, from, count)
to:目的
from:源
count:大小 |