static void prvExerciseTaskNotificationAPI( void ) { uint32_t ulNotificationValue; BaseType_t xReturned; /* The task should not yet have a notification pending. */ xReturned = xTaskNotifyWait( 0, 0, &ulNotificationValue, mainDONT_BLOCK ); configASSERT( xReturned == pdFAIL ); configASSERT( ulNotificationValue == 0UL ); /* Exercise the 'give' and 'take' versions of the notification API. */ xTaskNotifyGive( xTaskGetCurrentTaskHandle() ); xTaskNotifyGive( xTaskGetCurrentTaskHandle() ); ulNotificationValue = ulTaskNotifyTake( pdTRUE, mainDONT_BLOCK ); configASSERT( ulNotificationValue == 2 ); /* Exercise the 'notify' and 'clear' API. */ ulNotificationValue = 20; xTaskNotify( xTaskGetCurrentTaskHandle(), ulNotificationValue, eSetValueWithOverwrite ); ulNotificationValue = 0; xReturned = xTaskNotifyWait( 0, 0, &ulNotificationValue, mainDONT_BLOCK ); configASSERT( xReturned == pdPASS ); configASSERT( ulNotificationValue == 20 ); xTaskNotify( xTaskGetCurrentTaskHandle(), ulNotificationValue, eSetValueWithOverwrite ); xReturned = xTaskNotifyStateClear( NULL ); configASSERT( xReturned == pdTRUE ); /* First time a notification was pending. */ xReturned = xTaskNotifyStateClear( NULL ); configASSERT( xReturned == pdFALSE ); /* Second time the notification was already clear. */ }
/* Function required in order to link UARTCommandConsole.c - which is used by multiple different demo application. */ void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength ) { const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 5000 ); /* Only one port is supported. */ ( void ) pxPort; /* Clear the flag before initiating a new transmission */ sci1_txdone = FALSE; /* Don't send the string unless the previous string has been sent. */ if( ( xSendingTask == NULL ) && ( usStringLength > 0 ) ) { /* Ensure the calling task's notification state is not already pending. */ xTaskNotifyStateClear( NULL ); /* Store the handle of the transmitting task. This is used to unblock the task when the transmission has completed. */ xSendingTask = xTaskGetCurrentTaskHandle(); /* Send the string using the auto-generated API. */ R_SCI1_Serial_Send( ( uint8_t * ) pcString, usStringLength ); /* Wait in the Blocked state (so not using any CPU time) until the transmission has completed. */ ulTaskNotifyTake( pdTRUE, xMaxBlockTime ); } }
BaseType_t MPU_xTaskNotifyStateClear( TaskHandle_t xTask ) { BaseType_t xReturn; BaseType_t xRunningPrivileged = xPortRaisePrivilege(); xReturn = xTaskNotifyStateClear( xTask ); vPortResetPrivilege( xRunningPrivileged ); return xReturn; }
static void prvSingleTaskTests( void ) { const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL ); BaseType_t xReturned; uint32_t ulNotifiedValue, ulLoop, ulNotifyingValue, ulPreviousValue, ulExpectedValue; TickType_t xTimeOnEntering; const uint32_t ulFirstNotifiedConst = 100001UL, ulSecondNotifiedValueConst = 5555UL, ulMaxLoops = 5UL; const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL; /* ------------------------------------------------------------------------- Check blocking when there are no notifications. */ xTimeOnEntering = xTaskGetTickCount(); xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, xTicksToWait ); /* Should have blocked for the entire block time. */ if( ( xTaskGetTickCount() - xTimeOnEntering ) < xTicksToWait ) { xErrorStatus = pdFAIL; } configASSERT( xReturned == pdFAIL ); configASSERT( ulNotifiedValue == 0UL ); /* ------------------------------------------------------------------------- Check no blocking when notifications are pending. First notify itself - this would not be a normal thing to do and is done here for test purposes only. */ xReturned = xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue ); /* Even through the 'without overwrite' action was used the update should have been successful. */ configASSERT( xReturned == pdPASS ); /* No bits should have been pending previously. */ configASSERT( ulPreviousValue == 0 ); /* The task should now have a notification pending, and so not time out. */ xTimeOnEntering = xTaskGetTickCount(); xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, xTicksToWait ); if( ( xTaskGetTickCount() - xTimeOnEntering ) >= xTicksToWait ) { xErrorStatus = pdFAIL; } /* The task should have been notified, and the notified value should be equal to ulFirstNotifiedConst. */ configASSERT( xReturned == pdPASS ); configASSERT( ulNotifiedValue == ulFirstNotifiedConst ); /* Incremented to show the task is still running. */ ulNotifyCycleCount++; /*-------------------------------------------------------------------------- Check the non-overwriting functionality. The notification is done twice using two different notification values. The action says don't overwrite so only the first notification should pass and the value read back should also be that used with the first notification. */ xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite ); configASSERT( xReturned == pdPASS ); xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithoutOverwrite ); configASSERT( xReturned == pdFAIL ); /* Waiting for the notification should now return immediately so a block time of zero is used. */ xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdPASS ); configASSERT( ulNotifiedValue == ulFirstNotifiedConst ); /*-------------------------------------------------------------------------- Do the same again, only this time use the overwriting version. This time both notifications should pass, and the value written the second time should overwrite the value written the first time, and so be the value that is read back. */ xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithOverwrite ); configASSERT( xReturned == pdPASS ); xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithOverwrite ); configASSERT( xReturned == pdPASS ); xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdPASS ); configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst ); /*-------------------------------------------------------------------------- Check notifications with no action pass without updating the value. Even though ulFirstNotifiedConst is used as the value the value read back should remain at ulSecondNotifiedConst. */ xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eNoAction ); configASSERT( xReturned == pdPASS ); xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 ); configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst ); /*-------------------------------------------------------------------------- Check incrementing values. Send ulMaxLoop increment notifications, then ensure the received value is as expected - which should be ulSecondNotificationValueConst plus how ever many times to loop iterated. */ for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ ) { xReturned = xTaskNotify( xTaskToNotify, 0, eIncrement ); configASSERT( xReturned == pdPASS ); } xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdPASS ); configASSERT( ulNotifiedValue == ( ulSecondNotifiedValueConst + ulMaxLoops ) ); /* Should not be any notifications pending now. */ xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdFAIL ); /*-------------------------------------------------------------------------- Check all bits can be set by notifying the task with one additional bit set on each notification, and exiting the loop when all the bits are found to be set. As there are 32-bits the loop should execute 32 times before all the bits are found to be set. */ ulNotifyingValue = 0x01; ulLoop = 0; /* Start with all bits clear. */ xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 ); do { /* Set the next bit in the task's notified value. */ xTaskNotify( xTaskToNotify, ulNotifyingValue, eSetBits ); /* Wait for the notified value - which of course will already be available. Don't clear the bits on entry or exit as this loop is exited when all the bits are set. */ xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdPASS ); ulLoop++; /* Use the next bit on the next iteration around this loop. */ ulNotifyingValue <<= 1UL; } while ( ulNotifiedValue != ULONG_MAX ); /* As a 32-bit value was used the loop should have executed 32 times before all the bits were set. */ configASSERT( ulLoop == 32 ); /*-------------------------------------------------------------------------- Check bits are cleared on entry but not on exit when a notification fails to arrive before timing out - both with and without a timeout value. Wait for the notification again - but this time it is not given by anything and should return pdFAIL. The parameters are set to clear bit zero on entry and bit one on exit. As no notification was received only the bit cleared on entry should actually get cleared. */ xReturned = xTaskNotifyWait( ulBit0, ulBit1, &ulNotifiedValue, xTicksToWait ); configASSERT( xReturned == pdFAIL ); /* Notify the task with no action so as not to update the bits even though ULONG_MAX is used as the notification value. */ xTaskNotify( xTaskToNotify, ULONG_MAX, eNoAction ); /* Reading back the value should should find bit 0 is clear, as this was cleared on entry, but bit 1 is not clear as it will not have been cleared on exit as no notification was received. */ xReturned = xTaskNotifyWait( 0x00UL, 0x00UL, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdPASS ); configASSERT( ulNotifiedValue == ( ULONG_MAX & ~ulBit0 ) ); /*-------------------------------------------------------------------------- Now try clearing the bit on exit. For that to happen a notification must be received, so the task is notified first. */ xTaskNotify( xTaskToNotify, 0, eNoAction ); xTaskNotifyWait( 0x00, ulBit1, &ulNotifiedValue, 0 ); /* However as the bit is cleared on exit, after the returned notification value is set, the returned notification value should not have the bit cleared... */ configASSERT( ulNotifiedValue == ( ULONG_MAX & ~ulBit0 ) ); /* ...but reading the value back again should find that the bit was indeed cleared internally. The returned value should be pdFAIL however as nothing has notified the task in the mean time. */ xReturned = xTaskNotifyWait( 0x00, 0x00, &ulNotifiedValue, 0 ); configASSERT( xReturned == pdFAIL ); configASSERT( ulNotifiedValue == ( ULONG_MAX & ~( ulBit0 | ulBit1 ) ) ); /*-------------------------------------------------------------------------- Now try querying the previous value while notifying a task. */ xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue ); configASSERT( ulNotifiedValue == ( ULONG_MAX & ~( ulBit0 | ulBit1 ) ) ); /* Clear all bits. */ xTaskNotifyWait( 0x00, ULONG_MAX, &ulNotifiedValue, 0 ); xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue ); configASSERT( ulPreviousValue == 0 ); ulExpectedValue = 0; for( ulLoop = 0x01; ulLoop < 0x80UL; ulLoop <<= 1UL ) { /* Set the next bit up, and expect to receive the last bits set (so the previous value will not yet have the bit being set this time around). */ xTaskNotifyAndQuery( xTaskToNotify, ulLoop, eSetBits, &ulPreviousValue ); configASSERT( ulExpectedValue == ulPreviousValue ); ulExpectedValue |= ulLoop; } /* ------------------------------------------------------------------------- Clear the previous notifications. */ xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 ); /* The task should not have any notifications pending, so an attempt to clear the notification state should fail. */ configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE ); /* Get the task to notify itself. This is not a normal thing to do, and is only done here for test purposes. */ xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue ); /* Now the notification state should be eNotified, so it should now be possible to clear the notification state. */ configASSERT( xTaskNotifyStateClear( NULL ) == pdTRUE ); configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE ); /* Incremented to show the task is still running. */ ulNotifyCycleCount++; /* Leave all bits cleared. */ xTaskNotifyWait( ULONG_MAX, 0, NULL, 0 ); }