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
似乎得非常熟悉编译原理,是这样吗?