summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2010-03-29 14:04:11 +0000
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2010-03-29 14:04:11 +0000
commit11976ebc394f4b91e919cfb8ea8e3127bd9b2e6a (patch)
treedcb322afb6344cab96deb4f064b9ffd2df308b11
parent545f546bdfa62a33221497e78ade8cebe6d1c567 (diff)
downloadfreertos-11976ebc394f4b91e919cfb8ea8e3127bd9b2e6a.tar.gz
Finish off the Cortus demo application:
+ Add a traceTASK_SWITCHED_OUT macro as part of the RegTest.c. + Add task to test the saving and restoring of the interrupt mask. + Change the serial port interrupt handlers to use naked functions. git-svn-id: http://svn.code.sf.net/p/freertos/code/trunk@1010 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
-rw-r--r--Demo/CORTUS_APS3_GCC/Demo/FreeRTOSConfig.h19
-rw-r--r--Demo/CORTUS_APS3_GCC/Demo/RegTest.c91
-rw-r--r--Demo/CORTUS_APS3_GCC/Demo/serial.c58
3 files changed, 140 insertions, 28 deletions
diff --git a/Demo/CORTUS_APS3_GCC/Demo/FreeRTOSConfig.h b/Demo/CORTUS_APS3_GCC/Demo/FreeRTOSConfig.h
index 33110da7c..d3b6a2851 100644
--- a/Demo/CORTUS_APS3_GCC/Demo/FreeRTOSConfig.h
+++ b/Demo/CORTUS_APS3_GCC/Demo/FreeRTOSConfig.h
@@ -103,8 +103,21 @@ We use --gc-sections when linking, so there is no harm is setting all of these t
#define BLOCKQ_1 1
+
+
+
+/* A task is created to test the behaviour of the interrupt controller during
+context switches. This macro is just used to set a variable to true each time
+the test task is switched out - the task itself needs to know when this happens
+in order to complete its tests. This macro will slow down the context switch
+and can normally be removed (just delete the whole macro, although doing so will
+cause the test task to indicate an error). */
+extern void *xICTestTask;
+extern volatile unsigned long ulTaskSwitchedOut;
+#define traceTASK_SWITCHED_OUT() if( pxCurrentTCB == xICTestTask ) ulTaskSwitchedOut = pdTRUE
+
+
+
#endif /* FREERTOS_CONFIG_H */
-// Local Variables:
-// tab-width:4
-// End:
+
diff --git a/Demo/CORTUS_APS3_GCC/Demo/RegTest.c b/Demo/CORTUS_APS3_GCC/Demo/RegTest.c
index 21a4040ce..7719e9a3a 100644
--- a/Demo/CORTUS_APS3_GCC/Demo/RegTest.c
+++ b/Demo/CORTUS_APS3_GCC/Demo/RegTest.c
@@ -54,17 +54,45 @@
#include "FreeRTOS.h"
#include "task.h"
+/*
+ * Two test tasks that fill the CPU registers with known values before
+ * continuously looping round checking that each register still contains its
+ * expected value. Both tasks use a separate set of values, with an incorrect
+ * value being found at any time being indicative of an error in the context
+ * switch mechanism. One of the tasks uses a yield instruction to increase the
+ * test coverage. The nature of these tasks necessitates that they are written
+ * in assembly code.
+ */
static void vRegTest1( void *pvParameters );
static void vRegTest2( void *pvParameters );
-static volatile unsigned long ulRegTest1Counter = 0UL, ulRegTest2Counter = 0UL;
-
+/*
+ * A task that tests the management of the Interrupt Controller (IC) during a
+ * context switch. The state of the IC current mask level must be maintained
+ * across context switches. Also, yields must be able to be performed when the
+ * interrupt controller mask is not zero. This task tests both these
+ * requirements.
+ */
+static void prvICCheck1Task( void *pvParameters );
+
+/* Counters used to ensure the tasks are still running. */
+static volatile unsigned long ulRegTest1Counter = 0UL, ulRegTest2Counter = 0UL, ulICTestCounter = 0UL;
+
+/* Handle to the task that checks the interrupt controller behaviour. This is
+used by the traceTASK_SWITCHED_OUT() macro, which is defined in
+FreeRTOSConfig.h and can be removed - it is just for the purpose of this test. */
+xTaskHandle xICTestTask = NULL;
+
+/* Variable that gets set to pdTRUE by traceTASK_SWITCHED_OUT each time
+is switched out. */
+volatile unsigned long ulTaskSwitchedOut;
/*-----------------------------------------------------------*/
void vStartRegTestTasks( void )
{
xTaskCreate( vRegTest1, ( signed char * ) "RTest1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
xTaskCreate( vRegTest2, ( signed char * ) "RTest1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+ xTaskCreate( prvICCheck1Task, ( signed char * ) "ICCheck", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xICTestTask );
}
/*-----------------------------------------------------------*/
@@ -193,9 +221,61 @@ static void vRegTest2( void *pvParameters )
}
/*-----------------------------------------------------------*/
+static void prvICCheck1Task( void *pvParameters )
+{
+long lICCheckStatus = pdPASS;
+
+ for( ;; )
+ {
+ /* At this point the interrupt mask should be zero. */
+ if( ic->cpl != 0 )
+ {
+ lICCheckStatus = pdFAIL;
+ }
+
+ /* If we yield here, it should still be 0 when the task next runs.
+ ulTaskSwitchedOut is just used to check that a switch does actually
+ happen. */
+ ulTaskSwitchedOut = pdFALSE;
+ taskYIELD();
+ if( ( ulTaskSwitchedOut != pdTRUE ) || ( ic->cpl != 0 ) )
+ {
+ lICCheckStatus = pdFAIL;
+ }
+
+ /* Set the interrupt mask to portSYSTEM_INTERRUPT_PRIORITY_LEVEL + 1,
+ before checking it is as expected. */
+ taskENTER_CRITICAL();
+ if( ic->cpl != ( portSYSTEM_INTERRUPT_PRIORITY_LEVEL + 1 ) )
+ {
+ lICCheckStatus = pdFAIL;
+ }
+
+ /* If we yield here, it should still be
+ portSYSTEM_INTERRUPT_PRIORITY_LEVEL + 10 when the task next runs. */
+ ulTaskSwitchedOut = pdFALSE;
+ taskYIELD();
+ if( ( ulTaskSwitchedOut != pdTRUE ) || ( ic->cpl != ( portSYSTEM_INTERRUPT_PRIORITY_LEVEL + 1 ) ) )
+ {
+ lICCheckStatus = pdFAIL;
+ }
+
+ /* Return the interrupt mask to its default state. */
+ taskEXIT_CRITICAL();
+
+ /* Just increment a loop counter so the check task knows if this task
+ is still running or not. */
+ if( lICCheckStatus == pdPASS )
+ {
+ ulICTestCounter++;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
portBASE_TYPE xAreRegTestTasksStillRunning( void )
{
-static unsigned long ulLastCounter1 = 0UL, ulLastCounter2 = 0UL;
+static unsigned long ulLastCounter1 = 0UL, ulLastCounter2 = 0UL, ulLastICTestCounter = 0UL;
long lReturn;
/* Check that both loop counters are still incrementing, indicating that
@@ -208,6 +288,10 @@ long lReturn;
{
lReturn = pdFAIL;
}
+ else if( ulLastICTestCounter == ulICTestCounter )
+ {
+ lReturn = pdFAIL;
+ }
else
{
lReturn = pdPASS;
@@ -215,6 +299,7 @@ long lReturn;
ulLastCounter1 = ulRegTest1Counter;
ulLastCounter2 = ulRegTest2Counter;
+ ulLastICTestCounter = ulICTestCounter;
return lReturn;
}
diff --git a/Demo/CORTUS_APS3_GCC/Demo/serial.c b/Demo/CORTUS_APS3_GCC/Demo/serial.c
index 90cf9528a..95dd142b1 100644
--- a/Demo/CORTUS_APS3_GCC/Demo/serial.c
+++ b/Demo/CORTUS_APS3_GCC/Demo/serial.c
@@ -71,6 +71,16 @@
#define comBLOCK_RETRY_TIME 10
/*-----------------------------------------------------------*/
+/* The interrupt handlers are naked functions that call C handlers. The C
+handlers are marked as noinline to ensure they work correctly when the
+optimiser is on. */
+void interrupt5_handler( void ) __attribute__((naked));
+static void prvTxHandler( void ) __attribute__((noinline));
+void interrupt6_handler( void ) __attribute__((naked));
+static void prvRxHandler( void ) __attribute__((noinline));
+
+/*-----------------------------------------------------------*/
+
/* Queues used to hold received characters, and characters waiting to be
transmitted. */
static xQueueHandle xRxedChars;
@@ -116,7 +126,6 @@ signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedC
return pdFALSE;
}
}
-
/*-----------------------------------------------------------*/
void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength )
@@ -132,7 +141,6 @@ void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString
while( xSerialPutChar( pxPort, *pChNext, comBLOCK_RETRY_TIME ) != pdTRUE ); pChNext++;
}
}
-
/*-----------------------------------------------------------*/
signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, portTickType xBlockTime )
@@ -162,12 +170,20 @@ void vSerialClose( xComPortHandle xPort )
}
/*-----------------------------------------------------------*/
-void interrupt_handler( IRQ_UART1_TX )
+/* UART Tx interrupt handler. */
+void interrupt5_handler( void )
{
-static signed char cChar;
-static portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
-
+ /* This is a naked function. */
portSAVE_CONTEXT();
+ prvTxHandler();
+ portRESTORE_CONTEXT();
+}
+/*-----------------------------------------------------------*/
+
+static void prvTxHandler( void )
+{
+signed char cChar;
+portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
/* The interrupt was caused by the transmit fifo having space for at least one
character. Are there any more characters to transmit? */
@@ -186,36 +202,34 @@ static portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
ensure that the unblocked task is the task that executes when the interrupt
completes if the unblocked task has a priority higher than the interrupted
task. */
- if( xHigherPriorityTaskWoken )
- {
- portYIELD_FROM_ISR();
- }
- portRESTORE_CONTEXT();
+ portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
/*-----------------------------------------------------------*/
-void interrupt_handler( IRQ_UART1_RX )
+/* UART Rx interrupt. */
+void interrupt6_handler( void )
{
-static signed char cChar;
-static portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
-
portSAVE_CONTEXT();
+ prvRxHandler();
+ portRESTORE_CONTEXT();
+}
+/*-----------------------------------------------------------*/
+
+static void prvRxHandler( void )
+{
+signed char cChar;
+portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
/* The interrupt was caused by the receiver getting data. */
cChar = uart1->rx_data;
- (void)xQueueSendFromISR(xRxedChars, &cChar, &xHigherPriorityTaskWoken);
+ xQueueSendFromISR(xRxedChars, &cChar, &xHigherPriorityTaskWoken );
/* If an event caused a task to unblock then we call "Yield from ISR" to
ensure that the unblocked task is the task that executes when the interrupt
completes if the unblocked task has a priority higher than the interrupted
task. */
- if( xHigherPriorityTaskWoken )
- {
- portYIELD_FROM_ISR();
- }
-
- portRESTORE_CONTEXT();
+ portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
/*-----------------------------------------------------------*/