Complete SAMD20 demo - still needs tidy up.

Add comments to the XMC1000 reg test files.
pull/1/head
Richard Barry 12 years ago
parent 0c56f5018d
commit 41a1dc62b7

@ -403,6 +403,7 @@
<Value>../../../../Source/include</Value>
<Value>../../../../Source/portable/GCC/ARM_CM0</Value>
<Value>../../../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-CLI</Value>
<Value>../../../Common/include</Value>
</ListValues>
</armgcc.compiler.directories.IncludePaths>
<armgcc.compiler.optimization.OtherFlags>-fdata-sections</armgcc.compiler.optimization.OtherFlags>
@ -498,6 +499,49 @@
<GenerateEepFile>True</GenerateEepFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\Common\Minimal\blocktim.c">
<SubType>compile</SubType>
<Link>src\Common-Demo-Tasks\blocktim.c</Link>
</Compile>
<Compile Include="..\..\Common\Minimal\countsem.c">
<SubType>compile</SubType>
<Link>src\Common-Demo-Tasks\countsem.c</Link>
</Compile>
<Compile Include="..\..\Common\Minimal\dynamic.c">
<SubType>compile</SubType>
<Link>src\Common-Demo-Tasks\dynamic.c</Link>
</Compile>
<Compile Include="..\..\Common\Minimal\GenQTest.c">
<SubType>compile</SubType>
<Link>src\Common-Demo-Tasks\GenQTest.c</Link>
</Compile>
<Compile Include="..\..\Common\Minimal\QueueOverwrite.c">
<SubType>compile</SubType>
<Link>src\Common-Demo-Tasks\QueueOverwrite.c</Link>
</Compile>
<Compile Include="..\..\Common\Minimal\QueueSet.c">
<SubType>compile</SubType>
<Link>src\Common-Demo-Tasks\QueueSet.c</Link>
</Compile>
<Compile Include="..\..\Common\Minimal\recmutex.c">
<SubType>compile</SubType>
<Link>src\Common-Demo-Tasks\recmutex.c</Link>
</Compile>
<Compile Include="src\Common-Demo-Tasks\QPeek.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\main-blinky.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\main-full.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\printf-stdarg.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\RegTest.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\Sample-CLI-commands.c">
<SubType>compile</SubType>
</Compile>
@ -651,9 +695,9 @@
<Compile Include="src\ASF\sam0\utils\cmsis\samd20\source\system_samd20.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\ASF\sam0\utils\syscalls\gcc\syscalls.c">
<None Include="src\ASF\sam0\utils\syscalls\gcc\syscalls.c">
<SubType>compile</SubType>
</Compile>
</None>
<None Include="src\asf.h">
<SubType>compile</SubType>
</None>
@ -1055,6 +1099,7 @@
<Folder Include="src\FreeRTOS-Source\include" />
<Folder Include="src\FreeRTOS-Source\portable" />
<Folder Include="src\FreeRTOS-CLI" />
<Folder Include="src\Common-Demo-Tasks" />
</ItemGroup>
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
</Project>

@ -59,6 +59,7 @@ static void (*_sercom_interrupt_handlers[SERCOM_INST_NUM])(const uint8_t instanc
static void _sercom_default_handler(
const uint8_t instance)
{
( void ) instance;
Assert(false);
}

@ -482,8 +482,11 @@ void _usart_interrupt_handler(
module->tx_status = STATUS_OK;
/* Run callback if registered and enabled */
if (callback_status & (1 << USART_CALLBACK_BUFFER_TRANSMITTED)) {
(*(module->callback[USART_CALLBACK_BUFFER_TRANSMITTED]))(module);
if( module->remaining_tx_buffer_length == 0 ) /* Added by _RB_ */
{
if (callback_status & (1 << USART_CALLBACK_BUFFER_TRANSMITTED)) {
(*(module->callback[USART_CALLBACK_BUFFER_TRANSMITTED]))(module);
}
}
/* Check if the Receive Complete interrupt has occurred, and that

@ -0,0 +1,248 @@
/*
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!
*/
/*
* "Reg test" tasks - These fill the registers with known values, then check
* that each register maintains its expected value for the lifetime of the
* task. Each task uses a different set of values. The reg test tasks execute
* with a very low priority, so get preempted very frequently. A register
* containing an unexpected value is indicative of an error in the context
* switching mechanism.
*/
void vRegTest1Task( void ) __attribute__((naked));
void vRegTest2Task( void ) __attribute__((naked));
void vRegTest1Task( void )
{
__asm volatile
(
".extern ulRegTest1LoopCounter \n"
" \n"
" /* Fill the core registers with known values. */ \n"
" movs r1, #101 \n"
" movs r2, #102 \n"
" movs r3, #103 \n"
" movs r4, #104 \n"
" movs r5, #105 \n"
" movs r6, #106 \n"
" movs r7, #107 \n"
" movs r0, #108 \n"
" mov r8, r0 \n"
" movs r0, #109 \n"
" mov r9, r0 \n"
" movs r0, #110 \n"
" mov r10, r0 \n"
" movs r0, #111 \n"
" mov r11, r0 \n"
" movs r0, #112 \n"
" mov r12, r0 \n"
" movs r0, #100 \n"
" \n"
"reg1_loop: \n"
" \n"
" cmp r0, #100 \n"
" bne reg1_error_loop \n"
" cmp r1, #101 \n"
" bne reg1_error_loop \n"
" cmp r2, #102 \n"
" bne reg1_error_loop \n"
" cmp r3, #103 \n"
" bne reg1_error_loop \n"
" cmp r4, #104 \n"
" bne reg1_error_loop \n"
" cmp r5, #105 \n"
" bne reg1_error_loop \n"
" cmp r6, #106 \n"
" bne reg1_error_loop \n"
" cmp r7, #107 \n"
" bne reg1_error_loop \n"
" movs r0, #108 \n"
" cmp r8, r0 \n"
" bne reg1_error_loop \n"
" movs r0, #109 \n"
" cmp r9, r0 \n"
" bne reg1_error_loop \n"
" movs r0, #110 \n"
" cmp r10, r0 \n"
" bne reg1_error_loop \n"
" movs r0, #111 \n"
" cmp r11, r0 \n"
" bne reg1_error_loop \n"
" movs r0, #112 \n"
" cmp r12, r0 \n"
" bne reg1_error_loop \n"
" \n"
" /* Everything passed, increment the loop counter. */ \n"
" push { r1 } \n"
" ldr r0, =ulRegTest1LoopCounter \n"
" ldr r1, [r0] \n"
" add r1, r1, #1 \n"
" str r1, [r0] \n"
" \n"
" /* Yield to increase test coverage. */ \n"
" movs r0, #0x01 \n"
" ldr r1, =0xe000ed04 \n" /*NVIC_INT_CTRL */
" lsl r0, #28 \n" /* Shift to PendSV bit */
" str r0, [r1] \n"
" dsb \n"
" pop { r1 } \n"
" \n"
" /* Start again. */ \n"
" movs r0, #100 \n"
" b reg1_loop \n"
" \n"
"reg1_error_loop: \n"
" /* If this line is hit then there was an error in a core register value. \n"
" The loop ensures the loop counter stops incrementing. */ \n"
" b reg1_error_loop \n"
" nop \n"
);
}
/*-----------------------------------------------------------*/
void vRegTest2Task( void )
{
__asm volatile
(
".extern ulRegTest2LoopCounter \n"
" \n"
" /* Fill the core registers with known values. */ \n"
" movs r1, #1 \n"
" movs r2, #2 \n"
" movs r3, #3 \n"
" movs r4, #4 \n"
" movs r5, #5 \n"
" movs r6, #6 \n"
" movs r7, #7 \n"
" movs r0, #8 \n"
" movs r8, r0 \n"
" movs r0, #9 \n"
" mov r9, r0 \n"
" movs r0, #10 \n"
" mov r10, r0 \n"
" movs r0, #11 \n"
" mov r11, r0 \n"
" movs r0, #12 \n"
" mov r12, r0 \n"
" movs r0, #10 \n"
" \n"
"reg2_loop: \n"
" \n"
" cmp r0, #10 \n"
" bne reg2_error_loop \n"
" cmp r1, #1 \n"
" bne reg2_error_loop \n"
" cmp r2, #2 \n"
" bne reg2_error_loop \n"
" cmp r3, #3 \n"
" bne reg2_error_loop \n"
" cmp r4, #4 \n"
" bne reg2_error_loop \n"
" cmp r5, #5 \n"
" bne reg2_error_loop \n"
" cmp r6, #6 \n"
" bne reg2_error_loop \n"
" cmp r7, #7 \n"
" bne reg2_error_loop \n"
" movs r0, #8 \n"
" cmp r8, r0 \n"
" bne reg2_error_loop \n"
" movs r0, #9 \n"
" cmp r9, r0 \n"
" bne reg2_error_loop \n"
" movs r0, #10 \n"
" cmp r10, r0 \n"
" bne reg2_error_loop \n"
" movs r0, #11 \n"
" cmp r11, r0 \n"
" bne reg2_error_loop \n"
" movs r0, #12 \n"
" cmp r12, r0 \n"
" bne reg2_error_loop \n"
" \n"
" /* Everything passed, increment the loop counter. */ \n"
" push { r1 } \n"
" ldr r0, =ulRegTest2LoopCounter \n"
" ldr r1, [r0] \n"
" add r1, r1, #1 \n"
" str r1, [r0] \n"
" pop { r1 } \n"
" \n"
" /* Start again. */ \n"
" movs r0, #10 \n"
" b reg2_loop \n"
" \n"
"reg2_error_loop: \n"
" /* If this line is hit then there was an error in a core register value. \n"
" The loop ensures the loop counter stops incrementing. */ \n"
" b reg2_error_loop \n"
" nop \n"
);
}
/*-----------------------------------------------------------*/

@ -78,17 +78,16 @@
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
#include <stdint.h>
extern uint32_t SystemCoreClock;
#include <asf.h>
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 1
#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configCPU_CLOCK_HZ ( system_clock_source_get_hz( SYSTEM_CLOCK_SOURCE_DFLL ) )
#define configTICK_RATE_HZ ( ( portTickType ) 500 )
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 60 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 11000 ) )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 16000 ) )
#define configMAX_TASK_NAME_LEN ( 5 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0

@ -47,7 +47,7 @@
/* System clock bus configuration */
# define CONF_CLOCK_CPU_CLOCK_FAILURE_DETECT true
# define CONF_CLOCK_FLASH_WAIT_STATES 0
# define CONF_CLOCK_FLASH_WAIT_STATES 2
# define CONF_CLOCK_CPU_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
# define CONF_CLOCK_APBA_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
# define CONF_CLOCK_APBB_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
@ -86,8 +86,8 @@
# define CONF_CLOCK_OSC32K_RUN_IN_STANDBY false
/* SYSTEM_CLOCK_SOURCE_DFLL configuration - Digital Frequency Locked Loop */
# define CONF_CLOCK_DFLL_ENABLE false
# define CONF_CLOCK_DFLL_LOOP_MODE SYSTEM_CLOCK_DFLL_LOOP_MODE_OPEN
# define CONF_CLOCK_DFLL_ENABLE true
# define CONF_CLOCK_DFLL_LOOP_MODE SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED
# define CONF_CLOCK_DFLL_ON_DEMAND false
# define CONF_CLOCK_DFLL_RUN_IN_STANDBY false
@ -113,12 +113,12 @@
/* Configure GCLK generator 0 (Main Clock) */
# define CONF_CLOCK_GCLK_0_ENABLE true
# define CONF_CLOCK_GCLK_0_RUN_IN_STANDBY false
# define CONF_CLOCK_GCLK_0_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
# define CONF_CLOCK_GCLK_0_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_DFLL
# define CONF_CLOCK_GCLK_0_PRESCALER 1
# define CONF_CLOCK_GCLK_0_OUTPUT_ENABLE false
/* Configure GCLK generator 1 */
# define CONF_CLOCK_GCLK_1_ENABLE false
# define CONF_CLOCK_GCLK_1_ENABLE true
# define CONF_CLOCK_GCLK_1_RUN_IN_STANDBY false
# define CONF_CLOCK_GCLK_1_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
# define CONF_CLOCK_GCLK_1_PRESCALER 1

@ -0,0 +1,231 @@
/*
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!
*/
/******************************************************************************
* NOTE 1: This project provides two demo applications. A simple blinky style
* project, and a more comprehensive test and demo application. The
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select
* between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY
* in main.c. This file implements the simply blinky style version.
*
* NOTE 2: This file only contains the source code that is specific to the
* basic demo. Generic functions, such FreeRTOS hook functions, and functions
* required to configure the hardware, are defined in main.c.
******************************************************************************
*
* main_blinky() creates one queue, and two tasks. It then starts the
* scheduler.
*
* The Queue Send Task:
* The queue send task is implemented by the prvQueueSendTask() function in
* this file. prvQueueSendTask() sits in a loop that causes it to repeatedly
* block for 200 milliseconds before sending the value 100 to the queue that
* was created within main_blinky(). Once the value is sent, the task loops
* back around to block for another 200 milliseconds.
*
* The Queue Receive Task:
* The queue receive task is implemented by the prvQueueReceiveTask() function
* in this file. prvQueueReceiveTask() sits in a loop where it repeatedly
* blocks on attempts to read data from the queue that was created within
* main_blinky(). When data is received, the task checks the value of the
* data, and if the value equals the expected 100, toggles the LED. The 'block
* time' parameter passed to the queue receive function specifies that the
* task should be held in the Blocked state indefinitely to wait for data to
* be available on the queue. The queue receive task will only leave the
* Blocked state when the queue send task writes to the queue. As the queue
* send task writes to the queue every 200 milliseconds, the queue receive
* task leaves the Blocked state every 200 milliseconds, and therefore toggles
* the LED every 200 milliseconds.
*/
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
/* Priorities at which the tasks are created. */
#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
/* The rate at which data is sent to the queue. The 200ms value is converted
to ticks using the portTICK_RATE_MS constant. */
#define mainQUEUE_SEND_FREQUENCY_MS ( 200 / portTICK_RATE_MS )
/* The number of items the queue can hold. This is 1 as the receive task
will remove items as they are added, meaning the send task should always find
the queue empty. */
#define mainQUEUE_LENGTH ( 1 )
/* Values passed to the two tasks just to check the task parameter
functionality. */
#define mainQUEUE_SEND_PARAMETER ( 0x1111UL )
#define mainQUEUE_RECEIVE_PARAMETER ( 0x22UL )
/*-----------------------------------------------------------*/
/*
* The tasks as described in the comments at the top of this file.
*/
static void prvQueueReceiveTask( void *pvParameters );
static void prvQueueSendTask( void *pvParameters );
/*
* Called by main() to create the simply blinky style application if
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1.
*/
void main_blinky( void );
/*-----------------------------------------------------------*/
/* The queue used by both tasks. */
static xQueueHandle xQueue = NULL;
/*-----------------------------------------------------------*/
void main_blinky( void )
{
/* Create the queue. */
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) );
if( xQueue != NULL )
{
/* Start the two tasks as described in the comments at the top of this
file. */
xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */
( signed char * ) "Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
( void * ) mainQUEUE_RECEIVE_PARAMETER, /* The parameter passed to the task - just to check the functionality. */
mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */
NULL ); /* The task handle is not required, so NULL is passed. */
xTaskCreate( prvQueueSendTask, ( signed char * ) "TX", configMINIMAL_STACK_SIZE, ( void * ) mainQUEUE_SEND_PARAMETER, mainQUEUE_SEND_TASK_PRIORITY, NULL );
/* Start the tasks and timer running. */
vTaskStartScheduler();
}
/* If all is well, the scheduler will now be running, and the following
line will never be reached. If the following line does execute, then
there was insufficient FreeRTOS heap memory available for the idle and/or
timer tasks to be created. See the memory management section on the
FreeRTOS web site for more details. */
for( ;; );
}
/*-----------------------------------------------------------*/
static void prvQueueSendTask( void *pvParameters )
{
portTickType xNextWakeTime;
const unsigned long ulValueToSend = 100UL;
/* Check the task parameter is as expected. */
configASSERT( ( ( unsigned long ) pvParameters ) == mainQUEUE_SEND_PARAMETER );
/* Initialise xNextWakeTime - this only needs to be done once. */
xNextWakeTime = xTaskGetTickCount();
for( ;; )
{
/* Place this task in the blocked state until it is time to run again.
The block time is specified in ticks, the constant used converts ticks
to ms. While in the Blocked state this task will not consume any CPU
time. */
vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );
/* Send to the queue - causing the queue receive task to unblock and
toggle the LED. 0 is used as the block time so the sending operation
will not block - it shouldn't need to block as the queue should always
be empty at this point in the code. */
xQueueSend( xQueue, &ulValueToSend, 0U );
}
}
/*-----------------------------------------------------------*/
static void prvQueueReceiveTask( void *pvParameters )
{
unsigned long ulReceivedValue;
/* Check the task parameter is as expected. */
configASSERT( ( ( unsigned long ) pvParameters ) == mainQUEUE_RECEIVE_PARAMETER );
for( ;; )
{
/* Wait until something arrives in the queue - this task will block
indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
FreeRTOSConfig.h. */
xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
/* To get here something must have been received from the queue, but
is it the expected value? If it is, toggle the LED. */
if( ulReceivedValue == 100UL )
{
/* Toggle the LED. */
port_pin_toggle_output_level( LED_0_PIN );
ulReceivedValue = 0U;
}
}
}
/*-----------------------------------------------------------*/

@ -0,0 +1,327 @@
/*
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!
*/
/******************************************************************************
* NOTE 1: This project provides two demo applications. A simple blinky style
* project, and a more comprehensive test and demo application. The
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select
* between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY
* in main.c. This file implements the comprehensive test and demo version.
*
* NOTE 2: This file only contains the source code that is specific to the
* full demo. Generic functions, such FreeRTOS hook functions, and functions
* required to configure the hardware, are defined in main.c.
******************************************************************************
*
* main_full() creates a set of standard demo tasks, some application specific
* tasks, and a timer. It then starts the scheduler. The web documentation
* provides more details of the standard demo application tasks, which provide
* no particular functionality, but do provide a good example of how to use the
* FreeRTOS API.
*
* In addition to the standard demo tasks, the following tasks and timer are
* defined and/or created within this file:
*
* "Reg test" tasks - These fill the registers with known values, then check
* that each register maintains its expected value for the lifetime of the
* task. Each task uses a different set of values. The reg test tasks execute
* with a very low priority, so get preempted very frequently. A register
* containing an unexpected value is indicative of an error in the context
* switching mechanism.
*
* "Check" software timer - The check timer period is initially set to three
* seconds. Its callback function checks that all the standard demo tasks, and
* the register check tasks, are not only still executing, but are executing
* without reporting any errors. If the check timer callback discovers that a
* task has either stalled, or reported an error, then it changes the period of
* the check timer from the initial three seconds, to just 200ms. The callback
* function also toggles the LED each time it is called. This provides a
* visual indication of the system status: If the LED toggles every three
* seconds then no issues have been discovered. If the LED toggles every 200ms,
* then an issue has been discovered with at least one task.
*/
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "timers.h"
/* Common demo includes. */
#include "blocktim.h"
#include "countsem.h"
#include "recmutex.h"
#include "ParTest.h"
#include "dynamic.h"
#include "QueueOverwrite.h"
#include "QueueSet.h"
#include "GenQTest.h"
#include "QPeek.h"
/* The period after which the check timer will expire provided no errors have
been reported by any of the standard demo tasks. ms are converted to the
equivalent in ticks using the portTICK_RATE_MS constant. */
#define mainCHECK_TIMER_PERIOD_MS ( 3000UL / portTICK_RATE_MS )
/* The period at which the check timer will expire if an error has been
reported in one of the standard demo tasks. ms are converted to the equivalent
in ticks using the portTICK_RATE_MS constant. */
#define mainERROR_CHECK_TIMER_PERIOD_MS ( 200UL / portTICK_RATE_MS )
/* A block time of zero simply means "don't block". */
#define mainDONT_BLOCK ( 0UL )
/*-----------------------------------------------------------*/
/*
* Register check tasks, as described at the top of this file. The nature of
* these files necessitates that they are written in an assembly.
*/
extern void vRegTest1Task( void *pvParameters );
extern void vRegTest2Task( void *pvParameters );
/*
* Function that starts the command console.
*/
extern void vUARTCommandConsoleStart( uint16_t usStackSize, unsigned portBASE_TYPE uxPriority );
/*
* The check timer callback function, as described at the top of this file.
*/
static void prvCheckTimerCallback( xTimerHandle xTimer );
/*
* Called by main() to create the comprehensive test/demo application if
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is not set to 1.
*/
void main_full( void );
/*-----------------------------------------------------------*/
/* The following two variables are used to communicate the status of the
register check tasks to the check software timer. If the variables keep
incrementing, then the register check tasks has not discovered any errors. If
a variable stops incrementing, then an error has been found. */
volatile unsigned long ulRegTest1LoopCounter = 0UL, ulRegTest2LoopCounter = 0UL;
/*-----------------------------------------------------------*/
void main_full( void )
{
xTimerHandle xTimer = NULL;
/* The register test tasks are asm functions that don't use a stack. The
stack allocated just has to be large enough to hold the task context, and
for the additional required for the stack overflow checking to work (if
configured). */
const size_t xRegTestStackSize = 25U;
/* Create the standard demo tasks */
vCreateBlockTimeTasks();
vStartDynamicPriorityTasks();
vStartCountingSemaphoreTasks();
vStartRecursiveMutexTasks();
vStartQueueOverwriteTask( tskIDLE_PRIORITY );
vStartQueueSetTasks();
vStartGenericQueueTasks( tskIDLE_PRIORITY );
vStartQueuePeekTasks();
/* Start the task that manages the command console for FreeRTOS+CLI. */
vUARTCommandConsoleStart( ( configMINIMAL_STACK_SIZE * 3 ), tskIDLE_PRIORITY );
/* Create the register test tasks as described at the top of this file.
These are naked functions that don't use any stack. A stack still has
to be allocated to hold the task context. */
xTaskCreate( vRegTest1Task, /* Function that implements the task. */
( signed char * ) "Reg1", /* Text name of the task. */
xRegTestStackSize, /* Stack allocated to the task. */
NULL, /* The task parameter is not used. */
tskIDLE_PRIORITY, /* The priority to assign to the task. */
NULL ); /* Don't receive a handle back, it is not needed. */
xTaskCreate( vRegTest2Task, /* Function that implements the task. */
( signed char * ) "Reg2", /* Text name of the task. */
xRegTestStackSize, /* Stack allocated to the task. */
NULL, /* The task parameter is not used. */
tskIDLE_PRIORITY, /* The priority to assign to the task. */
NULL ); /* Don't receive a handle back, it is not needed. */
/* Create the software timer that performs the 'check' functionality,
as described at the top of this file. */
xTimer = xTimerCreate( ( const signed char * ) "CheckTimer",/* A text name, purely to help debugging. */
( mainCHECK_TIMER_PERIOD_MS ), /* The timer period, in this case 3000ms (3s). */
pdTRUE, /* This is an auto-reload timer, so xAutoReload is set to pdTRUE. */
( void * ) 0, /* The ID is not used, so can be set to anything. */
prvCheckTimerCallback /* The callback function that inspects the status of all the other tasks. */
);
/* If the software timer was created successfully, start it. It won't
actually start running until the scheduler starts. A block time of
zero is used in this call, although any value could be used as the block
time will be ignored because the scheduler has not started yet. */
if( xTimer != NULL )
{
xTimerStart( xTimer, mainDONT_BLOCK );
}
/* Start the kernel. From here on, only tasks and interrupts will run. */
vTaskStartScheduler();
/* If all is well, the scheduler will now be running, and the following
line will never be reached. If the following line does execute, then there
was insufficient FreeRTOS heap memory available for the idle and/or timer
tasks to be created. See the memory management section on the FreeRTOS web
site, or the FreeRTOS tutorial books for more details. */
for( ;; );
}
/*-----------------------------------------------------------*/
/* See the description at the top of this file. */
static void prvCheckTimerCallback( xTimerHandle xTimer )
{
static long lChangedTimerPeriodAlready = pdFALSE;
static unsigned long ulLastRegTest1Value = 0, ulLastRegTest2Value = 0;
unsigned long ulErrorFound = pdFALSE;
/* Check all the demo and test tasks to ensure that they are all still
running, and that none have detected an error. */
if( xAreDynamicPriorityTasksStillRunning() != pdPASS )
{
ulErrorFound |= ( 0x01UL << 0UL );
}
if( xAreBlockTimeTestTasksStillRunning() != pdPASS )
{
ulErrorFound |= ( 0x01UL << 1UL );
}
if( xAreCountingSemaphoreTasksStillRunning() != pdPASS )
{
ulErrorFound |= ( 0x01UL << 2UL );
}
if( xAreRecursiveMutexTasksStillRunning() != pdPASS )
{
ulErrorFound |= ( 0x01UL << 3UL );
}
/* Check that the register test 1 task is still running. */
if( ulLastRegTest1Value == ulRegTest1LoopCounter )
{
ulErrorFound |= ( 0x01UL << 4UL );
}
ulLastRegTest1Value = ulRegTest1LoopCounter;
/* Check that the register test 2 task is still running. */
if( ulLastRegTest2Value == ulRegTest2LoopCounter )
{
ulErrorFound |= ( 0x01UL << 5UL );
}
ulLastRegTest2Value = ulRegTest2LoopCounter;
if( xAreQueueSetTasksStillRunning() != pdPASS )
{
ulErrorFound |= ( 0x01UL << 6UL );
}
if( xIsQueueOverwriteTaskStillRunning() != pdPASS )
{
ulErrorFound |= ( 0x01UL << 7UL );
}
if( xAreGenericQueueTasksStillRunning() != pdPASS )
{
ulErrorFound |= ( 0x01UL << 8UL );
}
if( xAreQueuePeekTasksStillRunning() != pdPASS )
{
ulErrorFound |= ( 0x01UL << 9UL );
}
/* Toggle the check LED to give an indication of the system status. If
the LED toggles every mainCHECK_TIMER_PERIOD_MS milliseconds then
everything is ok. A faster toggle indicates an error. */
port_pin_toggle_output_level( LED_0_PIN );
/* Have any errors been latched in ulErrorFound? If so, shorten the
period of the check timer to mainERROR_CHECK_TIMER_PERIOD_MS milliseconds.
This will result in an increase in the rate at which the LED toggles. */
if( ulErrorFound != pdFALSE )
{
if( lChangedTimerPeriodAlready == pdFALSE )
{
lChangedTimerPeriodAlready = pdTRUE;
/* This call to xTimerChangePeriod() uses a zero block time.
Functions called from inside of a timer callback function must
*never* attempt to block. */
xTimerChangePeriod( xTimer, ( mainERROR_CHECK_TIMER_PERIOD_MS ), mainDONT_BLOCK );
}
}
}
/*-----------------------------------------------------------*/

@ -62,6 +62,22 @@
1 tab == 4 spaces!
*/
/******************************************************************************
* This project provides two demo applications. A simple blinky style project,
* and a more comprehensive test and demo application. The
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting (defined in this file) is used to
* select between the two. The simply blinky demo is implemented and described
* in main_blinky.c. The more comprehensive test and demo application is
* implemented and described in main_full.c.
*
* This file implements the code that is not demo specific, including the
* hardware setup and FreeRTOS hook functions. It also contains a dummy
* interrupt service routine called Dummy_IRQHandler() that is provided as an
* example of how to use interrupt safe FreeRTOS API functions (those that end
* in "FromISR").
*
*****************************************************************************/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
@ -69,13 +85,21 @@
/* Demo app includes. */
#include "UARTCommandConsole.h"
/* Demo application include. */
#include "QueueSet.h"
/* Library includes. */
#include <asf.h>
/* Set mainCREATE_SIMPLE_BLINKY_DEMO_ONLY to one to run the simple blinky demo,
or 0 to run the more comprehensive test and demo application. */
#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 0
/*-----------------------------------------------------------*/
/*
* Hardware and driver initialisation can be done in this function.
* Perform any application specific hardware configuration. The clocks,
* memory, etc. are configured before main() is called.
*/
static void prvSetupHardware( void );
@ -88,6 +112,13 @@ void vApplicationIdleHook( void );
void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName );
void vApplicationTickHook( void );
/*
* main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1.
* main_full() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0.
*/
extern void main_blinky( void );
extern void main_full( void );
/*-----------------------------------------------------------*/
/* Used in the run time stats calculations. */
@ -97,23 +128,26 @@ static unsigned long ulClocksPer10thOfAMilliSecond = 0UL;
int main (void)
{
/* Prepare the hardware for the demo. */
prvSetupHardware();
vUARTCommandConsoleStart( ( configMINIMAL_STACK_SIZE * 3 ), tskIDLE_PRIORITY );
/* Start the scheduler. */
vTaskStartScheduler();
/* If all is well, the scheduler will now be running, and the following line
will never be reached. If the following line does execute, then there was
insufficient FreeRTOS heap memory available for the idle and/or timer tasks
to be created. See the memory management section on the FreeRTOS web site
for more details. */
for( ;; );
/* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top
of this file. */
#if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1
{
main_blinky();
}
#else
{
main_full();
}
#endif
}
/*-----------------------------------------------------------*/
static void prvSetupHardware( void )
{
/* Initialisation is performed by the Atmel board support package. */
system_init();
}
/*-----------------------------------------------------------*/
@ -168,7 +202,22 @@ void vApplicationTickHook( void )
configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be
added here, but the tick hook is called from an interrupt context, so
code must not attempt to block, and only the interrupt safe FreeRTOS API
functions can be used (those that end in FromISR()). */
functions can be used (those that end in FromISR()). The code in this
tick hook implementation is for demonstration only - it has no real
purpose. It just gives a semaphore every 50ms. The semaphore unblocks a
task that then toggles an LED. Additionally, the call to
vQueueSetAccessQueueSetFromISR() is part of the "standard demo tasks"
functionality. */
/* The semaphore and associated task are not created when the simple blinky
demo is used. */
#if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 0
{
/* Write to a queue that is in use as part of the queue set demo to
demonstrate using queue sets from an ISR. */
vQueueSetAccessQueueSetFromISR();
}
#endif /* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY */
}
/*-----------------------------------------------------------*/

@ -0,0 +1,293 @@
/*
Copyright 2001, 2002 Georges Menie (www.menie.org)
stdarg version contributed by Christian Ettinger
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
putchar is the only external dependency for this file,
if you have a working putchar, leave it commented out.
If not, uncomment the define below and
replace outbyte(c) by your own function call.
*/
#define putchar(c) c
#include <stdarg.h>
static void printchar(char **str, int c)
{
//extern int putchar(int c);
if (str) {
**str = (char)c;
++(*str);
}
else
{
(void)putchar(c);
}
}
#define PAD_RIGHT 1
#define PAD_ZERO 2
static int prints(char **out, const char *string, int width, int pad)
{
register int pc = 0, padchar = ' ';
if (width > 0) {
register int len = 0;
register const char *ptr;
for (ptr = string; *ptr; ++ptr) ++len;
if (len >= width) width = 0;
else width -= len;
if (pad & PAD_ZERO) padchar = '0';
}
if (!(pad & PAD_RIGHT)) {
for ( ; width > 0; --width) {
printchar (out, padchar);
++pc;
}
}
for ( ; *string ; ++string) {
printchar (out, *string);
++pc;
}
for ( ; width > 0; --width) {
printchar (out, padchar);
++pc;
}
return pc;
}
/* the following should be enough for 32 bit int */
#define PRINT_BUF_LEN 12
static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)
{
char print_buf[PRINT_BUF_LEN];
register char *s;
register int t, neg = 0, pc = 0;
register unsigned int u = (unsigned int)i;
if (i == 0) {
print_buf[0] = '0';
print_buf[1] = '\0';
return prints (out, print_buf, width, pad);
}
if (sg && b == 10 && i < 0) {
neg = 1;
u = (unsigned int)-i;
}
s = print_buf + PRINT_BUF_LEN-1;
*s = '\0';
while (u) {
t = (unsigned int)u % b;
if( t >= 10 )
t += letbase - '0' - 10;
*--s = (char)(t + '0');
u /= b;
}
if (neg) {
if( width && (pad & PAD_ZERO) ) {
printchar (out, '-');
++pc;
--width;
}
else {
*--s = '-';
}
}
return pc + prints (out, s, width, pad);
}
static int print( char **out, const char *format, va_list args )
{
register int width, pad;
register int pc = 0;
char scr[2];
for (; *format != 0; ++format) {
if (*format == '%') {
++format;
width = pad = 0;
if (*format == '\0') break;
if (*format == '%') goto out;
if (*format == '-') {
++format;
pad = PAD_RIGHT;
}
while (*format == '0') {
++format;
pad |= PAD_ZERO;
}
for ( ; *format >= '0' && *format <= '9'; ++format) {
width *= 10;
width += *format - '0';
}
if( *format == 's' ) {
register char *s = (char *)va_arg( args, int );
pc += prints (out, s?s:"(null)", width, pad);
continue;
}
if( *format == 'd' ) {
pc += printi (out, va_arg( args, int ), 10, 1, width, pad, 'a');
continue;
}
if( *format == 'x' ) {
pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'a');
continue;
}
if( *format == 'X' ) {
pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'A');
continue;
}
if( *format == 'u' ) {
pc += printi (out, va_arg( args, int ), 10, 0, width, pad, 'a');
continue;
}
if( *format == 'c' ) {
/* char are converted to int then pushed on the stack */
scr[0] = (char)va_arg( args, int );
scr[1] = '\0';
pc += prints (out, scr, width, pad);
continue;
}
}
else {
out:
printchar (out, *format);
++pc;
}
}
if (out) **out = '\0';
va_end( args );
return pc;
}
int printf(const char *format, ...)
{
va_list args;
va_start( args, format );
return print( 0, format, args );
}
int sprintf(char *out, const char *format, ...)
{
va_list args;
va_start( args, format );
return print( &out, format, args );
}
int snprintf( char *buf, unsigned int count, const char *format, ... )
{
va_list args;
( void ) count;
va_start( args, format );
return print( &buf, format, args );
}
#ifdef TEST_PRINTF
int main(void)
{
char *ptr = "Hello world!";
char *np = 0;
int i = 5;
unsigned int bs = sizeof(int)*8;
int mi;
char buf[80];
mi = (1 << (bs-1)) + 1;
printf("%s\n", ptr);
printf("printf test\n");
printf("%s is null pointer\n", np);
printf("%d = 5\n", i);
printf("%d = - max int\n", mi);
printf("char %c = 'a'\n", 'a');
printf("hex %x = ff\n", 0xff);
printf("hex %02x = 00\n", 0);
printf("signed %d = unsigned %u = hex %x\n", -3, -3, -3);
printf("%d %s(s)%", 0, "message");
printf("\n");
printf("%d %s(s) with %%\n", 0, "message");
sprintf(buf, "justif: \"%-10s\"\n", "left"); printf("%s", buf);
sprintf(buf, "justif: \"%10s\"\n", "right"); printf("%s", buf);
sprintf(buf, " 3: %04d zero padded\n", 3); printf("%s", buf);
sprintf(buf, " 3: %-4d left justif.\n", 3); printf("%s", buf);
sprintf(buf, " 3: %4d right justif.\n", 3); printf("%s", buf);
sprintf(buf, "-3: %04d zero padded\n", -3); printf("%s", buf);
sprintf(buf, "-3: %-4d left justif.\n", -3); printf("%s", buf);
sprintf(buf, "-3: %4d right justif.\n", -3); printf("%s", buf);
return 0;
}
/*
* if you compile this file with
* gcc -Wall $(YOUR_C_OPTIONS) -DTEST_PRINTF -c printf.c
* you will get a normal warning:
* printf.c:214: warning: spurious trailing `%' in format
* this line is testing an invalid % at the end of the format string.
*
* this should display (on 32bit int machine) :
*
* Hello world!
* printf test
* (null) is null pointer
* 5 = 5
* -2147483647 = - max int
* char a = 'a'
* hex ff = ff
* hex 00 = 00
* signed -3 = unsigned 4294967293 = hex fffffffd
* 0 message(s)
* 0 message(s) with %
* justif: "left "
* justif: " right"
* 3: 0003 zero padded
* 3: 3 left justif.
* 3: 3 right justif.
* -3: -003 zero padded
* -3: -3 left justif.
* -3: -3 right justif.
*/
#endif
/* To keep linker happy. */
int write( int i, char* c, int n)
{
(void)i;
(void)n;
(void)c;
return 0;
}

@ -62,6 +62,15 @@
1 tab == 4 spaces!
*/
/*
* "Reg test" tasks - These fill the registers with known values, then check
* that each register maintains its expected value for the lifetime of the
* task. Each task uses a different set of values. The reg test tasks execute
* with a very low priority, so get preempted very frequently. A register
* containing an unexpected value is indicative of an error in the context
* switching mechanism.
*/
void vRegTest1Task( void ) __attribute__((naked));
void vRegTest2Task( void ) __attribute__((naked));

@ -62,6 +62,15 @@
1 tab == 4 spaces!
*/
/*
* "Reg test" tasks - These fill the registers with known values, then check
* that each register maintains its expected value for the lifetime of the
* task. Each task uses a different set of values. The reg test tasks execute
* with a very low priority, so get preempted very frequently. A register
* containing an unexpected value is indicative of an error in the context
* switching mechanism.
*/
RSEG CODE:CODE(2)
thumb

@ -62,6 +62,15 @@
; 1 tab == 4 spaces!
;*/
;/*
; * "Reg test" tasks - These fill the registers with known values, then check
; * that each register maintains its expected value for the lifetime of the
; * task. Each task uses a different set of values. The reg test tasks execute
; * with a very low priority, so get preempted very frequently. A register
; * containing an unexpected value is indicative of an error in the context
; * switching mechanism.
; */
PRESERVE8
THUMB

Loading…
Cancel
Save