contiki系统分析:时钟

Contiki的内核分析-定时器模型 导读 本文通过分析Contiki的源码,梳理Contiki的定时器模型中一共5个定时器的工作机制和原理。 引入 从本文开始,我们开始探究Contiki的5个定时器模型,遵循从易到难的原则,我们先开始两个基本的内核定时器timer和stimer,两者唯一的区别就是timer以内核tick为单位,stimer以秒为单位。因此只需要了解timer即可类推到stimer。 在探究timer之前,我们先回顾... 阅读详情

contiki系统提供了一系列的时钟库,可以供contiki系统或者用户态的程序调用.

时钟库包括时钟到期检查.在调度时钟时低功耗的模块被唤醒,实时的任务调度.

定时器也可以让执行具体的事情过程中进入休眼状态.


contiki的定时器的种类


contiki包抱一个时钟模块,但是有多个时钟模型:timer, stimer, ctimer, etimer, rtimer.不同的时钟有不同的作用.有的定时器运行时间长,但是间隔时间短,有的间隔时间长,但是运行时间短.有些能用于中断的上下文中(rtimer),但是有些不行.

定时器模块提供系统时钟,并且可以短时间的阻塞CPU.整个时钟库就是基于定时器来做的.

timer和stimer是提供了最简单的时钟操作,即检查时钟周期是否已经结束.应用程序需要从timer中读出状态,判断时钟是否过期.两种时钟最大的不同在于,tmiers是使用的系统时钟的ticks,而stimers是使用的秒,也就是stimers的一个时钟周期要长一些.和其它的时钟不同,这两个时钟能够在中断中安全使用.可以用到低层的驱动代码上.

etimer库主要提供的是事件时钟(event timer),在一个时钟周期后,contiki系统可以使用这个时钟做事件调度.主要用在contiki进程当系统的其它功能工作或休眼时,这个进程在等待一个时钟周期.

ctimer库主要用于回调时钟(callback timers),主要用一个时钟周期完了之后,去调度回调函数.当其它进程进入工作或者休眼状态时,这个进程仍然可以等待ctimer.由于ctimer本来就是当一个时钟周期结束时,去调用一个函数并且执行.ctimer运用的场合一般在没有明显的进程的地方,比如协议的执行时可以用到ctimer.ctimer可以通过rime协议栈去管理通讯是否超时的.

rtimer库主要是用来调度实时任务的.可以用到任何运行的contiki进程中,用时钟调度的方式去让实时任务运行.rtimer可用在对时间要求极严的的场合,比如无线电模块要在不延时的情况下开启或者关闭.

timer模块

实现文件core/sys/timer.c,对应的头文件是用来外部调用的.

contiki的timer是用来提供定时器的基本设置重启,清零.或者是检查时间到期.应用程序必须去主动检查定时器是否过期,不能自动的的获得过期的消息.

timer模块用clock_time()来获得当前的系统时间.但是对于不同的MCU,读取定时器的方法会有所有同,所以这个函数对不同的MCU有一套不同的定义.

比如CC2530芯片,clock_time()的实现在cpu/cc253x/dev/clock.c中,是contiki的系统时钟.

timer结构体定义在core/sys/timer.h中,同样,其它的不同类弄的模块都有符合自身功能的一个结构体的定义.

  1. struct timer {  
  2.   clock_time_t start;  
  3.   clock_time_t interval;  
  4. };  

其中clocl_time_t是一个unsigned short型的变量,定义在cpu/cc253x/8051def.h中.这里有一个8051的文件,是由于sdcc是基于8051的编译器,而CC2530也是一个增强型的8051.

timer结构体中包含两个变量,start,开始计数点,interval,过期时问.

timer库的API如下所示

void timer_set(struct timer *t, clock_time_t interval) : 开始定时器
void timer_reset(struct timer *t) : 以过期的时间间隔(interval)为起始点,重启timer
void timer_restart(struct timer *t) : 以当前时间,即clock_time()为起始点,重启tiemr
int timer_expired(struct timer *t) : 检查定时器是否到期
clock_time_t timer_remaining(struct timer *t) : 定时器计时结束的话,返回值是不可预料的.反回正数表示定时器还差多长时间(只是一个估计值)

值得注意的是,初始化timer必须要第一步调用timer_set(),它会初始化start和interval的值.

timer库可以安全的用在中断中.下面有个例子,就是说明在中断中如何去探测定时器结束.

  1. static struct timer rxtimer;  
  2.   
  3. void init(void) {  
  4.   timer_set(&rxtimer, CLOCK_SECOND / 2);  
  5. }  
  6.   
  7. interrupt(UART1RX_VECTOR)  
  8. uart1_rx_interrupt(void)  
  9. {  
  10.   if(timer_expired(&rxtimer)) {  
  11.     /* Timeout */  
  12.     /* ... */  
  13.   }  
  14.   timer_restart(&rxtimer);  
  15.   /* ... */  
  16. }  

上面的这个例子中的interrupt函数有许多局限性,是根据CPU的特点定义的,所以需要看MCU层支持的代码.

另外,关于clock_time()这个函数的实现,也牵涉到MCU,现在以2530为例来分析一下.

在cpu/cc253x/dev/clock.c这个文件中,有两个函数.

  1. /*---------------------------------------------------------------------------*/  
  2. CCIF clock_time_t  
  3. clock_time(void)  
  4. {  
  5.   return count;  
  6. }  
  7. /*---------------------------------------------------------------------------*/  
  8. CCIF unsigned long  
  9. clock_seconds(void)  
  10. {  
  11.   return seconds;  
  12. }  
里面实现了clock_time和clock_seconds,同时也引出了两个全局变量count和seconds.这两个变量正是timer和stimer实现的关键.前面提到过,timer是以tick为单位来计数的,但是stimer是以seconds为单位计数的.我们看一下这两个全局变量的定义cpu/cc253x/dev/clock.c:

  1. /* Sleep timer runs on the 32k RC osc. */  
  2. /* One clock tick is 7.8 ms */  
  3. #define TICK_VAL (32768/128)  /* 256 */  
  4. /*---------------------------------------------------------------------------*/  
  5. #if CLOCK_CONF_STACK_FRIENDLY  
  6. volatile __bit sleep_flag;  
  7. #else  
  8. #endif  
  9. /*---------------------------------------------------------------------------*/  
  10. /* Do NOT remove the absolute address and do NOT remove the initialiser here */  
  11. __xdata __at(0x0000) static unsigned long timer_value = 0;  
  12.   
  13. static volatile __data clock_time_t count = 0; /* Uptime in ticks */  
  14. static volatile __data clock_time_t seconds = 0; /* Uptime in secs */  

对于CC2530的CPU来说,总共包含了两个高频振荡器(32MHz的晶振和16MHz的RC振荡器)和两个低频振荡器(32KHz的晶振和低频振荡器).

休眼时钟是运行在32KHz的RC振荡器上的.精确的振荡周期为32.768KHz,

而系统的一个tick就是#define TICK_VAL (32768/128) /* 256 */来规定的.

这里做一下简单的计算,1/(32768/256)也就是7.8ms.

在CC2530的clock实现中,每一次增加count就加1.

然后在cpu/cc253x/8051def.h中间有

  1. /* Defines tick counts for a second. */  
  2. #define CLOCK_CONF_SECOND   128  

这个定义是7.8msx128=1s,也就是说,seconds的值与count的值是128倍的关系.

这样cc2530同时保留了timer和stimer的增量.

stimer模块

实际上stimer这个模块跟timer的用法,及API的功能完全一致,只不过是以seconds为单位计时的.而且在timer中也提到了如何实现的.

API如下

void stimer_set(struct stimer *t, unsigned long interval)
void stimer_reset(struct stimer *t)
void stimer_restart(struct stimer *t) 
int stimer_expired(struct stimer *t) 
unsigned long stimer_remaining(struct stimer *t) 

etimer模块

contiki中的etimer是提供了一个时钟来产生计时事件.当结束计时时,会给进程发送一个PROCESS_EVENT_TIMER类型的事件.etimer使用的时钟是clock_time(),即系统时钟.

etimer时钟最核心的内容就是etimer这个结构体.

  1. struct etimer {  
  2.   struct timer timer;  
  3.   struct etimer *next;  
  4.   struct process *p;   
  5. };  

单看这个结构体,不看其它内容.可以知道etimer是用链表形式管理的,每一个etimer对应于一个进程.

void etimer_set(struct etimer *t, clock_time_t interval) : 开始时钟
void etimer_reset(struct etimer *t) : 以前的时间间隔重新没置时钟
void etimer_restart(struct etimer *t) : 以当前的时间为间隔设置时钟
void etimer_stop(struct etimer *t) : 停止时钟
int etimer_expired(struct etimer *t) : 检查时钟是否终止
int etimer_pending() : 检查还有没有时钟在工作
clock_time_t etimer_next_expiration_time() :得到下一个事件时钟的终止时间.
void etimer_request_poll() :这一个接口在后面再详细描述。

要注意,由于时钟事件本身就是用用contiki系统的事件时钟调度的。当一个事件时钟需要从另一个contiki的process里面回调一个函数时。可以用PROCESS_CONTEXT_BEGIN() 和PROCESS_CONTEXT_END() 来临时的改变一下进程的上下文。
还要注意的是,etimer不能用在中断中。因为它是进程间的调度。

下面是一个例子,使用了一个事件定时器,让一个进程每分钟执行一次。

  1. PROCESS_THREAD(example_process, ev, data)  
  2. {  
  3.   static struct etimer et;  
  4.   PROCESS_BEGIN();  
  5.   
  6.   /* Delay 1 second */  
  7.   etimer_set(&et, CLOCK_SECOND);  
  8.   
  9.   while(1) {  
  10.     PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));  
  11.     /* Reset the etimer to trig again in 1 second */  
  12.     etimer_reset(&et);  
  13.     /* ... */  
  14.   }  
  15.   PROCESS_END();  
  16. }  

对于etimer的实现core/sys/etimer.c,还有一部分内容需要说明。

timerlist是把整个的etimer做为了个链表来维护的。然后在add_timer中采用前序插入法,把最新的etimer放到最前面。然后供etimer_set等API去做内部调用。

next_expiration变量。主要是用于获得下一次的etimer的时间间隔。用来实现etimer时钟的校准。遍历了链表上所有的etimer,如果哪个etimer的间隔时间最短,就把它做为next_expiration。即最小值。

  1. static struct etimer *timerlist;  
  2. static clock_time_t next_expiration;  
  3.   
  4. ....  
  5. /*---------------------------------------------------------------------------*/  
  6. static void  
  7. update_time(void)  
  8. {  
  9.   clock_time_t tdist;  
  10.   clock_time_t now;  
  11.   struct etimer *t;   
  12.   
  13.   if (timerlist == NULL) {  
  14.     next_expiration = 0;  
  15.   } else {  
  16.     now = clock_time();  
  17.     t = timerlist;  
  18.     /* Must calculate distance to next time into account due to wraps */  
  19.     tdist = t->timer.start + t->timer.interval - now;  
  20.     for(t = t->next; t != NULL; t = t->next) {  
  21.       if(t->timer.start + t->timer.interval - now < tdist) {  
  22.     tdist = t->timer.start + t->timer.interval - now;  
  23.       }     
  24.     }     
  25.     next_expiration = now + tdist;  
  26.   }  
  27. }  

其中在etimer_stop实现中

  1. void  
  2. etimer_stop(struct etimer *et)  
  3. {  
  4.   struct etimer *t;  
  5.   
  6.   /* First check if et is the first event timer on the list. */  
  7.   if(et == timerlist) {  
  8.     timerlist = timerlist->next;  
  9.     update_time();  
  10.   } else {  
  11.     /* Else walk through the list and try to find the item before the 
  12.        et timer. */  
  13.     for(t = timerlist; t != NULL && t->next != et; t = t->next);  
  14.   
  15.     if(t != NULL) {  
  16.       /* We've found the item before the event timer that we are about 
  17.      to remove. We point the items next pointer to the event after 
  18.      the removed item. */  
  19.       t->next = et->next;  
  20.   
  21.       update_time();  
  22.     }  
  23.   }  
  24.   
  25.   /* Remove the next pointer from the item to be removed. */  
  26.   et->next = NULL;  
  27.   /* Set the timer as expired */  
  28.   et->p = PROCESS_NONE;  
  29. }  

注意一下中间的for循环,它是用于找出下一个etimer是传入参数et的情况。然后再把et这个链表的指向销毁。然后把进程标记为空,即PROCESS_NONE。

这儿有一个疑问。为什么在创建,销毁时钟时,没有使用malloc,free之类的操作。其根本原因还是由于contiki本身适用于内存受限的操作系统,而且在编译时,把程序的各个段己经规定好了,不使用HEAP区域。etimer的内存空间最多也只能放在data或者是bss段中。所以才有了只清除内部的变量,而不释放本身的内存的做法。实际上,个人建议,把etimer的分配放到前面内存分配讨论过的mmem方式在初始化系统时去动态分配内存比较好。

etimer是依赖于MCU平台的。并且它需要依靠etimer_request_poll() 去回调进程,用来管理事件定时器。这也意味着,etimer可以让系统从休眼状态中唤醒,关于MCU的休眼和唤醒,在硬件上有特定的定时器。比如在cc2530中,就有专门的sleep timer来实现。etimer库提供了3个接口来实现操作。

etimer_pending() 检查是否有还没有过期的etimer

etimer_next_expiration_time() 得到下一个etimer的过期时间。

etimer_request_poll() 用来通知etimer库系统时钟要改变了或者是etimer要过期了,一般会周期性的调这个函数,然后检查系统时钟中否改变了。这个函数可以用在中断中。

由于etimer_repuest_poll()是用来调用etimer_process进程.我们把这个进程的代码再分析一遍.

  1. /*---------------------------------------------------------------------------*/  
  2. PROCESS_THREAD(etimer_process, ev, data)  
  3. {  
  4.   struct etimer *t, *u;  
  5.   
  6.   PROCESS_BEGIN();  
  7.   
  8.   timerlist = NULL;  
  9.   
  10.   while(1) {  
  11.     PROCESS_YIELD();  
  12.   
  13.     if(ev == PROCESS_EVENT_EXITED) {  
  14.       struct process *p = data;  
  15.   
  16.       while(timerlist != NULL && timerlist->p == p) {  
  17.     timerlist = timerlist->next;  
  18.       }  
  19.   
  20.       if(timerlist != NULL) {  
  21.     t = timerlist;  
  22.     while(t->next != NULL) {  
  23.       if(t->next->p == p) {  
  24.         t->next = t->next->next;  
  25.       } else  
  26.         t = t->next;  
  27.     }  
  28.       }  
  29.       continue;  
  30.     } else if(ev != PROCESS_EVENT_POLL) {  
  31.       continue;  
  32.     }  
  33.   
  34.   again:  
  35.   
  36.     u = NULL;  
  37.   
  38.     for(t = timerlist; t != NULL; t = t->next) {  
  39.       if(timer_expired(&t->timer)) {  
  40.     if(process_post(t->p, PROCESS_EVENT_TIMER, t) == PROCESS_ERR_OK) {  
  41.   
  42.       /* Reset the process ID of the event timer, to signal that the 
  43.          etimer has expired. This is later checked in the 
  44.          etimer_expired() function. */  
  45.       t->p = PROCESS_NONE;  
  46.       if(u != NULL) {  
  47.         u->next = t->next;  
  48.       } else {  
  49.         timerlist = t->next;  
  50.       }  
  51.       t->next = NULL;  
  52.       update_time();  
  53.       goto again;  
  54.     } else {  
  55.       etimer_request_poll();  
  56.     }  
  57.       }  
  58.       u = t;  
  59.     }  
  60.   
  61.   }  
  62.   
  63.   PROCESS_END();  
  64. }  

在这个函数的实现中,我们可以看到:

timerlist是整个系统统护的etimer的链表.由于protothread的作用,当前进程可能随时改变.那么,timerlist的值也会改变.

etimer_process主要是收集要结束的etimer,并且给其它进程发出event timer类型的消息.

接受PROCESS_EVENT_EXIT事件,找出要退出的etimer;

接受PROCESS_EVENT_TIMER事件,然后再从事件队列里删除已经到期的etimer,并且标记为PROCESS_NONE。
PROCESS_EVENT_POLL的事件没有做任何处理,大概属于后期处理的代码。

实际上,etimer_process这个进程运行的目的也就是不断的销毁即将退出的etimer.

ctimer模块

contiki系统中的回调的计时器,底层照例用的clock_time()这个系统时钟.

首先关心的是ctimer的结构体:

  1. struct ctimer {  
  2.   struct ctimer *next;  
  3.   struct etimer etimer;  
  4.   struct process *p;   
  5.   void (*f)(void *);   
  6.   void *ptr;  
  7. };  
其中ctimer->f即回调函数的接口.ctimer->ptr表示回调函数的参数.

列出了ctimer的API,由于使用方法与上面的timer相同,不做过多的解释.

void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr) 
void ctimer_reset(struct ctimer *t)
void ctimer_restart(struct ctimer *t) 
void ctimer_stop(struct ctimer *t)
int ctimer_expired(struct ctimer *t) 

示例:

  1. static void  
  2.  callback(void *ptr)  
  3.  {  
  4.    ctimer_reset(&timer);  
  5.    /* ... */  
  6.  }  
  7.    
  8.  void  
  9.  init(void)  
  10.  {  
  11.    ctimer_set(&timer, CLOCK_SECOND, callback, NULL);  
  12.  }  

我们再来分析一下ctimer的启动和设置情况.涉及到两个函数

void ctimer_init(void);

void ctimer_set(struct ctimer *c, clock_time_t t,void (*f)(void *), void *ptr);

init函数必需在contiki开始启动时调用,一般放在初始化的变量中.

set函数有4个传入参数

*c表示需要使用的ctimer的地址

t表示使用的时钟,有tick和second之分

f是回调的函数

*ptr是回调函数的参数,一般可以写个结构体.如果没有,可以把这个参数设为NULL.

set函数执行的时机,一般在这个ctimer过期时,就开始执行回调函数.

我们再看看ctimer_process这个进程的实现.

  1. PROCESS(ctimer_process, "Ctimer process");  
  2. PROCESS_THREAD(ctimer_process, ev, data)  
  3. {  
  4.   struct ctimer *c;   
  5.   PROCESS_BEGIN();  
  6.   
  7.   for(c = list_head(ctimer_list); c != NULL; c = c->next) {  
  8.     etimer_set(&c->etimer, c->etimer.timer.interval);  
  9.   }  
  10.   initialized = 1;  
  11.   
  12.   while(1) {  
  13.     PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_TIMER);  
  14.     for(c = list_head(ctimer_list); c != NULL; c = c->next) {  
  15.       if(&c->etimer == data) {  
  16.     list_remove(ctimer_list, c);   
  17.     PROCESS_CONTEXT_BEGIN(c->p);  
  18.     if(c->f != NULL) {  
  19.       c->f(c->ptr);  
  20.     }     
  21.     PROCESS_CONTEXT_END(c->p);  
  22.     break;  
  23.       }     
  24.     }     
  25.   }  
  26.   PROCESS_END();  
  27. }  

由于ctimer同样也是event timer,只不过多了一个回调的功能,所以在初始化ctimer时,用etimer_set来初始化系统启动时需要的ctimer.然后标记初始化完成.在ctimer_process中,主要是去轮询过期的ctimer,然后再进行回调.请注意,由于回调函数在另一个进程中,所以根据protothread的设计,需要调用PROCESS_CONTEXT_BEGIN()和PROCESS_CONTEXT_END()来临时的开辟其它进程中的上下文,最后关闭.

rtimer模块

第一步还是看一下rtimer的结构体

  1. struct rtimer {  
  2.   rtimer_clock_t time;  
  3.   rtimer_callback_t func;  
  4.   void *ptr;  
  5. };  

时钟类型,回调函数名,然后回调函数的参数.

函数指针定义

typedef void (* rtimer_callback_t)(struct rtimer *t, void *ptr);

这个timer不再是一个链表,只是一个timer,去提供实时性的需求.

rtimer本来就是用做contiki的实时任务的.有自己的时钟模块.利用rtimer_time来得到当前的系统时钟.然后用RTIMER_SECOND表示每一分钟的tick数.这儿的时钟跟timer模块用的晶振不一样.这已经是CPU上的时钟了.在CC2530上,利用CLKCONCMD寄存器,设置成500KHz的时钟.由于分频置TICKSPD[2:0]设的32MHz,也就是说RTIMER_SECOND设置成 500KHz/32Hz 为15625U,定义在cpu/cc253x/rtimer-arch.h中.是属于体系结构相关的代码.

和contiki中的其它时钟库不一样.rtimer要保证实时任务的优先级,并且立即执行.主要是大部分的函数都不具备优先执行权,所以用rtimer去优先执行是可取的.如果放在中断安全的一些函数中例如process_poll()中执行的话,与其它非优先级的进程一起执行的话,容易产生冲突,造成非优线程只能异步去执行.

有两种类型的实时任务.一种是硬实时任务,一种是软实时任务.其中硬实时任务的优先级要高点,

rtimer与其它的timer不一样的是,它在平台这一层只是提供了三个接口.

rtimer_init, rtimer_set, rtimer_run_next这三个接口.但是这三个接口的实现是严重依赖于MCU的特性的.

其中主要调用了rtimer_arch_schedule,在cc2530中是把时钟的模式先捕获,捕获完了做输出比较.

rtimer的具体实现现在还是分析的相当明白.需要对cc2530的定时器模式和工作流程做好分析之后,才能回过头来看rtimer 具体作用.

contiki学习笔记(五)ctimer和etimer 四、callback timer 回调计时器(ctimer) Callback timer Contiki system The ctimer module provides a timer mechanism(机制) that calls a specified C function when a ctimer expires. More… Files file ctimer.c Callbac... 阅读详情

相关推荐

Contiki实验2 - timer

struct timer timer;是一个定时器,按F12转定义后可以看到timer仅包含起始时刻clock_time_t start;和间隔时间clock_time_t interval;,通过比较到到期时间和新的当前时间,从而判断该定时器是不是到期。

STM32移植contiki进阶之三(中):timer 中文版

中文版contiki timer详解

hurry_liu的嵌入式之路 3639

小鹏P7车载以太网诊断实战:从OBD口定义到DoIP协议验证

本文详细解析了小鹏P7车载以太网诊断的实战过程。从OBD接口的针脚定义入手,依据ISO13400标准,确认了以太网线对位置,并指导制作专用的RJ45转OBD线束。通过搭建测试环境,使用Ping、端口扫描及Wireshark抓包,最终成功验证了车辆对DoIP协议的支持,为基于以太网的高速诊断与刷写提供了完整的技术路径。

CAT789的专栏 521

Contiki rtimer原理与移

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

jiangjunjie_2005的专栏 5217

vcs覆盖率相关

选择要查看的覆盖率点,右键选择 show xxx tests;

qq_40571921的博客 2385

Android开发者必看:5分钟搞定DeepSeek API接入(附完整代码示例)

本文为Android开发者提供快速接入DeepSeek API的完整指南,包含环境配置、网络层设计、请求体构建等关键步骤,并附有详细代码示例。通过工程化实践,帮助开发者高效集成AI对话、代码生成等高级功能,提升移动应用竞争力。

bush的博客 535

cc2530-关于Contiki系统的时钟

Contiki系统有两个系统时钟,分别是粗粒度时钟(coarse-grained)和细粒度时钟(fine-grained)。 其中 粗粒度时间使用的是128HZ的频率,例如CLOCK_SECOND。 细粒度时间使用的是32768HZ的频率,例如RTIMER_SECOND。 Contiki系统有四种类型的定时器,分别是:timer,etimer,ctimer和rtim

代码就是生产力!https://yannanxiu.cn/ 1816

海康工业相机 Could not find module MvCameraControl.dll(已解决)

【代码】海康摄像机 Could not find module MvCameraControl.dll(已解决)

hmbbpdx的博客 2220

linux 时间操作

转载http://blog.chinaunix.net/u2/85233/showart_1856092.html 我们有时需要得到程序的运行时间,但我们也要知道,根本不可能精确测量某一个程序运行的确切时间­[3],文献[4]中说的很明白,现摘录如 下。 我们平时常用的测量运行时间的方法并不是那么精确的,换句话说,想精确获取程序运行时间并不是那么 ...

weixin_30840573的博客 278

无源定位之时差估计的精确时差估计算法(ETDE)及MATLAB实现程序

时差估计算法之精确时差估计(ETDE)欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想

伊谢尔伦的林中小路 4254

由ip地址和子网掩码求网络号、主机号、广播地址(超详细)

1、用二进制数表示IP地址   在进行计算之前,我们首先要学会十进制的IP地址怎么转换为二进制的IP地址。   给出一个例子: 十进制:172.16.25.3 二进制:10101100.00010000.00011001.00000011 1、如果两台主机的网络号相同,我们就说它们是同一网段 2、主机号的意义 - 1)主机号部分全变成1,即为该网段的广播地址 - 2)主机号部分全变成0,即为该网段的网路地址(网络号) 3、如果主机号部分为x位,则该网络能容纳最大主机数为: 2的x次方-2。减2

爱吃雪糕的小布丁的博客 9万+

contiki-rtimer

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

aishibei0465的博客 269

【2025年华为秋招(AI)-11月19日-第二题(200分)- 终端款型聚类识别】(题目+思路+Java&C++&Python解析+在线测试)

该摘要总结了题目要求、输入输出格式、KMeans算法的实现步骤以及关键点。以下是150字内的摘要: 本文提出基于KMeans算法对终端型号进行聚类的方法。通过包间隔时长、连接持续时长、漫游前后信号强度4个特征,使用欧氏距离度量相似度。算法采用固定初始化策略(前k个样本作为初始质心),经过分配-更新迭代,直至质心移动小于1e-8或达到最大迭代次数。最终输出各簇样本数并按升序排列,解决了终端型号自动分类问题。示例显示该方法能有效识别3-4类终端,并准确统计每类数量。

m0_73659489的博客 141

contiki系统分析六:时钟

contiki系统提供了一系列的时钟库,可以供contiki系统或者用户态的程序调用. 时钟库包括时钟到期检查.在调度时钟时低功耗的模块被唤醒,实时的任务调度. 定时器也可以让执行具体的事情过程中进入休眼状态. contiki的定时器的种类 contiki包抱一个时钟模块,但是有多个时钟模型:timer, stimer, ctimer, etimer, rtimer

linux内核探索 3396

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

无线传感器网络安全实战:轻量级加密方案与攻击防御全解析

在物联网和工业互联网领域,数据安全是核心基石。加密技术通过算法保障数据的机密性、完整性和身份认证,其原理在于将明文信息转化为不可读的密文。对于资源受限的无线传感器网络节点而言,传统的计算密集型加密算法难以适用,因此轻量级密码学的技术价值凸显,它能在有限的计算能力、存储空间和电池电量下实现有效的安全防护。这直接关系到智能家居、环境监测、工业控制等关键应用场景的可靠运行。本文聚焦于如何应对DDoS和中间人攻击等威胁,探讨适用于WSN的轻量级加密选型与一体化安全架构设计,为构建安全的物联网系统提供工程实践参考。

weixin_30466039的博客 406

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Contiki学习笔记3:定时器

把学习笔记2暂时删掉了。我的论文查重居然和自己的重复了,等确实不再查重了再恢复吧。论文里面分析了protothread机制,完成了contiki内核的移植,然后在内核移植的基础上完成了uIP协议栈的移植,实现了UDP通信^_^,以后在把这些移植过程详细描述。 上次翻译完process篇后,感觉不错。写论文时自己分析了阅读了一些源码,感觉其实contiki的学习一定要自己去阅读源代码,去展开宏,不要

oatlmy 4828

关于contiki中的Ctimer和Etimer

文件目录:contiki\core\sys\1 etimer1.1 说明事件定时器,发生超时的时候会得到一个事件,etimer include了timer,timer使用的是clock的系统滴答时钟。 定时器结构体:struct etimer { struct timer timer; struct etimer *next; struct process *p; };定时器会被保存到

lissettecarlr的博客 1898

contiki学习笔记(八)rtimer stimer 计时器库

九、实时任务调度(rtimer) 实时模块处理实时任务的调度和执行(具有可预测的执行时间)。 Data Structures struct rtimer Representation of a real-time task. More... Files file rtimer.c 实时计时器模块中与体系结构无关的部分的实现。 file rtimer.h real-time timer mod...

qq_39549987的博客 1083

Contiki高级程序设计(二)

以锐米LoRa终端开发为例,RF和RTC的ISR都需要poll进程,这就需要引入新的机制来排队和区分poll消息源。

jiangjunjie_2005的专栏 2828

Contiki Rtimer 模块

一、rtimer概述 The Contiki rtimer library provides scheduling and execution of real-time tasks (with predictable execution times) 数据结构: struct rtimer { rtimer_clock_t time; rtimer_callback_t fu...

weixin_33755847的博客 177

Contiki的Rtime只支持一个Timer

在现有http://www.myexception.cn/mobile/1436453.html关于几个Timer的一个总结Contiki源代码中,在调用rtimer时,需要调用者获取当前的RITMER_NOW,然后在此基础上加上需要的time然后进行定时器调度。但是这样里边,如果存在多个定时任务的时候,如何处理呢?而且如果后一个定时任务的time正好小于前一个,又如何保证后一个被调用呢?在现有的

tietao的专栏 2186

Contiki学习笔记之时钟初始化

在platform/contiki-main.c源文件下的main函数数的第一行代码就是实现clock的初始化,以下是其函数体 /*---------------------------------------------------------------------------*/ /*  * There is some ambiguity between TI cc2530 softw

Skylar 3190
上一篇: C语言的三种整型数据类型:int、short int和long int
下一篇: CC2530 Power Management
NoteFAN
博客等级 码龄12年 5粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值