Index: /webserver/example/freeRTOSexample/Source/EnergyMeters/Meters.c =================================================================== --- /webserver/example/freeRTOSexample/Source/EnergyMeters/Meters.c (revision 19) +++ /webserver/example/freeRTOSexample/Source/EnergyMeters/Meters.c (revision 22) @@ -4,5 +4,5 @@ #include "task.h" -#define metersSTACK_SIZE configMINIMAL_STACK_SIZE +#define metersSTACK_SIZE configMINIMAL_STACK_SIZE+200 /* masks for RTC */ #define MASKSEC 0x3F // Second 00..59 00000000:00000000:00xxxxxx @@ -10,4 +10,7 @@ #define MASKHR 0x1F0000 // Hour 00..23 000xxxxx:00000000:00000000 +#include "MetersIncludes.h" + +extern xTickCount; /* tick counter (milliseconds) */ portBASE_TYPE Init_P2_0(void); @@ -21,5 +24,4 @@ portTickType xLastMeterTaskRunTime; /* keeps the last time the meter calculation ran */ -portTickType xMeterIdleRate = 1000; /* the rate (in ticks = ms) at which the calculation runs when no pulses triggered a calculation */ @@ -35,6 +37,4 @@ Init_P2_0(); /* init GPIO for meters */ - xLastMeterTaskRunTime = xTaskGetTickCount(); /* init last run time */ - for( ;; ) @@ -73,4 +73,5 @@ { + initMeterItems(); /* Spawn the task. */ xTaskCreate( vMeters_Task, ( signed portCHAR * ) "Meters", metersSTACK_SIZE, NULL, uxPriority, ( xTaskHandle * ) NULL ); @@ -106,2 +107,19 @@ } + +void initMeterItems(void) +{ + int i; + for (i = 0; i < NUMBER_OF_METERS; i++) + { + meterItems[i].meterEnabled = 0; // disable all meters + } + + // Init Gas meter + meterItems[METER_INDEX_GAS].meterEnabled = 1; /* 0: item not used, 1: meter enabled */ + meterItems[METER_INDEX_GAS].timeLastTick = getEpochTimeWithMs(); /* when did the last tick occur? epoch (seconds) */ + meterItems[METER_INDEX_GAS].timeBeforeLastTick = getEpochTimeWithMs(); /* when did the tick before last tick occur? epoch (seconds) */ + meterItems[METER_INDEX_GAS].valueLastTick = 0; /* what value did we have at the last tick? */ + meterItems[METER_INDEX_GAS].valueBeforeLastTick = 1; /* what value did we have at the tick before the last tick? */ + +} Index: /webserver/example/freeRTOSexample/Source/EnergyMeters/Meters_ISRs.c =================================================================== --- /webserver/example/freeRTOSexample/Source/EnergyMeters/Meters_ISRs.c (revision 19) +++ /webserver/example/freeRTOSexample/Source/EnergyMeters/Meters_ISRs.c (revision 22) @@ -2,7 +2,10 @@ #include "semphr.h" #include "task.h" +#include "MetersIncludes.h" -extern basementGasReading; extern xMetersSemaphore; +extern xTickCount; /* millisecond tick counter */ + +void handleGasMeterTick(void); /* The interrupt entry point. */ @@ -19,5 +22,5 @@ if ((IO2_INT_STAT_R & (1 << 10)) != 0) /* P2.10 interrupt triggered */ { - basementGasReading++; + handleGasMeterTick(); } // else if ((IO2_INT_STAT_R & (1 << n)) != 0) /* some other interrupt triggered */ @@ -56,5 +59,10 @@ } +void handleGasMeterTick(void) +{ + meterItems[METER_INDEX_GAS].timeBeforeLastTick = meterItems[METER_INDEX_GAS].timeLastTick; /* when did the tick before the last tick occur? */ + meterItems[METER_INDEX_GAS].timeLastTick = getEpochTimeWithMs(); /* when did the last tick occur? epoch (seconds) */ + meterItems[METER_INDEX_GAS].valueLastTick = 0; /* what value did we have at the last tick? */ + meterItems[METER_INDEX_GAS].valueBeforeLastTick = 1; /* what value did we have at the tick before the last tick? */ +} - - Index: /webserver/example/freeRTOSexample/Source/EnergyMeters/timeConversion.c =================================================================== --- /webserver/example/freeRTOSexample/Source/EnergyMeters/timeConversion.c (revision 22) +++ /webserver/example/freeRTOSexample/Source/EnergyMeters/timeConversion.c (revision 22) @@ -0,0 +1,92 @@ + +#include +#include "FreeRTOS.h" +#include "MetersIncludes.h" +#include "task.h" +#include "StackMacros.h" + +#define MASKSEC 0x3F // Second 00..59 00000000:00000000:00xxxxxx +#define MASKMIN 0x3F00 // Minute 00..59 00000000:00xxxxxx:00000000 +#define MASKHR 0x1F0000 // Hour 00..23 000xxxxx:00000000:00000000 + +extern xTickCount; /* tick counter (milliseconds) from FreeRTOS */ + +/* taken from Linux Kernel 2.6.30 */ +portLONG +mktime(const unsigned int year0, const unsigned int mon0, + const unsigned int day, const unsigned int hour, + const unsigned int min, const unsigned int sec); +unsigned long long getEpochTimeWithMs(void) +{ + /* get both registers while in critical section to eliminate the chance of inconsistencies when there are + * overflows of the SECONDS value. + */ + unsigned int timeHour; + unsigned int timeMin; + unsigned int timeSec; + unsigned int timeDay; + unsigned int timeMonth; + unsigned int timeYear; + unsigned long long tempTickTime; + portLONG cTIME0; + portLONG cTIME1; + +// portENTER_CRITICAL(); + cTIME0 = RTC_CTIME0; + cTIME1 = RTC_CTIME1; +// portEXIT_CRITICAL(); + + + timeHour = (cTIME0 & MASKHR)>>16; // Hour + timeMin = (cTIME0 & MASKMIN)>>8; // Minute + timeSec = cTIME0 & MASKSEC; // Second + timeDay = cTIME1 & 0xf; // Day + timeMonth = (cTIME1 >> 8) & 0xF; // Month + timeYear = (cTIME1 >> 16) & 0xFFF; // Year + + /* we get the epoch time, multiply it by 1000 and then add the milliseconds portion + of the Tick timer. This returns a millisecond time since epoch. + */ + tempTickTime = mktime(timeYear, timeMonth, timeDay, timeHour, timeMin, timeSec); + tempTickTime -= 3600 * 2; /* time zone adaptation (2 h) */ + tempTickTime = (tempTickTime * 1000) + (xTickCount % 1000); + return tempTickTime; +} + + +// mktime from linux kernel 2.6.30 kernel / time.c +/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. + * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 + * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. + * + * [For the Julian calendar (which was used in Russia before 1917, + * Britain & colonies before 1752, anywhere else before 1582, + * and is still in use by some communities) leave out the + * -year/100+year/400 terms, and add 10.] + * + * This algorithm was first published by Gauss (I think). + * + * WARNING: this function will overflow on 2106-02-07 06:28:16 on + * machines where long is 32-bit! (However, as time_t is signed, we + * will already get problems at other places on 2038-01-19 03:14:08) + */ +portLONG +mktime(const unsigned int year0, const unsigned int mon0, + const unsigned int day, const unsigned int hour, + const unsigned int min, const unsigned int sec) +{ + unsigned int mon = mon0, year = year0; + + /* 1..12 -> 11,12,1..10 */ + if (0 >= (int) (mon -= 2)) { + mon += 12; /* Puts Feb last since it has leap day */ + year -= 1; + } + + return ((((portLONG) + (year/4 - year/100 + year/400 + 367*mon/12 + day) + + year*365 - 719499 + )*24 + hour /* now have hours */ + )*60 + min /* now have minutes */ + )*60 + sec; /* finally seconds */ +} Index: /webserver/example/freeRTOSexample/Source/EnergyMeters/MetersIncludes.h =================================================================== --- /webserver/example/freeRTOSexample/Source/EnergyMeters/MetersIncludes.h (revision 22) +++ /webserver/example/freeRTOSexample/Source/EnergyMeters/MetersIncludes.h (revision 22) @@ -0,0 +1,20 @@ + +void initMeterItems(void); +unsigned long long getEpochTimeWithMs(void); + +#define NUMBER_OF_METERS 10 /* the number of meters we use */ + +#define METER_INDEX_GAS 0 /* index of the gas meter data */ + + +typedef struct +{ + portSHORT meterEnabled; /* 0: item not used, 1: meter enabled */ + unsigned long long timeLastTick; /* when did the last tick occur? epoch time in seconds */ + unsigned long long timeBeforeLastTick; /* when did the tick before the last tick occur? epoch time in seconds */ + portLONG valueLastTick; /* what value did we have at the last tick? */ + portLONG valueBeforeLastTick; /* what value did we have at the tick before the last tick? */ +} meterItem; + +meterItem meterItems[NUMBER_OF_METERS]; /* the data for all the meters */ + Index: /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/RTOSDemo.hzs =================================================================== --- /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/RTOSDemo.hzs (revision 19) +++ /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/RTOSDemo.hzs (revision 22) @@ -45,47 +45,29 @@ - - - - - + - + + + - - - - - - - - - - - - - - + - - - - - - - - - - - - - - + + + + + + + + + + + - + Index: /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/main.c =================================================================== --- /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/main.c (revision 19) +++ /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/main.c (revision 22) @@ -56,13 +56,8 @@ /* Demo app includes. */ -#include "BlockQ.h" -#include "death.h" -#include "integer.h" -#include "blocktim.h" + #include "portlcd.h" #include "flash.h" -#include "partest.h" -#include "semtest.h" -#include "PollQ.h" + /* Demo application definitions. */ @@ -74,9 +69,6 @@ #define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) -#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) -#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainFLASH_PRIORITY ( tskIDLE_PRIORITY + 2 ) -#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) -#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY ) + @@ -134,5 +126,5 @@ // vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); - vStartMetersTask( mainBLOCK_Q_PRIORITY ); + vStartMetersTask( mainFLASH_PRIORITY ); /* Start the standard demo tasks. */ // vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); @@ -181,33 +173,5 @@ /* Has an error been found in any task? */ - if( xAreBlockingQueuesStillRunning() != pdTRUE ) - { - xErrorOccurred = pdTRUE; - } - - if( xAreBlockTimeTestTasksStillRunning() != pdTRUE ) - { - xErrorOccurred = pdTRUE; - } - - if( xAreSemaphoreTasksStillRunning() != pdTRUE ) - { - xErrorOccurred = pdTRUE; - } - - if( xArePollingQueuesStillRunning() != pdTRUE ) - { - xErrorOccurred = pdTRUE; - } - - if( xIsCreateTaskStillRunning() != pdTRUE ) - { - xErrorOccurred = pdTRUE; - } - - if( xAreIntegerMathsTaskStillRunning() != pdTRUE ) - { - xErrorOccurred = pdTRUE; - } + LCD_cls(); Index: /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/RTOSDemo.hzp =================================================================== --- /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/RTOSDemo.hzp (revision 19) +++ /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/RTOSDemo.hzp (revision 22) @@ -11,13 +11,4 @@ - - - - - - - - - @@ -36,9 +27,4 @@ - - - - - @@ -105,4 +91,6 @@ + + Index: /bserver/example/freeRTOSexample/Demo/Common/Minimal/blocktim.c =================================================================== --- /webserver/example/freeRTOSexample/Demo/Common/Minimal/blocktim.c (revision 14) +++ (revision ) @@ -1,487 +1,0 @@ -/* - FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation and modified by the FreeRTOS exception. - **NOTE** The exception to the GPL is included to allow you to distribute a - combined work that includes FreeRTOS without being obliged to provide the - source code for proprietary components outside of the FreeRTOS kernel. - Alternative commercial license and support terms are also available upon - request. See the licensing section of http://www.FreeRTOS.org for full - license details. - - FreeRTOS 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; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - - *************************************************************************** - * * - * Looking for a quick start? Then check out the FreeRTOS eBook! * - * See http://www.FreeRTOS.org/Documentation for details * - * * - *************************************************************************** - - 1 tab == 4 spaces! - - Please ensure to read the configuration and relevant port sections of the - online documentation. - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/* - * This file contains some test scenarios that ensure tasks do not exit queue - * send or receive functions prematurely. A description of the tests is - * included within the code. - */ - -/* Kernel includes. */ -#include "FreeRTOS.h" -#include "task.h" -#include "queue.h" - -/* Demo includes. */ -#include "blocktim.h" - -/* Task priorities. Allow these to be overridden. */ -#ifndef bktPRIMARY_PRIORITY - #define bktPRIMARY_PRIORITY ( 3 ) -#endif - -#ifndef bktSECONDARY_PRIORITY - #define bktSECONDARY_PRIORITY ( 2 ) -#endif - -/* Task behaviour. */ -#define bktQUEUE_LENGTH ( 5 ) -#define bktSHORT_WAIT ( ( ( portTickType ) 20 ) / portTICK_RATE_MS ) -#define bktPRIMARY_BLOCK_TIME ( 10 ) -#define bktALLOWABLE_MARGIN ( 15 ) -#define bktTIME_TO_BLOCK ( 175 ) -#define bktDONT_BLOCK ( ( portTickType ) 0 ) -#define bktRUN_INDICATOR ( ( unsigned portBASE_TYPE ) 0x55 ) - -/* The queue on which the tasks block. */ -static xQueueHandle xTestQueue; - -/* Handle to the secondary task is required by the primary task for calls -to vTaskSuspend/Resume(). */ -static xTaskHandle xSecondary; - -/* Used to ensure that tasks are still executing without error. */ -static volatile portBASE_TYPE xPrimaryCycles = 0, xSecondaryCycles = 0; -static volatile portBASE_TYPE xErrorOccurred = pdFALSE; - -/* Provides a simple mechanism for the primary task to know when the -secondary task has executed. */ -static volatile unsigned portBASE_TYPE xRunIndicator; - -/* The two test tasks. Their behaviour is commented within the files. */ -static void vPrimaryBlockTimeTestTask( void *pvParameters ); -static void vSecondaryBlockTimeTestTask( void *pvParameters ); - -/*-----------------------------------------------------------*/ - -void vCreateBlockTimeTasks( void ) -{ - /* Create the queue on which the two tasks block. */ - xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( portBASE_TYPE ) ); - - /* vQueueAddToRegistry() adds the queue to the queue registry, if one is - in use. The queue registry is provided as a means for kernel aware - debuggers to locate queues and has no purpose if a kernel aware debugger - is not being used. The call to vQueueAddToRegistry() will be removed - by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is - defined to be less than 1. */ - vQueueAddToRegistry( xTestQueue, ( signed portCHAR * ) "Block_Time_Queue" ); - - /* Create the two test tasks. */ - xTaskCreate( vPrimaryBlockTimeTestTask, ( signed portCHAR * )"BTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL ); - xTaskCreate( vSecondaryBlockTimeTestTask, ( signed portCHAR * )"BTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary ); -} -/*-----------------------------------------------------------*/ - -static void vPrimaryBlockTimeTestTask( void *pvParameters ) -{ -portBASE_TYPE xItem, xData; -portTickType xTimeWhenBlocking; -portTickType xTimeToBlock, xBlockedTime; - - ( void ) pvParameters; - - for( ;; ) - { - /********************************************************************* - Test 1 - - Simple block time wakeup test on queue receives. */ - for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) - { - /* The queue is empty. Attempt to read from the queue using a block - time. When we wake, ensure the delta in time is as expected. */ - xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem; - - xTimeWhenBlocking = xTaskGetTickCount(); - - /* We should unblock after xTimeToBlock having not received - anything on the queue. */ - if( xQueueReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY ) - { - xErrorOccurred = pdTRUE; - } - - /* How long were we blocked for? */ - xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; - - if( xBlockedTime < xTimeToBlock ) - { - /* Should not have blocked for less than we requested. */ - xErrorOccurred = pdTRUE; - } - - if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) ) - { - /* Should not have blocked for longer than we requested, - although we would not necessarily run as soon as we were - unblocked so a margin is allowed. */ - xErrorOccurred = pdTRUE; - } - } - - /********************************************************************* - Test 2 - - Simple block time wakeup test on queue sends. - - First fill the queue. It should be empty so all sends should pass. */ - for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) - { - if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) - { - xErrorOccurred = pdTRUE; - } - - #if configUSE_PREEMPTION == 0 - taskYIELD(); - #endif - } - - for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) - { - /* The queue is full. Attempt to write to the queue using a block - time. When we wake, ensure the delta in time is as expected. */ - xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem; - - xTimeWhenBlocking = xTaskGetTickCount(); - - /* We should unblock after xTimeToBlock having not received - anything on the queue. */ - if( xQueueSend( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL ) - { - xErrorOccurred = pdTRUE; - } - - /* How long were we blocked for? */ - xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; - - if( xBlockedTime < xTimeToBlock ) - { - /* Should not have blocked for less than we requested. */ - xErrorOccurred = pdTRUE; - } - - if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) ) - { - /* Should not have blocked for longer than we requested, - although we would not necessarily run as soon as we were - unblocked so a margin is allowed. */ - xErrorOccurred = pdTRUE; - } - } - - /********************************************************************* - Test 3 - - Wake the other task, it will block attempting to post to the queue. - When we read from the queue the other task will wake, but before it - can run we will post to the queue again. When the other task runs it - will find the queue still full, even though it was woken. It should - recognise that its block time has not expired and return to block for - the remains of its block time. - - Wake the other task so it blocks attempting to post to the already - full queue. */ - xRunIndicator = 0; - vTaskResume( xSecondary ); - - /* We need to wait a little to ensure the other task executes. */ - while( xRunIndicator != bktRUN_INDICATOR ) - { - /* The other task has not yet executed. */ - vTaskDelay( bktSHORT_WAIT ); - } - /* Make sure the other task is blocked on the queue. */ - vTaskDelay( bktSHORT_WAIT ); - xRunIndicator = 0; - - for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) - { - /* Now when we make space on the queue the other task should wake - but not execute as this task has higher priority. */ - if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) - { - xErrorOccurred = pdTRUE; - } - - /* Now fill the queue again before the other task gets a chance to - execute. If the other task had executed we would find the queue - full ourselves, and the other task have set xRunIndicator. */ - if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) - { - xErrorOccurred = pdTRUE; - } - - if( xRunIndicator == bktRUN_INDICATOR ) - { - /* The other task should not have executed. */ - xErrorOccurred = pdTRUE; - } - - /* Raise the priority of the other task so it executes and blocks - on the queue again. */ - vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 ); - - /* The other task should now have re-blocked without exiting the - queue function. */ - if( xRunIndicator == bktRUN_INDICATOR ) - { - /* The other task should not have executed outside of the - queue function. */ - xErrorOccurred = pdTRUE; - } - - /* Set the priority back down. */ - vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); - } - - /* Let the other task timeout. When it unblockes it will check that it - unblocked at the correct time, then suspend itself. */ - while( xRunIndicator != bktRUN_INDICATOR ) - { - vTaskDelay( bktSHORT_WAIT ); - } - vTaskDelay( bktSHORT_WAIT ); - xRunIndicator = 0; - - - /********************************************************************* - Test 4 - - As per test 3 - but with the send and receive the other way around. - The other task blocks attempting to read from the queue. - - Empty the queue. We should find that it is full. */ - for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) - { - if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) - { - xErrorOccurred = pdTRUE; - } - } - - /* Wake the other task so it blocks attempting to read from the - already empty queue. */ - vTaskResume( xSecondary ); - - /* We need to wait a little to ensure the other task executes. */ - while( xRunIndicator != bktRUN_INDICATOR ) - { - vTaskDelay( bktSHORT_WAIT ); - } - vTaskDelay( bktSHORT_WAIT ); - xRunIndicator = 0; - - for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) - { - /* Now when we place an item on the queue the other task should - wake but not execute as this task has higher priority. */ - if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) - { - xErrorOccurred = pdTRUE; - } - - /* Now empty the queue again before the other task gets a chance to - execute. If the other task had executed we would find the queue - empty ourselves, and the other task would be suspended. */ - if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) - { - xErrorOccurred = pdTRUE; - } - - if( xRunIndicator == bktRUN_INDICATOR ) - { - /* The other task should not have executed. */ - xErrorOccurred = pdTRUE; - } - - /* Raise the priority of the other task so it executes and blocks - on the queue again. */ - vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 ); - - /* The other task should now have re-blocked without exiting the - queue function. */ - if( xRunIndicator == bktRUN_INDICATOR ) - { - /* The other task should not have executed outside of the - queue function. */ - xErrorOccurred = pdTRUE; - } - vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); - } - - /* Let the other task timeout. When it unblockes it will check that it - unblocked at the correct time, then suspend itself. */ - while( xRunIndicator != bktRUN_INDICATOR ) - { - vTaskDelay( bktSHORT_WAIT ); - } - vTaskDelay( bktSHORT_WAIT ); - - xPrimaryCycles++; - } -} -/*-----------------------------------------------------------*/ - -static void vSecondaryBlockTimeTestTask( void *pvParameters ) -{ -portTickType xTimeWhenBlocking, xBlockedTime; -portBASE_TYPE xData; - - ( void ) pvParameters; - - for( ;; ) - { - /********************************************************************* - Test 1 and 2 - - This task does does not participate in these tests. */ - vTaskSuspend( NULL ); - - /********************************************************************* - Test 3 - - The first thing we do is attempt to read from the queue. It should be - full so we block. Note the time before we block so we can check the - wake time is as per that expected. */ - xTimeWhenBlocking = xTaskGetTickCount(); - - /* We should unblock after bktTIME_TO_BLOCK having not sent - anything to the queue. */ - xData = 0; - xRunIndicator = bktRUN_INDICATOR; - if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL ) - { - xErrorOccurred = pdTRUE; - } - - /* How long were we inside the send function? */ - xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; - - /* We should not have blocked for less time than bktTIME_TO_BLOCK. */ - if( xBlockedTime < bktTIME_TO_BLOCK ) - { - xErrorOccurred = pdTRUE; - } - - /* We should of not blocked for much longer than bktALLOWABLE_MARGIN - either. A margin is permitted as we would not necessarily run as - soon as we unblocked. */ - if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) ) - { - xErrorOccurred = pdTRUE; - } - - /* Suspend ready for test 3. */ - xRunIndicator = bktRUN_INDICATOR; - vTaskSuspend( NULL ); - - /********************************************************************* - Test 4 - - As per test three, but with the send and receive reversed. */ - xTimeWhenBlocking = xTaskGetTickCount(); - - /* We should unblock after bktTIME_TO_BLOCK having not received - anything on the queue. */ - xRunIndicator = bktRUN_INDICATOR; - if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY ) - { - xErrorOccurred = pdTRUE; - } - - xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; - - /* We should not have blocked for less time than bktTIME_TO_BLOCK. */ - if( xBlockedTime < bktTIME_TO_BLOCK ) - { - xErrorOccurred = pdTRUE; - } - - /* We should of not blocked for much longer than bktALLOWABLE_MARGIN - either. A margin is permitted as we would not necessarily run as soon - as we unblocked. */ - if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) ) - { - xErrorOccurred = pdTRUE; - } - - xRunIndicator = bktRUN_INDICATOR; - - xSecondaryCycles++; - } -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xAreBlockTimeTestTasksStillRunning( void ) -{ -static portBASE_TYPE xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0; -portBASE_TYPE xReturn = pdPASS; - - /* Have both tasks performed at least one cycle since this function was - last called? */ - if( xPrimaryCycles == xLastPrimaryCycleCount ) - { - xReturn = pdFAIL; - } - - if( xSecondaryCycles == xLastSecondaryCycleCount ) - { - xReturn = pdFAIL; - } - - if( xErrorOccurred == pdTRUE ) - { - xReturn = pdFAIL; - } - - xLastSecondaryCycleCount = xSecondaryCycles; - xLastPrimaryCycleCount = xPrimaryCycles; - - return xReturn; -} Index: /bserver/example/freeRTOSexample/Demo/Common/Minimal/BlockQ.c =================================================================== --- /webserver/example/freeRTOSexample/Demo/Common/Minimal/BlockQ.c (revision 14) +++ (revision ) @@ -1,302 +1,0 @@ -/* - FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation and modified by the FreeRTOS exception. - **NOTE** The exception to the GPL is included to allow you to distribute a - combined work that includes FreeRTOS without being obliged to provide the - source code for proprietary components outside of the FreeRTOS kernel. - Alternative commercial license and support terms are also available upon - request. See the licensing section of http://www.FreeRTOS.org for full - license details. - - FreeRTOS 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; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - - *************************************************************************** - * * - * Looking for a quick start? Then check out the FreeRTOS eBook! * - * See http://www.FreeRTOS.org/Documentation for details * - * * - *************************************************************************** - - 1 tab == 4 spaces! - - Please ensure to read the configuration and relevant port sections of the - online documentation. - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/* - * Creates six tasks that operate on three queues as follows: - * - * The first two tasks send and receive an incrementing number to/from a queue. - * One task acts as a producer and the other as the consumer. The consumer is a - * higher priority than the producer and is set to block on queue reads. The queue - * only has space for one item - as soon as the producer posts a message on the - * queue the consumer will unblock, pre-empt the producer, and remove the item. - * - * The second two tasks work the other way around. Again the queue used only has - * enough space for one item. This time the consumer has a lower priority than the - * producer. The producer will try to post on the queue blocking when the queue is - * full. When the consumer wakes it will remove the item from the queue, causing - * the producer to unblock, pre-empt the consumer, and immediately re-fill the - * queue. - * - * The last two tasks use the same queue producer and consumer functions. This time the queue has - * enough space for lots of items and the tasks operate at the same priority. The - * producer will execute, placing items into the queue. The consumer will start - * executing when either the queue becomes full (causing the producer to block) or - * a context switch occurs (tasks of the same priority will time slice). - * - */ - -/* - -Changes from V4.1.1 - - + The second set of tasks were created the wrong way around. This has been - corrected. -*/ - - -#include - -/* Scheduler include files. */ -#include "FreeRTOS.h" -#include "task.h" -#include "queue.h" - -/* Demo program include files. */ -#include "BlockQ.h" - -#define blckqSTACK_SIZE configMINIMAL_STACK_SIZE -#define blckqNUM_TASK_SETS ( 3 ) - -/* Structure used to pass parameters to the blocking queue tasks. */ -typedef struct BLOCKING_QUEUE_PARAMETERS -{ - xQueueHandle xQueue; /*< The queue to be used by the task. */ - portTickType xBlockTime; /*< The block time to use on queue reads/writes. */ - volatile portSHORT *psCheckVariable; /*< Incremented on each successful cycle to check the task is still running. */ -} xBlockingQueueParameters; - -/* Task function that creates an incrementing number and posts it on a queue. */ -static portTASK_FUNCTION_PROTO( vBlockingQueueProducer, pvParameters ); - -/* Task function that removes the incrementing number from a queue and checks that -it is the expected number. */ -static portTASK_FUNCTION_PROTO( vBlockingQueueConsumer, pvParameters ); - -/* Variables which are incremented each time an item is removed from a queue, and -found to be the expected value. -These are used to check that the tasks are still running. */ -static volatile portSHORT sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 }; - -/* Variable which are incremented each time an item is posted on a queue. These -are used to check that the tasks are still running. */ -static volatile portSHORT sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 }; - -/*-----------------------------------------------------------*/ - -void vStartBlockingQueueTasks( unsigned portBASE_TYPE uxPriority ) -{ -xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2; -xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4; -xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6; -const unsigned portBASE_TYPE uxQueueSize1 = 1, uxQueueSize5 = 5; -const portTickType xBlockTime = ( portTickType ) 1000 / portTICK_RATE_MS; -const portTickType xDontBlock = ( portTickType ) 0; - - /* Create the first two tasks as described at the top of the file. */ - - /* First create the structure used to pass parameters to the consumer tasks. */ - pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); - - /* Create the queue used by the first two tasks to pass the incrementing number. - Pass a pointer to the queue in the parameter structure. */ - pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) ); - - /* The consumer is created first so gets a block time as described above. */ - pxQueueParameters1->xBlockTime = xBlockTime; - - /* Pass in the variable that this task is going to increment so we can check it - is still running. */ - pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] ); - - /* Create the structure used to pass parameters to the producer task. */ - pxQueueParameters2 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); - - /* Pass the queue to this task also, using the parameter structure. */ - pxQueueParameters2->xQueue = pxQueueParameters1->xQueue; - - /* The producer is not going to block - as soon as it posts the consumer will - wake and remove the item so the producer should always have room to post. */ - pxQueueParameters2->xBlockTime = xDontBlock; - - /* Pass in the variable that this task is going to increment so we can check - it is still running. */ - pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] ); - - - /* Note the producer has a lower priority than the consumer when the tasks are - spawned. */ - xTaskCreate( vBlockingQueueConsumer, ( signed portCHAR * ) "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL ); - xTaskCreate( vBlockingQueueProducer, ( signed portCHAR * ) "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL ); - - - - /* Create the second two tasks as described at the top of the file. This uses - the same mechanism but reverses the task priorities. */ - - pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); - pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) ); - pxQueueParameters3->xBlockTime = xDontBlock; - pxQueueParameters3->psCheckVariable = &( sBlockingProducerCount[ 1 ] ); - - pxQueueParameters4 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); - pxQueueParameters4->xQueue = pxQueueParameters3->xQueue; - pxQueueParameters4->xBlockTime = xBlockTime; - pxQueueParameters4->psCheckVariable = &( sBlockingConsumerCount[ 1 ] ); - - xTaskCreate( vBlockingQueueConsumer, ( signed portCHAR * ) "QProdB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL ); - xTaskCreate( vBlockingQueueProducer, ( signed portCHAR * ) "QConsB4", blckqSTACK_SIZE, ( void * ) pxQueueParameters4, uxPriority, NULL ); - - - - /* Create the last two tasks as described above. The mechanism is again just - the same. This time both parameter structures are given a block time. */ - pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); - pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) ); - pxQueueParameters5->xBlockTime = xBlockTime; - pxQueueParameters5->psCheckVariable = &( sBlockingProducerCount[ 2 ] ); - - pxQueueParameters6 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); - pxQueueParameters6->xQueue = pxQueueParameters5->xQueue; - pxQueueParameters6->xBlockTime = xBlockTime; - pxQueueParameters6->psCheckVariable = &( sBlockingConsumerCount[ 2 ] ); - - xTaskCreate( vBlockingQueueProducer, ( signed portCHAR * ) "QProdB5", blckqSTACK_SIZE, ( void * ) pxQueueParameters5, tskIDLE_PRIORITY, NULL ); - xTaskCreate( vBlockingQueueConsumer, ( signed portCHAR * ) "QConsB6", blckqSTACK_SIZE, ( void * ) pxQueueParameters6, tskIDLE_PRIORITY, NULL ); -} -/*-----------------------------------------------------------*/ - -static portTASK_FUNCTION( vBlockingQueueProducer, pvParameters ) -{ -unsigned portSHORT usValue = 0; -xBlockingQueueParameters *pxQueueParameters; -portSHORT sErrorEverOccurred = pdFALSE; - - pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; - - for( ;; ) - { - if( xQueueSend( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS ) - { - sErrorEverOccurred = pdTRUE; - } - else - { - /* We have successfully posted a message, so increment the variable - used to check we are still running. */ - if( sErrorEverOccurred == pdFALSE ) - { - ( *pxQueueParameters->psCheckVariable )++; - } - - /* Increment the variable we are going to post next time round. The - consumer will expect the numbers to follow in numerical order. */ - ++usValue; - } - } -} -/*-----------------------------------------------------------*/ - -static portTASK_FUNCTION( vBlockingQueueConsumer, pvParameters ) -{ -unsigned portSHORT usData, usExpectedValue = 0; -xBlockingQueueParameters *pxQueueParameters; -portSHORT sErrorEverOccurred = pdFALSE; - - pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; - - for( ;; ) - { - if( xQueueReceive( pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime ) == pdPASS ) - { - if( usData != usExpectedValue ) - { - /* Catch-up. */ - usExpectedValue = usData; - - sErrorEverOccurred = pdTRUE; - } - else - { - /* We have successfully received a message, so increment the - variable used to check we are still running. */ - if( sErrorEverOccurred == pdFALSE ) - { - ( *pxQueueParameters->psCheckVariable )++; - } - - /* Increment the value we expect to remove from the queue next time - round. */ - ++usExpectedValue; - } - } - } -} -/*-----------------------------------------------------------*/ - -/* This is called to check that all the created tasks are still running. */ -portBASE_TYPE xAreBlockingQueuesStillRunning( void ) -{ -static portSHORT sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 }; -static portSHORT sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 }; -portBASE_TYPE xReturn = pdPASS, xTasks; - - /* Not too worried about mutual exclusion on these variables as they are 16 - bits and we are only reading them. We also only care to see if they have - changed or not. - - Loop through each check variable to and return pdFALSE if any are found not - to have changed since the last call. */ - - for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ ) - { - if( sBlockingConsumerCount[ xTasks ] == sLastBlockingConsumerCount[ xTasks ] ) - { - xReturn = pdFALSE; - } - sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ]; - - - if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] ) - { - xReturn = pdFALSE; - } - sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ]; - } - - return xReturn; -} - Index: /bserver/example/freeRTOSexample/Demo/Common/Minimal/semtest.c =================================================================== --- /webserver/example/freeRTOSexample/Demo/Common/Minimal/semtest.c (revision 14) +++ (revision ) @@ -1,278 +1,0 @@ -/* - FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation and modified by the FreeRTOS exception. - **NOTE** The exception to the GPL is included to allow you to distribute a - combined work that includes FreeRTOS without being obliged to provide the - source code for proprietary components outside of the FreeRTOS kernel. - Alternative commercial license and support terms are also available upon - request. See the licensing section of http://www.FreeRTOS.org for full - license details. - - FreeRTOS 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; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - - *************************************************************************** - * * - * Looking for a quick start? Then check out the FreeRTOS eBook! * - * See http://www.FreeRTOS.org/Documentation for details * - * * - *************************************************************************** - - 1 tab == 4 spaces! - - Please ensure to read the configuration and relevant port sections of the - online documentation. - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/* - * Creates two sets of two tasks. The tasks within a set share a variable, access - * to which is guarded by a semaphore. - * - * Each task starts by attempting to obtain the semaphore. On obtaining a - * semaphore a task checks to ensure that the guarded variable has an expected - * value. It then clears the variable to zero before counting it back up to the - * expected value in increments of 1. After each increment the variable is checked - * to ensure it contains the value to which it was just set. When the starting - * value is again reached the task releases the semaphore giving the other task in - * the set a chance to do exactly the same thing. The starting value is high - * enough to ensure that a tick is likely to occur during the incrementing loop. - * - * An error is flagged if at any time during the process a shared variable is - * found to have a value other than that expected. Such an occurrence would - * suggest an error in the mutual exclusion mechanism by which access to the - * variable is restricted. - * - * The first set of two tasks poll their semaphore. The second set use blocking - * calls. - * - */ - - -#include - -/* Scheduler include files. */ -#include "FreeRTOS.h" -#include "task.h" -#include "semphr.h" - -/* Demo app include files. */ -#include "semtest.h" - -/* The value to which the shared variables are counted. */ -#define semtstBLOCKING_EXPECTED_VALUE ( ( unsigned portLONG ) 0xfff ) -#define semtstNON_BLOCKING_EXPECTED_VALUE ( ( unsigned portLONG ) 0xff ) - -#define semtstSTACK_SIZE configMINIMAL_STACK_SIZE - -#define semtstNUM_TASKS ( 4 ) - -#define semtstDELAY_FACTOR ( ( portTickType ) 10 ) - -/* The task function as described at the top of the file. */ -static portTASK_FUNCTION_PROTO( prvSemaphoreTest, pvParameters ); - -/* Structure used to pass parameters to each task. */ -typedef struct SEMAPHORE_PARAMETERS -{ - xSemaphoreHandle xSemaphore; - volatile unsigned portLONG *pulSharedVariable; - portTickType xBlockTime; -} xSemaphoreParameters; - -/* Variables used to check that all the tasks are still running without errors. */ -static volatile portSHORT sCheckVariables[ semtstNUM_TASKS ] = { 0 }; -static volatile portSHORT sNextCheckVariable = 0; - -/*-----------------------------------------------------------*/ - -void vStartSemaphoreTasks( unsigned portBASE_TYPE uxPriority ) -{ -xSemaphoreParameters *pxFirstSemaphoreParameters, *pxSecondSemaphoreParameters; -const portTickType xBlockTime = ( portTickType ) 100; - - /* Create the structure used to pass parameters to the first two tasks. */ - pxFirstSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) ); - - if( pxFirstSemaphoreParameters != NULL ) - { - /* Create the semaphore used by the first two tasks. */ - vSemaphoreCreateBinary( pxFirstSemaphoreParameters->xSemaphore ); - - if( pxFirstSemaphoreParameters->xSemaphore != NULL ) - { - /* Create the variable which is to be shared by the first two tasks. */ - pxFirstSemaphoreParameters->pulSharedVariable = ( unsigned portLONG * ) pvPortMalloc( sizeof( unsigned portLONG ) ); - - /* Initialise the share variable to the value the tasks expect. */ - *( pxFirstSemaphoreParameters->pulSharedVariable ) = semtstNON_BLOCKING_EXPECTED_VALUE; - - /* The first two tasks do not block on semaphore calls. */ - pxFirstSemaphoreParameters->xBlockTime = ( portTickType ) 0; - - /* Spawn the first two tasks. As they poll they operate at the idle priority. */ - xTaskCreate( prvSemaphoreTest, ( signed portCHAR * ) "PolSEM1", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL ); - xTaskCreate( prvSemaphoreTest, ( signed portCHAR * ) "PolSEM2", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL ); - } - } - - /* Do exactly the same to create the second set of tasks, only this time - provide a block time for the semaphore calls. */ - pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) ); - if( pxSecondSemaphoreParameters != NULL ) - { - vSemaphoreCreateBinary( pxSecondSemaphoreParameters->xSemaphore ); - - if( pxSecondSemaphoreParameters->xSemaphore != NULL ) - { - pxSecondSemaphoreParameters->pulSharedVariable = ( unsigned portLONG * ) pvPortMalloc( sizeof( unsigned portLONG ) ); - *( pxSecondSemaphoreParameters->pulSharedVariable ) = semtstBLOCKING_EXPECTED_VALUE; - pxSecondSemaphoreParameters->xBlockTime = xBlockTime / portTICK_RATE_MS; - - xTaskCreate( prvSemaphoreTest, ( signed portCHAR * ) "BlkSEM1", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( xTaskHandle * ) NULL ); - xTaskCreate( prvSemaphoreTest, ( signed portCHAR * ) "BlkSEM2", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( xTaskHandle * ) NULL ); - } - } - - /* vQueueAddToRegistry() adds the semaphore to the registry, if one is - in use. The registry is provided as a means for kernel aware - debuggers to locate semaphores and has no purpose if a kernel aware debugger - is not being used. The call to vQueueAddToRegistry() will be removed - by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is - defined to be less than 1. */ - vQueueAddToRegistry( ( xQueueHandle ) pxFirstSemaphoreParameters->xSemaphore, ( signed portCHAR * ) "Counting_Sem_1" ); - vQueueAddToRegistry( ( xQueueHandle ) pxSecondSemaphoreParameters->xSemaphore, ( signed portCHAR * ) "Counting_Sem_2" ); -} -/*-----------------------------------------------------------*/ - -static portTASK_FUNCTION( prvSemaphoreTest, pvParameters ) -{ -xSemaphoreParameters *pxParameters; -volatile unsigned portLONG *pulSharedVariable, ulExpectedValue; -unsigned portLONG ulCounter; -portSHORT sError = pdFALSE, sCheckVariableToUse; - - /* See which check variable to use. sNextCheckVariable is not semaphore - protected! */ - portENTER_CRITICAL(); - sCheckVariableToUse = sNextCheckVariable; - sNextCheckVariable++; - portEXIT_CRITICAL(); - - /* A structure is passed in as the parameter. This contains the shared - variable being guarded. */ - pxParameters = ( xSemaphoreParameters * ) pvParameters; - pulSharedVariable = pxParameters->pulSharedVariable; - - /* If we are blocking we use a much higher count to ensure loads of context - switches occur during the count. */ - if( pxParameters->xBlockTime > ( portTickType ) 0 ) - { - ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE; - } - else - { - ulExpectedValue = semtstNON_BLOCKING_EXPECTED_VALUE; - } - - for( ;; ) - { - /* Try to obtain the semaphore. */ - if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS ) - { - /* We have the semaphore and so expect any other tasks using the - shared variable to have left it in the state we expect to find - it. */ - if( *pulSharedVariable != ulExpectedValue ) - { - sError = pdTRUE; - } - - /* Clear the variable, then count it back up to the expected value - before releasing the semaphore. Would expect a context switch or - two during this time. */ - for( ulCounter = ( unsigned portLONG ) 0; ulCounter <= ulExpectedValue; ulCounter++ ) - { - *pulSharedVariable = ulCounter; - if( *pulSharedVariable != ulCounter ) - { - sError = pdTRUE; - } - } - - /* Release the semaphore, and if no errors have occurred increment the check - variable. */ - if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE ) - { - sError = pdTRUE; - } - - if( sError == pdFALSE ) - { - if( sCheckVariableToUse < semtstNUM_TASKS ) - { - ( sCheckVariables[ sCheckVariableToUse ] )++; - } - } - - /* If we have a block time then we are running at a priority higher - than the idle priority. This task takes a long time to complete - a cycle (deliberately so to test the guarding) so will be starving - out lower priority tasks. Block for some time to allow give lower - priority tasks some processor time. */ - vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR ); - } - else - { - if( pxParameters->xBlockTime == ( portTickType ) 0 ) - { - /* We have not got the semaphore yet, so no point using the - processor. We are not blocking when attempting to obtain the - semaphore. */ - taskYIELD(); - } - } - } -} -/*-----------------------------------------------------------*/ - -/* This is called to check that all the created tasks are still running. */ -portBASE_TYPE xAreSemaphoreTasksStillRunning( void ) -{ -static portSHORT sLastCheckVariables[ semtstNUM_TASKS ] = { 0 }; -portBASE_TYPE xTask, xReturn = pdTRUE; - - for( xTask = 0; xTask < semtstNUM_TASKS; xTask++ ) - { - if( sLastCheckVariables[ xTask ] == sCheckVariables[ xTask ] ) - { - xReturn = pdFALSE; - } - - sLastCheckVariables[ xTask ] = sCheckVariables[ xTask ]; - } - - return xReturn; -} - - Index: /bserver/example/freeRTOSexample/Demo/Common/Minimal/death.c =================================================================== --- /webserver/example/freeRTOSexample/Demo/Common/Minimal/death.c (revision 14) +++ (revision ) @@ -1,242 +1,0 @@ -/* - FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation and modified by the FreeRTOS exception. - **NOTE** The exception to the GPL is included to allow you to distribute a - combined work that includes FreeRTOS without being obliged to provide the - source code for proprietary components outside of the FreeRTOS kernel. - Alternative commercial license and support terms are also available upon - request. See the licensing section of http://www.FreeRTOS.org for full - license details. - - FreeRTOS 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; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - - *************************************************************************** - * * - * Looking for a quick start? Then check out the FreeRTOS eBook! * - * See http://www.FreeRTOS.org/Documentation for details * - * * - *************************************************************************** - - 1 tab == 4 spaces! - - Please ensure to read the configuration and relevant port sections of the - online documentation. - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/** - * Create a single persistent task which periodically dynamically creates another - * two tasks. The original task is called the creator task, the two tasks it - * creates are called suicidal tasks. - * - * One of the created suicidal tasks kill one other suicidal task before killing - * itself - leaving just the original task remaining. - * - * The creator task must be spawned after all of the other demo application tasks - * as it keeps a check on the number of tasks under the scheduler control. The - * number of tasks it expects to see running should never be greater than the - * number of tasks that were in existence when the creator task was spawned, plus - * one set of four suicidal tasks. If this number is exceeded an error is flagged. - * - * \page DeathC death.c - * \ingroup DemoFiles - *
- */ - -/* -Changes from V3.0.0 - + CreationCount sizes changed from unsigned portBASE_TYPE to - unsigned portSHORT to minimize the risk of overflowing. - - + Reset of usLastCreationCount added - -Changes from V3.1.0 - + Changed the dummy calculation to use variables of type long, rather than - float. This allows the file to be used with ports that do not support - floating point. - -*/ - -#include - -/* Scheduler include files. */ -#include "FreeRTOS.h" -#include "task.h" - -/* Demo program include files. */ -#include "death.h" - -#define deathSTACK_SIZE ( configMINIMAL_STACK_SIZE + 60 ) - -/* The task originally created which is responsible for periodically dynamically -creating another four tasks. */ -static portTASK_FUNCTION_PROTO( vCreateTasks, pvParameters ); - -/* The task function of the dynamically created tasks. */ -static portTASK_FUNCTION_PROTO( vSuicidalTask, pvParameters ); - -/* A variable which is incremented every time the dynamic tasks are created. This -is used to check that the task is still running. */ -static volatile unsigned portSHORT usCreationCount = 0; - -/* Used to store the number of tasks that were originally running so the creator -task can tell if any of the suicidal tasks have failed to die. -*/ -static volatile unsigned portBASE_TYPE uxTasksRunningAtStart = 0; - -/* Tasks are deleted by the idle task. Under heavy load the idle task might -not get much processing time, so it would be legitimate for several tasks to -remain undeleted for a short period. */ -static const unsigned portBASE_TYPE uxMaxNumberOfExtraTasksRunning = 2; - -/* Used to store a handle to the task that should be killed by a suicidal task, -before it kills itself. */ -xTaskHandle xCreatedTask; - -/*-----------------------------------------------------------*/ - -void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority ) -{ -unsigned portBASE_TYPE *puxPriority; - - /* Create the Creator tasks - passing in as a parameter the priority at which - the suicidal tasks should be created. */ - puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) ); - *puxPriority = uxPriority; - - xTaskCreate( vCreateTasks, ( signed portCHAR * ) "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL ); - - /* Record the number of tasks that are running now so we know if any of the - suicidal tasks have failed to be killed. */ - uxTasksRunningAtStart = ( unsigned portBASE_TYPE ) uxTaskGetNumberOfTasks(); - - /* FreeRTOS.org versions before V3.0 started the idle-task as the very - first task. The idle task was then already included in uxTasksRunningAtStart. - From FreeRTOS V3.0 on, the idle task is started when the scheduler is - started. Therefore the idle task is not yet accounted for. We correct - this by increasing uxTasksRunningAtStart by 1. */ - uxTasksRunningAtStart++; -} -/*-----------------------------------------------------------*/ - -static portTASK_FUNCTION( vSuicidalTask, pvParameters ) -{ -volatile portLONG l1, l2; -xTaskHandle xTaskToKill; -const portTickType xDelay = ( portTickType ) 200 / portTICK_RATE_MS; - - if( pvParameters != NULL ) - { - /* This task is periodically created four times. Two created tasks are - passed a handle to the other task so it can kill it before killing itself. - The other task is passed in null. */ - xTaskToKill = *( xTaskHandle* )pvParameters; - } - else - { - xTaskToKill = NULL; - } - - for( ;; ) - { - /* Do something random just to use some stack and registers. */ - l1 = 2; - l2 = 89; - l2 *= l1; - vTaskDelay( xDelay ); - - if( xTaskToKill != NULL ) - { - /* Make sure the other task has a go before we delete it. */ - vTaskDelay( ( portTickType ) 0 ); - - /* Kill the other task that was created by vCreateTasks(). */ - vTaskDelete( xTaskToKill ); - - /* Kill ourselves. */ - vTaskDelete( NULL ); - } - } -}/*lint !e818 !e550 Function prototype must be as per standard for task functions. */ -/*-----------------------------------------------------------*/ - -static portTASK_FUNCTION( vCreateTasks, pvParameters ) -{ -const portTickType xDelay = ( portTickType ) 1000 / portTICK_RATE_MS; -unsigned portBASE_TYPE uxPriority; - - uxPriority = *( unsigned portBASE_TYPE * ) pvParameters; - vPortFree( pvParameters ); - - for( ;; ) - { - /* Just loop round, delaying then creating the four suicidal tasks. */ - vTaskDelay( xDelay ); - - xCreatedTask = NULL; - - xTaskCreate( vSuicidalTask, ( signed portCHAR * ) "SUICID1", configMINIMAL_STACK_SIZE, NULL, uxPriority, &xCreatedTask ); - xTaskCreate( vSuicidalTask, ( signed portCHAR * ) "SUICID2", configMINIMAL_STACK_SIZE, &xCreatedTask, uxPriority, NULL ); - - ++usCreationCount; - } -} -/*-----------------------------------------------------------*/ - -/* This is called to check that the creator task is still running and that there -are not any more than four extra tasks. */ -portBASE_TYPE xIsCreateTaskStillRunning( void ) -{ -static unsigned portSHORT usLastCreationCount = 0xfff; -portBASE_TYPE xReturn = pdTRUE; -static unsigned portBASE_TYPE uxTasksRunningNow; - - if( usLastCreationCount == usCreationCount ) - { - xReturn = pdFALSE; - } - else - { - usLastCreationCount = usCreationCount; - } - - uxTasksRunningNow = ( unsigned portBASE_TYPE ) uxTaskGetNumberOfTasks(); - - if( uxTasksRunningNow < uxTasksRunningAtStart ) - { - xReturn = pdFALSE; - } - else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning ) - { - xReturn = pdFALSE; - } - else - { - /* Everything is okay. */ - } - - return xReturn; -} - - Index: /bserver/example/freeRTOSexample/Demo/Common/Minimal/PollQ.c =================================================================== --- /webserver/example/freeRTOSexample/Demo/Common/Minimal/PollQ.c (revision 14) +++ (revision ) @@ -1,240 +1,0 @@ -/* - FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation and modified by the FreeRTOS exception. - **NOTE** The exception to the GPL is included to allow you to distribute a - combined work that includes FreeRTOS without being obliged to provide the - source code for proprietary components outside of the FreeRTOS kernel. - Alternative commercial license and support terms are also available upon - request. See the licensing section of http://www.FreeRTOS.org for full - license details. - - FreeRTOS 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; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - - *************************************************************************** - * * - * Looking for a quick start? Then check out the FreeRTOS eBook! * - * See http://www.FreeRTOS.org/Documentation for details * - * * - *************************************************************************** - - 1 tab == 4 spaces! - - Please ensure to read the configuration and relevant port sections of the - online documentation. - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/* - * This version of PollQ. c is for use on systems that have limited stack - * space and no display facilities. The complete version can be found in - * the Demo/Common/Full directory. - * - * Creates two tasks that communicate over a single queue. One task acts as a - * producer, the other a consumer. - * - * The producer loops for three iteration, posting an incrementing number onto the - * queue each cycle. It then delays for a fixed period before doing exactly the - * same again. - * - * The consumer loops emptying the queue. Each item removed from the queue is - * checked to ensure it contains the expected value. When the queue is empty it - * blocks for a fixed period, then does the same again. - * - * All queue access is performed without blocking. The consumer completely empties - * the queue each time it runs so the producer should never find the queue full. - * - * An error is flagged if the consumer obtains an unexpected value or the producer - * find the queue is full. - */ - -/* -Changes from V2.0.0 - - + Delay periods are now specified using variables and constants of - portTickType rather than unsigned portLONG. -*/ - -#include - -/* Scheduler include files. */ -#include "FreeRTOS.h" -#include "task.h" -#include "queue.h" - -/* Demo program include files. */ -#include "PollQ.h" - -#define pollqSTACK_SIZE configMINIMAL_STACK_SIZE -#define pollqQUEUE_SIZE ( 10 ) -#define pollqPRODUCER_DELAY ( ( portTickType ) 200 / portTICK_RATE_MS ) -#define pollqCONSUMER_DELAY ( pollqPRODUCER_DELAY - ( portTickType ) ( 20 / portTICK_RATE_MS ) ) -#define pollqNO_DELAY ( ( portTickType ) 0 ) -#define pollqVALUES_TO_PRODUCE ( ( signed portBASE_TYPE ) 3 ) -#define pollqINITIAL_VALUE ( ( signed portBASE_TYPE ) 0 ) - -/* The task that posts the incrementing number onto the queue. */ -static portTASK_FUNCTION_PROTO( vPolledQueueProducer, pvParameters ); - -/* The task that empties the queue. */ -static portTASK_FUNCTION_PROTO( vPolledQueueConsumer, pvParameters ); - -/* Variables that are used to check that the tasks are still running with no -errors. */ -static volatile signed portBASE_TYPE xPollingConsumerCount = pollqINITIAL_VALUE, xPollingProducerCount = pollqINITIAL_VALUE; - -/*-----------------------------------------------------------*/ - -void vStartPolledQueueTasks( unsigned portBASE_TYPE uxPriority ) -{ -static xQueueHandle xPolledQueue; - - /* Create the queue used by the producer and consumer. */ - xPolledQueue = xQueueCreate( pollqQUEUE_SIZE, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) ); - - /* vQueueAddToRegistry() adds the queue to the queue registry, if one is - in use. The queue registry is provided as a means for kernel aware - debuggers to locate queues and has no purpose if a kernel aware debugger - is not being used. The call to vQueueAddToRegistry() will be removed - by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is - defined to be less than 1. */ - vQueueAddToRegistry( xPolledQueue, ( signed portCHAR * ) "Poll_Test_Queue" ); - - /* Spawn the producer and consumer. */ - xTaskCreate( vPolledQueueConsumer, ( signed portCHAR * ) "QConsNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( xTaskHandle * ) NULL ); - xTaskCreate( vPolledQueueProducer, ( signed portCHAR * ) "QProdNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( xTaskHandle * ) NULL ); -} -/*-----------------------------------------------------------*/ - -static portTASK_FUNCTION( vPolledQueueProducer, pvParameters ) -{ -unsigned portSHORT usValue = ( unsigned portSHORT ) 0; -signed portBASE_TYPE xError = pdFALSE, xLoop; - - for( ;; ) - { - for( xLoop = 0; xLoop < pollqVALUES_TO_PRODUCE; xLoop++ ) - { - /* Send an incrementing number on the queue without blocking. */ - if( xQueueSend( *( ( xQueueHandle * ) pvParameters ), ( void * ) &usValue, pollqNO_DELAY ) != pdPASS ) - { - /* We should never find the queue full so if we get here there - has been an error. */ - xError = pdTRUE; - } - else - { - if( xError == pdFALSE ) - { - /* If an error has ever been recorded we stop incrementing the - check variable. */ - portENTER_CRITICAL(); - xPollingProducerCount++; - portEXIT_CRITICAL(); - } - - /* Update the value we are going to post next time around. */ - usValue++; - } - } - - /* Wait before we start posting again to ensure the consumer runs and - empties the queue. */ - vTaskDelay( pollqPRODUCER_DELAY ); - } -} /*lint !e818 Function prototype must conform to API. */ -/*-----------------------------------------------------------*/ - -static portTASK_FUNCTION( vPolledQueueConsumer, pvParameters ) -{ -unsigned portSHORT usData, usExpectedValue = ( unsigned portSHORT ) 0; -signed portBASE_TYPE xError = pdFALSE; - - for( ;; ) - { - /* Loop until the queue is empty. */ - while( uxQueueMessagesWaiting( *( ( xQueueHandle * ) pvParameters ) ) ) - { - if( xQueueReceive( *( ( xQueueHandle * ) pvParameters ), &usData, pollqNO_DELAY ) == pdPASS ) - { - if( usData != usExpectedValue ) - { - /* This is not what we expected to receive so an error has - occurred. */ - xError = pdTRUE; - - /* Catch-up to the value we received so our next expected - value should again be correct. */ - usExpectedValue = usData; - } - else - { - if( xError == pdFALSE ) - { - /* Only increment the check variable if no errors have - occurred. */ - portENTER_CRITICAL(); - xPollingConsumerCount++; - portEXIT_CRITICAL(); - } - } - - /* Next time round we would expect the number to be one higher. */ - usExpectedValue++; - } - } - - /* Now the queue is empty we block, allowing the producer to place more - items in the queue. */ - vTaskDelay( pollqCONSUMER_DELAY ); - } -} /*lint !e818 Function prototype must conform to API. */ -/*-----------------------------------------------------------*/ - -/* This is called to check that all the created tasks are still running with no errors. */ -portBASE_TYPE xArePollingQueuesStillRunning( void ) -{ -portBASE_TYPE xReturn; - - /* Check both the consumer and producer poll count to check they have both - been changed since out last trip round. We do not need a critical section - around the check variables as this is called from a higher priority than - the other tasks that access the same variables. */ - if( ( xPollingConsumerCount == pollqINITIAL_VALUE ) || - ( xPollingProducerCount == pollqINITIAL_VALUE ) - ) - { - xReturn = pdFALSE; - } - else - { - xReturn = pdTRUE; - } - - /* Set the check variables back down so we know if they have been - incremented the next time around. */ - xPollingConsumerCount = pollqINITIAL_VALUE; - xPollingProducerCount = pollqINITIAL_VALUE; - - return xReturn; -} Index: /bserver/example/freeRTOSexample/Demo/Common/Minimal/integer.c =================================================================== --- /webserver/example/freeRTOSexample/Demo/Common/Minimal/integer.c (revision 14) +++ (revision ) @@ -1,206 +1,0 @@ -/* - FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation and modified by the FreeRTOS exception. - **NOTE** The exception to the GPL is included to allow you to distribute a - combined work that includes FreeRTOS without being obliged to provide the - source code for proprietary components outside of the FreeRTOS kernel. - Alternative commercial license and support terms are also available upon - request. See the licensing section of http://www.FreeRTOS.org for full - license details. - - FreeRTOS 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; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - - *************************************************************************** - * * - * Looking for a quick start? Then check out the FreeRTOS eBook! * - * See http://www.FreeRTOS.org/Documentation for details * - * * - *************************************************************************** - - 1 tab == 4 spaces! - - Please ensure to read the configuration and relevant port sections of the - online documentation. - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/* - * This version of integer. c is for use on systems that have limited stack - * space and no display facilities. The complete version can be found in - * the Demo/Common/Full directory. - * - * As with the full version, the tasks created in this file are a good test - * of the scheduler context switch mechanism. The processor has to access - * 32bit variables in two or four chunks (depending on the processor). The low - * priority of these tasks means there is a high probability that a context - * switch will occur mid calculation. See flop. c documentation for - * more information. - * - */ - -/* -Changes from V1.2.1 - - + The constants used in the calculations are larger to ensure the - optimiser does not truncate them to 16 bits. - -Changes from V1.2.3 - - + uxTaskCheck is now just used as a boolean. Instead of incrementing - the variable each cycle of the task, the variable is simply set to - true. sAreIntegerMathsTaskStillRunning() sets it back to false and - expects it to have been set back to true by the time it is called - again. - + A division has been included in the calculation. -*/ - -#include - -/* Scheduler include files. */ -#include "FreeRTOS.h" -#include "task.h" - -/* Demo program include files. */ -#include "integer.h" - -/* The constants used in the calculation. */ -#define intgCONST1 ( ( portLONG ) 123 ) -#define intgCONST2 ( ( portLONG ) 234567 ) -#define intgCONST3 ( ( portLONG ) -3 ) -#define intgCONST4 ( ( portLONG ) 7 ) -#define intgEXPECTED_ANSWER ( ( ( intgCONST1 + intgCONST2 ) * intgCONST3 ) / intgCONST4 ) - -#define intgSTACK_SIZE configMINIMAL_STACK_SIZE - -/* As this is the minimal version, we will only create one task. */ -#define intgNUMBER_OF_TASKS ( 1 ) - -/* The task function. Repeatedly performs a 32 bit calculation, checking the -result against the expected result. If the result is incorrect then the -context switch must have caused some corruption. */ -static portTASK_FUNCTION_PROTO( vCompeteingIntMathTask, pvParameters ); - -/* Variables that are set to true within the calculation task to indicate -that the task is still executing. The check task sets the variable back to -false, flagging an error if the variable is still false the next time it -is called. */ -static volatile signed portBASE_TYPE xTaskCheck[ intgNUMBER_OF_TASKS ] = { ( signed portBASE_TYPE ) pdFALSE }; - -/*-----------------------------------------------------------*/ - -void vStartIntegerMathTasks( unsigned portBASE_TYPE uxPriority ) -{ -portSHORT sTask; - - for( sTask = 0; sTask < intgNUMBER_OF_TASKS; sTask++ ) - { - xTaskCreate( vCompeteingIntMathTask, ( signed portCHAR * ) "IntMath", intgSTACK_SIZE, ( void * ) &( xTaskCheck[ sTask ] ), uxPriority, ( xTaskHandle * ) NULL ); - } -} -/*-----------------------------------------------------------*/ - -static portTASK_FUNCTION( vCompeteingIntMathTask, pvParameters ) -{ -/* These variables are all effectively set to constants so they are volatile to -ensure the compiler does not just get rid of them. */ -volatile portLONG lValue; -portSHORT sError = pdFALSE; -volatile signed portBASE_TYPE *pxTaskHasExecuted; - - /* Set a pointer to the variable we are going to set to true each - iteration. This is also a good test of the parameter passing mechanism - within each port. */ - pxTaskHasExecuted = ( volatile signed portBASE_TYPE * ) pvParameters; - - /* Keep performing a calculation and checking the result against a constant. */ - for( ;; ) - { - /* Perform the calculation. This will store partial value in - registers, resulting in a good test of the context switch mechanism. */ - lValue = intgCONST1; - lValue += intgCONST2; - - /* Yield in case cooperative scheduling is being used. */ - #if configUSE_PREEMPTION == 0 - { - taskYIELD(); - } - #endif - - /* Finish off the calculation. */ - lValue *= intgCONST3; - lValue /= intgCONST4; - - /* If the calculation is found to be incorrect we stop setting the - TaskHasExecuted variable so the check task can see an error has - occurred. */ - if( lValue != intgEXPECTED_ANSWER ) /*lint !e774 volatile used to prevent this being optimised out. */ - { - sError = pdTRUE; - } - - if( sError == pdFALSE ) - { - /* We have not encountered any errors, so set the flag that show - we are still executing. This will be periodically cleared by - the check task. */ - portENTER_CRITICAL(); - *pxTaskHasExecuted = pdTRUE; - portEXIT_CRITICAL(); - } - - /* Yield in case cooperative scheduling is being used. */ - #if configUSE_PREEMPTION == 0 - { - taskYIELD(); - } - #endif - } -} -/*-----------------------------------------------------------*/ - -/* This is called to check that all the created tasks are still running. */ -portBASE_TYPE xAreIntegerMathsTaskStillRunning( void ) -{ -portBASE_TYPE xReturn = pdTRUE; -portSHORT sTask; - - /* Check the maths tasks are still running by ensuring their check variables - are still being set to true. */ - for( sTask = 0; sTask < intgNUMBER_OF_TASKS; sTask++ ) - { - if( xTaskCheck[ sTask ] == pdFALSE ) - { - /* The check has not incremented so an error exists. */ - xReturn = pdFALSE; - } - - /* Reset the check variable so we can tell if it has been set by - the next time around. */ - xTaskCheck[ sTask ] = pdFALSE; - } - - return xReturn; -} -