Skip to content

Latest commit

 

History

History
562 lines (450 loc) · 16.9 KB

嵌入式系统课后习题.md

File metadata and controls

562 lines (450 loc) · 16.9 KB

嵌入式系统课后习题

第一章 嵌入式操作系统概述

1 什么是嵌入式系统?

  • 嵌入式计算机通常被称为嵌入式系统
  • 嵌入式系统是以应用为中心,以计算机技术为基础,软硬件可配置,对功能可靠性成本体积功耗有着严格要求的专用计算机系统

2 嵌入式系统与通用计算机系统有哪些区别?

  • 嵌入式系统是以应用为中心,以计算机技术为基础,软硬件可配置,对功能可靠性成本体积功耗有着严格要求的专用计算机系统
  • 嵌入式系统主要由嵌入式微处理器外围硬件设备嵌入式操作系统以及用户应用软件等部分组成。它具有嵌入性专用性计算机系统3个基本要素。
  • 嵌入式系统与通用计算机系统有着完全不同的技术要求技术发展方向
  • 通用计算机系统的技术要求是高速海量的数值计算,其技术发展方向是总线速度的无限提升、存储容量的无限扩大;
  • 嵌入式计算机系统的技术要求则是智能化控制,技术发展方向是与对象系统密切相关的潜入性能控制能力控制的可靠性不断提高。

形式与类型

  • “通”:实实在在的计算机。按其体系结构、运算速度和规模可分为大型机、中型机、小型机和微机
  • “嵌”:“看不见”的计算机,形式多样,应用领域广泛,按应用进行分类

组成

  • “通”:通用处理器、标准总线和外设、软硬件相对独立
  • “嵌”:面向特定应用的微处理器,总线和外设一般集成在处理器内部,软硬件紧密结合

系统资源

  • “通”:系统资源充足,有丰富的编译器、集成开发环境、调试器等
  • “嵌”:系统资源紧缺,没有编译器等相关开发工具

开发方式

  • “通”:开发平台和运行平台都是通用计算机
  • “嵌”:采用交叉编译方式,开发平台一般是通用计算机,运行平台是嵌入式系统

二次开发性

  • “通”:应用程序可重新编程
  • “嵌”:一般不能重新编程开发

发展目标

  • “通”:编程功能电脑,普遍进入社会
  • “嵌”:变为专用电脑,实现“普及计算”

3 简述RTOS的主要特点

实时性

  • 实时性是ERTOS最基本的特点,在事件发生时,软件必须能够在严格的时限内作出响应。
  • 硬实时
  • 系统对外部事件响应超时可能造成灾难性后果,响应时间必须严格小于截止时间。
  • 软实时
  • 系统对外部事件响应超时可能会导致系统产生一些错误,但不会造成灾难性后果,且大多数情况下不会影响系统正常工作

可确定性

  • 在系统运行过程中,系统调用的时间可以预测

并发性

  • RTOS需要同时激活多个任务处理对应的外部请求

高可信性

  • 高可靠性
  • 可靠性指在一组特定条件下,系统在一定时期内不发生故障的概率
  • 高稳健性
  • 稳健性特别前调容错处理出错自动恢复,确保软件系统不会因为软件错误而崩溃甚至出现灾难性后果
  • 高防危性
  • 防危性研究系统是否会导致灾难发生,关心的是引起危险的软件故障

安全性

  • 为嵌入式设备提供安全保障措施,关注外部对系统的恶意攻击,减少应用工作者的重复工作

可嵌入性

  • RTOS必须具有足够小的体积及很好的可剪裁性灵活性

可剪裁性

  • 组成RTOS的各模块能根据不同的要求合理剪裁,做到够用即可

可扩展性

  • 除提供基本的内核支持外,还需提供越来越多的e可扩展功能模块

3 简述微内核结构RTOS的特点

  • 除基本内核外,RTOS的其他服务可以根据应用需求随意剪裁
  • RTOS可以更加方便的扩展功能
  • 可以更加容易做到上层应用与下层应用的分离,便于系统移植
  • 可以大大加强RTOS服务模块的可重用性

4 一般的RTOS实现哪些功能

任务管理

  • 多任务机制是现代操作系统的基础。
  • 多任务并发执行造成了一种多任务同时执行的假象

中断管理

  • 中断时外部事件通知RTOS的主要机制
  • 实时系统必须能够快速响应外部中断,以成功的与外部环境进行交互

时钟管理

  • 实时时钟单纯地提供一个一个规则的脉冲序列,脉冲之间的间隔可以作为系统的时间基准。
  • 不需确保CPU能与时钟同步工作

任务协调

  • 对于外界提出多种请求,RTOS需要创建多个任务进行处理,任务之间往往有一定的执行顺序或资源的使用约束,这就要求任务在执行过程中能够互相通信,相互合作,协同完成外部请求。

内存管理

  • 任务在运行过程中需求是不断变化的,RTOS需要在竞争的任务之间分配资源

5 简述RTOS的发展趋势

开放性

  • 向标准化看齐,提供标准API,适应人们对自由软件的渴望

面向特定领域

  • 卡法面向特定领域的RTOS以抢占市场

面向网络

  • 提供丰富的网络支撑

可信性支持

多核支持

第二章 任务调度机制

1 什么是任务?

  • 任务是ERTOS软件设计师抽象出的相互作用的的程序集合或者软件实体,每个程序执行时也称为任务

动态性

  • 任务的运行状态不断变换包括:
  • 就绪态
  • 运行态
  • 等待态
  • 睡眠态
  • 阻塞态

并发性

  • 任务在宏观上是同时运行
  • 任务在微观上是串行

异步独立性

  • 若任务存在依赖关系,则任务具有同步性
  • 若任务之间相互独立,则任务各自按照相互独立,不可预知的速度运行

2 任务和线程的区别

  • 每个进程具有独立的地址空间
  • 虽然各个进程都访问同一地址,但是由于虚拟地址机制的存在,他们对应的物理地址是不同的

3 什么是任务切换?

  • 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}^	 

3 详细讲述堆栈初始化过程

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);
}

4 详细讲述RTOS如何创建一个任务

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);
}

5 详细叙述优先级位图法

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
}

第三章 任务调度策略

1 优先级反转会造成哪些后果?

  • 一些任务的截止时间无法确保
  • 可使用优先级继承解决

2 如何避免死锁

  • 优先级天花板

3 了解RM调度和EDF调度

  • RM:静态,针对周期性
  • EDF:动态 针对非周期性

4 对比RM和EDF的优缺点

相比于RM,EDF优点在于:

  • 可调度性上限为100%,CPU充分利用

相比于RM,EDF优点在于

  • 在实时系统中可操作性不高,调度实现的开销过大

5 RTOS采取哪些策略与机制来确保任务实时性

第四章 同步互斥

关中断也可以实现共享资源互斥访问

1 什么是任务同步、任务互斥?为什么需要对任务进行同步和互斥?

  • 任务之间以及任务和中断服务程序之间不是孤立的,它们需要互相作用互相影响
  • 同步机制确保任务A知道任务B已经产生了它所需要的数据
  • 互斥机制确保了任务A在对某共享数据进行操作时,数据不被其他任务篡改

任务之间的单项同步

  • 可以使用信号量使某任务与中断服务程序进行同步

任务之间的双向同步

  • 两个任务可以用两个信号量进行同

任务之间的互斥

  • 当多个任务共享系统资源时,多个任务必须互斥地对他们进行访问

2 UCOS采用什么方法进行系统之间的同步和互斥?

  • 使用信号量作为任务与ISR之间的同步与互斥机制

对信号量进行操作的函数

  • OSSemCreate 创建一个信号量
  • OSSemPend 获取一个信号量
  • OSSemPost 释放一个信号量
  • OSSemAccept 无等待的获取一个信号量
  • OSSemQuery 查询信号量当前的信号量

互斥信号量

  • 任务可以使用互斥信号量实现对共享资源的独占式处理

2 任务之间为什么需要通信?ucos采用什么方法实现任务之间的通信?

  • 任务之间、任务与中断服务程序之间仅有同步是不够的,他们之间还需要通信。
  • 所谓通信,就是指任务之间、任务和中断服务程序之间的交互
  • ucos通过事件控制块及其操作进行实现

3 请阐述消费者/生产者问题


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); 

第五章 中断和时间管理

1 区分中断、自陷、异常

  • 中断: 是由于CPU外部原因而改变程序运行流程的过程,中断的触发及响应属于异步事件
  • 自陷:表示通过处理器软件指令,可预期的使CPU正在执行的程序流发生变化,以执行特定的程序。
  • 异常:CPU自动的产生自陷,以处理特定异常事件。

2 简述TimeTick

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();
		}
	}
}