mirror of
https://github.com/FreeRTOS/FreeRTOS.git
synced 2025-09-17 04:55:13 +08:00
Add Full Demo to Qemu mps2 (#481)
* Add Full Demo to Qemu with MPS2 * Increase full demo heap memory * Add Full Demo to Qemu MPS2 * Fix headers * Fix header FreeRTOS version * Remove commented line * Remove commented line * Fix header checker version, and corresponding files * Fix checker version number requirements
This commit is contained in:
2
.github/scripts/check-header.py
vendored
2
.github/scripts/check-header.py
vendored
@ -369,7 +369,7 @@ FREERTOS_IGNORED_PATTERNS = [
|
|||||||
|
|
||||||
FREERTOS_HEADER = [
|
FREERTOS_HEADER = [
|
||||||
'/*\n',
|
'/*\n',
|
||||||
' * FreeRTOS V202011.00\n',
|
' * FreeRTOS V202012.00\n',
|
||||||
' * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n',
|
' * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n',
|
||||||
' *\n',
|
' *\n',
|
||||||
' * Permission is hereby granted, free of charge, to any person obtaining a copy of\n',
|
' * Permission is hereby granted, free of charge, to any person obtaining a copy of\n',
|
||||||
|
@ -38,48 +38,78 @@
|
|||||||
*
|
*
|
||||||
* See https://www.freertos.org/a00110.html
|
* See https://www.freertos.org/a00110.html
|
||||||
*----------------------------------------------------------*/
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
#define configASSERT_DEFINED 1
|
#define configASSERT_DEFINED 1
|
||||||
extern void vAssertCalled( void );
|
extern void vAssertCalled( void );
|
||||||
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( )
|
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( )
|
||||||
|
#define configQUEUE_REGISTRY_SIZE 20
|
||||||
|
|
||||||
#define configUSE_PREEMPTION 1
|
#define configUSE_PREEMPTION 1
|
||||||
#define configUSE_TIME_SLICING 1
|
#define configUSE_TIME_SLICING 0
|
||||||
|
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
|
||||||
|
|
||||||
#define configUSE_IDLE_HOOK 0
|
#define configUSE_IDLE_HOOK 1
|
||||||
#define configUSE_TICK_HOOK 0
|
#define configUSE_TICK_HOOK 1
|
||||||
#define configCPU_CLOCK_HZ ( ( unsigned long ) 20000000 )
|
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
|
||||||
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
|
#define configCPU_CLOCK_HZ ( ( unsigned long ) 20000000 )
|
||||||
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 2000 )
|
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
|
||||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 279000 ) )
|
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 2000 )
|
||||||
#define configMAX_TASK_NAME_LEN ( 10 )
|
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 900 ) )
|
||||||
#define configUSE_TRACE_FACILITY 0
|
#define configMAX_TASK_NAME_LEN ( 10 )
|
||||||
#define configUSE_16_BIT_TICKS 0
|
#define configUSE_TRACE_FACILITY 1
|
||||||
#define configIDLE_SHOULD_YIELD 0
|
#define configUSE_16_BIT_TICKS 0
|
||||||
#define configUSE_CO_ROUTINES 0
|
#define configIDLE_SHOULD_YIELD 1
|
||||||
|
#define configUSE_CO_ROUTINES 0
|
||||||
|
|
||||||
|
#define configMAX_PRIORITIES ( 10 )
|
||||||
|
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
|
||||||
|
#define configTIMER_QUEUE_LENGTH 20
|
||||||
|
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
|
||||||
|
#define configUSE_COUNTING_SEMAPHORES 1
|
||||||
|
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
||||||
|
#define configSUPPORT_STATIC_ALLOCATION 1
|
||||||
|
#define configNUM_TX_DESCRIPTORS 15
|
||||||
|
#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN 2
|
||||||
|
|
||||||
#define configMAX_PRIORITIES ( 10 )
|
|
||||||
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
|
|
||||||
#define configTIMER_QUEUE_LENGTH 20
|
|
||||||
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 3 )
|
|
||||||
#define configUSE_COUNTING_SEMAPHORES 1
|
|
||||||
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
|
||||||
#define configNUM_TX_DESCRIPTORS 15
|
|
||||||
|
|
||||||
/* Set the following definitions to 1 to include the API function, or zero
|
/* Set the following definitions to 1 to include the API function, or zero
|
||||||
to exclude the API function. */
|
to exclude the API function. */
|
||||||
|
|
||||||
#define configUSE_MALLOC_FAILED_HOOK 1
|
|
||||||
#define configUSE_MUTEXES 1
|
|
||||||
#define configUSE_RECURSIVE_MUTEXES 1
|
|
||||||
#define INCLUDE_vTaskPrioritySet 0
|
|
||||||
#define INCLUDE_uxTaskPriorityGet 0
|
|
||||||
#define INCLUDE_vTaskDelete 0
|
|
||||||
#define INCLUDE_vTaskCleanUpResources 0
|
|
||||||
#define INCLUDE_vTaskSuspend 0
|
|
||||||
#define INCLUDE_vTaskDelayUntil 1
|
|
||||||
#define INCLUDE_vTaskDelay 1
|
|
||||||
|
|
||||||
|
#define configUSE_MALLOC_FAILED_HOOK 1
|
||||||
|
#define configUSE_MUTEXES 1
|
||||||
|
#define configUSE_RECURSIVE_MUTEXES 1
|
||||||
|
#define configUSE_TIMERS 1
|
||||||
|
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
|
||||||
|
/*
|
||||||
|
#define INCLUDE_vTaskPrioritySet 1
|
||||||
|
#define INCLUDE_uxTaskPriorityGet 1
|
||||||
|
#define INCLUDE_vTaskDelete 1
|
||||||
|
#define INCLUDE_vTaskCleanUpResources 0
|
||||||
|
#define INCLUDE_vTaskSuspend 0
|
||||||
|
#define INCLUDE_vTaskDelayUntil 1
|
||||||
|
#define INCLUDE_vTaskDelay 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define INCLUDE_vTaskPrioritySet 1
|
||||||
|
#define INCLUDE_uxTaskPriorityGet 1
|
||||||
|
#define INCLUDE_vTaskDelete 1
|
||||||
|
#define INCLUDE_vTaskCleanUpResources 0
|
||||||
|
#define INCLUDE_vTaskSuspend 1
|
||||||
|
#define INCLUDE_vTaskDelayUntil 1
|
||||||
|
#define INCLUDE_vTaskDelay 1
|
||||||
|
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
||||||
|
#define INCLUDE_uxTaskGetStackHighWaterMark2 1
|
||||||
|
#define INCLUDE_xTaskGetSchedulerState 1
|
||||||
|
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1
|
||||||
|
#define INCLUDE_xTaskGetIdleTaskHandle 1
|
||||||
|
#define INCLUDE_xTaskGetHandle 1
|
||||||
|
#define INCLUDE_eTaskGetState 1
|
||||||
|
#define INCLUDE_xSemaphoreGetMutexHolder 1
|
||||||
|
#define INCLUDE_xTimerPendFunctionCall 1
|
||||||
|
#define INCLUDE_xTaskAbortDelay 1
|
||||||
|
|
||||||
|
unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */
|
||||||
|
|
||||||
|
#define projCOVERAGE_TEST 0
|
||||||
|
|
||||||
#define configKERNEL_INTERRUPT_PRIORITY 255
|
#define configKERNEL_INTERRUPT_PRIORITY 255
|
||||||
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
|
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
|
||||||
|
@ -24,10 +24,48 @@ INCLUDE_DIRS += -I$(FREERTOS_DIR)/Demo/CORTEX_M3_MPS2_QEMU_GCC/CMSIS
|
|||||||
INCLUDE_DIRS += -I$(KERNEL_DIR)/include
|
INCLUDE_DIRS += -I$(KERNEL_DIR)/include
|
||||||
INCLUDE_DIRS += -I$(KERNEL_DIR)/portable/GCC/ARM_CM3
|
INCLUDE_DIRS += -I$(KERNEL_DIR)/portable/GCC/ARM_CM3
|
||||||
|
|
||||||
SOURCE_FILES += main_blinky.c
|
ifeq ($(FULL_DEMO), 1)
|
||||||
CFLAGS := -DmainCREATE_SIMPLE_BLINKY_DEMO_ONLY=1
|
SOURCE_FILES += main_full.c
|
||||||
|
SOURCE_FILES += $(KERNEL_DIR)/stream_buffer.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/AbortDelay.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/BlockQ.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/blocktim.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/countsem.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/death.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/dynamic.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/EventGroupsDemo.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/flop.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/GenQTest.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/integer.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/IntSemTest.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/MessageBufferAMP.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/MessageBufferDemo.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/PollQ.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QPeek.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QueueOverwrite.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QueueSet.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QueueSetPolling.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/recmutex.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/semtest.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/StaticAllocation.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/StreamBufferDemo.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/StreamBufferInterrupt.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/TaskNotify.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/TimerDemo.c
|
||||||
|
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Full/print.c
|
||||||
|
|
||||||
DEFINES := -DprojCOVERAGE_TEST -DQEMU_SOC_MPS2 -DHEAP3
|
INCLUDE_DIRS += -I$(FREERTOS_DIR)/Demo/Common/include
|
||||||
|
INCLUDE_DIRS += -I${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/Include/
|
||||||
|
|
||||||
|
CFLAGS := -DmainCREATE_FULL_DEMO_ONLY=1
|
||||||
|
else
|
||||||
|
SOURCE_FILES += main_blinky.c
|
||||||
|
|
||||||
|
CFLAGS := -DmainCREATE_SIMPLE_BLINKY_DEMO_ONLY=1
|
||||||
|
endif
|
||||||
|
|
||||||
|
#DEFINES := -DprojCOVERAGE_TEST -DQEMU_SOC_MPS2 -DHEAP3
|
||||||
|
DEFINES := -DQEMU_SOC_MPS2 -DHEAP3
|
||||||
|
|
||||||
LDFLAGS = -T ./scripts/mps2_m3.ld -specs=nano.specs --specs=rdimon.specs -lc -lrdimon
|
LDFLAGS = -T ./scripts/mps2_m3.ld -specs=nano.specs --specs=rdimon.specs -lc -lrdimon
|
||||||
LDFLAGS += -Xlinker -Map=${BUILD_DIR}/output.map
|
LDFLAGS += -Xlinker -Map=${BUILD_DIR}/output.map
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# Emulating MPS2 Cortex M3 AN385 on QEMU
|
# Emulating MPS2 Cortex M3 AN385 on QEMU
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
1. GNU Arm Embedded Toolchain download [here](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads)
|
1. GNU Arm Embedded Toolchain download [here](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads) (tested on versiom 9.3.1 20200408)
|
||||||
3. qemu-arm-system download [here](https://www.qemu.org/download)
|
3. qemu-arm-system download [here](https://www.qemu.org/download) (tested on version 5.0.1 (v5.0.1-dirty))
|
||||||
2. Make (tested on version 3.82)
|
2. Make (tested on version 3.82)
|
||||||
4. Linux OS (tested on Ubuntu 18.04)
|
4. Linux OS (tested on Ubuntu 18.04)
|
||||||
|
|
||||||
@ -36,9 +36,40 @@ $ sudo qemu-system-arm -machine mps2-an385 -monitor null -semihosting \
|
|||||||
-serial stdio -nographic
|
-serial stdio -nographic
|
||||||
```
|
```
|
||||||
### Blinky Demo Expectations
|
### Blinky Demo Expectations
|
||||||
after running the blinky demo you shoud see on the screen the word blinking
|
After running the blinky demo you shoud see on the screen the word blinking
|
||||||
printed continuously
|
printed continuously
|
||||||
|
|
||||||
|
## Full Demo
|
||||||
|
### How to build blinky demo
|
||||||
|
Navigate with the command line to FreeRTOS/Demo/CORTEX\_M3\_MPS2\_QEMU\_GCC
|
||||||
|
For a release build run:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ export PATH=/path/to/arm/toolchain:$PATH
|
||||||
|
$ make FULL_DEMO=1
|
||||||
|
```
|
||||||
|
For a versions with debugging symbols and no optimizations **-O0**, run:
|
||||||
|
```
|
||||||
|
$ make FULL_DEMO=1 DEBUG=1
|
||||||
|
```
|
||||||
|
|
||||||
|
### How to run the Full Demo
|
||||||
|
run:
|
||||||
|
```
|
||||||
|
$ sudo qemu-system-arm -machine mps2-an385 -monitor null -semihosting \
|
||||||
|
--semihosting-config enable=on,target=native \
|
||||||
|
-kernel ./build/RTOSDemo.axf \
|
||||||
|
-serial stdio -nographic
|
||||||
|
```
|
||||||
|
### Full Demo Expectations
|
||||||
|
The full demo includes a ‘check’ that executes every (simulated) ten seconds,
|
||||||
|
but has the highest priority to ensure it gets processing time. Its main
|
||||||
|
function is to check all the standard demo tasks are still operational. The
|
||||||
|
check task maintains a status string that is output to the console each time
|
||||||
|
it executes. If all the standard demo tasks are running without error, then
|
||||||
|
the string contains “OK” and the current tick count. If an error has been
|
||||||
|
detected, then the string contains a message that indicates which task
|
||||||
|
reported the error.
|
||||||
|
|
||||||
## How to start debugging
|
## How to start debugging
|
||||||
1. gdb
|
1. gdb
|
||||||
|
58
FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/console.c
Normal file
58
FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/console.c
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS V202012.00
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Example console I/O wrappers.
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <semphr.h>
|
||||||
|
|
||||||
|
SemaphoreHandle_t xStdioMutex;
|
||||||
|
StaticSemaphore_t xStdioMutexBuffer;
|
||||||
|
|
||||||
|
void console_init(void)
|
||||||
|
{
|
||||||
|
xStdioMutex = xSemaphoreCreateMutexStatic(&xStdioMutexBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void console_print(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list vargs;
|
||||||
|
|
||||||
|
va_start(vargs, fmt);
|
||||||
|
|
||||||
|
xSemaphoreTake(xStdioMutex, portMAX_DELAY);
|
||||||
|
|
||||||
|
vprintf(fmt, vargs);
|
||||||
|
|
||||||
|
xSemaphoreGive(xStdioMutex);
|
||||||
|
|
||||||
|
va_end(vargs);
|
||||||
|
}
|
45
FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/console.h
Normal file
45
FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/console.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS V202012.00
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONSOLE_H
|
||||||
|
#define CONSOLE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Example console I/O wrappers.
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void console_init(void);
|
||||||
|
void console_print(const char *fmt, ...);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONSOLE_H */
|
@ -37,16 +37,31 @@ void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );
|
|||||||
void vApplicationMallocFailedHook( void );
|
void vApplicationMallocFailedHook( void );
|
||||||
void vApplicationIdleHook( void );
|
void vApplicationIdleHook( void );
|
||||||
void vApplicationTickHook( void );
|
void vApplicationTickHook( void );
|
||||||
|
void vFullDemoIdleFunction( void );
|
||||||
|
void vFullDemoTickHookFunction( void );
|
||||||
|
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
|
||||||
|
StackType_t **ppxTimerTaskStackBuffer,
|
||||||
|
uint32_t *pulTimerTaskStackSize );
|
||||||
|
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
|
||||||
|
StackType_t **ppxIdleTaskStackBuffer,
|
||||||
|
uint32_t *pulIdleTaskStackSize );
|
||||||
void main_blinky( void );
|
void main_blinky( void );
|
||||||
|
void main_full( void );
|
||||||
|
|
||||||
extern void initialise_monitor_handles(void);
|
extern void initialise_monitor_handles(void);
|
||||||
|
|
||||||
|
StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
|
||||||
|
|
||||||
int main ()
|
int main ()
|
||||||
{
|
{
|
||||||
#if (mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1)
|
#if (mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1)
|
||||||
{
|
{
|
||||||
main_blinky();
|
main_blinky();
|
||||||
}
|
}
|
||||||
|
#elif (mainCREATE_FULL_DEMO_ONLY == 1)
|
||||||
|
{
|
||||||
|
main_full();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
#error "Invalid Selection...\nPlease Select a Demo application from the main command"
|
#error "Invalid Selection...\nPlease Select a Demo application from the main command"
|
||||||
@ -93,11 +108,23 @@ volatile size_t xFreeHeapSpace;
|
|||||||
management options. If there is a lot of heap memory free then the
|
management options. If there is a lot of heap memory free then the
|
||||||
configTOTAL_HEAP_SIZE value in FreeRTOSConfig.h can be reduced to free up
|
configTOTAL_HEAP_SIZE value in FreeRTOSConfig.h can be reduced to free up
|
||||||
RAM. */
|
RAM. */
|
||||||
|
#if (mainCREATE_FULL_DEMO_ONLY == 1)
|
||||||
|
{
|
||||||
|
/* Call the idle task processing used by the full demo. The simple
|
||||||
|
blinky demo does not use the idle task hook. */
|
||||||
|
vFullDemoIdleFunction();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vApplicationTickHook( void )
|
void vApplicationTickHook( void )
|
||||||
{
|
{
|
||||||
|
#if (mainSELECTED_APPLICATION == FULL_DEMO )
|
||||||
|
{
|
||||||
|
vFullDemoTickHookFunction();
|
||||||
|
}
|
||||||
|
#endif /* mainSELECTED_APPLICATION */
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
@ -124,3 +151,52 @@ void vLoggingPrintf( const char *pcFormat, ... )
|
|||||||
vprintf( pcFormat, arg );
|
vprintf( pcFormat, arg );
|
||||||
va_end( arg );
|
va_end( arg );
|
||||||
}
|
}
|
||||||
|
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
|
||||||
|
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
|
||||||
|
used by the Idle task. */
|
||||||
|
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
|
||||||
|
StackType_t **ppxIdleTaskStackBuffer,
|
||||||
|
uint32_t *pulIdleTaskStackSize )
|
||||||
|
{
|
||||||
|
/* If the buffers to be provided to the Idle task are declared inside this
|
||||||
|
function then they must be declared static - otherwise they will be allocated on
|
||||||
|
the stack and so not exists after this function exits. */
|
||||||
|
static StaticTask_t xIdleTaskTCB;
|
||||||
|
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
|
||||||
|
|
||||||
|
/* Pass out a pointer to the StaticTask_t structure in which the Idle task's
|
||||||
|
state will be stored. */
|
||||||
|
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
|
||||||
|
|
||||||
|
/* Pass out the array that will be used as the Idle task's stack. */
|
||||||
|
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
|
||||||
|
|
||||||
|
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
|
||||||
|
Note that, as the array is necessarily of type StackType_t,
|
||||||
|
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
|
||||||
|
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
|
||||||
|
StackType_t **ppxTimerTaskStackBuffer,
|
||||||
|
uint32_t *pulTimerTaskStackSize )
|
||||||
|
{
|
||||||
|
/* If the buffers to be provided to the Timer task are declared inside this
|
||||||
|
function then they must be declared static - otherwise they will be allocated on
|
||||||
|
the stack and so not exists after this function exits. */
|
||||||
|
static StaticTask_t xTimerTaskTCB;
|
||||||
|
|
||||||
|
/* Pass out a pointer to the StaticTask_t structure in which the Timer
|
||||||
|
task's state will be stored. */
|
||||||
|
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
|
||||||
|
|
||||||
|
/* Pass out the array that will be used as the Timer task's stack. */
|
||||||
|
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
|
||||||
|
|
||||||
|
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
|
||||||
|
Note that, as the array is necessarily of type StackType_t,
|
||||||
|
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
|
||||||
|
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
|
||||||
|
}
|
||||||
|
905
FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_full.c
Normal file
905
FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_full.c
Normal file
@ -0,0 +1,905 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS V202012.00
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*******************************************************************************
|
||||||
|
* NOTE 1: The POSIX port is a simulation (or is that emulation?) only! Do not
|
||||||
|
* expect to get real time behaviour from the POSIX port or this demo
|
||||||
|
* application. It is provided as a convenient development and demonstration
|
||||||
|
* test bed only.
|
||||||
|
*
|
||||||
|
* Linux will not be running the FreeRTOS simulator threads continuously, so
|
||||||
|
* the timing information in the FreeRTOS+Trace logs have no meaningful units.
|
||||||
|
* See the documentation page for the Linux simulator for an explanation of
|
||||||
|
* the slow timing:
|
||||||
|
* https://freertos-wordpress.corp.amazon.com/FreeRTOS-simulator-for-Linux.html
|
||||||
|
* - READ THE WEB DOCUMENTATION FOR THIS PORT FOR MORE INFORMATION ON USING IT -
|
||||||
|
*
|
||||||
|
* NOTE 2: 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 3: This file only contains the source code that is specific to the
|
||||||
|
* full demo. Generic functions, such FreeRTOS hook functions, are defined in
|
||||||
|
* main.c.
|
||||||
|
*******************************************************************************
|
||||||
|
*
|
||||||
|
* main() creates all the demo application tasks, 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 tests are
|
||||||
|
* defined and/or created within this file:
|
||||||
|
*
|
||||||
|
* "Check" task - This only executes every five seconds but has a high priority
|
||||||
|
* to ensure it gets processor time. Its main function is to check that all the
|
||||||
|
* standard demo tasks are still operational. While no errors have been
|
||||||
|
* discovered the check task will print out "OK" and the current simulated tick
|
||||||
|
* time. If an error is discovered in the execution of a task then the check
|
||||||
|
* task will print out an appropriate error message.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* Kernel includes. */
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <task.h>
|
||||||
|
#include <queue.h>
|
||||||
|
#include <timers.h>
|
||||||
|
#include <semphr.h>
|
||||||
|
|
||||||
|
/* Standard demo includes. */
|
||||||
|
#include "BlockQ.h"
|
||||||
|
#include "integer.h"
|
||||||
|
#include "semtest.h"
|
||||||
|
#include "PollQ.h"
|
||||||
|
#include "GenQTest.h"
|
||||||
|
#include "QPeek.h"
|
||||||
|
#include "recmutex.h"
|
||||||
|
#include "flop.h"
|
||||||
|
#include "TimerDemo.h"
|
||||||
|
#include "countsem.h"
|
||||||
|
#include "death.h"
|
||||||
|
#include "dynamic.h"
|
||||||
|
#include "QueueSet.h"
|
||||||
|
#include "QueueOverwrite.h"
|
||||||
|
#include "EventGroupsDemo.h"
|
||||||
|
#include "IntSemTest.h"
|
||||||
|
#include "TaskNotify.h"
|
||||||
|
#include "QueueSetPolling.h"
|
||||||
|
#include "StaticAllocation.h"
|
||||||
|
#include "blocktim.h"
|
||||||
|
#include "AbortDelay.h"
|
||||||
|
#include "MessageBufferDemo.h"
|
||||||
|
#include "StreamBufferDemo.h"
|
||||||
|
#include "StreamBufferInterrupt.h"
|
||||||
|
#include "MessageBufferAMP.h"
|
||||||
|
#include "console.h"
|
||||||
|
|
||||||
|
/* Priorities at which the tasks are created. */
|
||||||
|
#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 2 )
|
||||||
|
#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||||
|
#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||||
|
#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||||
|
#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
|
||||||
|
#define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||||
|
#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY )
|
||||||
|
#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )
|
||||||
|
#define mainFLOP_TASK_PRIORITY ( tskIDLE_PRIORITY )
|
||||||
|
#define mainQUEUE_OVERWRITE_PRIORITY ( tskIDLE_PRIORITY )
|
||||||
|
|
||||||
|
#define mainTIMER_TEST_PERIOD ( 50 )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exercises code that is not otherwise covered by the standard demo/test
|
||||||
|
* tasks.
|
||||||
|
*/
|
||||||
|
extern BaseType_t xRunCodeCoverageTestAdditions( void );
|
||||||
|
|
||||||
|
/* Task function prototypes. */
|
||||||
|
static void prvCheckTask( void *pvParameters );
|
||||||
|
|
||||||
|
/* A task that is created from the idle task to test the functionality of
|
||||||
|
eTaskStateGet(). */
|
||||||
|
static void prvTestTask( void *pvParameters );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called from the idle task hook function to demonstrate a few utility
|
||||||
|
* functions that are not demonstrated by any of the standard demo tasks.
|
||||||
|
*/
|
||||||
|
static void prvDemonstrateTaskStateAndHandleGetFunctions( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called from the idle task hook function to demonstrate the use of
|
||||||
|
* xTimerPendFunctionCall() as xTimerPendFunctionCall() is not demonstrated by
|
||||||
|
* any of the standard demo tasks.
|
||||||
|
*/
|
||||||
|
static void prvDemonstratePendingFunctionCall( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The function that is pended by prvDemonstratePendingFunctionCall().
|
||||||
|
*/
|
||||||
|
static void prvPendedFunction( void *pvParameter1, uint32_t ulParameter2 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* prvDemonstrateTimerQueryFunctions() is called from the idle task hook
|
||||||
|
* function to demonstrate the use of functions that query information about a
|
||||||
|
* software timer. prvTestTimerCallback() is the callback function for the
|
||||||
|
* timer being queried.
|
||||||
|
*/
|
||||||
|
static void prvDemonstrateTimerQueryFunctions( void );
|
||||||
|
static void prvTestTimerCallback( TimerHandle_t xTimer );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A task to demonstrate the use of the xQueueSpacesAvailable() function.
|
||||||
|
*/
|
||||||
|
static void prvDemoQueueSpaceFunctions( void *pvParameters );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tasks that ensure indefinite delays are truly indefinite.
|
||||||
|
*/
|
||||||
|
static void prvPermanentlyBlockingSemaphoreTask( void *pvParameters );
|
||||||
|
static void prvPermanentlyBlockingNotificationTask( void *pvParameters );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The test function and callback function used when exercising the timer AP
|
||||||
|
* function that changes the timer's auto-reload mode.
|
||||||
|
*/
|
||||||
|
static void prvDemonstrateChangingTimerReloadMode( void *pvParameters );
|
||||||
|
static void prvReloadModeTestTimerCallback( TimerHandle_t xTimer );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* The variable into which error messages are latched. */
|
||||||
|
static char *pcStatusMessage = "OK: No errors";
|
||||||
|
|
||||||
|
/* This semaphore is created purely to test using the vSemaphoreDelete() and
|
||||||
|
semaphore tracing API functions. It has no other purpose. */
|
||||||
|
static SemaphoreHandle_t xMutexToDelete = NULL;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
int main_full( void )
|
||||||
|
{
|
||||||
|
/* Start the check task as described at the top of this file. */
|
||||||
|
xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );
|
||||||
|
|
||||||
|
/* Create the standard demo tasks. */
|
||||||
|
vStartTaskNotifyTask();
|
||||||
|
// vStartTaskNotifyArrayTask();
|
||||||
|
vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
|
||||||
|
vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
|
||||||
|
vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
|
||||||
|
vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );
|
||||||
|
vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );
|
||||||
|
vStartQueuePeekTasks();
|
||||||
|
vStartMathTasks( mainFLOP_TASK_PRIORITY );
|
||||||
|
vStartRecursiveMutexTasks();
|
||||||
|
vStartCountingSemaphoreTasks();
|
||||||
|
vStartDynamicPriorityTasks();
|
||||||
|
vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY );
|
||||||
|
vStartEventGroupTasks();
|
||||||
|
vStartInterruptSemaphoreTasks();
|
||||||
|
vCreateBlockTimeTasks();
|
||||||
|
vCreateAbortDelayTasks();
|
||||||
|
xTaskCreate( prvDemoQueueSpaceFunctions, "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
|
||||||
|
xTaskCreate( prvPermanentlyBlockingSemaphoreTask, "BlockSem", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
|
||||||
|
xTaskCreate( prvPermanentlyBlockingNotificationTask, "BlockNoti", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
|
||||||
|
|
||||||
|
vStartMessageBufferTasks( configMINIMAL_STACK_SIZE );
|
||||||
|
vStartStreamBufferTasks();
|
||||||
|
vStartStreamBufferInterruptDemo();
|
||||||
|
vStartMessageBufferAMPTasks( configMINIMAL_STACK_SIZE );
|
||||||
|
|
||||||
|
#if( configUSE_QUEUE_SETS == 1 )
|
||||||
|
{
|
||||||
|
vStartQueueSetTasks();
|
||||||
|
vStartQueueSetPollingTask();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
|
{
|
||||||
|
vStartStaticallyAllocatedTasks();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if( configUSE_PREEMPTION != 0 )
|
||||||
|
{
|
||||||
|
/* Don't expect these tasks to pass when preemption is not used. */
|
||||||
|
vStartTimerDemoTask( mainTIMER_TEST_PERIOD );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The suicide tasks must be created last as they need to know how many
|
||||||
|
tasks were running prior to their creation. This then allows them to
|
||||||
|
ascertain whether or not the correct/expected number of tasks are running at
|
||||||
|
any given time. */
|
||||||
|
vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
|
||||||
|
|
||||||
|
/* Create the semaphore that will be deleted in the idle task hook. This
|
||||||
|
is done purely to test the use of vSemaphoreDelete(). */
|
||||||
|
xMutexToDelete = xSemaphoreCreateMutex();
|
||||||
|
|
||||||
|
/* Start the scheduler itself. */
|
||||||
|
vTaskStartScheduler();
|
||||||
|
|
||||||
|
/* Should never get here unless there was not enough heap space to create
|
||||||
|
the idle and other system tasks. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvCheckTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
TickType_t xNextWakeTime;
|
||||||
|
const TickType_t xCycleFrequency = pdMS_TO_TICKS( 10000UL );
|
||||||
|
HeapStats_t xHeapStats;
|
||||||
|
|
||||||
|
/* Just to remove compiler warning. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
vTaskDelayUntil( &xNextWakeTime, xCycleFrequency );
|
||||||
|
|
||||||
|
/* Check the standard demo tasks are running without error. */
|
||||||
|
#if( configUSE_PREEMPTION != 0 )
|
||||||
|
{
|
||||||
|
/* These tasks are only created when preemption is used. */
|
||||||
|
if( xAreTimerDemoTasksStillRunning( xCycleFrequency ) != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: TimerDemo";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( xAreStreamBufferTasksStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: StreamBuffer";
|
||||||
|
}
|
||||||
|
else if( xAreMessageBufferTasksStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: MessageBuffer";
|
||||||
|
}
|
||||||
|
else if( xAreTaskNotificationTasksStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Notification";
|
||||||
|
}
|
||||||
|
// else if( xAreTaskNotificationArrayTasksStillRunning() != pdTRUE )
|
||||||
|
// {
|
||||||
|
// pcStatusMessage = "Error: NotificationArray";
|
||||||
|
// }
|
||||||
|
else if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: IntSem";
|
||||||
|
}
|
||||||
|
else if( xAreEventGroupTasksStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: EventGroup";
|
||||||
|
}
|
||||||
|
else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: IntMath";
|
||||||
|
}
|
||||||
|
else if( xAreGenericQueueTasksStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: GenQueue";
|
||||||
|
}
|
||||||
|
else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: QueuePeek";
|
||||||
|
}
|
||||||
|
else if( xAreBlockingQueuesStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: BlockQueue";
|
||||||
|
}
|
||||||
|
else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: SemTest";
|
||||||
|
}
|
||||||
|
else if( xArePollingQueuesStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: PollQueue";
|
||||||
|
}
|
||||||
|
else if( xAreMathsTaskStillRunning() != pdPASS )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Flop";
|
||||||
|
}
|
||||||
|
else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: RecMutex";
|
||||||
|
}
|
||||||
|
else if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: CountSem";
|
||||||
|
}
|
||||||
|
else if( xIsCreateTaskStillRunning() != pdTRUE )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Death";
|
||||||
|
}
|
||||||
|
else if( xAreDynamicPriorityTasksStillRunning() != pdPASS )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Dynamic";
|
||||||
|
}
|
||||||
|
else if( xIsQueueOverwriteTaskStillRunning() != pdPASS )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Queue overwrite";
|
||||||
|
}
|
||||||
|
else if( xAreBlockTimeTestTasksStillRunning() != pdPASS )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Block time";
|
||||||
|
}
|
||||||
|
else if( xAreAbortDelayTestTasksStillRunning() != pdPASS )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Abort delay";
|
||||||
|
}
|
||||||
|
else if( xIsInterruptStreamBufferDemoStillRunning() != pdPASS )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Stream buffer interrupt";
|
||||||
|
}
|
||||||
|
else if( xAreMessageBufferAMPTasksStillRunning() != pdPASS )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Message buffer AMP";
|
||||||
|
}
|
||||||
|
|
||||||
|
#if( configUSE_QUEUE_SETS == 1 )
|
||||||
|
else if( xAreQueueSetTasksStillRunning() != pdPASS )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Queue set";
|
||||||
|
}
|
||||||
|
else if( xAreQueueSetPollTasksStillRunning() != pdPASS )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Queue set polling";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
|
else if( xAreStaticAllocationTasksStillRunning() != pdPASS )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Static allocation";
|
||||||
|
}
|
||||||
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||||
|
|
||||||
|
printf( "%s - tick count %u \r\n",
|
||||||
|
pcStatusMessage,
|
||||||
|
xTaskGetTickCount() );
|
||||||
|
|
||||||
|
// Reset the error condition
|
||||||
|
pcStatusMessage = "OK: No errors";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTestTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
const unsigned long ulMSToSleep = 5;
|
||||||
|
|
||||||
|
/* Just to remove compiler warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* This task is just used to test the eTaskStateGet() function. It
|
||||||
|
does not have anything to do. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Sleep to reduce CPU load, but don't sleep indefinitely in case there are
|
||||||
|
tasks waiting to be terminated by the idle task. */
|
||||||
|
vTaskDelay( pdMS_TO_TICKS( ulMSToSleep ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Called from vApplicationIdleHook(), which is defined in main.c. */
|
||||||
|
void vFullDemoIdleFunction( void )
|
||||||
|
{
|
||||||
|
const unsigned long ulMSToSleep = 15;
|
||||||
|
void *pvAllocated;
|
||||||
|
|
||||||
|
/* Sleep to reduce CPU load, but don't sleep indefinitely in case there are
|
||||||
|
tasks waiting to be terminated by the idle task. */
|
||||||
|
vTaskDelay( pdMS_TO_TICKS( ulMSToSleep ) );
|
||||||
|
|
||||||
|
/* Demonstrate a few utility functions that are not demonstrated by any of
|
||||||
|
the standard demo tasks. */
|
||||||
|
prvDemonstrateTaskStateAndHandleGetFunctions();
|
||||||
|
|
||||||
|
/* Demonstrate the use of xTimerPendFunctionCall(), which is not
|
||||||
|
demonstrated by any of the standard demo tasks. */
|
||||||
|
prvDemonstratePendingFunctionCall();
|
||||||
|
|
||||||
|
/* Demonstrate the use of functions that query information about a software
|
||||||
|
timer. */
|
||||||
|
prvDemonstrateTimerQueryFunctions();
|
||||||
|
|
||||||
|
/* If xMutexToDelete has not already been deleted, then delete it now.
|
||||||
|
This is done purely to demonstrate the use of, and test, the
|
||||||
|
vSemaphoreDelete() macro. Care must be taken not to delete a semaphore
|
||||||
|
that has tasks blocked on it. */
|
||||||
|
if( xMutexToDelete != NULL )
|
||||||
|
{
|
||||||
|
/* For test purposes, add the mutex to the registry, then remove it
|
||||||
|
again, before it is deleted - checking its name is as expected before
|
||||||
|
and after the assertion into the registry and its removal from the
|
||||||
|
registry. */
|
||||||
|
configASSERT( pcQueueGetName( xMutexToDelete ) == NULL );
|
||||||
|
vQueueAddToRegistry( xMutexToDelete, "Test_Mutex" );
|
||||||
|
configASSERT( strcmp( pcQueueGetName( xMutexToDelete ), "Test_Mutex" ) == 0 );
|
||||||
|
vQueueUnregisterQueue( xMutexToDelete );
|
||||||
|
configASSERT( pcQueueGetName( xMutexToDelete ) == NULL );
|
||||||
|
|
||||||
|
vSemaphoreDelete( xMutexToDelete );
|
||||||
|
xMutexToDelete = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exercise heap_5 a bit. The malloc failed hook will trap failed
|
||||||
|
allocations so there is no need to test here. */
|
||||||
|
pvAllocated = pvPortMalloc( ( rand() % 500 ) + 1 );
|
||||||
|
vPortFree( pvAllocated );
|
||||||
|
|
||||||
|
/* Exit after a fixed time so code coverage results are written to the
|
||||||
|
disk. */
|
||||||
|
#if( projCOVERAGE_TEST == 1 )
|
||||||
|
{
|
||||||
|
const TickType_t xMaxRunTime = pdMS_TO_TICKS( 30000UL );
|
||||||
|
|
||||||
|
/* Exercise code not otherwise executed by standard demo/test tasks. */
|
||||||
|
if( xRunCodeCoverageTestAdditions() != pdPASS )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Code coverage additions failed.\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( xTaskGetTickCount() - configINITIAL_TICK_COUNT ) >= xMaxRunTime )
|
||||||
|
{
|
||||||
|
vTaskEndScheduler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Called by vApplicationTickHook(), which is defined in main.c. */
|
||||||
|
void vFullDemoTickHookFunction( void )
|
||||||
|
{
|
||||||
|
TaskHandle_t xTimerTask;
|
||||||
|
|
||||||
|
/* Call the periodic timer test, which tests the timer API functions that
|
||||||
|
can be called from an ISR. */
|
||||||
|
#if( configUSE_PREEMPTION != 0 )
|
||||||
|
{
|
||||||
|
/* Only created when preemption is used. */
|
||||||
|
vTimerPeriodicISRTests();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Call the periodic queue overwrite from ISR demo. */
|
||||||
|
vQueueOverwritePeriodicISRDemo();
|
||||||
|
|
||||||
|
#if( configUSE_QUEUE_SETS == 1 ) /* Remove the tests if queue sets are not defined. */
|
||||||
|
{
|
||||||
|
/* Write to a queue that is in use as part of the queue set demo to
|
||||||
|
demonstrate using queue sets from an ISR. */
|
||||||
|
vQueueSetAccessQueueSetFromISR();
|
||||||
|
vQueueSetPollingInterruptAccess();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Exercise event groups from interrupts. */
|
||||||
|
vPeriodicEventGroupsProcessing();
|
||||||
|
|
||||||
|
/* Exercise giving mutexes from an interrupt. */
|
||||||
|
vInterruptSemaphorePeriodicTest();
|
||||||
|
|
||||||
|
/* Exercise using task notifications from an interrupt. */
|
||||||
|
xNotifyTaskFromISR();
|
||||||
|
// xNotifyArrayTaskFromISR();
|
||||||
|
|
||||||
|
/* Writes to stream buffer byte by byte to test the stream buffer trigger
|
||||||
|
level functionality. */
|
||||||
|
vPeriodicStreamBufferProcessing();
|
||||||
|
|
||||||
|
/* Writes a string to a string buffer four bytes at a time to demonstrate
|
||||||
|
a stream being sent from an interrupt to a task. */
|
||||||
|
vBasicStreamBufferSendFromISR();
|
||||||
|
|
||||||
|
/* For code coverage purposes. */
|
||||||
|
xTimerTask = xTimerGetTimerDaemonTaskHandle();
|
||||||
|
configASSERT( uxTaskPriorityGetFromISR( xTimerTask ) == configTIMER_TASK_PRIORITY );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvPendedFunction( void *pvParameter1, uint32_t ulParameter2 )
|
||||||
|
{
|
||||||
|
static intptr_t ulLastParameter1 = 1000UL, ulLastParameter2 = 0UL;
|
||||||
|
intptr_t ulParameter1;
|
||||||
|
|
||||||
|
ulParameter1 = ( intptr_t ) pvParameter1;
|
||||||
|
|
||||||
|
/* Ensure the parameters are as expected. */
|
||||||
|
configASSERT( ulParameter1 == ( ulLastParameter1 + 1 ) );
|
||||||
|
configASSERT( ulParameter2 == ( ulLastParameter2 + 1 ) );
|
||||||
|
|
||||||
|
/* Remember the parameters for the next time the function is called. */
|
||||||
|
ulLastParameter1 = ulParameter1;
|
||||||
|
ulLastParameter2 = ulParameter2;
|
||||||
|
|
||||||
|
/* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
|
( void ) ulLastParameter1;
|
||||||
|
( void ) ulLastParameter2;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTestTimerCallback( TimerHandle_t xTimer )
|
||||||
|
{
|
||||||
|
/* This is the callback function for the timer accessed by
|
||||||
|
prvDemonstrateTimerQueryFunctions(). The callback does not do anything. */
|
||||||
|
( void ) xTimer;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvDemonstrateTimerQueryFunctions( void )
|
||||||
|
{
|
||||||
|
static TimerHandle_t xTimer = NULL;
|
||||||
|
const char *pcTimerName = "TestTimer";
|
||||||
|
volatile TickType_t xExpiryTime;
|
||||||
|
const TickType_t xDontBlock = 0;
|
||||||
|
|
||||||
|
if( xTimer == NULL )
|
||||||
|
{
|
||||||
|
xTimer = xTimerCreate( pcTimerName, portMAX_DELAY, pdTRUE, NULL, prvTestTimerCallback );
|
||||||
|
|
||||||
|
if( xTimer != NULL )
|
||||||
|
{
|
||||||
|
/* Called from the idle task so a block time must not be
|
||||||
|
specified. */
|
||||||
|
xTimerStart( xTimer, xDontBlock );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xTimer != NULL )
|
||||||
|
{
|
||||||
|
/* Demonstrate querying a timer's name. */
|
||||||
|
configASSERT( strcmp( pcTimerGetName( xTimer ), pcTimerName ) == 0 );
|
||||||
|
|
||||||
|
/* Demonstrate querying a timer's period. */
|
||||||
|
configASSERT( xTimerGetPeriod( xTimer ) == portMAX_DELAY );
|
||||||
|
|
||||||
|
/* Demonstrate querying a timer's next expiry time, although nothing is
|
||||||
|
done with the returned value. Note if the expiry time is less than the
|
||||||
|
maximum tick count then the expiry time has overflowed from the current
|
||||||
|
time. In this case the expiry time was set to portMAX_DELAY, so it is
|
||||||
|
expected to be less than the current time until the current time has
|
||||||
|
itself overflowed. */
|
||||||
|
xExpiryTime = xTimerGetExpiryTime( xTimer );
|
||||||
|
( void ) xExpiryTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvDemonstratePendingFunctionCall( void )
|
||||||
|
{
|
||||||
|
static intptr_t ulParameter1 = 1000UL, ulParameter2 = 0UL;
|
||||||
|
const TickType_t xDontBlock = 0; /* This is called from the idle task so must *not* attempt to block. */
|
||||||
|
|
||||||
|
/* prvPendedFunction() just expects the parameters to be incremented by one
|
||||||
|
each time it is called. */
|
||||||
|
ulParameter1++;
|
||||||
|
ulParameter2++;
|
||||||
|
|
||||||
|
/* Pend the function call, sending the parameters. */
|
||||||
|
xTimerPendFunctionCall( prvPendedFunction, ( void * ) ulParameter1, ulParameter2, xDontBlock );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvDemonstrateTaskStateAndHandleGetFunctions( void )
|
||||||
|
{
|
||||||
|
TaskHandle_t xIdleTaskHandle, xTimerTaskHandle;
|
||||||
|
char *pcTaskName;
|
||||||
|
static portBASE_TYPE xPerformedOneShotTests = pdFALSE;
|
||||||
|
TaskHandle_t xTestTask;
|
||||||
|
TaskStatus_t xTaskInfo;
|
||||||
|
extern StackType_t uxTimerTaskStack[];
|
||||||
|
|
||||||
|
/* Demonstrate the use of the xTimerGetTimerDaemonTaskHandle() and
|
||||||
|
xTaskGetIdleTaskHandle() functions. Also try using the function that sets
|
||||||
|
the task number. */
|
||||||
|
xIdleTaskHandle = xTaskGetIdleTaskHandle();
|
||||||
|
xTimerTaskHandle = xTimerGetTimerDaemonTaskHandle();
|
||||||
|
|
||||||
|
/* This is the idle hook, so the current task handle should equal the
|
||||||
|
returned idle task handle. */
|
||||||
|
if( xTaskGetCurrentTaskHandle() != xIdleTaskHandle )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Returned idle task handle was incorrect";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the same handle is obtained using the idle task's name. First try
|
||||||
|
with the wrong name, then the right name. */
|
||||||
|
if( xTaskGetHandle( "Idle" ) == xIdleTaskHandle )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Returned handle for name Idle was incorrect";
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xTaskGetHandle( "IDLE" ) != xIdleTaskHandle )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Returned handle for name Idle was incorrect";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the timer task handle was returned correctly. */
|
||||||
|
pcTaskName = pcTaskGetName( xTimerTaskHandle );
|
||||||
|
if( strcmp( pcTaskName, "Tmr Svc" ) != 0 )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Returned timer task handle was incorrect";
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xTaskGetHandle( "Tmr Svc" ) != xTimerTaskHandle )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Returned handle for name Tmr Svc was incorrect";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This task is running, make sure it's state is returned as running. */
|
||||||
|
if( eTaskStateGet( xIdleTaskHandle ) != eRunning )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Returned idle task state was incorrect";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this task is running, then the timer task must be blocked. */
|
||||||
|
if( eTaskStateGet( xTimerTaskHandle ) != eBlocked )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Returned timer task state was incorrect";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Also with the vTaskGetInfo() function. */
|
||||||
|
vTaskGetInfo( xTimerTaskHandle, /* The task being queried. */
|
||||||
|
&xTaskInfo, /* The structure into which information on the task will be written. */
|
||||||
|
pdTRUE, /* Include the task's high watermark in the structure. */
|
||||||
|
eInvalid ); /* Include the task state in the structure. */
|
||||||
|
|
||||||
|
/* Check the information returned by vTaskGetInfo() is as expected. */
|
||||||
|
if( ( xTaskInfo.eCurrentState != eBlocked ) ||
|
||||||
|
( strcmp( xTaskInfo.pcTaskName, "Tmr Svc" ) != 0 ) ||
|
||||||
|
( xTaskInfo.uxCurrentPriority != configTIMER_TASK_PRIORITY ) ||
|
||||||
|
( xTaskInfo.pxStackBase != uxTimerTaskStack ) ||
|
||||||
|
( xTaskInfo.xHandle != xTimerTaskHandle ) )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: vTaskGetInfo() returned incorrect information about the timer task";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Other tests that should only be performed once follow. The test task
|
||||||
|
is not created on each iteration because to do so would cause the death
|
||||||
|
task to report an error (too many tasks running). */
|
||||||
|
if( xPerformedOneShotTests == pdFALSE )
|
||||||
|
{
|
||||||
|
/* Don't run this part of the test again. */
|
||||||
|
xPerformedOneShotTests = pdTRUE;
|
||||||
|
|
||||||
|
/* Create a test task to use to test other eTaskStateGet() return values. */
|
||||||
|
if( xTaskCreate( prvTestTask, "Test", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xTestTask ) == pdPASS )
|
||||||
|
{
|
||||||
|
/* If this task is running, the test task must be in the ready state. */
|
||||||
|
if( eTaskStateGet( xTestTask ) != eReady )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Returned test task state was incorrect 1";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now suspend the test task and check its state is reported correctly. */
|
||||||
|
vTaskSuspend( xTestTask );
|
||||||
|
if( eTaskStateGet( xTestTask ) != eSuspended )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Returned test task state was incorrect 2";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now delete the task and check its state is reported correctly. */
|
||||||
|
vTaskDelete( xTestTask );
|
||||||
|
if( eTaskStateGet( xTestTask ) != eDeleted )
|
||||||
|
{
|
||||||
|
pcStatusMessage = "Error: Returned test task state was incorrect 3";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvDemoQueueSpaceFunctions( void *pvParameters )
|
||||||
|
{
|
||||||
|
QueueHandle_t xQueue = NULL;
|
||||||
|
const unsigned portBASE_TYPE uxQueueLength = 10;
|
||||||
|
unsigned portBASE_TYPE uxReturn, x;
|
||||||
|
|
||||||
|
/* Remove compiler warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Create the queue that will be used. Nothing is actually going to be
|
||||||
|
sent or received so the queue item size is set to 0. */
|
||||||
|
xQueue = xQueueCreate( uxQueueLength, 0 );
|
||||||
|
configASSERT( xQueue );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
for( x = 0; x < uxQueueLength; x++ )
|
||||||
|
{
|
||||||
|
/* Ask how many messages are available... */
|
||||||
|
uxReturn = uxQueueMessagesWaiting( xQueue );
|
||||||
|
|
||||||
|
/* Check the number of messages being reported as being available
|
||||||
|
is as expected, and force an assert if not. */
|
||||||
|
if( uxReturn != x )
|
||||||
|
{
|
||||||
|
/* xQueue cannot be NULL so this is deliberately causing an
|
||||||
|
assert to be triggered as there is an error. */
|
||||||
|
configASSERT( xQueue == NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ask how many spaces remain in the queue... */
|
||||||
|
uxReturn = uxQueueSpacesAvailable( xQueue );
|
||||||
|
|
||||||
|
/* Check the number of spaces being reported as being available
|
||||||
|
is as expected, and force an assert if not. */
|
||||||
|
if( uxReturn != ( uxQueueLength - x ) )
|
||||||
|
{
|
||||||
|
/* xQueue cannot be NULL so this is deliberately causing an
|
||||||
|
assert to be triggered as there is an error. */
|
||||||
|
configASSERT( xQueue == NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill one more space in the queue. */
|
||||||
|
xQueueSendToBack( xQueue, NULL, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform the same check while the queue is full. */
|
||||||
|
uxReturn = uxQueueMessagesWaiting( xQueue );
|
||||||
|
if( uxReturn != uxQueueLength )
|
||||||
|
{
|
||||||
|
configASSERT( xQueue == NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
uxReturn = uxQueueSpacesAvailable( xQueue );
|
||||||
|
|
||||||
|
if( uxReturn != 0 )
|
||||||
|
{
|
||||||
|
configASSERT( xQueue == NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The queue is full, start again. */
|
||||||
|
xQueueReset( xQueue );
|
||||||
|
|
||||||
|
#if( configUSE_PREEMPTION == 0 )
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvPermanentlyBlockingSemaphoreTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
SemaphoreHandle_t xSemaphore;
|
||||||
|
|
||||||
|
/* Prevent compiler warning about unused parameter in the case that
|
||||||
|
configASSERT() is not defined. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* This task should block on a semaphore, and never return. */
|
||||||
|
xSemaphore = xSemaphoreCreateBinary();
|
||||||
|
configASSERT( xSemaphore );
|
||||||
|
|
||||||
|
xSemaphoreTake( xSemaphore, portMAX_DELAY );
|
||||||
|
|
||||||
|
/* The above xSemaphoreTake() call should never return, force an assert if
|
||||||
|
it does. */
|
||||||
|
configASSERT( pvParameters != NULL );
|
||||||
|
vTaskDelete( NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvPermanentlyBlockingNotificationTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
/* Prevent compiler warning about unused parameter in the case that
|
||||||
|
configASSERT() is not defined. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* This task should block on a task notification, and never return. */
|
||||||
|
ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
|
||||||
|
|
||||||
|
/* The above ulTaskNotifyTake() call should never return, force an assert
|
||||||
|
if it does. */
|
||||||
|
configASSERT( pvParameters != NULL );
|
||||||
|
vTaskDelete( NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvReloadModeTestTimerCallback( TimerHandle_t xTimer )
|
||||||
|
{
|
||||||
|
intptr_t ulTimerID;
|
||||||
|
|
||||||
|
/* Increment the timer's ID to show the callback has executed. */
|
||||||
|
ulTimerID = ( intptr_t ) pvTimerGetTimerID( xTimer );
|
||||||
|
ulTimerID++;
|
||||||
|
vTimerSetTimerID( xTimer, ( void * ) ulTimerID );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvDemonstrateChangingTimerReloadMode( void *pvParameters )
|
||||||
|
{
|
||||||
|
TimerHandle_t xTimer;
|
||||||
|
const char * const pcTimerName = "TestTimer";
|
||||||
|
const TickType_t x100ms = pdMS_TO_TICKS( 100UL );
|
||||||
|
|
||||||
|
/* Avoid compiler warnings about unused parameter. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
xTimer = xTimerCreate( pcTimerName,
|
||||||
|
x100ms,
|
||||||
|
pdFALSE, /* Created as a one-shot timer. */
|
||||||
|
0,
|
||||||
|
prvReloadModeTestTimerCallback );
|
||||||
|
configASSERT( xTimer );
|
||||||
|
configASSERT( xTimerIsTimerActive( xTimer ) == pdFALSE );
|
||||||
|
configASSERT( xTimerGetTimerDaemonTaskHandle() != NULL );
|
||||||
|
configASSERT( strcmp( pcTimerName, pcTimerGetName( xTimer ) ) == 0 );
|
||||||
|
configASSERT( xTimerGetPeriod( xTimer ) == x100ms );
|
||||||
|
|
||||||
|
/* Timer was created as a one-shot timer. Its callback just increments the
|
||||||
|
timer's ID - so set the ID to 0, let the timer run for a number of timeout
|
||||||
|
periods, then check the timer has only executed once. */
|
||||||
|
vTimerSetTimerID( xTimer, ( void * ) 0 );
|
||||||
|
xTimerStart( xTimer, portMAX_DELAY );
|
||||||
|
vTaskDelay( 3UL * x100ms );
|
||||||
|
configASSERT( ( ( uintptr_t ) ( pvTimerGetTimerID( xTimer ) ) ) == 1UL );
|
||||||
|
|
||||||
|
/* Now change the timer to be an auto-reload timer and check it executes
|
||||||
|
the expected number of times. */
|
||||||
|
vTimerSetReloadMode( xTimer, pdTRUE );
|
||||||
|
vTimerSetTimerID( xTimer, ( void * ) 0 );
|
||||||
|
xTimerStart( xTimer, 0 );
|
||||||
|
vTaskDelay( ( 3UL * x100ms ) + ( x100ms / 2UL ) ); /* Three full periods. */
|
||||||
|
configASSERT( ( uintptr_t ) ( pvTimerGetTimerID( xTimer ) ) == 3UL );
|
||||||
|
configASSERT( xTimerStop( xTimer, 0 ) != pdFAIL );
|
||||||
|
|
||||||
|
/* Now change the timer back to be a one-shot timer and check it only
|
||||||
|
executes once. */
|
||||||
|
vTimerSetReloadMode( xTimer, pdFALSE );
|
||||||
|
vTimerSetTimerID( xTimer, ( void * ) 0 );
|
||||||
|
xTimerStart( xTimer, 0 );
|
||||||
|
vTaskDelay( 3UL * x100ms );
|
||||||
|
configASSERT( xTimerStop( xTimer, 0 ) != pdFAIL );
|
||||||
|
configASSERT( ( uintptr_t ) ( pvTimerGetTimerID( xTimer ) ) == 1UL );
|
||||||
|
|
||||||
|
/* Clean up at the end. */
|
||||||
|
xTimerDelete( xTimer, portMAX_DELAY );
|
||||||
|
vTaskDelete( NULL );
|
||||||
|
}
|
@ -31,7 +31,7 @@ MEMORY
|
|||||||
}
|
}
|
||||||
ENTRY(Reset_Handler)
|
ENTRY(Reset_Handler)
|
||||||
|
|
||||||
_Min_Heap_Size = 0x40000 ; /* Required amount of heap. */
|
_Min_Heap_Size = 0x300000 ; /* Required amount of heap. */
|
||||||
_Min_Stack_Size = 0x4000 ; /* Required amount of stack. */
|
_Min_Stack_Size = 0x4000 ; /* Required amount of stack. */
|
||||||
M_VECTOR_RAM_SIZE = (16 + 48) * 4;
|
M_VECTOR_RAM_SIZE = (16 + 48) * 4;
|
||||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||||
|
@ -19,10 +19,9 @@
|
|||||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*
|
*
|
||||||
* http://www.FreeRTOS.org
|
* https://www.FreeRTOS.org
|
||||||
* http://aws.amazon.com/freertos
|
* https://github.com/FreeRTOS
|
||||||
*
|
*
|
||||||
* 1 tab == 4 spaces!
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,8 +46,8 @@
|
|||||||
/*
|
/*
|
||||||
Changes from V2.0.0
|
Changes from V2.0.0
|
||||||
|
|
||||||
+ Delay periods are now specified using variables and constants of
|
+ Delay periods are now specified using variables and constants of
|
||||||
TickType_t rather than unsigned long.
|
TickType_t rather than unsigned long.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -61,7 +60,7 @@ Changes from V2.0.0
|
|||||||
#include "death.h"
|
#include "death.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
|
||||||
#define deathSTACK_SIZE ( ( unsigned short ) 512 )
|
#define deathSTACK_SIZE ( ( unsigned short ) 512 )
|
||||||
|
|
||||||
/* The task originally created which is responsible for periodically dynamically
|
/* The task originally created which is responsible for periodically dynamically
|
||||||
creating another four tasks. */
|
creating another four tasks. */
|
||||||
@ -89,16 +88,16 @@ void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority )
|
|||||||
{
|
{
|
||||||
unsigned portBASE_TYPE *puxPriority;
|
unsigned portBASE_TYPE *puxPriority;
|
||||||
|
|
||||||
/* Create the Creator tasks - passing in as a parameter the priority at which
|
/* Create the Creator tasks - passing in as a parameter the priority at which
|
||||||
the suicidal tasks should be created. */
|
the suicidal tasks should be created. */
|
||||||
puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) );
|
puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) );
|
||||||
*puxPriority = uxPriority;
|
*puxPriority = uxPriority;
|
||||||
|
|
||||||
xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL );
|
xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL );
|
||||||
|
|
||||||
/* Record the number of tasks that are running now so we know if any of the
|
/* Record the number of tasks that are running now so we know if any of the
|
||||||
suicidal tasks have failed to be killed. */
|
suicidal tasks have failed to be killed. */
|
||||||
uxTasksRunningAtStart = uxTaskGetNumberOfTasks();
|
uxTasksRunningAtStart = uxTaskGetNumberOfTasks();
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
@ -108,36 +107,36 @@ portDOUBLE d1, d2;
|
|||||||
TaskHandle_t xTaskToKill;
|
TaskHandle_t xTaskToKill;
|
||||||
const TickType_t xDelay = ( TickType_t ) 500 / portTICK_PERIOD_MS;
|
const TickType_t xDelay = ( TickType_t ) 500 / portTICK_PERIOD_MS;
|
||||||
|
|
||||||
if( pvParameters != NULL )
|
if( pvParameters != NULL )
|
||||||
{
|
{
|
||||||
/* This task is periodically created four times. Tow created tasks are
|
/* This task is periodically created four times. Tow created tasks are
|
||||||
passed a handle to the other task so it can kill it before killing itself.
|
passed a handle to the other task so it can kill it before killing itself.
|
||||||
The other task is passed in null. */
|
The other task is passed in null. */
|
||||||
xTaskToKill = *( TaskHandle_t* )pvParameters;
|
xTaskToKill = *( TaskHandle_t* )pvParameters;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xTaskToKill = NULL;
|
xTaskToKill = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( ;; )
|
for( ;; )
|
||||||
{
|
{
|
||||||
/* Do something random just to use some stack and registers. */
|
/* Do something random just to use some stack and registers. */
|
||||||
d1 = 2.4;
|
d1 = 2.4;
|
||||||
d2 = 89.2;
|
d2 = 89.2;
|
||||||
d2 *= d1;
|
d2 *= d1;
|
||||||
vTaskDelay( xDelay );
|
vTaskDelay( xDelay );
|
||||||
|
|
||||||
if( xTaskToKill != NULL )
|
if( xTaskToKill != NULL )
|
||||||
{
|
{
|
||||||
/* Make sure the other task has a go before we delete it. */
|
/* Make sure the other task has a go before we delete it. */
|
||||||
vTaskDelay( ( TickType_t ) 0 );
|
vTaskDelay( ( TickType_t ) 0 );
|
||||||
/* Kill the other task that was created by vCreateTasks(). */
|
/* Kill the other task that was created by vCreateTasks(). */
|
||||||
vTaskDelete( xTaskToKill );
|
vTaskDelete( xTaskToKill );
|
||||||
/* Kill ourselves. */
|
/* Kill ourselves. */
|
||||||
vTaskDelete( NULL );
|
vTaskDelete( NULL );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}/*lint !e818 !e550 Function prototype must be as per standard for task functions. */
|
}/*lint !e818 !e550 Function prototype must be as per standard for task functions. */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
@ -147,25 +146,25 @@ const TickType_t xDelay = ( TickType_t ) 1000 / portTICK_PERIOD_MS;
|
|||||||
unsigned portBASE_TYPE uxPriority;
|
unsigned portBASE_TYPE uxPriority;
|
||||||
const char * const pcTaskStartMsg = "Create task started.\r\n";
|
const char * const pcTaskStartMsg = "Create task started.\r\n";
|
||||||
|
|
||||||
/* Queue a message for printing to say the task has started. */
|
/* Queue a message for printing to say the task has started. */
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
uxPriority = *( unsigned portBASE_TYPE * ) pvParameters;
|
uxPriority = *( unsigned portBASE_TYPE * ) pvParameters;
|
||||||
vPortFree( pvParameters );
|
vPortFree( pvParameters );
|
||||||
|
|
||||||
for( ;; )
|
for( ;; )
|
||||||
{
|
{
|
||||||
/* Just loop round, delaying then creating the four suicidal tasks. */
|
/* Just loop round, delaying then creating the four suicidal tasks. */
|
||||||
vTaskDelay( xDelay );
|
vTaskDelay( xDelay );
|
||||||
|
|
||||||
xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask1 );
|
xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask1 );
|
||||||
xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask1, uxPriority, NULL );
|
xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask1, uxPriority, NULL );
|
||||||
|
|
||||||
xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask2 );
|
xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask2 );
|
||||||
xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask2, uxPriority, NULL );
|
xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask2, uxPriority, NULL );
|
||||||
|
|
||||||
++sCreationCount;
|
++sCreationCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
@ -177,27 +176,28 @@ static short sLastCreationCount = 0;
|
|||||||
short sReturn = pdTRUE;
|
short sReturn = pdTRUE;
|
||||||
unsigned portBASE_TYPE uxTasksRunningNow;
|
unsigned portBASE_TYPE uxTasksRunningNow;
|
||||||
|
|
||||||
if( sLastCreationCount == sCreationCount )
|
if( sLastCreationCount == sCreationCount )
|
||||||
{
|
{
|
||||||
sReturn = pdFALSE;
|
sReturn = pdFALSE;
|
||||||
}
|
}
|
||||||
|
sLastCreationCount = sCreationCount;
|
||||||
uxTasksRunningNow = uxTaskGetNumberOfTasks();
|
|
||||||
|
|
||||||
if( uxTasksRunningNow < uxTasksRunningAtStart )
|
uxTasksRunningNow = uxTaskGetNumberOfTasks();
|
||||||
{
|
|
||||||
sReturn = pdFALSE;
|
|
||||||
}
|
|
||||||
else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning )
|
|
||||||
{
|
|
||||||
sReturn = pdFALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Everything is okay. */
|
|
||||||
}
|
|
||||||
|
|
||||||
return sReturn;
|
if( uxTasksRunningNow < uxTasksRunningAtStart )
|
||||||
|
{
|
||||||
|
sReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning )
|
||||||
|
{
|
||||||
|
sReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Everything is okay. */
|
||||||
|
}
|
||||||
|
|
||||||
|
return sReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user