3401|12

603

帖子

1

TA的资源

纯净的硅(中级)

楼主
 

[BB方案]第三辑——用设备驱动控制LED [复制链接]



其实一直没看到楼主真正的做出些什么。
                                ——楼主

这些小儿科的实验,真真儿体现了楼主这矬货的水平。
                                ——楼主


上一辑,楼主终于实现了一个linux的驱动程序——只不过是个假的。

这一次,楼主要更进一步,利用这个驱动程序,来控制真正的硬件。

本期可能是唯一的一辑没有槽点的吧。

正式开始。

首先要确定一下到底是使用什么硬件……后来楼主终于在破烂堆里找到了一个led,好,就来它啦。

参照手册里下面这两张图,楼主也搭建了测试用的电路,没错一样一样的,楼主用的面包板和它不一样而已,LED的颜色好像也不一样。
好像它用了100欧的电阻,这个楼主实在是没有,于是拿了个470欧的。






恩,没错,用了GPIO44

BBB真的铺垫了很多事情,以至于我控制IO口根本不需要看芯片手册,操作文件就好了:

第一步:向/sys/class/gpio/export写入要控制的GPIO号,这里直接写入44
  1.                 filp = filp_open("/sys/class/gpio/export",O_WRONLY,0);
  2.                 filp->f_op->write(filp, "44", 3, &filp->f_pos);
  3.                 filp_close(filp, NULL);
复制代码
这样就在其目录出现了相应GPIO的目录和文件

第二步:向/sys/class/gpio/gpio44/direction写入相应GPIO的方向

  1.                 filp = filp_open("/sys/class/gpio/gpio44/direction",O_WRONLY,0);
  2.                 filp->f_op->write(filp, "out", 4, &filp->f_pos);
  3.                 filp_close(filp, NULL);
复制代码

第三步就可以写入0和1到/sys/class/gpio/gpio44/value,以控制该pin的输出电平啦。

当然,楼主实现了LED闪动的效果,闪动的频率是可以改变的,所以需要有一个timer

  1.                 init_timer(&this_drv_timer);
  2.                 this_drv_timer.function = timer_handler;
  3.                 this_drv_timer.expires = jiffies + timeout;
  4.                 add_timer(&this_drv_timer);
复制代码

每次timer_handler执行,就会再启动这个timer,
  1. static void timer_handler(unsigned long arg)
  2. {
  3.         init_timer(&this_drv_timer);
  4.         this_drv_timer.function = timer_handler;
  5.         this_drv_timer.expires = jiffies + timeout;
  6.         add_timer(&this_drv_timer);
  7.         {
  8.                 mm_segment_t old_fs;
  9.                 struct file* filp = NULL;
  10.                 char value_str[5];

  11.                 old_fs = get_fs();
  12.                 set_fs(KERNEL_DS);

  13.                 filp = filp_open("/sys/class/gpio/gpio44/value",O_WRONLY,0);
  14.                 sprintf(value_str, "%d", this_pin_v);
  15.                 this_pin_v ^= 1;
  16.                 filp->f_op->write(filp, value_str, 2, &filp->f_pos);
  17.                 filp_close(filp, NULL);

  18.                 set_fs(old_fs);
  19.         }
复制代码

这里楼主并没有实验太多的代码,基本是一次成型,只不过编码途中遇到一些需要说明的事情


首先,操作相关的文件,好像不允许是用库函数fopen以及相关函数了,而是要用filp_open及相关方法。(表问我为什么,我只是跟着学)
其次,操作文件时候,要搞一下get_fs和set_fs。(表问我为什么,我只是个初学者)
再次,操作timer,每次timer到时都会把自己撤下来,所以要在定时函数中重新启动timer以实现定周期。(表问我为什么,我只是抄的代码)
还有,timer是不精确的,所以有时候LED闪动并不均匀,而且会有明显的不适。(表问我为什么,timer不是我做的)
再有,还记得aoti吗,它和fopen一样也是不允许使用的,所以看到我用了simple_strtoul。(表问我为什么,但是我确实隐隐觉得atoi也不能用)
最后,不知道出于什么原因你能看到这里,我很感激,谢谢你,祝福你,May the force be with you。以下是我的整个源码文件。结果不重要,过程才重要。

  1. /* hello.c -- sjtitr */

  2. #include <linux/init.h>
  3. #include <linux/module.h>
  4. #include <linux/moduleparam.h>

  5. #include <linux/kernel.h>  
  6. #include <linux/init.h>  
  7. #include <linux/platform_device.h>  

  8. #include <asm/uaccess.h>
  9. #include <linux/kdev_t.h>
  10. #include <linux/fs.h>

  11. #include <linux/cdev.h>
  12. #include <linux/device.h>
  13. #include <linux/timer.h>

  14. #define THIS_DRV_NAME        "PracticeDriver"


  15. /* ------------------------- fileops --------------------------------- */
  16. #define FIXED_FILE_SIZE        20

  17. int practice_open(struct inode *inode, struct file *filp);
  18. int practice_release(struct inode *inode, struct file *filp);
  19. ssize_t practice_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos);
  20. ssize_t practice_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos);

  21. unsigned char vt_file[FIXED_FILE_SIZE];
  22. unsigned char vt_file_i = 0;

  23. static unsigned int timeout;



  24. int practice_open(struct inode *inode, struct file *filp)
  25. {
  26.         printk(KERN_ERR "FOPS - Open\n");
  27.         return 0;
  28. }

  29. int practice_release(struct inode *inode, struct file *filp)
  30. {
  31.         printk(KERN_ERR "FOPS - Release\n");
  32.         return 0;
  33. }

  34. ssize_t practice_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos)
  35. {
  36.         ssize_t size = (count < FIXED_FILE_SIZE) ? count : FIXED_FILE_SIZE;
  37.         copy_to_user(buffer, vt_file, size);
  38.         printk(KERN_ERR "FOPS - Read %d bytes\n", size);
  39.         return size;
  40. }

  41. ssize_t practice_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos)
  42. {
  43.         ssize_t size = (count < FIXED_FILE_SIZE) ? count : FIXED_FILE_SIZE;
  44.         char *after;
  45.         copy_from_user(vt_file, buffer, size);
  46.         timeout = simple_strtoul(vt_file, &after, 10) / 2;
  47.         printk(KERN_ERR "FOPS - Write %d\n", timeout);
  48.         return size;
  49. }



  50. /* ------------------------- Driver ---------------------------------- */


  51. static struct file_operations this_drv_fops =
  52. {
  53.         .owner                = THIS_MODULE,
  54.         .open                = practice_open,
  55.         .release        = practice_release,
  56.         .read                = practice_read,
  57.         .write                = practice_write,
  58. };

  59. static unsigned int this_dev_t;
  60. static struct class *this_class;

  61. static struct timer_list this_drv_timer;
  62. static unsigned char this_pin_v;


  63. static void timer_handler(unsigned long arg)
  64. {
  65.         init_timer(&this_drv_timer);
  66.         this_drv_timer.function = timer_handler;
  67.         this_drv_timer.expires = jiffies + timeout;
  68.         add_timer(&this_drv_timer);
  69.         {
  70.                 mm_segment_t old_fs;
  71.                 struct file* filp = NULL;
  72.                 char value_str[5];

  73.                 old_fs = get_fs();
  74.                 set_fs(KERNEL_DS);

  75.                 filp = filp_open("/sys/class/gpio/gpio44/value",O_WRONLY,0);
  76.                 sprintf(value_str, "%d", this_pin_v);
  77.                 this_pin_v ^= 1;
  78.                 filp->f_op->write(filp, value_str, 2, &filp->f_pos);
  79.                 filp_close(filp, NULL);

  80.                 set_fs(old_fs);
  81.         }
  82. }


  83. /* ------------------------- Module ---------------------------------- */
  84. MODULE_AUTHOR("sjtitr");
  85. MODULE_LICENSE("Dual BSD/GPL");

  86. static int hello_init(void)
  87. {
  88.         int ret = 0;       
  89.         int major;
  90.        
  91.         printk(KERN_ALERT "Hello!\n");

  92.         if(!ret && (major = register_chrdev(0, THIS_DRV_NAME, &this_drv_fops))<0)  
  93.         {  
  94.                 printk("Failed to register chrdev\n");  
  95.                 ret = 1;  
  96.         }

  97.         if(!ret)
  98.         {
  99.                 this_dev_t = MKDEV(major, 0);

  100.                 printk(KERN_ERR "make driver fs\n");

  101.                 this_class = class_create(THIS_MODULE,THIS_DRV_NAME);
  102.                 if (IS_ERR(this_class))
  103.                 {
  104.                         printk(KERN_ERR "Failed to make driver fs\n");
  105.                         unregister_chrdev(MAJOR(this_dev_t), THIS_DRV_NAME);
  106.                         ret = 1;
  107.                 }
  108.                 else
  109.                 {
  110.                         device_create(this_class, NULL, this_dev_t, NULL, THIS_DRV_NAME"%d", 0);
  111.                 }
  112.         }

  113.         if(!ret)
  114.         {
  115.                 mm_segment_t old_fs;
  116.                 struct file* filp = NULL;
  117.                 char value_str[5];

  118.                 old_fs = get_fs();
  119.                 set_fs(KERNEL_DS);

  120.                 filp = filp_open("/sys/class/gpio/export",O_WRONLY,0);
  121.                 filp->f_op->write(filp, "44", 3, &filp->f_pos);
  122.                 filp_close(filp, NULL);
  123.                 filp = filp_open("/sys/class/gpio/gpio44/direction",O_WRONLY,0);
  124.                 filp->f_op->write(filp, "out", 4, &filp->f_pos);
  125.                 filp_close(filp, NULL);
  126.                 filp = filp_open("/sys/class/gpio/gpio44/value",O_WRONLY,0);
  127.                 sprintf(value_str, "%d", this_pin_v);
  128.                 this_pin_v ^= 1;
  129.                 filp->f_op->write(filp, value_str, 2, &filp->f_pos);
  130.                 filp_close(filp, NULL);

  131.                 set_fs(old_fs);

  132.                 timeout = HZ / 2;
  133.                 init_timer(&this_drv_timer);
  134.                 this_drv_timer.function = timer_handler;
  135.                 this_drv_timer.expires = jiffies + timeout;
  136.                 add_timer(&this_drv_timer);
  137.         }
  138.             return 0;  
  139. }

  140. static void hello_exit(void)
  141. {
  142.         mm_segment_t old_fs;
  143.         struct file* filp = NULL;

  144.         old_fs = get_fs();
  145.         set_fs(KERNEL_DS);

  146.         filp = filp_open("/sys/class/gpio/unexport",O_WRONLY,0);
  147.         filp->f_op->write(filp, "44", 3, &filp->f_pos);
  148.         filp_close(filp, NULL);

  149.         set_fs(old_fs);

  150.         device_destroy(this_class, this_dev_t);
  151.         class_destroy(this_class);
  152.         unregister_chrdev(MAJOR(this_dev_t), THIS_DRV_NAME);  
  153.         printk(KERN_ALERT "Goodbye!\n");
  154. }

  155. module_init(hello_init);
  156. module_exit(hello_exit);
复制代码



最新回复

那个是论坛本身上传代码的一个小bug已经修复 [attach]148626[/attach]   详情 回复 发表于 2014-4-29 10:46

赞赏

1

查看全部赞赏

点赞 关注
 

回复
举报

603

帖子

1

TA的资源

纯净的硅(中级)

沙发
 
最近这代码提交问题很大呀,怎么头文件包含变成了那样?上次也是。
 
 

回复

1560

帖子

24

TA的资源

五彩晶圆(初级)

板凳
 
哈哈,太感谢楼主了。谢谢分享~ 不过论坛的代码编辑功能确实有待改善啊。

点评

嗯,上次修正过看来争取今天能解决好  详情 回复 发表于 2014-4-28 11:04
个人签名这孩子,成熟的象征,理智的典范。
 
 
 

回复

9178

帖子

5

TA的资源

管理员

4
 
lonerzf 发表于 2014-4-28 10:23
哈哈,太感谢楼主了。谢谢分享~ 不过论坛的代码编辑功能确实有待改善啊。

嗯,上次修正过看来争取今天能解决好
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
 
 
 

回复

5979

帖子

8

TA的资源

版主

5
 
这个 这个 图不是BBB哦

点评

懒了懒了,直接从一个什么pdf里截图出来,但是使用的pin口确实一样呢,这个倒是真的。  详情 回复 发表于 2014-4-28 13:12
个人签名生活就是油盐酱醋再加一点糖,快活就是一天到晚乐呵呵的忙
===================================
做一个简单的人,踏实而务实,不沉溺幻想,不庸人自扰
 
 
 

回复

603

帖子

1

TA的资源

纯净的硅(中级)

6
 
chenzhufly 发表于 2014-4-28 13:04
这个 这个 图不是BBB哦

懒了懒了,直接从一个什么pdf里截图出来,但是使用的pin口确实一样呢,这个倒是真的。
 
 
 

回复

1059

帖子

0

TA的资源

纯净的硅(高级)

7
 
难道linux驱动这么容易上手?早知道团一块BB了

点评

字符驱动还好说 块设备的话......  详情 回复 发表于 2014-4-28 17:05
有必要买一块哦,我也是上个星期才买的  详情 回复 发表于 2014-4-28 16:59
个人签名博客:http://www.ysgh.net/
 
 
 

回复

115

帖子

0

TA的资源

一粒金砂(中级)

8
 
嘿嘿,吸收了,赞一个
 
 
 

回复

115

帖子

0

TA的资源

一粒金砂(中级)

9
 
astwyg 发表于 2014-4-28 16:18
难道linux驱动这么容易上手?早知道团一块BB了

有必要买一块哦,我也是上个星期才买的
 
 
 

回复

115

帖子

0

TA的资源

一粒金砂(中级)

10
 
请问楼主你的头文件是空哒?

点评

那个是论坛本身上传代码的一个小bug已经修复 [attachimg]148626[/attachimg]  详情 回复 发表于 2014-4-29 10:46
 
 
 

回复

774

帖子

2

TA的资源

纯净的硅(中级)

11
 
astwyg 发表于 2014-4-28 16:18
难道linux驱动这么容易上手?早知道团一块BB了

字符驱动还好说
块设备的话......
 
 
 

回复

348

帖子

16

TA的资源

纯净的硅(高级)

12
 
好文,要顶,向楼主的专研精神学习。
 
 
 

回复

9178

帖子

5

TA的资源

管理员

13
 
jaccopa 发表于 2014-4-28 17:02
请问楼主你的头文件是空哒?

那个是论坛本身上传代码的一个小bug已经修复




加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表