wireless_driver.h
u8_wireless_uart_flag —— 串口互斥的唯一手段4.2 信号强度字段的"哨兵值"约定4.3 PROTOCOL_TYPE_E 的位打包4.4 6 个 tick 字段的用途分工4.5 E_LINKER_ID_INFO.u8_is4G 的双重来源5. 对外接口6. 依赖关系7. 备注与风险点源文件路径:
midware/ethernt/wireless/wireless_driver.h所属模块:midware/ethernt/wireless(无线通讯棒驱动层) 代码行数:103
1. 文件职责
本文件是无线通讯棒(易联/自研 WIFI 棒、4G 棒)驱动层的对外头文件,屏蔽具体模块型号差异,向上提供统一的"探测器 + 收发 + 状态刷新"接口。
它定义了无线运行状态总表 WIRELESS_TAB_T 与通讯棒身份信息 E_LINKER_ID_INFO,前者是网络层(ethernet.c)判断能否走无线通道、何时重启通讯棒的唯一数据源。
PROTOCOL_TYPE_E 联合体把通讯棒上报的协议支持位(纯 TCP / TCP+TLS / MQTT / MQTTS)打包成一个字节,供 ethernet.c 选择端口与加密方式。
本文件不包含实现,全部函数在 wireless_driver.c 与 wifi/e_linker_wifi.c 中。
2. 关键数据结构与宏
| 名称 | 类型 | 说明 |
|---|---|---|
WIRELESS_DEBUG_INFO | 宏 | 置 1 打开 P1 抄表/无线状态详详细打印;默认 0 |
WIRELESS_DEBUG | 宏 | 置 1 打开通用无线调试打印;默认 0 |
WIRELESS_POWER_PIN | 宏 | 通讯棒电源控制引脚 GPIO_PIN_7 |
WIRELESS_POWER_PORT | 宏 | 通讯棒电源控制端口 GPIOH |
MAX_E_LINKER_SN_LEN | 宏 | 通讯棒 SN 最大长度 16 |
MAX_E_LINKER_P1_LEN | 宏 | P1 采集器数据帧最小有效长度 75 |
MAX_WIFI_4G_ICCID_LEN | 宏 | 4G SIM 卡 ICCID 最大长度 25 |
WIRELESS_TYPE_E | 枚举 | 通讯棒类型:NONE(0)、ZLG、E_LINKER_WIFI、E_LINKER_4G、ALPHA_LINKER_WIFI、MAX_WIRELESS |
PROTOCOL_TYPE_E | 联合体 | 低 4 位为协议支持标志位:u8_only_tcp_support_flag、u8_tcp_tls_support_flag、u8_mqtt_support_flag、u8_mqtts_support_flag,高 4 位 bit4..bit7 保留 |
WIRELESS_TAB_T | 结构体 | 无线运行时总表:u8_wireless_found 是否已识别、u8_wireless_type 类型、s8_wireless_eirp WIFI 信号强度(-99 表示无效)、u8_4g_rssi/u8_4g_ber 4G 信号质量(99 表示无效)、u8linkstatus 是否连上路由/基站、u8tcpstatus 是否连上云服务器、u8_wireless_rst_flag 重启请求、volatile u8_wireless_uart_flag 串口占用标志、u8_wifi_support_P1_falg 是否支持 P1(仅易联 18031 版本支持)、6 个 tick 字段(u32_dectect_tick/u32_link_tick/u32_tcp_tick/u32_wireless_check_tick/u32_P1_read_tick/u32_P1_refresh_tick)、protocol_support_state 协议支持位、u32_WIFI_uart_tick 上次串口活动 tick |
E_LINKER_ID_INFO | 结构体 | 通讯棒身份:u8_e_linker_SN[17] 序列号、u8_e_linker_HW[15] 硬件版本、u8_e_linker_SW[15] 软件版本、u8_ICCID[25] 4G 卡号、u8_is4G 是否 4G 模块 |
3. 函数清单
本文件为头文件,只含函数声明。
| 函数名 | 作用域 | 说明(一句话) |
|---|---|---|
void wireless_set_restart_flag(u8 flag) | 全局(声明) | 设置通讯棒重启请求标志 |
u8 wireless_query_restart_flag(void) | 全局(声明) | 查询通讯棒重启请求标志 |
u8 wireless_send(u8* buf, u32 len, u16 timeout) | 全局(声明) | 向通讯棒串口发送数据,1 成功 / 0 超时 |
u8 wifi_recv_flag(void) | 全局(声明) | 查询串口是否有待读数据——本工程中只有声明、无任何定义 |
u32 wireless_recv(u8* buf, u32 len) | 全局(声明) | 从通讯棒串口读取数据,返回实际读取长度 |
void wireless_status_detect(void) | 全局(声明) | 通讯棒识别、状态刷新、重启的统一巡检入口 |
void wireless_init(void) | 全局(声明) | 复位无线运行时状态并上电通讯棒 |
void wireless_restart(void) | 全局(声明) | 断电-断电-上电三段式硬重启通讯棒 |
void wireless_read_P1_data(void) | 全局(声明) | 通过通讯棒读取 P1 采集器电表数据 |
void wireless_status_refresh(char *buf) | 全局(声明) | 解析云端下发的 JSON 中的 "WiFi info" 字段刷新无线状态 |
注意 u8 wifi_recv_flag(void); 被声明了两次(第 94 行与第 99 行),完全重复。
4. 核心逻辑解析
本文件不含可执行逻辑,但其类型设计的几个要点直接决定上层行为:
4.1 u8_wireless_uart_flag —— 串口互斥的唯一手段
该字段被声明为 volatile u8(第 63 行),是三层调用者共用的"串口占用锁":
wireless_driver.c:wireless_status_detect()在开头检查、占用、末尾释放;wireless_driver.c:wireless_read_P1_data()在检查通过后占用,末尾释放;ethernet.c:wireless_event_pro()检查占用则直接返回,占用后逐片发送并在末尾释放;ethernet.c:wireless_receive_event()也短暂占用。
没有任何原子操作或 uCOS-II 信号量保护,仅靠 volatile 提示编译器不要优化掉读写。
4.2 信号强度字段的"哨兵值"约定
s8_wireless_eirp = -99、u8_4g_rssi = 99、u8_4g_ber = 99 是本文件与实现文件共同约定的"无效值"。ethernet.c 与上层上报时依赖这些哨兵判断"无信号"而不是"信号 0"。这些魔数在三处实现里硬编码(wireless_driver.c:270/279/280/331/332/362/391-393、e_linker_wifi.c 未直接赋值但参与判断),没有宏定义。
4.3 PROTOCOL_TYPE_E 的位打包
ethernet.c:get_ethernet_server_port() 只读其中一个位 bit.u8_tcp_tls_support_flag,决定用端口 2(TLS)还是端口 1(非 TLS)。MQTT 相关位在本工程中暂未被使用,属预留。该字段由 e_linker_wifi.c:e_linker_protocol_support_state() 通过逐字符扫描 AT 响应中逗号分隔的位置填位(e_linker_wifi.c:1015-1024)。
4.4 6 个 tick 字段的用途分工
| 字段 | 用途 | 消费位置 |
|---|---|---|
u32_dectect_tick | 模块识别节流(10s) | wireless_driver.c:196 |
u32_link_tick | 连不上路由的 3 小时超时判据 | ethernet.c:1108-1124 |
u32_tcp_tick | 连上路由但 30 分钟连不上服务器 | ethernet.c:1127-1142 |
u32_wireless_check_tick | 5 分钟一次的常规状态巡检 | wireless_driver.c:245 |
u32_P1_read_tick | P1 抄表节流(800ms 下限) | wireless_driver.c:484 |
u32_P1_refresh_tick | P1 数据新鲜度判定(3s 超时判电表丢失) | wireless_driver.c:612 |
u32_WIFI_uart_tick | 串口帧间最小间隔(30ms) | wireless_driver.c:189/484、ethernet.c:763(已注释) |
4.5 E_LINKER_ID_INFO.u8_is4G 的双重来源
该字段在 wireless_status_refresh()(wireless_driver.c:125,从云端 JSON 的 sscanf 第 13 项)中被写入,同时 E_LINKER_ID_INFO 里的 SN/HW/SW 也在 wireless_module_find() 路径下由 get_e_linker_wifi_info()(AT 指令)填充。两条来源都会写同一个结构体,存在数据互相覆盖的可能。
5. 对外接口
本文件导出
- 类型:
WIRELESS_TYPE_E、PROTOCOL_TYPE_E、WIRELESS_TAB_T、E_LINKER_ID_INFO - 宏:
WIRELESS_POWER_PIN/WIRELESS_POWER_PORT、MAX_E_LINKER_SN_LEN/MAX_E_LINKER_P1_LEN/MAX_WIFI_4G_ICCID_LEN、调试开关 - 全局变量(extern):
WIRELESS_TAB_T g_t_wireless_info、E_LINKER_ID_INFO g_e_linker_info - 函数原型:上表 10 个(含重复的
wifi_recv_flag)
本文件引用的外部内容
chip.h—— GD32 基础类型(u8/s8/u16/u32)gpio.h——GPIO_PIN_7、GPIOH
6. 依赖关系
依赖:chip.h、gpio.h。
被依赖:
midware/ethernt/wireless/wireless_driver.c(实现)midware/ethernt/wireless/wifi/e_linker_wifi.c:15#include "wireless_driver.h"(使用g_t_wireless_info、AT_DEFAULT_PWD的兄弟宏、MAX_E_LINKER_SN_LEN)midware/ethernt/ethernet.h:14#include "wireless_driver.h"—— 因此net/ems.h、net/server.c、e_linker_wifi.c等全部间接可见midware/meter/meter.c:5879调用wireless_read_P1_data()net/server.c:7054调用wireless_status_refresh()
7. 备注与风险点
- 重复声明:
u8 wifi_recv_flag(void);在wireless_driver.h:94与:99出现两次。 - 死声明:
wifi_recv_flag()在整个工程中只有声明、没有任何定义(grep -rn "wifi_recv_flag"仅命中本头文件两行)。若某处真的调用它会链接失败;实际代码走的是wireless_recv_flag()(wireless_driver.h:79声明、wireless_driver.c:79定义、内部转发e_linker_recv_flag())。两个名字只差一个字符,是典型的命名陷阱。 volatile覆盖不全:只有u8_wireless_uart_flag加 volatile,其余被跨任务共享的字段(u8tcpstatus、u8linkstatus、各 tick)均无 volatile 也无临界区保护。- 哨兵值无宏:
-99、99用于表示信号无效,散落在实现里硬编码。 u8_link_tick拼写不统一:同一结构体内u8linkstatus无下划线而u32_link_tick有,易写错。elinker_4g_state的but7:该拼写错误在e_linker_wifi.h:31(不是本文件),但同属这套类型设计。PROTOCOL_TYPE_E的高 4 位:bit4..bit7保留未用,u8_all = 0清零后e_linker_protocol_support_state()用移位逐位赋值,若通讯棒上报超过 8 个字段会被if(l_u8_delim_tick > 7) break;截断(见e_linker_wifi.c:1022)。WIRELESS_TAB_T未打包:没有#pragma pack(1),也不持久化,属纯运行时结构,无兼容性问题。