US915 OTAA Join bad sate 原因记录
原因
该问题不是普通射频、网关或 Join 参数问题,也不能简单归类为 “协议栈自带 bug”。更准确地说:
这是 SWL2001 协议栈 US915 / AU915 区域实现中的状态机约束被触发。
真正触发原因是应用层 / 适配层在 OTAA Join 前使用
smtc_real_set_channel_mask() 重放信道掩码的时机不合适。
也就是说,bad sate 的报错位置确实在协议栈内部,属于协议栈
US915 / AU915 区域状态保护逻辑主动触发的 panic;但触发条件并不是
协议栈无条件自身异常,而是 Join 前外部调用时机改变了协议栈期望的
区域状态。因此对外说明时,建议描述为:
这是协议栈内部 US915 / AU915 channel mask 状态保护被触发,
触发原因是入网前恢复 / 设置 channel mask 的时机不符合该协议栈
区域状态机要求。
bad sate panic 来自协议栈内部的 US915 / AU915 after-join
snapshot channel mask 保护逻辑。协议栈要求 Join Accept 处理前,
first_ch_mask_received 必须保持在入网前允许的状态。
US915 / AU915 的 smtc_real_set_channel_mask() 不是单纯复制掩码。
该接口内部会推进区域私有的 first_ch_mask_received 状态机。
如果在 OTAA Join 之前,由应用层恢复 AT+QCHAN 缓存,或由 Join
选频流程提前调用该接口,就会导致 first_ch_mask_received 在
Join Accept 到来前被提前推进。
当 Join Accept 没有有效 ChMask CFList 时,协议栈会进入本地
after_join_snapshot_channel_mask 推导流程。此时如果
first_ch_mask_received 已经不处于入网前允许的状态,协议栈会触发:
!!! LBM PANIC: region_us_915_init_after_join_snapshot_channel_mask:531 bad sate !!!
因此,本问题的根因是:
入网前信道掩码重放方式错误,提前推进了 US915 / AU915 的
first_ch_mask_received 状态机,从而触发协议栈内部状态保护。
触发条件
该问题通常需要同时满足以下条件:
1. 频段为 US915 或 AU915;
2. 入网前配置或恢复了固定信道掩码,例如 AT+QCHAN;
3. Join 前调用或间接调用了 smtc_real_set_channel_mask();
4. Join Accept 未携带有效 ChMask CFList;
5. 协议栈进入 after-join snapshot channel mask 推导流程。
注意事项
bad satepanic 本身来自 SWL2001 协议栈内部保护逻辑。该保护逻辑被触发,不代表射频链路、网关或 Join 参数一定异常。
smtc_real_set_channel_mask()对 US915 / AU915 有状态副作用, 不适合在 OTAA Join 前用于恢复用户信道掩码。入网前如需恢复信道掩码,应只同步 Join 选频需要的数据,避免推进
first_ch_mask_received状态机。LoRaWAN 1.0.4 场景中 Join Accept 通常可能携带 ChMask CFList, 因此不一定触发该问题;但这不代表入网前调用
smtc_real_set_channel_mask()是安全的。