From 1b7ecd99dbde9a7fa62999fa46c8548c40f248dd Mon Sep 17 00:00:00 2001 From: RichardBarry Date: Sat, 1 Dec 2007 20:28:04 +0000 Subject: [PATCH] Counting semaphore demo added. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@120 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Demo/Common/Minimal/countsem.c | 275 ++++++++++++++++++++++ Demo/Common/include/countsem.h | 44 ++++ Demo/PC/FreeRTOSConfig.h | 25 +- Demo/PC/main.c | 40 +--- Demo/PC/rtosdemo.tgt | 232 ++++++++++-------- Demo/PC/rtosdemo.wpj | 12 +- Source/include/FreeRTOS.h | 4 + Source/include/queue.h | 5 +- Source/include/semphr.h | 76 +++++- Source/portable/GCC/ARM7_AT91SAM7S/port.c | 2 +- Source/queue.c | 68 ++---- 11 files changed, 581 insertions(+), 202 deletions(-) create mode 100644 Demo/Common/Minimal/countsem.c create mode 100644 Demo/Common/include/countsem.h diff --git a/Demo/Common/Minimal/countsem.c b/Demo/Common/Minimal/countsem.c new file mode 100644 index 000000000..dab2c0dc2 --- /dev/null +++ b/Demo/Common/Minimal/countsem.c @@ -0,0 +1,275 @@ +/* + FreeRTOS.org V4.6.1 - Copyright (C) 2003-2007 Richard Barry. + + This file is part of the FreeRTOS.org distribution. + + FreeRTOS.org is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + FreeRTOS.org is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FreeRTOS.org; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + A special exception to the GPL can be applied should you wish to distribute + a combined work that includes FreeRTOS.org, without being obliged to provide + the source code for any proprietary components. See the licensing section + of http://www.FreeRTOS.org for full details of how and when the exception + can be applied. + + *************************************************************************** + See http://www.FreeRTOS.org for documentation, latest information, license + and contact details. Please ensure to read the configuration and relevant + port sections of the online documentation. + + Also see http://www.SafeRTOS.com a version that has been certified for use + in safety critical systems, plus commercial licensing, development and + support options. + *************************************************************************** +*/ + + +/* + * Simple demonstration of the usage of counting semaphore. + */ + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo program include files. */ +#include "countsem.h" + +/* The maximum count value that the semaphore used for the demo can hold. */ +#define countMAX_COUNT_VALUE ( 200 ) + +/* Constants used to indicate whether or not the semaphore should have been +created with its maximum count value, or its minimum count value. These +numbers are used to ensure that the pointers passed in as the task parameters +are valid. */ +#define countSTART_AT_MAX_COUNT ( 0xaa ) +#define countSTART_AT_ZERO ( 0x55 ) + +/* Two tasks are created for the test. One uses a semaphore created with its +count value set to the maximum, and one with the count value set to zero. */ +#define countNUM_TEST_TASKS ( 2 ) +#define countDONT_BLOCK ( 0 ) + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdTRUE should any unexpected behaviour be +detected in any of the tasks. */ +static portBASE_TYPE xErrorDetected = pdFALSE; + +/*-----------------------------------------------------------*/ + +/* + * The demo task. This simply counts the semaphore up to its maximum value, + * the counts it back down again. The result of each semaphore 'give' and + * 'take' is inspected, with an error being flagged if it is found not to be + * the expected result. + */ +static void prvCountingSemaphoreTask( void *pvParameters ); + +/* + * Utility function to increment the semaphore count value up from zero to + * countMAX_COUNT_VALUE. + */ +static void prvIncrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter ); + +/* + * Utility function to decrement the semaphore count value up from + * countMAX_COUNT_VALUE to zero. + */ +static void prvDecrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter ); + +/*-----------------------------------------------------------*/ + +/* The structure that is passed into the task as the task parameter. */ +typedef struct COUNT_SEM_STRUCT +{ + /* The semaphore to be used for the demo. */ + xSemaphoreHandle xSemaphore; + + /* Set to countSTART_AT_MAX_COUNT if the semaphore should be created with + its count value set to its max count value, or countSTART_AT_ZERO if it + should have been created with its count value set to 0. */ + unsigned portBASE_TYPE uxExpectedStartCount; + + /* Incremented on each cycle of the demo task. Used to detect a stalled + task. */ + unsigned portBASE_TYPE uxLoopCounter; +} xCountSemStruct; + +/* Two structures are defined, one is passed to each test task. */ +static xCountSemStruct xParameters[ countNUM_TEST_TASKS ]; + +/*-----------------------------------------------------------*/ + +void vStartCountingSemaphoreTasks( void ) +{ + /* Create the semaphores that we are going to use for the test/demo. The + first should be created such that it starts at its maximum count value, + the second should be created such that it starts with a count value of zero. */ + xParameters[ 0 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, countMAX_COUNT_VALUE ); + xParameters[ 0 ].uxExpectedStartCount = countSTART_AT_MAX_COUNT; + xParameters[ 0 ].uxLoopCounter = 0; + + xParameters[ 1 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, 0 ); + xParameters[ 1 ].uxExpectedStartCount = 0; + xParameters[ 1 ].uxLoopCounter = 0; + + /* Were the semaphores created? */ + if( ( xParameters[ 0 ].xSemaphore != NULL ) || ( xParameters[ 1 ].xSemaphore != NULL ) ) + { + /* Create the demo tasks, passing in the semaphore to use as the parameter. */ + xTaskCreate( prvCountingSemaphoreTask, "CNT1", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 0 ] ), tskIDLE_PRIORITY, NULL ); + xTaskCreate( prvCountingSemaphoreTask, "CNT2", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 1 ] ), tskIDLE_PRIORITY, NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvDecrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter ) +{ +unsigned portBASE_TYPE ux; + + /* If the semaphore count is at its maximum then we should not be able to + 'give' the semaphore. */ + if( xSemaphoreGive( xSemaphore ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* We should be able to 'take' the semaphore countMAX_COUNT_VALUE times. */ + for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ ) + { + if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) != pdPASS ) + { + /* We expected to be able to take the semaphore. */ + xErrorDetected = pdTRUE; + } + + ( *puxLoopCounter )++; + } + + /* If the semaphore count is zero then we should not be able to 'take' + the semaphore. */ + if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +static void prvIncrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter ) +{ +unsigned portBASE_TYPE ux; + + /* If the semaphore count is zero then we should not be able to 'take' + the semaphore. */ + if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* We should be able to 'give' the semaphore countMAX_COUNT_VALUE times. */ + for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ ) + { + if( xSemaphoreGive( xSemaphore ) != pdPASS ) + { + /* We expected to be able to take the semaphore. */ + xErrorDetected = pdTRUE; + } + + ( *puxLoopCounter )++; + } + + /* If the semaphore count is at its maximum then we should not be able to + 'give' the semaphore. */ + if( xSemaphoreGive( xSemaphore ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +static void prvCountingSemaphoreTask( void *pvParameters ) +{ +xCountSemStruct *pxParameter; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ); + + const portCHAR * const pcTaskStartMsg = "Counting semaphore demo started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + /* The semaphore to be used was passed as the parameter. */ + pxParameter = ( xCountSemStruct * ) pvParameters; + + /* Did we expect to find the semaphore already at its max count value, or + at zero? */ + if( pxParameter->uxExpectedStartCount == countSTART_AT_MAX_COUNT ) + { + prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) ); + } + + /* Now we expect the semaphore count to be 0, so this time there is an + error if we can take the semaphore. */ + if( xSemaphoreTake( pxParameter->xSemaphore, 0 ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } + + for( ;; ) + { + prvIncrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) ); + prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) ); + } +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xAreCountingSemaphoreTasksStillRunning( void ) +{ +static unsigned portBASE_TYPE uxLastCount0 = 0, uxLastCount1 = 0; +portBASE_TYPE xReturn = pdPASS; + + /* Return fail if any 'give' or 'take' did not result in the expected + behaviour. */ + if( xErrorDetected != pdFALSE ) + { + xReturn = pdFAIL; + } + + /* Return fail if either task is not still incrementing its loop counter. */ + if( uxLastCount0 == xParameters[ 0 ].uxLoopCounter ) + { + xReturn = pdFAIL; + } + else + { + uxLastCount0 = xParameters[ 0 ].uxLoopCounter; + } + + if( uxLastCount1 == xParameters[ 1 ].uxLoopCounter ) + { + xReturn = pdFAIL; + } + else + { + uxLastCount1 = xParameters[ 1 ].uxLoopCounter; + } + + return xReturn; +} + + diff --git a/Demo/Common/include/countsem.h b/Demo/Common/include/countsem.h new file mode 100644 index 000000000..9f33f26c5 --- /dev/null +++ b/Demo/Common/include/countsem.h @@ -0,0 +1,44 @@ +/* + FreeRTOS.org V4.6.1 - Copyright (C) 2003-2007 Richard Barry. + + This file is part of the FreeRTOS.org distribution. + + FreeRTOS.org is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + FreeRTOS.org is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FreeRTOS.org; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + A special exception to the GPL can be applied should you wish to distribute + a combined work that includes FreeRTOS.org, without being obliged to provide + the source code for any proprietary components. See the licensing section + of http://www.FreeRTOS.org for full details of how and when the exception + can be applied. + + *************************************************************************** + See http://www.FreeRTOS.org for documentation, latest information, license + and contact details. Please ensure to read the configuration and relevant + port sections of the online documentation. + + Also see http://www.SafeRTOS.com a version that has been certified for use + in safety critical systems, plus commercial licensing, development and + support options. + *************************************************************************** +*/ + +#ifndef COUNT_SEMAPHORE_TEST_H +#define COUNT_SEMAPHORE_TEST_H + +void vStartCountingSemaphoreTasks( void ); +portBASE_TYPE xAreCountingSemaphoreTasksStillRunning( void ); + +#endif + diff --git a/Demo/PC/FreeRTOSConfig.h b/Demo/PC/FreeRTOSConfig.h index b35b89bc7..4b8f5623c 100644 --- a/Demo/PC/FreeRTOSConfig.h +++ b/Demo/PC/FreeRTOSConfig.h @@ -50,18 +50,19 @@ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. *----------------------------------------------------------*/ -#define configUSE_PREEMPTION 1 -#define configUSE_IDLE_HOOK 1 -#define configUSE_TICK_HOOK 1 -#define configTICK_RATE_HZ ( ( portTickType ) 1000 ) -#define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 256 ) /* This can be made smaller if required. */ -#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 32 * 1024 ) ) -#define configMAX_TASK_NAME_LEN ( 16 ) -#define configUSE_TRACE_FACILITY 1 -#define configUSE_16_BIT_TICKS 1 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_CO_ROUTINES 1 -#define configUSE_MUTEXES 1 +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 1 +#define configTICK_RATE_HZ ( ( portTickType ) 1000 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 256 ) /* This can be made smaller if required. */ +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 32 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 16 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 1 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_CO_ROUTINES 1 +#define configUSE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 #define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 10 ) #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) diff --git a/Demo/PC/main.c b/Demo/PC/main.c index 603c22a9e..981ab9b57 100644 --- a/Demo/PC/main.c +++ b/Demo/PC/main.c @@ -65,38 +65,6 @@ *
*/ -/* -Changes from V1.00: - - + Prevent the call to kbhit() for debug builds as the debugger seems to - have problems stepping over the call. - -Changes from V1.2.3 - - + The integer and comtest tasks are now used when the cooperative scheduler - is being used. Previously they were only used with the preemptive - scheduler. - -Changes from V1.2.6 - - + Create new tasks as defined by the new demo application file dynamic.c. - -Changes from V2.0.0 - - + Delay periods are now specified using variables and constants of - portTickType rather than unsigned portLONG. - -Changes from V3.1.1 - - + The tasks defined in the new file "events.c" are now created and - monitored for errors. - -Changes from V3.2.4 - - + Now includes the flash co-routine demo rather than the flash task demo. - This is to demonstrate the co-routine functionality. -*/ - #include #include #include "FreeRTOS.h" @@ -122,6 +90,7 @@ Changes from V3.2.4 #include "blocktim.h" #include "GenQTest.h" #include "QPeek.h" +#include "countsem.h" /* Priority definitions for the tasks in the demo application. */ #define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) @@ -185,6 +154,7 @@ portSHORT main( void ) vStartDynamicPriorityTasks(); vStartMultiEventTasks(); vStartQueuePeekTasks(); + vStartCountingSemaphoreTasks(); /* Create the "Print" task as described at the top of the file. */ xTaskCreate( vErrorChecks, "Print", mainPRINT_STACK_SIZE, NULL, mainPRINT_TASK_PRIORITY, NULL ); @@ -408,6 +378,12 @@ static portSHORT sErrorHasOccurred = pdFALSE; sErrorHasOccurred = pdTRUE; } + if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE ) + { + vDisplayMessage( "Error in counting semaphore demo task!\r\n" ); + sErrorHasOccurred = pdTRUE; + } + if( sErrorHasOccurred == pdFALSE ) { vDisplayMessage( "OK " ); diff --git a/Demo/PC/rtosdemo.tgt b/Demo/PC/rtosdemo.tgt index ed17eb9a8..022052d99 100644 --- a/Demo/PC/rtosdemo.tgt +++ b/Demo/PC/rtosdemo.tgt @@ -75,7 +75,7 @@ WVList 0 19 WPickList -53 +55 20 MItem 3 @@ -724,8 +724,8 @@ WVList 0 172 MItem -27 -..\COMMON\MINIMAL\crflash.c +28 +..\COMMON\MINIMAL\countsem.c 173 WString 4 @@ -742,8 +742,8 @@ WVList 0 176 MItem -26 -..\COMMON\MINIMAL\crhook.c +27 +..\COMMON\MINIMAL\crflash.c 177 WString 4 @@ -760,8 +760,8 @@ WVList 0 180 MItem -28 -..\COMMON\MINIMAL\GenQTest.c +26 +..\COMMON\MINIMAL\crhook.c 181 WString 4 @@ -778,8 +778,8 @@ WVList 0 184 MItem -25 -..\COMMON\MINIMAL\QPeek.c +28 +..\COMMON\MINIMAL\GenQTest.c 185 WString 4 @@ -796,8 +796,8 @@ WVList 0 188 MItem -15 -fileio\fileio.c +25 +..\COMMON\MINIMAL\QPeek.c 189 WString 4 @@ -814,8 +814,8 @@ WVList 0 192 MItem -6 -main.c +15 +fileio\fileio.c 193 WString 4 @@ -832,8 +832,8 @@ WVList 0 196 MItem -17 -partest\partest.c +6 +main.c 197 WString 4 @@ -850,8 +850,8 @@ WVList 0 200 MItem -15 -serial\serial.c +17 +partest\partest.c 201 WString 4 @@ -868,26 +868,26 @@ WVList 0 204 MItem -3 -*.h +15 +serial\serial.c 205 WString -3 -NIL +4 +COBJ 206 WVList 0 207 WVList 0 --1 +20 +1 1 -0 0 208 MItem -31 -..\..\SOURCE\INCLUDE\croutine.h +3 +*.h 209 WString 3 @@ -898,14 +898,14 @@ WVList 211 WVList 0 -204 -1 +-1 1 0 +0 212 MItem -27 -..\..\source\include\list.h +31 +..\..\SOURCE\INCLUDE\croutine.h 213 WString 3 @@ -916,14 +916,14 @@ WVList 215 WVList 0 -204 +208 1 1 0 216 MItem -31 -..\..\source\include\portable.h +27 +..\..\source\include\list.h 217 WString 3 @@ -934,14 +934,14 @@ WVList 219 WVList 0 -204 +208 1 1 0 220 MItem 31 -..\..\source\include\projdefs.h +..\..\source\include\portable.h 221 WString 3 @@ -952,14 +952,14 @@ WVList 223 WVList 0 -204 +208 1 1 0 224 MItem -28 -..\..\source\include\queue.h +31 +..\..\source\include\projdefs.h 225 WString 3 @@ -970,14 +970,14 @@ WVList 227 WVList 0 -204 +208 1 1 0 228 MItem -29 -..\..\source\include\semphr.h +28 +..\..\source\include\queue.h 229 WString 3 @@ -988,14 +988,14 @@ WVList 231 WVList 0 -204 +208 1 1 0 232 MItem -27 -..\..\source\include\task.h +29 +..\..\source\include\semphr.h 233 WString 3 @@ -1006,14 +1006,14 @@ WVList 235 WVList 0 -204 +208 1 1 0 236 MItem -55 -..\..\source\portable\owatcom\16bitdos\common\portasm.h +27 +..\..\source\include\task.h 237 WString 3 @@ -1024,14 +1024,14 @@ WVList 239 WVList 0 -204 +208 1 1 0 240 MItem -53 -..\..\source\portable\owatcom\16bitdos\pc\portmacro.h +55 +..\..\source\portable\owatcom\16bitdos\common\portasm.h 241 WString 3 @@ -1042,14 +1042,14 @@ WVList 243 WVList 0 -204 +208 1 1 0 244 MItem -26 -..\common\include\blockq.h +53 +..\..\source\portable\owatcom\16bitdos\pc\portmacro.h 245 WString 3 @@ -1060,14 +1060,14 @@ WVList 247 WVList 0 -204 +208 1 1 0 248 MItem -28 -..\COMMON\INCLUDE\blocktim.h +26 +..\common\include\blockq.h 249 WString 3 @@ -1078,14 +1078,14 @@ WVList 251 WVList 0 -204 +208 1 1 0 252 MItem -27 -..\common\include\comtest.h +28 +..\COMMON\INCLUDE\blocktim.h 253 WString 3 @@ -1096,14 +1096,14 @@ WVList 255 WVList 0 -204 +208 1 1 0 256 MItem -26 -..\COMMON\INCLUDE\crhook.h +27 +..\common\include\comtest.h 257 WString 3 @@ -1114,14 +1114,14 @@ WVList 259 WVList 0 -204 +208 1 1 0 260 MItem -25 -..\common\include\death.h +28 +..\COMMON\INCLUDE\countsem.h 261 WString 3 @@ -1132,14 +1132,14 @@ WVList 263 WVList 0 -204 +208 1 1 0 264 MItem -27 -..\COMMON\INCLUDE\dynamic.h +26 +..\COMMON\INCLUDE\crhook.h 265 WString 3 @@ -1150,14 +1150,14 @@ WVList 267 WVList 0 -204 +208 1 1 0 268 MItem -26 -..\common\include\fileio.h +25 +..\common\include\death.h 269 WString 3 @@ -1168,14 +1168,14 @@ WVList 271 WVList 0 -204 +208 1 1 0 272 MItem -25 -..\common\include\flash.h +27 +..\COMMON\INCLUDE\dynamic.h 273 WString 3 @@ -1186,14 +1186,14 @@ WVList 275 WVList 0 -204 +208 1 1 0 276 MItem -24 -..\common\include\flop.h +26 +..\common\include\fileio.h 277 WString 3 @@ -1204,14 +1204,14 @@ WVList 279 WVList 0 -204 +208 1 1 0 280 MItem -28 -..\COMMON\INCLUDE\GenQTest.h +25 +..\common\include\flash.h 281 WString 3 @@ -1222,14 +1222,14 @@ WVList 283 WVList 0 -204 +208 1 1 0 284 MItem -27 -..\common\include\partest.h +24 +..\common\include\flop.h 285 WString 3 @@ -1240,14 +1240,14 @@ WVList 287 WVList 0 -204 +208 1 1 0 288 MItem -25 -..\common\include\pollq.h +28 +..\COMMON\INCLUDE\GenQTest.h 289 WString 3 @@ -1258,14 +1258,14 @@ WVList 291 WVList 0 -204 +208 1 1 0 292 MItem -25 -..\common\include\print.h +27 +..\common\include\partest.h 293 WString 3 @@ -1276,14 +1276,14 @@ WVList 295 WVList 0 -204 +208 1 1 0 296 MItem -27 -..\common\include\semtest.h +25 +..\common\include\pollq.h 297 WString 3 @@ -1294,14 +1294,14 @@ WVList 299 WVList 0 -204 +208 1 1 0 300 MItem -26 -..\common\include\serial.h +25 +..\common\include\print.h 301 WString 3 @@ -1312,14 +1312,14 @@ WVList 303 WVList 0 -204 +208 1 1 0 304 MItem -16 -FreeRTOSConfig.h +27 +..\common\include\semtest.h 305 WString 3 @@ -1330,7 +1330,43 @@ WVList 307 WVList 0 -204 +208 +1 +1 +0 +308 +MItem +26 +..\common\include\serial.h +309 +WString +3 +NIL +310 +WVList +0 +311 +WVList +0 +208 +1 +1 +0 +312 +MItem +16 +FreeRTOSConfig.h +313 +WString +3 +NIL +314 +WVList +0 +315 +WVList +0 +208 1 1 0 diff --git a/Demo/PC/rtosdemo.wpj b/Demo/PC/rtosdemo.wpj index cd8e9e655..3c869d9bc 100644 --- a/Demo/PC/rtosdemo.wpj +++ b/Demo/PC/rtosdemo.wpj @@ -4,10 +4,10 @@ projectIdent VpeMain 1 WRect -0 -0 -7680 -9216 +6 +9 +6229 +7197 2 MProject 3 @@ -31,7 +31,7 @@ WRect 0 0 7168 -8474 +8270 0 0 9 @@ -39,5 +39,5 @@ WFileName 12 rtosdemo.tgt 0 -24 +25 7 diff --git a/Source/include/FreeRTOS.h b/Source/include/FreeRTOS.h index d83ebbefa..35e4426e9 100644 --- a/Source/include/FreeRTOS.h +++ b/Source/include/FreeRTOS.h @@ -116,6 +116,10 @@ #define configUSE_MUTEXES 0 #endif +#ifndef configUSE_COUNTING_SEMAPHORES + #define configUSE_COUNTING_SEMAPHORES 0 +#endif + #if ( configUSE_MUTEXES == 1 ) /* xTaskGetCurrentTaskHandle is used by the priority inheritance mechanism within the mutex implementation so must be available if mutexes are used. */ diff --git a/Source/include/queue.h b/Source/include/queue.h index 482ccc3f6..611389f19 100644 --- a/Source/include/queue.h +++ b/Source/include/queue.h @@ -1175,10 +1175,11 @@ signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQue signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ); /* - * For internal use only. Use xSemaphoreCreateMutex() instead of calling - * this function directly. + * For internal use only. Use xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting() instead of calling these functions directly. */ xQueueHandle xQueueCreateMutex( void ); +xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ); #ifdef __cplusplus } diff --git a/Source/include/semphr.h b/Source/include/semphr.h index 9855ed722..a1ada86aa 100644 --- a/Source/include/semphr.h +++ b/Source/include/semphr.h @@ -34,11 +34,11 @@ *************************************************************************** */ -#include "queue.h" - #ifndef SEMAPHORE_H #define SEMAPHORE_H +#include "queue.h" + typedef xQueueHandle xSemaphoreHandle; #define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( unsigned portCHAR ) 1 ) @@ -84,12 +84,12 @@ typedef xQueueHandle xSemaphoreHandle; * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary * \ingroup Semaphores */ -#define vSemaphoreCreateBinary( xSemaphore ) { \ - xSemaphore = xQueueCreate( ( unsigned portCHAR ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH ); \ - if( xSemaphore != NULL ) \ - { \ - xSemaphoreGive( xSemaphore ); \ - } \ +#define vSemaphoreCreateBinary( xSemaphore ) { \ + xSemaphore = xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH ); \ + if( xSemaphore != NULL ) \ + { \ + xSemaphoreGive( xSemaphore ); \ + } \ } /** @@ -341,6 +341,66 @@ typedef xQueueHandle xSemaphoreHandle; */ #define xSemaphoreCreateMutex() xQueueCreateMutex() +/** + * semphr. h + *
vSemaphoreCreateCounting( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE uxMaxCount )
+ * + * Macro that creates a counting semaphore by using the existing + * queue mechanism. The queue length is used as the maximum count. The data + * size is 0 as we don't want to actually store any data - we just want to + * know if the queue is empty or full. + * + * Counting semaphores are typically used for two things: + * + * 1) Counting events. + * + * In this usage scenario an event handler will 'give' a semphore each time + * an event occurs (incrementing the semaphore count value), and a handler + * task will 'take' a semaphore each time it processes an event + * (decrementing the semaphore count value). The count value is therefore + * the difference between the number of events that have occurred and the + * number that have been processed. In this case it is desirable for the + * initial count value to be zero. + * + * 2) Resource management. + * + * In this usage scenario the count value indicates the number of resources + * available. To obtain control of a resource a task must first obtain a + * semphoare - decrementing the semaphore count value. When the count value + * reaches zero there are no free resources. When a task finishes with the + * resource it 'gives' the semahore back - incrementing the semaphore count + * value. In this case it is desirable for the initial count value to be + * equal to the maximum count value, indicating that all resources are free. + * + * @param uxMaxCount The maximum count value that can be reached. When the + * semaphore reaches this value it can nolonger be 'given'. + * @param uxInitialCount + * + * @return Handle to the created semaphore. Should be of type xSemaphoreHandle. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ xSemaphoreHandle xSemaphore = NULL;
+
+    // Semaphore cannot be used before a call to vSemaphoreCreateCounting().
+    // This is a macro so pass the variable in directly.
+    vSemaphoreCreateBinary( xSemaphore,  );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.  
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting + * \ingroup Semaphores + */ +#define xSemaphoreCreateCounting( uxCountValue, uxInitialCount ) xQueueCreateCountingSemaphore( uxCountValue, uxInitialCount ) #endif /* SEMAPHORE_H */ diff --git a/Source/portable/GCC/ARM7_AT91SAM7S/port.c b/Source/portable/GCC/ARM7_AT91SAM7S/port.c index de7994c0c..bf1cfaa29 100644 --- a/Source/portable/GCC/ARM7_AT91SAM7S/port.c +++ b/Source/portable/GCC/ARM7_AT91SAM7S/port.c @@ -114,7 +114,7 @@ portSTACK_TYPE *pxOriginalTOS; *pxTopOfStack = ( portSTACK_TYPE ) pxCode + portINSTRUCTION_SIZE; pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0xaaaaaaaa; /* R14 */ + *pxTopOfStack = ( portSTACK_TYPE ) 0x00000000; /* R14 */ pxTopOfStack--; *pxTopOfStack = ( portSTACK_TYPE ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ pxTopOfStack--; diff --git a/Source/queue.c b/Source/queue.c index b2a363792..ba0e89383 100644 --- a/Source/queue.c +++ b/Source/queue.c @@ -34,49 +34,6 @@ *************************************************************************** */ -/* -Changes from V1.01 - - + More use of 8bit data types. - + Function name prefixes changed where the data type returned has changed. - -Changed from V2.0.0 - - + Added the queue locking mechanism and make more use of the scheduler - suspension feature to minimise the time interrupts have to be disabled - when accessing a queue. - -Changed from V2.2.0 - - + Explicit use of 'signed' qualifier on portCHAR types added. - -Changes from V3.0.0 - - + API changes as described on the FreeRTOS.org WEB site. - -Changes from V3.2.3 - - + Added the queue functions that can be used from co-routines. - -Changes from V4.0.5 - - + Added a loop within xQueueSend() and xQueueReceive() to prevent the - functions exiting when a block time remains and the function has - not completed. - -Changes from V4.1.2: - - + BUG FIX: Removed the call to prvIsQueueEmpty from within xQueueCRReceive - as it exited with interrupts enabled. Thanks Paul Katz. - -Changes from V4.1.3: - - + Modified xQueueSend() and xQueueReceive() to handle the (very unlikely) - case whereby a task unblocking due to a temporal event can remove/send an - item from/to a queue when a higher priority task is still blocked on the - queue. This modification is a result of the SafeRTOS testing. -*/ - #include #include #include "FreeRTOS.h" @@ -100,6 +57,11 @@ Changes from V4.1.3: #define uxQueueType pcHead #define queueQUEUE_IS_MUTEX NULL +/* Semaphores do not actually store or copy data, so have an items size of +zero. */ +#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( 0 ) +#define queueDONT_BLOCK ( ( portTickType ) 0 ) + /* * Definition of the queue used by the scheduler. * Items are queued by copy, not reference. @@ -144,6 +106,7 @@ signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ); signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, const void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ); xQueueHandle xQueueCreateMutex( void ); +xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ); #if configUSE_CO_ROUTINES == 1 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ); @@ -296,6 +259,25 @@ size_t xQueueSizeInBytes; #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ +#if configUSE_COUNTING_SEMAPHORES == 1 + + xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) + { + xQueueHandle pxHandle; + + pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH ); + + if( pxHandle != NULL ) + { + pxHandle->uxMessagesWaiting = uxInitialCount; + } + + return pxHandle; + } + +#endif /* configUSE_COUNTING_SEMAPHORES */ +/*-----------------------------------------------------------*/ + signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) { signed portBASE_TYPE xReturn = pdPASS; -- 2.39.5