Chinaunix首页 | 论坛 | 博客
  • 博客访问: 393232
  • 博文数量: 87
  • 博客积分: 1171
  • 博客等级: 少尉
  • 技术积分: 1068
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-19 14:34
文章分类

全部博文(87)

文章存档

2014年(10)

2013年(24)

2012年(53)

我的朋友

分类: 嵌入式

2012-10-12 20:10:44

摘要:

    process_run用于处理系统所有needspoll标记为1的进程及处理事件队列的下一个事件。本文深入原码,详细分析,也包括do_poll和do_event函数。

 

 

     在contiki中,有些进程需要紧急处理,比如中断中来了数据,此时,你需要将对应的进程赶快处理掉中断来的数据,否则可能会引起灾难性的后果,此时调用 process_poll(&slip_process); 将中断函数对应的进程 needpool设置为1,这样,此进程将会取得优先运行的特权。不过有个前提是,此进程处于p->state == PROCESS_STATE_RUNNING || p->state == PROCESS_STATE_CALLED) 这两个中状态时才行。当然此时全局变量 poll_requested也会置1。

一、运行process_run

intmain()

{

  dbg_setup_uart();

  usart_puts("Initialising\n");


  clock_init();

  process_init

  process_start(&etimer_process,NULL);

  autostart_start(autostart_processes);


  while(1)

  

    /*执行完所有needspoll为1的进程及处理完所有队列*/

    do

    {

    }

    while(process_run()>0);

  

  return0;

}

二、process_run剖析

process_run处理系统所有needspoll标记为1的进程及处理事件队列的下一个事件,源代码如下:

staticvolatileunsigned charpoll_requested;//全局静态变量,标识系统是否有needspoll为1的进程


intprocess_run(void)

{

  if(poll_requested)//进程链表有needspoll为1的进程

  {

    do_poll();//见2.1

  

}

  do_event();//见2.2


  

}

    透过上述的源代码,可以直观看出needspoll标记为1的进程可以优先执行。并且每执行一次process_run,将处理系统所有needspoll标记为1的进程,而只处理事件队列的一个事件。

2.1 do_poll函数

    复位全局变量poll_requested,遍历整个进程链表,将needspoll标记为1的进程投入运行,并将相应的needspoll复位。源代码如下:

staticvoiddo_poll(void)

{

  structprocess*p;

  poll_requested =0;//复位全局变量


  for(=process_list;!=NULL;=p->next)//处理所有needspoll为1的进程

  {

    if(p->needspoll)//将needspoll为1的进程投入执行

    {

      p->state=PROCESS_STATE_RUNNING;

      p->needspoll =0;

      call_process(p,PROCESS_EVENT_POLL,NULL);

    }

  }

}

    

2.2 do_event函数

    do_event处理事件队列的一个事件,有两种事件需特殊处理:PROCESS_BROADCAST和PROCESS_EVENT_INIT。前者是广播事件,需处理所有进程,后者是初始化事件,需将进程状态设为PROCESS_STATE_RUNNING。源代码如下:

staticprocess_num_events_t nevents;/*事件队列的总事件数 */

staticprocess_num_events_t fevent;/*指向下一个要传递的事件的位置*/

staticstructevent_data events[PROCESS_CONF_NUMEVENTS];/*事件队列,用数组存储,逻辑上是环形队列*/


staticvoiddo_event(void)

{

  /*以下3个变量恰为struct event_data的成员,用于暂存即将处理(fevent事件)的值*/

  staticprocess_event_t ev;

  staticprocess_data_t data;

  staticstructprocess*receiver;


  staticstructprocess*p;


  if(nevents >0)

  {

    /*提取将要处理事件的成员变量*/

    ev =events[fevent].ev;

    data =events[fevent].data;

    

    

    fevent =(fevent +1)%PROCESS_CONF_NUMEVENTS;//更新fevent(指向下一个待处理的事件,类型于微机的PC)

    --nevents;//事件队列被组织成环形队列,所以取余数


    if(receiver==PROCESS_BROADCAST)//如果事件是广播事件PROCESS_BROADCAST,则处理所有进程

    {

      for(=process_list;!=NULL;=p->next)

      {

        if(poll_requested){

        {

          do_poll();

        }

        call_process(p,ev,data);//

    }

    else

    {

      if(ev ==PROCESS_EVENT_INIT)//若事件是初始化,设置进程状态,确保进程状态为PROCESS_STATE_RUNNING

      {

        receiver->state=PROCESS_STATE_RUNNING;

      }

      call_process(receiver,ev,data);

    }

  

}

 

http://blog.chinaunix.net/uid-9112803-id-2890335.html

阅读(1889) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

Effel122014-06-26 15:54:30

我们现在是在contiki下进行射频移植,即把原来的Tmote-sky节点的射频cc2420换成rf230,mcu用的还是msp430。在完成驱动程序的编写后,把程序下到节点中,
执行到
 rf230_transmit () 函数中的

 hal_set_slptr_high();
  hal_set_slptr_low();
  hal_frame_write(buffer, total_len);

后 rf230的状态寄存器(0x01)从 0x19 的 TX_ARET_ON 状态 跳转到 0x12 的 BUSY_TX_ARET
状态  但是进去这个状态后就回不来了  一直执行  
  rf230_waitidle();  然后不停的重启    重启还是进去这个状态回不来

有的时候 程序下完了就能正常跑,不知道什么原因?