【Linux Device Driver】—(1)—Char Drivers——代码

上一篇文章简单介绍了下几点需要注意的,我今天看了看那本书,发现 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、测试结果

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值