LoRa开发4:移植Contiki
1 LoRa终端需要OS吗?
尽管工程师有很多理由拒绝在LoRa终端上使用OS(Operating System,操作系统):“它很复杂”,“没必要”,“内存太小”,“有学习成本”,“要改变编程思维”,“可能不稳定”……然而,基于以下理由,我们强烈推荐移植一个小型OS:
降低复杂度
LoRa终端的复杂度其实比我们想象的要高:它需要驱动SX1278,这需要处理很多事件,如接收数据超时,接收数据错误等;它需要实现网络算法,申请入网,主动上报,低功耗唤醒,断网续连等;它需要管理本地设备,采集传感器数据,控制阀门等。
使用OS,可以将上述任务分解成多个进程,开发者专注于每个进程的实现,可以有效降低复杂度。
复用组件
LoRa终端一定有这样的需求:射频CAD侦听到唤醒信号后,快速通知进程接收数据帧;需要一个软定时器来灵活地延时和唤醒……这些系统组件,OS都提供,要知道,这些丰富的组件可是经过严格测试的。复用成熟稳定的组件是提高软件生产力的有效手段,这方面,操作系统功不可没。
提高CPU效率
当LoRa终端“等待射频发送数据包完成”前,它无事可干;而其他进程希望得到CPU运行权,不用担心,操作系统会完成调度,它会将“因等待而无事可干”的进程阻塞,而将CPU分配给“具备运行条件”的进程享用。
移植性更好
有一天,因为某种原因(需要更强大的计算能力,需要更低成本等)需要更换LoRa终端的MCU,有操作系统支撑的系统就轻松多了,因为应用软件调用的是操作系统的API,它很少与硬件层直接打交道;基本上,只要将操作系统移植到“新MCU平台”,软件系统就OK了。
2 Contiki是一个怎样的OS?
Contiki是少有能同时实现2个目标的操作系统:对内存要求极低,同时支持进程阻塞机制。8位单片机的RAM极为宝贵,几KB都是很大了,一般的RTOS(FreeRTOS或uc/os-ii等)无法运行,而Contikil可运行良好;有些操作系统,如OSAL也在极少的RAM上可以运行,但是这种基于“状态机”开发的机制,让代码很难理解,程序执行流在状态中来回判断和切换,让逻辑更复杂。
节能内存
Contiki有一个巧妙的机制来实现进程的调度:当进程被阻塞时,OS记录该进程的下一C语言行号;当进程继续运行时,从记录的C语言行号继续运行。这种机制从2个方面极大节省内存:所有的进程共享一个栈,没有上下文机切换。甚至在小于1KB内存的MCU上,Contiki都可以良好地运行。
进程可以阻塞
在Contiki系统中可以实现如下语句,进程发送无线电数据包,然后阻塞自己,直到发送完毕。这种“优雅”的机制,非常符合程序员思维,同时降低了开发的复杂度。
SX1278Send(packetbuf_dataptr(),packetbuf_datalen());
PROCESS_YIELD_UNTIL(RF_Tx_Done ==s_tRFResult);
移植简单
如果仅使用Contiki的内核,只需要移植clock.c,即从MCU中找一个定时器来给etimer进程提供时钟源。如果使用Contiki的网络协议栈,需要按radio.c实现无线收发函数。
丰富的网络协议栈
针对无线通信,Contiki提供3种MAC协议,还有RIME通信原语和RPL路由协议;针对TCP/IP,Contiki提供uIP协议栈,它支持IPv4和IPv6。
3 怎样移植Contiki?
移植一个操作系统是指将它运行在给定的硬件平台。因为Contiki是非可剥夺的OS,不用实现上下文切换(CPU的寄存器保存与恢复),因此它的内核移植特别容易,一般是实现2个定时器:etimer和rtimer。
如果站在3万英尺的高度,一个基于Contiki嵌入式系统的层次结构如下所示。
考虑2种情况,首先需要升级Contiki更高版本的软件,其次需要将Contiki移植到不同的硬件平台。为了尽可能地减少升级和移植的工作量,增加了ports文件夹,ports目录中文件与core目录中文件低耦合。
3.1 移植Contiki内核
如果仅仅只移植Contiki的内核,那么还是比较容易的,一般说来只需要修改2个文件:clock.c和contiki-conf.h。
clock.c有2个函数需要适配对应硬件平台:
void clock_init(void); 设置一定时器,每秒产生CLOCK_SECOND个tick;
void SysTick_handler(void); tick中断时递增时间,检测是否有超时事件;
contiki-conf.h:设置contiki系统的一些参数,如:CLOCK_CONF_SECOND=100;
3.2 移植rtimer
3.2.1 rtimer用途
Contiki系统引入rtimer可以满足精准定时的需要,一些对时间极为敏感的模块(如MAC协议)依赖于rtimer。和etimer的粗粒度(常见为100Hz)不同,rtimer是细粒度(常见为1kHz)定时器。
3.2.2 rtimer移植
移植rtimer比较容易,基于MCU实现rtimer-arch.c和rtimer-arch.h。
需要特别注意,大多数定时器(尤其是8位MCU)位宽为16位,即MAX=65535, rtimer的频率定为1kHz比较合理,它既可以保证比较好的精度(1ms),又具备65秒的满量程,这可以适应大多数的应用需要。
另外,大多数应用需要随机撤销和重启动rtimer,它可以通过添加2个函数来实现:rtimer_arch_disable_irq()和rtimer_arch_enable_irq()。
关于rtimer更多的原理与应用介绍,请链接:
http://blog.csdn.net/jiangjunjie_2005/article/details/44947899
4 怎样应用Contiki?
Contiki是标准ANSI C语言开发,调用API函数和系统组件和一般的OS无异。在进程函数中开发,以下三点需要注意:
1. 自动变量不能跨越阻塞语句
2. 不能使用switch语句
3. 执行语句位于PROCESS_BEGIN()和PROCESS_END()之间
详细了解该规则,请参考《Contiki开发要点》:
http://blog.csdn.net/jiangjunjie_2005/article/details/44725997
从一个入门级的Contiki进行代码,请参考《Contiki开发5:Hello, Contiki》:
http://blog.csdn.net/jiangjunjie_2005/article/details/51921568
您的留言或需求: