[话题] 【EVB-T335开发板试用体验】5、linux驱动篇:点亮一盏LED灯(中)

[复制链接]

技术员

发表于 2017-4-19 09:41:21   573 查看 0 回复 显示全部楼层 倒序浏览
分享
本帖最后由 jackeyt 于 2017-4-19 09:41 编辑

试用目录:
1、【EVB-T335开发板试用体验】+1开箱上电
2、【EVB-T335开发板试用体验】2、开发环境搭建+踩坑纪录
3、【EVB-T335开发板试用体验】3、建立linux内核source insight工程
4、【EVB-T335开发板试用体验】4、linux驱动篇:点亮一盏LED灯(上)




此贴是【EVB-T335开发板试用体验】的第五篇:Linux驱动篇:点亮一盏LED灯(中)

该系列主要有三篇文章,主要介绍在Linux下如何编写LED(IO)驱动的三种主流方法:
1、使ioremap/unremap实现虚拟地址到物理地址的映射,以实现对芯片物理寄存器的读写操作从而实现IO控制;
2、使用Linux的GPIO库实现对IO的直接操作从而实现LED的亮灭控制;
3、利用平台总线(platform)实现IO操作,该方法易用,移植方法,主推方法。

本篇是该系列的第二篇,主讲如何通过Linux的库函数的方法实现Linux下对IO的操作实现。
主要包括以下内容:

一、硬件部分
(硬件部分原理主要参考上篇文章的描述,这里不再赘述,本篇主要讲软件编写部分)

二、软件部分
1、Linux 下IO分组原理
2、Linux 驱动实现

三、应用层测试程序
1、应用层测试程序实现
2、交叉编译结果与测试


二、软件部分

1、Linux 下IO分组原理

    EVB-T335开发板的板载BSP已经实现了GPIO的底层函数接口,可以直接调用gpio_request,gpio_free,gpio_get_value,gpio_set_value等函数,实现对GPIO接口的申请、释放、设置输出值和获取输入值。由于BSP实现了标准的GPIO接口函数,我们编写的上层驱动无需关注实现的细节,可以直接调用,这样也大大提高了我们开发简单字符设备驱动程序的效率。
   使用GPIO标准函数接口,我们需要知道当前使用板卡的GPIO编号规则。对于AM335X系列的板卡,其将GPIO分为4个组,GPIO0~GPIO3,每个组32个引脚,引脚编号从GPIO0依次递增,引脚编号算法为:
GPIO_PORT_NUM = GPIO_GROUP_NUM*32 +GPIO_SUB_NUM
   其中GPIO_GROUP_NUM为组号(0,1,2,3),GPIO_SUB_NUM为GPIO在这一组中的序号(0,1,2,...,31)。
   根据上述思路,我们可以通过一个宏定义来实现对IO口的预定义以便编程使用。
  1. #define AM335X_GPIO(bank,gpio) (32*(bank)+(gpio)) //define gpio port number
复制代码
       以我们使用LED所在的IO口为例,其所对应的IO口为GPIO3_4,则其对应的GPIO号为:3*32 + 4 =100。


2、Linux 驱动实现
       在上一篇中,我们已经介绍过了现应的Linux驱动框架,这里不再赘述了,接下来,我们使用MISC DEV机制来实现加载我们的驱动进入内核中,其使用方法较为简单,不再需要像字符驱动那么繁琐。    有了之前的基础,看下以下代码就很清晰明了了。
  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/fs.h>
  4. #include <linux/device.h>
  5. #include <linux/gpio.h>
  6. #include <linux/err.h>
  7. #include <linux/types.h>
  8. #include <asm/uaccess.h>
  9. #include <linux/miscdevice.h>
  10. #include <linux/gpio.h>

  11. #define AM335X_GPIO(bank,gpio) (32*(bank)+(gpio)) //define gpio port number
  12. #define REV_DEV_MINOR 250

  13. char kbuf[100];

  14. static ssize_t fop_write(struct file *filp, const char __user *ubuf,
  15.                          size_t count, loff_t *ppos)
  16. {
  17.         if (copy_from_user(kbuf,ubuf,1))
  18.                 {
  19.                 printk("write is error \n");
  20.         }

  21.         switch (kbuf[0])
  22.                 {
  23.                         case '1':
  24.                                         gpio_set_value(AM335X_GPIO(3,4),1);
  25.                                         break;

  26.                         case '0':
  27.                                         gpio_set_value(AM335X_GPIO(3,4),0);
  28.                                         break;

  29.                         default :
  30.                                         break;
  31.         }

  32.         return 0;
  33. }

  34. int fop_open(struct inode *inode, struct file *filp)
  35. {
  36.     printk("success open the file \n");
  37.     return 0;
  38. }

  39. int fop_release(struct inode *inode, struct file *filp)
  40. {
  41.     printk("success close the file \n");
  42.     return 0;
  43. }

  44. static const struct file_operations rev_fops = {
  45.     .owner = THIS_MODULE,
  46.     .write = fop_write,
  47.     .open = fop_open,
  48.     .release = fop_release,
  49. };

  50. static struct miscdevice rev_dev = {
  51.     .minor = REV_DEV_MINOR,
  52.     .name = "rev_dev",
  53.     .fops = &rev_fops,
  54. };

  55. static int __init leds_init(void)
  56. {
  57.     int rc = -1;

  58.     rc = misc_register(&rev_dev);
  59.     if (rc)
  60.         {
  61.         printk("misc rigester is error \n");
  62.     }

  63.     if(gpio_request(AM335X_GPIO(3,16),"rec_gpio"))
  64.         {
  65.         printk("gpio_request is error \n");
  66.         return -EINVAL;
  67.     }
  68.     gpio_direction_output(AM335X_GPIO(3,16),0);

  69.     return 0;
  70. }

  71. static void __exit leds_exit(void)
  72. {
  73.     printk(KERN_INFO "success fress \n");

  74.     gpio_free(AM335X_GPIO(3,16));
  75.        
  76.     misc_deregister(&rev_dev);
  77. }


  78. module_init(leds_init);
  79. module_exit(leds_exit);


  80. MODULE_LICENSE("GPL");

复制代码
三、应用层测试程序
1、应用层测试程序实现

   我们知道,在linux系统下,一切皆文件!    
   并且按照上文所述,我们最终需要通过底层write函数进行实际IO控制。因此,我们的思路大概是:先打开一个设备文件,然后向其写入对应的数据,使其IO输出相应的电平。
  应用程序比较简单,这里不再赘述,大家看看代码就知道了:
   
  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>

  5. #define FILE "/dev/led_module"

  6. int main(void)
  7. {
  8.         int fd = -1;
  9.         fd = open(FILE,O_RDWR);
  10.         if(fd < 0)
  11.         {
  12.                 printf("scanf is error\n");
  13.                 return -1;
  14.         }
  15.         while(1)
  16.         {
  17.                 write(fd,"1",1);
  18.                 printf("led on success\n");
  19.                 sleep(2);
  20.                 write(fd,"0",1);
  21.                 printf("led off success\n");
  22.                 sleep(2);
  23.         }
  24.            close(fd);
  25.         return 0;
  26. }
复制代码
    我们使用上节讲过的Makefile来进行编译管理即可:
  1. KERNEL_DIR :=/home/jackeyt/linux-3.14.43-evbt335

  2. all:
  3.         $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
  4.         
  5. clean:
  6.         rm -rf *.o *.ko *.mod.o *.mod
  7.         
  8. obj-m   +=led_drv.o
复制代码
    可根据实际情况将内核目录以及相应的驱动文件改成实际的。

2、交叉编译结果与测试
   
    将上述文件都放至相同的目录下,输入编译指令进入内核模块编译:
  1. make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
复制代码
      交叉编译应用层程序:
  1. arm-linux-gnueabihf-gcc  -o  led_test  led_test.c
复制代码
      然后,直接在开发板上,执行:
  1. ./led_test
复制代码
   
   便可以观察到开发板上的LED一亮一灭了,同时,串口终端上会输出:




标签:linux LED灯
高级模式
您需要登录后才可以回帖 登录 | 注册

专家问答 查看更多>>
关闭

站长推荐 上一条 /8 下一条

小黑屋|手机版|Archiver| 电子发烧友 ( 粤ICP备14022951号-2 )     

GMT+8, 2017-6-29 11:44 , Processed in 0.120675 second(s), 13 queries , Memcache On.

微信扫描
快速回复 返回顶部 返回列表
-

推荐专区

技术干货集中营

专家问答

用户帮助┃咨询与建议┃版主议事

我的提问

工程师杂谈

工程师创意

工程师职场

论坛电子赛事

社区活动专版

发烧友活动

-

嵌入式论坛

单片机/MCU论坛

FPGA|CPLD|ASIC论坛

DSP论坛

嵌入式系统论坛

-

电源技术论坛

电源技术论坛

-

硬件设计论坛

电路设计论坛

电子元器件论坛

控制|传感

总线技术|接口技术

-

测试测量论坛

LabVIEW论坛

Matlab论坛

测试测量技术专区

仪器仪表技术专区

-

EDA设计论坛

multisim论坛

PCB设计论坛

proteus论坛|仿真论坛

EasyEDA-中国人自已的EDA工具

-

综合技术与应用

电机控制

智能电网

光电及显示

参考设计中心

汽车电子技术论坛

医疗电子论坛

-

开源硬件

DFRobot专区

树莓派论坛

智能硬件论坛

开发快智能硬件开发平台

Intel物联网开发者专区

Waveshare

乐美客SBC专区

Arduino论坛

BeagleBone论坛

机器人论坛

创客神器NanoPi

小钢炮CANNON

比派科技banana pi专区

-

无线通信论坛

无线通信技术专区

天线|RF射频|微波|雷达技术

-

IC设计论坛

芯片测试与失效分析

Mixed Signal/SOC[数模混合芯片设计]

Analog/RF IC设计

设计与制造封装测试

-

个人版区

阿东Verilog技术专版

直流马达驱动电路设计

LabVIEW英雄联盟

特权同学FPGA专区

-

厂商专区

灵动微电子 MM32

盈鹏飞嵌入式

TI论坛

TI Deyisupport社区

芯灵思嵌入式论坛

Tisan

米尔科技

庆科社区

WIZnet技术专区

Cypress技术论坛

飞凌嵌入式

Qualcomm技术论坛

英创嵌入式

机智云GoKit论坛

-

检测技术与质量

电磁兼容(EMC)设计与整改

安规知识论坛

检测与认证

-

消费电子论坛

手机技术论坛

平板电脑/mid论坛

音视/视频/机顶盒论坛

-

电子论坛综合区

聚丰众筹官方社区

新人报道区

聚丰供应链

-

论坛服务区

-

供求信息发布

供需广告

招聘┃求职发布区

电子展览展会专区