EMS 知识库
首页 / knowledge/代码解析/midware/debug

ate.c

源文件路径:midware/debug/ate.c 所属模块:midware/debug(设备中间件 - 板级调试/产线测试) 代码行数:219

1. 文件职责

本文件实现 EMS 主控板在产线 ATE(自动化测试设备)工位上的一种特殊工作模式:把 USART2(TTL 调试串口,PB10/PB11)与 UART4(外部 485 总线,PC12/PD2 配 PG9 收发使能)从"两个独立的标准串口"临时改造成一条位级透传(passthrough)通路,让测试工装接在 USART2 上就能直接与接到 UART4 上的逆变器/被控设备通信,而 EMS 自身不解析报文。

进入该模式后,EMS 的逆变器通信逻辑被挂起(midware/inverter/inverter.c 中多处 get_passthrough_flag() == FALSE 判断),LCD/LED 也切换到测试提示画面(hmi/ui/ui_main.c:778、hmi/led.c:388)。驱动链是:task_system_aux(midware/auxiliary/system_aux.c:2085)每 400 ms 调用一次 passthrough_detection(),由它判断进入/退出并做外设重配置;实际的数据搬运在两个外部中断服务函数里完成(EXTI2 在本文件,EXTI11 在 hardware/exti/exti.c:70)。

2. 关键数据结构与宏

本文件没有定义结构体/枚举,只有两个文件级静态变量作为状态载体。

名称类型说明
s_u8_passthrough_flagstatic u8透传模式开关。TRUE 表示当前处于模拟串口透传状态(ate.c:25)。只有本文件的 set_passthrough_flag() 写,get_passthrough_flag() 对外读
s_u32_passthrough_tickstatic u32透传活动时间戳(uCOS-II tick,1 tick = 1 ms)。进入透传时记一次,之后每次 UART4 侧 RX 下降/上升沿(PD2 的 EXTI2 中断)刷新一次(ate.c:26)。超时判据以此为基准
EXTI_11 / EXTI_2GD32 SPL 宏外部中断线编号。EXTI_2(PD2,UART4_RX)在本文件配置并由本文件的 EXTI2_IRQHandler 服务;EXTI_11(PB11,USART2_RX)在本文件配置,但中断服务函数在 hardware/exti/exti.c:70 的 EXTI10_15_IRQHandler 中
RCU_GPIOB/GPIOC/GPIOD/GPIOG/SYSCFGGD32 SPL 宏透传所需外设时钟

3. 函数清单

函数名作用域说明
emulated_serial_passthroughstatic(前置声明 ate.c:31,定义 ate.c:41)把 USART2 与 UART4 的 TX/RX 引脚重配置为普通 GPIO,并打开 EXTI2 / EXTI11 中断,建立位级硬件透传通路
EXTI2_IRQHandler全局(ISR,ate.c:84)PD2(UART4_RX)边沿中断服务:清标志、刷新 s_u32_passthrough_tick、把 PD2 电平直接搬到 PB10(USART2_TX)
set_passthrough_flagstatic(前置声明 ate.c:32,定义 ate.c:105)写 s_u8_passthrough_flag,入参做 == TRUE 归一化
get_passthrough_flag全局(ate.c:117)读透传标志,供逆变器通信、LCD、LED 等多处查询
get_passthrough_timeout_flagstatic(前置声明 ate.c:33,定义 ate.c:129)判断透传是否应退出:升级中 / 单板测试中 / 该机型不支持透传 → 立即退出;ATE 模式 → 不退出;否则按 10 s 无活动超时
passthrough_detection全局(ate.c:163)透传状态机主体:检测进入条件并重配置外设、进入;检测退出条件并恢复 9600 bps 标准串口

4. 核心逻辑解析

4.1 透传模式的定位

EMS 正常工作时,UART4 是它自己与逆变器通信的 485 口,USART2 是外部调试口。ATE 工位希望"绕过 EMS 直接测逆变器",于是本文件把两个外设都 usart_deinit() 掉,改成 GPIOD2→GPIOB10、GPIOB11→GPIOC12(+PG9) 两组输入捕获 + 输出翻转,使两条物理链路在电平上首尾相接,形成一条"USART2 ↔ UART4"的透明中继。整个过程不涉及任何协议解析,因此对 Modbus/厂商私有协议都通用。

4.2 进入条件与状态迁移

passthrough_detection()(ate.c:163)用一串 else if 做互斥判断,前四个分支都是空实现,即"不进入透传";只有第五个分支才真正进入:

进入条件(全部满足):
  1. 不在逆变器固件升级中:Get_Status_Is_Updated_From_Server(UPDT_INV1/2/3) 均为 FALSE
  2. 不在单板测试中:g_u8_single_board_test_enable == FALSE
  3. 该机型/该并机模式下允许透传:passthrough_detection_flag() == TRUE
  4. UART4 侧收到了数据:uart4_is_recv_async_data() == TRUE
  5. 当前尚未处于透传:get_passthrough_flag() == FALSE

其中第 5 条内部还有一个机型相关的使能极性反转(ate.c:182-190):

即同一个配置位 u8_passthrough_disenable_flag("透传禁用标志")在 EMS3.6-4 板型上语义被反过来了,名字与行为不一致。

进入动作(ate.c:191-200):置标志 → usart_deinit(UART4)、usart_deinit(USART2) → emulated_serial_passthrough() 重配引脚 → 清两侧缓冲区 → 记录 s_u32_passthrough_tick。

4.3 退出条件

get_passthrough_timeout_flag()(ate.c:129)按优先级返回:

优先级条件返回值含义
1Get_Status_Is_Updated_From_Server(UPDT_INV1/INV2/INV3)TRUE逆变器要升级了,强制退出,让 EMS 拿回 UART4
2g_u8_single_board_test_enable == TRUETRUE产线单板自检要占用串口,强制退出
3passthrough_detection_flag() == FALSETRUE机型/并机模式不支持透传(如并机走 UART4/USART3 时)
4g_t_inv_info.t_control_parameter.u8_ate_mode_flag 非 0FALSEATE 模式常驻透传,从不超时
5其它abs(s_u32_passthrough_tick - OSTimeGet()) > 1000010 s(10000 tick @ 1000 Hz)无 UART4 侧活动即超时退出

退出动作(ate.c:207-217):清标志 → exti_interrupt_disable(EXTI_2/EXTI_11) → usart2_init(9600)、uart4_init(9600) 恢复标准串口(注意:波特率被硬编码为 9600)→ 清缓冲 → set_inverter_init()(置 g_t_inv_info.u8_init_flag = TRUE,让逆变器通信重新走一遍识别流程)。

4.4 中断与位级转发时序

进入透传时打开的是一对双边沿外部中断:

时序特征:没有采样、没有滤波、没有去抖,纯组合逻辑式转发,因此透传速率完全取决于中断响应延迟,只能在 9600 bps 这类低速下可靠工作。s_u32_passthrough_tick 只由 UART4 侧(PD2)刷新,USART2 侧的 EXTI11 不刷新它,所以"只有工装不停发、逆变器一直不回话"的场景下 10 s 也会超时退出。

4.5 与 uCOS-II 任务/全局变量的配合

5. 对外接口

本文件导出

名称类型供谁使用
get_passthrough_flag(void)函数midware/inverter/inverter.c(挂起各厂商逆变器通信)、hmi/led.c、hmi/ui/ui_main.c
passthrough_detection(void)函数midware/auxiliary/system_aux.c:2085(task_system_aux 周期调用)
EXTI2_IRQHandler(void)ISR由 GD32 中断向量表调用(EXTI2_IRQn)

本文件调用的外部函数/变量

来源模块使用内容
inverter.h / inverter.cpassthrough_detection_flag()、set_inverter_init()、g_t_inv_info
net/upd_download.hGet_Status_Is_Updated_From_Server(UPDT_INV1/2/3)
net/server.h枚举 UPDT_INV1/INV2/INV3(net/server.h:188-196 的 ENUpdateType)
system/board_init/board_init.hget_board_type()、BOARD_EMS3_6_4_E
hardware/usart2usart2_init()、usart2_clear_buffer()
hardware/usart4uart4_init()、uart4_clear_buffer()、uart4_is_recv_async_data()
board_test.hg_u8_single_board_test_enable
GD32 SPL(HALLIB/)rcu_periph_clock_enable、gpio_mode_set、gpio_output_options_set、syscfg_exti_line_config、exti_init、exti_interrupt_flag_clear、exti_interrupt_disable、usart_deinit
system/sys/chip.h位带宏 PBout(n)、PDin(n)(chip.h:100/107)
uCOS-IIOSTimeGet()、OSIntEnter()、OSIntExit()、SYSTEM_SUPPORT_OS

6. 依赖关系

依赖

ate.h、usart2.h、usart4.h、includes.h(uCOS-II 总头)、inverter.h、inv_download.h、board_test.h、board_init.h(ate.c:13-20)。

被依赖

7. 备注与风险点

  1. 函数名与注释不符:ate.c:122-128 的注释块写的是 get_passthrough_tick,实际函数名是 get_passthrough_timeout_flag(ate.c:129)。
  2. s_u8_passthrough_flag 未加 volatile:该变量被 ISR(间接)与任务上下文读写的语义边界存在,但真正在中断里写的只有 s_u32_passthrough_tick(ISR 写、任务读),编译器优化下存在读到陈旧值的理论风险。
  3. s_u32_passthrough_tick 只在 EXTI2 里刷新:单向活动(工装→设备)不会续期,10 s 后仍会超时退出,行为与"任意方向的透传活动都续期"的直觉不同。
  4. 退出时波特率硬编码 9600(ate.c:212-213),未保留进入前的波特率;若业务侧原本配置为其它速率,退出后需要靠 set_inverter_init() 触发的重新识别流程再调整。
  5. u8_passthrough_disenable_flag 在 EMS3.6-4 上语义反转(ate.c:183-190),标志名与含义相反,极易误配置。
  6. 中断服务与初始化分居两个文件:EXTI11 的 SYSCFG/EXTI 配置在 ate.c:56-58,中断服务在 hardware/exti/exti.c:70。改动其中一处时容易漏掉另一处。
  7. ate.c 直接操作裸 GPIO 位带(PBout(10) = PDin(2)),没有做"引脚当前是否仍被 USART 复用"的防御;若透传中发生复位流程不完整(例如升级抢占),可能残留半配置状态。
  8. emulated_serial_passthrough() 中 syscfg 时钟使能注释写成"使能GPIOD中断时钟"(ate.c:47),实为 RCU_SYSCFG,注释误导。
  9. 所有进入/不进入的空分支都是 { } 而非注释说明,代码可读性差;这一写法本身无功能问题。