feat(aic8800): AIC8800DC SoftAP for SG2002 — boot AP, SSH + HTTP, client reconnect#1318
Conversation
Port the AIC8800DC firmware/driver path so the boot-time SoftAP brings up, broadcasts, accepts client association, and carries data (SSH verified) on the LicheeRV Nano (SG2002). Key fixes that made the AP functional: - TX data-plane (MGMT + DATA 802.11 frames) routed on func1 (data_func), not func2 (command mailbox). func2 is command/CFM only, func1 is the data plane for both TX and RX. This was why no client could ever associate. - MGMT frame field fixes: byte[2]=0x01 on both frame builders, ac=3 (VO). - AIC8800DC firmware image/init path (fw/firmware/dc.rs + chip variant). - Diagnostic logging at info for CMD sent / CFM received / MGMT sent, to make the command->CFM round-trip observable on hardware. Runtime AP<->STA mode switching is not yet functional and is tracked separately; the boot AP path is the verified milestone here.
Builds on the boot-AP milestone (6518369) to make the AIC8800DC SoftAP reliable enough for sustained client traffic and reconnection. Verified on SG2002 (LicheeRV Nano): client associates fast, SSH and HTTP both work, and a client can reconnect after disconnecting. Four independent fixes, each rooted in an observed failure on real hardware: - TX poll kicker (tx.rs): wifi-tx is an edge-triggered poll task that registers its waker after tx_process; a wake() landing in that window is lost (PollSet has no sticky bit) and, combined with the pending_flag head-of-line block, freezes all TX for seconds. RX already had a 10ms kicker for the same hazard; add the symmetric one for TX so any lost wake is recovered within ~10ms. - ME_STA_ADD dedup with control-port self-heal (ap.rs, bus.rs): the firmware does not CFM a repeated ME_STA_ADD for an already-registered MAC, so a phone retransmitting AssocReq made the AP worker block 5s and timeout. Track registered STAs as (mac, sta_idx, ctrl_port_open); skip ME_STA_ADD for known MACs, and retry opening the control port on re-assoc until it actually succeeds (a timed-out control-port open previously left data frames dropped by the firmware → no ping/SSH). - Deauth/Disassoc handling (rx.rs): these were silently ignored, so a disconnected STA stayed in the dedup table and reconnects were skipped entirely. Remove the MAC from the table on 0xC/0xA so a reconnect fully re-registers. - Demote per-frame hot-path logs info→debug (rx.rs, tx.rs): on the single- core cooperative scheduler each info log is a blocking UART write; during an Auth flood these starve the TX/kicker tasks. Demoting them markedly speeds up association. Per-connection events (registered, control port OPENED, deauth) stay at info.
- cargo fmt across the AIC8800DC SoftAP changes (import wrapping, multi-line log argument formatting). - Replace `kicks % 100 == 0` with `kicks.is_multiple_of(100)` in the RX poll kicker to satisfy clippy::manual_is_multiple_of under -D warnings. No functional change.
There was a problem hiding this comment.
Review — PR #1318 (AIC8800DC SoftAP)
整体方向清晰,DC 固件 bring-up 和 SoftAP 稳定性改进的思路合理,代码注释充分。以下是阻塞和非阻塞发现。
🔴 阻塞问题
1. 与 dev 分支存在合并冲突
PR 当前 mergeStateStatus=dirty,3 个文件与 dev 有冲突:
components/aic8800/src/fdrv/protocol/cmd.rscomponents/aic8800/src/fdrv/thread/rx.rscomponents/aic8800/src/fdrv/thread/tx.rs
请 rebase 到最新 dev 顶端后解决冲突。
2. DIAG 诊断日志不应使用 log::info!
init.rs 中 poll_for_response 添加了每 500 次重试扫描 func1/func2 block_cnt 的 [DIAG] 日志,级别为 info。单核协作调度下 info 级别每条都是一次阻塞式 UART 写入,会显著拖慢轮询路径。请降级为 log::debug! 或 log::trace!。具体位置:
init.rs~L178-192:poll_for_response中的[DIAG] retry=...日志init.rs~L295-300:polling_send_cmd中的pre-send block_cnt f1/f2日志
3. AIC8801/D80 回归风险未隔离
作者自己在 PR body 里提到 AIC8801 实测已有回归。以下改动无 ChipVariant 门控,对所有变体生效:
rx.rs:drain_func(bus, 2)+drain_func(bus, 1)— D80/8801 本来只读 func1,现在额外读 func2tx.rs: byte[2]=0x01 变更、ac=3(VO) 变更rx.rs: Auth/AssocResp 的 log 级别从 info→debug 对所有变体生效
建议对 DC-only 的行为差异加 matches!(chip, Aic8800DC | Aic8800DW) 门控,或至少在 PR body 的回归状态更新后再合入。
🟡 非阻塞建议
4. 生产环境诊断计数器
rx.rs 中的 RX_KICK_COUNT、RX_POLL_COUNT、RX_LAST_BLOCKCNT、RX_NONZERO_READS 静态变量及其 trace 输出是调试用的。建议用 #[cfg(debug_assertions)] 包裹,或在确认 DC 稳定后移除。
5. registered_stas 无容量上限
ApState::registered_stas 是 Vec,只在 deauth/disassoc 时 remove。虽然当前 aid=1 限制实际不会增长太多,但建议加一个合理上限(如 16)或换用 BoundedVec。
6. CI 无 check runs
此 PR 的 head SHA 9f23f98 没有任何 GitHub Actions check runs。请确认 CI 工作流是否正常触发。
总结: 方向正确、注释详尽,但需解决合并冲突并将 DIAG 日志降级后再合入。同时建议隔离对 D80/8801 的行为变更。
Powered by mimo-v2.5-pro
# Conflicts: # components/aic8800/src/fdrv/protocol/cmd.rs # components/aic8800/src/fdrv/thread/rx.rs # components/aic8800/src/fdrv/thread/tx.rs
After merging upstream/dev's func-agnostic RX refactor, process_rx_frames drained both func2 and func1 unconditionally. Only DC/DW route the command CFM/indication mailbox to func2; 8801/D80 keep command+data on func1, so polling func2 there issued a wasted CMD52 every RX cycle. Gate the func2 drain on cmd_func()==2 to keep the three variants on their correct path.
…STA table Review feedback from mai-team-app: - init.rs: demote [DIAG] retry scan and cmd-send/pre-send block_cnt logs from info to debug/trace; gate the extra register reads behind log_enabled!(Trace) so the production polling path issues no extra CMD52. - rx.rs: drop orphaned diagnostic counters (RX_POLL_COUNT / RX_LAST_BLOCKCNT / RX_NONZERO_READS); cfg(debug_assertions)-gate the remaining RX_KICK_COUNT heartbeat. - ap.rs: bound registered_stas at MAX_REGISTERED_STAS (16) to prevent unbounded growth from AssocReq without matching deauth. - tx.rs: mgmt-frame ac=VO is now gated to DC/DW (dual_pipe); 8801/D80 keep vendor ac=BK to match upstream/dev and avoid regression. byte[2] reverted to the shared SDIO_TYPE_DATA constant (== 0x01 on both sides, so it was never a behavior change).
There was a problem hiding this comment.
二次审查 — PR #1318 (AIC8800DC SoftAP)
本审查基于最新 head 928daa40a,已在本地完成代码审读和验证。
改动概述
将 SoftAP 路径移植到 AIC8800DC(DC-H) 芯片 + CV1800 SDIO host。主要改动:
- SDIO 命令邮箱路由:DC/DW 命令走 func2,数据走 func1
- TX poll kicker 修复边沿触发丢失唤醒问题
- ME_STA_ADD 去重 + 控制端口自愈
- Deauth/Disassoc 处理(从注册表移除使重连完整)
- 热路径日志降级 info→debug
- 新增 DC-H 专用固件及 RF 校准路径
🔴 阻塞问题
1. CI 失败:Run clippy / run_host 构建 panic
build.rs 在尝试下载 remote_path: "" 的固件时 panic:
failed to GET https://raw.githubusercontent.com/lxowalle/aic8800-sdio-firmware/c56f910044cc854d6c553bcb9a644f3bca5a4c38/: http status: 400
7 个新增固件文件(fmacfw_patch_8800dc_h_u02.bin、fmacfw_patch_tbl_8800dc_h_u02.bin、fmacfw_calib_8800dc_h_u02.bin、dc_ldpc_cfg_ram.bin、dc_agc_cfg_ram.bin、dc_txgain_map.bin、dc_txgain_map_h.bin)设置了 remote_path: "",注释说明为 "In-tree only"。但 components/aic8800/firmware/ 目录为空(仅有 .gitignore 和 README.md),导致 build script 尝试下载时拼出 URL 以 c8/ 结尾(commit hash + 空路径),HTTP 400 报错。
修复方向:
- 将 DC-H 固件二进制文件提交到
components/aic8800/firmware/目录;或 - 为这些文件设置有效的
remote_path(上传到上游固件仓库);或 - 在
download()函数中对空remote_path发出更明确的错误信息而非 panic。
上一次审查(mai-team-app[bot])当时此问题尚未出现(审查针对的是
9f23f98旧 head),新 push928daa40a引入了这些 in-tree-only 文件但未提交实际固件。
2. 所有变体行为变更未隔离
作者在 PR body 中已承认 AIC8801 实测存在回归。以下改动对所有芯片变体生效,无 ChipVariant 门控:
rx.rs中process_rx_frames的drain_func(bus, 2)— 对 D80/8801 多排空了一次 func2tx.rs中 MGMT 帧构造器的 byte[2]=0x01、ac=3(VO) 变更rx.rsAuth/AssocResp 日志级别 info→debug 对所有变体生效
建议对 DC-only 的行为差异加 matches!(chip, Aic8800DC | Aic8800DW) 门控,或至少在 D80/8801 回归验证通过前不合并。
🟡 非阻塞建议
3. init.rs DIAG 诊断日志已降级为 trace
上次审查建议将 poll_for_response 中的寄存器扫描和 polling_send_cmd 的 pre-send 读数从 info 降级。当前代码已将 DIAG 日志改为 log::trace! 并加了 log::log_enabled! 守卫。✅ 已解决。
4. registered_stas 已添加容量上限
consts.rs 新增 MAX_REGISTERED_STAS: usize = 16,ap.rs 中在注册前检查容量。✅ 上次建议已采纳。
5. 生产环境诊断计数器
rx.rs 中的 RX_KICK_COUNT、RX_POLL_COUNT 等静态变量及 trace 输出已用 #[cfg(debug_assertions)] 包裹。✅ 已处理。
CI 状态分析
CI workflow 对当前 head 928daa40a 的检查结果:
Check formatting / run_host→ SUCCESS ✅Run sync-lint / run_container→ SUCCESS ✅Run clippy / run_host→ FAILURE ❌(构建 panic,见上)Test axvisor x86_64 svm hosted / run_host→ SUCCESS ✅- 其余测试因 clippy 失败被 CANCELLED(预期行为)
本地验证:cargo fmt --check 通过 ✅。clippy 无法在本地完成验证(同样因 firmware 缺失触发 build.rs panic)。
重复/重叠分析
未发现其他 open PR 与此 PR 重叠。PR #1185、#1266、#1276 已合入 dev,是本 PR 的前置基础。
审查结论
请求变更:CI clippy 失败为 PR 直接导致的阻塞问题(firmware 文件缺失),且对所有变体的行为变更未隔离,作者已确认 AIC8801 存在回归。请修复 build.rs panic 后重新提交,并对 DC-only 差异加变体门控或完成 D80/8801 回归验证。
Powered by mimo-v2.5-pro
Two AP-mode stability fixes for "associates + gets IP but ping/SSH dead": 1. MM_STA_DEL on disconnect. Downlink data frames route by a single global sta_idx (hostdesc staid); firmware delivers reliably only to low slots. The deauth/disassoc handler cleared the driver table but never sent MM_STA_DEL_REQ, so the firmware kept the old slot and the NEXT station got a higher sta_idx (0->1->2...) whose downlink never arrived — the client kept re-ARPing and ping/SSH failed. Now the RX handler enqueues the freed sta_idx (can't send_cmd on the RX thread — CFM is processed there, would deadlock; same reason AssocReq is queued), and the AP worker drains the del-queue BEFORE the assoc-queue so a reconnecting STA reuses the known-good low slot. 2. Control-port reconcile. Opening the control port (authorize) could time out under single-core UART starvation; the old code only retried on AssocReq re-transmission, which a settled client never sends, so the data plane stayed dead. The AP worker now periodically re-issues SET_CONTROL_PORT for any unauthorized STA (capped at CONTROL_PORT_MAX_RETRY) until it succeeds. Still single-concurrent-STA by design (one global sta_idx, one DHCP lease).
There was a problem hiding this comment.
PR #1318 Review — AIC8800DC SoftAP for SG2002
总体评价: PR 结构清晰、commit 历史规整(7 commits)、描述详尽,DC 固件 bring-up 和 SoftAP 稳定性修复的技术设计合理。之前两轮 inline 评论均已回应(DIAG 日志降级 ✅、func2 drain 门控 ✅)。以下是复审发现,有一项阻塞合入。
🔴 阻塞:AIC8801 回归未解决
PR body 已明确写到:
⚠️ AIC8801 上板实测:当前镜像无法连入 boot AP、无法模式切换……本 PR 改动均无is_v3/ChipVariant门控、对所有变体生效,故不排除影响;D80 回归状态待复测。合入前需在 D80/8801 上回归验证。
这说明作者自己认为回归未解决。以下改动对所有芯片生效,任何一项都可能引起回归:
registered_stas去重逻辑(ap.rshandle_assoc_req):D80/8801 固件是否也对重复 MAC 的ME_STA_ADD不回 CFM?如果不是,去重会跳过合法注册。MM_STA_DEL_REQ(apm.rs):D80/8801 是否支持此消息?虽然send_mm_sta_del_req失败只 warn 不 panic,但未知固件行为可能引起副作用。- 控制端口对账(
reconcile_control_ports):50ms 周期自唤醒 +CONTROL_PORT_MAX_RETRY=20,在 D80/8801 上的行为未验证。 - TX/RX poll kicker:新增两个 10ms 周期任务,独占 ax_task 线程,在 D80/8801 上是否影响调度?
建议: 至少在 D80 上完成 SoftAP 回归测试后再合入。如果短期无法测试,建议对 registered_stas 去重、sta_del_queue 处理、控制端口对账等逻辑加 ChipVariant 门控(仅 DC/DW 启用),避免影响既有芯片。
🟡 建议:build.rs 空 remote_path 会 panic
DC-H 固件和 RF cfg blob 共 7 个文件的 remote_path 为空字符串:
FirmwareFile {
name: "fmacfw_patch_8800dc_h_u02.bin",
remote_path: "", // ← download() 会拼出无效 URL 并 panic
sha256: "e3257b...",
},download() 函数构造 https://raw.githubusercontent.com/.../{remote_path},空路径会导致 404 并 panic!。
当前 components/aic8800/firmware/ 目录为空(只有 .gitignore 和 README.md),这些文件不在 in-tree 目录中。如果 $AIC8800_FIRMWARE_DIR 也没设置,build 会直接失败。
建议: 在 download() 开头加 guard:
fn download(file: &FirmwareFile) -> Vec<u8> {
if file.remote_path.is_empty() {
panic!("firmware {} is in-tree only but not found in firmware/ dir or $AIC8800_FIRMWARE_DIR", file.name);
}
// ...
}或者将 DC-H 固件文件提交到 in-tree firmware/ 目录。
🟢 代码质量小结
-
registered_stas用裸 tuple(mac, idx, ctrl_open, retries)访问(ap.rs):e.2 = true、e.3.saturating_add(1)可读性差。建议改为命名 struct:struct RegisteredSta { mac: [u8; 6], sta_idx: u8, ctrl_open: bool, retries: u8, }
bus.rs 中已有
pub type RegisteredSta = ([u8; 6], u8, bool, u8);的 type alias,改为 struct 更安全。 -
cmd_func逻辑三处重复:init.rs::cmd_func()、SdioTransport::cmd_func()、IpcTransport::cmd_func()。建议统一到一处(如ChipVariant上的方法),避免新增芯片变体时遗漏。 -
MM_STA_DEL_REQtimeout=0(ap.rssend_mm_sta_del_req(&bus, idx, 0)):fire-and-forget 设计合理(避免 AP worker 阻塞),但建议加一行注释说明为何 timeout=0。 -
data_func()永远返回 1(sdio_transport.rs):对 DC/DW 正确(数据面在 func1),但建议加注释说明这是 by-design 而非临时 hardcode。
✅ 正面评价
- DC 固件 bring-up 序列(dc.rs)移植自 vendor BSP,步骤完整、注释详尽
- SDIO 双管道架构(cmd_func vs data_func)设计清晰
- TX/RX poll kicker 解决 PollSet 无 sticky 的根本问题,对称且优雅
- STA 去重 + 控制端口对账 + Deauth 清理构成完整的 AP 生命周期管理
- 热路径日志降级(info→debug/trace)对单核调度性能有实质改善
- PR 描述坦诚记录已知问题和回归风险
结论: request_changes。核心阻塞项是 AIC8801 回归(作者自己也标记为合入前必验)。建议先做 D80/8801 回归测试,或对新逻辑加芯片门控。build.rs 空路径问题建议一并修复。
Powered by mimo-v2.5-pro
CI `Run clippy / run_host` panicked in build.rs: the 7 AIC8800DC-H
firmware/RF-config blobs have remote_path "" (no upstream mirror — they're
extracted from the vendor BSP/rootfs), but firmware/.gitignore ignored
*.bin, so they were absent from a fresh checkout. build.rs then fell
through to download("") and hit HTTP 400.
- Allow-list the 7 in-tree-only blobs in firmware/.gitignore (downloadable
blobs stay ignored and keep coming from the upstream mirror).
- Commit the blobs; their SHA-256 already match the digests in build.rs.
- Harden download(): assert remote_path is non-empty with an actionable
message instead of emitting a confusing 400.
There was a problem hiding this comment.
第四轮审查 — PR #1318 (AIC8800DC SoftAP for SG2002)
审查基于: head 0a501f8649 (最新 push,含 vendor firmware 修复)
改动概述
将 SoftAP 路径移植到 AIC8800DC(DC-H) + CV1800 SDIO host。核心改动:
- SDIO 双管道架构:cmd_func/data_func 分离(DC/DW 命令走 func2,数据走 func1)
- TX/RX poll kicker 修复边沿触发丢失唤醒
- ME_STA_ADD 去重 + 控制端口自愈
- Deauth/Disassoc 处理 + MM_STA_DEL_REQ
- 热路径日志降级 info→debug/trace
- DC-H 固件内嵌 + build.rs 空路径 assert
已解决的前轮问题 ✅
- DIAG 日志降级(review #1)→ 已改为
log::trace!+log::log_enabled!守卫 ✅ - build.rs 空 remote_path panic(review #2)→ 已加
assert!(!file.remote_path.is_empty())并 vendor 固件二进制 ✅ - drain_func 门控(review #1/#2)→ 已用
if bus.transport.cmd_func() == 2 { drain_func(bus, 2); }门控 ✅ - registered_stas 容量上限(review #2)→ 已加
MAX_REGISTERED_STAS = 16✅ - 诊断计数器(review #2)→ 已用
#[cfg(debug_assertions)]包裹 ✅ - CMD/数据 FIFO func 路由 → 已用
transport.cmd_func()/transport.data_func()✅ - reinit_sdio_func DC 专用路径 → 已用
is_dcflag 门控 ✅
CI 状态
| 检查 | 结果 |
|---|---|
| Check formatting / run_host | ✅ SUCCESS |
| Run sync-lint / run_container | ✅ SUCCESS |
| Run clippy / run_host | ✅ SUCCESS |
| Test axvisor riscv64 qemu / run_host | ✅ SUCCESS |
| Test axvisor self-hosted x86_64 UEFI / run_host | ✅ SUCCESS |
| Test axvisor loongarch64 qemu / run_container | ✅ SUCCESS |
| Test axvisor self-hosted board orangepi-5-plus-linux | ✅ SUCCESS |
| Test arceos aarch64/x86_64/loongarch64 qemu | ✅ SUCCESS |
| Test axvisor self-hosted x86_64 / run_host (smoke-vmx) | ❌ FAILURE |
| 其余 starry 测试 | CANCELLED(被上者取消) |
smoke-vmx 失败是 axvisor x86_64 VMX 测试,与 aic8800 WiFi 驱动无关联(PR 仅改 components/aic8800/),且同机 axvisor x86_64 UEFI 测试通过。判定为无关 CI 失败。
🔴 阻塞:AIC8801/D80 回归未验证
PR body 已明确声明:
⚠️ AIC8801 上板实测:当前镜像无法连入 boot AP、无法模式切换……本 PR 改动均无is_v3/ChipVariant门控、对所有变体生效,故不排除影响;D80 回归状态待复测。合入前需在 D80/8801 上回归验证。
经审读最新代码,以下改动对所有芯片变体生效且无 ChipVariant 门控:
-
STA 注册去重(ap.rs
handle_assoc_req):已注册 MAC 跳过 ME_STA_ADD。D80/8801 固件是否也对重复 MAC 不回 CFM?如果不是,去重会跳过合法重新注册,导致重连失败。 -
MM_STA_DEL_REQ(apm.rs + ap.rs
sta_del_queue):D80/8801 固件是否支持MM_STA_DEL_REQ消息?虽然失败仅 warn,但未知固件行为可能引起副作用(如固件内部状态不一致)。 -
控制端口对账(ap.rs
reconcile_control_ports):50ms 周期自唤醒 + 最多 20 次重试。D80/8801 上的行为未验证,额外的周期性命令可能干扰已有正常流程。 -
TX/RX poll kicker(tx.rs + rx.rs):各独占一个 ax_task 线程做 10ms 周期唤醒。D80/8801 上是否影响调度或造成不必要的 SDIO 竞争?
-
Deauth/Disassoc 处理(rx.rs):新增
0xC/0xA帧处理分支。
作者自己确认这是合入前必验项。当前无 D80/8801 回归测试证据。
建议方向(二选一):
- 方案 A:在 D80 上完成 SoftAP 回归测试(boot AP → 客户端关联 → ping/SSH → 断开重连),提供日志证据。
- 方案 B:对上述 1-5 项加
if matches!(chip, Aic8800DC | Aic8800DW)门控,仅 DC/DW 启用新行为,D80/8801 走原有路径。方案 B 工作量小且安全。
🟢 代码质量评价
- DC SDIO 双管道架构设计清晰,cmd_func/data_func 抽象合理
- TX/RX poll kicker 解决 PollSet 无 sticky 的根本问题,对称优雅
- STA 去重 + 控制端口对账 + Deauth 清理构成完整的 AP 生命周期管理
- 固件 bring-up 序列(dc.rs)注释详尽
registered_stas用裸 tuple(mac, idx, ctrl_open, retries)可读性稍差,建议后续改为命名 struct
重复/重叠分析
未发现其他 open PR 与本 PR 重叠。PR #1185、#1266、#1276 已合入 dev,是本 PR 的前置基础。
结论:方向正确、代码质量好、前轮问题均已修复。请求变更:核心阻塞项是 AIC8801/D80 回归(作者自己标记为合入前必验)。建议先做 D80 回归测试,或对通用行为加芯片门控。
Powered by mimo-v2.5-pro
Reviewer flagged 5 AP-lifecycle changes from the DC port that applied to all chip variants without gating, risking regressions on the existing AIC8801/D80 support (which lacked re-verification). Add ChipVariant back to SdioTransport (it was collapsed into is_v3/cmd_func proxies) plus a semantic `is_dual_pipe()` predicate, and gate all 5 behind it so D80/8801 follow the upstream/dev path verbatim: 1. STA registration dedup + registered_stas table maintenance 2. MM_STA_DEL_REQ slot reclaim queue 3. Periodic control-port reconciliation (50ms retry loop) 4. TX/RX poll kickers (10ms wakeup tasks) 5. Deauth/Disassoc de-registration Non-DC branches verified byte-equivalent to baseline handle_assoc_req. Verified on hardware: - AIC8800DC (newboard): SoftAP + ping/SSH + AP<->STA mode switch OK - AIC8801 (LicheeRV Nano): SoftAP + ping/SSH OK (no regression)
已按方案 B 加芯片门控 + 回归验证 (commit f6fb19b)感谢细致 review。核心阻塞项「AIC8801/D80 回归」已处理,采用建议的方案 B。 门控落地
非 DC 分支已逐项与 baseline 回归验证(真机)
关于 8801 在第三方板的 SSH 卡顿排查确认与本 PR 内核改动无关,属该板 fip.bin(boot firmware)阶段的 SDIO 引脚/PHY 配置:① SDIO 时钟写死且恒 25MHz(不读 DTB);② CIsmoke-vmx 失败是 axvisor x86_64 VMX 测试(本 PR 仅改 |
There was a problem hiding this comment.
第五轮审查 — PR #1318 (AIC8800DC SoftAP for SG2002)
审查基于: head f6fb19b(最新 push)
改动概述
将 SoftAP 路径移植到 AIC8800DC(DC-H) + CV1800 SDIO host。核心改动:
- SDIO 双管道架构:cmd_func/data_func 分离(DC/DW 命令走 func2,数据走 func1)
- TX/RX poll kicker 修复边沿触发丢失唤醒
- ME_STA_ADD 去重 + 控制端口自愈
- Deauth/Disassoc 处理 + MM_STA_DEL_REQ 槽位回收
- 热路径日志降级 info→debug/trace
- DC-H 固件内嵌 + build.rs 空路径 assert
- 所有 5 项 AP 生命周期改动全部用
is_dual_pipe()门控到仅 DC/DW
前轮问题解决状态
| 问题 | 状态 |
|---|---|
| 合并冲突 | ✅ 已解决 |
| DIAG 日志降级 | ✅ 改为 log::trace! + log::log_enabled! 守卫 |
| build.rs 空 remote_path panic | ✅ 加 assert! + 固件二进制已 vendor 到 in-tree |
| drain_func 门控 | ✅ cmd_func() == 2 门控 |
| registered_stas 容量上限 | ✅ MAX_REGISTERED_STAS = 16 |
| AIC8801/D80 回归 | ✅ 5 项全部 is_dual_pipe() 门控 + AIC8801 真机验证无回归 |
| 诊断计数器 | ✅ #[cfg(debug_assertions)] 包裹 |
芯片门控验证
逐一确认代码中 5 项 AP 生命周期改动的门控:
- STA 注册去重 →
ap.rs:100let dual = bus.transport.is_dual_pipe() - MM_STA_DEL 槽位回收 →
ap.rs:35if bus.transport.is_dual_pipe() - 控制端口周期对账 →
ap.rs:62if bus.transport.is_dual_pipe() - TX poll kicker →
tx.rs:50if bus.transport.is_dual_pipe() - Deauth/Disassoc 清表 →
rx.rs:444if !bus.transport.is_dual_pipe() { return; }
非 DC/DW 分支走与 upstream/dev 逐字节一致的原有路径,不受 DC 适配影响。
CI 状态
CI workflow 对当前 head f6fb19b 的整体结论为 SUCCESS。各测试矩阵 job 因路径过滤器(PR 仅改 components/aic8800/)而 skip,属于预期行为。前轮 smoke-vmx 失败为 axvisor x86_64 VMX 测试,与本 PR 的 aic8800 驱动无关。
本地验证:cargo fmt --check -p aic8800 通过 ✅。无 [patch.crates-io] 引入。
回归测试
作者已提供真机验证:
- AIC8800DC(LicheeRV Nano / SG2002):SoftAP 广播、客户端关联、SSH + HTTP 互通、断开重连、AP↔STA 模式切换 ✅
- AIC8801(LicheeRV Nano):boot AP + 客户端关联 + ping + SSH 全通,门控后无回归 ✅
- D80:暂无板实测,通过门控走已验证 dev 路径作为护栏
重复/重叠分析
未发现其他 open PR 与本 PR 重叠。PR #1185、#1266、#1276 已合入 dev,是本 PR 的前置基础。
审查结论
批准合入。经过 4 轮审查,所有阻塞问题均已解决:合并冲突已修复、日志级别已降级、固件已 vendor、所有行为差异已门控到 DC/DW。AIC8801 真机验证无回归。代码设计合理(双管道 SDIO 架构、PollSet 唤醒修复、STA 生命周期管理),注释详尽,CI 通过。
Powered by mimo-v2.5-pro
ZR233
left a comment
There was a problem hiding this comment.
当前 head:f6fb19b29aa8ec2a52a9eeba18eac8e71fbe8446
复审通过。此前的阻塞项已经逐项处理:合并状态为 CLEAN;DIAG 日志已降级并加 trace 守卫;in-tree only 固件已经提交且 build.rs 对空 remote_path 给出明确断言;func2 drain 以及 AP 生命周期相关逻辑均已用 is_dual_pipe()/cmd_func() 门控到 DC/DW 路径,避免影响 AIC8801/D80 的既有路径。
本地验证:
- cargo fmt --check -p aic8800
- cargo xtask clippy --package aic8800
- git diff --check origin/dev...HEAD
- 校验 components/aic8800/firmware/*.bin 的 sha256 与 build.rs 清单一致
CI 当前为通过/按路径过滤跳过的预期状态。真机验证依赖 SG2002/AIC8800DC/AIC8801 硬件,本机无法复跑;作者已在 PR 中补充 AIC8800DC 与 AIC8801 的实测结果。当前仍显示的旧 bot unresolved threads 对应问题在代码中已处理,建议合入前在 GitHub 上做行政性 resolve。
Per review, remove all .bin blobs from components/aic8800/firmware/. The 7 AIC8800DC-H blobs were the only ones vendored in-tree; the rest were already fetched at build time. They split into two kinds: - 3 firmware images (fmacfw_patch / fmacfw_patch_tbl / fmacfw_calib _8800dc_h_u02) are now fetched from the pinned upstream mirror (lxowalle/aic8800-sdio-firmware @ c56f910), same as every other blob, with SHA-256 verification. Board-tested on AIC8800DC: SoftAP + SSH + AP<->STA mode switch all work with these upstream versions. - 4 RF config tables (ldpc / agc / txgain / txgain_h) are NOT firmware images and have no upstream mirror -- they are little-endian u32 arrays from the vendor BSP source aic8800dc_compat.c. Inlined as Rust byte arrays in src/fw/firmware/dc_rf_cfg.rs (byte-identical to the removed blobs), so no .bin is kept for them either. components/aic8800/firmware/ now contains zero .bin files. .gitignore drops the per-file allow-list; README documents both sources.
|
已清理 bin 文件 (commit 90bdc07)。
三块板(AIC8801 / AIC8800DC / AIC8800D80)均已真机验证 SoftAP + 模式切换正常。本地发布检查全过: |
There was a problem hiding this comment.
第六轮审查 — PR #1318 (AIC8800DC SoftAP for SG2002)
审查基于: head 90bdc079a(最新 push:stop vendoring DC-H firmware blobs in-tree)
改动概述
将 SoftAP 路径移植到 AIC8800DC(DC-H) + CV1800 SDIO host。核心改动:
- SDIO 双管道架构:cmd_func/data_func 分离(DC/DW 命令走 func2,数据走 func1)
- TX/RX poll kicker 修复边沿触发丢失唤醒
- ME_STA_ADD 去重 + 控制端口自愈
- Deauth/Disassoc 处理 + MM_STA_DEL_REQ 槽位回收
- 热路径日志降级 info→debug/trace
- DC-H 固件改为从上游下载(不再 in-tree vendor)+ RF cfg 内联为 Rust 字节数组
- 所有 5 项 AP 生命周期改动全部用
is_dual_pipe()门控到仅 DC/DW
前轮问题解决状态
| 问题 | 状态 |
|---|---|
| DIAG 日志降级 | ✅ log::trace! + log::log_enabled! 守卫 |
| build.rs 空 remote_path | ✅ DC-H 固件改上游下载,assert guard 保留 |
| drain_func 门控 | ✅ cmd_func() == 2 门控 |
| registered_stas 容量上限 | ✅ MAX_REGISTERED_STAS = 16 |
| 5 项 AP 生命周期门控 | ✅ 全部 is_dual_pipe() 门控 |
| AIC8801/D80 回归 | ✅ AIC8801 真机验证无回归 |
| 诊断计数器 | ✅ #[cfg(debug_assertions)] 包裹 |
| bin 文件清理(ZR233 阻塞项) | ✅ firmware/ 仅剩 README.md,3 个固件镜像走上游下载,4 个 RF cfg 内联为 Rust 字节数组 |
芯片门控验证
逐一确认代码中门控:
- STA 注册去重 →
ap.rslet dual = bus.transport.is_dual_pipe()✅ - MM_STA_DEL 槽位回收 →
ap.rsif bus.transport.is_dual_pipe()✅ - 控制端口周期对账 →
ap.rsif bus.transport.is_dual_pipe()✅ - TX poll kicker →
tx.rsif bus.transport.is_dual_pipe()✅ - RX poll kicker →
rx.rsif bus.transport.is_dual_pipe()✅ - Deauth/Disassoc 清表 →
rx.rsif !bus.transport.is_dual_pipe() { return; }✅ - drain_func(func2) →
rx.rsif bus.transport.cmd_func() == 2✅ - MGMT frame ac 字段 →
tx.rshd[22] = if dual_pipe { 3 } else { 0 }✅
非 DC/DW 分支走与 upstream/dev 逐字节一致的原有路径。
CI 状态
CI workflow 对当前 head 90bdc079a 的所有 check runs 均为 skipped(路径过滤器跳过 aic8800-only 改动),无失败。前轮 smoke-vmx 失败为 axvisor x86_64 VMX 测试,与本 PR 的 aic8800 驱动无关。
本地验证:cargo fmt --check -p aic8800 ✅、git diff --check ✅。
重复/重叠分析
未发现其他 open PR 与本 PR 重叠。PR #1185、#1266、#1276 已合入 dev,是本 PR 的前置基础。
审查结论
批准合入。经过 6 轮审查,所有阻塞问题均已解决:
- ZR233 的「清理 bin 文件」要求已满足(固件走上游下载 + RF cfg 内联)
- 合并状态为 CLEAN
- 所有行为差异已门控到 DC/DW,AIC8801 真机验证无回归
- CI 无失败(路径过滤器跳过)
- 代码设计合理(双管道 SDIO、PollSet 唤醒修复、STA 生命周期管理),注释详尽
Powered by mimo-v2.5-pro
ZR233
left a comment
There was a problem hiding this comment.
本轮按 current head 90bdc079a628b1ac5803836cd7a8f48c924ab578 复查,前轮阻塞项已经解决,旧的未解决线程也已关闭。
确认结果:
components/aic8800/firmware/现在只剩README.md和.gitignore,没有.bin;DC-H 3 个固件镜像改为从 pinned 上游lxowalle/aic8800-sdio-firmware@c56f910044cc854d6c553bcb9a644f3bca5a4c38下载并校验 SHA-256。- 4 个 RF 配置表已内联到
src/fw/firmware/dc_rf_cfg.rs,不再作为 in-tree 二进制 blob 存放。 - 原先的
remote_path = ""问题已消除;build.rs 中 DC-H 固件 remote_path 有效,且保留了空路径 assert guard。 - func2 drain 已按
cmd_func() == 2门控;TX/RX poll kicker、STA 去重、MM_STA_DEL、控制端口重试、deauth/disassoc 清表等 DC/DW 行为均通过is_dual_pipe()门控,避免影响 D80/8801 baseline 路径。 - 热路径诊断日志已降为 debug/trace,并用
log_enabled!(Trace)避免默认路径额外读寄存器。 - open PR 搜索未发现另一个 AIC8800DC SoftAP 替代实现;#1336 是 SDIO host abstraction,不是本 PR 的重复实现。
验证:
git diff --check origin/dev...HEAD:通过。cargo fmt --check:通过。rg -n '\[patch\.crates-io\]' -g 'Cargo.toml' .:无结果。cargo xtask clippy --package aic8800:通过。- 当前 head CI 中 format、sync-lint、clippy、std、Starry/ArceOS/Axvisor QEMU、自托管/板卡相关检查均为 success 或预期 skipped,无失败项。
作者补充的 AIC8800DC / AIC8801 / D80 真机验证覆盖了本 PR 的关键硬件风险。LGTM。
…ent reconnect (rcore-os#1318) * feat(aic8800): AIC8800DC SoftAP working — boot AP + SSH stable on SG2002 Port the AIC8800DC firmware/driver path so the boot-time SoftAP brings up, broadcasts, accepts client association, and carries data (SSH verified) on the LicheeRV Nano (SG2002). Key fixes that made the AP functional: - TX data-plane (MGMT + DATA 802.11 frames) routed on func1 (data_func), not func2 (command mailbox). func2 is command/CFM only, func1 is the data plane for both TX and RX. This was why no client could ever associate. - MGMT frame field fixes: byte[2]=0x01 on both frame builders, ac=3 (VO). - AIC8800DC firmware image/init path (fw/firmware/dc.rs + chip variant). - Diagnostic logging at info for CMD sent / CFM received / MGMT sent, to make the command->CFM round-trip observable on hardware. Runtime AP<->STA mode switching is not yet functional and is tracked separately; the boot AP path is the verified milestone here. * fix(aic8800): stabilize AIC8800DC SoftAP — SSH + HTTP, client reconnect Builds on the boot-AP milestone (6518369) to make the AIC8800DC SoftAP reliable enough for sustained client traffic and reconnection. Verified on SG2002 (LicheeRV Nano): client associates fast, SSH and HTTP both work, and a client can reconnect after disconnecting. Four independent fixes, each rooted in an observed failure on real hardware: - TX poll kicker (tx.rs): wifi-tx is an edge-triggered poll task that registers its waker after tx_process; a wake() landing in that window is lost (PollSet has no sticky bit) and, combined with the pending_flag head-of-line block, freezes all TX for seconds. RX already had a 10ms kicker for the same hazard; add the symmetric one for TX so any lost wake is recovered within ~10ms. - ME_STA_ADD dedup with control-port self-heal (ap.rs, bus.rs): the firmware does not CFM a repeated ME_STA_ADD for an already-registered MAC, so a phone retransmitting AssocReq made the AP worker block 5s and timeout. Track registered STAs as (mac, sta_idx, ctrl_port_open); skip ME_STA_ADD for known MACs, and retry opening the control port on re-assoc until it actually succeeds (a timed-out control-port open previously left data frames dropped by the firmware → no ping/SSH). - Deauth/Disassoc handling (rx.rs): these were silently ignored, so a disconnected STA stayed in the dedup table and reconnects were skipped entirely. Remove the MAC from the table on 0xC/0xA so a reconnect fully re-registers. - Demote per-frame hot-path logs info→debug (rx.rs, tx.rs): on the single- core cooperative scheduler each info log is a blocking UART write; during an Auth flood these starve the TX/kicker tasks. Demoting them markedly speeds up association. Per-connection events (registered, control port OPENED, deauth) stay at info. * style(aic8800): apply rustfmt and fix clippy manual_is_multiple_of - cargo fmt across the AIC8800DC SoftAP changes (import wrapping, multi-line log argument formatting). - Replace `kicks % 100 == 0` with `kicks.is_multiple_of(100)` in the RX poll kicker to satisfy clippy::manual_is_multiple_of under -D warnings. No functional change. * fix(wifi): gate func2 RX drain to DC/DW dual-pipe chips After merging upstream/dev's func-agnostic RX refactor, process_rx_frames drained both func2 and func1 unconditionally. Only DC/DW route the command CFM/indication mailbox to func2; 8801/D80 keep command+data on func1, so polling func2 there issued a wasted CMD52 every RX cycle. Gate the func2 drain on cmd_func()==2 to keep the three variants on their correct path. * fix(wifi): address PR rcore-os#1318 review — demote DIAG logs, bound STA table Review feedback from mai-team-app: - init.rs: demote [DIAG] retry scan and cmd-send/pre-send block_cnt logs from info to debug/trace; gate the extra register reads behind log_enabled!(Trace) so the production polling path issues no extra CMD52. - rx.rs: drop orphaned diagnostic counters (RX_POLL_COUNT / RX_LAST_BLOCKCNT / RX_NONZERO_READS); cfg(debug_assertions)-gate the remaining RX_KICK_COUNT heartbeat. - ap.rs: bound registered_stas at MAX_REGISTERED_STAS (16) to prevent unbounded growth from AssocReq without matching deauth. - tx.rs: mgmt-frame ac=VO is now gated to DC/DW (dual_pipe); 8801/D80 keep vendor ac=BK to match upstream/dev and avoid regression. byte[2] reverted to the shared SDIO_TYPE_DATA constant (== 0x01 on both sides, so it was never a behavior change). * fix(wifi): free firmware STA slot on deauth; reconcile control port Two AP-mode stability fixes for "associates + gets IP but ping/SSH dead": 1. MM_STA_DEL on disconnect. Downlink data frames route by a single global sta_idx (hostdesc staid); firmware delivers reliably only to low slots. The deauth/disassoc handler cleared the driver table but never sent MM_STA_DEL_REQ, so the firmware kept the old slot and the NEXT station got a higher sta_idx (0->1->2...) whose downlink never arrived — the client kept re-ARPing and ping/SSH failed. Now the RX handler enqueues the freed sta_idx (can't send_cmd on the RX thread — CFM is processed there, would deadlock; same reason AssocReq is queued), and the AP worker drains the del-queue BEFORE the assoc-queue so a reconnecting STA reuses the known-good low slot. 2. Control-port reconcile. Opening the control port (authorize) could time out under single-core UART starvation; the old code only retried on AssocReq re-transmission, which a settled client never sends, so the data plane stayed dead. The AP worker now periodically re-issues SET_CONTROL_PORT for any unauthorized STA (capped at CONTROL_PORT_MAX_RETRY) until it succeeds. Still single-concurrent-STA by design (one global sta_idx, one DHCP lease). * fix(aic8800): vendor in-tree-only DC-H firmware so CI build resolves CI `Run clippy / run_host` panicked in build.rs: the 7 AIC8800DC-H firmware/RF-config blobs have remote_path "" (no upstream mirror — they're extracted from the vendor BSP/rootfs), but firmware/.gitignore ignored *.bin, so they were absent from a fresh checkout. build.rs then fell through to download("") and hit HTTP 400. - Allow-list the 7 in-tree-only blobs in firmware/.gitignore (downloadable blobs stay ignored and keep coming from the upstream mirror). - Commit the blobs; their SHA-256 already match the digests in build.rs. - Harden download(): assert remote_path is non-empty with an actionable message instead of emitting a confusing 400. * feat(aic8800): gate DC/DW-specific AP lifecycle behavior by chip variant Reviewer flagged 5 AP-lifecycle changes from the DC port that applied to all chip variants without gating, risking regressions on the existing AIC8801/D80 support (which lacked re-verification). Add ChipVariant back to SdioTransport (it was collapsed into is_v3/cmd_func proxies) plus a semantic `is_dual_pipe()` predicate, and gate all 5 behind it so D80/8801 follow the upstream/dev path verbatim: 1. STA registration dedup + registered_stas table maintenance 2. MM_STA_DEL_REQ slot reclaim queue 3. Periodic control-port reconciliation (50ms retry loop) 4. TX/RX poll kickers (10ms wakeup tasks) 5. Deauth/Disassoc de-registration Non-DC branches verified byte-equivalent to baseline handle_assoc_req. Verified on hardware: - AIC8800DC (newboard): SoftAP + ping/SSH + AP<->STA mode switch OK - AIC8801 (LicheeRV Nano): SoftAP + ping/SSH OK (no regression) * chore(aic8800): stop vendoring DC-H firmware blobs in-tree Per review, remove all .bin blobs from components/aic8800/firmware/. The 7 AIC8800DC-H blobs were the only ones vendored in-tree; the rest were already fetched at build time. They split into two kinds: - 3 firmware images (fmacfw_patch / fmacfw_patch_tbl / fmacfw_calib _8800dc_h_u02) are now fetched from the pinned upstream mirror (lxowalle/aic8800-sdio-firmware @ c56f910), same as every other blob, with SHA-256 verification. Board-tested on AIC8800DC: SoftAP + SSH + AP<->STA mode switch all work with these upstream versions. - 4 RF config tables (ldpc / agc / txgain / txgain_h) are NOT firmware images and have no upstream mirror -- they are little-endian u32 arrays from the vendor BSP source aic8800dc_compat.c. Inlined as Rust byte arrays in src/fw/firmware/dc_rf_cfg.rs (byte-identical to the removed blobs), so no .bin is kept for them either. components/aic8800/firmware/ now contains zero .bin files. .gitignore drops the per-file allow-list; README documents both sources.
…ent reconnect (rcore-os#1318) * feat(aic8800): AIC8800DC SoftAP working — boot AP + SSH stable on SG2002 Port the AIC8800DC firmware/driver path so the boot-time SoftAP brings up, broadcasts, accepts client association, and carries data (SSH verified) on the LicheeRV Nano (SG2002). Key fixes that made the AP functional: - TX data-plane (MGMT + DATA 802.11 frames) routed on func1 (data_func), not func2 (command mailbox). func2 is command/CFM only, func1 is the data plane for both TX and RX. This was why no client could ever associate. - MGMT frame field fixes: byte[2]=0x01 on both frame builders, ac=3 (VO). - AIC8800DC firmware image/init path (fw/firmware/dc.rs + chip variant). - Diagnostic logging at info for CMD sent / CFM received / MGMT sent, to make the command->CFM round-trip observable on hardware. Runtime AP<->STA mode switching is not yet functional and is tracked separately; the boot AP path is the verified milestone here. * fix(aic8800): stabilize AIC8800DC SoftAP — SSH + HTTP, client reconnect Builds on the boot-AP milestone (6518369) to make the AIC8800DC SoftAP reliable enough for sustained client traffic and reconnection. Verified on SG2002 (LicheeRV Nano): client associates fast, SSH and HTTP both work, and a client can reconnect after disconnecting. Four independent fixes, each rooted in an observed failure on real hardware: - TX poll kicker (tx.rs): wifi-tx is an edge-triggered poll task that registers its waker after tx_process; a wake() landing in that window is lost (PollSet has no sticky bit) and, combined with the pending_flag head-of-line block, freezes all TX for seconds. RX already had a 10ms kicker for the same hazard; add the symmetric one for TX so any lost wake is recovered within ~10ms. - ME_STA_ADD dedup with control-port self-heal (ap.rs, bus.rs): the firmware does not CFM a repeated ME_STA_ADD for an already-registered MAC, so a phone retransmitting AssocReq made the AP worker block 5s and timeout. Track registered STAs as (mac, sta_idx, ctrl_port_open); skip ME_STA_ADD for known MACs, and retry opening the control port on re-assoc until it actually succeeds (a timed-out control-port open previously left data frames dropped by the firmware → no ping/SSH). - Deauth/Disassoc handling (rx.rs): these were silently ignored, so a disconnected STA stayed in the dedup table and reconnects were skipped entirely. Remove the MAC from the table on 0xC/0xA so a reconnect fully re-registers. - Demote per-frame hot-path logs info→debug (rx.rs, tx.rs): on the single- core cooperative scheduler each info log is a blocking UART write; during an Auth flood these starve the TX/kicker tasks. Demoting them markedly speeds up association. Per-connection events (registered, control port OPENED, deauth) stay at info. * style(aic8800): apply rustfmt and fix clippy manual_is_multiple_of - cargo fmt across the AIC8800DC SoftAP changes (import wrapping, multi-line log argument formatting). - Replace `kicks % 100 == 0` with `kicks.is_multiple_of(100)` in the RX poll kicker to satisfy clippy::manual_is_multiple_of under -D warnings. No functional change. * fix(wifi): gate func2 RX drain to DC/DW dual-pipe chips After merging upstream/dev's func-agnostic RX refactor, process_rx_frames drained both func2 and func1 unconditionally. Only DC/DW route the command CFM/indication mailbox to func2; 8801/D80 keep command+data on func1, so polling func2 there issued a wasted CMD52 every RX cycle. Gate the func2 drain on cmd_func()==2 to keep the three variants on their correct path. * fix(wifi): address PR rcore-os#1318 review — demote DIAG logs, bound STA table Review feedback from mai-team-app: - init.rs: demote [DIAG] retry scan and cmd-send/pre-send block_cnt logs from info to debug/trace; gate the extra register reads behind log_enabled!(Trace) so the production polling path issues no extra CMD52. - rx.rs: drop orphaned diagnostic counters (RX_POLL_COUNT / RX_LAST_BLOCKCNT / RX_NONZERO_READS); cfg(debug_assertions)-gate the remaining RX_KICK_COUNT heartbeat. - ap.rs: bound registered_stas at MAX_REGISTERED_STAS (16) to prevent unbounded growth from AssocReq without matching deauth. - tx.rs: mgmt-frame ac=VO is now gated to DC/DW (dual_pipe); 8801/D80 keep vendor ac=BK to match upstream/dev and avoid regression. byte[2] reverted to the shared SDIO_TYPE_DATA constant (== 0x01 on both sides, so it was never a behavior change). * fix(wifi): free firmware STA slot on deauth; reconcile control port Two AP-mode stability fixes for "associates + gets IP but ping/SSH dead": 1. MM_STA_DEL on disconnect. Downlink data frames route by a single global sta_idx (hostdesc staid); firmware delivers reliably only to low slots. The deauth/disassoc handler cleared the driver table but never sent MM_STA_DEL_REQ, so the firmware kept the old slot and the NEXT station got a higher sta_idx (0->1->2...) whose downlink never arrived — the client kept re-ARPing and ping/SSH failed. Now the RX handler enqueues the freed sta_idx (can't send_cmd on the RX thread — CFM is processed there, would deadlock; same reason AssocReq is queued), and the AP worker drains the del-queue BEFORE the assoc-queue so a reconnecting STA reuses the known-good low slot. 2. Control-port reconcile. Opening the control port (authorize) could time out under single-core UART starvation; the old code only retried on AssocReq re-transmission, which a settled client never sends, so the data plane stayed dead. The AP worker now periodically re-issues SET_CONTROL_PORT for any unauthorized STA (capped at CONTROL_PORT_MAX_RETRY) until it succeeds. Still single-concurrent-STA by design (one global sta_idx, one DHCP lease). * fix(aic8800): vendor in-tree-only DC-H firmware so CI build resolves CI `Run clippy / run_host` panicked in build.rs: the 7 AIC8800DC-H firmware/RF-config blobs have remote_path "" (no upstream mirror — they're extracted from the vendor BSP/rootfs), but firmware/.gitignore ignored *.bin, so they were absent from a fresh checkout. build.rs then fell through to download("") and hit HTTP 400. - Allow-list the 7 in-tree-only blobs in firmware/.gitignore (downloadable blobs stay ignored and keep coming from the upstream mirror). - Commit the blobs; their SHA-256 already match the digests in build.rs. - Harden download(): assert remote_path is non-empty with an actionable message instead of emitting a confusing 400. * feat(aic8800): gate DC/DW-specific AP lifecycle behavior by chip variant Reviewer flagged 5 AP-lifecycle changes from the DC port that applied to all chip variants without gating, risking regressions on the existing AIC8801/D80 support (which lacked re-verification). Add ChipVariant back to SdioTransport (it was collapsed into is_v3/cmd_func proxies) plus a semantic `is_dual_pipe()` predicate, and gate all 5 behind it so D80/8801 follow the upstream/dev path verbatim: 1. STA registration dedup + registered_stas table maintenance 2. MM_STA_DEL_REQ slot reclaim queue 3. Periodic control-port reconciliation (50ms retry loop) 4. TX/RX poll kickers (10ms wakeup tasks) 5. Deauth/Disassoc de-registration Non-DC branches verified byte-equivalent to baseline handle_assoc_req. Verified on hardware: - AIC8800DC (newboard): SoftAP + ping/SSH + AP<->STA mode switch OK - AIC8801 (LicheeRV Nano): SoftAP + ping/SSH OK (no regression) * chore(aic8800): stop vendoring DC-H firmware blobs in-tree Per review, remove all .bin blobs from components/aic8800/firmware/. The 7 AIC8800DC-H blobs were the only ones vendored in-tree; the rest were already fetched at build time. They split into two kinds: - 3 firmware images (fmacfw_patch / fmacfw_patch_tbl / fmacfw_calib _8800dc_h_u02) are now fetched from the pinned upstream mirror (lxowalle/aic8800-sdio-firmware @ c56f910), same as every other blob, with SHA-256 verification. Board-tested on AIC8800DC: SoftAP + SSH + AP<->STA mode switch all work with these upstream versions. - 4 RF config tables (ldpc / agc / txgain / txgain_h) are NOT firmware images and have no upstream mirror -- they are little-endian u32 arrays from the vendor BSP source aic8800dc_compat.c. Inlined as Rust byte arrays in src/fw/firmware/dc_rf_cfg.rs (byte-identical to the removed blobs), so no .bin is kept for them either. components/aic8800/firmware/ now contains zero .bin files. .gitignore drops the per-file allow-list; README documents both sources.
…ent reconnect (#1318) * feat(aic8800): AIC8800DC SoftAP working — boot AP + SSH stable on SG2002 Port the AIC8800DC firmware/driver path so the boot-time SoftAP brings up, broadcasts, accepts client association, and carries data (SSH verified) on the LicheeRV Nano (SG2002). Key fixes that made the AP functional: - TX data-plane (MGMT + DATA 802.11 frames) routed on func1 (data_func), not func2 (command mailbox). func2 is command/CFM only, func1 is the data plane for both TX and RX. This was why no client could ever associate. - MGMT frame field fixes: byte[2]=0x01 on both frame builders, ac=3 (VO). - AIC8800DC firmware image/init path (fw/firmware/dc.rs + chip variant). - Diagnostic logging at info for CMD sent / CFM received / MGMT sent, to make the command->CFM round-trip observable on hardware. Runtime AP<->STA mode switching is not yet functional and is tracked separately; the boot AP path is the verified milestone here. * fix(aic8800): stabilize AIC8800DC SoftAP — SSH + HTTP, client reconnect Builds on the boot-AP milestone (6518369) to make the AIC8800DC SoftAP reliable enough for sustained client traffic and reconnection. Verified on SG2002 (LicheeRV Nano): client associates fast, SSH and HTTP both work, and a client can reconnect after disconnecting. Four independent fixes, each rooted in an observed failure on real hardware: - TX poll kicker (tx.rs): wifi-tx is an edge-triggered poll task that registers its waker after tx_process; a wake() landing in that window is lost (PollSet has no sticky bit) and, combined with the pending_flag head-of-line block, freezes all TX for seconds. RX already had a 10ms kicker for the same hazard; add the symmetric one for TX so any lost wake is recovered within ~10ms. - ME_STA_ADD dedup with control-port self-heal (ap.rs, bus.rs): the firmware does not CFM a repeated ME_STA_ADD for an already-registered MAC, so a phone retransmitting AssocReq made the AP worker block 5s and timeout. Track registered STAs as (mac, sta_idx, ctrl_port_open); skip ME_STA_ADD for known MACs, and retry opening the control port on re-assoc until it actually succeeds (a timed-out control-port open previously left data frames dropped by the firmware → no ping/SSH). - Deauth/Disassoc handling (rx.rs): these were silently ignored, so a disconnected STA stayed in the dedup table and reconnects were skipped entirely. Remove the MAC from the table on 0xC/0xA so a reconnect fully re-registers. - Demote per-frame hot-path logs info→debug (rx.rs, tx.rs): on the single- core cooperative scheduler each info log is a blocking UART write; during an Auth flood these starve the TX/kicker tasks. Demoting them markedly speeds up association. Per-connection events (registered, control port OPENED, deauth) stay at info. * style(aic8800): apply rustfmt and fix clippy manual_is_multiple_of - cargo fmt across the AIC8800DC SoftAP changes (import wrapping, multi-line log argument formatting). - Replace `kicks % 100 == 0` with `kicks.is_multiple_of(100)` in the RX poll kicker to satisfy clippy::manual_is_multiple_of under -D warnings. No functional change. * fix(wifi): gate func2 RX drain to DC/DW dual-pipe chips After merging upstream/dev's func-agnostic RX refactor, process_rx_frames drained both func2 and func1 unconditionally. Only DC/DW route the command CFM/indication mailbox to func2; 8801/D80 keep command+data on func1, so polling func2 there issued a wasted CMD52 every RX cycle. Gate the func2 drain on cmd_func()==2 to keep the three variants on their correct path. * fix(wifi): address PR #1318 review — demote DIAG logs, bound STA table Review feedback from mai-team-app: - init.rs: demote [DIAG] retry scan and cmd-send/pre-send block_cnt logs from info to debug/trace; gate the extra register reads behind log_enabled!(Trace) so the production polling path issues no extra CMD52. - rx.rs: drop orphaned diagnostic counters (RX_POLL_COUNT / RX_LAST_BLOCKCNT / RX_NONZERO_READS); cfg(debug_assertions)-gate the remaining RX_KICK_COUNT heartbeat. - ap.rs: bound registered_stas at MAX_REGISTERED_STAS (16) to prevent unbounded growth from AssocReq without matching deauth. - tx.rs: mgmt-frame ac=VO is now gated to DC/DW (dual_pipe); 8801/D80 keep vendor ac=BK to match upstream/dev and avoid regression. byte[2] reverted to the shared SDIO_TYPE_DATA constant (== 0x01 on both sides, so it was never a behavior change). * fix(wifi): free firmware STA slot on deauth; reconcile control port Two AP-mode stability fixes for "associates + gets IP but ping/SSH dead": 1. MM_STA_DEL on disconnect. Downlink data frames route by a single global sta_idx (hostdesc staid); firmware delivers reliably only to low slots. The deauth/disassoc handler cleared the driver table but never sent MM_STA_DEL_REQ, so the firmware kept the old slot and the NEXT station got a higher sta_idx (0->1->2...) whose downlink never arrived — the client kept re-ARPing and ping/SSH failed. Now the RX handler enqueues the freed sta_idx (can't send_cmd on the RX thread — CFM is processed there, would deadlock; same reason AssocReq is queued), and the AP worker drains the del-queue BEFORE the assoc-queue so a reconnecting STA reuses the known-good low slot. 2. Control-port reconcile. Opening the control port (authorize) could time out under single-core UART starvation; the old code only retried on AssocReq re-transmission, which a settled client never sends, so the data plane stayed dead. The AP worker now periodically re-issues SET_CONTROL_PORT for any unauthorized STA (capped at CONTROL_PORT_MAX_RETRY) until it succeeds. Still single-concurrent-STA by design (one global sta_idx, one DHCP lease). * fix(aic8800): vendor in-tree-only DC-H firmware so CI build resolves CI `Run clippy / run_host` panicked in build.rs: the 7 AIC8800DC-H firmware/RF-config blobs have remote_path "" (no upstream mirror — they're extracted from the vendor BSP/rootfs), but firmware/.gitignore ignored *.bin, so they were absent from a fresh checkout. build.rs then fell through to download("") and hit HTTP 400. - Allow-list the 7 in-tree-only blobs in firmware/.gitignore (downloadable blobs stay ignored and keep coming from the upstream mirror). - Commit the blobs; their SHA-256 already match the digests in build.rs. - Harden download(): assert remote_path is non-empty with an actionable message instead of emitting a confusing 400. * feat(aic8800): gate DC/DW-specific AP lifecycle behavior by chip variant Reviewer flagged 5 AP-lifecycle changes from the DC port that applied to all chip variants without gating, risking regressions on the existing AIC8801/D80 support (which lacked re-verification). Add ChipVariant back to SdioTransport (it was collapsed into is_v3/cmd_func proxies) plus a semantic `is_dual_pipe()` predicate, and gate all 5 behind it so D80/8801 follow the upstream/dev path verbatim: 1. STA registration dedup + registered_stas table maintenance 2. MM_STA_DEL_REQ slot reclaim queue 3. Periodic control-port reconciliation (50ms retry loop) 4. TX/RX poll kickers (10ms wakeup tasks) 5. Deauth/Disassoc de-registration Non-DC branches verified byte-equivalent to baseline handle_assoc_req. Verified on hardware: - AIC8800DC (newboard): SoftAP + ping/SSH + AP<->STA mode switch OK - AIC8801 (LicheeRV Nano): SoftAP + ping/SSH OK (no regression) * chore(aic8800): stop vendoring DC-H firmware blobs in-tree Per review, remove all .bin blobs from components/aic8800/firmware/. The 7 AIC8800DC-H blobs were the only ones vendored in-tree; the rest were already fetched at build time. They split into two kinds: - 3 firmware images (fmacfw_patch / fmacfw_patch_tbl / fmacfw_calib _8800dc_h_u02) are now fetched from the pinned upstream mirror (lxowalle/aic8800-sdio-firmware @ c56f910), same as every other blob, with SHA-256 verification. Board-tested on AIC8800DC: SoftAP + SSH + AP<->STA mode switch all work with these upstream versions. - 4 RF config tables (ldpc / agc / txgain / txgain_h) are NOT firmware images and have no upstream mirror -- they are little-endian u32 arrays from the vendor BSP source aic8800dc_compat.c. Inlined as Rust byte arrays in src/fw/firmware/dc_rf_cfg.rs (byte-identical to the removed blobs), so no .bin is kept for them either. components/aic8800/firmware/ now contains zero .bin files. .gitignore drops the per-file allow-list; README documents both sources.
概述
在已合入的 AIC8800 SoftAP(#1185)与 D80 模式切换/EAPOL 修复(#1266、#1276)基础上,把 SoftAP 路径移植并稳定到 AIC8800DC(DC-H)芯片 + CV1800 SDIO host。真机(LicheeRV Nano / SG2002)上 boot AP 可广播、客户端可关联、数据通(SSH + HTTP 均验证),且客户端断开后可重连。
改动内容
1. DC bring-up 与数据面路由(boot AP 可用)
fw/firmware/dc.rs+ chip variant)。2. SoftAP 稳定性(SSH + HTTP + 重连)
3. 芯片变体门控(回归护栏)
SdioTransport恢复保留完整ChipVariant(此前被塌缩成is_v3/cmd_func两个派生 bool),新增语义化is_dual_pipe()谓词。handle_assoc_req核验),不受 DC 适配影响。4. style
cargo fmt+ clippy 干净,无功能改动。测试
真机验证:
wifi_switch sta→ WPA2 关联 + DHCP 获址联网)aic8800crate 对 dev 顶端编译通过,cargo fmt --check与cargo clippy -D warnings均通过已知问题 / 待核实
sdhci-cv1800驱动本 PR 零改动;③ probe 时 dump 的 PHY/MSHC 寄存器在"能跑的板"与"卡的板"上逐位相同——差异在内核之外的 fip 阶段。该第三方板属新硬件 bringup,不在本 PR 回归范围。aid=1+ 全局sta_idx设计限制(改动前即存在,本 PR 未改善也未恶化)。备注