木子剑
生命不熄,学习不止!

CONTIKI里面有三种事件: 时间事件,外部事件,内核事件

时间事件,说白了就是类似etimer的事件,这个是最简单的,比如“hello world.c”,你可以测试一个RTIMER事件,都一样的。

外部事件,说白了就是RF,  NET, GPIO等等事件,可以去阅读 【进阶学习CONTIKI NG之button 】,这个我也是实验很久才通的。

内核事件,就是进程与进程之间的通讯事件,网上有很资料了,都是长篇大论,然而并没有实际的测试代码。

 

直接上源码吧,一个进程采集信号,一个进程处理信号(你是能申请用户事件,但无法释放它。。。。。):

/*------------------------------系统内部事件的通讯----------------------------*/
// event post教程: https://max.book118.com/html/2018/0210/152645224.shtm 
// 学习线程之间传送事件和数据,实现多个线程间的交互.

static process_event_t event_data_ready; //特定于应用程序的事件值
PROCESS(temp_process, "temperature_process");//假设这个是采集数据的process
PROCESS(print_process, "print process");//假设是对采集好的数据处理process

PROCESS_THREAD(temp_process, ev, data)//采集数据的实现(模拟的)
{
  static struct etimer timer10;
  static u8_t count = 0;  //C99关键字u8_t; s8_t; u16_t.
  static int valid;//测试值

  PROCESS_BEGIN();

  event_data_ready = process_alloc_event();
  etimer_set(&timer10, CLOCK_SECOND);


  while(1)
  {
    PROCESS_WAIT_EVENT_UNTIL(ev = PROCESS_EVENT_TIMER);
    count++;
    printf("loading data: %d\n", count);
    if(count==4)//假设正在采集信号
    {
      count = 0; //采集好了
      valid = 0x57;//假设数据为0x57

      //通知print_process进行处理数据,产生event_data_ready用户事件
      process_post(&print_process, event_data_ready, &valid);
    }

    etimer_reset(&timer10);
  }

  PROCESS_END();

}


PROCESS_THREAD(print_process, ev, data)//print的process实现
{

  PROCESS_BEGIN();

  while(1)
  {

    PROCESS_WAIT_EVENT_UNTIL(ev = event_data_ready); //等待用户事件产生
    printf("the data is : 0x%x\n\n", *(int*)data);  //处理数据,就打印到PC串口吧

  }

  PROCESS_END();
}



/*------------------------所有自启动的测试PROCESSES---------------------------*/
AUTOSTART_PROCESSES(//&demo_timer1, &demo_timer2, &demo_timer3, &demo_timer4,//all timer测试
                    //&hello_process,                 // printf测试--通过
                    //&GpioIputOutputTest,            // led基本测试--通过
                    &button_hal_example,              // 按键和传感器测试--通过
                    //&sensor_process                 // 仿真sensor--通过
                    &temp_process, &print_process     // 测试进程间的通讯--通过
                    );

 

 

测试效果如下所示:

 

 从执行效果来看,是完全正确的,这个的测试解决了一个重要问题,让CONTIKI为我做任何事情( 时间事件,外部事件,内核事件);

当然UDP,RF ,NET这些功能才是重头戏,我会想办法在LINUX下实现它的,不要着急!

 

题外话  IEEE 802.15.4已经发布2020版本了,好像变化不大吧,没细看!但在CONTIKI NG V4.6已经支持了!!

 

 

时间:2020-01-06

process_post(&print_process, event_data_ready, &valid);//异步通讯,进入事件队列

它可以换一下的。

process_post_synch(&print_process, event_data_ready, &valid);//同步通讯,马上执行事件

它们效果是一样的,但执行本质是不一样的。 

 

官方对共享资源和中断操作详见:https://github.com/contiki-ng/contiki-ng/wiki/Documentation:-Multitasking-and-scheduling

我把它们译为中文:

【访问共享资源】
同步访问共享资源在很大程度上取决于代码的哪些部分访问它们。
当仅从主线程上下文中访问共享资源时,开发人员无需依赖任何同步原语,因为调度程序不会意外中断对资源的读/写操作。
当可以从中断上下文内部以及外部访问共享资源时,事情会变得更加复杂。在这种情况下,开发人员需要确保资源状态保持一致。
为此,Contiki-NG提供了一些基本的同步原语(例如互斥体和关键部分),这些原语在doc:synch-primitives以及在线API文档中都有详细记录。
 
【编写中断处理程序】
考虑到以上所有内容,在开发可能在中断上下文中运行的代码时,需要格外小心。中断处理程序开发人员需要记住
,以下Contiki-NG系统和库函数在中断上下文中运行不安全:
发布事件:在中断上下文中调用process_post()和process_post_synch()是不安全的。
如果中断处理程序需要对进程进行调度,则应使用轮询机制,而不要调用process_poll()。 
某些数据结构操作库在中断上下文中不安全使用。这包括:
主要的链表库(list。[ch]),
队列库(queue.h),
堆栈库(stack.h),
循环链表库(circular-list。[ch]),
双链列表库(dbl-list。[ch]),
循环的双向链接列表库(dbl-circ-list。[ch])。
计划计时器:事件计时器(etimer),
回调计时器(ctimer)和trick流计时器(trickle-timer)库依赖于列表操作。
因此,在中断上下文中操作事件和回调计时器是不安全的。
邻居表操作:nbr中的所有功能。[hc]
看门狗定时器永远不应该在中断上下文中刷新:
从中断内部调用watchdog_periodic()可能会导致设备永不从固件崩溃中恢复,因为其WDT在中断中被频繁刷新。
posted on 2021-01-06 00:14  木子剑  阅读(378)  评论(0编辑  收藏  举报