- 嵌入式计算机通常被称为嵌入式系统
- 嵌入式系统是以应用为中心,以计算机技术为基础,软硬件可配置,对功能、可靠性、成本、体积、功耗有着严格要求的专用计算机系统
- 嵌入式系统是以应用为中心,以计算机技术为基础,软硬件可配置,对功能、可靠性、成本、体积、功耗有着严格要求的专用计算机系统
- 嵌入式系统主要由嵌入式微处理器、外围硬件设备、嵌入式操作系统以及用户应用软件等部分组成。它具有嵌入性、专用性和计算机系统3个基本要素。
- 嵌入式系统与通用计算机系统有着完全不同的技术要求和技术发展方向。
- 通用计算机系统的技术要求是高速、海量的数值计算,其技术发展方向是总线速度的无限提升、存储容量的无限扩大;
- 而嵌入式计算机系统的技术要求则是智能化控制,技术发展方向是与对象系统密切相关的潜入性能、控制能力与控制的可靠性不断提高。
- “通”:实实在在的计算机。按其体系结构、运算速度和规模可分为大型机、中型机、小型机和微机
- “嵌”:“看不见”的计算机,形式多样,应用领域广泛,按应用进行分类
- “通”:通用处理器、标准总线和外设、软硬件相对独立
- “嵌”:面向特定应用的微处理器,总线和外设一般集成在处理器内部,软硬件紧密结合
- “通”:系统资源充足,有丰富的编译器、集成开发环境、调试器等
- “嵌”:系统资源紧缺,没有编译器等相关开发工具
- “通”:开发平台和运行平台都是通用计算机
- “嵌”:采用交叉编译方式,开发平台一般是通用计算机,运行平台是嵌入式系统
- “通”:应用程序可重新编程
- “嵌”:一般不能重新编程开发
- “通”:编程功能电脑,普遍进入社会
- “嵌”:变为专用电脑,实现“普及计算”
- 实时性是ERTOS最基本的特点,在事件发生时,软件必须能够在严格的时限内作出响应。
- 硬实时
- 系统对外部事件响应超时可能造成灾难性后果,响应时间必须严格小于截止时间。
- 软实时
- 系统对外部事件响应超时可能会导致系统产生一些错误,但不会造成灾难性后果,且大多数情况下不会影响系统正常工作
- 在系统运行过程中,系统调用的时间可以预测
- RTOS需要同时激活多个任务处理对应的外部请求
- 高可靠性
- 可靠性指在一组特定条件下,系统在一定时期内不发生故障的概率
- 高稳健性
- 稳健性特别前调容错处理和出错自动恢复,确保软件系统不会因为软件错误而崩溃甚至出现灾难性后果
- 高防危性
- 防危性研究系统是否会导致灾难发生,关心的是引起危险的软件故障
- 为嵌入式设备提供安全保障措施,关注外部对系统的恶意攻击,减少应用工作者的重复工作
- RTOS必须具有足够小的体积及很好的可剪裁性和灵活性
- 组成RTOS的各模块能根据不同的要求合理剪裁,做到够用即可
- 除提供基本的内核支持外,还需提供越来越多的e可扩展功能模块
- 除基本内核外,RTOS的其他服务可以根据应用需求随意剪裁
- RTOS可以更加方便的扩展功能
- 可以更加容易做到上层应用与下层应用的分离,便于系统移植
- 可以大大加强RTOS服务模块的可重用性
- 多任务机制是现代操作系统的基础。
- 多任务并发执行造成了一种多任务同时执行的假象
- 中断时外部事件通知RTOS的主要机制
- 实时系统必须能够快速响应外部中断,以成功的与外部环境进行交互
- 实时时钟单纯地提供一个一个规则的脉冲序列,脉冲之间的间隔可以作为系统的时间基准。
- 不需确保CPU能与时钟同步工作
- 对于外界提出多种请求,RTOS需要创建多个任务进行处理,任务之间往往有一定的执行顺序或资源的使用约束,这就要求任务在执行过程中能够互相通信,相互合作,协同完成外部请求。
- 任务在运行过程中需求是不断变化的,RTOS需要在竞争的任务之间分配资源
- 向标准化看齐,提供标准API,适应人们对自由软件的渴望
- 卡法面向特定领域的RTOS以抢占市场
- 提供丰富的网络支撑
- 任务是ERTOS软件设计师抽象出的相互作用的的程序集合或者软件实体,每个程序执行时也称为任务
- 任务的运行状态不断变换包括:
- 就绪态
- 运行态
- 等待态
- 睡眠态
- 阻塞态
- 任务在宏观上是同时运行的
- 任务在微观上是串行的
- 若任务存在依赖关系,则任务具有同步性
- 若任务之间相互独立,则任务各自按照相互独立,不可预知的速度运行
- 每个进程具有独立的地址空间
- 虽然各个进程都访问同一地址,但是由于虚拟地址机制的存在,他们对应的物理地址是不同的
- CPU的执行权限从一个任务转移到另一个任务
- 从底层来看就是改变了PC的值
- 任务主动触发任务切换
- 任务无法获得足够的资源被操作系统进行任务切换
- 外部中断触发任务中断
- 保存当前任务环境
- 寻找当前优先级最高任务/中断服务程序
- 回复要执行任务的环境
OSCtxSw:
STMFD SP!, {LR} ;PC
STMFD SP!, {R0-R12, LR} ;R0-R12 LR
MRS R0, CPSR ;Push CPSR
STMFD SP!, {R0}
;----------------------------------------------------------------------------------
; OSTCBCur->OSTCBStkPtr = SPa
;---------------------------------------------------------------------------------- LDR R0, =OSTCBCur
LDR R0, [R0]
STR SP, [R0]
BL OSTaskSwHook
;---------------------------------------------------------------------------------
; OSTCBCur = OSTCBHighRdy;
;----------------------------------------------------------------------------------
LDR R0, =OSTCBHighRdy
LDR R1, =OSTCBCur
LDR R0, [R0]
STR R0, [R1]
//LDR将R0所指向寄存器中的值存放到R0中
//STR将R0放入R1所指向的寄存器中
;---------------------------------------------------------------------------------
; OSPrioCur = OSPrioHighRdy;
;---------------------------------------------------------------------------------
LDR R0, =OSPrioHighRdy
LDR R1, =OSPrioCur
LDRB R0, [R0]
STRB R0, [R1]
;----------------------------------------------------------------------------------
; OSTCBHighRdy->OSTCBStkPtr;
;----------------------------------------------------------------------------------
LDR R0, =OSTCBHighRdy
LDR R0, [R0]
LDR SP, [R0]
;----------------------------------------------------------------------------------
;Restore New task context
;----------------------------------------------------------------------------------
LDMFD SP!, {R0} ;POP CPSR
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^
OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt)
//task:任务执行函数入口
//p_arg:任务参数地址
//ptos:栈顶指针
//opt:预留参数
{
OS_STK *stk;
opt = opt;
stk = ptos;
*(stk) = (OS_STK)task; /* Entry Point*/
*(--stk) = (INT32U)0; /*LR */
*(--stk) = (INT32U)0; /*R12*/
*(--stk) = (INT32U)0; /*R11*/
*(--stk) = (INT32U)0; /*R10*/
*(--stk) = (INT32U)0; /*R9*/
*(--stk) = (INT32U)0; /*R8*/
*(--stk) = (INT32U)0; /*R7*/
*(--stk) = (INT32U)0; /*R6*/
*(--stk) = (INT32U)0; /*R5*/
*(--stk) = (INT32U)0; /*R4*/
*(--stk) = (INT32U)0; /*R3*/
*(--stk) = (INT32U)0; /*R2*/
*(--stk) = (INT32U)0; /*R1*/
*(--stk) = (INT32U)p_arg; //压入参数环境
*(--stk) = (INT32U)0x 0x00000013L; //压入处理器状态寄存器CPSR
return (stk);
}
INT8U OSTaskCreate (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos,INT8U prio)
//task:指针函数,指向任务所开始的函数,当任务被第一次调度运行时,将会从函数处开始运行
//p_arg:传给task的参数指针
//ptos:堆栈指针
//prio:进程优先级
{
OS_STK * psp;
//为寄存器分配空间
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr = 0;
#endif
OS_ENTER_CRITICAL();//进入中断
if (OSIntNesting > 0) //判断中断嵌套层数
{
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_CREATE_ISR);
}
if (OSTCBPrioTbl[prio] == (OS_TCB *)0)
//判断有没有任务占用该优先级
{
OSTCBPrioTbl[prio] = (OS_TCB *)1;
OS_EXIT_CRITICAL();
psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0); //初始化任务栈
err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);//初始化TCB
if (err == OS_NO_ERR)
{
OS_ENTER_CRITICAL();
OSTaskCtr++;
OS_EXIT_CRITICAL();
if (OSRunning == TRUE)
{
OS_Sched();//调度任务
}
else
{
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = (OS_TCB *)0;
OS_EXIT_CRITICAL();
}
return (err);
}
OS_EXIT_CRITICAL();
return (OS_PRIO_EXIST);
}
INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
//prio进程优先级
//ptos栈顶指针
//pbos栈底指针
//id任务标识符
//stk_size栈容量
//opt选择项
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
OS_TCB *ptcb;//申请一个指向TCB的指针
OS_ENTER_CRITICAL();
ptcb = OSTCBFreeList;//从空闲列获取一个TCB
if (ptcb != (OS_TCB *)0) {
OSTCBFreeList = ptcb->OSTCBNext;//修改空想列列首,使其指向下一项
OS_EXIT_CRITICAL();
ptcb->OSTCBStkPtr= ptos;
ptcb->OSTCBPrio = (INT8U)prio;
ptcb->OSTCBStat = OS_STAT_RDY;
ptcb->OSTCBDly = 0;
pext = pext;
stk_size = stk_size;
pbos = pbos;
opt = opt;
id = id;
ptcb->OSTCBY = prio >> 3;
ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY];
ptcb->OSTCBX = prio & 0x07;
ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX];
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = ptcb;
ptcb->OSTCBNext = OSTCBList;
ptcb->OSTCBPrev = (OS_TCB *)0;
if (OSTCBList != (OS_TCB *)0)
{
OSTCBList->OSTCBPrev = ptcb;
}
OSTCBList = ptcb;
OSRdyGrp |= ptcb->OSTCBBitY;
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
OS_EXIT_CRITICAL();
return (OS_NO_MORE_TCB);
}
void OS_Sched (void)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr = 0;
#endif
OS_ENTER_CRITICAL();
if (OSIntNesting == 0)
{
if (OSLockNesting == 0)
{
OS_SchedNew();
if (OSPrioHighRdy != OSPrioCur)
{
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
#if OS_TASK_PROFILE_EN > 0
OSTCBHighRdy->OSTCBCtxSwCtr++;
#endif
OSCtxSwCtr++;
OS_TASK_SW();
}
}
}
OS_EXIT_CRITICAL();
}
static void OS_SchedNew (void)
{
#if OS_LOWEST_PRIO <= 63
INT8U y;
y= OSUnMapTbl[OSRdyGrp];
OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
#else
INT8U y;
INT16U *ptbl;
if ((OSRdyGrp & 0xFF) != 0)
{
y = OSUnMapTbl[OSRdyGrp & 0xFF];
}
else
{
y = OSUnMapTbl[(OSRdyGrp >> 8) & 0xFF] + 8;
}
ptbl = &OSRdyTbl[y];
if ((*ptbl & 0xFF) != 0)
{
OSPrioHighRdy = (INT8U)((y << 4) + OSUnMapTbl[(*ptbl & 0xFF)]);
} else
{
OSPrioHighRdy = (INT8U)((y << 4) + OSUnMapTbl[(*ptbl >> 8) & 0xFF] + 8);
}
#endif
}
- 一些任务的截止时间无法确保
- 可使用优先级继承解决
- 优先级天花板
- RM:静态,针对周期性
- EDF:动态 针对非周期性
- 可调度性上限为100%,CPU充分利用
- 在实时系统中可操作性不高,调度实现的开销过大
关中断也可以实现共享资源互斥访问
- 任务之间以及任务和中断服务程序之间不是孤立的,它们需要互相作用互相影响
- 同步机制确保任务A知道任务B已经产生了它所需要的数据
- 互斥机制确保了任务A在对某共享数据进行操作时,数据不被其他任务篡改
- 可以使用信号量使某任务与中断服务程序进行同步
- 两个任务可以用两个信号量进行同
- 当多个任务共享系统资源时,多个任务必须互斥地对他们进行访问
- 使用信号量作为任务与ISR之间的同步与互斥机制
- OSSemCreate 创建一个信号量
- OSSemPend 获取一个信号量
- OSSemPost 释放一个信号量
- OSSemAccept 无等待的获取一个信号量
- OSSemQuery 查询信号量当前的信号量
- 任务可以使用互斥信号量实现对共享资源的独占式处理
- 任务之间、任务与中断服务程序之间仅有同步是不够的,他们之间还需要通信。
- 所谓通信,就是指任务之间、任务和中断服务程序之间的交互
- ucos通过事件控制块及其操作进行实现
Producer
do
{
…
Produce a new item
…
Apply empty
Apply mutex
…
Add the new item to the queue
…
Free mutex
Free full
} while (1);
Consumer
do
{
Apply full
Apply mutex
…
Move a item from the queue
…
Free mutex
Free empty
…
Consume the newly-moved item
…
} while (1);
- 中断: 是由于CPU外部原因而改变程序运行流程的过程,中断的触发及响应属于异步事件
- 自陷:表示通过处理器软件指令,可预期的使CPU正在执行的程序流发生变化,以执行特定的程序。
- 异常:CPU自动的产生自陷,以处理特定异常事件。
void OSTimeTick (void)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
OS_TCB *ptcb;
if (OSRunning == TRUE)
{
ptcb = OSTCBList;
while (ptcb->OSTCBPrio != OS_IDLE_PRIO)
{
OS_ENTER_CRITICAL();
if (ptcb->OSTCBDly != 0)
{
if (--ptcb->OSTCBDly == 0)
{
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY)
{
OSRdyGrp |= ptcb->OSTCBBitY;
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
}
else
{
ptcb->OSTCBDly = 1;
}
}
}
ptcb = ptcb->OSTCBNext;
OS_EXIT_CRITICAL();
}
}
}