用设备驱动控制LED
首先要确定一下到底是使用什么硬件……后来楼主终于在破烂堆里找到了一个led,好,就来它啦。
参照手册里下面这两张图,楼主也搭建了测试用的电路,没错一样一样的,楼主用的面包板和它不一样而已,LED的颜色好像也不一样。
好像它用了100欧的电阻,这个楼主实在是没有,于是拿了个470欧的。
恩,没错,用了GPIO44
BBB真的铺垫了很多事情,以至于我控制IO口根本不需要看芯片手册,操作文件就好了:
第一步:向/sys/class/gpio/export写入要控制的GPIO号,这里直接写入44
- filp = filp_open("/sys/class/gpio/export",O_WRONLY,0);
- filp->f_op->write(filp, "44", 3, &filp->f_pos);
- filp_close(filp, NULL);
[color=rgb(51, 102, 153) !important]复制代码
这样就在其目录出现了相应GPIO的目录和文件
第二步:向/sys/class/gpio/gpio44/direction写入相应GPIO的方向
- filp = filp_open("/sys/class/gpio/gpio44/direction",O_WRONLY,0);
- filp->f_op->write(filp, "out", 4, &filp->f_pos);
- filp_close(filp, NULL);
[color=rgb(51, 102, 153) !important]复制代码
第三步就可以写入0和1到/sys/class/gpio/gpio44/value,以控制该pin的输出电平啦。
当然,楼主实现了LED闪动的效果,闪动的频率是可以改变的,所以需要有一个timer
- init_timer(&this_drv_timer);
- this_drv_timer.function = timer_handler;
- this_drv_timer.expires = jiffies + timeout;
- add_timer(&this_drv_timer);
[color=rgb(51, 102, 153) !important]复制代码
每次timer_handler执行,就会再启动这个timer,
- static void timer_handler(unsigned long arg)
- {
- init_timer(&this_drv_timer);
- this_drv_timer.function = timer_handler;
- this_drv_timer.expires = jiffies + timeout;
- add_timer(&this_drv_timer);
- {
- mm_segment_t old_fs;
- struct file* filp = NULL;
- char value_str[5];
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- filp = filp_open("/sys/class/gpio/gpio44/value",O_WRONLY,0);
- sprintf(value_str, "%d", this_pin_v);
- this_pin_v ^= 1;
- filp->f_op->write(filp, value_str, 2, &filp->f_pos);
- filp_close(filp, NULL);
- set_fs(old_fs);
- }
[color=rgb(51, 102, 153) !important]复制代码
这里楼主并没有实验太多的代码,基本是一次成型,只不过编码途中遇到一些需要说明的事情
首先,操作相关的文件,好像不允许是用库函数fopen以及相关函数了,而是要用filp_open及相关方法。(表问我为什么,我只是跟着学)
其次,操作文件时候,要搞一下get_fs和set_fs。(表问我为什么,我只是个初学者)
再次,操作timer,每次timer到时都会把自己撤下来,所以要在定时函数中重新启动timer以实现定周期。(表问我为什么,我只是抄的代码)
还有,timer是不精确的,所以有时候LED闪动并不均匀,而且会有明显的不适。(表问我为什么,timer不是我做的)
再有,还记得aoti吗,它和fopen一样也是不允许使用的,所以看到我用了simple_strtoul。(表问我为什么,但是我确实隐隐觉得atoi也不能用)
最后,不知道出于什么原因你能看到这里,我很感激,谢谢你,祝福你,May the force be with you。以下是我的整个源码文件。结果不重要,过程才重要。
- /* hello.c -- sjtitr */
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/platform_device.h>
- #include <asm/uaccess.h>
- #include <linux/kdev_t.h>
- #include <linux/fs.h>
- #include <linux/cdev.h>
- #include <linux/device.h>
- #include <linux/timer.h>
- #define THIS_DRV_NAME "PracticeDriver"
- /* ------------------------- fileops --------------------------------- */
- #define FIXED_FILE_SIZE 20
- int practice_open(struct inode *inode, struct file *filp);
- int practice_release(struct inode *inode, struct file *filp);
- ssize_t practice_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos);
- ssize_t practice_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos);
- unsigned char vt_file[FIXED_FILE_SIZE];
- unsigned char vt_file_i = 0;
- static unsigned int timeout;
- int practice_open(struct inode *inode, struct file *filp)
- {
- printk(KERN_ERR "FOPS - Open\n");
- return 0;
- }
- int practice_release(struct inode *inode, struct file *filp)
- {
- printk(KERN_ERR "FOPS - Release\n");
- return 0;
- }
- ssize_t practice_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos)
- {
- ssize_t size = (count < FIXED_FILE_SIZE) ? count : FIXED_FILE_SIZE;
- copy_to_user(buffer, vt_file, size);
- printk(KERN_ERR "FOPS - Read %d bytes\n", size);
- return size;
- }
- ssize_t practice_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos)
- {
- ssize_t size = (count < FIXED_FILE_SIZE) ? count : FIXED_FILE_SIZE;
- char *after;
- copy_from_user(vt_file, buffer, size);
- timeout = simple_strtoul(vt_file, &after, 10) / 2;
- printk(KERN_ERR "FOPS - Write %d\n", timeout);
- return size;
- }
- /* ------------------------- Driver ---------------------------------- */
- static struct file_operations this_drv_fops =
- {
- .owner = THIS_MODULE,
- .open = practice_open,
- .release = practice_release,
- .read = practice_read,
- .write = practice_write,
- };
- static unsigned int this_dev_t;
- static struct class *this_class;
- static struct timer_list this_drv_timer;
- static unsigned char this_pin_v;
- static void timer_handler(unsigned long arg)
- {
- init_timer(&this_drv_timer);
- this_drv_timer.function = timer_handler;
- this_drv_timer.expires = jiffies + timeout;
- add_timer(&this_drv_timer);
- {
- mm_segment_t old_fs;
- struct file* filp = NULL;
- char value_str[5];
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- filp = filp_open("/sys/class/gpio/gpio44/value",O_WRONLY,0);
- sprintf(value_str, "%d", this_pin_v);
- this_pin_v ^= 1;
- filp->f_op->write(filp, value_str, 2, &filp->f_pos);
- filp_close(filp, NULL);
- set_fs(old_fs);
- }
- }
- /* ------------------------- Module ---------------------------------- */
- MODULE_AUTHOR("sjtitr");
- MODULE_LICENSE("Dual BSD/GPL");
- static int hello_init(void)
- {
- int ret = 0;
- int major;
-
- printk(KERN_ALERT "Hello!\n");
- if(!ret && (major = register_chrdev(0, THIS_DRV_NAME, &this_drv_fops))<0)
- {
- printk("Failed to register chrdev\n");
- ret = 1;
- }
- if(!ret)
- {
- this_dev_t = MKDEV(major, 0);
- printk(KERN_ERR "make driver fs\n");
- this_class = class_create(THIS_MODULE,THIS_DRV_NAME);
- if (IS_ERR(this_class))
- {
- printk(KERN_ERR "Failed to make driver fs\n");
- unregister_chrdev(MAJOR(this_dev_t), THIS_DRV_NAME);
- ret = 1;
- }
- else
- {
- device_create(this_class, NULL, this_dev_t, NULL, THIS_DRV_NAME"%d", 0);
- }
- }
- if(!ret)
- {
- mm_segment_t old_fs;
- struct file* filp = NULL;
- char value_str[5];
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- filp = filp_open("/sys/class/gpio/export",O_WRONLY,0);
- filp->f_op->write(filp, "44", 3, &filp->f_pos);
- filp_close(filp, NULL);
- filp = filp_open("/sys/class/gpio/gpio44/direction",O_WRONLY,0);
- filp->f_op->write(filp, "out", 4, &filp->f_pos);
- filp_close(filp, NULL);
- filp = filp_open("/sys/class/gpio/gpio44/value",O_WRONLY,0);
- sprintf(value_str, "%d", this_pin_v);
- this_pin_v ^= 1;
- filp->f_op->write(filp, value_str, 2, &filp->f_pos);
- filp_close(filp, NULL);
- set_fs(old_fs);
- timeout = HZ / 2;
- init_timer(&this_drv_timer);
- this_drv_timer.function = timer_handler;
- this_drv_timer.expires = jiffies + timeout;
- add_timer(&this_drv_timer);
- }
- return 0;
- }
- static void hello_exit(void)
- {
- mm_segment_t old_fs;
- struct file* filp = NULL;
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- filp = filp_open("/sys/class/gpio/unexport",O_WRONLY,0);
- filp->f_op->write(filp, "44", 3, &filp->f_pos);
- filp_close(filp, NULL);
- set_fs(old_fs);
- device_destroy(this_class, this_dev_t);
- class_destroy(this_class);
- unregister_chrdev(MAJOR(this_dev_t), THIS_DRV_NAME);
- printk(KERN_ALERT "Goodbye!\n");
- }
- module_init(hello_init);
- module_exit(hello_exit);
[color=rgb(51, 102, 153) !important]复制代码
[color=rgb(51, 102, 153) !important]
|
|