概述
上一篇文章简单介绍了下几点需要注意的,我今天看了看那本书,发现 register_chrdev() 和 unregister_chrdev() 这两个函数即将要退出时代的舞台。。。。。
但是我发现这个家伙要比注册 cdev 这个家伙简单多了。。。。
这里把代码简单的搞一下拉到,主要是实现 LED 灯的全亮和全灭,实现下简单的字符设备,当然还要用到 ioremap 这系列函数!无非就是把 I/O 地址映射到虚拟内存,通过操作这些虚拟内存的地址来操作 LED 的 I/O 内存!!!!!
1、驱动程序
①、tiny6410_led.c
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
MODULE_LICENSE("GPL");
struct class *tiny6410_class;
static int major;
volatile unsigned long *gpkcon0 = NULL;
volatile unsigned long *gpkcon1 = NULL;
volatile unsigned long *gpkdat = NULL;
int led_open(struct inode *inode, struct file *filp)
{
/* LED1 - 4 分别对应GPK4 -7 */
/* 设置LED 引脚为输出引脚 */
*gpkcon0 &= (((0x1) << (4*4)) | ((0x1) << (5*4)) | ((0x1) << (6*4)) | ((0x1) << (7*4)));
/* 对应管脚置高,使LED 全灭 */
*gpkdat |= 0xf0;
return 0;
}
static ssize_t led_write(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
/* LED 全部熄灭或者全部打开 */
int val;
copy_from_user(&val, buf, size);
/* 点灯 */
if(val == 1) {
*gpkdat &= ~((1<<4) | (1<<5) | (1<<6) | (1<<7));
}
/* 灭灯 */
else {
*gpkdat |= ((1<<4) | (1<<5) | (1<<6) | (1<<7));
}
}
static const struct file_operations led_fops =
{
.open = led_open,
.write = led_write,
.owner = THIS_MODULE,
};
static void tiny6410_led_pin_setup(void)
{
gpkcon0 = (volatile unsigned long *)ioremap(0x7F008800, 16);
gpkcon1 = gpkcon0 + 1;
gpkdat = gpkcon0 + 2;
}
static void tiny6410_led_pin_release(void)
{
iounmap(gpkcon0);
iounmap(gpkcon1);
iounmap(gpkdat);
}
static int __init led_init(void)
{
major = register_chrdev(0, "tiny6410_led", &led_fops);
tiny6410_class = class_create(THIS_MODULE, "led_class");
device_create(tiny6410_class, NULL, MKDEV(major, 0), NULL, "tiny6410_led");
tiny6410_led_pin_setup();
return 0;
}
static void __exit led_exit(void)
{
tiny6410_led_pin_release();
unregister_chrdev(major, "tiny6410_led");
device_destroy(tiny6410_class, MKDEV(major, 0));
class_destroy(tiny6410_class);
}
module_init(led_init);
module_exit(led_exit);
②、Makefile
2、测试程序
tiny6410_led_app.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
/* led on
* led off
*/
int main(int argc, char **argv)
{
int fd;
int val = 0;
fd = open("/dev/tiny6410_led", O_RDWR);
if (fd < 0) {
printf("can't open!n");
}
if (argc != 2)
{
printf("Usage :n");
printf("%s <on|off>n", argv[0]);
return 0;
}
if (strcmp(argv[1], "on") == 0)
{
val = 1;
}
else
{
val = 0;
}
write(fd, &val, 4);
return 0;
}
3、测试结果
最后
以上就是忧郁哑铃为你收集整理的【Linux Device Driver】—(1)—Char Drivers——代码的全部内容,希望文章能够帮你解决【Linux Device Driver】—(1)—Char Drivers——代码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复