Contiki高级程序设计(二)
2016-06-30 22:41
441 查看
Contiki高级程序设计(二)
引言
锐米通信(www.rimelink.com)使用Contiki系统开发高性能的LoRa终端,Contiki使8位的MCU也可以具备强大的功能,同时提高开发效率。为让行业内朋友了解和使用该OS,我们撰写一些文章来介绍Contiki开发经验。1. 需求
在Contiki系统中,ISR通过poll消息和进程通信,它不能post消息给进程(原因参见:http://blog.csdn.net/jiangjunjie_2005/article/details/44684811)。了解Contiki机制的朋友知道,poll是通过在“进程控制块”的needspoll置1来完成,这样一来,poll消息具备2个不方便的地方:1. 没有排队功能,即poll多个消息和1个消息是等价的----进程仅响应一次;
2. 没有区分功能,如果多个ISR给进程poll消息,进程无法区分消息源。
以锐米LoRa终端开发为例,RF和RTC的ISR都需要poll进程,这就需要引入新的机制来排队和区分poll消息源。
2. 原理
如果像post消息一样建立一个队列来缓存poll消息,看上去不错,但是有点“重量级”----代价有点大。一般而言,一个进程需要响应的硬件ISR种类不太多,可以使用位存储实现poll消息区分。如下图所示:申明一个变量PollType,bit-0记录RF_ISR,bit-1记录RTC_ISR。3. 实现
我们还是用嵌入式工程师通用语言----C语言来描述实现吧。非常重要的理论!一定要防止竞态的错误,因为存储该poll消息的变量一定会被ISR和进程访问(读和写),它们属于不同执行流。关于竞态的更多原理请链接:http://blog.csdn.net/jiangjunjie_2005/article/details/22980041
3.1 定义“原子变量”类型:
#include <stdint.h>typedef volatile uint8_t Atomic_t;
3.2 实现“原子操作”函数:
函数1 原子设置位。static void AtomicSetBit(Atomic_t*p_tAtomic, uint8_t byEventBit)
{
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState); /* Disable INT */
*p_tAtomic |= byEventBit;
HAL_EXIT_CRITICAL_SECTION(intState); /* Enable INT */
return;
}
函数2 原子测试位,如果该位为1清除该位。
static bool AtomicTestClearBit(Atomic_t*p_tAtomic, uint8_t byEventBit)
{
bool bIsSet;
halIntState_t intState;
ASSERT(p_tAtomic);
HAL_ENTER_CRITICAL_SECTION(intState); /* Disable INT */
if (*p_tAtomic & byEventBit)
{
*p_tAtomic &= ~byEventBit;
bIsSet = TRUE;
}
else
{
bIsSet = FALSE;
}
HAL_EXIT_CRITICAL_SECTION(intState); /* Enable INT */
return bIsSet;
}
3.3 使用实例
申明一原子变量和poll消息位:/* Distinguish type of poll: RF_ISR andRTC_ISR. */
#define NETWORK_POLL_RF 0x01
#define NETWORK_POLL_RTC 0x02
static Atomic_t s_tNetworkPoll = 0;
RF的ISR实现如下:
static void RFTxDone(void)
{
AtomicSetBit (s_tNetworkPoll,NETWORK_POLL_RF);
process_poll(&NetworkProcess);/* Inform Network-Process */
return;
}
RTC的ISR实现如下:
static void RTC_ISR(void)
{
AtomicSetBit (s_tNetworkPoll,NETWORK_POLL_RTC);
process_poll(&NetworkProcess);/* Inform Network-Process */
return;
}
进程处理代码如下:
PROCESS_THREAD(NetworkProcess, ev, data)
{
PROCESS_BEGIN();
while (1)
{
/* Block process until receive a message by poll or post. */
PROCESS_YIELD();
/* Distinguishmessages as well as process it. */
if(PROCESS_EVENT_POLL == ev)
{
if (AtomicTestClearBit(&s_tNetworkPoll, NETWORK_POLL_RTC))
{
/* Poll by RTC, deal with it! */
}
if (AtomicTestClearBit(&s_tNetworkPoll, NETWORK_POLL_RF))
{
/* Poll by RF, deal with it! */
}
PROCESS_END();
}
相关文章推荐
- 对javascript的一点点认识总结《javascript高级程序设计》读书笔记
- Linux进程通信(IPC)方式简介
- Web跨浏览器进程通信(Web跨域)
- contiki udp 使用
- windows cc2530 6lowpan(contiki)报文监控
- android的AIDL----讲述进程间通信
- android的Bound Service----讲述进程间通信
- 生产者消费者问题分析
- Linux进程通信
- aidl的使用简介
- android接口定义语言(AIDL)的使用示例
- Packetbuffer Basics (包缓冲区基础知识)
- Contiki 实例hello_world详细剖析
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
- 用Doxygen和Graphviz给Contiki文档添加类图和调用图
- Linux的SOCKET编程详解
- android进程间的通信方式AIDL
- Linux应用程序开发笔记->六种进程间通信方式
- cc2650鼓捣教程-2.一切的开始 Hello world程序!
- cc2650鼓捣教程-1.硬件选型与contiki 6lowpan环境配置