Example #1
0
static void prvRegTest1Task( void *pvParameters )
{
    /* This task is created in privileged mode so can access the file scope
    queue variable.  Take a stack copy of this before the task is set into user
    mode.  Once this task is in user mode the file scope queue variable will no
    longer be accessible but the stack copy will. */
    QueueHandle_t xQueue = xFileScopeCheckQueue;

    /* Now the queue handle has been obtained the task can switch to user
    mode.  This is just one method of passing a handle into a protected
    task, the other	reg test task uses the task parameter instead. */
    portSWITCH_TO_USER_MODE();

    /* First check that the parameter value is as expected. */
    if( pvParameters != ( void * ) 0x12345678 ) {
        /* Error detected.  Delete the task so it stops communicating with
        the check task. */
        prvDeleteMe();
    }


    for( ;; ) {
        /* This task tests the kernel context switch mechanism by reading and
        writing directly to registers - which requires the test to be written
        in assembly code. */
        __asm volatile
        (
            "		MOV	R4, #104			\n" /* Set registers to a known value.  R0 to R1 are done in the loop below. */
            "		MOV	R5, #105			\n"
            "		MOV	R6, #106			\n"
            "		MOV	R8, #108			\n"
            "		MOV	R9, #109			\n"
            "		MOV	R10, #110			\n"
            "		MOV	R11, #111			\n"
            "reg1loop:						\n"
            "		MOV	R0, #100			\n" /* Set the scratch registers to known values - done inside the loop as they get clobbered. */
            "		MOV	R1, #101			\n"
            "		MOV	R2, #102			\n"
            "		MOV R3, #103			\n"
            "		MOV	R12, #112			\n"
            "		SVC #1					\n" /* Yield just to increase test coverage. */
            "		CMP	R0, #100			\n" /* Check all the registers still contain their expected values. */
            "		BNE	prvDeleteMe			\n" /* Value was not as expected, delete the task so it stops communicating with the check task. */
            "		CMP	R1, #101			\n"
            "		BNE	prvDeleteMe			\n"
            "		CMP	R2, #102			\n"
            "		BNE	prvDeleteMe			\n"
            "		CMP R3, #103			\n"
            "		BNE	prvDeleteMe			\n"
            "		CMP	R4, #104			\n"
            "		BNE	prvDeleteMe			\n"
            "		CMP	R5, #105			\n"
            "		BNE	prvDeleteMe			\n"
            "		CMP	R6, #106			\n"
            "		BNE	prvDeleteMe			\n"
            "		CMP	R8, #108			\n"
            "		BNE	prvDeleteMe			\n"
            "		CMP	R9, #109			\n"
            "		BNE	prvDeleteMe			\n"
            "		CMP	R10, #110			\n"
            "		BNE	prvDeleteMe			\n"
            "		CMP	R11, #111			\n"
            "		BNE	prvDeleteMe			\n"
            "		CMP	R12, #112			\n"
            "		BNE	prvDeleteMe			\n"
            :::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12"
        );

        /* Send mainREG_TEST_1_STILL_EXECUTING to the check task to indicate that this
        task is still functioning. */
        prvSendImAlive( xQueue, mainREG_TEST_1_STILL_EXECUTING );

        /* Go back to check all the register values again. */
        __asm volatile( "		B reg1loop	" );
    }
}
Example #2
0
static void prvTestMemoryRegions( void )
{
    long l;
    char cTemp;

    /* The check task (from which this function is called) is created in the
    Privileged mode.  The privileged array can be both read from and written
    to while this task is privileged. */
    cPrivilegedOnlyAccessArray[ 0 ] = 'a';
    if( cPrivilegedOnlyAccessArray[ 0 ] != 'a' ) {
        /* Something unexpected happened.  Delete this task so the error is
        apparent (no output will be displayed). */
        prvDeleteMe();
    }

    /* Writing off the end of the RAM allocated to this task will *NOT* cause a
    protection fault because the task is still executing in a privileged mode.
    Uncomment the following to test. */
    /*cPrivilegedOnlyAccessArray[ mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE ] = 'a';*/

    /* Now set the task into user mode. */
    portSWITCH_TO_USER_MODE();

    /* Accessing the privileged only array will now cause a fault.  Uncomment
    the following line to test. */
    /*cPrivilegedOnlyAccessArray[ 0 ] = 'a';*/

    /* The read/write array can still be successfully read and written. */
    for( l = 0; l < mainREAD_WRITE_ALIGN_SIZE; l++ ) {
        cReadWriteArray[ l ] = 'a';
        if( cReadWriteArray[ l ] != 'a' ) {
            /* Something unexpected happened.  Delete this task so the error is
            apparent (no output will be displayed). */
            prvDeleteMe();
        }
    }

    /* But attempting to read or write off the end of the RAM allocated to this
    task will cause a fault.  Uncomment either of the following two lines to
    test. */
    /* cReadWriteArray[ 0 ] = cReadWriteArray[ -1 ]; */
    /* cReadWriteArray[ mainREAD_WRITE_ALIGN_SIZE ] = 0x00; */

    /* The read only array can be successfully read... */
    for( l = 0; l < mainREAD_ONLY_ALIGN_SIZE; l++ ) {
        cTemp = cReadOnlyArray[ l ];
    }

    /* ...but cannot be written.  Uncomment the following line to test. */
    /* cReadOnlyArray[ 0 ] = 'a'; */

    /* Writing to the first and last locations in the stack array should not
    cause a protection fault.  Note that doing this will cause the kernel to
    detect a stack overflow if configCHECK_FOR_STACK_OVERFLOW is greater than
    1. */
    xCheckTaskStack[ 0 ] = 0;
    xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS - 1 ] = 0;

    /* Writing off either end of the stack array should cause a protection
    fault, uncomment either of the following two lines to test. */
    /* xCheckTaskStack[ -1 ] = 0; */
    /* xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS ] = 0; */

    ( void ) cTemp;
}
Example #3
0
static void prvCheckTask( void *pvParameters )
{
/* This task is created in privileged mode so can access the file scope
queue variable.  Take a stack copy of this before the task is set into user
mode.  Once that task is in user mode the file scope queue variable will no
longer be accessible but the stack copy will. */
xQueueHandle xQueue = xFileScopeCheckQueue;
long lMessage;
unsigned long ulStillAliveCounts[ 2 ] = { 0 };
char *pcStatusMessage = "PASS\r\n";
unsigned char x = 5, y = 10;

	/* Just to remove compiler warning. */
	( void ) pvParameters;

	/* Demonstrate how the various memory regions can and can't be accessed. 
	The task privilege is set down to user mode within this function. */
	prvTestMemoryRegions();

	/* Change the memory regions allocated to this task to those initially
	set up for demonstration purposes to those actually required by the task. */
	vTaskAllocateMPURegions( NULL, xAltRegions );

	/* This loop performs the main function of the task, which is blocking
	on a message queue then processing each message as it arrives. */
	for( ;; )
	{
		/* Wait for the next message to arrive. */
		xQueueReceive( xQueue, &lMessage, portMAX_DELAY );
		
		switch( lMessage )
		{
			case mainREG_TEST_1_STILL_EXECUTING	:	
					/* Message from task 1, so task 1 must still be executing. */
					( ulStillAliveCounts[ 0 ] )++;
					break;

			case mainREG_TEST_2_STILL_EXECUTING	:						
					/* Message from task 2, so task 2 must still be executing. */
					( ulStillAliveCounts[ 1 ] )++;
					break;

			case mainPRINT_SYSTEM_STATUS		:	
					/* Message from tick hook, time to print out the system
					status.  If messages has stopped arriving from either reg
					test task then the status must be set to fail. */
					if( ( ulStillAliveCounts[ 0 ] == 0 ) || ( ulStillAliveCounts[ 1 ] == 0 )  )
					{
						/* One or both of the test tasks are no longer sending 
						'still alive' messages. */
						pcStatusMessage = "FAIL\r\n";
					}

					/* Print a pass/fail message to the LCD - moving the
					message each time to provide feedback that the output
					is still being produced.  LCD_PrintString() accesses const
					data stored in flash, which all tasks are at liberty to do, 
					and GPIO for which an MPU region has been set up for it. */
					LCD_ClearScreen();
					LCD_PrintString( x>>1, y>>1, pcStatusMessage, 6, COLOR_RED );
					x += 7;
					y += 9;

					/* Reset the count of 'still alive' messages. */
					memset( ulStillAliveCounts, 0x00, sizeof( ulStillAliveCounts ) );
					break;

		default :
					/* Something unexpected happened.  Delete this task so the 
					error is apparent (no output will be displayed). */
					prvDeleteMe();
					break;
		}
	}
}
Example #4
0
static void prvCheckTask( void *pvParameters )
{
    /* This task is created in privileged mode so can access the file scope
    queue variable.  Take a stack copy of this before the task is set into user
    mode.  Once that task is in user mode the file scope queue variable will no
    longer be accessible but the stack copy will. */
    QueueHandle_t xQueue = xFileScopeCheckQueue;
    long lMessage;
    unsigned long ulStillAliveCounts[ 2 ] = { 0 };
    const char *pcStatusMessage = "PASS\r\n";

    /* The debug_printf() function uses RAM that is outside of the control of the
    application writer.  Therefore the application_defined_privileged_functions.h
    header file is used to provide a version that executes with privileges. */
    extern int MPU_debug_printf( const char *pcMessage );

    /* Just to remove compiler warning. */
    ( void ) pvParameters;

    /* Demonstrate how the various memory regions can and can't be accessed.
    The task privilege level is set down to user mode within this function. */
    prvTestMemoryRegions();

    /* Tests are done so lower the privilege status. */
    portSWITCH_TO_USER_MODE();

    /* This loop performs the main function of the task, which is blocking
    on a message queue then processing each message as it arrives. */
    for( ;; ) {
        /* Wait for the next message to arrive. */
        xQueueReceive( xQueue, &lMessage, portMAX_DELAY );

        switch( lMessage ) {
            case mainREG_TEST_1_STILL_EXECUTING	:
                /* Message from task 1, so task 1 must still be executing. */
                ( ulStillAliveCounts[ 0 ] )++;
                break;

            case mainREG_TEST_2_STILL_EXECUTING	:
                /* Message from task 2, so task 2 must still be executing. */
                ( ulStillAliveCounts[ 1 ] )++;
                break;

            case mainPRINT_SYSTEM_STATUS		:
                /* Message from tick hook, time to print out the system
                status.  If messages has stopped arriving from either reg
                test task then the status must be set to fail. */
                if( ( ulStillAliveCounts[ 0 ] == 0 ) || ( ulStillAliveCounts[ 1 ] == 0 )  ) {
                    /* One or both of the test tasks are no longer sending
                    'still alive' messages. */
                    pcStatusMessage = "FAIL\r\n";
                }

                /* Print a pass/fail message to the terminal.  This will be
                visible in the CrossWorks IDE. */
                MPU_debug_printf( pcStatusMessage );

                /* Reset the count of 'still alive' messages. */
                memset( ulStillAliveCounts, 0x00, sizeof( ulStillAliveCounts ) );
                break;

            default :
                /* Something unexpected happened.  Delete this task so the
                error is apparent (no output will be displayed). */
                prvDeleteMe();
                break;
        }
    }
}
Example #5
0
static void prvCheckTask( void *pvParameters )
{
/* This task is created in privileged mode so can access the file scope
queue variable.  Take a stack copy of this before the task is set into user
mode.  Once that task is in user mode the file scope queue variable will no
longer be accessible but the stack copy will. */
QueueHandle_t xQueue = xFileScopeCheckQueue;
int32_t lMessage;
uint32_t ulStillAliveCounts[ 2 ] = { 0 };
const char *pcStatusMessage = "PASS\r\n";
volatile uint32_t ulStatus = pdPASS;


	/* Just to remove compiler warning. */
	( void ) pvParameters;

	/* Demonstrate how the various memory regions can and can't be accessed.
	The task privilege level is set down to user mode within this function. */
	prvTestMemoryRegions();

	/* Tests are done so lower the privilege status. */
	portSWITCH_TO_USER_MODE();

	/* This loop performs the main function of the task, which is blocking
	on a message queue then processing each message as it arrives. */
	for( ;; )
	{
		/* Wait for the next message to arrive. */
		xQueueReceive( xQueue, &lMessage, portMAX_DELAY );

		switch( lMessage )
		{
			case mainREG_TEST_1_STILL_EXECUTING	:
					/* Message from task 1, so task 1 must still be executing. */
					( ulStillAliveCounts[ 0 ] )++;
					break;

			case mainREG_TEST_2_STILL_EXECUTING	:
					/* Message from task 2, so task 2 must still be executing. */
					( ulStillAliveCounts[ 1 ] )++;
					break;

			case mainPRINT_SYSTEM_STATUS		:
					/* Message from tick hook, time to print out the system
					status.  If messages has stopped arriving from either reg
					test task then the status must be set to fail. */
					if( ( ulStillAliveCounts[ 0 ] == 0 ) || ( ulStillAliveCounts[ 1 ] == 0 )  )
					{
						/* One or both of the test tasks are no longer sending
						'still alive' messages. */
						pcStatusMessage = "FAIL\r\n";

						/* ulStatus can be viewed (live) in the Keil watch window. */
						ulStatus = pdFAIL;
						( void ) ulStatus;
					}

					/**** print pcStatusMessage here. ****/
					( void ) pcStatusMessage;

					/* Reset the count of 'still alive' messages. */
					memset( ulStillAliveCounts, 0x00, sizeof( ulStillAliveCounts ) );
					break;

		default :
					/* Something unexpected happened.  Delete this task so the
					error is apparent (no output will be displayed). */
					prvDeleteMe();
					break;
		}
	}
}