新手移植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 寫的好,頂起先. good,要顶 更正:
1.新加OS_CONTEXT_SWITCH_METHOD,为0任务切换保护全部32个寄存器,SREG,Os_Enter_Sum和返回地址(共36字节), 为1 任务切换保只护其中20个寄存器,SREG,Os_Enter_Sum和返回地址(共24字节)。 修改一下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。 照LS那样改后,加上#include <avr/pgmspace.h>,各个任务就不能运行了!
虽然是可以节省SRAM,但是程序不能运行
我曾经做过试验,一个很简单的一维数组,如果像上面这样存放在FLASH中,那么直接去读取数组中的一个数据好像没有多大问题,当连续去读时就会出错,而用pgm_read_byte(&(OSMapTbl))这样去读时就不会出错。
本人也是菜鸟一个,对UCOS还不了解,不知我说的对不对,请LS验证一下,谢谢
还是要感谢LZ 此贴不要顶了。
这是我当初才刚开始学AVR发的帖子。
错误肯定是难免的。
(以前是出生牛犊不怕虎,才学了点皮毛SMALL RTOS51,就敢发上来)
Small RTOS很久都没用了,忘记的已经差不多了。 路过 看看!! mark 顶了!
页:
[1]