ATmega8515 发表于 2007-5-15 18:24:55

新手移植Small RTOS for AVR第四版,欢迎测试,期待高手指点。

AVR新手移植Small RTOS第四版,欢迎测试,期待高手指点。



更新:新加OS_CONTEXT_SWITCH_METHOD,在OS_CPU.h,为0任务切换保护全部32个寄存器, 为1 任务切换保只护其中22个寄存器,这样可以节省大量的堆栈空间。



根据程明计 SMALL RTOS51一书所讲:

“C51编译器在编译C语言程序时,如果发现一个函数调用了一个外部函数,就认为这个函数返回时,R0-R7,ACC,B,PSW,DPH,DPL等寄存器已经变化。因此,它不会在调用这个函数前用这些寄存器保存有用数据,外部函数返回时这些寄存器是什么值都不影响程序执行。”

以及AVR-GCC C调用汇编规则:

“R18-R27,R30,R31,局部变量分配寄存器,汇编可以自由使用这些寄存器,无需恢复”。



推断:任务切换时,不必保护R18-R27,R30,R31。



根据AVR实际情况,改动原版Small RTOS51的地方:

1.新加OS_CONTEXT_SWITCH_METHOD,为0任务切换保护全部32个寄存器,SREG,Os_Enter_Sum和返回地址(共36字节), 为1 任务切换保只护其中22个寄存器,SREG,Os_Enter_Sum和返回地址(共26字节)。

#define OS_CONTEXT_SWITCH_METHOD        1        //在OS_CPU.h

2.不区分任务快速切换和一般任务切换,OSCtxSw()和OSIntCtxSw()为同一函数。

#define OSIntCtxSw()        OSCtxSw()//在OS_CPU.h。

3.空闲任务OSIdle()也有自己一份堆栈。

4.不是将所有剩余SRAM空间分配给系统堆栈,系统堆栈空间大小由自己设定

#define         OS_STACK_SIZE         512                //在OS_CPU.h,系统堆栈空间大小(包括空闲任务OSIdle的堆栈)

5.新加EN_OSStkChk,在OS_CPU.h里,#define EN_OSStkChk                        1

根据两个全局变量OS_Stk_Null,OS_Stk_Min_Null查看切换任务时系统堆栈剩余大小。可以参考此值调整OS_STACK_SIZE大小。

6..非系统管理中断(不受OS_ENTER_CRICITAL()影响)用法:

打开非系统管理中断编译开关

#define EN_SP2                      1//在OS_CPU.h

定义非系统管理中断预留堆栈大小

#define        Sp2Space            32          //在OS_CPU.h

改写三个宏

OS_ENTER_CRITICAL():打开总中断,关闭系统管理中断(包括系统时钟中断),Os_Enter_Sum加一

OS_ENTER_EXIT ():Os_Enter_Sum减一,如果为0,则打开总中断,打开系统管理中断(包括系统时钟中断)

OS_SET_INT打开总中断(R0暂存SREG,将R0最高位置位即可,不要直接操作SREG),打开系统管理中断(包括系统时钟中断),不需要对Os_Enter_Sum减一操作。

非系统管理中断由用户任务在必要的时候打开。

注意:非系统管理中断中不能再开中断。





欢迎测试,期待高手指点。







测试例子16个任务控制16个LED闪烁,任务切换只保存通用寄存器中的22个(如果保护全部32个寄存器,16个任务ATmega16 1K的SRAM空间不够用)。

#define OS_CONTEXT_SWITCH_METHOD                1

硬件连线:

PORTB0-------------------LED0        //20ms闪烁一次

PORTB1-------------------LED1         //40ms闪烁一次

PORTB2-------------------LED2         //80ms闪烁一次

PORTB3-------------------LED3        //160ms闪烁一次

PORTB4-------------------LED4        //320ms闪烁一次

PORTB5-------------------LED5        //640ms闪烁一次

PORTB6-------------------LED6        //1.28s闪烁一次

PORTB7-------------------LED7        //2.56s闪烁一次

PORTD0-------------------LED8        //5.12s闪烁一次       

PORTD1-------------------LED9         //10.24s闪烁一次

PORTD2-------------------LED10        //20.48s闪烁一次

PORTD3-------------------LED11//40.96s闪烁一次

PORTD4-------------------LED12        //80.92s闪烁一次       

PORTD5-------------------LED13         //2.73m闪烁一次

PORTD6-------------------LED14        //5.46m 闪烁一次

PORTD7-------------------LED15//10.92m闪烁一次





#include "config.h"





#define LED_PORT0        PORTB

#define LED_DDR0        DDRB

#define LED_PORT1        PORTD

#define LED_DDR1        DDRD



void Task0(void)

{

        LED_PORT0=0XFF;

        LED_DDR0=0XFF;

        LED_PORT1=0XFF;

        LED_DDR1=0XFF;





        while(1)

        {

        OSWait(K_TMO,OS_TICKS_PER_SEC/50);

        LED_PORT0^=_BV(0);                                //20ms闪烁一次

        OSSendSignal(1);

        }

}





void Task1(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);               

        }

        LED_PORT0^=_BV(1);                //40ms闪烁一次

        OSSendSignal(2);

        }



}



void Task2(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);               

                }

        LED_PORT0^=_BV(2);        //80ms闪烁一次

        OSSendSignal(3);

        }



}



void Task3(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);               

                }

        LED_PORT0^=_BV(3);                //160ms闪烁一次

        OSSendSignal(4);

        }



}



void Task4(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);               

                }

        LED_PORT0^=_BV(4);                //320ms闪烁一次

        OSSendSignal(5);

        }



}

   void Task5(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);               

                }

        LED_PORT0^=_BV(5);                //640ms闪烁一次

        OSSendSignal(6);

        }



}



   void Task6(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);               

                }

        LED_PORT0^=_BV(6);                        //1.28s闪烁一次

        OSSendSignal(7);

        }



}

    void Task7(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);        //2.56s闪烁一次       

                }

        LED_PORT0^=_BV(7);

        OSSendSignal(8);

        }



}

    void Task8(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);        //5.12s闪烁一次       

                }

        LED_PORT1^=_BV(0);

        OSSendSignal(9);

        }



}



   void Task9(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);                //10.24s闪烁一次       

                }

        LED_PORT1^=_BV(1);

        OSSendSignal(10);

        }

}



   void Task10(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);                //20.48s闪烁一次

                }

        LED_PORT1^=_BV(2);

        OSSendSignal(11);

        }

}





   void Task11(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);                //40.96s闪烁一次       

                }

        LED_PORT1^=_BV(3);

        OSSendSignal(12);

        }

}







    void Task12(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);                //81.92s闪烁一次       

                }

        LED_PORT1^=_BV(4);

        OSSendSignal(13);

        }

}





   void Task13(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);                //2.73m闪烁一次       

                }

        LED_PORT1^=_BV(5);

        OSSendSignal(14);

        }

}



void Task14(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);                //5.46m闪烁一次       

                }

        LED_PORT1^=_BV(6);

        OSSendSignal(15);

        }

}





void Task15(void)

{

uint8 i;

                while(1)

        {

        for(i=0;i<2;i++)

                {

                OSWait(K_SIG,0);                //10.92m闪烁一次       

                }

        LED_PORT1^=_BV(7);



        }

}



点击此处下载armok01154202.rar

eddia2000 发表于 2007-5-15 18:37:33

寫的好,頂起先.

johnlj 发表于 2007-5-16 00:02:33

good,要顶

ATmega8515 发表于 2007-5-16 10:46:20

更正:

1.新加OS_CONTEXT_SWITCH_METHOD,为0任务切换保护全部32个寄存器,SREG,Os_Enter_Sum和返回地址(共36字节), 为1 任务切换保只护其中20个寄存器,SREG,Os_Enter_Sum和返回地址(共24字节)。

korren 发表于 2007-5-17 12:06:56

修改一下OS_CORE.C下的这一段代码可以节省一点RAM.

#if OS_MAX_TASKS < 9

uint8 OSTaskRuning = 0xff;

uint8const OSMapTbl[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00};

#else

uint16 OSTaskRuning = 0xffff;

uint16 const OSMapTbl[] = {0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000,0x0000};

#endif

改为:

#if OS_MAX_TASKS < 9

uint8 OSTaskRuning = 0xff;

uint8const PROGMEMOSMapTbl[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00};

#else

uint16 OSTaskRuning = 0xffff;

uint16 const PROGMEM OSMapTbl[] = {0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000,0x0000};

#endif。

jiben042 发表于 2009-4-11 14:52:26

照LS那样改后,加上#include <avr/pgmspace.h>,各个任务就不能运行了!
虽然是可以节省SRAM,但是程序不能运行
我曾经做过试验,一个很简单的一维数组,如果像上面这样存放在FLASH中,那么直接去读取数组中的一个数据好像没有多大问题,当连续去读时就会出错,而用pgm_read_byte(&(OSMapTbl))这样去读时就不会出错。
本人也是菜鸟一个,对UCOS还不了解,不知我说的对不对,请LS验证一下,谢谢
还是要感谢LZ

void_c 发表于 2009-4-14 22:49:33

此贴不要顶了。

这是我当初才刚开始学AVR发的帖子。
错误肯定是难免的。
(以前是出生牛犊不怕虎,才学了点皮毛SMALL RTOS51,就敢发上来)

Small RTOS很久都没用了,忘记的已经差不多了。

algebra 发表于 2009-12-4 13:11:35

路过 看看!!

wcm_e 发表于 2009-12-4 16:37:43

mark

shushikuan 发表于 2011-6-29 23:42:15

顶了!
页: [1]
查看完整版本: 新手移植Small RTOS for AVR第四版,欢迎测试,期待高手指点。