/* FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that has become a de facto standard. * * * * Help yourself get started quickly and support the FreeRTOS * * project by purchasing a FreeRTOS tutorial book, reference * * manual, or both from: http://www.FreeRTOS.org/Documentation * * * * Thank you! * * * *************************************************************************** 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 modification 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. 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. Full license text is available from the following link: http://www.freertos.org/a00114.html 1 tab == 4 spaces! *************************************************************************** * * * Having a problem? Start by reading the FAQ "My application does * * not run, what could be wrong?" * * * * http://www.FreeRTOS.org/FAQHelp.html * * * *************************************************************************** http://www.FreeRTOS.org - Documentation, books, training, latest versions, license and Real Time Engineers Ltd. contact details. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */ /* * This file contains a demo created to execute on the Rowley Associates * LPC2138 CrossFire development board. * * main() creates all the demo application tasks, then starts the scheduler. * The WEB documentation provides more details of the standard demo application * tasks. * * Main.c also creates a task called "Check". This only executes every few * seconds but has a high priority so is guaranteed to get processor time. * Its function is to check that all the other tasks are still operational. * Each standard demo task maintains a unique count that is incremented each * time the task successfully completes its function. Should any error occur * within such a task the count is permanently halted. The check task inspects * the count of each task to ensure it has changed since the last time the * check task executed. If all the count variables have changed all the tasks * are still executing error free, and the check task writes "PASS" to the * CrossStudio terminal IO window. Should any task contain an error at any time * the error is latched and "FAIL" written to the terminal IO window. * * Finally, main() sets up an interrupt service routine and task to handle * pushes of the button that is built into the CrossFire board. When the button * is pushed the ISR wakes the button task - which generates a table of task * status information which is also displayed on the terminal IO window. * * A print task is defined to ensure exclusive and consistent access to the * terminal IO. This is the only task that is allowed to access the terminal. * The check and button task therefore do not access the terminal directly but * instead pass a pointer to the message they wish to display to the print task. */ /* Standard includes. */ #include <__cross_studio_io.h> /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" #include "queue.h" #include "semphr.h" /* Demo app includes. */ #include "BlockQ.h" #include "death.h" #include "dynamic.h" #include "integer.h" #include "PollQ.h" #include "blocktim.h" #include "recmutex.h" #include "semtest.h" /* Hardware configuration definitions. */ #define mainBUS_CLK_FULL ( ( unsigned char ) 0x01 ) #define mainLED_BIT 0x80000000 #define mainP0_14__EINT_1 ( 2 << 28 ) #define mainEINT_1_EDGE_SENSITIVE 2 #define mainEINT_1_FALLING_EDGE_SENSITIVE 0 #define mainEINT_1_CHANNEL 15 #define mainEINT_1_VIC_CHANNEL_BIT ( 1 << mainEINT_1_CHANNEL ) #define mainEINT_1_ENABLE_BIT ( 1 << 5 ) /* Demo application definitions. */ #define mainQUEUE_SIZE ( 3 ) #define mainLED_DELAY ( ( portTickType ) 500 / portTICK_RATE_MS ) #define mainERROR_LED_DELAY ( ( portTickType ) 50 / portTICK_RATE_MS ) #define mainCHECK_DELAY ( ( portTickType ) 5000 / portTICK_RATE_MS ) #define mainLIST_BUFFER_SIZE 2048 #define mainNO_DELAY ( 0 ) #define mainSHORT_DELAY ( 150 / portTICK_RATE_MS ) /* Task priorities. */ #define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) #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 mainPRINT_TASK_PRIORITY ( tskIDLE_PRIORITY + 0 ) /*-----------------------------------------------------------*/ /* The semaphore used to wake the button task from within the external interrupt handler. */ xSemaphoreHandle xButtonSemaphore; /* The queue that is used to send message to vPrintTask for display in the terminal output window. */ xQueueHandle xPrintQueue; /* The rate at which the LED will toggle. The toggle rate increases if an error is detected in any task. */ static portTickType xLED_Delay = mainLED_DELAY; /*-----------------------------------------------------------*/ /* * Simply flashes the on board LED every mainLED_DELAY milliseconds. */ static void vLEDTask( void *pvParameters ); /* * Checks the status of all the demo tasks then prints a message to the * CrossStudio terminal IO windows. The message will be either PASS or FAIL * depending on the status of the demo applications tasks. A FAIL status will * be latched. * * Messages are not written directly to the terminal, but passed to vPrintTask * via a queue. */ static void vCheckTask( void *pvParameters ); /* * Controls all terminal output. If a task wants to send a message to the * terminal IO it posts a pointer to the text to vPrintTask via a queue. This * ensures serial access to the terminal IO. */ static void vPrintTask( void *pvParameter ); /* * Simply waits for an interrupt to be generated from the built in button, then * generates a table of tasks states that is then written by vPrintTask to the * terminal output window within CrossStudio. */ static void vButtonHandlerTask( void *pvParameters ); /*-----------------------------------------------------------*/ int main( void ) { /* Setup the peripheral bus to be the same as the PLL output. */ VPBDIV = mainBUS_CLK_FULL; /* Create the queue used to pass message to vPrintTask. */ xPrintQueue = xQueueCreate( mainQUEUE_SIZE, sizeof( char * ) ); /* Create the semaphore used to wake vButtonHandlerTask(). */ vSemaphoreCreateBinary( xButtonSemaphore ); xSemaphoreTake( xButtonSemaphore, 0 ); /* Start the standard demo tasks. */ vStartIntegerMathTasks( tskIDLE_PRIORITY ); vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); vStartDynamicPriorityTasks(); vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); #if configUSE_PREEMPTION == 1 { /* The timing of console output when not using the preemptive scheduler causes the block time tests to detect a timing problem. */ vCreateBlockTimeTasks(); } #endif vStartRecursiveMutexTasks(); /* Start the tasks defined within this file. */ xTaskCreate( vLEDTask, ( signed char * ) "LED", configMINIMAL_STACK_SIZE, NULL, mainLED_TASK_PRIORITY, NULL ); xTaskCreate( vCheckTask, ( signed char * ) "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); xTaskCreate( vPrintTask, ( signed char * ) "Print", configMINIMAL_STACK_SIZE, NULL, mainPRINT_TASK_PRIORITY, NULL ); xTaskCreate( vButtonHandlerTask, ( signed char * ) "Button", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); /* Start the scheduler. */ vTaskStartScheduler(); /* The scheduler should now be running, so we will only ever reach here if we ran out of heap space. */ return 0; } /*-----------------------------------------------------------*/ static void vLEDTask( void *pvParameters ) { /* Just to remove compiler warnings. */ ( void ) pvParameters; /* Configure IO. */ IO0DIR |= mainLED_BIT; IO0SET = mainLED_BIT; for( ;; ) { /* Not very exiting - just delay... */ vTaskDelay( xLED_Delay ); /* ...set the IO ... */ IO0CLR = mainLED_BIT; /* ...delay again... */ vTaskDelay( xLED_Delay ); /* ...then clear the IO. */ IO0SET = mainLED_BIT; } } /*-----------------------------------------------------------*/ static void vCheckTask( void *pvParameters ) { portBASE_TYPE xErrorOccurred = pdFALSE; portTickType xLastExecutionTime; const char * const pcPassMessage = "PASS\n"; const char * const pcFailMessage = "FAIL\n"; /* Just to remove compiler warnings. */ ( void ) pvParameters; /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil() works correctly. */ xLastExecutionTime = xTaskGetTickCount(); for( ;; ) { /* Perform this check every mainCHECK_DELAY milliseconds. */ vTaskDelayUntil( &xLastExecutionTime, mainCHECK_DELAY ); /* Has an error been found in any task? */ if( xAreIntegerMathsTaskStillRunning() != pdTRUE ) { xErrorOccurred = pdTRUE; } if( xArePollingQueuesStillRunning() != pdTRUE ) { xErrorOccurred = pdTRUE; } if( xAreSemaphoreTasksStillRunning() != pdTRUE ) { xErrorOccurred = pdTRUE; } if( xAreDynamicPriorityTasksStillRunning() != pdTRUE ) { xErrorOccurred = pdTRUE; } if( xAreBlockingQueuesStillRunning() != pdTRUE ) { xErrorOccurred = pdTRUE; } #if configUSE_PREEMPTION == 1 { /* The timing of console output when not using the preemptive scheduler causes the block time tests to detect a timing problem. */ if( xAreBlockTimeTestTasksStillRunning() != pdTRUE ) { xErrorOccurred = pdTRUE; } } #endif if( xAreRecursiveMutexTasksStillRunning() != pdTRUE ) { xErrorOccurred = pdTRUE; } /* Send either a pass or fail message. If an error is found it is never cleared again. */ if( xErrorOccurred == pdTRUE ) { xLED_Delay = mainERROR_LED_DELAY; xQueueSend( xPrintQueue, &pcFailMessage, portMAX_DELAY ); } else { xQueueSend( xPrintQueue, &pcPassMessage, portMAX_DELAY ); } } } /*-----------------------------------------------------------*/ static void vPrintTask( void *pvParameters ) { char *pcMessage; /* Just to stop compiler warnings. */ ( void ) pvParameters; for( ;; ) { /* Wait for a message to arrive. */ while( xQueueReceive( xPrintQueue, &pcMessage, portMAX_DELAY ) != pdPASS ); /* Write the message to the terminal IO. */ #ifndef NDEBUG debug_printf( "%s", pcMessage ); #endif } } /*-----------------------------------------------------------*/ static void vButtonHandlerTask( void *pvParameters ) { static signed char cListBuffer[ mainLIST_BUFFER_SIZE ]; const signed char *pcList = &( cListBuffer[ 0 ] ); const char * const pcHeader = "\nTask State Priority Stack #\n************************************************"; extern void (vButtonISRWrapper) ( void ); /* Just to stop compiler warnings. */ ( void ) pvParameters; /* Configure the interrupt. */ portENTER_CRITICAL(); { /* Configure P0.14 to generate interrupts. */ PINSEL0 |= mainP0_14__EINT_1; EXTMODE = mainEINT_1_EDGE_SENSITIVE; EXTPOLAR = mainEINT_1_FALLING_EDGE_SENSITIVE; /* Setup the VIC for EINT 1. */ VICIntSelect &= ~mainEINT_1_VIC_CHANNEL_BIT; VICIntEnable |= mainEINT_1_VIC_CHANNEL_BIT; VICVectAddr1 = ( long ) vButtonISRWrapper; VICVectCntl1 = mainEINT_1_ENABLE_BIT | mainEINT_1_CHANNEL; } portEXIT_CRITICAL(); for( ;; ) { /* For debouncing, wait a while then clear the semaphore. */ vTaskDelay( mainSHORT_DELAY ); xSemaphoreTake( xButtonSemaphore, mainNO_DELAY ); /* Wait for an interrupt. */ xSemaphoreTake( xButtonSemaphore, portMAX_DELAY ); /* Send the column headers to the print task for display. */ xQueueSend( xPrintQueue, &pcHeader, portMAX_DELAY ); /* Create the list of task states. */ vTaskList( cListBuffer ); /* Send the task status information to the print task for display. */ xQueueSend( xPrintQueue, &pcList, portMAX_DELAY ); } } /*-----------------------------------------------------------*/ void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName ) { /* Check pcTaskName for the name of the offending task, or pxCurrentTCB if pcTaskName has itself been corrupted. */ ( void ) pxTask; ( void ) pcTaskName; for( ;; ); }