uCOS和FreeRTOS在临界区上处理的不同方式,不过本质上是一样的

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uCOS和FreeRTOS在临界区上处理的不同方式,不过本质上是一样的相关的知识,希望对你有一定的参考价值。

参考技术A 首先要弄清什么是垄断?
垄断, 是指一个或几个大型企业占有一个经济部门的绝大部分的生产或流通份额,并控制相关商品的价格,从而获得高额垄断利润的情况。垄断发展到现阶段已经由私人垄断资本发展到国家垄断资本。
国家垄断资本主义是资产阶级国家力量同垄断组织力量结合在一起的垄断资本主义,它可以通过国家调节经济生活,加强对劳动人民的剥削和掠夺,更好地保证垄断资产阶级获得高额垄断利润,更有利于维护资本主义制度。无论采取国有经济的形式和国有资本与私人垄断资本结合的形式,还是国家在私人垄断企业外部对国民经济进行调节,总之,所有的国家垄断资本主义的具体形式,其实质都是私人垄断资本利用国家机器来为其发展服务的手段,是私人垄断资本为了维护垄断统治和获取高额垄断利润而和国家政权相结合的一种垄断资本主义形式,是资产阶级国家在直接参与社会资本的再生产过程中,代表资产阶级总利益并凌驾于个别垄断资本之上,对社会经济进行调节的一种形式。
国家垄断资本主义的具体形式多种多样,分类方法也不一致。有的把国家垄断资本主义区分为国家所有制经济和国家调节两种基本形式;有的把它区分为国家所有制经济、国家消费(采购)和国家调节三种基本形式;有的把它划分为国家所有制经济、国家财政对国民收入再分配、国家政策与计划调节三种基本形式,如此等等。但是,国家所有制经济的建立和发展,既是国家财政支出的结果,同时也是国家调节的一种杠杆,不能把国家所有制经济同国家调节的其他形式完全对立起来。实际上,国家垄断资本主义的各种形式,都是国家调节社会经济的不同杠杆,而国家对社会经济的调节,都是在国家和垄断资本的各种结合形式中进行的。

FreeRTOS临界区

  FreeRTOS临界区是指那些必须完整运行,不能被打断的代码段,比如有的外设的初始化需要严格的时序,初始化过程中不能被打断。 FreeRTOS 在进入临界区代码的时候需要关闭中断,当处理完临界区代码以后再打开中断。 FreeRTOS 系统本身就有很多的临界区代码,这些代码都加了临界区代码保护,我们在写自己的用户程序的时候有些地方也需要添加临界区代码保护。
  FreeRTOS 与 临界区代 码 保 护 有 关 的 函 数 有 4 个 : taskENTER_CRITICAL() 、taskEXIT_CRITICAL() 、taskENTER_CRITICAL_FROM_ISR() 和taskEXIT_CRITICAL_FROM_ISR(),这四个函数其实是宏定义,在 task.h 文件中有定义。 这四个函数的区别是前两个是任务级的临界段代码保护,后两个是中断级的临界段代码保护。

一、任务级临界区代码保护

  taskENTER_CRITICAL()和 taskEXIT_CRITICAL()是任务级的临界代码保护,一个是进入临界段,一个是退出临界段, 这两个函数是成对使用的,这函数的定义如下:

/**
 * task. h
 *
 * Macro to mark the start of a critical code region.  Preemptive context
 * switches cannot occur when in a critical region.
 *
 * NOTE: This may alter the stack (depending on the portable implementation)
 * so must be used with care!
 *
 * \\defgroup taskENTER_CRITICAL taskENTER_CRITICAL
 * \\ingroup SchedulerControl
 */
#define taskENTER_CRITICAL()		portENTER_CRITICAL()
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()

/**
 * task. h
 *
 * Macro to mark the end of a critical code region.  Preemptive context
 * switches cannot occur when in a critical region.
 *
 * NOTE: This may alter the stack (depending on the portable implementation)
 * so must be used with care!
 *
 * \\defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL
 * \\ingroup SchedulerControl
 */
#define taskEXIT_CRITICAL()			portEXIT_CRITICAL()
#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x )

  而 portENTER_CRITICAL()和 portEXIT_CRITICAL()也是宏定义,在文件 portmacro.h 中有定义,如下:

#define portENTER_CRITICAL()					vPortEnterCritical()
#define portEXIT_CRITICAL()						vPortExitCritical()

  函数 vPortEnterCritical()和 vPortExitCritical()在文件 port.c 中,函数如下:

void vPortEnterCritical( void )

	portDISABLE_INTERRUPTS();
	uxCriticalNesting++;

	/* This is not the interrupt safe version of the enter critical function so
	assert() if it is being called from an interrupt context.  Only API
	functions that end in "FromISR" can be used in an interrupt.  Only assert if
	the critical nesting count is 1 to protect against recursive calls if the
	assert function also uses a critical section. */
	if( uxCriticalNesting == 1 )
	
		configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
	

/*-----------------------------------------------------------*/

void vPortExitCritical( void )

	configASSERT( uxCriticalNesting );
	uxCriticalNesting--;
	if( uxCriticalNesting == 0 )
	
		portENABLE_INTERRUPTS();
	

  可以看出在进入函数 vPortEnterCritical()以后会首先关闭中断,然后给变量 uxCriticalNesting加一, uxCriticalNesting 是个全局变量,用来记录临界段嵌套次数的。函数 vPortExitCritical()是退出临界段调用的,函数每次将 uxCriticalNesting 减一,只有当 uxCriticalNesting 为 0 的时候才会调用函数 portENABLE_INTERRUPTS()使能中断。这样保证了在有多个临界段代码的时候不会因为某一个临界段代码的退出而打乱其他临界段的保护,只有所有的临界段代码都退出以后才会使能中断!
  任务级临界代码保护使用方法如下:

void My_TaskTest(void *pvParameters) 
   
   while(true)
    
		/* 为了保证对PORTA寄存器的访问不被中断,将访问操作放入临界区。进入临界区 */
		taskENTER_CRITICAL();
		/* 在taskENTER_CRITICAL() 与 taskEXIT_CRITICAL()之间不会切换到其它任务。 中断可以执行,也允许嵌套,但只是针对优先级高于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断 – 而且这些中断不允许访问
		FreeRTOS API 函数. */
		PORTA |= 0x01;
		/* 我们已经完成了对PORTA的访问,因此可以安全地离开临界区了。 */
		taskEXIT_CRITICAL();
        vTaskDelay(20 / portTICK_PERIOD_MS);
   
   vTaskDelete(NULL);	

  注意临界区代码一定要精简!因为进入临界区会关闭中断,这样会导致优先级低于configMAX_SYSCALL_INTERRUPT_PRIORITY 的中断得不到及时的响应!

以上是关于uCOS和FreeRTOS在临界区上处理的不同方式,不过本质上是一样的的主要内容,如果未能解决你的问题,请参考以下文章

FreeRTOS临界区

FreeRTOS和Ucos在任务优先级的区别

FreeRTOS和Ucos在打开关闭中断的区别

FreeRTOS 临界段和开关中断

emWin万年历,含uCOS-III和FreeRTOS两个版本

FreeRTOS与uc/os