dongwen543 发表于 2011-9-28 07:31:41

看看

sddzycnq 发表于 2011-9-28 22:11:30

mark

feixuehanyi 发表于 2011-10-8 18:48:04

mark

summerstar 发表于 2011-10-8 21:41:45

确实不错!

skefer 发表于 2011-10-16 15:24:40

嵌入式入门..不好入啊..还是不能看得太懂,难道需要一些汇编基础知识么..

zuzuzu 发表于 2011-10-18 01:53:46

收藏

xingyunma 发表于 2011-11-24 14:42:51

此贴只应天上有

along 发表于 2011-11-24 16:52:32

mark

love_TYQ 发表于 2011-11-25 15:26:43

跑第四个的时候,有些问题,原程序跑的时候,会运行一次后,跑到ROM没有使用的空间去,按以下的方法更改一下就行了:半天工夫找出来的;
void OSSched(void)
{
        //根据中断时保存寄存器的次序入栈,模拟一次中断后,入栈的情况
        __asm__ __volatile__("PUSH __zero_reg__");//R1
        __asm__ __volatile__("PUSH __tmp_reg__");//R0
        __asm__ __volatile__("IN   __tmp_reg__,__SREG__");//保存状态寄存器SREG
        __asm__ __volatile__("PUSH __tmp_reg__");
        __asm__ __volatile__("CLR__zero_reg__ ");//R0重新清零

        __asm__ __volatile__("PUSH R18");
        __asm__ __volatile__("PUSH R19");
        __asm__ __volatile__("PUSH R20");
        __asm__ __volatile__("PUSH R21");
        __asm__ __volatile__("PUSH R22");
        __asm__ __volatile__("PUSH R23");
        __asm__ __volatile__("PUSH R24");
        __asm__ __volatile__("PUSH R25");
        __asm__ __volatile__("PUSH R26");
        __asm__ __volatile__("PUSH R27");
        __asm__ __volatile__("PUSH R30");
        __asm__ __volatile__("PUSH R31");
        __asm__ __volatile__("PUSH R28");
        __asm__ __volatile__("PUSH R29");

        TCB.OSTaskStackTop=SP;         //将正在运行的任务的堆栈底保存

   unsigned char flag=0;
        unsigned char OSNextTaskID;                           //在现有堆栈上开设新的空间
        // for (OSNextTaskID = 0;                                  //进行任务调度
                // (OSNextTaskID < OSTASK )&& (!(OSRdTab & (0x01<<OSNextTaskID)));
                // OSNextTaskID++);
       
        for(OSNextTaskID=0;OSNextTaskID<OSTASK;OSNextTaskID++)
        {
                if(OSRdTab & (0x01<<OSNextTaskID))
                {
                        flag=1;
                        OSTaskRuningPri = OSNextTaskID ;
                        break;
                }
        }
       
        //三个任务都执行过,重新开始
        if(flag==0)   
        {
                OSTaskRuningPri=OSTASK;
                //OSRdTab=0x07;
        }

        cli();//保护堆栈转换
        SP=TCB.OSTaskStackTop;
        sei();

        __asm__ __volatile__("POP R29");
        __asm__ __volatile__("POP R28");
        __asm__ __volatile__("POP R31");
        __asm__ __volatile__("POP R30");
        __asm__ __volatile__("POP R27");
        __asm__ __volatile__("POP R26");
        __asm__ __volatile__("POP R25");
        __asm__ __volatile__("POP R24");
        __asm__ __volatile__("POP R23");
        __asm__ __volatile__("POP R22");
        __asm__ __volatile__("POP R21");
        __asm__ __volatile__("POP R20");
        __asm__ __volatile__("POP R19");
        __asm__ __volatile__("POP R18");

        __asm__ __volatile__("POP__tmp_reg__");
        __asm__ __volatile__("OUT__SREG__,__tmp_reg__");
        __asm__ __volatile__("POP__tmp_reg__");
        __asm__ __volatile__("POP__zero_reg__");

}

问题出在,当前面三个任务都执行一次,原程序不能执行到任务调度的那个程序去,改成以上的就好了。

love_zjb 发表于 2011-11-25 19:04:21

mark

love_TYQ 发表于 2011-11-28 09:41:49

哪位大侠能解释一下第五篇实现的功能?看了好久都没有看懂

chenruichao 发表于 2011-11-28 16:20:35

这资料好,mark一下

zh172865401 发表于 2011-12-1 09:41:42

很好,记录下

anxiangbo 发表于 2011-12-12 13:06:46

mark

zhoubaoming 发表于 2011-12-12 16:24:03

学习下

xiaoshidu 发表于 2011-12-15 23:40:07

很好的记录过程!

Gloriousle 发表于 2011-12-19 17:17:21

挖古董了。

m_hornet 发表于 2011-12-19 19:44:21

这个必须留着 仔细研读

willX 发表于 2011-12-20 12:32:12

好贴! 顶。

mushk 发表于 2011-12-21 01:13:56

这个必须MARK

LitePuter_uvn 发表于 2011-12-21 14:54:42

古董贴,牛x~~

wb156351 发表于 2011-12-22 15:55:32

mark

Helloeveryon 发表于 2011-12-22 23:42:31

MARK

wzc0759 发表于 2011-12-29 19:13:25

mark

linux_dragon 发表于 2012-1-27 00:05:32

等时机成熟再来看
mark下

raohao101 发表于 2012-2-9 09:48:48

mark!!!!!!

loqin 发表于 2012-2-13 11:11:08

mark^

zhuht668 发表于 2012-2-16 10:48:58

收藏了

jyjmaster 发表于 2012-2-16 11:12:12

mark

yzuwdf 发表于 2012-2-16 13:49:50

好帖!!!!!!

yxyy 发表于 2012-2-16 15:59:39

mark

syma 发表于 2012-2-16 16:32:43

《建立一个属于自己的AVR的RTOS》

ailibuli 发表于 2012-2-24 22:26:45

mark!

yalihendaya 发表于 2012-2-27 15:01:23

该补习一下汇编了。。

abcfanyuan 发表于 2012-3-27 00:06:07

mark学习学习

Rainbow7 发表于 2012-3-27 00:07:39

听说不错,看看

zhengxg1990 发表于 2012-3-30 12:04:23

挖这么老的坟,这帖子确实不错,给了我很多启发{:smile:}

catshit_one 发表于 2012-3-30 21:08:38

现在开始学

bisoo 发表于 2012-3-31 09:43:53

有时间在慢慢的研究研究

jorkay 发表于 2012-4-20 09:43:25

mark{:time:}

keepmoving29 发表于 2012-5-26 15:29:32

记下来慢慢看....

acai039033 发表于 2012-6-13 13:44:59

没天理啊 怎么有这么好的文章,真正受用

kuki0702 发表于 2012-6-13 15:05:44

很不错的。。。先mark一下,再细读

eryueniao 发表于 2012-6-20 14:59:18

cool                                                                                                                                                                                                      

changwuyong 发表于 2012-6-21 01:16:32

标记一下

makathy 发表于 2012-6-28 22:49:00

看了很多次,

时代还怪 发表于 2012-7-3 12:10:51

我编译第四篇的时候出现excessive stack overflow,stop sim
avrstudio 仿真,优化等级是s
为什么会这样呢

zxqsd 发表于 2012-7-21 16:57:27

mark一下,以后查看

shuxmpx123 发表于 2012-7-23 15:39:48


这几天没啥事做,把Cortex-M3权威指南_cn 初略看了一遍,然后看了一点关于UCOSII的东西,突然发现理解了单片机的工作原理,以前也看过类似的资料,但是是一种很朦胧的理解,可能理解一个东西,是需要时间的。。

写UCOS的Jean J.Labrosse在他的书上有这样一句话,“渐渐地,我自然会想到,写个实时内核直有那么难吗?不就是不断地保存,恢复CPU的那些寄存器嘛。”

单片机工作也不就是这样嘛,不断的进栈,出栈;   操作系统的任务调度,也是不断的控制进栈,出栈;

Tliang 发表于 2012-7-23 22:39:49

我也写了一个简单的这个东西。。可是怎么没一个人顶。。。郁闷
源码:#include<avr/io.h>
#include"Task.h"
#include<avr/interrupt.h>

#define Task_Max5                                //任务数
#define Stack_Top 12                        //任务堆栈空间


typedef struct Task_Value
{
        uint8         p;                                        //任务堆栈指针
        uint16        delay;                                //任务延时
        uint8        State;                                //任务状态
}Task;

static Task Task_Buf;                                //任务空间

static uint8 Task_SP;        //任务堆栈空间

static uint8 Task_Run_ID;                                        //正在运行任务ID

void AddTask(uint16 TaskName, uint16 TaskDelay, uint8 TaskID)
{
        Task_Buf.p = (uint16)Task_SP + 9;
        //AVR单片机SP堆栈方向是由上往下生长的,执行RET的时候SP将加1,所以要比实际地址小1
        Task_SP = (uint8)(TaskName >> 8);                //地址高8位
        Task_SP = (uint8)(TaskName & 0xff);                //地址低8位
        Task_Buf.delay = TaskDelay;
        Task_Buf.State = 0;
}

void Task_Delay(uint16 Del)
{
        uint8 Temp = 0;
        Task_Buf.p        = SP;                                        //保存当前堆栈
        Task_Buf.delay = Del;                                //设置延时
        Task_Buf.State -= 1;                                //将状态置0

        for(Temp = 0;Temp < Task_Max - 1;Temp++)
        {
                if(Task_Buf.State == 1)                                //如果有任务处于就绪状态,执行.
                {
                        break;
                }
        }

        SP = Task_Buf.p;                                                        //将任务堆栈地址赋给SP堆栈地址
        Task_Run_ID = Temp;                                                                //运行改变ID
}

ISR(TIM0_OVF_vect)
{
        uint8 Index = 0;
        uint8 IDBuf = Task_Run_ID;                                                //保存当前运行任务的ID
        uint8 Task_Run_SP = Task_Buf.p - SP;       
        //任务堆栈指针减去当前堆栈指针得到中断所使用掉的堆栈

        TCNT0 = 0x00;
        Task_Buf.p = SP + Task_Run_SP;
        //当前堆栈指针加上中断所使用掉的堆栈数得到中断前堆栈指针,保存

        for(Index = 0;Index < Task_Max;Index++)
        {
                if(Task_Buf.p != 0)
                {
                        if((Task_Buf.delay == 0) && (Task_Buf.State == 0))
                        {
                                //如果任务延时时间到,将就绪置位
                                Task_Buf.State = 1;

                                if(Index < IDBuf)
                                {
                                        IDBuf = Index;                //如果当前运行任务优先级低于就绪任务则切换
                                }

                        }
                        else if((Task_Buf.delay != 0) && (Task_Buf.State == 0))
                        {

                                Task_Buf.delay -= 1;        //时间未到,时间标志减1

                        }
                }
        }
        //将运行任务指针减去中断所用堆栈数得到中断返回前的堆栈指针,中断返回将加上
        //中断所用掉的堆栈数量,就得到将运行任务的实际堆栈指针
        SP = Task_Buf.p - Task_Run_SP;       
        Task_Run_ID = IDBuf;                //改变当前运行任务ID

}

void Task_Kong(void)
{
        while(1);                                //当没有任务执行的时候就停留在此处,可以加入CPU空闲计算
}

void Time0_Task_Start(void)
{
        AddTask((uint16)Task_Kong, 0, Task_Max - 1);        //添加空任务
        TCCR0A = 0x00;
        TCCR0B = 0x03;
        TCNT0 = 0x00;
        TIMSK0 |= 0x01;
        sei();
        Task_Run_ID = Task_Max - 1;                                                //开始运行运行空任务,可用形参指定运行那个任务
        SP = Task_Buf.p;                                        //任务开始运行
}

Tliang 发表于 2012-7-23 22:40:05

我也写了一个简单的这个东西。。可是怎么没一个人顶。。。郁闷
源码:#include<avr/io.h>
#include"Task.h"
#include<avr/interrupt.h>

#define Task_Max5                                //任务数
#define Stack_Top 12                        //任务堆栈空间


typedef struct Task_Value
{
        uint8         p;                                        //任务堆栈指针
        uint16        delay;                                //任务延时
        uint8        State;                                //任务状态
}Task;

static Task Task_Buf;                                //任务空间

static uint8 Task_SP;        //任务堆栈空间

static uint8 Task_Run_ID;                                        //正在运行任务ID

void AddTask(uint16 TaskName, uint16 TaskDelay, uint8 TaskID)
{
        Task_Buf.p = (uint16)Task_SP + 9;
        //AVR单片机SP堆栈方向是由上往下生长的,执行RET的时候SP将加1,所以要比实际地址小1
        Task_SP = (uint8)(TaskName >> 8);                //地址高8位
        Task_SP = (uint8)(TaskName & 0xff);                //地址低8位
        Task_Buf.delay = TaskDelay;
        Task_Buf.State = 0;
}

void Task_Delay(uint16 Del)
{
        uint8 Temp = 0;
        Task_Buf.p        = SP;                                        //保存当前堆栈
        Task_Buf.delay = Del;                                //设置延时
        Task_Buf.State -= 1;                                //将状态置0

        for(Temp = 0;Temp < Task_Max - 1;Temp++)
        {
                if(Task_Buf.State == 1)                                //如果有任务处于就绪状态,执行.
                {
                        break;
                }
        }

        SP = Task_Buf.p;                                                        //将任务堆栈地址赋给SP堆栈地址
        Task_Run_ID = Temp;                                                                //运行改变ID
}

ISR(TIM0_OVF_vect)
{
        uint8 Index = 0;
        uint8 IDBuf = Task_Run_ID;                                                //保存当前运行任务的ID
        uint8 Task_Run_SP = Task_Buf.p - SP;       
        //任务堆栈指针减去当前堆栈指针得到中断所使用掉的堆栈

        TCNT0 = 0x00;
        Task_Buf.p = SP + Task_Run_SP;
        //当前堆栈指针加上中断所使用掉的堆栈数得到中断前堆栈指针,保存

        for(Index = 0;Index < Task_Max;Index++)
        {
                if(Task_Buf.p != 0)
                {
                        if((Task_Buf.delay == 0) && (Task_Buf.State == 0))
                        {
                                //如果任务延时时间到,将就绪置位
                                Task_Buf.State = 1;

                                if(Index < IDBuf)
                                {
                                        IDBuf = Index;                //如果当前运行任务优先级低于就绪任务则切换
                                }

                        }
                        else if((Task_Buf.delay != 0) && (Task_Buf.State == 0))
                        {

                                Task_Buf.delay -= 1;        //时间未到,时间标志减1

                        }
                }
        }
        //将运行任务指针减去中断所用堆栈数得到中断返回前的堆栈指针,中断返回将加上
        //中断所用掉的堆栈数量,就得到将运行任务的实际堆栈指针
        SP = Task_Buf.p - Task_Run_SP;       
        Task_Run_ID = IDBuf;                //改变当前运行任务ID

}

void Task_Kong(void)
{
        while(1);                                //当没有任务执行的时候就停留在此处,可以加入CPU空闲计算
}

void Time0_Task_Start(void)
{
        AddTask((uint16)Task_Kong, 0, Task_Max - 1);        //添加空任务
        TCCR0A = 0x00;
        TCCR0B = 0x03;
        TCNT0 = 0x00;
        TIMSK0 |= 0x01;
        sei();
        Task_Run_ID = Task_Max - 1;                                                //开始运行运行空任务,可用形参指定运行那个任务
        SP = Task_Buf.p;                                        //任务开始运行
}

Tliang 发表于 2012-7-23 22:44:54

在我这个程序里面Task_Delay里面的Task_Buf.State -= 1不知道为什么加了几个任务后不能用Task_Buf.State = 0来清0,只有减1了,AVR的汇编看不懂。所以来请教一下{:3_52:}

shuxmpx123 发表于 2012-7-24 10:12:06

楼上的朋友,看了你前面2个函数,有两个地方不懂。。。。

1:
static uint8 Task_SP;      //任务堆栈空间

Task_Buf.p = (uint16)Task_SP + 9;

这里定义的是二维数组,为什么下面用的时候是一维数组了;

2:
      for(Temp = 0;Temp < Task_Max - 1;Temp++)
      {
                if(Task_Buf.State == 1)                              //如果有任务处于就绪状态,执行.
                {
                        break;
                }
      }

      SP = Task_Buf.p;                                                      //将任务堆栈地址赋给SP堆栈地址
      Task_Run_ID = Temp;                                                                //运行改变ID

这里,如果没有任务处于就绪状态呢? 执行第Task_Max - 2 个任务?貌似不太严谨;

Tliang 发表于 2012-7-24 14:47:23

shuxmpx123 发表于 2012-7-24 10:12 static/image/common/back.gif
楼上的朋友,看了你前面2个函数,有两个地方不懂。。。。

1:


1.一个是Task_SP一个是Task_Buf不是一个
如果是说Task_Buf.p = (uint16)Task_SP + 9;这一句的话。这个是把Task_SP的地址给Task_Buf.p。
2.这个我创建了一个优先级为最低的任务,为Task_Max - 1这里如果直接用Temp < Task_Max的话,那么在循环完后Temp就和Task_Max一样大了。程序创建了Task_Max个任务空间,是由0~Task_Max-1而不是0~Task_Max所以没有就绪任务就执行优先级最低的任务。也就是Task_Kong这个任务什么也不做。

Tliang 发表于 2012-7-24 14:49:41

http://www.amobbs.com/thread-5487993-1-1.html
我发的那个贴,我已经把测试的程序打包放在5楼。你可以下去看看

shuxmpx123 发表于 2012-7-24 14:51:48

Tliang 发表于 2012-7-24 14:47 static/image/common/back.gif
1.一个是Task_SP一个是Task_Buf不是一个
如果是说Task_Buf.p = (uint16)Task_SP + 9; ...

哦明白了,谢谢

Tliang 发表于 2012-7-24 15:03:33

我贴那个程序是ATTINY24上面测试可以的。。。后面打包的是ATmega8的。前面是在ATmega8上测试后来移到ATtiny24上面了,有两个我没细看就把程序贴出来了,汗。。。难怪没人理。大概别人一看就以为不行吧。毕竟ATtiny24没多少人用过吧。。。

liuruoshui 发表于 2012-7-26 09:51:00

对此贴标准一下,系统工作原理上还有有所欠缺!

只是代号 发表于 2012-7-27 09:20:46

强帖留名。{:smile:}

leicai05 发表于 2012-8-14 16:50:44

avr rtos学习

kihell 发表于 2012-8-14 20:41:19

mark很好的东西

zhaolei2612 发表于 2012-9-10 13:00:42

mark,标记一下。

zenith1032 发表于 2012-9-12 11:06:55

mark,AVR rtos

Allen520 发表于 2012-11-26 10:38:10

{:lol:}{:lol:} 最近也认识了一位大虾,研究RTOS ,我也想找个入门的资料学习一下,结果看到这帖子了,感谢分享!!!

电子小生 发表于 2012-12-3 21:16:30

先记下,再慢慢看!

netawater 发表于 2012-12-3 21:21:28

果断收藏!

yushiqian_2012 发表于 2012-12-6 22:38:31

我已经复印了

211LIRUISHUO 发表于 2012-12-23 17:24:59

好东西啊,谢谢啦

211LIRUISHUO 发表于 2013-1-3 14:51:00

求教:
//防止被编译器占用

register unsigned char tempR4asm("r4");

register unsigned char tempR5asm("r5");

register unsigned char tempR6asm("r6");

register unsigned char tempR7asm("r7");

register unsigned char tempR8asm("r8");

register unsigned char tempR9asm("r9");

register unsigned char tempR10 asm("r10");

register unsigned char tempR11 asm("r11");

register unsigned char tempR12 asm("r12");

register unsigned char tempR13 asm("r13");

register unsigned char tempR14 asm("r14");

register unsigned char tempR15 asm("r15");

register unsigned char tempR16 asm("r16");

register unsigned char tempR16 asm("r17");

为什么要重复定义?

register unsigned char tempR16 asm("r16");

register unsigned char tempR16 asm("r17");

tempR16代表的是r16还是r17???

huzhen816 发表于 2013-4-17 16:58:29

有时间一定要研究研究!!!

jz701209李 发表于 2013-4-18 11:16:39

学习一下....

heart080811126 发表于 2013-4-21 21:18:17

谢谢莫老大的分享!!!!!!!!!!!!!!!!!!!!!

王力斯 发表于 2014-2-28 15:53:11

好好收藏下顶一个。。。

lizihui 发表于 2014-7-9 12:00:35

让这帖子继续啊,我现在用的ICC7,好像不支持*stack_p--= (unsigned int)Task;       //将任务的地址低位压入堆栈,
    *stack_p--= (unsigned int)Task >> 8;//将任务的地址高位压入堆栈,这种取函数地址,取出来的地址是错误的

滴答滴答下雨啦 发表于 2014-7-10 10:36:37

armok 发表于 2006-1-17 11:35
第八篇:占先式内核(完善的服务)



    如果将前面所提到的占先式内核和协作式内核组合在一起,很容易就可以 ...

学习了……谢谢!

b951011 发表于 2014-7-10 15:55:25

學習中,我要加油

www378660084 发表于 2014-7-14 19:37:21

写的非常好~~

werewofe 发表于 2014-8-1 16:45:45

PaulDE 发表于 2008-1-31 21:07
第八篇,占先式内核(完善的服务) 谁试过了?不知道何故我只是在PC端无休止的收到 0x00,郁闷啊
自己对串口 ...

00是有事在串口初始话的时候,URD = 0;你屏蔽掉就没有了

werewofe 发表于 2014-8-1 16:58:29

armok 发表于 2009-11-24 00:39
楼上,留意标题 : 教程: 建立一个属于自己的AVR的RTOS (作者:hjc800323)

已经注明了作者不是我。 ...

这贴子,有没有运行成功的啊,在设置串口的地方好像有问题,不应该在初始化时,置寄存器空中断,还有运行一次就复位

werewofe 发表于 2014-8-1 16:59:47

dzyong 发表于 2010-1-28 23:33
试过代码任务可以被挂起,但是任务恢复不了,不知怎么回事?

你们有试过,难道没有问题么?? ...

嗯,试了3天了,也不太好使

werewofe 发表于 2014-8-1 17:00:44

savagex 发表于 2010-3-16 10:01
事实证明,不管哪一个,所有任务运行一次后,都会复位,从0000开始重新运行。想了很久没想明白哪的问题。所 ...

3天了,我也准备放弃了

default 发表于 2014-8-13 22:47:53

现在在学习嵌入式系统,暂时还看不懂

shin555 发表于 2014-8-14 09:19:53

avr的rtos                                       mark

chpl 发表于 2014-9-3 12:29:36

好叼的帖子!!

RainKing 发表于 2014-9-4 19:25:53

必须顶啊...............

bbslhb 发表于 2018-7-6 19:41:56

惭愧,03年的时候刚上大学,就知道瞎金钵玩。现在知道多学点用处大了,回头学了。

余松灿 发表于 2019-7-29 10:54:48

似乎得非常熟悉编译原理,是这样吗?
页: 1 2 3 [4]
查看完整版本: 教程: 建立一个属于自己的AVR的RTOS (作者:hjc800323)