字符设备实现控制led的驱动
2013-07-10 09:23
232 查看
硬软件环境:s3c2440/linux-2.6.36/busybox-1.18.4/arm-linux-gcc 4.4.3
下面是模块c代码:
下面是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); |
#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 |
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
相关文章推荐
- 控制Windows Mobile的LED之四:多色呼吸LED SN3199的驱动
- 【原创】Tiny6410简单驱动 --- LED控制
- JZ2440通过sysfs控制gpio实现板载LED的控制
- 51单片机做的74HC595驱动控制LED
- 嵌入式驱动之PWM控制LED灯
- 使用input输入子系统实现对tiny6410LED灯的控制
- NodeMCU实现远程控制LED灯
- 树莓派linux驱动学习之LED控制
- 按键控制LED实现启动、停止按钮
- Android驱动入门-Led控制+app+ndk库+底层驱动
- ESP8266-01之NodeMCU(lua)实现远程控制LED灯
- linux字符驱动学习实践1(简单控制LED灯)
- 字符设备驱动控制led灯
- 字符设备驱动应用---LED设备驱动实现
- ALSA --- amixer控制声卡驱动实现Line-in功能
- 外网远程控制LED小灯的实现
- NodeMCU实现远程控制LED灯
- ARM开发板(S3C2440)上LED灯驱动及跑马灯的实现
- Android驱动入门-Led控制+app+ndk库+底层驱动
- 2416开发记录八: platform驱动之LED(字符设备)