自己画了个avr的RTOS,但有点问题麻烦大家帮忙看看~
本帖最后由 cadier 于 2012-5-11 22:54 编辑整个的环境为winavr20100110 atmega48
看了几个帖子,照猫画虎写了个时间片轮番调度的程序,但有些小问题。具体情况是系统能正常的切换任务,但各个任务中的延时没法正常进行,试了下延时超过一个时间片(5ms)后的指令就没办法执行,而且局部变量好像也在切换任务后归零了。我对单片机也是半瓶水,耽误大家一点时间给小弟指导指导,麻烦了!程序具体如下:
#include<avr/io.h>
#include<avr/interrupt.h>
#include<util/delay.h>
#define TASK_NUM 4
#define TASK_STACK_SIZE 50
#define TOTAL_TASK_STACK TASK_NUM*TASK_STACK_SIZE
unsigned char Stack;
unsigned char TaskID=0;
unsigned char TaskRunID=0;
unsigned int OSTaskStackTop;
void OSTaskCreate(void(*Task)(void),unsigned char *pStack)
{
unsigned char i;
*pStack--=(unsigned int)Task;
*pStack--=(unsigned int)Task>>8;
*pStack--=0x00; //R1
*pStack--=0x00; //R0
*pStack--=0x80; //SREG
for(i=0;i<30;i++)
{*pStack--=0x00;}
OSTaskStackTop=(unsigned int)pStack;
}
void OSStartTask(void)
{
SP=OSTaskStackTop+33;
TCNT0=0xB2;
asm("reti" "\t");
}
void OSSched(void)
{
asm volatile("PUSH R1""\t");
asm volatile("PUSH R0""\t");
asm volatile("IN R0,0x3F""\t");
asm volatile("PUSH R0""\t");
asm volatile("CLR R1""\t");
asm volatile("PUSH R2""\t");
asm volatile("PUSH R3""\t");
asm volatile("PUSH R4""\t");
asm volatile("PUSH R5""\t");
asm volatile("PUSH R6""\t");
asm volatile("PUSH R7""\t");
asm volatile("PUSH R8""\t");
asm volatile("PUSH R9""\t");
asm volatile("PUSH R10""\t");
asm volatile("PUSH R11""\t");
asm volatile("PUSH R12""\t");
asm volatile("PUSH R13""\t");
asm volatile("PUSH R14""\t");
asm volatile("PUSH R15""\t");
asm volatile("PUSH R16""\t");
asm volatile("PUSH R17""\t");
asm volatile("PUSH R18""\t");
asm volatile("PUSH R19""\t");
asm volatile("PUSH R20""\t");
asm volatile("PUSH R21""\t");
asm volatile("PUSH R22""\t");
asm volatile("PUSH R23""\t");
asm volatile("PUSH R24""\t");
asm volatile("PUSH R25""\t");
asm volatile("PUSH R26""\t");
asm volatile("PUSH R27""\t");
asm volatile("PUSH R28""\t");
asm volatile("PUSH R29""\t");
asm volatile("PUSH R30""\t");
asm volatile("PUSH R31""\t");
OSTaskStackTop=SP;
if(TaskRunID>=TaskID) TaskRunID=0;
SP=OSTaskStackTop;
asm volatile("POP R31""\t");
asm volatile("POP R30""\t");
asm volatile("POP R29""\t");
asm volatile("POP R28""\t");
asm volatile("POP R27""\t");
asm volatile("POP R26""\t");
asm volatile("POP R25""\t");
asm volatile("POP R24""\t");
asm volatile("POP R23""\t");
asm volatile("POP R22""\t");
asm volatile("POP R21""\t");
asm volatile("POP R20""\t");
asm volatile("POP R19""\t");
asm volatile("POP R18""\t");
asm volatile("POP R17""\t");
asm volatile("POP R16""\t");
asm volatile("POP R15""\t");
asm volatile("POP R14""\t");
asm volatile("POP R13""\t");
asm volatile("POP R12""\t");
asm volatile("POP R11""\t");
asm volatile("POP R10""\t");
asm volatile("POP R9""\t");
asm volatile("POP R8""\t");
asm volatile("POP R7""\t");
asm volatile("POP R6""\t");
asm volatile("POP R5""\t");
asm volatile("POP R4""\t");
asm volatile("POP R3""\t");
asm volatile("POP R2""\t");
asm volatile("POP R0""\t");
asm volatile("OUT 0x3f,R0""\t");
asm volatile("POP R0""\t");
asm volatile("POP R1""\t");
TCNT0=0xB2;
asm("reti" "\t");
}
void Timer0_init(void)
{
TCCR0B=0x00;
TCNT0=0xB2;
TIMSK0=0x01;
TCCR0A=0x00;
TCCR0B=0x03;
sei();
}
SIGNAL(SIG_OVERFLOW0)
{
asm("RJMP OSSched");
}
void Task1(void)
{
while(1)
{
DDRC=0b00000001;
PORTC=0b00000001;
}
}
void Task2(void)
{
while(1)
{
DDRC=0b00000010;
PORTC=0b00000000;
_delay_ms(500);
PORTC=0b00000010;
_delay_ms(500);
}
}
int main(void)
{
Timer0_init();
OSTaskCreate(Task1,&Stack);
OSTaskCreate(Task2,&Stack);
OSStartTask();
}
Task2运行的时候只要_delay_ms()的值小于5时,LED就会常亮,大于5时就常灭。
将Task2延时改为
for(unsigned char i=0;i<1000;i++)
{ _delay_ms(4);}
也是没法延时,好像局部变量在切换后清零了,仔细看了下堆栈的操作也应该没问题,各位前辈麻烦指点一小下下!!! 没有 看你的代码,仅从症状描述看
“延时超过一个时间片(5ms)后的指令就没办法执行”
PC指针恢复不正确。
“局部变量好像也在切换任务后归零了”
寄存器 压栈 或者出栈错误 楼上先谢谢啊!
但有一段asm("RJMP OSSched") 其他帖子上都是 asm("JMP OSSched")atmega48没有JMP,用RJMP会不会有影响??
还有说是GCC优化选择 -Os(原话:优化设置:-0s,其他形式下需要改变入栈与出栈代码) 这是啥意思,要到哪设置,是不是makefile 中的优化等级 s 级啊??
这个星期一直纠结在这上面,OSSched()中的入栈和出栈我也其他贴比对了,没问题。还是说atmega48的入栈和出栈有特殊要求?
跪谢能解决问题的前辈啊~
页:
[1]