Contiki高级程序设计(二)

本文介绍了Contiki系统中ISR与进程之间的通信机制,并提出了一种改进方案来解决poll消息的排队和区分问题。通过使用位存储实现poll消息区分,有效地解决了ISR通信中的局限性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Contiki高级程序设计(二)

引言

锐米通信(www.rimelink.com)使用Contiki系统开发高性能的LoRa终端,Contiki使8位的MCU也可以具备强大的功能,同时提高开发效率。为让行业内朋友了解和使用该OS,我们撰写一些文章来介绍Contiki开发经验。

1. 需求

在Contiki系统中,ISR通过poll消息和进程通信,它不能post消息给进程(原因参见:http://blog.youkuaiyun.com/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.youkuaiyun.com/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();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值