SysChannel 通信
本案例演示 WS53 Device 与 Linux Host 通过 SDIO SysChannel 协同工作,包括报文分流、Device 信息上报和 Host 命令交互。完整验证需要匹配的 Linux 驱动、SDIO 硬件连接和 Host 构建环境,不能只烧录 WS53 单板完成。
学习目标
- 理解 SysChannel 的 Device、Linux Host 和网络报文分流关系。
- 掌握 WS53 侧通道初始化、过滤规则、收发回调和 IP/MAC 上报流程。
- 掌握 Host 侧
sample_link与sample_cli的职责和基本验证方法。
案例说明
Device 端源码位于:src/application/samples/wifi/syschannel_dev/
Linux Host 配套源码位于:src/application/samples/wifi/syschannel_host/linux/
Device 端设置网络报文过滤规则、初始化 SDIO SysChannel,并处理 Host 发来的命令。Host 端的 sample_link 负责连接内核 Netlink 通道、接收 Device 上报并维护 Linux 网络接口;sample_cli 通过本机 UDP 端口向 sample_link 发送控制命令。
flowchart LR
C[sample_cli] -->|UDP 127.0.0.1:8822| L[sample_link]
L <-->|Netlink mode 28| K[Linux SysChannel 驱动]
K <-->|SDIO| D[WS53 SysChannel Device]
D --> W[LwIP/Wi-Fi 网络栈]
关键配置
| 配置项 | 默认值或位置 | 说明 |
|---|---|---|
| Device sample | CONFIG_SAMPLE_SUPPORT_SYSCHANNEL_DEV |
使能后,Wi-Fi sample CMake 才加入 syschannel_dev |
| Device 传输类型 | SDIO_TYPE |
需与硬件和 Host 驱动一致 |
| Host 交叉工具链 | arm-himix100-linux |
定义在 syschannel_host/linux/base.mak,应按 Host 平台修改 |
| Host 网络接口 | wlan0 |
sample_link 使用该名称配置 MAC 和 IP |
| CLI 本机端口 | UDP 8822 | sample_cli 与 sample_link 的本地命令通道 |
| Netlink 参数 | PID 1100、mode 28 | 必须与配套内核驱动实现一致 |
Host 示例会配置 Linux wlan0 的 MAC 和 IP,需要相应权限。不要在生产设备上未经评估直接运行;接口名、Netlink 参数和权限模型都应按实际平台适配。
默认过滤规则
syschannel_set_default_filter() 先使用 WIFI_FILTER_VLWIP 设置默认去向,再通过 WIFI_FILTER_LWIP 添加送往 WS53 LwIP 的例外规则。
| 协议 | 匹配方向 | 端口 | 用途 |
|---|---|---|---|
| IPv4 UDP | 本地端口 | 68 | DHCP Client |
| IPv4 UDP | 本地端口 | 67 | DHCP Server |
| IPv4 TCP | 本地端口 | 6001 | 示例业务端口 |
| IPv4 TCP | 远端端口 | 6002 | 示例业务端口 |
| IPv4 UDP | 本地端口 | 7001 | 示例业务端口 |
| IPv4 UDP | 远端端口 | 7002 | 示例业务端口 |
| IPv6 UDP | 本地端口 | 68 | 示例 IPv6 过滤规则 |
6001、6002、7001 和 7002 只是示例值。产品应按真实协议修改,并检查端口方向、IPv4/IPv6 覆盖范围和默认去向,避免将管理报文错误转发到另一侧。
代码详解
1. 设置默认去向和精确过滤规则
static int syschannel_add_udp_local_filter(uint16_t port)
{
syschannel_ipv4_filter filter = {0};
filter.local_port = port;
filter.packet_type = IPPROTO_UDP;
filter.match_mask = WIFI_FILTER_MASK_LOCAL_PORT |
WIFI_FILTER_MASK_PROTOCOL;
filter.config_type = WIFI_FILTER_LWIP; /* 报文送往 WS53 */
return uapi_syschannel_add_filter((osal_char *)&filter,
sizeof(filter), WIFI_FILTER_TYPE_IPV4);
}
static int syschannel_config_filter(void)
{
int ret = uapi_syschannel_set_default_filter(WIFI_FILTER_VLWIP);
if (ret != OSAL_OK) {
return ret;
}
if (syschannel_add_udp_local_filter(68) != OSAL_OK) {
return OSAL_NOK;
}
return syschannel_add_udp_local_filter(67);
}
match_mask 决定哪些字段参与匹配,config_type 决定命中规则后的报文去向。新增 TCP 或远端端口规则时,应同时修改 packet_type、端口字段和对应的掩码位。
2. 初始化 Device 通道并注册回调
案例在独立任务中初始化 SysChannel,避免阻塞系统启动流程。核心顺序如下。
static int syschannel_device_start(void)
{
if (netifapi_netif_add_ext_callback(&callback,
app_demo_netif_ext_callback) != ERR_OK) {
return OSAL_NOK;
}
if (syschannel_set_default_filter() != OSAL_OK) {
return OSAL_NOK;
}
uapi_syschannel_register_rx_cb(syschannel_rx_callback);
uapi_syschannel_register_timeout_cb(syschannel_timeout_callback);
if (uapi_syschannel_dev_init(SDIO_TYPE) != OSAL_OK) {
return OSAL_NOK;
}
uapi_syschannel_register_suspend_cb(syschannel_suspend_callback);
return OSAL_OK;
}
仓库案例实际将网络回调和过滤器注册封装在 syschannel_dev_init_demo() 中,并在 sdio_init_task_body() 调用 uapi_syschannel_dev_init()。产品移植时应保留错误回滚:初始化失败后不得继续发送数据,也不能向业务报告通道已就绪。
3. 处理 Host 命令
Device 示例识别以下三个文本命令。
| 命令 | Device 行为 |
|---|---|
cmd_get_mac |
读取网络接口 MAC,并向 Host 返回“命令类型 + 6 字节 MAC” |
cmd_get_ip |
返回命令类型、IPv4 地址、掩码和网关 |
cmd_set_filter |
重新设置默认过滤规则 |
static const char g_host_cmd[][20] = {
"cmd_get_mac",
"cmd_get_ip",
"cmd_set_filter",
};
unsigned int syschannel_rx_callback(unsigned char *buf, int length)
{
struct netif *netif = get_syschannel_netif();
if ((buf == NULL) || (length <= 0) || (netif == NULL)) {
return OSAL_NOK;
}
/* 比较前必须同时校验 length 和命令字符串长度。 */
if (syschannel_cmd_equal(buf, length, g_host_cmd[0])) {
syschannel_send_mac(netif);
} else if (syschannel_cmd_equal(buf, length, g_host_cmd[1])) {
syschannel_send_ip(netif);
} else if (syschannel_cmd_equal(buf, length, g_host_cmd[2])) {
(void)syschannel_set_default_filter();
}
return OSAL_OK;
}
syschannel_cmd_equal() 表示产品应补充的带长度比较封装。原案例展示了命令分发思路;正式实现应避免对非 NUL 结尾的 Host 缓冲区直接使用无界字符串比较。
4. 上报 MAC、IP 和网络变化
MAC 消息共 7 字节:第 1 字节为 HOST_CMD_GET_MAC,后续 6 字节为 MAC。IP 有效载荷为 13 字节:1 字节命令类型、4 字节 IPv4 地址、4 字节掩码和 4 字节网关。
osal_char mac_msg[SYSCHANNEL_MAC_ADDR_LEN + 1] = {0};
mac_msg[0] = HOST_CMD_GET_MAC;
(void)memcpy_s(&mac_msg[1], SYSCHANNEL_MAC_ADDR_LEN,
netif->hwaddr, SYSCHANNEL_MAC_ADDR_LEN);
uapi_syschannel_send_to_host(mac_msg, sizeof(mac_msg));
Device 示例还注册了 LwIP netif 扩展回调,在 IPv4 地址发生变化时主动上报。Host 解析协议时必须以消息类型和实际长度为准,并统一约定字节序。
Note
当前示例构造的 IP 有效内容为 13 字节,但调用 uapi_syschannel_send_to_host() 时传入 MAX_IPV4_LEN + 1。如果 Host 协议只定义上述 13 字节,产品适配时应统一双方长度定义,不能依赖额外的尾部零字节。
5. Host 侧命令链路
Host 端构建生成两个程序:
sample_link:初始化 SysChannel、注册接收回调、与 Netlink 驱动通信,并配置wlan0。sample_cli:将一条命令发往127.0.0.1:8822,等待sample_link返回结果。
sample_link 启动后会主动发送 cmd_get_mac。其 CLI 明确支持 help 和 quit;其他输入会作为设备控制命令转交,能否执行取决于 Host 驱动和 Device 侧协议实现。
6. 超时、挂起和重新初始化
案例注册了心跳超时和挂起回调,但回调中的复位/重新探卡流程只是设计注释。超时回调可能运行在中断上下文,不能直接执行等待 SDIO 卡等阻塞操作。
推荐处理方式:
- 回调中仅设置“需要复位/重新探卡”标志并唤醒恢复任务。
- 恢复任务调用
uapi_syschannel_dev_reset()清理旧状态。 - 根据 Host 上下电策略等待硬件稳定。
- 在任务上下文调用
uapi_syschannel_dev_reinit(),重新注册必要状态并恢复收发。 - 恢复成功前保持上层业务离线,避免继续使用旧通道。
运行与验证
- 确认 WS53 与 Linux Host 的 SDIO 硬件连接、供电时序和内核 SysChannel 驱动匹配。
- 在 WS53 目标配置中使能
CONFIG_SAMPLE_SUPPORT_SYSCHANNEL_DEV,构建、烧录并检查syschannel dev init success和sdio init finish日志。 - 进入
src/application/samples/wifi/syschannel_host/linux/,确认base.mak中的交叉工具链适用于目标 Host,再执行make构建sample_link和sample_cli。 - 以具备网络接口配置权限的用户启动
sample_link,确认 Netlink 初始化成功并能收到 Device 的 MAC/IP 消息。 - 在另一终端执行
sample_cli help,验证本地 CLI 通道;完成测试后执行sample_cli quit。 - 触发 WS53 DHCP 地址变化,确认 Host 能收到更新且
wlan0配置符合预期。 - 分别验证未知命令、错误长度、通道断开、心跳超时、Host 重启和 Device 重新初始化。
- 将示例端口、接口名、Netlink 参数和命令协议替换为产品配置后,再进行压力与异常恢复测试。
构建 WS53 固件的基础流程参见快速入门。