【FreeRTOS初探】资源管理

文章目录


#资源管理
##概览

  1. 多任务系统潜在风险——当一个任务在使用某个资源的过程中,还没有完全结束对资源的方位,便被迫切出运行态,使得资源处于非一致、不完整状态。当此时有另一个任务或中断来访问此资源,会导致数据损坏或其他错误。
  2. 可重入——每个函数可以安全地被多个任务调用,或者在任务与中断中均可调用,则,这个函数是可重入的。若一个函数除了访问自己栈空间上分配的数据空间和内核寄存器外,不会访问其他任何数据,则这个函数是可重入的

例:

可重入函数示例

/*A parameter is passed into the function. This will either be passed on the stack or in a CPU register. Either way is safe as each task maintains its own stack and its own set of register values.*/
long lAddOneHunderad ( long lVal1)
{
	/*This function scope variable will also be allocated to the stack or a register, depending on compiler and optimization level. Each task or interrupt that calls this function will have its own copy of lVar2.*/
	long lVal2;
	lVar2 = lVar1 + 100;

	/*Most likely the return value will be placed in a CPU register,although it too could be placed on the stack.*/
	return lVar2;
}

不可重入函数示例

/*In this case lVar1 is a global variable so every task that calls the function will be accessing the same single copy of the variable.*/
long lVal1;
long lNonsenseFunction ( void )
{
	/*This variable is static so is not allocated on the stack.Each task that calls the function will be accessing the single copy of the variable.*/
	static long lState = 0;
	long lReturn;

	switch( lState )
	{
		case 0: 
			lReturn = lVar1 + 10;
			lState = 1;
			break;
		case 1:
			lReturn = lVar1 +20;
			1State = 0;
			break;
	}
}

###互斥
访问一个被多任务共享,或是被任务与中断共享的资源时,需要采用“互斥”技术,以保证数据在任何时候都保持一致性
目的:确保任务从开始访问资源就具有排他性,直到这个资源有回复到完整状态。
###内容

  • 为什么以及在什么时候有必要进行资源管理与控制?
  • 什么是临界区?
  • 互斥是什么意思?
  • 挂起调度器有什么意义?
  • 如何使用互斥量?
  • 如何创建与使用守护任务?
  • 什么是优先级反转,以及优先级继承是如何减小(但不是消除)其影响的。

##临界区与挂起调度器

###基本临界区
定义:指宏taskENTER_CRITICAL()taskEXIT_CRITICAL()之间的代码区间

临界区——提供互斥功能的原始实现方式。
临界区的工作仅仅是简单地把中断全部关掉,或是关掉优先级在configMAX_SYSCAL_INTERRUPT_PRIORITY及以下的中断(依赖于具体使用的FreeRTOS移植)。
抢占式上下文切换只可能在某个中断中完成,所以调用taskENTER_CRITICAL()的任务可以在关中断的时段内一直保持运行态,直到退出临界区。

临界区时间过长会影响中断响应时间——在调用taskENTER_CRITICAL()后应尽快地调用taskEXIT_CRITICAL()。

支持临界区嵌套——内核有维护一个嵌套深度计数。临界区只会在嵌套深度为0时才会真正退出。
范例:使用连接区对寄存器的访问进行保护。

/*为保证对PORTA寄存器的范围不被中断,将访问操作放到临界区。*/
taskENTER_CRITICAL();

/*在taskENTER_CRITICAL()与taskEXIT_CRITICAL()之间不会切换到其他任务。
 *中断可以执行,也允许嵌套,只是针对优先级高于configMAX_SYSCALL_INTERRUPT_PRIOPITY的中断。
 *而且这些中断不允许方位FreeRTOS API函数。*/
PORTA |= 0x01;

taskEXIT_CRITICAL();

###挂起(锁定)调度器
功能:由挂起调度器实现的临时区只可以保护一段代码区间不被别的任务打断,对中断无效(因为中断是使能的)。
使用环境临时区太长而不适合简单的关中断实现,就可以考虑挂起调度器方式。
劣势:唤醒调度器是个相对较长的操作。
####vTaskSuspendAll()
函数作用:挂起调度器(实现停止上下文切换而不用关中断)。
函数原型:

void vTaskSupendAll( void );

注意事项:在调度器处于挂起状态时,不能调用FreeRTOS API函数。

###xTaskResumeAll()
函数作用:唤醒调度器
函数原型:

portBASE_TYPE xTaskResumeAll( void );

函数返回:
pdTRUE——一个挂起的上下文切换请求能在xTadkResumeAll()返回前得到执行。
pdFALSE——其他情况。
##互斥量(及二值信号值)
作用:互斥量是特殊的二值信号,用于控制两个或多个任务之前访问共享资源
MUTEX(互斥量):MUTual EXclusion
用法:
互斥量——与共享资源关联的令牌。
一个任务想要合法地访问资源,必须先取得(Take)令牌,成为持有者。
当令牌持有者完成资源使用后,必须立即归还(Give)令牌。
一个任务只能持有令牌才能访问共享资源。
互斥功能缺陷:
1 .优先级反转
2. 优先级继承
3. 死锁
###互斥量与二值信号的区别
在信号被获取后,
用于互斥的信号量必须归还。
用于同步的信号量在完成同步后便丢弃,无需归还。

###xSemaphoreCreateMutex API
作用:创建互斥量类型的信号量
函数原型:

xSemaphoreHandle xSemaphoreCreateMutex( void );

函数返回:
NULL——返回失败(内存堆空间不足导致FreeRTOS无法为互斥量分配结构数据空间)
非NULL——互斥量创建成功,返回位改互斥量的句柄。
##守护任务
守护任务是对某个资源具有唯一所有权的任务。
只有守护任务才可以直接访问其守护的资源——其他任务要访问只能间接地通过守护任务提供的服务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值