📄 dynamic.c
字号:
/* Now delay to ensure the other task has processor time. */
vTaskDelay( priSLEEP_TIME );
/* Check the shared variable again. This time to ensure mutual
exclusion the whole scheduler will be locked. This is just for
demo purposes! */
vTaskSuspendAll();
{
if( ulLastCounter == ulCounter )
{
/* The shared variable has not changed. There is a problem
with the continuous count task so flag an error. */
sError = pdTRUE;
xTaskResumeAll();
vPrintDisplayMessage( &pcTaskFailMsg );
vTaskSuspendAll();
}
}
xTaskResumeAll();
}
/* Second section: */
/* Suspend the continuous counter task so it stops accessing the shared variable. */
vTaskSuspend( xContinuousIncrementHandle );
/* Reset the variable. */
ulCounter = ( unsigned portLONG ) 0;
/* Resume the limited count task which has a higher priority than us.
We should therefore not return from this call until the limited count
task has suspended itself with a known value in the counter variable.
The scheduler suspension is not necessary but is included for test
purposes. */
vTaskSuspendAll();
vTaskResume( xLimitedIncrementHandle );
xTaskResumeAll();
/* Does the counter variable have the expected value? */
if( ulCounter != priMAX_COUNT )
{
sError = pdTRUE;
vPrintDisplayMessage( &pcTaskFailMsg );
}
if( sError == pdFALSE )
{
/* If no errors have occurred then increment the check variable. */
portENTER_CRITICAL();
usCheckVariable++;
portEXIT_CRITICAL();
}
/* Resume the continuous count task and do it all again. */
vTaskResume( xContinuousIncrementHandle );
}
}
/*-----------------------------------------------------------*/
static void vQueueSendWhenSuspendedTask( void *pvParameters )
{
static unsigned portLONG ulValueToSend = ( unsigned portLONG ) 0;
const portCHAR * const pcTaskStartMsg = "Queue send while suspended task started.\r\n";
const portCHAR * const pcTaskFailMsg = "Queue send while suspended failed.\r\n";
/* Just to stop warning messages. */
( void ) pvParameters;
/* Queue a message for printing to say the task has started. */
vPrintDisplayMessage( &pcTaskStartMsg );
for( ;; )
{
vTaskSuspendAll();
{
/* We must not block while the scheduler is suspended! */
if( xQueueSend( xSuspendedTestQueue, ( void * ) &ulValueToSend, priNO_BLOCK ) != pdTRUE )
{
if( xSuspendedQueueSendError == pdFALSE )
{
xTaskResumeAll();
vPrintDisplayMessage( &pcTaskFailMsg );
vTaskSuspendAll();
}
xSuspendedQueueSendError = pdTRUE;
}
}
xTaskResumeAll();
vTaskDelay( priSLEEP_TIME );
++ulValueToSend;
}
}
/*-----------------------------------------------------------*/
static void vQueueReceiveWhenSuspendedTask( void *pvParameters )
{
static unsigned portLONG ulExpectedValue = ( unsigned portLONG ) 0, ulReceivedValue;
const portCHAR * const pcTaskStartMsg = "Queue receive while suspended task started.\r\n";
const portCHAR * const pcTaskFailMsg = "Queue receive while suspended failed.\r\n";
portBASE_TYPE xGotValue;
/* Just to stop warning messages. */
( void ) pvParameters;
/* Queue a message for printing to say the task has started. */
vPrintDisplayMessage( &pcTaskStartMsg );
for( ;; )
{
do
{
/* Suspending the scheduler here is fairly pointless and
undesirable for a normal application. It is done here purely
to test the scheduler. The inner xTaskResumeAll() should
never return pdTRUE as the scheduler is still locked by the
outer call. */
vTaskSuspendAll();
{
vTaskSuspendAll();
{
xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK );
}
if( xTaskResumeAll() )
{
xSuspendedQueueReceiveError = pdTRUE;
}
}
xTaskResumeAll();
} while( xGotValue == pdFALSE );
if( ulReceivedValue != ulExpectedValue )
{
if( xSuspendedQueueReceiveError == pdFALSE )
{
vPrintDisplayMessage( &pcTaskFailMsg );
}
xSuspendedQueueReceiveError = pdTRUE;
}
++ulExpectedValue;
}
}
/*-----------------------------------------------------------*/
static void prvChangePriorityWhenSuspendedTask( void *pvParameters )
{
const portCHAR * const pcTaskStartMsg = "Priority change when suspended task started.\r\n";
const portCHAR * const pcTaskFailMsg = "Priority change when suspended task failed.\r\n";
/* Just to stop warning messages. */
( void ) pvParameters;
/* Queue a message for printing to say the task has started. */
vPrintDisplayMessage( &pcTaskStartMsg );
for( ;; )
{
/* Start with the counter at 0 so we know what the counter should be
when we check it next. */
ulPrioritySetCounter = ( unsigned portLONG ) 0;
/* Resume the helper task. At this time it has a priority lower than
ours so no context switch should occur. */
vTaskResume( xChangePriorityWhenSuspendedHandle );
/* Check to ensure the task just resumed has not executed. */
portENTER_CRITICAL();
{
if( ulPrioritySetCounter != ( unsigned portLONG ) 0 )
{
xPriorityRaiseWhenSuspendedError = pdTRUE;
vPrintDisplayMessage( &pcTaskFailMsg );
}
}
portEXIT_CRITICAL();
/* Now try raising the priority while the scheduler is suspended. */
vTaskSuspendAll();
{
vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, ( configMAX_PRIORITIES - 1 ) );
/* Again, even though the helper task has a priority greater than
ours, it should not have executed yet because the scheduler is
suspended. */
portENTER_CRITICAL();
{
if( ulPrioritySetCounter != ( unsigned portLONG ) 0 )
{
xPriorityRaiseWhenSuspendedError = pdTRUE;
vPrintDisplayMessage( &pcTaskFailMsg );
}
}
portEXIT_CRITICAL();
}
xTaskResumeAll();
/* Now the scheduler has been resumed the helper task should
immediately preempt us and execute. When it executes it will increment
the ulPrioritySetCounter exactly once before suspending itself.
We should now always find the counter set to 1. */
portENTER_CRITICAL();
{
if( ulPrioritySetCounter != ( unsigned portLONG ) 1 )
{
xPriorityRaiseWhenSuspendedError = pdTRUE;
vPrintDisplayMessage( &pcTaskFailMsg );
}
}
portEXIT_CRITICAL();
/* Delay until we try this again. */
vTaskDelay( priSLEEP_TIME * 2 );
/* Set the priority of the helper task back ready for the next
execution of this task. */
vTaskSuspendAll();
vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, tskIDLE_PRIORITY );
xTaskResumeAll();
}
}
/*-----------------------------------------------------------*/
static void prvChangePriorityHelperTask( void *pvParameters )
{
/* Just to stop warning messages. */
( void ) pvParameters;
for( ;; )
{
/* This is the helper task for prvChangePriorityWhenSuspendedTask().
It has it's priority raised and lowered. When it runs it simply
increments the counter then suspends itself again. This allows
prvChangePriorityWhenSuspendedTask() to know how many times it has
executed. */
ulPrioritySetCounter++;
vTaskSuspend( NULL );
}
}
/*-----------------------------------------------------------*/
/* Called to check that all the created tasks are still running without error. */
portBASE_TYPE xAreDynamicPriorityTasksStillRunning( void )
{
/* Keep a history of the check variables so we know if it has been incremented
since the last call. */
static unsigned portSHORT usLastTaskCheck = ( unsigned portSHORT ) 0;
portBASE_TYPE xReturn = pdTRUE;
/* Check the tasks are still running by ensuring the check variable
is still incrementing. */
if( usCheckVariable == usLastTaskCheck )
{
/* The check has not incremented so an error exists. */
xReturn = pdFALSE;
}
if( xSuspendedQueueSendError == pdTRUE )
{
xReturn = pdFALSE;
}
if( xSuspendedQueueReceiveError == pdTRUE )
{
xReturn = pdFALSE;
}
if( xPriorityRaiseWhenSuspendedError == pdTRUE )
{
xReturn = pdFALSE;
}
usLastTaskCheck = usCheckVariable;
return xReturn;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -