多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

33_实验三十二_GPIO寄存器与LED硬件

33_实验三十二_GPIO寄存器与LED硬件 实验三十二 GPIO 寄存器与 LED 硬件——一切外设操作的起点对应课件《第8章 GPIO端口》8.1~8.2 节 8.3 节前半Slide 2-26系列说明本系列基于华清远见 FS-MP1ASTM32MP157A开发板对应课件《第8章 GPIO端口》。toychar 是内核里的一块数据本篇开始碰真硬件GPIO。它是所有外设操作的基础——GPIO 的每种行为输入/输出/复用/模拟都由寄存器决定而操作寄存器就是读写特定地址的内存这个等式成立之后一切芯片手册都能读懂了。本篇先立概念与寄存器地图下一篇实验三十三写 LED 驱动两个版本寄存器直控版 自动创建设备文件版点亮板上三颗绿灯。前置实验三十一驱动三件套写法、实验二十四设备文件与主次设备号。一、GPIO 是什么为什么说它是一切硬件操作的基础GPIOGeneral Purpose I/O ports通用输入/输出端口是芯片引脚通过它们输入或输出高低电平。STM32MP157 有176 个 GPIO 引脚分 A~K、Z 共 12 组每组称一个 Port记 GPIOx每组 16 个引脚GPIOK、GPIOZ 各 8 个引脚记Pxy——如 PB2 B 组 2 号。每个引脚有四种工作模式输入、输出、复用给片上外设用、模拟——工作在哪种模式、各模式下的参数全部由寄存器决定。课件 8.1 的推论值得抄在墙上GPIO 的模式靠写寄存器、数据靠读写寄存器——对 GPIO 的操作就是对寄存器的读写其他外设同理每个寄存器分配了一个内存地址——于是控制外设最终等价于读写特定地址的内存单元。芯片手册的一切寄存器描述地址、位域、复位值说的都是这件事。二、七个寄存器GPIO 的控制面板8.2每组 GPIOA~K、Z有自己的一套寄存器各组长得一样——4 个配置、2 个数据、1 个置位/复位外加杂项寄存器全名干什么GPIOx_MODERport mode register引脚功能00 输入 / 01 输出 / 10 复用 / 11 模拟GPIOx_OTYPERoutput type register输出类型0 推挽 / 1 开漏GPIOx_OSPEEDRoutput speed register输出速度上限低/中/高/极高GPIOx_PUPDRpull-up/pull-down register内部上拉/下拉00 无 / 01 上拉 / 10 下拉GPIOx_IDRinput data register输入数据只读GPIOx_ODRoutput data register输出数据读写GPIOx_BSRRbit set/reset register原子置位/复位 ODR写 1 生效每个引脚在寄存器里占位的方式有规律MODER/OSPEEDR/PUPDR 是每引脚 2 位4 种状态引脚 y 占 bit 2y1:2yOTYPER/IDR/ODR/BSRR 是每引脚 1 位——所以配置 PZ5 时动的是 bit11:102 位组控制 PZ5 电平时动的是 bit51 位组。记住这个换算下面看每只寄存器的芯片手册截图图课件 Slide 6——GPIOx_MODERAddress offset 0x00Reset 0xFFFF FFFFMODER15[1:0]~MODER0[1:0] 每引脚两位00 Input / 01 General purpose output / 10 Alternate function / 11 Analog。图课件 Slide 7——GPIOx_OTYPERoffset 0x04bit15~0 每引脚一位0 Output push-pull推挽复位值/ 1 Output open-drain开漏。推挽与开漏OTYPER 的两个选项电路图看一眼就懂图课件 Slide 8——推挽输出两只互补 MOS 管串联上管 P 接 VDD、下管 N 接地输入高时上管导通输出高、输入低时下管导通输出低——两个方向都推得动驱动能力强是我们点亮 LED 的选择。图课件 Slide 8——开漏输出片内只有一只漏极开路的 N-MOS 管接地输出高需要片外上拉电阻接 Vcc——“只能拉低、放开靠上拉”。多设备共线I2C 总线就靠它实现线与F-2 改 U-Boot 的 SD 卡 CD 引脚时GPIO_PULL_UP的上拉、F-1 电源节点里的开漏概念在这里见到电路本体。图课件 Slide 9——GPIOx_OSPEEDRoffset 0x0800 Low / 01 Medium / 10 High / 11 Very high——上限速度选型与 VDD 范围、外部负载有关点 LED 随便选抓高速信号才讲究。图课件 Slide 10——GPIOx_PUPDRoffset 0x0C00 无 / 01 上拉 / 10 下拉 / 11 保留——F-2 里 SD 卡 CD 引脚上拉 低有效的软件写法对应的就是这里的硬件位。一张全景图把七个寄存器的关系连起来图课件 Slide 11——芯片手册 Figure 119《I/O 端口位的基本结构》左侧 BSRR/ODR/IDR 三个寄存器与复用功能输入/输出通路右侧输入驱动施密特触发器与输出驱动Output control P-MOS/N-MOS 对管推挽/开漏/禁用引脚带保护二极管与可开关的上拉/下拉电阻。一张图看完配置怎么起作用。图课件 Slide 12——GPIOx_IDRoffset 0x10Reset 0x0000 XXXX——引脚当前电平不定。图课件 Slide 12——IDR 位表bit15~0 只读存放对应引脚的输入值输出模式下读它得到引脚当前电平。图课件 Slide 13——GPIOx_ODRoffset 0x14bit15~0 读写注释说明原子置位/复位请走 BSRR/BRR——这正是下面 BSRR 的存在意义。图课件 Slide 14——BSRR 位说明bit31~16 为 BR15~0写 1 复位对应 ODR 位bit15~0 为 BS15~0写 1 置位只写寄存器读返回 0BSx 与 BRx 同时写 1 时 BSx 优先。图课件 Slide 14——GPIOx_BSRRoffset 0x18低 16 位 BS置位、高 16 位 BR复位全部 write-only。BSRR 的妙处改一个引脚不需要读-改-写三步ODR 方式要valreadl(); val|bit; writel(val);——中断一来就可能被别的代码搅了直接写一次就生效写 0 的位无动作。实验三十三的 led_switch 会直接用它。三、LED 硬件与程序控制设备四步8.3 前半看原理图FS-MP1A 的三颗 LED 接在GPIOZ上——图课件 Slide 15——LED 连接原理图左半网络标号 PZ5引脚 H4、PZ6G3、PZ7H3分别接 LED1、LED2、LED3 网络。图课件 Slide 15——原理图右半三路 LED 各经 470Ω 限流电阻R114/R115/R117接绿色 LEDD35/D36/D38负极共同接地——GPIO 输出高电平 LED 亮输出低 灭正极逻辑与很多低电平点亮的板子相反写驱动前必看原理图。程序控制设备的四步流程一切外设通吃与实验三十核心三步合流流程驱动里的落点(1) 使能设备开时钟注册驱动时做led.c 里这段被注释原因见下(2) 配置设备模式/参数注册驱动时做MODER/OTYPER/OSPEEDR/PUPDR(3) 操作设备file_operations 的操作函数BSRR 置位复位(4) 用毕关闭复位/断电注销驱动时做操作寄存器要先过两道坎第一道虚拟地址。Linux 开着虚拟内存程序里的地址都是虚拟地址芯片手册给的寄存器地址是物理地址——用ioremap把物理地址映射成虚拟地址用完iounmap解除void__iomem*ioremap(resource_size_tres_cookie,size_tsize);// 物理首址、长度 → 虚拟首址voidiounmap(volatilevoid__iomem*addr);// 用完必须解除第二道有序访问。寄存器读写不要用裸指针——编译器可能乱序优化要用内核提供的读写函数图课件 Slide 19——读操作函数u8 readb(addr)、u16 readw(addr)、u32 readl(addr)——8/16/32 位读返回读到的数据。图课件 Slide 19——写操作函数void writeb(u8 value, addr)、void writew(u16 value, addr)、void writel(u32 value, addr)——8/16/32 位写。图课件 Slide 20——内核文档原文“The read and write functions are defined to be ordered. That is the compiler is not permitted to reorder the I/O sequence.”读写函数被定义为有序编译器不得重排 I/O 访问顺序——这就是别用裸指针的官方理由。寄存器物理地址怎么算芯片手册查 GPIOZ基址 0x54004000加上 8.2 节各寄存器的偏移MODER 0x00、OTYPER 0x04、OSPEEDR 0x08、PUPDR 0x0C、BSRR 0x18即得。基址的出处图课件 Slide 21——芯片手册 Register boundary addresses 表AHB5 段0x54004000–0x540043FF1 KBGPIOZ同表还能看到 RNG10x54003000、HASH10x54002000等邻居。时钟使能——一段注定被注释掉的代码本节最有意思的知识点GPIOZ 的时钟由 RCCReset and Clock Control模块管使能位在RCC_MP_AHB5ENSETRRCC 基址 0x50000000 offset 0x210的 bit0GPIOZEN写 1 使能图课件 Slide 24——RCC_MP_AHB5ENSETRoffset 0x210Reset 0x0001 0000写 ‘1’ 使能外设时钟、写 ‘0’ 无效果位域含 bit0 GPIOZEN、bit6 RNG1EN、bit5 HASH1EN、bit4 CRYPT1EN、bit8 BKPSRAMEN 等。图课件 Slide 24——GPIOZEN 位说明Set by software——写 ‘1’ 使能读 ‘1’ 已使能写 ‘0’ 无效果读 ‘0’ 时钟关闭。但课件明说LED 驱动里这段代码注释掉了两个原因图课件 Slide 26——TrustZone Environment 框图Normal WorldPL0 应用 / PL1 普通 OS / PL2 Hypervisor与 Secure WorldPL0 可信应用 / PL1 可信 OS底部 Secure Monitor 横跨两界——我们跑的 Linux 是正常世界TF-A第 3 章收官时接任 FSBL 的那位是安全世界的住民。出厂 TF-A 已经使能了 GPIOZ 时钟——第 3 章烧进板的 TF-A 顺手办了RCC_MP_AHB5ENSETR 属于安全世界AHB5 总线上的设备都是非安全世界我们的 Linux写不动它——写了也无效。驱动源码里保留注释版代码是为了给完整流程留教材——读到#if 0段时知道它为什么躺平即可。四、实验环境实际项目实际值板子第 7 章收官形态三颗绿色 LED 在板上PZ5/PZ6/PZ7高电平点亮Ubuntugcc-arm-9.2 内核源码树 drivers-dev.zip 已解01-toychar 用过本篇材料drivers-dev.zip的02-led/led.c ledApp.c Makefile——不重复复制这个包已在第 7 章目录05_字符设备驱动/复制并解压过直接取里面的02-led/子目录实验三十三编译开工自检10 秒本篇是认知篇读图与源码预读。确认02-led/led.c里 6 个ioremap、#if 0时钟段、BSRR 的15/121都能对上本篇讲过的寄存器——对上了实验三十三的代码就没有一行是新的。五、课件 ↔ 步骤对应表课件 Slide内容对应本篇2~3GPIO 概念、12 组 176 脚、四种模式、“一切皆寄存器读写”第一节4~14七个寄存器逐个 推挽/开漏电路 I/O 位结构图第二节15~16LED 原理图PZ5~7 高电平点亮第三节17程序控制设备四步流程第三节18~20ioremap/iounmap、readl/writel、有序访问第三节21~22GPIOZ 基址 0x54004000第三节23~26RCC 时钟使能、安全世界与 TF-A代码注释的原因第三节本篇概念 → 后面谁用 → 现在含糊的后果本篇概念后面哪一篇用现在含糊的后果MODER/OTYPER/OSPEEDR/PUPDR/BSRR 位段实验三十三 led.c 的六步初始化逐行对照代码里val ~(0x3 10)不知道在配哪个脚BSRR 只写、原子置位复位led_switch 的直接写、不读改写画蛇添足先读后写读到全 0 还以为寄存器坏了ioremap readl/writel实验三十三全部寄存器操作第 9 章 dtsled 的 of_iomap裸指针访问寄存器偶发跑飞查不到高电平点亮 PZ5~7实验三十三测试现象的预期灯不亮不知道是驱动错还是极性记反安全世界/RCC 注释段读第 9 章设备树版驱动时的时钟处理以为漏抄了使能代码本篇不需要新动手的材料。六、自测一览自测问题达标答案在哪一节STM32MP157 的 GPIO 怎么编号12 组 A~K、Z每组 16 脚K/Z 各 8引脚 Pxy 如 PB2、PZ5第一节四种工作模式由哪个寄存器选每脚占几位MODER2 位00 输入/01 输出/10 复用/11 模拟第二节推挽与开漏的区别LED 用哪个推挽双向驱动开漏只能拉低、靠外部上拉——LED 用推挽第二节改一个引脚电平为什么推荐 BSRR 而不是 ODRBSRR 只写、写 1 生效、原子操作——免读改写竞态第二节访问寄存器为什么不能直接用指针编译器可能乱序用 readl/writel有序且先 ioremap 把物理地址映射为虚拟地址第三节GPIOZ 时钟使能代码为什么被注释TF-A 已使能 RCC_MP_AHB5ENSETR 属安全世界Linux 写不动第三节LED 亮灭的电平极性高电平点亮三只绿灯负极接地经 470Ω 限流第三节七、下一步LED 驱动两个版本下一篇实验三十三把本篇的寄存器地图变成能上板的代码led.c 寄存器直控版主 201、手动 mknodledApp 写 1 开灯写 0 关灯mdevled.c 自动创建设备文件版alloc_chrdev_region→cdev→class_create→device_create 五函数与注销逆序——mdev 与 class 机制联动后/dev/led会自己出现。
返回列表