ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

I.MX6U 裸机开发22. LCDID读取及IO初始化

I.MX6U 裸机开发22. LCDID读取及IO初始化 I.MX6U 裸机开发22. LCDID读取及IO初始化一、实验内容1. 读屏 ID原理1.1 硬件上 ID 编码规则1.2 模拟开关作用1.3 为什么是 DATA23 / 15 / 7为什么是 GPIO3 的 28 / 20 / 121.4 电平转成 0x43841.5 读取步骤对应代码2. 支持的屏幕 ID3. 程序流程4. 预期串口输出二、调试方式与前课不同虚拟机 Ubuntu 改成 WSL1. 编译WSL2. USB-OTG 下载本课主用Windows3. 串口查看日志4. 可选仍用 SD 卡5. 故障排查三、读取 ID 参考代码本课在板子上读取正点原子 LCD 的型号 ID并通过串口printf打印结果。调试方式与前面课程不同本课将使用 Windows 下 USB-OTGHID SDP下载到内存运行不再依赖 SD 卡烧录。名词速览本课首次集中用到USB-OTGOn-The-Go板子上那路可当「从设备」连电脑的 USB本课用它做下载不是串口那根线。HIDHuman Interface Device一种 USB 设备类常见于键鼠i.MX 下载模式也伪装成 HID方便免装专用驱动。SDPSerial Download ProtocolNXP 规定的「串行下载协议」规定主机如何把镜像写进芯片内存并跳转执行。DDR板载大容量动态内存程序下载后在这里运行掉电/按 RESET 后内容丢失USB 下载模式尤其如此。⭐ 本次验证目标USB 下载启动功能本课核心目的是验证USB OTG 下载 → DDR 内存运行这条链路是否可用LCD ID 读取只是验证时的观察输出。验证成功的判定标准拨码0100USB 下载模式后设备管理器出现SE Blank 6ULLVID_15A2 PID_0080SE Blank 6ULL芯片处于「空白片 / 串行下载」状态时Windows 看到的产品名。VID / PIDUSB 厂商号 / 产品号15A2是 Freescale/NXP0080对应 i.MX6ULL 下载模式。dl.py三步全部 OKDCD_WRITE→WRITE_FILE→JUMP_ADDRESS见下文调试节解释程序在 DDR 中跑起来串口打印LCD ID 0x4384ATK4384LED0 每 500ms 闪烁三条都满足即说明 USB 下载启动功能验证通过之后其他课程也可复用此方式快速调试无需反复烧 SD 卡。一、实验内容1. 读屏 ID原理先澄清一点本课读的不是液晶控制器芯片内部的「厂商 ID 寄存器」也没有对屏幕发 RGB/SPI 读命令。正点原子的做法是在屏幕模组背面用M0 / M1 / M2 三个电阻焊点预先焊成不同的高低电平组合相当于给每款屏打了一个硬件「型号跳线」MCU 上电后用 GPIO 把这 3 位读出来再查表映射成软件里的ATK4384这类 ID。不同尺寸/分辨率的屏LCDIF 时序、像素时钟、分辨率都不一样。若写死一套参数换一块屏就会花屏或点不亮。所以要先识别「接的是哪一块」后面初始化才选对参数。1.1 硬件上 ID 编码规则在开发板屏幕背面可以看到丝印和 M0、M1、M2 的电阻焊点每一款屏出厂时M0M2 上会选择性地焊接上拉或下拉电阻有的脚接高、有的脚接低形成 3 bit 组合。MCU 把对应引脚配成输入后读到的就是这 3 个电平M2M1M0idx软件拼出来的数对应型号本工程约定0000ATK43420011ATK70840102ATK70161004ATK4384本板实测1015ATK1018所以「能读 ID」的本质是读 3 个 GPIO 的高低电平不是访问某个神秘的内存地址。1.2 模拟开关作用RGB 屏正常工作时LCD_DATA023要传像素数据。若 ID 电阻网络一直挂在 DATA 线上会干扰显示。正点原子的做法是ID 信号走LCD_DATAxS一侧真正进 MCU 的是LCD_DATAx中间用模拟开关SGM决定是否把「屏上的 M0M2」接到 MCU。控制脚接到LCD_VSYNC原理图里的 SGM CTRL读 ID 前把 VSYNC 配成 GPIO输出高→ 开关导通 → MCU 才能采到 M0M2平时显示开关断开或不走这条读 ID 路径DATA 线专心传像素一句话VSYNC 在这里临时当「开关使能」用不是在读场同步波形。1.3 为什么是 DATA23 / 15 / 7为什么是 GPIO3 的 28 / 20 / 12这些不是软件随便选的「地址」而是原理图已经焊死的连线再对照芯片手册的引脚复用表IOMUXC查出来的屏上丝印接到 MCU 的 LCD 信号RGB 含义IOMUXC 宏切到 GPIO实际 GPIOM0LCD_DATA23R7红最高位IOMUXC_LCD_DATA23_GPIO3_IO28GPIO3_IO28M1LCD_DATA15G7绿最高位IOMUXC_LCD_DATA15_GPIO3_IO20GPIO3_IO20M2LCD_DATA07B7蓝最高位IOMUXC_LCD_DATA07_GPIO3_IO12GPIO3_IO12开关控制LCD_VSYNC行同步IOMUXC_LCD_VSYNC_GPIO3_IO03GPIO3_IO03为何挑 R7/G7/B7DATA23/15/7这三根硬件设计如此正点原子把 M0/M1/M2 复用到 RGB 总线最高位这三根线上读完 ID 后同一组脚仍可改回 LCDIF 功能去显示。软件侧只能跟着原理图走你在代码里写gpio_pinread(GPIO3, 28)是因为手册写明「焊盘 LCD_DATA23 复用到 GPIO 时 GPIO3 的 bit28」换成别的脚号读到的就不是 M0。「GPIO3_IO28」不是内存地址它表示「GPIO 控制器 3 的第 28 号引脚」。底层会去操作该控制器的 DR/PSR 等寄存器但你选 28/20/12 的依据是引脚编号不是随便填的十六进制外设基址。代码里两步缺一不可IOMUXC_SetPinMux(..._GPIO3_IOxx, 0)把焊盘从 LCDIF 功能切到 GPIOgpio_initgpio_pinread按输入方式读电平若只配 GPIO 方向、不改 IOMUXC脚仍接在 LCD 控制器上读 ID 会失败。1.4 电平转成0x4384idx M0 | (M1 1) | (M2 2)即M0 为 bit0M1 为 bit1M2 为 bit2。例如本板 ATK4384读到 M00, M10, M21 →idx 0b100 4if (idx 4) return ATK4384; /* 0x4384 */0x4384本身只是正点原子/本工程约定的型号常量方便后面switch (lcdid)选分辨率硬件上真正有信息量的是那 3 bit 的idx。1.5 读取步骤对应代码LCD_VSYNC→ GPIO 输出高打开模拟开关LCD_DATA23/15/7→ GPIO 输入必要时配上下拉与电阻网络匹配读 GPIO3_IO28 / 20 / 12拼出idx查表返回ATKxxxx配置引脚时会用到IOMUXCIO Multiplexer Controller引脚复用控制器同一焊盘可切到 LCD 功能或 GPIO 功能读 ID 时要切到 GPIO。2. 支持的屏幕 IDidxID型号规格00x4342ATK43424.3 寸 480×27210x7084ATK70847 寸 800×48020x7016ATK70167 寸 1024×60040x4384ATK43844.3 寸 800×48050x1018ATK101810.1 寸 1280×800表里的ID是软件约定的型号编码不是面板内部寄存器里读出来的厂商 ID后续初始化 LCD 时序、分辨率时就靠这个值选参数。3. 程序流程上电 / USB 下载跳转 ├─ bsp_int_init() ├─ imx6u_clkinit() / clk_enable() ├─ led_init() / beep_init() / gpt1_delay_init() ├─ uart_init(UART1) # 115200 ├─ lcd_init() # 读 ID 并 printf └─ while(1) LED0 每 500ms 翻转关键代码board/imx6u/bsp_lcd.c—lcd_read_id()/lcd_init()board/imx6u/bsp_uart.c— UART1异步串口接 CH340 后变成电脑上的 COM 口lib/stdio/lib/printf.c— 裸机 printf没有操作系统标准库自己往 UART 丢字符bootloader/start.S— 启动汇编设栈、清 BSS、跳进main4. 预期串口输出本板使用正点原子 4.3 寸 800×480 屏ATK4384串口输出类似LCD ID 0x4384具体值取决于所接屏幕本板实测为 ATK4384。二、调试方式与前课不同对比项前几课常见本课编译环境虚拟机里的 UbuntuWSLWindows 子系统里的 Linux交叉编译下载介质SD 卡 imxdownload多在虚拟机里操作USB OTG Windows 侧tools/dl.py运行位置从 SD 启动下载到DDR 内存后跳转掉电丢失USB / 串口虚拟机可做 USB 透传后再在 Ubuntu 里用在 Windows 本机操作本仓库 WSL1 看不到 USB拨码SD 启动USB 下载模式0100拨码 / BOOT_MODE板子上的拨码开关告诉 BootROM「从哪启动」。0100表示进入Serial Downloader串行下载器只等电脑通过 USB 送程序不会去读 SD。虚拟机 Ubuntu 改成 WSL前几课习惯在VMware / VirtualBox 里装 Ubuntu交叉编译、imxdownload烧 SD、有时再把 USB 设备透传进虚拟机。能用但有几处别扭工程在 Windows 盘与虚拟机磁盘之间来回拷或要配共享文件夹USB 透传偶发不稳定拔插、占用冲突虚拟机本身占内存、开机慢本课起改用WSLWindows Subsystem for Linux在 Windows 里直接跑一套 Ubuntu 用户态用来装arm-linux-gnueabihf-gcc做交叉编译。代码就放在 Windows 路径如D:\documents\...WSL 里用/mnt/d/...访问同一份文件编译产物两边立刻可见不必再拷来拷去。本仓库当前是WSL1优点和 Windows 文件系统集成紧、访问D:盘快限制看不到 USB 设备没有真正的 Linux USB 协议栈所以编译仍在 WSLUSB 下载dl.py、串口助手COM7必须在Windows完成若仍想用虚拟机只要工具链一致、能生成同样的load.imx即可本课文档按 WSL Windows 下载来写。1. 编译WSLcd/mnt/d/documents/learn_i.mx6u/22_lcdidmakecleanmake产物生成在工程目录Windows 资源管理器里也能直接看到uart_printf.bin— 裸机二进制纯机器码还不能直接给 BootROM 用load.imx— 带IVT DCD头的 NXP 镜像USB 下载 / SD 烧录都用它补充两个头信息名词IVTImage Vector Table镜像向量表文件最前面一块结构告诉 BootROM「程序入口在哪、DCD 在哪、镜像自身加载地址self是多少」。DCDDevice Configuration Data一串「写寄存器」命令主要用来在跳进程序前初始化 DDR。没有 DCDDDR 还没起来大程序根本写不进去。2. USB-OTG 下载本课主用Windows硬件准备拨码拨到USB 下载模式正点原子0100BOOT_MODE10USB 线接板子OTG Type-C不要插成串口那个口另一根线接USB 转串口 Type-C板上是CH340芯片把 UART 转成电脑 COM 口本机为COM7设备管理器应出现 HIDVID_15A2 PID_0080描述SE Blank 6ULL依赖pip install hidapi pyserial下载并可选读串口# 脚本默认下载 22_lcdid\load.imx并尝试读 COM7python D:\documents\learn_i.mx6u\tools\dl.py# 已用串口助手占用 COM7 时只下载python D:\documents\learn_i.mx6u\tools\dl.py--no-serial# 指定镜像 / 串口python D:\documents\learn_i.mx6u\tools\dl.py D:\documents\learn_i.mx6u\22_lcdid\load.imx--com COM7脚本做的事走SDP over HID即用 HID 报告封装 SDP 命令DCD_WRITE把 DCD 数据先写到OCRAM片上 SRAM地址0x00910000。DDR 还没初始化时不能往 DDR 写OCRAM 上电即可用BootROM 在这里执行 DCD 去「点亮」DDR。WRITE_FILEDDR 就绪后把整份load.imx写到 IVT 里的self地址本课为0x877FF400在 DDR 里。JUMP_ADDRESS让 BootROM 跳到 IVT再按 IVT 里的entry进入你的程序。成功时终端类似[1] DCD_WRITE ... status0x128A8A12 [OK] [2] WRITE_FILE ... status0x88888888 [OK] [3] JUMP_ADDRESS ... [OK] LCD ID 0x4384失败后请按板子RESET重新出现 “SE Blank 6ULL” 后再下载。提醒USB 下载模式下按 RESET 重新进下载器不会自动再跑刚才 DDR 里的程序要看串口输出必须再执行一次dl.py。3. 串口查看日志参数值端口COM7以本机设备管理器为准波特率115200数据位 / 停止位 / 校验8 / 1 / 无波特率每秒传输的符号速率双方必须一致否则就是乱码。本课 UART1 配成 115200 8N18 数据位、无校验、1 停止位。注意printf只在启动时打一次先开串口再下载或用dl.py自动读两个 Type-COTG 下载CH340 日志插反会失败COM7 被 sscom 等占用时dl.py打不开串口用--no-serial日志改在串口助手看4. 可选仍用 SD 卡与前课相同适合需要掉电保存时cd/mnt/d/documents/learn_i.mx6u/22_lcdid../tools/imxdownload uart_printf.bin /dev/sdX# 先用 lsblk 确认设备号拨码改回 SD 启动后上电。此时程序在 SD 里按 RESET 会重新启动应用串口会再次打印 LCD ID——这点和 USB 下载模式相反。5. 故障排查下载后 ├─ LED0 闪 │ ├─ 是 → 查串口口/COM/波特率/是否错过启动打印 │ └─ 否 → 程序没跑起来 │ ├─ 无 SE Blank 6ULL → 拨码、OTG 线、按 RESET │ └─ 有设备但脚本失败 → 按 RESET 后重跑 dl.py └─ 串口乱码 → 波特率是否 115200三、读取 ID 参考代码下面用到的IOMUXC_SetPinMux/IOMUXC_SetPinConfig就是在配引脚复用和电气特性上下拉、驱动强度等gpio_init/gpio_pinread则是把脚当普通输入输出用。/** * 正点原子 LCDM0~M2 组合 * LCD_DATA23R7[M0]; LCD_DATA15G7[M1]; LCD_DATA7B7[M2] */unsignedshortlcd_read_id(void){unsignedcharidx0;gpio_pin_config_tlcdid_io;IOMUXC_SetPinMux(IOMUXC_LCD_VSYNC_GPIO3_IO03,0);IOMUXC_SetPinConfig(IOMUXC_LCD_VSYNC_GPIO3_IO03,0x10B0);lcdid_io.directionkGPIO_DigitalOutput;lcdid_io.outputLogic1;/* 打开模拟开关 */gpio_init(GPIO3,3,lcdid_io);IOMUXC_SetPinMux(IOMUXC_LCD_DATA07_GPIO3_IO12,0);IOMUXC_SetPinConfig(IOMUXC_LCD_DATA07_GPIO3_IO12,0xF080);IOMUXC_SetPinMux(IOMUXC_LCD_DATA15_GPIO3_IO20,0);IOMUXC_SetPinConfig(IOMUXC_LCD_DATA15_GPIO3_IO20,0xF080);IOMUXC_SetPinMux(IOMUXC_LCD_DATA23_GPIO3_IO28,0);IOMUXC_SetPinConfig(IOMUXC_LCD_DATA23_GPIO3_IO28,0xF080);lcdid_io.directionkGPIO_DigitalInput;gpio_init(GPIO3,12,lcdid_io);gpio_init(GPIO3,20,lcdid_io);gpio_init(GPIO3,28,lcdid_io);idx(unsignedchar)gpio_pinread(GPIO3,28);idx|(unsignedchar)gpio_pinread(GPIO3,20)1;idx|(unsignedchar)gpio_pinread(GPIO3,12)2;if(idx0)returnATK4342;if(idx1)returnATK7084;if(idx2)returnATK7016;if(idx4)returnATK4384;if(idx5)returnATK1018;return0;}
返回列表