RTOS的精确延时功能扩展

来源:互联网 发布:非线性优化的优缺点 编辑:程序博客网 时间:2024/05/21 17:21

引用网址:http://www.cnblogs.com/embeddedtech/archive/2012/05/26/2519293.html

RTOS的精确延时功能扩展

大家都知道,OS有一个系统时基,这个时基大多取值为100,200,500,1000,一般都不会大于1000。取1000的时候,意味着每1毫秒就产生一次时基中断,OS时基函数也就被执行一次,如果这个时基中断产生的太频繁,对系统性能是有很大影响的。假设我们的系统时基选择100,那就是延时精度为10毫秒。这种精度很让人烦恼不是吗? 
那么怎样提供一个精确的RTOS延时而又不增加系统负担呢? 
在延时段死循环执行指定数量的指令?不是!因为这是最浪费CPU资源的做法! 
把RTOS时基增加?也不是!因为每个时基都会耗费CPU资源,增加时基就意味着增加CPU资源耗费! 
这里,我在LPC17xx上使用RIT模块实现了一个精确延时模块,目前精度为10微秒,系统是ucos-ii,供大家参考。 
原理很简单,就是维护一个链表结构。有几个线程正在延时,就有几个链表节点,链表节点不占用堆内存,用的是线程局部堆栈。 
延时计数硬件不用每10微秒产生中断,中断次数就等于链表的节点数而已!如果不用RIT硬件模块,其他硬件定时器一样可以实现的。

hp_timer.h内容:

   1:  #ifndef __HP_TIMER_H__
   2:  #define __HP_TIMER_H__
   3:  ////////////////////////////////////////////////////////////////////////////////
   4:  #include "target.h"
   5:  #include "fport.h"
   6:  #include "frame.h"
   7:   
   8:  typedef struct {
   9:      u32_t ticks;
  10:      OS_EVENT *ev;
  11:      void *next;
  12:  } hp_tmr_t;
  13:   
  14:  void hp_timer_init(void);
  15:  void hp_delay(u32_t ticks);
  16:  void hp_delay_ex(hp_tmr_t *tmr);
  17:   
  18:  ////////////////////////////////////////////////////////////////////////////////
  19:  #endif /* __HP_TIMER_H__ */
  20:   

hp_timer.c内容:

   1:  #include "hp_timer.h"
   2:   
   3:  static u32_t hpTickBase;
   4:  static hp_tmr_t *hpList = NULL;
   5:  ////////////////////////////////////////////////////////////////////////////////
   6:  //|          |
   7:  //| 函数名称 |: hp_timer_init
   8:  //| 功能描述 |: 
   9:  //|          |: 
  10:  //| 参数列表 |: 
  11:  //|          |: 
  12:  //| 返    回 |: 
  13:  //|          |: 
  14:  //| 备注信息 |: 10uS延时单位。
  15:  //|          |: 
  16:  ////////////////////////////////////////////////////////////////////////////////
  17:  void hp_timer_init(void)
  18:  {
  19:      u32_t utmp;
  20:      
  21:      target_enable_power(PCONP_RIT);
  22:      utmp = target_get_apbclk(PCLK_RIT);
  23:      utmp /= 100000u;    /* 每10uS的APB时钟计数。*/
  24:      hpTickBase = utmp;
  25:      
  26:      NVIC_DisableIRQ(RIT_IRQn);
  27:      LPC_RIT->RIMASK = 0u;
  28:      // 清除中断标志并停止计数器。
  29:      LPC_RIT->RICTRL = ((1<<2)|(1<<0));
  30:      NVIC_EnableIRQ(RIT_IRQn);
  31:  }
  32:   
  33:  ////////////////////////////////////////////////////////////////////////////////
  34:  //|          |
  35:  //| 函数名称 |: RIT_IRQHandler
  36:  //| 功能描述 |: 
  37:  //|          |: 
  38:  //| 参数列表 |: 
  39:  //|          |: 
  40:  //| 返    回 |: 
  41:  //|          |: 
  42:  //| 备注信息 |: 
  43:  //|          |: 
  44:  ////////////////////////////////////////////////////////////////////////////////
  45:  void RIT_IRQHandler(void)
  46:  {
  47:      DECL_CPU_SR;
  48:      u32_t tmval;
  49:      hp_tmr_t *p;
  50:      
  51:      // 清除中断标志并停止计数器。
  52:      LPC_RIT->RICTRL = ((1<<2)|(1<<0));
  53:      OS_ENTER_CRITICAL();
  54:      OSIntNesting++;
  55:      p = hpList;
  56:      while(p && (p->ticks == 0)){
  57:          if(p->ev){
  58:              OSSemPost(p->ev);
  59:          }
  60:          p = (hp_tmr_t *)p->next;
  61:      }
  62:      hpList = p;
  63:      if(p){
  64:          tmval = p->ticks*hpTickBase;
  65:          tmval += LPC_RIT->RICOUNTER;
  66:          LPC_RIT->RICOMPVAL = tmval;
  67:          p->ticks = 0;
  68:          LPC_RIT->RICTRL = ((1<<2)|(1<<3));
  69:      }
  70:      OS_EXIT_CRITICAL();
  71:      
  72:      OSIntExit();
  73:  }
  74:   
  75:  ////////////////////////////////////////////////////////////////////////////////
  76:  //|          |
  77:  //| 函数名称 |: __internal_delay
  78:  //| 功能描述 |: 
  79:  //|          |: 
  80:  //| 参数列表 |: 
  81:  //|          |: 
  82:  //| 返    回 |: 
  83:  //|          |: 
  84:  //| 备注信息 |: 10uS延时单位。
  85:  //|          |: 
  86:  ////////////////////////////////////////////////////////////////////////////////
  87:  static void __internal_delay(hp_tmr_t *tmr)
  88:  {
  89:      hp_tmr_t *p;
  90:      DECL_CPU_SR;
  91:      INT8U err;
  92:      u32_t cnt;
  93:      
  94:      tmr->next = 0;
  95:      OS_ENTER_CRITICAL();
  96:      // 清除中断标志并停止计数器。
  97:      LPC_RIT->RICTRL = ((1<<2)|(1<<0));
  98:      p = hpList;
  99:      if(p){
 100:          cnt = LPC_RIT->RICOMPVAL;
 101:          cnt -= LPC_RIT->RICOUNTER;
 102:          cnt /= hpTickBase;
 103:          LPC_RIT->RICOMPVAL -= cnt*hpTickBase;
 104:          p->ticks += cnt;
 105:          if(p->ticks > tmr->ticks){
 106:              p->ticks -= tmr->ticks;
 107:              tmr->next = p;
 108:              hpList = tmr;
 109:          }else{
 110:              while(1){
 111:                  tmr->ticks -= p->ticks;
 112:                  if(p->next == NULL){
 113:                      p->next = tmr;
 114:                      break;
 115:                  }
 116:                  if(((hp_tmr_t *)p->next)->ticks >= tmr->ticks){
 117:                      ((hp_tmr_t *)p->next)->ticks -= tmr->ticks;
 118:                      tmr->next = p->next;
 119:                      p->next = tmr;
 120:                      break;
 121:                  }
 122:                  p = p->next;
 123:              }
 124:          }
 125:          cnt = hpList->ticks;
 126:          LPC_RIT->RICOMPVAL += cnt*hpTickBase;
 127:          hpList->ticks = 0;
 128:      }else{
 129:          // 列表为空。
 130:          hpList = tmr;
 131:          cnt = tmr->ticks*hpTickBase;
 132:          cnt += LPC_RIT->RICOUNTER;
 133:          LPC_RIT->RICOMPVAL = cnt;
 134:          tmr->ticks = 0;
 135:      }
 136:      // 启动计数器。
 137:      LPC_RIT->RICTRL = ((1<<2)|(1<<3));
 138:      OS_EXIT_CRITICAL();
 139:      
 140:      OSSemPend(tmr->ev, 0, &err);
 141:  }
 142:   
 143:  ////////////////////////////////////////////////////////////////////////////////
 144:  //|          |
 145:  //| 函数名称 |: hp_delay
 146:  //| 功能描述 |: 
 147:  //|          |: 
 148:  //| 参数列表 |: ticks 延时时间,单位是10uS。
 149:  //|          |: 
 150:  //| 返    回 |: 
 151:  //|          |: 
 152:  //| 备注信息 |: 注意:100MHZ主频时,调用该函数会有10uS以上的代码执行开销,因此:
 153:  //|          |:       当ticks参数为1时,当函数返回时就已经过去20uS时间了。
 154:  ////////////////////////////////////////////////////////////////////////////////
 155:  void hp_delay(u32_t ticks)
 156:  {
 157:      OS_EVENT *ev;
 158:      INT8U err;
 159:      
 160:      if(ticks){
 161:          ev = OSSemCreate(0);
 162:          if(ev){
 163:              hp_tmr_t tmr;
 164:              tmr.ticks = ticks;
 165:              tmr.ev = ev;
 166:              __internal_delay(&tmr);
 167:              OSSemDel(ev, OS_DEL_ALWAYS, &err);
 168:          }
 169:      }
 170:  }
 171:   
 172:  ////////////////////////////////////////////////////////////////////////////////
 173:  //|          |
 174:  //| 函数名称 |: hp_delay_ex
 175:  //| 功能描述 |: 
 176:  //|          |: 
 177:  //| 参数列表 |: 
 178:  //|          |: 
 179:  //| 返    回 |: 
 180:  //|          |: 
 181:  //| 备注信息 |: 10uS延时单位。
 182:  //|          |: 
 183:  ////////////////////////////////////////////////////////////////////////////////
 184:  void hp_delay_ex(hp_tmr_t *tmr)
 185:  {
 186:      if(tmr && tmr->ev && tmr->ticks){
 187:          __internal_delay(tmr);
 188:      }
 189:  }
 190:   
0 0
原创粉丝点击