linux编写硬件外设的驱动–LED
在我们的linux驱动编写时, 若是使用了最小核心板/系统板, 这些系统模块通常都有官方的SDK, 将其中的GPIO或其他外设引出.
这样我们可以省去硬件内存映射的步骤, 直接操作其中注册好的设备.
知识点
- 内核态的文件打开/关闭与读写
- 虚拟设备到真实设备的映射, 硬件抽象的实现, 便于移植/修改
- 体验将多个代码文件共同编译成一个ko内核驱动模块
- 使用C语言程序来与用户态的驱动进行交互, 从而控制内核模块
哪里可以找到这些硬件设备
设备文件通常都存储在**/sys/class目录**下

编写LED内核驱动的前置知识
在LED设备的目录下, 有以下分区

其中brightness代表了当前的亮度, 可读可写, 写入要求为字符’1’或’0’.
其中trigger代表了LED的亮灭触发源, 可读可写, 可以通过cat指令来获取可以写入的变量范围.
在终端中通过命令行来控制LED
在终端下, 我们可以通过echo指令来为brightness赋值
echo 1/0 > /sys/class/leds/led0/brightness
实现最简单的C语言LED控制程序
对于我们的C语言程序来说, 这brightness也是一种文件而已, 要对其赋值, 自然要用到
- open函数
- write函数
- read函数(如有必要)
注意: open/write时要在root用户下, 否则没有权限, 导致打开文件失败
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv){
int fd;
char status;
if (argc != 3)
{
printf("Usage: %s <dev> <on | off>\n", argv[0]);
return -1;
}
fd = open(argv[1], O_RDWR);
if(fd == -1){
printf("can not open file %s\r\n", argv[1]);
return -1;
}
if(0 == strcmp(argv[2], "on")){
status = '1';
write(fd, &status, 1);
}else{
status = '0';
write(fd, &status, 1);
}
close(fd);
return 0;
}
编写完成之后, 进行简单的编译
gcc -o led_test led_test.c
如果发现报错: 找不到头文件 <stddef.h> 可以尝试sudo apt-get upgrade一下, 可能是内核更新导致的. 内核版本可通过uname -r指令查看
编译完成后, 就可以直接对其进行操作了

如果没有在root用户或者sudo前缀下直接打开led0, 就会报错无法打开文件

正常写入则不会有报错提示(不过也没有其他消息提示, 建议结合自己的硬件观察效果, 或者加一个read函数)

开始编写LED内核驱动模块
类似地, 我们内核驱动模块的关键点依旧在于file_operation中的成员函数的实现
LED驱动模块 – 本体
#include "linux/module.h"
#include "linux/kernel.h"
#include "linux/init.h"
#include "linux/fs.h"
#include "linux/errno.h"
#include <linux/miscdevice.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#<

最低0.47元/天 解锁文章
3122





