NextPF 三大作业实战指南(MTK8788 / Android 15)
平台:MTK8788(SoC = MT6771)/ Android 15 / kernel-6.6
读法:每节先"是什么/为什么"(小白看),再"代码在哪/长啥样"(带全路径+行号),最后"怎么改/怎么测/怎么排错"(专业落地)。
0. 这张图要做的三件事
| # | 原文方针 | 人话 | 难度 |
|---|---|---|---|
| 1 | USB-UART → USB | 去掉"串口转USB"外挂芯片,改用 SoC 原生串口 | 中 |
| 2 | 确认 SoC UART + 检查并禁用 auto-suspend | 别让串口自动休眠,否则丢数据 | 高(核心) |
| 3 | UART 有/无可切换(同一软件) | 同一镜像,有串口/无串口机器都能跑 | 低 |
1. 名词扫盲
| 名词 | 大白话 |
|---|---|
| UART | 串口,TX发RX收两根线,最稳的点对点通信 |
| USB-UART桥接芯片 | CP2102/FTDI/PL2303,把串口翻成USB插电脑 |
| 原生UART | SoC自带串口控制器,不用外挂芯片 |
| 8250 | 经典串口寄存器标准,MTK驱动叫8250_mtk |
| autosuspend | 闲一会自动断电,串口被休眠会丢字节 |
| pm_runtime | 内核运行时电源管理,autosuspend归它管 |
| clk时钟 | 硬件心跳,关时钟=省电=停工 |
| APDMA | MTK串口搬运工,自动搬数据省CPU |
| dts/pinctrl | 设备树/引脚复用 |
| defconfig | 开关清单:=y编入 =m模块 没写=关 |
| RTS/CTS | 硬件流控线,防丢包 |
| EFR | MTK扩展功能寄存器,控流控 |
2. 关键文件全路径清单(照着打开)
| 用途 | 全路径 |
|---|---|
| UART驱动 | kernel-6.6/drivers/tty/serial/8250/8250_mtk.c |
| 驱动开关 | kernel-6.6/drivers/tty/serial/8250/Kconfig(SERIAL_8250_MT6577,L477) |
| 编译挂接 | kernel-6.6/drivers/tty/serial/8250/Makefile(obj-$(CONFIG_SERIAL_8250_MT6577)+=8250_mtk.o) |
| 设备树 | kernel/kernel_device_modules-6.6/arch/arm64/boot/dts/mediatek/mt6771.dts |
| 引脚定义 | kernel/kernel_device_modules-6.6/include/dt-bindings/pinctrl/mt6771-pinfunc.h |
| USB配置 | kernel-6.6/arch/arm64/configs/gki_defconfig |
| FTDI桥驱动 | kernel-6.6/drivers/usb/serial/ftdi_sio.c |
链路图
open("/dev/ttyS1") → tty框架 → 8250_port.c → 8250_mtk.c → mt6771.dts apuart1 → 硬件 SoC UART @0x110030008250_mtk.c 函数行号(已核实)
| 函数 | 行 | 作用 |
|---|---|---|
| mtk8250_dma_enable | 155 | 开APDMA |
| mtk8250_set_flow_ctrl | 243 | 流控 |
| mtk8250_set_termios | 306 | 波特率 |
| mtk8250_runtime_suspend | 429 | 关baud/bus时钟 |
| mtk8250_runtime_resume | 444 | 开时钟 |
| mtk8250_do_pm | 455 | 开关口唤醒/挂起 |
| mtk8250_probe_of | 473 | 取时钟+DMA |
| mtk8250_probe | 518 | 开runtime PM |
| mtk8250_suspend/resume | 604/628 | 深睡+唤醒中断 |
| mtk8250_of_match | 648 | mediatek,mt6577-uart |
3. 作业一:USB-UART → 原生 USB
现状(gki_defconfig 已核实)
542: CONFIG_USB_SERIAL=m 543: CONFIG_USB_SERIAL_FTDI_SIO=m # 现在靠FTDI桥路径:MCU→FTDI芯片→USB→主机。
目标
MCU→SoC apuart→ttyS*,匹配mediatek,mt6577-uart(8250_mtk.c:649)。
dts 节点(mt6771.dts 已核实)
apuart1: serial@11003000 { compatible = "mediatek,mt6577-uart"; reg = <0 0x11003000 0 0x1000>; interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH 0>; clocks = <&clk26m>, <&infracfg_ao INFRACFG_AO_UART1_CG>; clock-names = "baud", "bus"; dmas = <&apdma 2 &apdma 3>; dma-names = "tx", "rx"; };改:&apuart1 { pinctrl-0=<&uart1_pin>; status="okay"; };,FTDI 留=m兼容旧机。
4. 真实引脚号(mt6771-pinfunc.h 已核实)
| 信号 | 引脚 | 宏 |
|---|---|---|
| URXD1 | GPIO19 | PINMUX_GPIO19__FUNC_URXD1 |
| UTXD1 | GPIO20 | PINMUX_GPIO20__FUNC_UTXD1 |
| UCTS1 | GPIO23 | PINMUX_GPIO23__FUNC_UCTS1 |
| URTS1 | GPIO24 | PINMUX_GPIO24__FUNC_URTS1 |
| URXD0 | GPIO95/96 | PINMUX_GPIO95__FUNC_URXD0 |
| UTXD0 | GPIO96/95 | PINMUX_GPIO96__FUNC_UTXD0 |
pinctrl 示例:
uart1_pin: uart1-pins { pins { pinmux = <PINMUX_GPIO19__FUNC_URXD1>, <PINMUX_GPIO20__FUNC_UTXD1>; }; };带流控加 GPIO23/24。
5. 作业二:禁用 autosuspend(核心)
为什么:闲→关baud/bus时钟→来数据来不及上电→丢字节。
源码(已核实)
probe(L584):pm_runtime_set_active+pm_runtime_enable
suspend(L429):while(serial_in DEBUG0)等空闲→关uart_clk/bus_clk
do_pm(L455): 开口get_sync 关口put_sync_suspend
深睡(L604):pinctrl_pm_select_sleep_state+enable_irq_wake(rx_wakeup_irq)
禁法
- A 验证:
echo on>.../power/control;autosuspend_delay_ms=-1 - B dts不写延时
- C 改驱动去掉pm_runtime_enable
查:runtime_status=active,idle后不丢。
6. 作业三:型号兼容
status="okay"/"disabled"overlay 切;驱动内置;应用打不开ttyS1容错。
7. 流控(L243) / 8. DMA(L155)
HW=EFR_HW_FC开CTSI/RTSI;SW=XON1/XOFF1;DMA=dma-names tx/rx需CONFIG_SERIAL_8250_DMA。
9. 排错
| 现象 | 查 |
|---|---|
| 无ttyS1 | status okay+nr_uarts |
| 丢前几字节 | autosuspend未禁 |
| 乱码 | 波特率/引脚 |
| 高速丢 | RTS/CTS或DMA |
| probe失败 | “Can’t get uart clock” 时钟名baud/bus |
10. 自检
- echo>/dev/ttyS1收发 [ ] idle后不丢 [ ] active [ ] 双机型同镜像 [ ] dmesg无错