《基于嵌入式实时操作系统的程序设计技术(第2版) 》学习笔记

第6章 行为同步

用于同步的通信手段
计数信号量、事件标志组、消息邮箱、消息队列
行为同步:

  1. ISR和任务之间的同步
    例子:外部中断按键后执行OSSemPost(Sem),
    蜂鸣器任务OSSemPend(Sem,0,&err),蜂鸣器响一次。
  2. 两个任务之间的单向通信
    例子:KeyTask按键后执行OSSemPost(Sem1)和OSSemPost(Sem)。
    LedTask OSSemPend(Sem1,0,&err),BeepTask OSSemPend(Sem2,0,&err)。按键一次,灯亮一次,蜂鸣器响一次。
    采用消息分发功能的消息邮箱作为通信工具,减少通信工具的个数。
    KeyTask发出OSMboxPostOpt(Mybox, (void *)1, OS_POST_OPT_BROADCAST)。
    LedTask OSMboxPend(Mybox,0,&err); BeepTask OSMboxPend(Mybox,0,&err)。
  3. 两个任务之间的双向同步
    单向同步,必须保证消息的平均生产时间比消息的平均消费时间长,否则再长的消息队列也会溢出。双向同步,消息的生产受消费者反向控制,达到产销平衡。双向同步的主要功能为确认每次通信均成功,没有遗漏。
    KeyTask 按键后执行OSMboxPost(SeMbox, (void *)1); OSMboxPend(Ackbox,0,&err);
    DispTask OSMboxPend(SeMbox,0,&err) 接收到SeMbox后,执行显示代码,再OSMboxPost(Ackbox, (void *)1)。
  4. 两个以上任务同步一个任务
    DispTask OSFlagPend(FlagW, 0x03, OS_FLAG_WAIT_SET_ALL + OS_FLAG_CONSUME, 0, &err);
    接收到后执行 串口数据发送出去,再等待。即有信号就发。
    KeyTask 按键后执行 OSFlagPost(FLAGW, 0x02, OS_FLAG_SET, &err);
    BeepTask 响半秒停半秒后执行 OSFlagPost(FLAGW, 0x01, OS_FLAG_SET, &err);
  5. 多个任务相互同步
    每个任务运行到同步点后都必须等待其他任务,都到达后依次离开同步点
    需使用 事件标志组、签到计数器、关中断
    KeyTask 有按键后执行synch();
    BeepTask 响半秒停半秒后执行synch();
    DispTask执行synch(); 有信号就发送,发送完之后执行synch();
    //公共函数,使用了全局变量,成为不可重入函数,公共函数并不要求一定是可重入函数,能够做到互斥访问也是可以的。采用关中断的方式对全局变量count进行互斥访问,也同样使能该函数满足公共函数的要求
void synch(void) 		
{
	INT8U err;
	OS_ENTER_CRITICAL();				//关中断 
	if(count == total - 1){
		Count = 0;					//清签到器
		OS_EXIT_CRITICAL();			//开中断
		OSMboxPostOpt(Mybox, (void *)1, OS_POST_OPT_BROADCAST);					//消息分发
	}else {
		Count ++;						//签到
		OS_EXIT_CRITICAL();
	OSMboxPend(Mybox,0,&err)		//等待
	}
}

第7章 资源同步

被两个以上并发程序单元(任务或ISR)访问的资料称为共享资源,共享资源一定是全局资源。全局资源不一定是共享资源。举一个反例,点阵数据是全局数组,但只为一个任务使用,这就不是共享资源。
任务对共享资源进行访问的代码段落称为关键段落,必须互斥才能保证共享资源信息的可靠性和完整性。
关中断、关调度、使用互斥信号量、使用计数信号量

  1. 关中断 参与访问共享资源的并发程序单元包括ISR,只能用关中断
    关中断缺点:影响系统的实时性,所以关键段落尽量剪短
    用途:用于对简单资源的短暂访问,常用于全局变量、小规模全局数据结构的访问
    例子1 5. 多个任务相互同步中介绍的例子。
    优先级低的任务判断if(count == total-1) 后,发生ISR切换到高优先级的任务,判断if(count == total-1),发现任务没全签到,则自己签到后挂起,低优先级任务接着运行count++(此时count=total+1),再挂起,系统瘫痪。
    例子2 读取并显示日历时钟数据
    RtcIntIsr 中每秒刷新年月日时分秒数据
    KeyTask 按键后执行OSMboxPost(Mybox, (void *)1); 触发一次显示任务
    DispTask OSMboxPend(Mybox,0,&err),如果显示到“时”的时候,RtcIntIsr发生,刷新了数据,等再回到显示任务时,数据出错了。
    关中断时间太长,系统的实时性将严重恶化,实际上是行不通的。解决方法是:关中断时对共享资源进行“拍照”,之后再开中断。在RtcIntIsr也加关中断、开中断是防区高优先级中断打断RtcIntIsr中断导致数据破坏,在DispTask中关中断把共享资源复制到临时变量中,再开中断,后面慢慢处理。
  2. 关调度
    优点:没有关中断,系统对异步中断可以响应,使相关任务进入就绪状态,但不会马上进入运行状态。
    缺点:使与共享资源无关的任务受到牵连。

第8章 数据通信

嵌入式系统的运行过程中,ISR和任务之间,任务和任务之间必然伴随数据通信,根据实际情况选择最合适的方法。

  1. 全局变量
    可以充当一种共享资源,用于任务之间传输数据。关中断
  2. 内存数据块
    采用消息队列的通信方式,常常将内存块作为消息内容缓冲区
  3. 消息邮箱
    消息邮箱发送是保存数据的地址,可以是全局的,也可以是局部的,只要任务没有删除,保存在局部变量中的消息是安全的。
    每按键一次进行一次采样,并将采样结果通过消息邮箱发送给显示任务,显示任务从消息邮箱得到消息后将采样结果显示出来
    KeyTask按键按下时发送 OSMboxPost(Mbox,(void *)&Temp);
    DispTask Samp = *(INT32U *)OSMboxPend(Mbox, 0, &err); 再对Samp处理显示等。
    ISR中不能用消息邮箱发送局部变量,其他任务会接收不正确,ISR发送完之后就退出了ISR,局部变量也随之失效。
    ISR中发送全局变量,绝对可靠,但变量定义与ISR代码分离,程序可读性下降。
    ISR可靠发送消息的方法有三种:
    1)将消息保存在全局变量中
INT32U  Val;
void eint3Isr(void)
{
	OSIntEnter();OSMboxPost(Mbox,(void *)&Val); 
	OSIntExit();}

2)将消息保存在ISR的静态局部变量中

void eint3Isr(void)
{
	static INT32U  Val;
	OSIntEnter();OSMboxPost(Mbox,(void *)&Val); 
	OSIntExit();}

3)将消息内容冒充指针进行发送
接收消息的一方直接从消息指针中提取消息内容,但消息不能大于4字节且不能为0。如果只用低字节,可以把高字节置0xff(多少位置1根据实际需要 ),接收方忽略高字节即可。
发送OSMboxPost(Mbox,(void *)(Val | 0xff000000);
接收 Samp = ( (INT32U )OSMboxPend(Mbox, 0, &err) )& 0x00ffffff;
4. 消息队列
消息队列是具有同步功能和缓冲功能的数据通信手段,适用于
通信双方至少有一方没有稳定的执行周期:消息产生随机或消息处理速度与消息内容有关
通信双方的执行周期不同:产生周期短,消息处理长,但一次可以连续处理几条
每按一次键,2s时间采样100个数据,显示任务要4s显示完成。在4s内按一次则能刚好显示,短时间内超速按键,由于消息有缓冲,只要平均按键时间小于4s,消息不会遗漏都显示。

第9章 时间管理

1. 控制任务的执行周期
延时函数OSTimeDly()和OSTimeDlyHMSM(),控制周期任务的执行周期。

void MyTask(void *pdata)
{
	进行准备工作的代码;
	while(1)
	{
	任务实体代码;
	调用系统延时函数
	}
}
  1. 控制任务的运行节奏
    任务函数中插入延时函数来控制任务的运行节奏,以便把CPU空闲出来供其他任务使用。
void MyTask(void *pdata)
{
	进行准备工作的代码;
	while(1)
	{
		等待信号量等;
		任务实体代码1;
		调用系统延时函数;
		任务实体代码2;
		调用系统延时函数
	}
}
  1. 状态查询
    任务不能通过行为同步功能来获取状态信息,必须主动查询,查询的过程中定时插入延时函数,不断地交出CPU供其他任务使用。延时时间根据查询的精度要求来决定。
  2. 终止周期性任务
    OSSemPend(Sem, 20, *err); 等待时限为20个时钟节拍。

第10章 采样任务设计

  1. 使用延时函数控制采样周期
    采样对象是低频信号,采样频率可以设得比较低,即采样周期比系统节拍周期长得多。
  2. 使用定时中断控制采样周期
    采样周期与系统节拍周期在同一个数量级时,如仍然用延时函数控制采样周期,其采样周期的时间抖动将比较明显,严重影响采样结果的质量。用定时器中断来产生稳定的采样周期。
  3. 使用节拍钩子函数进行采样
    节拍钩子函数是系统节拍函数的一部分,具有ISR的性质,应尽可能简洁,不允许调用使自己挂起的系统服务函数。
    使用节拍钩子函数与使用单独的定时器中断的最大区别在于控制方式不同。定时器中断可以“使能/禁止”中断源,系统节拍不能“禁止”其钩子函数也不能单独“禁止”。
  4. 被动采样
    由外部信号启动的采样过程的方式称为被动采样。在被动采样中,采样时刻是随机的,没有采样周期的概念。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值