android驱动学习-sysfs文件系统设备--LED(3)

本文介绍了一种通过Sysfs文件系统实现LED控制的方法。通过编写Linux内核模块,创建了一个可读写的sysfs属性,允许应用程序通过cat和echo命令控制LED状态。

目的:学习sysfs文件系统,直接在应用层使用cat 和echo命令来控制LED。

 

===============================================

驱动:

C代码  收藏代码
  1. #include <linux/module.h>  
  2. #include <asm/uaccess.h>  
  3. #include <linux/version.h>  
  4. #include <linux/io.h>  
  5. #include <linux/gpio.h>  
  6. #include <plat/gpio-cfg.h>  
  7. #include <mach/regs-gpio.h>  
  8. #include <asm/mach/arch.h>  
  9. #include <linux/kobject.h>  
  10. #include <linux/string.h>  
  11.   
  12. #define GPIO_LED1  S5PV210_GPH1(3)  
  13. struct kobject *kobj;  
  14. const static char *str_ledon = "ledon";  
  15. const static char *str_ledoff= "ledoff";  
  16.   
  17. static ssize_t led_show(struct kobject *kobj, struct kobj_attribute *attr,char *buf )  
  18. {  
  19.     char *s= buf;  
  20.     int len;  
  21.     if(gpio_get_value(GPIO_LED1))  
  22.        s += sprintf(s,"%s\n",str_ledon);  
  23.     else  
  24.       s += sprintf(s,"%s\n",str_ledoff);  
  25.     if (s != buf)  
  26.         *(s-1) = '\n';  
  27.   
  28.     return (s - buf);  
  29. }  
  30. static ssize_t led_store(struct kobject *kobj,struct kobj_attribute *attr,const char* buf, size_t n)  
  31. {  
  32.      
  33.     char *p;  
  34.     int len;  
  35.     p = memchr(buf, '\n', n);  
  36.     len = p ? p - buf : n;   
  37.     printk(KERN_INFO "%s:enter\n",__func__);  
  38.       
  39.     s3c_gpio_cfgpin(GPIO_LED1,S3C_GPIO_OUTPUT  );  
  40.     s3c_gpio_setpull(GPIO_LED1,S3C_GPIO_PULL_UP );  
  41.     if(gpio_request(GPIO_LED1,"led_sysfs")> 0)  
  42.     {  
  43.         if(!strncmp(buf,str_ledon,len ))  
  44.         {  
  45.             printk(KERN_INFO "%s:1\n",__func__);  
  46.             gpio_set_value(GPIO_LED1,0);  
  47.         }  
  48.         else if(!strncmp(buf,str_ledoff,len ))  
  49.         {  
  50.             printk(KERN_INFO "%s:2\n",__func__);  
  51.             gpio_set_value(GPIO_LED1,1);  
  52.         }  
  53.     }  
  54.     else  
  55.        printk(KERN_INFO "%s:3\n",__func__);   
  56.   
  57.     return len ;  
  58. }  
  59. //具体属性参数  
  60. static struct kobj_attribute  kobj_attr ={  
  61.     .attr = {  
  62.         .name =  __stringify(ledstate), //把ledstate转换成字符串  
  63.         .mode = 0666, //表示此属性可读可写  
  64.      },  
  65.     .show = led_show, //对应读  
  66.     .store= led_store, //对应写  
  67.   
  68. };  
  69. //属性数组  
  70. static struct attribute *attr_g[] ={  
  71.     &kobj_attr.attr,  
  72.     NULL,// 必须包含NULL  
  73. };  
  74. //对属性数组的封装。  
  75. static struct attribute_group grp ={  
  76.     .attrs = attr_g,  
  77. };  
  78.       
  79. static int __init led_init(void)  
  80. {  
  81.   
  82.       
  83.     kobj = kobject_create_and_add("led_sysfs",NULL);  
  84.     if(!kobj )  
  85.     {  
  86.         printk(KERN_INFO "kobject don't create \n");  
  87.         return -ENOMEM;  
  88.     }  
  89.    return  sysfs_create_group(kobj, &grp);  
  90.   
  91. }  
  92. static void __exit led_exit(void)  
  93. {  
  94.    printk(KERN_INFO "%s:enter\n",__func__);  
  95.    sysfs_remove_group(kobj, &grp);  
  96.    kobject_del(kobj);  
  97. }  
  98.   
  99.   
  100. module_init(led_init);  
  101. module_exit(led_exit);  
  102. MODULE_LICENSE("GPL");  

 

Makefile:

 

C代码  收藏代码
  1. OBJ = /home/xhy/kernel  
  2.   
  3. all :  
  4.     make -C $(OBJ) M=`pwd` modules  
  5. clean:  
  6.     make -C $(OBJ) M=`pwd` clean  
  7.   
  8. obj-m   += led_sysfs.o  

 --------------------------------------------------

  make后把生成的led_sysfs.ko文件push到小机上,

  adb shell

  insmod led_sysfs.ko

  cd /sys/

C代码  收藏代码
  1. # lsmod  
  2. led_sysfs 1432 0 - Live 0xbf02a000  

 

  cd led_sysfs

 

C代码  收藏代码
  1. # cat ledstate  
  2. ledoff  

 

 

### 3.1 使用adb shell访问sysfs文件系统 在调试Android系统中的LED驱动sysfs接口时,可以通过`adb shell`连接设备并访问`/sys/class/leds/`目录下的LED设备节点。每个LED设备通常对应一个子目录,例如`led_name`,其中包含多个属性文件,如`brightness`、`trigger`和自定义的`hw_pattern`等。 ```bash adb shell cd /sys/class/leds/led_name ls ``` 通过上述命令可以查看当前LED设备支持的sysfs接口文件。例如,可以通过以下命令查看LED的当前亮度值: ```bash cat brightness ``` 也可以通过写入数值来改变LED的亮度: ```bash echo 128 > brightness ``` 如果LED驱动支持硬件模式控制,则可以通过写入特定格式的字符串到`hw_pattern`文件来控制呼吸灯效果: ```bash echo "10 1000 100 1000 10 1000 100 1000" > hw_pattern ``` ### 3.2 使用dmesg查看内核日志 在调试LED驱动时,可以使用`dmesg`命令查看内核日志,以确认驱动程序是否正常工作。例如,当LED设备初始化时,可以通过`printk`在内核模块中打印调试信息: ```bash dmesg | grep -i led ``` 在驱动代码中添加适当的日志输出,可以帮助定位sysfs接口是否被正确创建以及属性操作函数是否被正确调用: ```c pr_info("LED hw_pattern sysfs file created\n"); ``` 这些日志信息将有助于确认驱动程序是否成功注册了sysfs属性文件,并且可以正常响应用户空间的写入操作[^1]。 ### 3.3 使用strace跟踪系统调用 在用户空间调试LED驱动sysfs接口时,可以使用`strace`工具跟踪系统调用。例如,可以使用以下命令跟踪向`hw_pattern`文件写入数据的过程: ```bash strace -f -o led_debug.log sh -c &#39;echo "10 1000 100 1000 10 1000 100 1000" > /sys/class/leds/led_name/hw_pattern&#39; ``` 该命令将生成一个日志文件`led_debug.log`,其中记录了与写入操作相关的系统调用过程。通过分析日志,可以确认写入操作是否成功,以及是否触发了内核空间的属性处理函数[^1]。 ### 3.4 使用sysfsutils工具进行自动化测试 为了简化对sysfs接口的测试过程,可以使用`sysfsutils`工具对sysfs文件进行批量读写操作。该工具可以通过脚本化的方式模拟不同的测试场景,例如: ```bash sudo apt install sysfsutils ``` 配置`/etc/sysfs.conf`文件,添加以下内容以设置LED亮度: ```conf /class/leds/led_name/brightness = 255 ``` 然后运行以下命令应用配置: ```bash sudo sysfsctl -w ``` 通过这种方式,可以验证LED驱动sysfs接口在不同配置下的行为是否符合预期。此外,还可以编写脚本自动测试多个LED属性文件,以确保驱动程序的稳定性和兼容性[^2]。 ### 3.5 使用内核调试器和模块卸载/加载进行调试 在内核模块开发过程中,可以使用`insmod`和`rmmod`命令加载和卸载LED驱动模块,并通过`modinfo`查看模块信息: ```bash modinfo led_module.ko rmmod led_module insmod led_module.ko ``` 通过在模块初始化和退出函数中添加调试信息,可以确认模块是否成功注册LED设备sysfs属性文件: ```c static int __init led_module_init(void) { pr_info("LED module loaded\n"); return 0; } static void __exit led_module_exit(void) { pr_info("LED module unloaded\n"); } ``` 这些调试信息可以通过`dmesg`查看,以确认模块加载和卸载过程是否正常[^2]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值