vTaskNotifyGiveFromISR源码分析

以STM32平台为例,在STM32中数值优先级越低,逻辑优先级越高。

	void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )
	{
	TCB_t * pxTCB;
	uint8_t ucOriginalNotifyState;
	UBaseType_t uxSavedInterruptStatus;

		configASSERT( xTaskToNotify ); (1)

		/* RTOS ports that support interrupt nesting have the concept of a
		maximum	system call (or maximum API call) interrupt priority.
		Interrupts that are	above the maximum system call priority are keep
		permanently enabled, even when the RTOS kernel is in a critical section,
		but cannot make any calls to FreeRTOS API functions.  If configASSERT()
		is defined in FreeRTOSConfig.h then
		portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
		failure if a FreeRTOS API function is called from an interrupt that has
		been assigned a priority above the configured maximum system call
		priority.  Only FreeRTOS functions that end in FromISR can be called
		from interrupts	that have been assigned a priority at or (logically)
		below the maximum system call interrupt priority.  FreeRTOS maintains a
		separate interrupt safe API to ensure interrupt entry is as fast and as
		simple as possible.  More information (albeit Cortex-M specific) is
		provided on the following link:
		http://www.freertos.org/RTOS-Cortex-M3-M4.html */
		portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); (2)

		pxTCB = ( TCB_t * ) xTaskToNotify;

		uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); (3)
		{
			ucOriginalNotifyState = pxTCB->ucNotifyState; (4)
			pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; (5)

			/* 'Giving' is equivalent to incrementing a count in a counting
			semaphore. */
			( pxTCB->ulNotifiedValue )++;/*任务通知值+1*/

			traceTASK_NOTIFY_GIVE_FROM_ISR();

			/* 如果任务在阻塞等待通知 */
			if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
			{
				/* 该任务不应该出现在事件列表中,如果在则触发断言. */
				configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
                /* 如果任务调度器运行中 */
				if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
				{
				    /*唤醒任务,将任务从阻塞列表中移除,添加到就绪列表中*/
					( void ) uxListRemove( &( pxTCB->xStateListItem ) );
					prvAddTaskToReadyList( pxTCB );
				}
				else
				{
					/* 调度器处于挂起状态,中断依然正常发生,但是不能直接操作就绪列表
					将任务加入到就绪挂起列表,任务调度恢复后会移动到就绪列表 */
					vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
				}
                /*如果刚刚唤醒的任务优先级比当前任务高,则设置上下文切换标识,等退出函数后手动切换上下文,
                  或者在系统节拍中断服务程序中自动切换上下文*/
				if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
				{
					/* 设置返回参数,表示需要任务切换,在退出中断前进行任务切换. */
					if( pxHigherPriorityTaskWoken != NULL )
					{
						*pxHigherPriorityTaskWoken = pdTRUE;
					}
					else
					{
						/* 设置自动切换标志. */
						xYieldPending = pdTRUE;
					}
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
		}
		portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
	}

(1) 断言机制,如果 xTaskToNotify 为NULL,那么程序无法向后面运行
(2)

默认情况下源码定义的优先级如下
LIBRARY_LOWEST_INTERRUPT_PRIORITY 15
LIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5

如果一个中断的数值优先级小于5,那么他将被永久启用,即使是处于RTOS的临界区,并且该中断不能调用任何FreeRTOS的 API函数,否者将触发断言(如果启用了断言)。如果中断数值优先级处于5~15之间(包括等于),那么它能并且只能调用以FromISR 结尾的 FreeRTOS API函数。中断要尽可能简单。
(3) 关中断,中断数值优先级大于等于LIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY的都将被屏蔽。
(4) 保存一份任务通知的原始状态,看看任务是否在等待通知,方便在发送通知后恢复任务。
(5)设置当前任务通知的状态为taskNOTIFICATION_RECEIVED

上一篇:Android Bitmap压缩策略


下一篇:interrupt,park/unpark,wait/notify