我写的嵌入式操作系统,现在传上来与大家共同探讨!
看过几个的嵌入式操作系统,汇编的精巧,移植难,看明白也不容易.C的庞大,吃内存.我想要一个综合两者的优先点系统,于是DIY一方,尝试了一下.编译器-IAR,CPU-M64,最高级优化,
只含定时器,两个跑马灯任务,CODE 1400Byte,RAM 269Byte,不含中断嵌套,可以关闭内核堆栈,加入信号量,互斥体,邮箱后,任务堆栈,函数调用深度堆栈(RSTACK)都要增加点击此处下载ourdev_181833.rar(文件大小:143K)
一个信号量,一个互斥体,一个邮箱,三个小任务,CODE 2717Byte,RAM 465Byte,含允许一级中断嵌套的内核堆栈点击此处下载ourdev_181834.rar(文件大小:166K)
一个信号量 两个小任务,CODE 1947Byte,RAM 320Byte 关闭中断嵌套的内核堆栈点击此处下载ourdev_181835.rar(文件大小:152K)
一个互斥体 两个小任务,CODE 1991Byte,RAM 322Byte 关闭中断嵌套的内核堆栈点击此处下载ourdev_181836.rar(文件大小:153K)
一个邮箱 三个小任务,CODE 1991Byte,RAM 405Btye 关闭中断嵌套的内核堆栈点击此处下载ourdev_181837.rar(文件大小:152K)
基本上是用C写的,用汇编部分只是对寄存器进行出栈,入栈,中断出入.
抢先式调度,同优先级的按FCFS原则进行调度
看到最后生成的代码,和内存占用量,离最初的目标还好远.
发代码时又有了一个新的想法:如果信号量,互斥体,邮箱不使用超时机制,代码量应该可以更小,但是不用超时机制会怎样,怎样应用呢?
不使用超时机制一个信号量,一个互斥体,一个邮箱,三个小任务,CODE 1918Byte,RAM 404Byte,不允许一级中断嵌套的内核堆栈点击此处下载ourdev_181955.rar(文件大小:152K)
欢迎各位验证,拍砖,找虫,打压(尽可能生也更小的代码和内存占用量),共同探讨嵌入式操作系统及应用(应用是最终目的^_^) 强。有没有OS讨论群?
我也想裁减一下usmartx,或者结合small rtos和usmartx,以适合更小行MCU(4KRAM,256字节RAM)。 我的QQ还开不了群,有兴趣加我156388624,发消息MircoROS 我认为在小型MCU,特别是小RAM的MCU,没必要用抢先式调度,并且给每个任务都分配堆栈。
任务多了,RAM占用量是很大的。
不如用协作式,也不必给任务单独分配堆栈。占用RAM量将减小很多。 #define OS_ENTER_CRITICAL() {cpu_sreg = SREG;OS_DISABLE_INTERRUPT();}//OS_DISABLE_INTERRUPT()//
#define OS_EXIT_CRITICAL() {SREG = cpu_sreg;}//OS_ENABLE_INTERRUPT()//
嵌套的话,会不会有危险? 协作式的任务是不能返回的,所以在程序时有很多限制,只能使用状态机制进行流程控制.如果采用时间片也和抢占式的一样要占用不少的RAM.
#define OS_ENTER_CRITICAL() {cpu_sreg = SREG;OS_DISABLE_INTERRUPT();}//OS_DISABLE_INTERRUPT()//
#define OS_EXIT_CRITICAL() {SREG = cpu_sreg;}//OS_ENABLE_INTERRUPT()//
在嵌套时是不会有危险的,可以放心使用的 强人,我一直想用一个,可是自己写不出来,终于。。。。 下面我贴一个协作式的处理方法,没有信号量,互斥体和邮箱:
并非我原创.
____________________________sch.h____________________________
typedef struct
{
void (*Function)(void);
UINT32 Delay;
UINT16 Period;
UINT16 RunMe;
}TASK;
#ifndef NULL
#define NULL 0
#endif
#define REPORT_ERRORS0
#define TICKS_PER_SEC100
#define SCH_MAX_TASKS3
#define NORMAL (0)
#define OK (1)
#define IGNORE (2)
#define ABOUT (3)
#define CANCEL (4)
#define TIMEOUT (5)
#define ERROR_TOO_MANY_TASKS (21)
#define ERROR_CANNOT_DELETE_TASK (22)
#define INEXISTENCE (255)
#define __BIT_MASK(BIT) (0x0001<<BIT)
#define __BIT_NMASK(BIT) (~(1<<BIT))
#define ClrBit(PORT,MSK) PORT &= ~(MSK)
#define SetBit(PORT,MSK) PORT |= MSK
#ifdef __SYSTEM_C
#define SYS_EXTERN
#else
#define SYS_EXTERN extern
#endif
SYS_EXTERN TASK gTask;
SYS_EXTERN UINT32 gErrorCode;
SYS_EXTERN UINT32 gLastErrorCode;
SYS_EXTERN UINT32 gErrorTickCnt;
void SchedulerInit (void);
void SchedulerStart(void);
void SchedulerDispatchTask(void);
void ReportStatus(void);
void GoToSleep(void);
UINT8 AddTask(void (*Fnc)(void),UINT32 Del,UINT32 Per);
BOOL DeleteTask(UINT8 Task_Index);
_____________________________________sch.c__________________________________________
/*
*************************************************************************************
**
** 时间触发调度器
**
** 文 件 名: scheduler.c
**
** 版 本: 1.0
**
** 日 期: 2005/02/09
**
** 描 述: 参考<时间嵌入式系统设计模式>的混合式调度器的设计思想,应用到AVR系统上来.支持多个
** 合作式调度的任务支持一个抢式任务(可以中断合作式任务)
**
** 历 史 记录:
** 1. 日期: 2005/02/09
** 作者:
** 修改: 创建
**
*************************************************************************************
*/
#define __SYSTEM_C
#include "system.h"
void TickISR(void);
voidSchedulerInit (void)
{
UINT32 freq;
//初始化定时器
for (UINT8 Index = 0; Index < SCH_MAX_TASKS; Index ++)
{
gTask.Function = NULL;
gTask.Delay = 0;
gTask.Period = 0;
gTask.RunMe = 0;
}
}
void SchedulerStart(void)
{
//启动定时器
//开启中断
}
//__irq __arm
void TickISR(void)
{
UINT8 Index;
for (Index = 0; Index < SCH_MAX_TASKS; Index ++)
{
if (gTask.Function != NULL) /* 有一个任务 */
{
if (gTask.Delay == 0) /* 需要运行 */
{
{
gTask.RunMe ++;
}
if (gTask.Period) /* 是定期调度的任务 */
{
gTask.Delay = gTask.Period;
}
}
else
{
gTask.Delay --; /* 任务运行的时间还没有到 */
}
}
}
}
void SchedulerDispatchTask(void)
{
UINT8 Index;
for (Index = 0; Index < SCH_MAX_TASKS; Index++ )
{
if ((gTask.RunMe > 0))
{
if (gTask.Function != NULL)
(*gTask.Function)();
gTask.RunMe --;
if (gTask.Period == 0)
{
gTask.Function = NULL;
}
}
}
ReportStatus();
GoToSleep();
}
void ReportStatus(void)
{
#if REPORT_ERRORS > 0
if (gErrorCode != gLastErrorCode)
{
/* 在此处添加出错提示代码 */
gLastErrorCode = gErrorCode;
if (gErrorCode != 0)
{
gErrorTickCnt = 60000;
}
else
{
gErrorTickCnt = 0;
}
}
else
{
if (gErrorTickCnt != 0)
{
if (--gErrorTickCnt == 0)
{
gErrorCode = 0;
}
}
}
#endif
}
void GoToSleep(void)
{
}
UINT8 AddTask(void (*Fnc)(void), //任务函数
UINT32 Del, //直到任务第一次运行时的时标数
UINT32 Per //重复运行之间的时标数
)
{
UINT8 Index = 0;
while ( (gTask.Function != NULL) && (Index < SCH_MAX_TASKS))
{
Index++;
}
if (Index == SCH_MAX_TASKS)
{
gErrorCode = ERROR_TOO_MANY_TASKS;
return SCH_MAX_TASKS;
}
gTask.Function = Fnc;
gTask.Delay = Del;
gTask.Period = Per;
gTask.RunMe = 0;
return Index;
}
BOOL DeleteTask(UINT8 Index)
{
BOOL Return_Code;
if (gTask.Function == 0)
{
gErrorCode = ERROR_CANNOT_DELETE_TASK;
Return_Code = FALSE;
}
else
{
Return_Code = TRUE;
}
gTask.Function = NULL;
gTask.Delay = 0;
gTask.Period = 0;
gTask.RunMe = 0;
return Return_Code;
}
__________________________________________main.c_______________________________
void Task1(void)
{
任务必须返回,处理时间要小于调度时间
}
................
void main(void)
{
//添加任务
AddTask(Task1);
//下面的就不用管了
SchedulerStart();
for (;;)
{
SchedulerDispatchTask();
}
} 协作式的任务是要返回的,协作式有个很大的优点就是可以不必给任务分配堆栈,不单独分配堆栈空间,任务占用的总堆栈空间是任务中使用堆栈空间最大的一个。
假设有5个任务,实际堆栈空间使用最大值分别是80,80,80,80,100,分配堆栈裕量是20,
不考虑中断
采用协作式,使用最大总堆栈空间是100,如果需要给总堆栈分配一个空间加上裕量是100+20=120
采用抢占式,给任务分配的空间分别是100,100,100,100,120,总共是100+100+100+100+120=520
如果考虑中断用栈没有与任务用栈分开,假设中断用栈是40,裕量10
采用协作式,如果需要给总堆栈分配空间 120+50=170
采用抢占式,给任务分配的空间分别是 (100+50)+(100+50)+(100+50)+(100+50)+(120+50)=770
省RAM空间是很大的。任务越多,节省空间越大。
抢占式调度占用RAM空间绝大部分都是分配给任务堆栈。
还有抢占式任务切换的时候,进栈,出栈也要花费大量时间。
如果出现了
//假设中断是开放的
OS_ENTER_CRITICAL();//执行后,SREG.7=0,cpu_sreg.7=1
OS_ENTER_CRITICAL();//执行后,SREG.7=0,cpu_sreg.7=0
OS_EXIT_CRITICAL();//执行后,cpu_sreg.7=0,SREG.7=0
OS_EXIT_CRITICAL();//执行后,cpu_sreg.7=0,SREG.7=0 看来是理解的问题.
void A (void)
{
OS_ENTER_CRITICAL();//
................
OS_EXIT_CRITICAL();//
}
void B(void)
{
OS_ENTER_CRITICAL();//
A();
OS_EXIT_CRITICAL();//
}
这种嵌套是没问题的.
但,下面这种就有问题了.
void B(void)
{
OS_ENTER_CRITICAL();//
....
OS_ENTER_CRITICAL();//
A();
OS_EXIT_CRITICAL();//
....
OS_EXIT_CRITICAL();//
}
这根本上是错误的,没有意义,必须避免.
OS_ENTER_CRITICAL();//表示进入关键代码
OS_EXIT_CRITICAL();//表示退出键代码
必须配对使用.
同样,在同一个函数中,OS_MutexLock 与OS_MutexUnLock也必须配对使用 我的意思是嵌套,就像括号一样,(与)成对。
那么嵌套括号就是(……(……)……).
对应就是
OS_ENTER_CRITICAL();
……
OS_ENTER_CRITICAL();
……
OS_EXIT_CRITICAL();
……
OS_EXIT_CRITICAL(); 强烈支持楼主,先一下了,系统开销情况怎么样,还有怎不能写个使用手册的,方便大家移植和使用. 支持楼主,学习一下 楼主厉害,向楼主学习 强人 强,记号 谢谢 我看得眼花撩乱! 写OS不用太多资金投入,希望网站能组织个嵌入式OS的开源项目,重在学习,呵呵。 mark 标记一下. mark! 严重学习当中。 学习 mark mark 看看 学习中,谢谢楼主分享 强烈希望网站能建个嵌入式OS的群,重在学习。 牛人。。。 mark 回帖是个好习惯 学习!!!!!!! 学习,不过好像看不懂.
页:
[1]