背景
接手一个IoT工程,使用STM8L + NBIOT模块实现远程数传。源代码大体上已经构建完成,但是既没有使用ISR + Mainloop + FSM的设计方式,又没有使用RTOS做任务调度。所以如果花时间重新撸代码,时间和精力都不允许。实际上,我已经投入了大量时间来翻代码(填坑),增加了ISR,systicker,FSM,以及数据收发结构体......但是依然存在很多问题。
延时问题
阻塞型的代码设计,很多事情无法同时完成。尤其是阻塞型delay/wait会造成很多麻烦,比如Modem在通讯时需要较长时间等待和重试,而此时keyboard判断和处理几乎无法实现,而我并不希望在定时中断嵌入键盘处理。因为定时中断应该只提供ticker,而不应该和应用相关。
RTOS Thread.yield的做法是,在Modem等慢速设备通讯任务中,遇到延时,将控制权交还给RTOS,并调度到其他任务中。于是我参考了这一做法,利用回调函数和systicker来实现任务切换。
// setup callback functions of void cb(void)
void set_delay_cb(void (*cb)()){
callback = cb;
}
void yield_ms(uint8_t t)
{
assert_param(t<=250);
u32 period = t;
u32 start = systicker;
while((systicker - start)<period){
if(callback==NULL)
asm("nop");
else
callback();
}
}
void yield(uint8_t t)
{
assert_param(t<=60);
u32 period = (u32)(t*1000);
u32 start = systicker;
while((systicker - start)<period){
if(callback==NULL)
asm("nop");
else
callback();
}
}
time.c
void hw_update(void){
LED_update();
key_update();
MTR_update();
PM_update();
}
void main {
set_delay_cb(hw_update); // set callback as background task
yield(10); // delay 10 seconds, which perform callback functions.
}
main.c
结构简单非常简单。但是放在hw_update()后台的函数与前台函数不能够有资源竞争,后台函数最好不要有while循环,也不要递归调用yield。
网友评论