您的位置:首页 > 其它

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();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息