From 2a5795f6bd55c6ccd4d2e730381d9a42af224c72 Mon Sep 17 00:00:00 2001 From: richardbarry Date: Fri, 28 Oct 2011 11:46:15 +0000 Subject: [PATCH] Add in interrupt nesting test - not yet complete. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1628 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../RTOSDemo/FreeRTOSConfig.h | 7 +- .../RTOSDemo/InterruptNestTest.c | 203 ++++++++++++++++++ .../RTOSDemo/InterruptNestTest.h | 61 ++++++ .../RTOSDemo/main.c | 29 ++- .../RTOSDemo/serial.c | 3 - 5 files changed, 289 insertions(+), 14 deletions(-) create mode 100644 Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/InterruptNestTest.c create mode 100644 Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/InterruptNestTest.h diff --git a/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/FreeRTOSConfig.h b/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/FreeRTOSConfig.h index 403133a4c..cd2f137b5 100644 --- a/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/FreeRTOSConfig.h +++ b/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/FreeRTOSConfig.h @@ -75,7 +75,7 @@ peripheral clock. */ #define configCPU_CLOCK_HZ ( ( unsigned long ) 150000000UL ) #define configPERIPHERAL_CLOCK_HZ ( ( unsigned long ) configCPU_CLOCK_HZ / 2UL ) #define configTICK_RATE_HZ ( ( portTickType ) 1000UL ) -#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 ) +#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 6 ) #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 32 * 1024 ) ) #define configMAX_TASK_NAME_LEN ( 16 ) @@ -110,8 +110,7 @@ runs from RAM. */ #define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE /* Set the following definitions to 1 to include the API function, or zero - to exclude the API function. - We use --gc-sections when linking, so there is no harm is setting all of these to 1 */ + to exclude the API function. */ #define INCLUDE_vTaskPrioritySet 1 #define INCLUDE_uxTaskPriorityGet 1 @@ -125,7 +124,7 @@ runs from RAM. */ #define configKERNEL_INTERRUPT_PRIORITY 1 /* Default definition of configASSERT(). */ -//#define configASSERT( x ) if( ( x ) == 0 ) { portDISABLE_INTERRUPTS(); for( ;; ); } +#define configASSERT( x ) if( ( x ) == 0 ) { portDISABLE_INTERRUPTS(); for( ;; ); } #endif /* FREERTOS_CONFIG_H */ diff --git a/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/InterruptNestTest.c b/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/InterruptNestTest.c new file mode 100644 index 000000000..6f24605ad --- /dev/null +++ b/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/InterruptNestTest.c @@ -0,0 +1,203 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + 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. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + 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. +*/ + +/* Standard includes. */ +#include +#include + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo application includes. */ +#include "InterruptNestTest.h" + +/* TriCore specific includes. */ +#include +#include +#include +#include + +/* This constant is specific to this test application. It allows the high +frequency (interrupt nesting test) timer to know how often to trigger, and the +check task to know how many iterations to expect at any given time. */ +#define tmrtestHIGH_FREQUENCY_TIMER_TEST_HZ ( 1931UL ) + +static void prvPortHighFrequencyTimerHandler( int iArg ) __attribute__((longcall)); +static void prvHighFrequencyTimerTask( void *pvParameters ); + +static const unsigned long ulCompareMatchValue = configPERIPHERAL_CLOCK_HZ / tmrtestHIGH_FREQUENCY_TIMER_TEST_HZ; +static const unsigned long ulInterruptsPer10ms = tmrtestHIGH_FREQUENCY_TIMER_TEST_HZ / 100UL; +static const unsigned long ulSemaphoreGiveRate_ms = 10UL; + +static xSemaphoreHandle xHighFrequencyTimerSemaphore = NULL; +static unsigned long ulHighFrequencyCounterIterations = 0UL; + +/*-----------------------------------------------------------*/ + +void vSetupInterruptNestingTest( void ) +{ +unsigned long ulCompareMatchBits; + + /* Create the semaphore used to communicate between the high frequency + interrupt and the task. */ + vSemaphoreCreateBinary( xHighFrequencyTimerSemaphore ); + configASSERT( xHighFrequencyTimerSemaphore ); + + /* Create the task that pends on the semaphore that is given by the + high frequency interrupt. */ + xTaskCreate( prvHighFrequencyTimerTask, ( signed char * ) "HFTmr", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL ); + + /* Setup the interrupt itself. The STM module clock divider is setup when + the tick interrupt is configured - which is when the scheduler is started - + so there is no need to do it here. */ + + unlock_wdtcon(); + { + /* Wait until access to Endint protected register is enabled. */ + while( 0 != ( WDT_CON0.reg & 0x1UL ) ); + + /* RMC == 1 so STM Clock == FPI */ + STM_CLC.reg = ( 1UL << 8 ); + } + lock_wdtcon(); + + /* The tick interrupt uses compare match 0, so this test uses compare match + 1, which means shifting up the values by 16 before writing them to the + register. */ + ulCompareMatchBits = ( 0x1fUL - __CLZ( ulCompareMatchValue ) ); + ulCompareMatchBits <<= 16UL; + + /* Write the values to the relevant SMT registers, without changing other + bits. */ + taskENTER_CRITICAL(); + { + STM_CMCON.reg &= ~( 0x1fUL << 16UL ); + STM_CMCON.reg |= ulCompareMatchBits; + STM_CMP1.reg = ulCompareMatchValue; + + if( 0 != _install_int_handler( configMAX_SYSCALL_INTERRUPT_PRIORITY - 5, prvPortHighFrequencyTimerHandler, 0 ) ) + { + /* Set-up the interrupt. */ + STM_SRC1.reg = ( ( configMAX_SYSCALL_INTERRUPT_PRIORITY - 5 ) | 0x00005000UL ); + + /* Enable the Interrupt. */ + STM_ISRR.reg &= ~( 0x03UL << 2UL ); + STM_ISRR.reg |= ( 0x1UL << 2UL ); + STM_ICR.reg &= ~( 0x07UL << 4UL ); + STM_ICR.reg |= ( 0x5UL << 4UL ); + } + else + { + /* Failed to install the interrupt. */ + configASSERT( ( ( volatile void * ) NULL ) ); + } + } + taskEXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +unsigned long ulInterruptNestingTestGetIterationCount( unsigned long *pulExpectedIncFrequency_ms ) +{ + *pulExpectedIncFrequency_ms = ulSemaphoreGiveRate_ms; + return ulHighFrequencyCounterIterations; +} +/*-----------------------------------------------------------*/ + +static void prvHighFrequencyTimerTask( void *pvParameters ) +{ + /* Just to remove compiler warnings about the unused parameter. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Wait for the next trigger from the high frequency timer interrupt. */ + xSemaphoreTake( xHighFrequencyTimerSemaphore, portMAX_DELAY ); + + /* Just count how many times the task has been unblocked before + returning to wait for the semaphore again. */ + ulHighFrequencyCounterIterations++; + } +} +/*-----------------------------------------------------------*/ + +static void prvPortHighFrequencyTimerHandler( int iArg ) +{ +static volatile unsigned long ulExecutionCounter = 0UL; +unsigned long ulHigherPriorityTaskWoken = pdFALSE; + + /* Just to avoid compiler warnings about unused parameters. */ + ( void ) iArg; + + /* Clear the interrupt source. */ + STM_ISRR.reg = 1UL << 2UL; + + /* Reload the Compare Match register for X ticks into the future.*/ + STM_CMP1.reg += ulCompareMatchValue; + + ulExecutionCounter++; + + if( ulExecutionCounter >= ulInterruptsPer10ms ) + { + ulExecutionCounter = xSemaphoreGiveFromISR( xHighFrequencyTimerSemaphore, &ulHigherPriorityTaskWoken ); + + /* If the semaphore was given ulExeuctionCounter will now be pdTRUE. */ + configASSERT( ulExecutionCounter == pdTRUE ); + + /* Start counting again. */ + ulExecutionCounter = 0UL; + } + + portYIELD_FROM_ISR( ulHigherPriorityTaskWoken ); +} diff --git a/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/InterruptNestTest.h b/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/InterruptNestTest.h new file mode 100644 index 000000000..1a6b58821 --- /dev/null +++ b/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/InterruptNestTest.h @@ -0,0 +1,61 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + 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. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + 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. +*/ + +#ifndef INTERRUPT_NEST_TEST_H +#define INTERRUPT_NEST_TEST_H + +void vSetupInterruptNestingTest( void ); +unsigned long ulInterruptNestingTestGetIterationCount( unsigned long *pulExpectedIncFrequency_ms ); + +#endif /* INTERRUPT_NEST_TEST_H */ + diff --git a/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/main.c b/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/main.c index 7cbfe7832..acda40487 100644 --- a/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/main.c +++ b/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/main.c @@ -123,6 +123,7 @@ #include "serial.h" #include "death.h" #include "TimerDemo.h" +#include "InterruptNestTest.h" /*-----------------------------------------------------------*/ @@ -141,9 +142,9 @@ /* The rate at which the on board LED will toggle when there is/is not an error. */ -#define mainNO_ERROR_FLASH_PERIOD ( ( portTickType ) 5000 / portTICK_RATE_MS ) -#define mainERROR_FLASH_PERIOD ( ( portTickType ) 500 / portTICK_RATE_MS ) -#define mainON_BOARD_LED_BIT ( ( unsigned long ) 7 ) +#define mainNO_ERROR_FLASH_PERIOD_MS ( ( portTickType ) 5000 / portTICK_RATE_MS ) +#define mainERROR_FLASH_PERIOD_MS ( ( portTickType ) 500 / portTICK_RATE_MS ) +#define mainON_BOARD_LED_BIT ( ( unsigned long ) 7 ) /* Constant used by the standard timer test functions. */ #define mainTIMER_TEST_PERIOD ( 50 ) @@ -238,7 +239,7 @@ int main( void ) static void prvCheckTask( void *pvParameters ) { -portTickType xDelayPeriod = mainNO_ERROR_FLASH_PERIOD; +portTickType xDelayPeriod = mainNO_ERROR_FLASH_PERIOD_MS; portTickType xLastExecutionTime; /* Just to stop compiler warnings. */ @@ -250,7 +251,7 @@ portTickType xLastExecutionTime; /* Cycle for ever, delaying then checking all the other tasks are still operating without error. If an error is detected then the delay period - is decreased from mainNO_ERROR_FLASH_PERIOD to mainERROR_FLASH_PERIOD so + is decreased from mainNO_ERROR_FLASH_PERIOD_MS to mainERROR_FLASH_PERIOD_MS so the on board LED flash rate will increase. NOTE: This task could easily be replaced by a software timer callback to remove the overhead of having an extra task. */ @@ -268,7 +269,7 @@ portTickType xLastExecutionTime; at a higher frequency to give visible feedback that something has gone wrong (it might just be that the loop back connector required by the comtest tasks has not been fitted). */ - xDelayPeriod = mainERROR_FLASH_PERIOD; + xDelayPeriod = mainERROR_FLASH_PERIOD_MS; } /* The toggle rate of the LED depends on how long this task delays for. @@ -281,6 +282,7 @@ portTickType xLastExecutionTime; static long prvCheckOtherTasksAreStillRunning( void ) { long lReturn = pdPASS; +unsigned long ulHighFrequencyTimerTaskIterations, ulExpectedIncFrequency_ms; /* Check all the demo tasks (other than the flash tasks) to ensure that they are all still running, and that none have detected an error. */ @@ -340,11 +342,23 @@ long lReturn = pdPASS; lReturn = pdFAIL; } + /* Obtain the number of times the task associated with the high frequency + (interrupt nesting) timer test has increment since the check task last + executed, and the frequency at which it is expected to execute in ms. */ + ulHighFrequencyTimerTaskIterations = ulInterruptNestingTestGetIterationCount( &ulExpectedIncFrequency_ms ); + if( ulHighFrequencyTimerTaskIterations < ( ( mainNO_ERROR_FLASH_PERIOD_MS / ulExpectedIncFrequency_ms ) - 1 ) ) + { + /* Would have expected the high frequency timer task to have + incremented its execution count more times that reported. */ + lReturn = pdFAIL; + } + + #if configUSE_TIMERS == 1 { /* For space constraint reasons, do not include the timer demo in builds that execute from RAM. */ - if( xAreTimerDemoTasksStillRunning( mainNO_ERROR_FLASH_PERIOD ) != pdTRUE ) + if( xAreTimerDemoTasksStillRunning( mainNO_ERROR_FLASH_PERIOD_MS ) != pdTRUE ) { lReturn = pdFAIL; } @@ -670,6 +684,7 @@ static void prvOptionallyCreateComprehensveTestApplication( void ) vStartGenericQueueTasks( tskIDLE_PRIORITY ); vStartRecursiveMutexTasks(); vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED ); + vSetupInterruptNestingTest(); #if configUSE_TIMERS == 1 { diff --git a/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/serial.c b/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/serial.c index 0620aa63a..fe0d32bd3 100644 --- a/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/serial.c +++ b/Demo/TriCore_TC1782_TriBoard_GCC/RTOSDemo/serial.c @@ -99,9 +99,6 @@ static xQueueHandle xSerialTransmitQueue = NULL; static xQueueHandle xSerialReceiveQueue = NULL; static volatile portBASE_TYPE xTransmitStatus = 0UL; -/* This reference is required by the Save/Restore Context Macros. */ -extern volatile unsigned portBASE_TYPE * pxCurrentTCB; - /*-----------------------------------------------------------*/ xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength ) -- 2.39.5