struct rtimer {
rtimer_clock_t time;
rtimer_callback_t func;
void *ptr;
}; typedef unsigned short rtimer_clock_t;
typedef void (* rtimer_callback_t)(struct rtimer *t, void *ptr);

三个参数:时钟类型,回调函数,回调函数的参数

参考博客:http://blog.csdn.net/jiangjunjie_2005/article/details/44947899 (简称博客1)

     http://blog.sina.com.cn/s/blog_686ee2910102vxce.html (简称博客2)

  这个timer不再是一个链表,只是一个timer,去提供实时性的要求。只能串行使用rtimer定时器的中断回调功能。

rtimer用途

  Contiki系统引入rtimer可以满足精准定时的需要,一些对时间极为敏感的模块(如MAC协议)依赖于rtimer。和etimer的粗粒度(常见为100Hz)不同,rtimer是细粒度(常见为10kHz,100us)定时器。根据经验(别人的经验),细粒度定时器如果中断频繁特别容易消耗CPU资源,为此,contiki设计rtimer时尽可能地减少中断,大部分应用场合为读取定时器计数值。

  

    上图发现,rtimer没有常见的next指针来挂接后续节点,确实,contiki为了减少rtimer中断的爆发,只能挂接一个rtimer结构。如果同时挂接2个或以上的rtimer结构,那么最新挂接的有效,其它的rtimer结构将丢失。

rtimer中断时序

  

  上图展示了rtimer的中断时序,当调用rtimer_arch_schedule()时,它设置rtimer定时器的中断间隔时长timeout,中断服务函数rtimer_irq_handler会调用rtimer->callback()回调函数。

  注意2点,中断只允许发生一次(不懂,搞明白再回头来解释原因)(终于明白了博客1中版主所说的这句话的意思,在使用rtimer的时候,只能rtimer_set一次,不能反复产生到时中断,搞明白rtimer_set函数的内涵),即rtimer_arch_schedule()使能中断,而rtimer_irq_handler()禁止中断;rtimer->callback()是在中断状态下运行,特别注意防止竟态错误,例如:调用process_poll()合法,调用process_post()非法。(暂时不懂原因)

rtimer的移植  

  即,基于MCU实现rtimer-arch.c和rtimer-arch.h

   大多数定时器(尤其是8位MCU)位宽为16位,即MAX=65535,而MAC协议往往需要1秒以上的定时周期,因此rtimer的频率必须小于30kHz。一个比较好的数值是10kHz,它既可以保证比较好的精度(间隔为100us),又具备6.5秒的满量程,这可以适应大多数的应用需要。

  另外,大多数应用需要随机撤销和重启动rtimer,它可以通过添加2个函数来实现:

  rtimer_arch_disable_irq()和rtimer_arch_enable_irq()。

  对于contiki系统而言,其已经在/core/sys/rtimer.h&c中对rtimer相关结构进行了定义,对于特定平台而言,主要需要实现以下几个函数:

  rtimer_arch_init(),针对特定平台的初始化操作,被rtimer_init()函数调用;

  rtimer_arch_now(),用于获取当前的rtimer时间;

  rtimer_arch_schedule(rtimer_clock_t t),传递一个唤醒时间​,在特定时刻进行调度操作,调用rtimer_run_next()。

  同时需要在rtimer_arch.h中定义RTIMER_ARCH_SECOND确定rtimer每秒的滴答数。

stm32移植准备

  1)移植过程中,首先确定rtimer每秒的滴答数是多少,在本系统中,达到100us的精度就OK了,因此选用了10kHz的频率。

  2)选定用于实现rtimer的定时器,stm32具备多个定时器,我所使用的是stm32f103,具备TIM1和TIM8等高级定时器,也有TIM2-TIM5等通用定时器,还有TIM6和TIM7等基本定时器。不知道用哪种定时器来实现rtimer更合适,知道的朋友可以来补充说明一下,这里暂时选用TIM2通用定时器。并用TIM2的TIM_IT_CC1中断来完成rtimer_run_next的调度。(因为常用的中断TIM_IT_Update,便搞不明白了定时器中断类型到底有什么区别,写个博客分析一下)

  以上也是整理参考博客的内容,下面说明一下我是如何实现的

实现rtimer-arch.h文件

#include "contiki-conf.h"
#include "rtimer.h" //确定rtimer每秒的滴答数
#define RTIMER_ARCH_SECOND 10000 /* 10kHz(100us)*/
//这里使用stm32的通用定时器2来实现
#define RTIMER_TIM TIM2 /*在TIM2的中断服务函数TIM2_IRQHandler中调用*/
void rtimer_irq_handler(void);
/*针对特定平台的初始化操作,被rtimer_init()函数调用*/
void rtimer_arch_init(void);
/*用于获取当前的rtimer时间*/
rtimer_clock_t rtimer_arch_now(void);
/*传递一个唤醒时间,在特定时刻进行中断调度操作,中断中调用rtimer_run_next()*/
/*还不太理解这个唤醒时间是怎么个调度法,关键不理解函数中的TIM_SetCompare1()的意义*/
void rtimer_arch_schedule(rtimer_clock_t t);
/*失能和使能超时中断*/
void rtimer_arch_disable_irq(void);
void rtimer_arch_enable_irq(void);

实现rtimer-arch.c文件

 #include "sys/rtimer.h"
#include "rtimer-arch.h"
#include "timer2.h" #define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif void
rtimer_irq_handler(void)
{ /* Clear interrupt pending bit */
TIM_ClearITPendingBit(RTIMER_TIM,TIM_IT_CC1); /* Do interrupt only once! */
/*中断到来后需要将中断禁止,避免多次产生中断*/
rtimer_arch_disable_irq(); //ENERGEST_ON(ENERGEST_TYPE_IRQ);//开启了节能中断
rtimer_run_next();
//ENERGEST_OFF(ENERGEST_TYPE_IRQ); return;
} void
rtimer_irq_handler(void)
{ /* Clear interrupt pending bit */
TIM_ClearITPendingBit(RTIMER_TIM,TIM_IT_CC1); /* Do interrupt only once! */
/*中断到来后需要将中断禁止,避免多次产生中断*/
rtimer_arch_disable_irq(); //ENERGEST_ON(ENERGEST_TYPE_IRQ);//开启了节能中断
rtimer_run_next();
//ENERGEST_OFF(ENERGEST_TYPE_IRQ); return;
} void
rtimer_arch_init(void)
{
TIM2_Int_Init(); return;
} rtimer_clock_t
rtimer_arch_now(void)
{
rtimer_clock_t tT1, tT2; do
{
/* Avoid race condition on reading counter of TIM1 */
tT1 = TIM_GetCounter(RTIMER_TIM);
tT2 = TIM_GetCounter(RTIMER_TIM);
} while (tT1 != tT2); return tT1;
} void
rtimer_arch_schedule(rtimer_clock_t t)
{
/* Sets the TIM2 Capture Compare1 Register value */
TIM_SetCompare1(RTIMER_TIM,t);
PRINTF("进入rtimer_arch_schedule\r\n");
PRINTF("%d\r\n",rtimer_arch_now()); /* MUST clear the remained flag of TIM2 compare */
TIM_ClearFlag(RTIMER_TIM,TIM_FLAG_CC1); /* Enable interrupt of Capture compare 1 */
TIM_ITConfig(RTIMER_TIM,TIM_IT_CC1, ENABLE); return;
} void
rtimer_arch_disable_irq(void)
{
TIM_ITConfig(RTIMER_TIM,TIM_IT_CC1, DISABLE); return;
} void
rtimer_arch_enable_irq(void)
{
/* MUST clear the remained flag of TIM2 compare */
TIM_ClearFlag(RTIMER_TIM,TIM_FLAG_CC1); /* Enable interrupt of Capture compare 1 */
TIM_ITConfig(RTIMER_TIM,TIM_IT_CC1, ENABLE); return;
}

最后附上timer2.c的代码,来显示和rtimer的衔接

 void TIM2_Int_Init(void)
{
u16 arr=;
u16 psc=(uint16_t)(SystemCoreClock / RTIMER_ARCH_SECOND) -;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
NVIC_InitTypeDef NVIC_InitStruct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//①定时器时钟使能 TIM_TimeBaseInitStruct.TIM_Period=arr;//设置自动重装载寄存器周期的值
TIM_TimeBaseInitStruct.TIM_Prescaler=psc;//设置时钟频率的预分频值
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//定时器向上计数
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//设置时钟分割
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);//②初始化、配置定时器 TIM_ITConfig(TIM2,TIM_IT_CC1,ENABLE);//开启更新中断 TIM_Cmd(TIM2,ENABLE);//使能定时器 NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=;
NVIC_Init(&NVIC_InitStruct);//配置中断 }
//编写中断服务函数
void TIM2_IRQHandler(void)
{ if(TIM_GetITStatus(TIM2,TIM_IT_CC1)==SET)
{
TickCounter2++;//6.5535s产生一次中断
rtimer_irq_handler();//调用rtimer中的中断处理函数 }
/* leave interrupt */ }

  正确使用rtimer还不是很理解,还需要继续实验。

  

  

  

contiki-rtimer的更多相关文章

  1. Contiki Rtimer 模块

    一.rtimer概述 The Contiki rtimer library provides scheduling and execution of real-time tasks (with pre ...

  2. [置顶] STM32移植contiki进阶之三(中):timer 中文版

    鉴于自己英语水平不高,在这里,将上一篇关于contiki 的timer的文章翻译为中文,让自己在学习的时候,更方便点.文中有许多不是很通顺的地方,将就吧. Timers Contiki系统提供了一套时 ...

  3. contiki etimer部分

    1.前言     contiki是一款小型开源,易于移植的多任务操作系统,专门为无线传感网设计,适合内存受限制的网络系统.国内的研究和应用还处于初级阶段,甚至还不知道这个contiki如何发音,也没有 ...

  4. Contiki源码+原理+功能+编程+移植+驱动+网络(转)

    源:Contiki源码+原理+功能+编程+移植+驱动+网络 请链接:http://www.rimelink.com/nd.jsp? id=31&_np=105_315 假设您对于用Contik ...

  5. Contiki 2.7 Makefile 文件(四)

    3.第三部分 这里我们假设TARGET为native (1) OBJECTDIR = obj_$(TARGET) LOWERCASE = -abcdefghijklmnopqrstuvwxyz UPP ...

  6. Contiki源码结构

    Contiki源码结构 apps目录下,用于存放Application,也就是我们的应用程序放在这个目录下.如webserver,webrowser等,如下图所示. core目录是contiki操作系 ...

  7. Contiki学习笔记  第一个程序:Hello World

    想来想去,还是得先写一个程序,找下感觉,增强一下自信心,那就国际惯例Hello World吧.先到这个网址下一个Instant Contiki 2.7.之所以没用3.0的,是因为有些问题,我源码是下的 ...

  8. contiki在keil下的stm32平台移植

    参考博客: http://www.aiuxian.com/article/p-705047.html http://blog.csdn.net/u013232419/article/details/4 ...

  9. 专为物联网开发的开源操作系统Contiki(转)

    专为物联网开发的开源操作系统Contiki(转)  (2012-04-19 15:31:09) 原文网址:http://blog.sina.com.cn/s/blog_6de000c201010z7n ...

  10. 简单的玩玩etimer <contiki学习笔记之九 补充>

    这幅图片是对前面  <<contiki学习笔记之九>>  的一个补充说明. 简单的玩玩etimer <contiki学习笔记之九> 或许,自己正在掀开contiki ...

随机推荐

  1. linux hadoop安装

    linux hadoop安装 本文介绍如何在Linux下安装伪分布式的hadoop开发环境. 在一开始想利用cgywin在 windows下在哪, 但是一直卡在ssh的安装上.所以最后换位虚拟机+ub ...

  2. win7远程桌面连接windows2008服务器,连接启动很慢。我是这样解决的。

    1.在本地链接属性中把IPv6勾选取消掉. 2.在window命令中运行 (cmd) netsh int tcp setglobal autotuninglevel=disable 祝君成功!

  3. 对于前端JS、Html、CSS的大小、位置是否影响网站的相应时间

    1.页面中大量的注释代码.空行会影响页面的加载速度 尽量去除打断的注释代码,及空行:尽可能的使用压缩后的JS.CSS文件,太小的文件没必要压缩 2.有人说CSS样式放在页面的开头,JS文件放在页面的结 ...

  4. VS2015解决非Unicode编码包含中文字段无法编译的问题

    用VS2015打开并编译,定位到编译错误的文件(.cs而不是可视化编辑视图) 文件--高级保存选项--编码 改为 Unicode-代码页1200 这样不论用VS2015/2013/2012/2010 ...

  5. Asp.net MVC+Bootstrap3的悬浮式登录框效果

    1.引用Bootstarp3 @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/bootstrap&q ...

  6. Qt : QProcess

    QProcess 类用来启动另外的一个出现并与他们联系. 开始一个进程,通过传递你想要运行程序的名称和命令行参数作为参数给start()函数,来开始一个进程.参数作为独立的字符串来提供. QProce ...

  7. redmine computed custom field formula tips

    项目中要用到Computed custom field插件,公式不知道怎么写,查了些资料,记录在这里. 1.http://apidock.com/ruby/Time/strftime 查看ruby的字 ...

  8. redis和memcached

    Redis 1.主从配置(主从复制不会阻塞master.) 1)bind  192.168.1.2(请修改成本机的IP地址,要不然,客户端无法进行访问) 2)slaveof 192.168.1.1 6 ...

  9. 20160626001 O2O Website

    1. http://sidapai.baijia.baidu.com/   百度百家 2. http://www.huxiu.com/    虎嗅网 3. http://i.wshang.com   ...

  10. 4W1T教程1 如何使用幻灯片

    第一步,读取类别为xxXX前五张幻灯片 <!-- 幻灯片循环开始-->{section name=banner loop=$banner} <li data-transition=& ...