
我们之前的程序都是对需要的gpio寄存器地址进行映射,从而实现对gpio口的配置,在Linux内核中可以调用某些API接口实现对gpio口的设置,这就是gpio子系统。 可以将设备树下的led节点改为: stm32mp1_led { compatible= "stm32mp1-led"; status= "okay"; reg= <0X50000A28 0X04 /* RCC_MP_AHB4ENSETR */ 0X500020000X04 /* GPIOI_MODER */ 0X500020040X04 /* GPIOI_OTYPER */ 0X500020080X04 /* GPIOI_OSPEEDR */ 0X5000200C0X04 /* GPIOI_PUPDR */ 0X500020180X04 >; /* GPIOI_BSRR */ }; 改为,其中改了个名字,compatible改为”name,led”否则申请不到该设备,reg原来为映射地址,此处改为led-gpio,在gpio子系统中直接设置io信息。 xhy_led{ compatible= "xhy,led"; status= "okay"; led-gpio= <&gpioa 14 GPIO_ACTIVE_LOW>; }; 然后重新编译.dtb文件: make ARCH=armCROSS_COMPILE=arm-none-linux-gnueabihf- dtbs 然后将dts/stm32mp157a-dk1.dtb复制到tftp文件夹中: cp arch/arm/boot/dts/stm32mp157a-dk1.dtb/home/helloxhy/tftp/ -rf 板子重启后可以在超级终端上面查询到修改后的设备树信息: ls /proc/device-tree/ ![]() 接下来写驱动程序: 首先加入子系统需要的头文件: #include <linux/of_gpio.h> 然后把地址映射的指针所有信息删除: /* static void __iomem*MPU_AHB4_PERIPH_RCC_PI; static void __iomem *GPIOI_MODER_PI; static void __iomem *GPIOI_OTYPER_PI; static void __iomem *GPIOI_OSPEEDR_PI; static void __iomem *GPIOI_PUPDR_PI; static void __iomem *GPIOI_BSRR_PI; */ 接下来在设备结构体中添加节点的gpio编号: struct newchrled_dev{ dev_t devid; /* 设备号 */ struct cdev cdev; /* cdev */ struct class *class; /* 类 */ struct device *device; /* 设备 */ int major; /* 主设备号 */ int minor; /* 次设备号 */ struct device_node *nd; /* 在设备结构体中添加设备节点 */ int led_gpio; /* led 所使用的 GPIO 编号 */ }; 然后在led_write中修改对GPIOI_BSRR_PI的操作,改为对设备节点的操作,直接调用API接口gpio_set_value: gpio_set_value(dev->led_gpio, 1); //关闭LED gpio_set_value(dev->led_gpio, 0); //开启LED 接下来对led_init进行修改,不需要做寄存器映射和寄存器操作了,直接在设备树节点上面的信息进行获取然后调用API进行操作就可以了。 首先把映射和寄存器操作全部删除: MPU_AHB4_PERIPH_RCC_PI= of_iomap(newchrled.nd, 0); GPIOI_MODER_PI= of_iomap(newchrled.nd, 1); GPIOI_OTYPER_PI= of_iomap(newchrled.nd, 2); GPIOI_OSPEEDR_PI= of_iomap(newchrled.nd, 3); GPIOI_PUPDR_PI= of_iomap(newchrled.nd, 4); GPIOI_BSRR_PI= of_iomap(newchrled.nd, 5); //2、时钟配置打开对应寄存器的时钟,查阅手册第866页,GPIOA为寄存器的第0位 val= readl(MPU_AHB4_PERIPH_RCC_PI); val&= ~(0X1 << 0); // 清除以前的设置 val|= (0X1 << 0); // 设置新值 writel(val,MPU_AHB4_PERIPH_RCC_PI); /*2、设置GPIOI_MODER_PI寄存器,查阅手册第1072页13.4.1,PA14设置第28、29两个字节。 00:输入模式 01:输出模式 10:复用模式 11:模拟模式 *//* val= readl(GPIOI_MODER_PI); val&= ~(0X3 << 28); // bit0:1清零 val|= (0X1 << 28); // bit0:1设置01 writel(val,GPIOI_MODER_PI); /*3、设置GPIOI_OTYPER_PI寄存器,查阅手册第1072页13.4.2,PA14设置第14字节。 0:推览输出 1:上拉模式 *//* val= readl(GPIOI_OTYPER_PI); val&= ~(0X1 << 14); /* bit0清零,设置为上拉*/ /*writel(val,GPIOI_OTYPER_PI); /*4、设置GPIOI_ OSPEEDR _PI寄存器,查阅手册第1073页13.4.3,PA14设置第28、29两个字节 设置IO口速度: 00 ![]() 01:Medium speed 10:High speed 11:Very high speed *//* val= readl(GPIOI_OSPEEDR_PI); val&= ~(0X3 << 28); /* bit0:1 清零 */ /*val|= (0x2 << 28); /* bit0:1 设置为10*/ /*writel(val,GPIOI_OSPEEDR_PI); /*5、设置GPIOI_ PUPDR寄存器,查阅手册第1073页13.4.4,PA14设置第28、29两个字节。 配置I/O上拉或下拉 00:禁止上拉、下拉 01:上拉 10:下拉 11:保留 */ /*val= readl(GPIOI_PUPDR_PI); val&= ~(0X3 << 28); /* bit0:1 清零*/ /*val|= (0x1 << 28); /*bit0:1 设置为01*/ /*writel(val,GPIOI_PUPDR_PI); /*6、设置GPIOI_ BSRR寄存器,查阅手册第1074页13.4.7,PA14设置第14、30两个字节。 用来设置IO的开关 */ ////val= readl(GPIOI_BSRR_PI); //val|= (0x1 << 14); //writel(val,GPIOI_BSRR_PI); 接下来对设备数进行读取,依然把获取的信息放在.nd中: newchrled.nd =of_find_node_by_path("/xhy_led"); 然后获取设备树的compatible信息"xhy,led": proper= of_find_property(newchrled.nd, "compatible", NULL); 获取status 属性内容"okay": ret =of_property_read_string(newchrled.nd, "status", &str); 原来的程序时获取reg信息,此时已经改为led-gpio,所以此处获取gpio属性<&gpioa 14 GPIO_ACTIVE_LOW>: newchrled.led_gpio =of_get_named_gpio(newchrled.nd, "led-gpio", 0); 获取到led-gpiod 编号和信息,下一步需要调用API使申请到的信息起作用,此处发现一个问题,compatible参数如果不为name,name2格式的话会报错: ret = gpio_request(newchrled.led_gpio,"LED-GPIO"); 然后设备便起作用了,接下来进行操作就可以了: gpio_direction_output(newchrled.led_gpio,1); 另外需要把led_init和led_exit解除映射改为清除gpio: iounmap(MPU_AHB4_PERIPH_RCC_PI); iounmap(GPIOI_MODER_PI); iounmap(GPIOI_OTYPER_PI); iounmap(GPIOI_OSPEEDR_PI); iounmap(GPIOI_PUPDR_PI); iounmap(GPIOI_BSRR_PI);*/ 改为: gpio_free(newchrled.led_gpio); ![]() |
基于STM32MP1和STM32MP2在嵌入式Linux平台上部署有效的安全保护机制
利用STM32MP1和STM32MP2为嵌入式Linux提供有效的安全措施:供当今决策者参考的3条宝贵经验
STM32MP1 WiFi连接
【STM32MP157】从ST官方例程中分析RPMsg-TTY/SDB核间通信的使用方法
【STM32MPU 安全启动】 TF-A BL2 TrustedBoot原理学习
《STM32MPU安全启动》学**结
《STM32MPU安全启动》学习笔记之optee 如何加载CORTEX-M核和使能校验
《STM32MPU安全启动》学习笔记之TF-A BL2校验optee和uboot的流程以及如何使能
《STM32MPU 安全启动》课程学习心得+开启一扇通往嵌入式系统安全领域深处的大门。
《STM32MPU安全启动》 课程学习心得