搜索
bottom↓
回复: 2

自己画了个avr的RTOS,但有点问题麻烦大家帮忙看看~

[复制链接]

出0入0汤圆

发表于 2012-5-11 22:51:07 | 显示全部楼层 |阅读模式
本帖最后由 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[TOTAL_TASK_STACK];

unsigned char TaskID=0;
unsigned char TaskRunID=0;
unsigned int OSTaskStackTop[TASK_NUM];

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[TaskID++]=(unsigned int)pStack;
}

void OSStartTask(void)
{
  SP=OSTaskStackTop[0]+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[TaskRunID++]=SP;
  if(TaskRunID>=TaskID) TaskRunID=0;
  SP=OSTaskStackTop[TaskRunID];
  
  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[49]);
  OSTaskCreate(Task2,&Stack[99]);
  
  OSStartTask();
}



Task2运行的时候只要_delay_ms()的值小于5时,LED就会常亮,大于5时就常灭。
将Task2延时改为
  for(unsigned char i=0;i<1000;i++)
{ _delay_ms(4);}
也是没法延时,好像局部变量在切换后清零了,仔细看了下堆栈的操作也应该没问题,各位前辈麻烦指点一小下下!!!

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

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

出0入0汤圆

发表于 2012-5-12 07:59:43 | 显示全部楼层
没有 看你的代码,仅从症状描述看

“延时超过一个时间片(5ms)后的指令就没办法执行”

PC指针恢复不正确。

“局部变量好像也在切换任务后归零了”

寄存器 压栈 或者出栈错误

出0入0汤圆

 楼主| 发表于 2012-5-13 17:18:15 | 显示全部楼层
楼上先谢谢啊!

但有一段  asm("RJMP OSSched")   其他帖子上都是 asm("JMP OSSched")  atmega48没有JMP,用RJMP会不会有影响??

还有说是GCC优化选择 -Os(原话:优化设置:-0s,其他形式下需要改变入栈与出栈代码) 这是啥意思,要到哪设置,是不是makefile 中的优化等级 s 级啊??

这个星期一直纠结在这上面,OSSched()中的入栈和出栈我也其他贴比对了,没问题。还是说atmega48的入栈和出栈有特殊要求?

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

本版积分规则

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

GMT+8, 2024-7-23 11:20

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

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