当有人发送UDP数据包时,有人能解释一下Contiki-OS内发生的事情吗?
以下是使用CC2538芯片运行的设备电流消耗:
我的问题是:为什么传输UDP广播数据包(大约250ms)需要这么长时间才知道理论上250kbps的408比特长度的数据包应该在大约2ms内传输?我知道传输最后是否可以说十毫秒,但这里差异很大。
我使用contiki/examples/ipv6/simple-udp-rpl/broadcast-example.c
有没有人有想法?
答案 0 :(得分:2)
默认情况下,Contiki使用ContikiMAC无线电任务循环(RDC)协议。该协议必须处理两个相互冲突的要求:当没有数据包要接收时,允许接收节点几乎一直处于休眠状态,但同时允许尽可能可靠地传送数据。 ContikiMAC采用的解决方案是将负担放在变送器上。鉴于接收器每秒检查无线电信道8次(cc2538dk平台上的默认配置),发送器必须发送至少125 ms的持续时间,以确保接收器已唤醒并看到该数据包。实际上,这意味着数据包会在行中多次重传。有关详细说明,请参阅ContikiMAC paper和Contiki documentation。
话虽如此,你不会总是看到最长持续时间的传输。如果是单播,接收器通常在成功接收后发送ACK。发送器检查此ACK,如果收到则停止发送。这样,所需的预期平均传输次数减少了两倍。然后还有Phase Optimization - 它允许发送者将传输的开始与接收器的预期唤醒时间同步。但是对于广播,没有生成ACK并且阶段优化也不起作用。
意外长传输的另一个可能原因是CCA检查失败。在发送分组之前,无线电栈首先检查介质是否空闲;如果不是,它将备份一段时间并重试。
答案 1 :(得分:1)
我发现了问题:传输数据包后收音机没有正常关闭。
在文件transmit()
中的函数cpu/cc2538/dev/cc2538-rf.c
的末尾,只有先前关闭了广播,广播才会关闭。
if(rf_flags & WAS_OFF) {
rf_flags &= ~WAS_OFF;
off();
}
但实际上程序从未进入此状态,并且在传输数据包后不会立即关闭无线电。
问题出现是因为函数channel_clear()
(在transmit()
函数的开头调用)首先清除此标志。因此,函数transmit()
在执行之前不再知道无线电已经关闭,因此无线电一直处于打开状态。
为了解决这个问题,我在channel_clear()
内部放置了一个局部变量来关闭收音机,只有在函数本身内部打开时才清除该标志。
static int
channel_clear(void)
{
int cca;
/* Fix: local variable */
uint8_t intern_onoff;
intern_onoff = 0;
PRINTF("RF: CCA\n");
/* If we are off, turn on first */
if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) {
rf_flags |= WAS_OFF;
on();
intern_onoff = 1;
}
/* Wait on RSSI_VALID */
while((REG(RFCORE_XREG_RSSISTAT) & RFCORE_XREG_RSSISTAT_RSSI_VALID) == 0);
if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_CCA) {
cca = CC2538_RF_CCA_CLEAR;
} else {
cca = CC2538_RF_CCA_BUSY;
}
/* If we were off, turn back off */
if((rf_flags & WAS_OFF) == WAS_OFF && intern_onoff) {
rf_flags &= ~WAS_OFF;
off();
intern_onoff = 0;
}
return cca;
}
数据包传输过程中的电流消耗现在看起来像是:
注意:选通时间有意减少到10ms:
#define STROBE_TIME RTIMER_ARCH_SECOND / 100
这解释了为什么广播消息只有三个传输选通。
频闪的持续时间是3ms。这意味着数据速率约为140kbps(?)。