打印

尝试写个多任务内核voidtask(avr,msp430,stm32)

[复制链接]
3354|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
voidx|  楼主 | 2009-11-7 11:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 voidx 于 2009-11-7 11:47 编辑

尝试写个多任务内核voidtask,
与一般RTOS不同的是,voidtask任务空闲时,回到主函数运行while(1)循环,换句话说,主函数就是voidtask的空闲任务。这么做不用单独给空闲任务分配堆栈,对avr这种小RAM MCU来说,还是能节省点RAM。


移植平台avr+gcc,avr+iar,msp430+iar,stm32+iar

AVR+IAR下简单例子:


#include "config.h"
TTask TaskA;   //任务A控制块
TTask TaskB;   //任务B控制块
TTask TaskC;   //任务C控制块
#define TaskAStackSize 100   //任务A堆栈大小
#define TaskBStackSize 100   //任务B堆栈大小
#define TaskCStackSize 100   //任务C堆栈大小
uint8 TaskAStack[TaskAStackSize];  //任务A堆栈空间
uint8 TaskBStack[TaskBStackSize];  //任务B堆栈空间
uint8 TaskCStack[TaskCStackSize];  //任务C堆栈空间
#define LED_A   IO_BIT_ALIAS(&PORTB,0)   //LED_A,IO口位域别名
#define LED_B   IO_BIT_ALIAS(&PORTB,1)   //LED_B,IO口位域别名
#define LED_C   IO_BIT_ALIAS(&PORTB,2)   //LED_C,IO口位域别名
ATTR_CTASK void TaskAProc(void)   //任务A处理
{
    volatile float f1=1.0;        //测试浮点运算
  
    sei();                        //任务开始开中断,每个任务都有自己单独的总中断标志位,任务开始执行时,总中断标志位是关闭的
    while(1)
   {
       f1+=0.1;                        //测试浮点运算
     
       LED_A=1;                        //LED_A写1  
       TSK_Delay(VT_TICKS_PER_SEC/2);  //延时1/2S
      
       LED_A=0;                        //LED_A写0
       TSK_Delay(VT_TICKS_PER_SEC-VT_TICKS_PER_SEC/2);  //延时1/2S
   }
}
ATTR_CTASK void TaskBProc(void)  
{
    volatile float f2=1.0;     //测试浮点运算
  
    sei();                     //任务开始开中断,每个任务都有自己单独的总中断标志位
    while(1)
   {  
       f2+=0.1;                        //测试浮点运算
           
       LED_B=1;                        //LED_B写1  
       TSK_Delay(VT_TICKS_PER_SEC/3);  //延时1/3S
      
       LED_B=0;                        //LED_B写0
       TSK_Delay(VT_TICKS_PER_SEC-VT_TICKS_PER_SEC/3);  //延时2/3S
   }
}
ATTR_CTASK void TaskCProc(void)  
{
    volatile float f3=1.0;     //测试浮点运算
  
    sei();                     //任务开始开中断,每个任务都有自己单独的总中断标志位
    while(1)
    {
       f3+=0.1;                        //测试浮点运算
     
       LED_C=1;                        //LED_C写1  
       TSK_Delay(VT_TICKS_PER_SEC/4);  //延时1/4S
      
       LED_C=0;                        //LED_C写0
       TSK_Delay(VT_TICKS_PER_SEC-VT_TICKS_PER_SEC/4);  //延时3/4S
    }
}
int main()
{
     cli();                   //任务开始调度前,要关中断,每个任务都有自己单独的总中断标志位
     
     DDRB  |=_BV(0)|_BV(1)|_BV(2);    //LED_A,LED_B,LED_C输出
     PORTB |=_BV(0)|_BV(1)|_BV(2);    //LED_A,LED_B,LED_C写1
     _delay_ms(1000);
     PORTB &=~(_BV(0)|_BV(1)|_BV(2)); //LED_A,LED_B,LED_C写0
         
     VT_TicksInit();                   //系统节拍初始化
#ifdef __AVR_IAR__  
     //AVR IAR使用双堆栈
     TSK_Init(&TaskA,(TTaskProc *)TaskAProc,0,&TaskAStack[TaskAStackSize-33],&TaskAStack[TaskAStackSize-1]); //任务A初始化,优先级0
     TSK_Init(&TaskB,(TTaskProc *)TaskBProc,1,&TaskBStack[TaskBStackSize-33],&TaskBStack[TaskBStackSize-1]); //任务B初始化,优先级1
     TSK_Init(&TaskC,(TTaskProc *)TaskCProc,2,&TaskCStack[TaskCStackSize-33],&TaskCStack[TaskCStackSize-1]); //任务C初始化,优先级2
#else
     //AVR GCC使用单堆栈
     TSK_Init(&TaskA,(TTaskProc *)TaskAProc,0,&TaskAStack[TaskAStackSize-1]); //任务A初始化,优先级0
     TSK_Init(&TaskB,(TTaskProc *)TaskBProc,1,&TaskBStack[TaskBStackSize-1]); //任务B初始化,优先级1
     TSK_Init(&TaskC,(TTaskProc *)TaskCProc,2,&TaskCStack[TaskCStackSize-1]); //任务C初始化,优先级2
#endif
                    
    TSK_Start();           //任务开始调度(开始调度由空闲任务主函数切换到用户任务)
   
    sei();                 //空闲任务主函数开中断,空闲任务主函数也有自己单独的总中断标志位
   
    while(1)              //任务空闲时,运行这里
    {   
            
     SleepIdle();        //空闲休眠
        
    }
}


void VT_TicksInit(void)
{
     TCNT2 = 0;
     TCCR2=_BV(WGM21) | T2_CLK_DIV_128;
     OCR2 = F_CPU/128/VT_TICKS_PER_SEC-1;
     TIFR|=_BV(OCF2);
     TIMSK=_BV(OCIE2);
}

ISR_ATTR_NAKED(TIMER2_COMP_vect)    //系统节拍中断,裸中断
{      
      VT_IntEnter();                //VoidTask入中断   
      VT_TicksHandler();            //节拍处理
      VT_IntExit();                 //VoidTask出中断  
}

voidtask.rar

1.51 MB

相关帖子

沙发
voidx|  楼主 | 2009-11-7 11:37 | 只看该作者
AVRIAR任务切换移植代码:

//上下文初始化,IAR是双堆栈,GCC是单堆栈
void ctx_init(TContext **ppContext,TTaskProc *TaskCode,void *Stack1,void *Stack2)
{
  ctx_sp_t *ctx_sp;
  ctx_y_t  *ctx_y;

  ctx_y=(ctx_y_t *)Stack1 - 1;
  ctx_sp=(ctx_sp_t *)Stack2 - 1;

  ctx_sp->_pcl = (uint16)TaskCode%256;
  ctx_sp->_pch = (uint16)TaskCode/256;
   
  ctx_y->_sreg = 0;
  
  ctx_y->_spl  = (uint16)ctx_sp%256;
  ctx_y->_sph  = (uint16)ctx_sp/256;
  
  ctx_y->_r31 = 0x31;
  ctx_y->_r30 = 0x30;
   
  ctx_y->_r27 = 0x27;
  ctx_y->_r26 = 0x26;  
  ctx_y->_r25 = 0x25;
  ctx_y->_r24 = 0x24;  
  
  ctx_y->_r23 = 0x23;
  ctx_y->_r22 = 0x22;  
  ctx_y->_r21 = 0x21;
  ctx_y->_r20 = 0x20;  
  
  ctx_y->_r19 = 0x19;
  ctx_y->_r18 = 0x18;  
  ctx_y->_r17 = 0x17;
  ctx_y->_r16 = 0x16;
  
  ctx_y->_r15 = 0x15;
  ctx_y->_r14 = 0x14;  
  ctx_y->_r13 = 0x13;
  ctx_y->_r12 = 0x12;  
  
  ctx_y->_r11 = 0x11;
  ctx_y->_r10 = 0x10;  
  ctx_y->_r9  = 0x9;
  ctx_y->_r8  = 0x8;  
  
  ctx_y->_r7  = 0x7;
  ctx_y->_r6  = 0x6;  
  ctx_y->_r5  = 0x5;
  ctx_y->_r4  = 0x4;  
  
  ctx_y->_r3  = 0x3;
  ctx_y->_r2  = 0x2;  
  ctx_y->_r1  = 0x1;
  ctx_y->_r0  = 0x0;  
  
  *ppContext=ctx_y;

}


void TSK_Swap(void)                //任务切换,非中断
{
     CRITICAL()
    {   
      if(VTTaskSwapEnable!=0)
       {
         tsk_swap_ctx();
       }
    }
}

void TSK_IntSwap(void)             //任务切换,中断
{      
    if(VTTaskSwapEnable!=0)
    {
       tsk_int_swap_ctx();
    }
}


ATTR_NAKED void tsk_swap_ctx(void)
{
     SWAP_CTX_ENTER();
     tsk_next_ready();
     SWAP_CTX_EXIT();  
}

ATTR_NAKED void tsk_int_swap_ctx(void)
{
      tsk_next_ready();
      INT_SWAP_CTX_EXIT();
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

35

主题

118

帖子

2

粉丝