NuttX下实现周期任务管理服务

本文介绍如何在NuttX实时操作系统中实现周期任务管理服务。通过提供的Timer API,可以轻松地将Linux下的周期性定时任务移植到NuttX。文章详细展示了周期任务管理服务的初始化、任务注册和执行过程。

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

NuttX下实现周期任务管理服务

由于NuttX提供的Timer API与Linux类似,所以非常方便将Linux下周期性定时任务函数移植到NuttX下面。
例如提供一个周期性任务注册接口,接口申明如下:

typedef void (*timer_notify)(void* );

/****************************************************************************
 * Public Function Prototypes
 ****************************************************************************/

int init_timer_manager(int cycle_ms);

int attach_timer(timer_notify notify, int timeout, 
                  e_periodic_attr attr, void* param);
int detach_timer(timer_notify notify); 

init_timer_manager实现如下:

 int init_timer_manager(int cycle_ms)
{
  struct sigaction   act;
  struct sigaction   oact;
  struct sigevent    notify;
  struct itimerspec  timer;
  timer_t            timerid;
  int                status;
  struct sched_param sparam;
  int prio_min;
  int prio_max;
  int prio_mid;
  pthread_attr_t attr;  

  sem_init(&timer_sem, 0, 0);

  INIT_LIST_HEAD(&oneshoot_list);
  INIT_LIST_HEAD(&periodic_list);

  pthread_mutex_init(&periodic_mut, NULL);
  pthread_mutex_init(&oneshoot_mut,NULL);

  status = pthread_attr_init(&attr);
  if (status != OK)
  {
    printf("nsem_test: pthread_attr_init failed, status=%d\n",  status);
  }

  prio_min = sched_get_priority_min(SCHED_FIFO);
  prio_max = sched_get_priority_max(SCHED_FIFO);
  prio_mid = (prio_min + prio_max) / 2;

  sparam.sched_priority = (prio_mid + prio_max) / 2;
  status = pthread_attr_setschedparam(&attr,&sparam);
  if (status != OK)
  {
    printf("nsem_test: ERROR: pthread_attr_setschedparam failed, status=%d\n",  status);
    goto errorout;
  }

  status = pthread_create(&timer_threadid, &attr, timer_thread, NULL);
  if (status != 0)
  {
    printf("%s: ERROR: thread creation failed\n",  __FUNCTION__);
    goto errorout;
  }

  /* Set timer timeout action */

  act.sa_sigaction = timer_expiration;
  act.sa_flags  = SA_SIGINFO;

  (void)sigfillset(&act.sa_mask);
  (void)sigdelset(&act.sa_mask, TIMER_MANAGER_SIGNAL);

  status = sigaction(TIMER_MANAGER_SIGNAL, &act, &oact);
  if (status != OK)
  {
    printf("timer_test: ERROR sigaction failed, status=%d\n" , status);
    goto errorout;
  }

  /* Create the POSIX timer */

  notify.sigev_notify            = SIGEV_SIGNAL;
  notify.sigev_signo             = TIMER_MANAGER_SIGNAL;
  notify.sigev_value.sival_int   = TIMER_SIGVALUE_INT;
#ifdef CONFIG_SIG_EVTHREAD
  notify.sigev_notify_function   = NULL;
  notify.sigev_notify_attributes = NULL;
#endif

  status = timer_create(CLOCK_REALTIME, &notify, &timerid);
  if (status != OK)
  {
    printf("timer_test: timer_create failed, errno=%d\n", errno);
    goto errorout;
  }

  /* Start the POSIX timer */

  timer.it_value.tv_sec     = 2; /* initial value shouldn't set to 0 */
  timer.it_value.tv_nsec    = 0;
  timer.it_interval.tv_sec  = (cycle_ms/NSEC_PER_USEC);
  timer.it_interval.tv_nsec = ((cycle_ms%NSEC_PER_USEC)*NSEC_PER_MSEC);

  status = timer_settime(timerid, TIMER_ABSTIME, &timer, NULL);
  if (status != OK)
  {
    printf("timer_test: timer_settime failed, errno=%d\n", errno);
    goto errorout;
  }  

  return status;

errorout:
  sem_destroy(&timer_sem);  
  return status;
}

attach_timer实现如下:

int attach_timer(timer_notify notify, int timeout,
                  e_periodic_attr attr, void* param)
{
  int status;
  s_timer_unit* new_timer;
  pthread_mutex_t* mux; 
  struct list_head* list;

  if ((notify == NULL) || (timeout == 0))
    {
      return -ENOENT;
    }

  new_timer = (s_timer_unit* )malloc(sizeof(s_timer_unit));
  if (new_timer == NULL)
    {
      return -ENOMEM;
    }

  INIT_LIST_HEAD(&new_timer->list);  
  new_timer->notify = notify;
  new_timer->curr_time    = 0;
  new_timer->timeout_time = timeout;
  new_timer->timer_param  = param;

  if (attr == ONESHOOT_TYPE)
    {
      mux  = &oneshoot_mut;
      list = &oneshoot_list;
    }
  else if (attr == PERIODIC_TYPE)
    {
      mux  = &periodic_mut;
      list = &periodic_list;
    }
  else
    {
      goto error_out;
    }  

  status = pthread_mutex_lock(mux);
  if (status != 0)
    {
      printf("%s: mutex_lock error\n",__FUNCTION__);
      goto error_out;
    }

  timer_taskcount++;    
  list_add_tail(&new_timer->list, list);
  pthread_mutex_unlock(mux);

  return status;

error_out:
  free((void *)new_timer); 
  return status;
} 

然后通过一个线程接收timer发出来的信号量,来查询任务列表中是否有超时任务需要得到执行,具体线程实现代码如下:

static void *timer_thread(FAR void *para)
{
  int status;
  s_timer_unit* timer;
  struct list_head* curr_list;

  while (1)
    {
      status = sem_wait(&timer_sem);
      if (status != 0)
        {
          printf("%s: sem_wait ERROR \n", __FUNCTION__);
          continue;
        }

//       printf("timer_thread run\n");
//       fflush(stdout);  

      /* Scan oneshoot timer list and found if any timer task timeout */

      status = pthread_mutex_lock(&oneshoot_mut);
      if (status == 0)
        {           
          for (curr_list = oneshoot_list.next; curr_list != &oneshoot_list; )
            {
              timer = container_of(curr_list, s_timer_unit, list);
              curr_list = timer->list.next;
              if(++timer->curr_time >= timer->timeout_time)
                {
                  timer_taskcount--;
                  timer->notify(timer->timer_param);
                  list_del(&timer->list);
                  free((void *)timer);
                }
            }
          pthread_mutex_unlock(&oneshoot_mut);
        }

      /* Scan periodic timer list and found if any timer task timeout */ 

      status = pthread_mutex_lock(&periodic_mut);
      if (status == 0)
      {
        for (curr_list = periodic_list.next; curr_list != &periodic_list; )
        {
          timer = container_of(curr_list, s_timer_unit, list);
          curr_list = timer->list.next;
          if(++timer->curr_time >= timer->timeout_time)
          {
            timer->notify(timer->timer_param);
            timer->curr_time = 0;
          }
        }
        pthread_mutex_unlock(&periodic_mut);
      }       
    }

  pthread_exit(NULL);
  return NULL; /* Non-reachable -- needed for some compilers */
}

这就是NuttX RTOS的优势,非常方便你将以前Linux下的代码移植到NuttX平台下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值