label : 给 gpio 设置个名字。 返回值: 0 , 申请成功;其他值,申请失败。
2 、 gpio_free 函数
作用:如果不使用某个 GPIO 了,那么就可以调用 gpio_free 函数进行释放。
函数原型: void gpio_free(unsigned gpio)
参数: gpio : 要释放的 gpio 标号。
返回值:无。
3 、 gpio_direction_input 函数
作用: 此函数用于设置某个 GPIO 为输入
函数原型:
int gpio\_direction\_input(unsigned gpio)
参数 : gpio : 要设置为输入的 GPIO 标号。
返回值:设置成功返回 0 ; 设置失败返回负值
4 、 gpio_direction_output 函数
作用:此函数用于设置某个 GPIO 为输出,并且设置默认输出值
函数原型:
int gpio\_direction\_output(unsigned gpio, int value)
参数:
gpio : 要设置为输出的 GPIO 标号。
value : GPIO 默认输出值。 返回值:设置成功返回 0 ; 设置失败返回负值
5 、 gpio_get_value 函数
作用: 此函数用于获取某个 GPIO 的值 (0 或 1)
函数原型:
int \_\_gpio\_get\_value(unsigned gpio)
参数:
gpio : 要获取的 GPIO 标号。
返回值:成功返回 GPIO 值,失败返回负值。
6 、 gpio_set_value 函数
作用: 此函数用于设置某个 GPIO 的值 函数原型:
void \_\_gpio\_set\_value(unsigned gpio, int value)
参数: gpio : 要设置的 GPIO 标号。
value : 要设置的值。 返回值:无
7 、 of_get_named_gpio
函数作用: 此函数获取 GPIO 编号,因为 Linux 内核中关于 GPIO 的 API 函数都要使用 GPIO 编 号,此函数会将设备树中类似 <&gpio1 3 GPIO_ACTIVE_LOW> 的属性信息转换为对应的 GPIO 编号,函数原型如下:
int of\_get\_named\_gpio(struct device\_node \*np,const char \*propname,int index)
参数:
np : 设备节点。
propname : 包含要获取 GPIO 信息的属性名。
index : 因为一个属性里面可能包含多个 GPIO ,此参数指定要获取哪个 GPIO 的编号,如果 只有一个 GPIO 信息的话此参数为 0 。
返回值:
成功返回到的 GPIO 编号,失败返回一个负数。
实践课
使用gpio子系统控制蜂鸣器,基本配置文件如下所示:
.
.
.
.
.
.
.
beep_gpio = of\_get\_named\_gpio(test_device_node,"beep\_gpio",0);
if (beep_gpio < 0){
printk("of\_get\_named\_gpio is erron\n");
return -1;
}
printk("beep\_gpio is %d\n",beep_gpio);
ret = gpio\_request(beep_gpio,"beep\_gpio");
if (ret<0)
{
printk("gpio\_request is erron\n");
return -1;
}
gpio\_direction\_output(beep_gpio,1);//引脚配置
ret = misc\_register(&misc_dev);//注册杂项设备
if (ret<0)
{
printk("misc\_register is error\n");
return -1;
}
在杂项设备中,颠覆了以往使用蜂鸣器,而使用gpio子系统控制蜂鸣器。
if (kbuf[0] == 1)
gpio\_set\_value(beep_gpio,1);//open 寄存器操作换成了GPIO子系统的函数
else if (kbuf[0] == 0)
gpio\_set\_value(beep_gpio,0);//close
ioctl接口
unlocked_ioctl 接口
1、什么是 unlocked_ioctl 接口?
unlocked_ioctl 就是 ioctl 接口,但是功能和对应的系统调用均没有发生变化。
2、 unlocked_ioctl 和 read/write 函数有什么相同点和不同点?
相同点:都可以往内核写数据。
不同点: read 函数只能完成读的功能,write 只能完成写的功能。 但是读取大数据的时候效率高。
ioctl 既可以读也可以写。读取大数据的时候效率不高。
3、unlocked_ioctl 接口命令规则。
一共是32位。
第一个分区:0-7,命令的编号,范围是 0-255。
第二个分区:8-15 ,命令的幻数。
第一个分区和第二个分区主要作用是用来区分命令的。编号一样,幻数不能一样。
第三个分区: 16-29 表示传递的数据大小。
第四个分区: 30-31 代表读写的方向。因为ioctl既可以读也可以写。
00 : 表示用户程序和驱动程序没有数据传递
10 : 表示用户程序从驱动里面读数据
01 : 表示用户程序向驱动里面写数据
11 : 先写数据到驱动里面,然后在从驱动里面把数据读出来。(用得不多)
4、 命令的合成宏与分解宏
合成宏:
\_IO(type,nr) : 用来定义没有数据传递的命令
\_IOR(type,nr,size) : 用来定义从驱动中读取数据的命令
\_IOW(type,nr,size) : 用来定义向驱动写入数据的命令
\_IOWR(type,nr,size) :用来定义数据交换类型的命令,先写入数据,再读取数据这类命令。
参数: type : 表示命令组成的魔数,也就是 8~15 位
nr : 表示命令组成的编号,也就是 0~7 位
size : 表示命令组成的参数传递大小,注意这里不是传递数字,而是数据类型,如要传递 4 字节,就可以写成 int
分解宏:
\_IOC\_DIR(nr) 分解命令的方向,也就是上面说 30~31 位的值
\_IOC\_TYPE(nr) 分解命令的魔数,也就是上面说 8~15 位的值
\_IOC\_NR(nr) 分解命令的编号,也就是上面说 0~7 位
\_IOC\_SIZE(nr) 分解命令的复制数据大小,也就是上面说的 16~29 位
参数说明: nr : 要分解的命令
实践课
通过应用层传递参数到驱动层控制硬件io。
驱动层代码:
#define CMD\_TEST0 \_IO('L',0)
#define CMD\_TEST1 \_IO('L',1)
#define CMD\_TEST2 \_IOW('L',2,int)
#define CMD\_TEST3 \_IOW('L',3,int)
#define CMD\_TEST4 \_IOW('L',4,int)
long misc\_ioctl(struct file \*file,unsigned int cmd, unsigned long value)
{
int val;
switch(cmd){
case CMD_TEST0:
printk("LED ON!!!\n");
printk("value is %ld\n",value);
break;
case CMD_TEST1:
printk("LED OFF!!!\n");
printk("value is %ld\n",value);
break;
case CMD_TEST4:
val = 12;
//从驱动中读取数据
if(copy\_to\_user((int \*)value,&val,sizeof(val))!=0)
{
printk("copy to user error\n");
return -1;
}
break;
}
return 0;
}
struct file\_operations misc_fops ={
.owner = THIS_MODULE,
.open = misc_open,
.release = misc_close,
.read = misc_read,
.write = misc_write,
.unlocked_ioctl = misc_ioctl//添加结构体成员
};
应用层代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
## 最后
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。**
**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/8dbb3739827a9fe70d56f8593b9582b3.png)
![img](https://img-blog.csdnimg.cn/img_convert/801530bbf940885f4ff73cc43244bb7b.jpeg)
![img](https://img-blog.csdnimg.cn/img_convert/4103cf92cb8d3fbe903c0d76bcbae3c8.png)
![img](https://img-blog.csdnimg.cn/img_convert/07d11fb7a3f3f7096928d202026d833d.png)
![img](https://img-blog.csdnimg.cn/img_convert/e2498e145a902e12ff860a8ef58e69a2.png)
![img](https://img-blog.csdnimg.cn/img_convert/c36fdf736926922b3d1bf1150e311abf.png)
![](https://img-blog.csdnimg.cn/img_convert/94a3ad5ba675c18180abcdb8c07a174c.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**
[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!
片转存中...(img-KIZM5H9T-1715840791669)]
[外链图片转存中...(img-LSTiNnRt-1715840791669)]
[外链图片转存中...(img-2cGiJLQt-1715840791670)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**
[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!