字符设备实现控制led的驱动
来源:互联网 发布:java基础小程序源代码 编辑:程序博客网 时间:2024/05/12 22:49
硬软件环境:s3c2440/linux-2.6.36/busybox-1.18.4/arm-linux-gcc 4.4.3
下面是模块c代码:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/uaccess.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zhanglong");
/*
* 板子上的led1,2,4,8分别对应连在GPF4,5,6,7上
*
*GPFCON ==> 0x56000050
*GPFDAT ==> 0x56000054
*GPFUP ==> 0x56000058
*
*/
#define IO_PHYS 0x56000000
#define GPFCON_OFFSET 0x50
#define GPFDAT_OFFSET 0x54
#define GPFUP_OFFSET 0x58
struct led_device_s {
struct cdev dev;
dev_t no;
short *io_gpfcon; //注意数据类型, 前面因为错误声明为char型指针,造成结果与预期的不同,郁闷了很久.
char *io_gpfdat;
char *io_gpfup;
};
struct led_device_s my_led[4];
ssize_t my_write(struct file *fp, const char __user *buf, size_t count, loff_t *off)
{
struct led_device_s *get = fp->private_data;
unsigned int minor;
minor = MINOR(get->no);
*(get->io_gpfcon) &= ~(3 << ((minor * 2) + 8));
*(get->io_gpfcon) |= (1 << ((minor * 2) + 8));
*(get->io_gpfup) &= ~(1 << (minor + 4));
if((*buf == 0) || (*buf == 48)) {
*(get->io_gpfdat) &= ~(1 << (minor + 4));
} else {
*(get->io_gpfdat) |= (1 << (minor + 4));
}
return 4;
}
ssize_t my_read(struct file *fp, char __user *buf, size_t count, loff_t *off)
{
return 4; //不能返回0, 否则读相关设备时会卡住.
}
int my_open(struct inode *no, struct file *fp)
{
fp->private_data = container_of(no->i_cdev, struct led_device_s, dev);
//printk(" kernel: open.\n");
return 0;
}
int my_release(struct inode *no, struct file *fp)
{
//printk(" kernel: release.\n");
return 0;
}
struct file_operations my_ops = {
.open = my_open,
.release = my_release,
.read = my_read,
.write = my_write,
};
int test_init(void)
{
int ret = 0;
char *virt;
int i;
virt = ioremap(IO_PHYS, SZ_4K);
for (i = 0; i < 4; i ++) {
my_led[i].no = MKDEV(52, i);
cdev_init(&my_led[i].dev, &my_ops);
my_led[i].io_gpfcon = virt + GPFCON_OFFSET;
my_led[i].io_gpfdat = virt + GPFDAT_OFFSET;
my_led[i].io_gpfup = virt + GPFUP_OFFSET;
}
ret = register_chrdev_region(my_led[0].no, 4, "my dev");
if (ret) {
printk(" register device number failed.\n");
return ret;
}
for (i = 0; i < 4; i ++) {
cdev_add(&my_led[i].dev, my_led[i].no, 1);
}
return ret;
}
void test_exit(void)
{
int i ;
for (i = 0; i < 4; i ++) {
cdev_del(&my_led[i].dev);
}
unregister_chrdev_region(my_led[0].no, 4);
}
module_init(test_init);
module_exit(test_exit);
下面是Makefile文件内容
执行make命令后,“insmod test.ko”插入模块。用
echo 1 > led0_node
echo 0 > led0_node
echo 1 > led1_node
echo 0 > led1_node
echo 1 > led2_node
echo 0 > led2_node
echo 1 > led3_node
echo 0 > led3_node
即可使led灭或亮
其中led0_node,led1_node,led2_node,led3_node必须是字符设备文件,主,次设备号分别为(52,0)(52,1)(52,2)(52,3)
led0_node,led1_node,led2_node,led3_node对应的GPF4,5,6,7控制的led
下面是模块c代码:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/uaccess.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zhanglong");
/*
* 板子上的led1,2,4,8分别对应连在GPF4,5,6,7上
*
*GPFCON ==> 0x56000050
*GPFDAT ==> 0x56000054
*GPFUP ==> 0x56000058
*
*/
#define IO_PHYS 0x56000000
#define GPFCON_OFFSET 0x50
#define GPFDAT_OFFSET 0x54
#define GPFUP_OFFSET 0x58
struct led_device_s {
struct cdev dev;
dev_t no;
short *io_gpfcon; //注意数据类型, 前面因为错误声明为char型指针,造成结果与预期的不同,郁闷了很久.
char *io_gpfdat;
char *io_gpfup;
};
struct led_device_s my_led[4];
ssize_t my_write(struct file *fp, const char __user *buf, size_t count, loff_t *off)
{
struct led_device_s *get = fp->private_data;
unsigned int minor;
minor = MINOR(get->no);
*(get->io_gpfcon) &= ~(3 << ((minor * 2) + 8));
*(get->io_gpfcon) |= (1 << ((minor * 2) + 8));
*(get->io_gpfup) &= ~(1 << (minor + 4));
if((*buf == 0) || (*buf == 48)) {
*(get->io_gpfdat) &= ~(1 << (minor + 4));
} else {
*(get->io_gpfdat) |= (1 << (minor + 4));
}
return 4;
}
ssize_t my_read(struct file *fp, char __user *buf, size_t count, loff_t *off)
{
return 4; //不能返回0, 否则读相关设备时会卡住.
}
int my_open(struct inode *no, struct file *fp)
{
fp->private_data = container_of(no->i_cdev, struct led_device_s, dev);
//printk(" kernel: open.\n");
return 0;
}
int my_release(struct inode *no, struct file *fp)
{
//printk(" kernel: release.\n");
return 0;
}
struct file_operations my_ops = {
.open = my_open,
.release = my_release,
.read = my_read,
.write = my_write,
};
int test_init(void)
{
int ret = 0;
char *virt;
int i;
virt = ioremap(IO_PHYS, SZ_4K);
for (i = 0; i < 4; i ++) {
my_led[i].no = MKDEV(52, i);
cdev_init(&my_led[i].dev, &my_ops);
my_led[i].io_gpfcon = virt + GPFCON_OFFSET;
my_led[i].io_gpfdat = virt + GPFDAT_OFFSET;
my_led[i].io_gpfup = virt + GPFUP_OFFSET;
}
ret = register_chrdev_region(my_led[0].no, 4, "my dev");
if (ret) {
printk(" register device number failed.\n");
return ret;
}
for (i = 0; i < 4; i ++) {
cdev_add(&my_led[i].dev, my_led[i].no, 1);
}
return ret;
}
void test_exit(void)
{
int i ;
for (i = 0; i < 4; i ++) {
cdev_del(&my_led[i].dev);
}
unregister_chrdev_region(my_led[0].no, 4);
}
module_init(test_init);
module_exit(test_exit);
下面是Makefile文件内容
#KERNEL = /home/zl/my2440-2.6.13
KERNEL = /media/STUDY/linux/kernel/my2440-2.6.36
#KERNEL = /lib/modules/$(shell uname -r)/build
default:
make -C $(KERNEL) M=$(shell pwd) modules
clean:
make -C $(KERNEL) M=$(shell pwd) modules clean
obj-m += test.o
执行make命令后,“insmod test.ko”插入模块。用
echo 1 > led0_node
echo 0 > led0_node
echo 1 > led1_node
echo 0 > led1_node
echo 1 > led2_node
echo 0 > led2_node
echo 1 > led3_node
echo 0 > led3_node
即可使led灭或亮
其中led0_node,led1_node,led2_node,led3_node必须是字符设备文件,主,次设备号分别为(52,0)(52,1)(52,2)(52,3)
led0_node,led1_node,led2_node,led3_node对应的GPF4,5,6,7控制的led
- 字符设备实现控制led的驱动
- 字符设备实现控制led的驱动
- 字符设备驱动之led灯的控制实验
- 字符设备驱动控制led灯
- LED字符设备驱动
- led字符设备驱动
- 字符设备驱动---Led
- 字符设备驱动应用---LED设备驱动实现
- Tiny6410 简单的LED字符设备驱动
- Tiny6410 简单的LED字符设备驱动
- 基于TQ2440的led字符设备驱动
- 字符设备驱动-LED驱动
- Linux驱动开发-OK6410-LED字符设备驱动实现过程
- 字符设备驱动-----控制mini2440开发板的4个led灯
- 字符设备驱动之LED
- 字符设备驱动点亮led
- 字符设备驱动----LED驱动程序
- Linux 字符设备驱动 LED
- Effective C++ 读书笔记(10)
- 创业者,你为什么这么着急?
- JAXB中各种常见注解小结
- Linux 文件操作汇总
- Spring中事务传播【1】
- 字符设备实现控制led的驱动
- 编程解决智力题之统计正方形
- Spring中事务传播【2】
- 实例:中断的下半部分之三work_queue
- Spring中事务隔离
- 【*笔记本电脑小键盘使用方法教程*】
- Python语言使用备忘
- HDU4003_Find_Metal_Mineral_树形DP分组
- 实例:中断的下半部分之二tasklet