☰
08_GPIO点灯_从J41插针查到复用与寄存器
2026/10/8 2:15:07 网站建设 项目流程

Jetson Nano GPIO 点灯:从 J41 插针查到寄存器

对象:你目前使用的 Jetson Nano / Tegra X1、J41物理 12 脚、板端内核4.9.253-tegra。这是一份查资料与理解课程代码的流程;实际板型、设备树版本和灯的亮灭仍须在你的板上核对。配套代码见 led.c 和 app.c。

先抓住与 STM32 相同、不同的地方

两者都要回答三件事:选哪个管脚功能、设输入还是输出、输出高还是低。STM32 常从芯片封装脚直接查到 GPIO 端口和MODER/ODR/BSRR;Jetson Nano 还隔着载板 J41、模组 SODIMM、SoC 管脚命名、可能的电平转换器,以及 Linux 已有的 pinctrl/GPIO 驱动。

你熟悉的 STM32 思路此例在 Jetson Nano 上对应什么
开发板排针 → MCU 封装脚J41-12 → 载板信号I2S0_SCLK→ 模组第 199 脚 → SoC 管脚DAP4_SCLK
选 GPIO/复用功能Pinmux 管脚设置 + GPIO 控制器的CNF位;这是两层
配置输出方向Pinmux 的TRISTATE放行输出,再设 GPIO 的OE
写高/低电平GPIO 的OUT位 7
裸机直接写寄存器课程的led.ko在内核中ioremap/readl/writel;用户程序只能经/dev/led的ioctl调用它

J41 物理 12 脚

载板 I2S0_SCLK

模组脚 199

SoC DAP4_SCLK

Pinmux 0x70003150

GPIO3_PJ.07

CNF / OE / OUT 的 bit 7

输出通路

LED 电路

一、打开哪份资料、查哪里

下列文件都在I:\Linux内核驱动\嵌入式AI班资料\7.硬件控制资料。页码是 PDF 阅读器显示的页码;有印刷页码时也写出。

顺序资料与位置本例查到什么
12.1 载板标注说明,PDF 第 21–22 页、印刷第 17–18 页,Figure 3-1 / Table 3-3找J41 Header Pin #12;表格同一行给出模组信号I2S0_SCLK、模组脚199、Tegra 管脚DAP4_SCLK、GPIO 口PJ.07。J41-39 是 GND,J41-40 是信号。
22.3 载板电路图,PDF 第 19 页用J41、I2S0_SCLK搜网名,并看到 J41 信号经过载板电平转换器;排针不是直接焊到 SoC 焊球。
34.1 名称指南,PDF 第 15 页、印刷第 11 页复核模组第199脚:模组名I2S0_SCLK,SoC 名DAP4_SCLK。
44.2 开发板 40PIN 表,Jetson_Nano_DevKit工作表第 145 行一行同时看到 J41 脚位、SoC 名、GPIO 名、设备树 pin 名,以及当前用途/方向。
53.1 Tegra X1 TRM,第 9 章:PDF 第 331 页 §9.15.82;第 247–252 页 §9.13/Table 32查PINMUX_AUX_DAP4_SCLK_0、GPIO Controller 3 — Port J、CNF/OE/OUT的偏移和位定义。
64.4 NVIDIA 40-pin 配置说明,PDF 第 4–8 页理解表格生成 pinmux 设备树文件、启动阶段应用配置的流程;这是持久配置路线,与老师的运行时直接写寄存器实验不同。

本例暂时用不到 ARM Cortex-A57/GIC 手册。查“J41 第几脚”先看载板资料;查“寄存器偏移和每个位”才进入Tegra X1 TRM,不要在 2977 页 TRM 中盲搜12。

二、把五种名字串成同一个管脚

按4.2 开发板表 → Jetson_Nano_DevKit → 第 7 行列标题 → 第 145 行读:

单元格值它是什么
C14512J41 物理插针号。
A145/B145I2S0_SCLK/199模组对外信号名 /模组 SODIMM 脚号,199 不是 J41 脚号。
D145DAP4_SCLKTegra SoC 的管脚名称;用它去 TRM 搜 pinmux 寄存器。
H145GPIO3_PJ.07GPIO 控制器 3、J 口、口内第 7 位。用它去 GPIO 寄存器表查。
I145I2S4B_SCLK同一 SoC 管脚的一个SFIO 复用功能。载板写I2S0_SCLK,SoC 功能表写I2S4B_SCLK,编号体系不同。
W145/AE145dap4_sclk_pj7/GPIO_PJ7设备树 pinctrl 查找名 / GPIO pin group 名;拿dap4_sclk_pj7去 BSP 的.dtsi搜。
AS145/AT145GPIO3_PJ.07/Input这份表当前设为 GPIO 用途、输入方向;要在启动配置中设输出,方向也要改变。

**查找动作:**先在载板 PDF 搜J41并定位12;然后在表格C列搜12,找到第 145 行;接着用DAP4_SCLK搜 TRM 的 Pinmux 小节,用GPIO3_PJ.07找 Controller 3 / Port J。改查别的引脚时,重新走这条链,不复制 PJ.07 的地址。

4.3模组表的同一管脚也在第 145 行,但没有 4.2 的“40 Pin Header”列,所以相应字段整体左移:SoC 名在C145、GPIO 名在G145、设备树名在V145、用途/方向在AR145/AS145。NVIDIA 的 4.4 说明提到AR/AS,与你手中 4.2 表的AS/AT不同。总以当前工作表第 7 行的列标题为准。

三、两处“复用”到底怎么配

**第一处:SoC 管脚的 Pinmux 寄存器。**在 TRM §9.15.82 搜PINMUX_AUX_DAP4_SCLK_0:偏移0x3150,本例物理地址0x70003150。该寄存器至少要分清:

位含义对输出灯的关系
PM[1:0]选择SFIO编码:0=I2S4B,1=RSVD1,2/3=RSVD2/3。不能把PM=1翻译成“GPIO 编号 1”。板级 GPIO 配置可能采用rsvd1来避开 I2S;最终 GPIO/SFIO 还要看下方CNF。
TRISTATE[4]1为高阻,0为允许输出通路。老师代码清零 bit 4。只清这里还不会自动输出高电平。
PUPD[3:2]无上下拉、下拉或上拉。决定输入/空闲时的默认偏置;不是控制亮灭的OUT。
E_INPUT[6]、PARK[5]输入缓冲、深睡眠停放状态。本例代码没有系统处理这些字段,不能说它完成了全部管脚配置。

老师代码为(readl(gpio_pinmux) & ~(1 << 4)) | 1:它清 bit 4、置 bit 0,没有清PM的 bit 1,因此并不保证最终PM[1:0]=01;而01在手册中标为RSVD1。理解代码时应按位核对,后续正式配置应使用与当前 BSP 对应的 pinctrl/设备树方案,不把这句推广给其他管脚。

第二处:GPIO 控制器本身。GPIO3_PJ.07中的J决定寄存器位置,07决定寄存器内的位:

  • CNF bit 7 = 1:选择 GPIO,而非 SFIO。
  • OE bit 7 = 1:GPIO 作为输出;0是输入/高阻。
  • OUT bit 7 = 1/0:输出高/低。课程接线约定高电平亮、低电平灭。

所以Pinmux 放行输出 → CNF 选 GPIO → OE 选输出 → OUT 写电平,四个动作服务于同一根管脚,不能只做其中一个。TRM §9.13.1–9.13.3 分别说明了这三个 GPIO 寄存器的条件。

四、偏移怎么算:为什么是0x04 / 0x14 / 0x24

先从 Linux 4.9 的 Tegra210 SoC 设备树看两块 MMIO 范围:GPIO 控制器为0x6000D000起,Pinmux 的 mux 寄存器范围为0x70003000起。这是核对地址来源的参考;你自己的 NVIDIA BSP 和板上实际设备树仍要再对照。

TRM Table 32 的GPIO Controller 3 — Port I J K L一行里,J 是第二列:

目标相对整个 GPIO 块0x6000D000相对老师取的 GPIO3 基址0x6000D200实际物理地址
J 口CNF+0x204+0x040x6000D204
J 口OE+0x214+0x140x6000D214
J 口OUT+0x224+0x240x6000D224
GPIO 块 0x6000D000 + 控制器 3 的 0x200 + J 口 CNF 的 0x04 = 0x6000D204 GPIO3 基址 0x6000D200 + J 口 OUT 的 0x24 = 0x6000D224 目标位 = 1 << 7 = 0x80

0x04是J 口相对于 I 口的寄存器位置,7是J 口内的位号,二者不能相加。上表是 TRM 的Lower / Read-Modify-Write地址;右侧另有0x284/0x294/0x2A4等Upper / Per-Pin Mask Write地址。老师代码使用readl → 改位 → writel的 Lower 地址,没有使用 Mask Write。不要把两列混用。

Pinmux 的0x70003150也可写成0x70003000 + 0x150;TRM 写的Offset: 0x3150可理解为相对0x70000000。不能把0x3150再加到0x70003000上。这里的 Pinmux 地址与上面的 GPIO 地址属于不同 MMIO 区域。

五、对照你现在的led.c看执行顺序

  1. register_chrdev_region(MKDEV(500,0), ...)占用字符设备号。这里的500:0只负责把/dev/led关联到驱动,和 J41-12、模组脚 199、GPIO bit 7没有数值关系。
  2. ioremap(0x70003150, 8)获得 Pinmux MMIO 的内核映射地址;readl/writel修改该管脚的复用/三态字段。
  3. ioremap(0x6000D200, 0xFF)获得 GPIO3 寄存器窗口;用+0x04设置 J 口CNFbit 7,用+0x14设置OEbit 7,再用+0x24设置OUTbit 7。
  4. cdev_init/cdev_add把file_operations接入字符设备;板端/dev/led必须是字符节点500,0。
  5. 用户态open("/dev/led") → ioctl(LED_ON/LED_OFF);内核进入led_ioctl() → led_on()/led_off(),最终只改OUT的 bit 7。用户态循环的usleep(100000)决定闪烁频率。
/* 代码实际要找的三个地址:都在 GPIO3 的 J 口,只改第 7 位。 */#defineGPIO30x6000D200#defineCNF0x04#defineOE0x14#defineOUT0x24/* GPIO3 + OUT = 0x6000D224;bit 7 = 0x80。 */

ioremap后的指针是内核虚拟地址,不是应用可直接解引用的物理地址;卸载时要iounmap。同一 J 口还有其他位,读改写是为保留其他位,但它没有解决与 Linux GPIO/pinctrl 驱动并发使用同一寄存器的资源归属问题。课程直接写寄存器是理解硬件的实验。

六、表格配置与老师代码是两条不同时间线

  • **老师当前实验:运行时设置。**板子已经启动 Linux,insmod led.ko才执行上述 MMIO 写入;模块卸载或重启后,这些运行时写入不等于持久的板级 Pinmux 配置。
  • NVIDIA 板级流程:启动时设置。在 4.2 表第 145 行按列标题确认Customer Usage、Pin Direction、初始状态,再由表格生成 pinmux/gpio 的设备树文件,与匹配当前 L4T/BSP、板型版本的启动配置一起部署。你这份 4.2 表目前显示 GPIO 用途、Input;若要上电就是输出,需要把方向及安全初始状态一同设计,并核对生成的配置。NVIDIA 的说明指出 CBoot 会应用这部分 pinmux 配置,Linux 不会自动重新应用 CBoot 那一份。NVIDIA Jetson Nano 适配文档

**现在学习这份 MD 时只读资料、核对当前板子即可。**4.4 文档中的 U-Boot/CBoot、刷机命令和文件名针对其发布版本,不应直接复制到你现在的4.9.253-tegra系统。以后进入 Platform/设备树/GPIO 子系统,再做匹配 BSP 的持久配置和驱动资源管理。

七、板上只读核对与常见误认

在Jetson Linux中查看板型和实际加载的设备树信息,不写寄存器:

uname-runame-mcat/proc/device-tree/modeltr'\0''\n'</proc/device-tree/compatibletest-r/proc/device-tree/nvidia,dtsfilename&&tr-d'\0'</proc/device-tree/nvidia,dtsfilename

在Ubuntu 虚拟机的 NVIDIA BSP 中用上一步的板型/文件名找相应.dts/.dtsi,再搜索dap4_sclk_pj7、GPIO_PJ7、gpio@6000d000。看到名字和配置后,才判断当前板实际由谁占用这根脚。没有板端结果之前,本笔记的地址链是手册与课程代码的静态核对。

常见误认正确区分
“12、199、7 是同一个 GPIO 编号。”12=J41 物理插针;199=模组 SODIMM 脚;7=PJ 口内位号。
“GPIO3_PJ.07的 3 是高电平 3V。”3 指第 3 组 GPIO 控制器;J 指端口,07 指位号。排针电平由载板规格确认。
“PM=1就是 GPIO。”TRM 把 1 标为RSVD1;GPIO_CNF决定 GPIO/SFIO。
“设置OUT=1灯就一定亮。”还要 Pinmux 放行、CNF=GPIO、OE=输出、设备节点/驱动正常,外接电路也要正确。
“J41-40 是地。”J41-39 是 GND;40 是I2S0_DOUT信号。

**接灯留意载板能力:**2.1 的 J41 表为 12 脚标出很弱的20 µA / -20 µA驱动,并注明这类信号经过 TXB0108 电平转换器。课程“串电阻直连 LED”的思路适合解释高低电平,但不保证裸 LED 能明显发光;做可见亮灭测试宜让 12 脚驱动高阻缓冲/晶体管,LED 电流由合适电源与限流电阻提供。J41-12 到 J41-39 的信号/地关系先确认,不要把 40 脚当地线。

最后给自己做一个闭卷追踪:任选 J41 的另一个可用 GPIO,能否从载板 Table 3-3 找到模组/SoC 名,在 4.2 表找到设备树名,在 TRM 找到 Controller/Port/位,再分别算出 Pinmux 与 GPIO 的地址?能走通这一遍,就真正掌握了老师找 PJ.07 的方法。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询