文章目录
1.GPIO子系统
1.1GPIO子系统的层次结构
1.2GPIO子系统的API接口
int of_get_named_gpio(struct device_node *np,const char *propname, int index)
功能:根据节点结构体解析gpio编号
参数:
@np:节点指针
@propname:键
@index:索引号
返回值:成功返回gpio的编号,失败返回错误码
int gpio_request(unsigned gpio, const char *label)
功能:申请要使用的gpio
参数:
@gpio:gpio的编号
@label:标签名
返回值:成功返回0,失败返回错误码
int gpio_direction_input(unsigned gpio)
功能:设置gpio的为输入
参数:
@gpio:gpio的编号
返回值:成功返回0,失败返回错误码
int gpio_direction_output(unsigned gpio, int value)
功能:设置gpio的为输出
参数:
@gpio:gpio的编号
@value:默认电平的状态 1高电平 0低电平
返回值:成功返回0,失败返回错误码
int gpio_get_value(unsigned gpio)
功能:读取管脚的值
参数:
@gpio:gpio的编号
返回值:1高电平 0低电平
void gpio_set_value(unsigned gpio, int value)
功能:设置输出电平的值
参数:
@gpio:gpio的编号
@value:1高电平 0低电平
返回值:无
void gpio_free(unsigned gpio)
功能:释放gpio
参数:
@gpio:gpio的编号
返回值:无
1.3GPIO子系统的设备树添加
1.3.1LED的硬件原理图
注:控制器的设备树在Linux内核源码中已经写好了
1.3.2控制器的设备树
//stm32mp151.dtsi
pinctrl: pin-controller@50002000 {
#address-cells = <1>; //子节点地址的个数
#size-cells = <1>; //子节点地址长度的个数
gpioe: gpio@50006000 {
gpio-controller; //空属性,只起到标识作用
#gpio-cells = <2>; //修饰子节点成员的个数
reg = <0x50006000 0x400>;//描述地址
clocks = <&rcc GPIOE>; //时钟
st,bank-name = "GPIOE";
status = "disabled"; //控制器的状态,disabled:控制器没有工作,okay:工作
};
};
&pinctrl {
gpioe: gpio@50006000 {
status = "okay"; //使能控制器
ngpios = <16>; //这一组管脚的个数
gpio-ranges = <&pinctrl 0 64 16>; //管脚的排序
};
};
1.3.3编写自己的设备树
参考内核帮助文档填写自己的设备树。
/home/linux/linux-5.10.61/Documentation/devicetree/bindings/gpio/gpio.txt
myleds{
led1 = <&gpioe 10 0>;
led2 = <&gpiof 10 0>;
led3 = <&gpioe 8 0>;
};
1.4GPIO子系统点灯的实例
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
// myleds{
// led1 = <&gpioe 10 0>;
// led2 = <&gpiof 10 0>;
// led3 = <&gpioe 8 0>;
// };
struct device_node* node;
char* pname[] = {
"led1", "led2", "led3" };
int gpiono[3] = {
0 };
static int __init myleds_init(void)
{
int i, ret;
// 1.获取device_node
node = of_find_node_by_name(NULL, "myleds");
if (node == NULL) {
printk("parse device node error\n");
return -ENODATA;
}
// 2.获取gpio编号
for (i = 0; i < ARRAY_SIZE(gpiono); i++) {
gpiono[i] = of_get_named_gpio(node, pname[i], 0);
if (gpiono[i] < 0) {
printk("get gpio number error\n");
return -EINVAL;
}
// 3.申请要使用的gpio
if ((ret = gpio_request(gpiono[i], NULL)) != 0) {
printk("reqeust gpio error");
return ret;
}
// 4.操作gpio
gpio_direction_output(gpiono[i], 1);