搜索
bottom↓
回复: 9

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

[复制链接]

出0入0汤圆

发表于 2007-5-15 18:24:55 | 显示全部楼层 |阅读模式
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

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2007-5-15 18:37:33 | 显示全部楼层
寫的好,頂起先.

出0入0汤圆

发表于 2007-5-16 00:02:33 | 显示全部楼层
good,要顶

出0入0汤圆

 楼主| 发表于 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字节)。

出0入0汤圆

发表于 2007-5-17 12:06:56 | 显示全部楼层
修改一下OS_CORE.C下的这一段代码可以节省一点RAM.

#if OS_MAX_TASKS < 9

uint8 OSTaskRuning = 0xff;

uint8  const 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;

uint8  const PROGMEM  OSMapTbl[] = {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。

出0入0汤圆

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

出0入0汤圆

发表于 2009-4-14 22:49:33 | 显示全部楼层
此贴不要顶了。

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

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

出0入0汤圆

发表于 2009-12-4 13:11:35 | 显示全部楼层
路过 看看!!

出0入0汤圆

发表于 2009-12-4 16:37:43 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-6-29 23:42:15 | 显示全部楼层
顶了!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 13:14

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表