void_c 发表于 2009-6-5 00:12:32

尝试写个简单任务调度内核voidtask

尝试写个简单任务调度内核。
自己写的玩玩,不保证正确,还没在目标板试过。

1.任务只有延时,切换功能。
2.任务切换未保护所有寄存器。
3.没有空闲任务,空闲时切换到主函数。
4.IAR必须设置STACK_DOUL为1,GCC必须设置STACK_DOUL为0。


#include "config.h"

TTask TaskA,TaskB,TaskC;
TTimer TimerA ,TimerB ,TimerC ;

void TaskAProc(void)
{
        while(1)
        {
            PORTD^=_BV(7);   
            TMR_Delay(&TimerA,3);
        }
}

void TaskBProc(void)
{
        while(1)
        {
          PORTD^=_BV(6);
             TMR_Delay(&TimerB,4);
        }
}

void TaskCProc(void)
{
        while(1)
        {
           PORTD^=_BV(5);         
            TMR_Delay(&TimerC,5);
        }
}

int main()
{

   DDRD=_BV(7)|_BV(6)|_BV(5);
   PORTD=_BV(7)|_BV(6)|_BV(5);
         
   TCNT2 = 0;
   TCCR2A=_BV(WGM21);
   TCCR2B = T2_CLK_DIV_128;
   OCR2A=OCR2A_INIT;
   TIFR2|=_BV(OCF2A);
   TIMSK2=_BV(OCIE2A);

#if STACK_DOUL==1               //AVRIAR 双堆栈
   TSK_Init(&TaskA,TaskAProc,0,64,32);
   TSK_Init(&TaskB,TaskBProc,1,64,32);
   TSK_Init(&TaskC,TaskCProc,2,64,32);
#else                            //AVRGCC 单堆栈
    TSK_Init(&TaskA,TaskAProc,0,64+32);
    TSK_Init(&TaskB,TaskBProc,1,64+32);
    TSK_Init(&TaskC,TaskCProc,2,64+32);
#endif
         
    sei();
         
    TSK_Start();
         
    while(1)
    {   
            
    }
}

SIGNAL(TIMER2_COMPA_vect)
{   
      VT_TicksHander();
}

点击此处下载 ourdev_451011.rar(文件大小:213K) (原文件名:VoidTask.rar)

void_c 发表于 2009-6-6 15:04:46

更新一下:
点击此处下载 ourdev_451643.rar(文件大小:129K) (原文件名:VoidTask.7z.rar)







顺便把以前写的TEvent,TEventTiny一并放上来。
点击此处下载 ourdev_451147.rar(文件大小:878K) (原文件名:TEvent20090606.7z.rar)
点击此处下载 ourdev_451148.rar(文件大小:1.12M) (原文件名:TEventTiny20090606.7z.rar)

void_c 发表于 2009-6-9 17:39:28

更新一下:20090609
点击此处下载 ourdev_452201.rar(文件大小:135K) (原文件名:VoidTask.7z.rar)


#include "config.h"

TTask TaskA,TaskB,TaskC;

void TaskAProc(void)
{
    sei();
    while(1)
   {
       PORTD^=_BV(7);   
       TSK_Delay(VT_TICKS_PER_SEC/2);   
   }
}

void TaskBProc(void)
{
    sei();
    while(1)
   {
       PORTD^=_BV(6);   
       TSK_Delay(VT_TICKS_PER_SEC/3);
   }
}

void TaskCProc(void)
{
    sei();
    while(1)
    {
      PORTD^=_BV(5);      
      TSK_Delay(VT_TICKS_PER_SEC/4);   
    }
}

int main()
{
   DDRD=_BV(7)|_BV(6)|_BV(5);
   PORTD=_BV(7)|_BV(6)|_BV(5);
         
   TCNT2 = 0;
   TCCR2=_BV(WGM21) | T2_CLK_DIV_128;
   OCR2=OCR2_INIT;
   TIFR|=_BV(OCF2);
   TIMSK=_BV(OCIE2);

#if STACK_DOUL==1               //AVRIAR 双堆栈
   TSK_Init(&TaskA,TaskAProc,0,64,32);
   TSK_Init(&TaskB,TaskBProc,1,64,32);
   TSK_Init(&TaskC,TaskCProc,2,64,32);
#else                            //AVRGCC 单堆栈
    TSK_Init(&TaskA,TaskAProc,0,64+32);
    TSK_Init(&TaskB,TaskBProc,1,64+32);
    TSK_Init(&TaskC,TaskCProc,2,64+32);
#endif
         
    sei();
         
    TSK_Start();
         
    while(1)
    {   
      while(VT_MainScheduler());
         SleepIdle();
      
    }
}

SIGNAL(TIMER2_COMP_vect)
{   
      VT_TicksHander();
}

void_c 发表于 2009-6-10 11:25:20

更新一下:20090610
移植到IAR8051

IAR8051堆栈处理很麻烦,汇编也不会,硬着头皮移植过来的,不保证正确。
任务切换只保护了寄存器:R6,R7,V0-Vn,VB,PSW,EA,DPH,DPL,SP

mcu是CC1110,必须设置为Near,Large,XDATA stack reentrant,1 DPTR。



#include "config.h"

TTask TaskA,TaskB,TaskC;

void TaskAProc(void)
{
volatile float f1=1.0;   //测试浮点运算
    EA=1;
    while(1)
   {
       P0_7=!P0_7;
       f1+=0.1;
       TSK_Delay(VT_TICKS_PER_SEC/2);
   }
}

void TaskBProc(void)
{
volatile float f2=1.0;   //测试浮点运算
    EA=1;
    while(1)
   {
       P0_6=!P0_6;
       f2+=0.1;
       TSK_Delay(VT_TICKS_PER_SEC/3);   
   }
}

void TaskCProc(void)
{
volatile float f3=1.0;   //测试浮点运算
    EA=1;
    while(1)
   {
       f3+=0.1;
       TSK_Delay(VT_TICKS_PER_SEC/4);   
   }
}


int main()
{
    CLK_RC_TO_XOSC();
   
    P0DIR|=_BV(6)|_BV(7);

    TSK_Init(&TaskA,TaskAProc,0,100);
    TSK_Init(&TaskB,TaskBProc,1,100);
    TSK_Init(&TaskC,TaskCProc,2,100);
   
    TMR_TicksInit();
   
    EA=1;
    TSK_Start();
   
   
    while(1)
    {   
       while(VT_MainScheduler());      
    }
}

ISR(T4_VECTOR)
{
    EA=0;
   
    T4OVFIF = 0;
    T4IF = 0;
   
    VT_TicksHander();
   
    EA=1;
}



点击此处下载 ourdev_452359.rar(文件大小:219K) (原文件名:VoidTask.7z.rar)

jerico 发表于 2009-6-10 12:54:47

帮顶

void_c 发表于 2009-6-12 13:08:36

更新一下:20090612

简化移植。
移植只需要重写两个函数CTX_Init和CTX_Swap(另外还有临界段)。



IAREWAVR:

#include "VT.h"

#if STACK_DOUL!=1
#error   "STACK_DOUL must be 1 in avriar"
#endif

//上下文初始化,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 *)((char *)Stack1) - 1;
ctx_sp=(ctx_sp_t *)Stack2 - 1;

ctx_sp->_pcl = (uint16)TaskCode%256;
ctx_sp->_pch = (uint16)TaskCode/256;
   
ctx_y->_spl= (uint16)ctx_sp%256;
ctx_y->_sph= (uint16)ctx_sp/256;

//ctx_y->_sreg = 0x00;

ctx_y->_r27 = 0x27;
ctx_y->_r26 = 0x26;
ctx_y->_r25 = 0x25;
ctx_y->_r24 = 0x24;

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;

CRITICAL()
{
    *ppContext=ctx_y;
}
}

//寄存器分为 "草稿寄存器“和 "存储寄存器" --------个人叫法
//外部函数可以任意使用草稿寄存器而不必恢复,而使用存储寄存器必须先保护

//AVRIAR   
//草稿寄存器R0-R3,R16-R23,R30-R31   
//存储寄存器R4-15,R24-R27
//特殊寄存器R28-R29

//AVRGCC   
//草稿寄存器R18-R27,R30-R31   
//存储寄存器R2-R17,R28-R29
//特殊寄存器R0-R1

//上下文切换只保护存储寄存器寄存器,sp
#define SAVE_CONTEXT()             \
do{                              \
asm("ST      -Y,   R4    ");   \
asm("ST      -Y,   R5    ");   \
asm("ST      -Y,   R6    ");   \
asm("ST      -Y,   R7    ");   \
asm("ST      -Y,   R8    ");   \
asm("ST      -Y,   R9    ");   \
asm("ST      -Y,   R10   ");   \
asm("ST      -Y,   R11   ");   \
asm("ST      -Y,   R12   ");   \
asm("ST      -Y,   R13   ");   \
asm("ST      -Y,   R14   ");   \
asm("ST      -Y,   R15   ");   \
asm("ST      -Y,   R24   ");   \
asm("ST      -Y,   R25   ");   \
asm("ST      -Y,   R26   ");   \
asm("ST      -Y,   R27   ");   \
asm("in      R24,0x3D");   \
asm("ST      -Y,   R24   ");   \
asm("IN      R24,0x3E");   \
asm("ST      -Y,   R24   ");   \
}while(0)

#define RESTORE_CONTEXT()          \
do{                              \
asm("LD      R24,Y+    ");   \
asm("OUT   0X3E, R24   ");   \
asm("LD      R24,Y+    ");   \
asm("OUT   0X3D, R24   ");   \
asm("LD      R27,Y+    ");   \
asm("LD      R26,Y+    ");   \
asm("LD      R25,Y+    ");   \
asm("LD      R24,Y+    ");   \
asm("LD      R15,Y+    ");   \
asm("LD      R14,Y+    ");   \
asm("LD      R13,Y+    ");   \
asm("LD      R12,Y+    ");   \
asm("LD      R11,Y+    ");   \
asm("LD      R10,Y+    ");   \
asm("LD      R9,   Y+    ");   \
asm("LD      R8,   Y+    ");   \
asm("LD      R7,   Y+    ");   \
asm("LD      R6,   Y+    ");   \
asm("LD      R5,   Y+    ");   \
asm("LD      R4,   Y+    ");   \
}while(0)

//                     R16:R17          R18:R19         
void CTX_Swap(TContext **ppContext1,TContext **ppContext2)
{
    SAVE_CONTEXT();
   
    asm ("movw    r30,r16");       //Z=ppContext1
    asm ("st      z+, r28");       //*ppContext1=Y
    asm ("st      z,r29");
   
    asm ("movw    r30,r18");       //Z=ppContext2
    asm ("ld      r28, z+");       //Y=*ppContext2
    asm ("ld      r29, z");
   
    RESTORE_CONTEXT();
   
   asm ("ret");
}


点击此处下载 ourdev_452919.rar(文件大小:200K) (原文件名:VoidTask.7z.rar)

void_c 发表于 2009-6-14 23:50:23

更新一下:20090614

移植到STM32,只能使用主堆栈,上下文切换只保护R4-11,LR。


#include "VT.h"
#include "hal_cpu.h"

void CTX_Init(TContext **ppContext,TTaskProc *TaskProc,void *Stack1)
{
ctx_sp_t *ctx_sp;

ctx_sp=(ctx_sp_t *)Stack1 - 1;    //调整上下文指针,预留空间保存上下文

ctx_sp->_lr = ((uint32)TaskProc); //填充任务地址

ctx_sp->_r4 = 0x04;          //填充R4-R11
ctx_sp->_r5 = 0X05;
ctx_sp->_r6 = 0x06;
ctx_sp->_r7 = 0x07;
ctx_sp->_r8 = 0x08;
ctx_sp->_r9 = 0x09;
ctx_sp->_r10 = 0x10;
ctx_sp->_r11 = 0x11;

CRITICAL()
{
    *ppContext=(void *)ctx_sp;   //保存新的上下文指针
}
}

//寄存器分为 "草稿寄存器“和 "存储寄存器" --------个人叫法
//外部函数可以任意使用草稿寄存器而不必恢复,而使用存储寄存器必须先保护

//Cortex-M3
//草稿寄存器R0-R3,R12
//存储寄存器R4-11,
//特殊寄存器SP,LR,PC

//上下文切换只保护存储寄存器寄存器,lr
#define SAVE_CONTEXT()             \
do{                              \
    asm ("push {r4-r11,lr}");      \
}while(0)

#define RESTORE_CONTEXT()          \
do{                              \
    asm ("pop {r4-r11,lr}");       \
}while(0)



//注意:CM3任务只能使用主堆栈!!!!!!

//void CTX_Swap(TContext **ppContext1,TContext **ppContext2)
//SAVE_CONTEXT
//*ppContext1=SP
//SP=*ppContext2
//RESTOR_CONTEXT
//return

//                     r0                     r1
void CTX_Swap(TContext **ppContext1,TContext **ppContext2)
{
SAVE_CONTEXT();

asm ("mov    r4,sp");         //*ppContext1=SP
asm ("str    r4,");

asm ("ldr    r4,");//SP=*ppContext2
asm ("mov    sp,r4");

RESTORE_CONTEXT();

asm ("bx    lr");
}


点击此处下载 ourdev_453262.rar(文件大小:594K) (原文件名:VoidTask.7z.rar)
页: [1]
查看完整版本: 尝试写个简单任务调度内核voidtask