From 020aedc9bb9744b3773d2f27ae0a98d5145e024e Mon Sep 17 00:00:00 2001 From: pvvx Date: Fri, 7 Apr 2017 17:47:33 +0300 Subject: [PATCH] update --- .cproject | 2 +- .settings/language.settings.xml | 6 +- .../freertos_v8.1.2/Demo/Common/Full/BlockQ.c | 346 ++ .../freertos_v8.1.2/Demo/Common/Full/PollQ.c | 258 + .../Demo/Common/Full/comtest.c | 384 ++ .../freertos_v8.1.2/Demo/Common/Full/death.c | 241 + .../Demo/Common/Full/dynamic.c | 616 +++ .../freertos_v8.1.2/Demo/Common/Full/events.c | 406 ++ .../freertos_v8.1.2/Demo/Common/Full/flash.c | 166 + .../freertos_v8.1.2/Demo/Common/Full/flop.c | 369 ++ .../Demo/Common/Full/integer.c | 365 ++ .../freertos_v8.1.2/Demo/Common/Full/print.c | 144 + .../Demo/Common/Full/semtest.c | 323 ++ .../Demo/Common/Minimal/AltBlckQ.c | 332 ++ .../Demo/Common/Minimal/AltBlock.c | 549 ++ .../Demo/Common/Minimal/AltPollQ.c | 275 + .../Demo/Common/Minimal/AltQTest.c | 587 +++ .../Demo/Common/Minimal/BlockQ.c | 324 ++ .../Demo/Common/Minimal/EventGroupsDemo.c | 1074 ++++ .../Demo/Common/Minimal/GenQTest.c | 857 +++ .../Demo/Common/Minimal/IntQueue.c | 760 +++ .../Demo/Common/Minimal/PollQ.c | 258 + .../Demo/Common/Minimal/QPeek.c | 474 ++ .../Demo/Common/Minimal/QueueOverwrite.c | 268 + .../Demo/Common/Minimal/QueueSet.c | 715 +++ .../Demo/Common/Minimal/TimerDemo.c | 1079 ++++ .../Demo/Common/Minimal/blocktim.c | 505 ++ .../Demo/Common/Minimal/comtest.c | 303 ++ .../Demo/Common/Minimal/comtest_strings.c | 349 ++ .../Demo/Common/Minimal/countsem.c | 322 ++ .../Demo/Common/Minimal/crflash.c | 246 + .../Demo/Common/Minimal/crhook.c | 270 + .../Demo/Common/Minimal/death.c | 254 + .../Demo/Common/Minimal/dynamic.c | 511 ++ .../Demo/Common/Minimal/flash.c | 157 + .../Demo/Common/Minimal/flash_timer.c | 136 + .../Demo/Common/Minimal/flop.c | 383 ++ .../Demo/Common/Minimal/integer.c | 201 + .../Demo/Common/Minimal/recmutex.c | 440 ++ .../Demo/Common/Minimal/semtest.c | 298 ++ .../Demo/Common/Minimal/sp_flop.c | 365 ++ .../Demo/Common/include/AltBlckQ.h | 74 + .../Demo/Common/include/AltBlock.h | 74 + .../Demo/Common/include/AltPollQ.h | 74 + .../Demo/Common/include/AltQTest.h | 75 + .../Demo/Common/include/BlockQ.h | 74 + .../Demo/Common/include/EventGroupsDemo.h | 82 + .../Demo/Common/include/GenQTest.h | 76 + .../Demo/Common/include/IntQueue.h | 80 + .../Demo/Common/include/PollQ.h | 74 + .../Demo/Common/include/QPeek.h | 75 + .../Demo/Common/include/QueueOverwrite.h | 75 + .../Demo/Common/include/QueueSet.h | 75 + .../Demo/Common/include/TimerDemo.h | 76 + .../Demo/Common/include/blocktim.h | 74 + .../Demo/Common/include/comtest.h | 75 + .../Demo/Common/include/comtest2.h | 73 + .../Demo/Common/include/comtest_strings.h | 73 + .../Demo/Common/include/countsem.h | 73 + .../Demo/Common/include/crflash.h | 85 + .../Demo/Common/include/crhook.h | 81 + .../Demo/Common/include/death.h | 74 + .../Demo/Common/include/dynamic.h | 74 + .../Demo/Common/include/fileIO.h | 74 + .../Demo/Common/include/flash.h | 72 + .../Demo/Common/include/flash_timer.h | 79 + .../Demo/Common/include/flop.h | 74 + .../Demo/Common/include/integer.h | 74 + .../Demo/Common/include/mevents.h | 74 + .../Demo/Common/include/partest.h | 76 + .../Demo/Common/include/print.h | 75 + .../Demo/Common/include/recmutex.h | 73 + .../Demo/Common/include/semtest.h | 73 + .../Demo/Common/include/serial.h | 136 + .../freertos/freertos_v8.1.2/Source/Makefile | 48 + .../Source/include/stdint.readme | 27 + .../Source/portable/GCC/ARM_CM3/Makefile | 33 + .../Source/portable/GCC/ARM_CM3_MPU/port.c | 1246 +++++ .../portable/GCC/ARM_CM3_MPU/portmacro.h | 218 + .../Source/portable/GCC/ARM_CM4F/Makefile | 33 + .../Source/portable/GCC/ARM_CM4F/port.c | 784 +++ .../Source/portable/GCC/ARM_CM4F/portmacro.h | 196 + .../Source/portable/IAR/ARM_CM3/port.c | 655 +++ .../Source/portable/IAR/ARM_CM3/portasm.s | 155 + .../Source/portable/IAR/ARM_CM3/portmacro.h | 210 + .../Source/portable/IAR/ARM_CM4F/port.c | 659 +++ .../Source/portable/IAR/ARM_CM4F/portasm.s | 195 + .../Source/portable/IAR/ARM_CM4F/portmacro.h | 193 + .../Source/portable/MemMang/Makefile | 41 + .../Source/portable/MemMang/heap_1.c | 170 + .../Source/portable/MemMang/heap_2.c | 299 ++ .../Source/portable/MemMang/heap_3.c | 131 + .../Source/portable/MemMang/heap_4.c | 544 ++ .../Source/portable/MemMang/heap_5.c | 9 + .../Source/portable/RVDS/ARM_CM3/port.c | 724 +++ .../Source/portable/RVDS/ARM_CM3/portmacro.h | 185 + .../Source/portable/RVDS/ARM_CM4F/port.c | 803 +++ .../Source/portable/RVDS/ARM_CM4F/portmacro.h | 186 + .../soc/realtek/8195a/fwlib/hal_adc.h | 6 +- .../soc/realtek/8195a/fwlib/hal_log_uart.h | 1 + .../8195a/fwlib/rtl8195a/src/rtl8195a_ssi.c | 2 +- .../soc/realtek/8195a/fwlib/src/hal_adc.c | 52 +- .../realtek/8195a/fwlib/src/hal_log_uart.c | 11 +- .../8195a/fwlib/src/hal_soc_ps_monitor.c | 11 +- build/bin/ota.bin | Bin 299964 -> 299880 bytes build/bin/ram_2.bin | Bin 299928 -> 299844 bytes build/bin/ram_2.ns.bin | Bin 299944 -> 299860 bytes build/bin/ram_2.p.bin | Bin 299944 -> 299860 bytes build/bin/ram_all.bin | Bin 345016 -> 344932 bytes build/obj/build.nmap | 4661 ++++++++--------- project/inc/rtl8195a/rtl_libc.h | 4 +- project/src/user/atcmd_user.c | 101 +- project/src/user/wifi_console.c | 47 +- sdkbuild.mk | 3 +- 114 files changed, 28699 insertions(+), 2408 deletions(-) create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/BlockQ.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/PollQ.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/comtest.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/death.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/dynamic.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/events.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flash.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flop.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/integer.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/print.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/semtest.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlckQ.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlock.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltPollQ.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltQTest.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/BlockQ.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/EventGroupsDemo.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/GenQTest.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/IntQueue.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/PollQ.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QPeek.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueOverwrite.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueSet.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/TimerDemo.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/blocktim.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest_strings.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/countsem.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crflash.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crhook.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/death.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/dynamic.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash_timer.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flop.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/integer.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/recmutex.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/semtest.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/sp_flop.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlckQ.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlock.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltPollQ.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltQTest.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/BlockQ.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/EventGroupsDemo.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/GenQTest.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/IntQueue.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/PollQ.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QPeek.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueOverwrite.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueSet.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/TimerDemo.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/blocktim.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest2.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest_strings.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/countsem.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crflash.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crhook.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/death.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/dynamic.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/fileIO.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash_timer.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flop.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/integer.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/mevents.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/partest.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/print.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/recmutex.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/semtest.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/serial.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/Makefile create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/include/stdint.readme create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3/Makefile create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/port.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/portmacro.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/Makefile create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/port.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/portmacro.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/port.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portasm.s create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portmacro.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/port.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portasm.s create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portmacro.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/Makefile create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_1.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_2.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_3.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_4.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/port.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/portmacro.h create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/port.c create mode 100644 RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/portmacro.h diff --git a/.cproject b/.cproject index f241c9d..5905371 100644 --- a/.cproject +++ b/.cproject @@ -978,7 +978,7 @@ mingw32-make.exe - -s -j + -s -j 4 all true false diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml index f2c5d7d..baf2884 100644 --- a/.settings/language.settings.xml +++ b/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -16,7 +16,7 @@ - + @@ -27,7 +27,7 @@ - + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/BlockQ.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/BlockQ.c new file mode 100644 index 0000000..e6d56eb --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/BlockQ.c @@ -0,0 +1,346 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/** + * Creates six tasks that operate on three queues as follows: + * + * The first two tasks send and receive an incrementing number to/from a queue. + * One task acts as a producer and the other as the consumer. The consumer is a + * higher priority than the producer and is set to block on queue reads. The queue + * only has space for one item - as soon as the producer posts a message on the + * queue the consumer will unblock, pre-empt the producer, and remove the item. + * + * The second two tasks work the other way around. Again the queue used only has + * enough space for one item. This time the consumer has a lower priority than the + * producer. The producer will try to post on the queue blocking when the queue is + * full. When the consumer wakes it will remove the item from the queue, causing + * the producer to unblock, pre-empt the consumer, and immediately re-fill the + * queue. + * + * The last two tasks use the same queue producer and consumer functions. This time the queue has + * enough space for lots of items and the tasks operate at the same priority. The + * producer will execute, placing items into the queue. The consumer will start + * executing when either the queue becomes full (causing the producer to block) or + * a context switch occurs (tasks of the same priority will time slice). + * + * \page BlockQC blockQ.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V1.00: + + + Reversed the priority and block times of the second two demo tasks so + they operate as per the description above. + +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. + +Changes from V4.0.2 + + + The second set of tasks were created the wrong way around. This has been + corrected. +*/ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "BlockQ.h" +#include "print.h" + +#define blckqSTACK_SIZE ( ( unsigned short ) configMINIMAL_STACK_SIZE ) +#define blckqNUM_TASK_SETS ( 3 ) + +/* Structure used to pass parameters to the blocking queue tasks. */ +typedef struct BLOCKING_QUEUE_PARAMETERS +{ + QueueHandle_t xQueue; /*< The queue to be used by the task. */ + TickType_t xBlockTime; /*< The block time to use on queue reads/writes. */ + volatile short *psCheckVariable; /*< Incremented on each successful cycle to check the task is still running. */ +} xBlockingQueueParameters; + +/* Task function that creates an incrementing number and posts it on a queue. */ +static void vBlockingQueueProducer( void *pvParameters ); + +/* Task function that removes the incrementing number from a queue and checks that +it is the expected number. */ +static void vBlockingQueueConsumer( void *pvParameters ); + +/* Variables which are incremented each time an item is removed from a queue, and +found to be the expected value. +These are used to check that the tasks are still running. */ +static volatile short sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 }; + +/* Variable which are incremented each time an item is posted on a queue. These +are used to check that the tasks are still running. */ +static volatile short sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartBlockingQueueTasks( unsigned portBASE_TYPE uxPriority ) +{ +xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2; +xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4; +xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6; +const unsigned portBASE_TYPE uxQueueSize1 = 1, uxQueueSize5 = 5; +const TickType_t xBlockTime = ( TickType_t ) 1000 / portTICK_PERIOD_MS; +const TickType_t xDontBlock = ( TickType_t ) 0; + + /* Create the first two tasks as described at the top of the file. */ + + /* First create the structure used to pass parameters to the consumer tasks. */ + pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Create the queue used by the first two tasks to pass the incrementing number. + Pass a pointer to the queue in the parameter structure. */ + pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) ); + + /* The consumer is created first so gets a block time as described above. */ + pxQueueParameters1->xBlockTime = xBlockTime; + + /* Pass in the variable that this task is going to increment so we can check it + is still running. */ + pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] ); + + /* Create the structure used to pass parameters to the producer task. */ + pxQueueParameters2 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Pass the queue to this task also, using the parameter structure. */ + pxQueueParameters2->xQueue = pxQueueParameters1->xQueue; + + /* The producer is not going to block - as soon as it posts the consumer will + wake and remove the item so the producer should always have room to post. */ + pxQueueParameters2->xBlockTime = xDontBlock; + + /* Pass in the variable that this task is going to increment so we can check + it is still running. */ + pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] ); + + + /* Note the producer has a lower priority than the consumer when the tasks are + spawned. */ + xTaskCreate( vBlockingQueueConsumer, "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL ); + xTaskCreate( vBlockingQueueProducer, "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL ); + + + + /* Create the second two tasks as described at the top of the file. This uses + the same mechanism but reverses the task priorities. */ + + pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) ); + pxQueueParameters3->xBlockTime = xDontBlock; + pxQueueParameters3->psCheckVariable = &( sBlockingProducerCount[ 1 ] ); + + pxQueueParameters4 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters4->xQueue = pxQueueParameters3->xQueue; + pxQueueParameters4->xBlockTime = xBlockTime; + pxQueueParameters4->psCheckVariable = &( sBlockingConsumerCount[ 1 ] ); + + xTaskCreate( vBlockingQueueProducer, "QProdB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueConsumer, "QConsB4", blckqSTACK_SIZE, ( void * ) pxQueueParameters4, uxPriority, NULL ); + + + + /* Create the last two tasks as described above. The mechanism is again just + the same. This time both parameter structures are given a block time. */ + pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) ); + pxQueueParameters5->xBlockTime = xBlockTime; + pxQueueParameters5->psCheckVariable = &( sBlockingProducerCount[ 2 ] ); + + pxQueueParameters6 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters6->xQueue = pxQueueParameters5->xQueue; + pxQueueParameters6->xBlockTime = xBlockTime; + pxQueueParameters6->psCheckVariable = &( sBlockingConsumerCount[ 2 ] ); + + xTaskCreate( vBlockingQueueProducer, "QProdB5", blckqSTACK_SIZE, ( void * ) pxQueueParameters5, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueConsumer, "QConsB6", blckqSTACK_SIZE, ( void * ) pxQueueParameters6, tskIDLE_PRIORITY, NULL ); +} +/*-----------------------------------------------------------*/ + +static void vBlockingQueueProducer( void *pvParameters ) +{ +unsigned short usValue = 0; +xBlockingQueueParameters *pxQueueParameters; +const char * const pcTaskStartMsg = "Blocking queue producer started.\r\n"; +const char * const pcTaskErrorMsg = "Could not post on blocking queue\r\n"; +short sErrorEverOccurred = pdFALSE; + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + if( xQueueSendToBack( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS ) + { + vPrintDisplayMessage( &pcTaskErrorMsg ); + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully posted a message, so increment the variable + used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the variable we are going to post next time round. The + consumer will expect the numbers to follow in numerical order. */ + ++usValue; + } + } +} +/*-----------------------------------------------------------*/ + +static void vBlockingQueueConsumer( void *pvParameters ) +{ +unsigned short usData, usExpectedValue = 0; +xBlockingQueueParameters *pxQueueParameters; +const char * const pcTaskStartMsg = "Blocking queue consumer started.\r\n"; +const char * const pcTaskErrorMsg = "Incorrect value received on blocking queue.\r\n"; +short sErrorEverOccurred = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + for( ;; ) + { + if( xQueueReceive( pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + vPrintDisplayMessage( &pcTaskErrorMsg ); + + /* Catch-up. */ + usExpectedValue = usData; + + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully received a message, so increment the + variable used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the value we expect to remove from the queue next time + round. */ + ++usExpectedValue; + } + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreBlockingQueuesStillRunning( void ) +{ +static short sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 }; +static short sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 }; +portBASE_TYPE xReturn = pdPASS, xTasks; + + /* Not too worried about mutual exclusion on these variables as they are 16 + bits and we are only reading them. We also only care to see if they have + changed or not. + + Loop through each check variable and return pdFALSE if any are found not + to have changed since the last call. */ + + for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ ) + { + if( sBlockingConsumerCount[ xTasks ] == sLastBlockingConsumerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ]; + + + if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ]; + } + + return xReturn; +} + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/PollQ.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/PollQ.c new file mode 100644 index 0000000..6148a80 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/PollQ.c @@ -0,0 +1,258 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +/** + * This is a very simple queue test. See the BlockQ. c documentation for a more + * comprehensive version. + * + * Creates two tasks that communicate over a single queue. One task acts as a + * producer, the other a consumer. + * + * The producer loops for three iteration, posting an incrementing number onto the + * queue each cycle. It then delays for a fixed period before doing exactly the + * same again. + * + * The consumer loops emptying the queue. Each item removed from the queue is + * checked to ensure it contains the expected value. When the queue is empty it + * blocks for a fixed period, then does the same again. + * + * All queue access is performed without blocking. The consumer completely empties + * the queue each time it runs so the producer should never find the queue full. + * + * An error is flagged if the consumer obtains an unexpected value or the producer + * find the queue is full. + * + * \page PollQC pollQ.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "print.h" + +/* Demo program include files. */ +#include "PollQ.h" + +#define pollqSTACK_SIZE ( ( unsigned short ) configMINIMAL_STACK_SIZE ) + +/* The task that posts the incrementing number onto the queue. */ +static void vPolledQueueProducer( void *pvParameters ); + +/* The task that empties the queue. */ +static void vPolledQueueConsumer( void *pvParameters ); + +/* Variables that are used to check that the tasks are still running with no errors. */ +static volatile short sPollingConsumerCount = 0, sPollingProducerCount = 0; +/*-----------------------------------------------------------*/ + +void vStartPolledQueueTasks( unsigned portBASE_TYPE uxPriority ) +{ +static QueueHandle_t xPolledQueue; +const unsigned portBASE_TYPE uxQueueSize = 10; + + /* Create the queue used by the producer and consumer. */ + xPolledQueue = xQueueCreate( uxQueueSize, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) ); + + /* Spawn the producer and consumer. */ + xTaskCreate( vPolledQueueConsumer, "QConsNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, NULL ); + xTaskCreate( vPolledQueueProducer, "QProdNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static void vPolledQueueProducer( void *pvParameters ) +{ +unsigned short usValue = 0, usLoop; +QueueHandle_t *pxQueue; +const TickType_t xDelay = ( TickType_t ) 200 / portTICK_PERIOD_MS; +const unsigned short usNumToProduce = 3; +const char * const pcTaskStartMsg = "Polled queue producer started.\r\n"; +const char * const pcTaskErrorMsg = "Could not post on polled queue.\r\n"; +short sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The queue being used is passed in as the parameter. */ + pxQueue = ( QueueHandle_t * ) pvParameters; + + for( ;; ) + { + for( usLoop = 0; usLoop < usNumToProduce; ++usLoop ) + { + /* Send an incrementing number on the queue without blocking. */ + if( xQueueSendToBack( *pxQueue, ( void * ) &usValue, ( TickType_t ) 0 ) != pdPASS ) + { + /* We should never find the queue full - this is an error. */ + vPrintDisplayMessage( &pcTaskErrorMsg ); + sError = pdTRUE; + } + else + { + if( sError == pdFALSE ) + { + /* If an error has ever been recorded we stop incrementing the + check variable. */ + ++sPollingProducerCount; + } + + /* Update the value we are going to post next time around. */ + ++usValue; + } + } + + /* Wait before we start posting again to ensure the consumer runs and + empties the queue. */ + vTaskDelay( xDelay ); + } +} +/*-----------------------------------------------------------*/ + +static void vPolledQueueConsumer( void *pvParameters ) +{ +unsigned short usData, usExpectedValue = 0; +QueueHandle_t *pxQueue; +const TickType_t xDelay = ( TickType_t ) 200 / portTICK_PERIOD_MS; +const char * const pcTaskStartMsg = "Polled queue consumer started.\r\n"; +const char * const pcTaskErrorMsg = "Incorrect value received on polled queue.\r\n"; +short sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The queue being used is passed in as the parameter. */ + pxQueue = ( QueueHandle_t * ) pvParameters; + + for( ;; ) + { + /* Loop until the queue is empty. */ + while( uxQueueMessagesWaiting( *pxQueue ) ) + { + if( xQueueReceive( *pxQueue, &usData, ( TickType_t ) 0 ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + /* This is not what we expected to receive so an error has + occurred. */ + vPrintDisplayMessage( &pcTaskErrorMsg ); + sError = pdTRUE; + /* Catch-up to the value we received so our next expected value + should again be correct. */ + usExpectedValue = usData; + } + else + { + if( sError == pdFALSE ) + { + /* Only increment the check variable if no errors have + occurred. */ + ++sPollingConsumerCount; + } + } + ++usExpectedValue; + } + } + + /* Now the queue is empty we block, allowing the producer to place more + items in the queue. */ + vTaskDelay( xDelay ); + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running with no errors. */ +portBASE_TYPE xArePollingQueuesStillRunning( void ) +{ +static short sLastPollingConsumerCount = 0, sLastPollingProducerCount = 0; +portBASE_TYPE xReturn; + + if( ( sLastPollingConsumerCount == sPollingConsumerCount ) || + ( sLastPollingProducerCount == sPollingProducerCount ) + ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + sLastPollingConsumerCount = sPollingConsumerCount; + sLastPollingProducerCount = sPollingProducerCount; + + return xReturn; +} diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/comtest.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/comtest.c new file mode 100644 index 0000000..92c1e5d --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/comtest.c @@ -0,0 +1,384 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/** + * Creates two tasks that operate on an interrupt driven serial port. A loopback + * connector should be used so that everything that is transmitted is also received. + * The serial port does not use any flow control. On a standard 9way 'D' connector + * pins two and three should be connected together. + * + * The first task repeatedly sends a string to a queue, character at a time. The + * serial port interrupt will empty the queue and transmit the characters. The + * task blocks for a pseudo random period before resending the string. + * + * The second task blocks on a queue waiting for a character to be received. + * Characters received by the serial port interrupt routine are posted onto the + * queue - unblocking the task making it ready to execute. If this is then the + * highest priority task ready to run it will run immediately - with a context + * switch occurring at the end of the interrupt service routine. The task + * receiving characters is spawned with a higher priority than the task + * transmitting the characters. + * + * With the loop back connector in place, one task will transmit a string and the + * other will immediately receive it. The receiving task knows the string it + * expects to receive so can detect an error. + * + * This also creates a third task. This is used to test semaphore usage from an + * ISR and does nothing interesting. + * + * \page ComTestC comtest.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V1.00: + + + The priority of the Rx task has been lowered. Received characters are + now processed (read from the queue) at the idle priority, allowing low + priority tasks to run evenly at times of a high communications overhead. + +Changes from V1.01: + + + The Tx task now waits a pseudo random time between transissions. + Previously a fixed period was used but this was not such a good test as + interrupts fired at regular intervals. + +Changes From V1.2.0: + + + Use vSerialPutString() instead of single character puts. + + Only stop the check variable incrementing after two consecutive errors. + +Changed from V1.2.5 + + + Made the Rx task 2 priorities higher than the Tx task. Previously it was + only 1. This is done to tie in better with the other demo application + tasks. + +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. + + Slight modification to task priorities. + +*/ + + +/* Scheduler include files. */ +#include +#include +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "serial.h" +#include "comtest.h" +#include "print.h" + +/* The Tx task will transmit the sequence of characters at a pseudo random +interval. This is the maximum and minimum block time between sends. */ +#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x15e ) +#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0xc8 ) + +#define comMAX_CONSECUTIVE_ERRORS ( 2 ) + +#define comSTACK_SIZE ( ( unsigned short ) 256 ) + +#define comRX_RELATIVE_PRIORITY ( 1 ) + +/* Handle to the com port used by both tasks. */ +static xComPortHandle xPort; + +/* The transmit function as described at the top of the file. */ +static void vComTxTask( void *pvParameters ); + +/* The receive function as described at the top of the file. */ +static void vComRxTask( void *pvParameters ); + +/* The semaphore test function as described at the top of the file. */ +static void vSemTestTask( void * pvParameters ); + +/* The string that is repeatedly transmitted. */ +const char * const pcMessageToExchange = "Send this message over and over again to check communications interrupts. " + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n"; + +/* Variables that are incremented on each cycle of each task. These are used to +check that both tasks are still executing. */ +volatile short sTxCount = 0, sRxCount = 0, sSemCount = 0; + +/* The handle to the semaphore test task. */ +static TaskHandle_t xSemTestTaskHandle = NULL; + +/*-----------------------------------------------------------*/ + +void vStartComTestTasks( unsigned portBASE_TYPE uxPriority, eCOMPort ePort, eBaud eBaudRate ) +{ +const unsigned portBASE_TYPE uxBufferLength = 255; + + /* Initialise the com port then spawn both tasks. */ + xPort = xSerialPortInit( ePort, eBaudRate, serNO_PARITY, serBITS_8, serSTOP_1, uxBufferLength ); + xTaskCreate( vComTxTask, "COMTx", comSTACK_SIZE, NULL, uxPriority, NULL ); + xTaskCreate( vComRxTask, "COMRx", comSTACK_SIZE, NULL, uxPriority + comRX_RELATIVE_PRIORITY, NULL ); + xTaskCreate( vSemTestTask, "ISRSem", comSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xSemTestTaskHandle ); +} +/*-----------------------------------------------------------*/ + +static void vComTxTask( void *pvParameters ) +{ +const char * const pcTaskStartMsg = "COM Tx task started.\r\n"; +TickType_t xTimeToWait; + + /* Stop warnings. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* Send the string to the serial port. */ + vSerialPutString( xPort, pcMessageToExchange, strlen( pcMessageToExchange ) ); + + /* We have posted all the characters in the string - increment the variable + used to check that this task is still running, then wait before re-sending + the string. */ + sTxCount++; + + xTimeToWait = xTaskGetTickCount(); + + /* Make sure we don't wait too long... */ + xTimeToWait %= comTX_MAX_BLOCK_TIME; + + /* ...but we do want to wait. */ + if( xTimeToWait < comTX_MIN_BLOCK_TIME ) + { + xTimeToWait = comTX_MIN_BLOCK_TIME; + } + + vTaskDelay( xTimeToWait ); + } +} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */ +/*-----------------------------------------------------------*/ + +static void vComRxTask( void *pvParameters ) +{ +const char * const pcTaskStartMsg = "COM Rx task started.\r\n"; +const char * const pcTaskErrorMsg = "COM read error\r\n"; +const char * const pcTaskRestartMsg = "COM resynced\r\n"; +const char * const pcTaskTimeoutMsg = "COM Rx timed out\r\n"; +const TickType_t xBlockTime = ( TickType_t ) 0xffff / portTICK_PERIOD_MS; +const char *pcExpectedChar; +portBASE_TYPE xGotChar; +char cRxedChar; +short sResyncRequired, sConsecutiveErrors, sLatchedError; + + /* Stop warnings. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The first expected character is the first character in the string. */ + pcExpectedChar = pcMessageToExchange; + sResyncRequired = pdFALSE; + sConsecutiveErrors = 0; + sLatchedError = pdFALSE; + + for( ;; ) + { + /* Receive a message from the com port interrupt routine. If a message is + not yet available the call will block the task. */ + xGotChar = xSerialGetChar( xPort, &cRxedChar, xBlockTime ); + if( xGotChar == pdTRUE ) + { + if( sResyncRequired == pdTRUE ) + { + /* We got out of sequence and are waiting for the start of the next + transmission of the string. */ + if( cRxedChar == '\n' ) + { + /* This is the end of the message so we can start again - with + the first character in the string being the next thing we expect + to receive. */ + pcExpectedChar = pcMessageToExchange; + sResyncRequired = pdFALSE; + + /* Queue a message for printing to say that we are going to try + again. */ + vPrintDisplayMessage( &pcTaskRestartMsg ); + + /* Stop incrementing the check variable, if consecutive errors occur. */ + sConsecutiveErrors++; + if( sConsecutiveErrors >= comMAX_CONSECUTIVE_ERRORS ) + { + sLatchedError = pdTRUE; + } + } + } + else + { + /* We have received a character, but is it the expected character? */ + if( cRxedChar != *pcExpectedChar ) + { + /* This was not the expected character so post a message for + printing to say that an error has occurred. We will then wait + to resynchronise. */ + vPrintDisplayMessage( &pcTaskErrorMsg ); + sResyncRequired = pdTRUE; + } + else + { + /* This was the expected character so next time we will expect + the next character in the string. Wrap back to the beginning + of the string when the null terminator has been reached. */ + pcExpectedChar++; + if( *pcExpectedChar == '\0' ) + { + pcExpectedChar = pcMessageToExchange; + + /* We have got through the entire string without error. */ + sConsecutiveErrors = 0; + } + } + } + + /* Increment the count that is used to check that this task is still + running. This is only done if an error has never occurred. */ + if( sLatchedError == pdFALSE ) + { + sRxCount++; + } + } + else + { + vPrintDisplayMessage( &pcTaskTimeoutMsg ); + } + } +} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */ +/*-----------------------------------------------------------*/ + +static void vSemTestTask( void * pvParameters ) +{ +const char * const pcTaskStartMsg = "ISR Semaphore test started.\r\n"; +portBASE_TYPE xError = pdFALSE; + + /* Stop warnings. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + if( xSerialWaitForSemaphore( xPort ) ) + { + if( xError == pdFALSE ) + { + sSemCount++; + } + } + else + { + xError = pdTRUE; + } + } +} /*lint !e715 !e830 !e818 pvParameters not used but function prototype must be standard for task function. */ +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreComTestTasksStillRunning( void ) +{ +static short sLastTxCount = 0, sLastRxCount = 0, sLastSemCount = 0; +portBASE_TYPE xReturn; + + /* Not too worried about mutual exclusion on these variables as they are 16 + bits and we are only reading them. We also only care to see if they have + changed or not. */ + + if( ( sTxCount == sLastTxCount ) || ( sRxCount == sLastRxCount ) || ( sSemCount == sLastSemCount ) ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + sLastTxCount = sTxCount; + sLastRxCount = sRxCount; + sLastSemCount = sSemCount; + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vComTestUnsuspendTask( void ) +{ + /* The task that is suspended on the semaphore will be referenced from the + Suspended list as it is blocking indefinitely. This call just checks that + the kernel correctly detects this and does not attempt to unsuspend the + task. */ + xTaskResumeFromISR( xSemTestTaskHandle ); +} diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/death.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/death.c new file mode 100644 index 0000000..aaf4cff --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/death.c @@ -0,0 +1,241 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/** + * Create a single persistent task which periodically dynamically creates another + * four tasks. The original task is called the creator task, the four tasks it + * creates are called suicidal tasks. + * + * Two of the created suicidal tasks kill one other suicidal task before killing + * themselves - leaving just the original task remaining. + * + * The creator task must be spawned after all of the other demo application tasks + * as it keeps a check on the number of tasks under the scheduler control. The + * number of tasks it expects to see running should never be greater than the + * number of tasks that were in existence when the creator task was spawned, plus + * one set of four suicidal tasks. If this number is exceeded an error is flagged. + * + * \page DeathC death.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "death.h" +#include "print.h" + +#define deathSTACK_SIZE ( ( unsigned short ) 512 ) + +/* The task originally created which is responsible for periodically dynamically +creating another four tasks. */ +static void vCreateTasks( void *pvParameters ); + +/* The task function of the dynamically created tasks. */ +static void vSuicidalTask( void *pvParameters ); + +/* A variable which is incremented every time the dynamic tasks are created. This +is used to check that the task is still running. */ +static volatile short sCreationCount = 0; + +/* Used to store the number of tasks that were originally running so the creator +task can tell if any of the suicidal tasks have failed to die. */ +static volatile unsigned portBASE_TYPE uxTasksRunningAtStart = 0; +static const unsigned portBASE_TYPE uxMaxNumberOfExtraTasksRunning = 5; + +/* Used to store a handle to the tasks that should be killed by a suicidal task, +before it kills itself. */ +TaskHandle_t xCreatedTask1, xCreatedTask2; + +/*-----------------------------------------------------------*/ + +void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority ) +{ +unsigned portBASE_TYPE *puxPriority; + + /* Create the Creator tasks - passing in as a parameter the priority at which + the suicidal tasks should be created. */ + puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) ); + *puxPriority = uxPriority; + + 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 + suicidal tasks have failed to be killed. */ + uxTasksRunningAtStart = uxTaskGetNumberOfTasks(); +} +/*-----------------------------------------------------------*/ + +static void vSuicidalTask( void *pvParameters ) +{ +portDOUBLE d1, d2; +TaskHandle_t xTaskToKill; +const TickType_t xDelay = ( TickType_t ) 500 / portTICK_PERIOD_MS; + + if( pvParameters != NULL ) + { + /* 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. + The other task is passed in null. */ + xTaskToKill = *( TaskHandle_t* )pvParameters; + } + else + { + xTaskToKill = NULL; + } + + for( ;; ) + { + /* Do something random just to use some stack and registers. */ + d1 = 2.4; + d2 = 89.2; + d2 *= d1; + vTaskDelay( xDelay ); + + if( xTaskToKill != NULL ) + { + /* Make sure the other task has a go before we delete it. */ + vTaskDelay( ( TickType_t ) 0 ); + /* Kill the other task that was created by vCreateTasks(). */ + vTaskDelete( xTaskToKill ); + /* Kill ourselves. */ + vTaskDelete( NULL ); + } + } +}/*lint !e818 !e550 Function prototype must be as per standard for task functions. */ +/*-----------------------------------------------------------*/ + +static void vCreateTasks( void *pvParameters ) +{ +const TickType_t xDelay = ( TickType_t ) 1000 / portTICK_PERIOD_MS; +unsigned portBASE_TYPE uxPriority; +const char * const pcTaskStartMsg = "Create task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + uxPriority = *( unsigned portBASE_TYPE * ) pvParameters; + vPortFree( pvParameters ); + + for( ;; ) + { + /* Just loop round, delaying then creating the four suicidal tasks. */ + vTaskDelay( xDelay ); + + xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask1 ); + xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask1, uxPriority, NULL ); + + xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask2 ); + xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask2, uxPriority, NULL ); + + ++sCreationCount; + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that the creator task is still running and that there +are not any more than four extra tasks. */ +portBASE_TYPE xIsCreateTaskStillRunning( void ) +{ +static short sLastCreationCount = 0; +short sReturn = pdTRUE; +unsigned portBASE_TYPE uxTasksRunningNow; + + if( sLastCreationCount == sCreationCount ) + { + sReturn = pdFALSE; + } + + uxTasksRunningNow = uxTaskGetNumberOfTasks(); + + if( uxTasksRunningNow < uxTasksRunningAtStart ) + { + sReturn = pdFALSE; + } + else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning ) + { + sReturn = pdFALSE; + } + else + { + /* Everything is okay. */ + } + + return sReturn; +} + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/dynamic.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/dynamic.c new file mode 100644 index 0000000..294743d --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/dynamic.c @@ -0,0 +1,616 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/** + * The first test creates three tasks - two counter tasks (one continuous count + * and one limited count) and one controller. A "count" variable is shared + * between all three tasks. The two counter tasks should never be in a "ready" + * state at the same time. The controller task runs at the same priority as + * the continuous count task, and at a lower priority than the limited count + * task. + * + * One counter task loops indefinitely, incrementing the shared count variable + * on each iteration. To ensure it has exclusive access to the variable it + * raises it's priority above that of the controller task before each + * increment, lowering it again to it's original priority before starting the + * next iteration. + * + * The other counter task increments the shared count variable on each + * iteration of it's loop until the count has reached a limit of 0xff - at + * which point it suspends itself. It will not start a new loop until the + * controller task has made it "ready" again by calling vTaskResume (). + * This second counter task operates at a higher priority than controller + * task so does not need to worry about mutual exclusion of the counter + * variable. + * + * The controller task is in two sections. The first section controls and + * monitors the continuous count task. When this section is operational the + * limited count task is suspended. Likewise, the second section controls + * and monitors the limited count task. When this section is operational the + * continuous count task is suspended. + * + * In the first section the controller task first takes a copy of the shared + * count variable. To ensure mutual exclusion on the count variable it + * suspends the continuous count task, resuming it again when the copy has been + * taken. The controller task then sleeps for a fixed period - during which + * the continuous count task will execute and increment the shared variable. + * When the controller task wakes it checks that the continuous count task + * has executed by comparing the copy of the shared variable with its current + * value. This time, to ensure mutual exclusion, the scheduler itself is + * suspended with a call to vTaskSuspendAll (). This is for demonstration + * purposes only and is not a recommended technique due to its inefficiency. + * + * After a fixed number of iterations the controller task suspends the + * continuous count task, and moves on to its second section. + * + * At the start of the second section the shared variable is cleared to zero. + * The limited count task is then woken from it's suspension by a call to + * vTaskResume (). As this counter task operates at a higher priority than + * the controller task the controller task should not run again until the + * shared variable has been counted up to the limited value causing the counter + * task to suspend itself. The next line after vTaskResume () is therefore + * a check on the shared variable to ensure everything is as expected. + * + * + * The second test consists of a couple of very simple tasks that post onto a + * queue while the scheduler is suspended. This test was added to test parts + * of the scheduler not exercised by the first test. + * + * + * The final set of two tasks implements a third test. This simply raises the + * priority of a task while the scheduler is suspended. Again this test was + * added to exercise parts of the code not covered by the first test. + * + * \page Priorities dynamic.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. + + Added a second, simple test that uses the functions + vQueueReceiveWhenSuspendedTask() and vQueueSendWhenSuspendedTask(). + +Changes from V3.1.1 + + + Added a third simple test that uses the vTaskPrioritySet() function + while the scheduler is suspended. + + Modified the controller task slightly to test the calling of + vTaskResumeAll() while the scheduler is suspended. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "dynamic.h" +#include "print.h" + +/* Function that implements the "limited count" task as described above. */ +static void vLimitedIncrementTask( void * pvParameters ); + +/* Function that implements the "continuous count" task as described above. */ +static void vContinuousIncrementTask( void * pvParameters ); + +/* Function that implements the controller task as described above. */ +static void vCounterControlTask( void * pvParameters ); + +/* The simple test functions that check sending and receiving while the +scheduler is suspended. */ +static void vQueueReceiveWhenSuspendedTask( void *pvParameters ); +static void vQueueSendWhenSuspendedTask( void *pvParameters ); + +/* The simple test functions that check raising and lowering of task priorities +while the scheduler is suspended. */ +static void prvChangePriorityWhenSuspendedTask( void *pvParameters ); +static void prvChangePriorityHelperTask( void *pvParameters ); + + +/* Demo task specific constants. */ +#define priSTACK_SIZE ( ( unsigned short ) configMINIMAL_STACK_SIZE ) +#define priSLEEP_TIME ( ( TickType_t ) 50 ) +#define priLOOPS ( 5 ) +#define priMAX_COUNT ( ( unsigned long ) 0xff ) +#define priNO_BLOCK ( ( TickType_t ) 0 ) +#define priSUSPENDED_QUEUE_LENGTH ( 1 ) + +/*-----------------------------------------------------------*/ + +/* Handles to the two counter tasks. These could be passed in as parameters +to the controller task to prevent them having to be file scope. */ +static TaskHandle_t xContinuousIncrementHandle, xLimitedIncrementHandle, xChangePriorityWhenSuspendedHandle; + +/* The shared counter variable. This is passed in as a parameter to the two +counter variables for demonstration purposes. */ +static unsigned long ulCounter; + +/* Variable used in a similar way by the test that checks the raising and +lowering of task priorities while the scheduler is suspended. */ +static unsigned long ulPrioritySetCounter; + +/* Variables used to check that the tasks are still operating without error. +Each complete iteration of the controller task increments this variable +provided no errors have been found. The variable maintaining the same value +is therefore indication of an error. */ +static unsigned short usCheckVariable = ( unsigned short ) 0; +static portBASE_TYPE xSuspendedQueueSendError = pdFALSE; +static portBASE_TYPE xSuspendedQueueReceiveError = pdFALSE; +static portBASE_TYPE xPriorityRaiseWhenSuspendedError = pdFALSE; + +/* Queue used by the second test. */ +QueueHandle_t xSuspendedTestQueue; + +/*-----------------------------------------------------------*/ +/* + * Start the seven tasks as described at the top of the file. + * Note that the limited count task is given a higher priority. + */ +void vStartDynamicPriorityTasks( void ) +{ + xSuspendedTestQueue = xQueueCreate( priSUSPENDED_QUEUE_LENGTH, sizeof( unsigned long ) ); + xTaskCreate( vContinuousIncrementTask, "CONT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinuousIncrementHandle ); + xTaskCreate( vLimitedIncrementTask, "LIM_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY + 1, &xLimitedIncrementHandle ); + xTaskCreate( vCounterControlTask, "C_CTRL", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vQueueSendWhenSuspendedTask, "SUSP_SEND", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vQueueReceiveWhenSuspendedTask, "SUSP_RECV", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( prvChangePriorityWhenSuspendedTask, "1st_P_CHANGE", priSTACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL ); + xTaskCreate( prvChangePriorityHelperTask, "2nd_P_CHANGE", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xChangePriorityWhenSuspendedHandle ); +} +/*-----------------------------------------------------------*/ + +/* + * Just loops around incrementing the shared variable until the limit has been + * reached. Once the limit has been reached it suspends itself. + */ +static void vLimitedIncrementTask( void * pvParameters ) +{ +unsigned long *pulCounter; + + /* Take a pointer to the shared variable from the parameters passed into + the task. */ + pulCounter = ( unsigned long * ) pvParameters; + + /* This will run before the control task, so the first thing it does is + suspend - the control task will resume it when ready. */ + vTaskSuspend( NULL ); + + for( ;; ) + { + /* Just count up to a value then suspend. */ + ( *pulCounter )++; + + if( *pulCounter >= priMAX_COUNT ) + { + vTaskSuspend( NULL ); + } + } +} +/*-----------------------------------------------------------*/ + +/* + * Just keep counting the shared variable up. The control task will suspend + * this task when it wants. + */ +static void vContinuousIncrementTask( void * pvParameters ) +{ +unsigned long *pulCounter; +unsigned portBASE_TYPE uxOurPriority; + + /* Take a pointer to the shared variable from the parameters passed into + the task. */ + pulCounter = ( unsigned long * ) pvParameters; + + /* Query our priority so we can raise it when exclusive access to the + shared variable is required. */ + uxOurPriority = uxTaskPriorityGet( NULL ); + + for( ;; ) + { + /* Raise our priority above the controller task to ensure a context + switch does not occur while we are accessing this variable. */ + vTaskPrioritySet( NULL, uxOurPriority + 1 ); + ( *pulCounter )++; + vTaskPrioritySet( NULL, uxOurPriority ); + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +/* + * Controller task as described above. + */ +static void vCounterControlTask( void * pvParameters ) +{ +unsigned long ulLastCounter; +short sLoops; +short sError = pdFALSE; +const char * const pcTaskStartMsg = "Priority manipulation tasks started.\r\n"; +const char * const pcTaskFailMsg = "Priority manipulation Task Failed\r\n"; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* Start with the counter at zero. */ + ulCounter = ( unsigned long ) 0; + + /* First section : */ + + /* Check the continuous count task is running. */ + for( sLoops = 0; sLoops < priLOOPS; sLoops++ ) + { + /* Suspend the continuous count task so we can take a mirror of the + shared variable without risk of corruption. */ + vTaskSuspend( xContinuousIncrementHandle ); + ulLastCounter = ulCounter; + vTaskResume( xContinuousIncrementHandle ); + + /* Now delay to ensure the other task has processor time. */ + vTaskDelay( priSLEEP_TIME ); + + /* Check the shared variable again. This time to ensure mutual + exclusion the whole scheduler will be locked. This is just for + demo purposes! */ + vTaskSuspendAll(); + { + if( ulLastCounter == ulCounter ) + { + /* The shared variable has not changed. There is a problem + with the continuous count task so flag an error. */ + sError = pdTRUE; + xTaskResumeAll(); + vPrintDisplayMessage( &pcTaskFailMsg ); + vTaskSuspendAll(); + } + } + xTaskResumeAll(); + } + + + /* Second section: */ + + /* Suspend the continuous counter task so it stops accessing the shared variable. */ + vTaskSuspend( xContinuousIncrementHandle ); + + /* Reset the variable. */ + ulCounter = ( unsigned long ) 0; + + /* Resume the limited count task which has a higher priority than us. + We should therefore not return from this call until the limited count + task has suspended itself with a known value in the counter variable. + The scheduler suspension is not necessary but is included for test + purposes. */ + vTaskSuspendAll(); + vTaskResume( xLimitedIncrementHandle ); + xTaskResumeAll(); + + /* Does the counter variable have the expected value? */ + if( ulCounter != priMAX_COUNT ) + { + sError = pdTRUE; + vPrintDisplayMessage( &pcTaskFailMsg ); + } + + if( sError == pdFALSE ) + { + /* If no errors have occurred then increment the check variable. */ + portENTER_CRITICAL(); + usCheckVariable++; + portEXIT_CRITICAL(); + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Resume the continuous count task and do it all again. */ + vTaskResume( xContinuousIncrementHandle ); + } +} +/*-----------------------------------------------------------*/ + +static void vQueueSendWhenSuspendedTask( void *pvParameters ) +{ +static unsigned long ulValueToSend = ( unsigned long ) 0; +const char * const pcTaskStartMsg = "Queue send while suspended task started.\r\n"; +const char * const pcTaskFailMsg = "Queue send while suspended failed.\r\n"; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + vTaskSuspendAll(); + { + /* We must not block while the scheduler is suspended! */ + if( xQueueSend( xSuspendedTestQueue, ( void * ) &ulValueToSend, priNO_BLOCK ) != pdTRUE ) + { + if( xSuspendedQueueSendError == pdFALSE ) + { + xTaskResumeAll(); + vPrintDisplayMessage( &pcTaskFailMsg ); + vTaskSuspendAll(); + } + + xSuspendedQueueSendError = pdTRUE; + } + } + xTaskResumeAll(); + + vTaskDelay( priSLEEP_TIME ); + + ++ulValueToSend; + } +} +/*-----------------------------------------------------------*/ + +static void vQueueReceiveWhenSuspendedTask( void *pvParameters ) +{ +static unsigned long ulExpectedValue = ( unsigned long ) 0, ulReceivedValue; +const char * const pcTaskStartMsg = "Queue receive while suspended task started.\r\n"; +const char * const pcTaskFailMsg = "Queue receive while suspended failed.\r\n"; +portBASE_TYPE xGotValue; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + do + { + /* Suspending the scheduler here is fairly pointless and + undesirable for a normal application. It is done here purely + to test the scheduler. The inner xTaskResumeAll() should + never return pdTRUE as the scheduler is still locked by the + outer call. */ + vTaskSuspendAll(); + { + vTaskSuspendAll(); + { + xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK ); + } + if( xTaskResumeAll() ) + { + xSuspendedQueueReceiveError = pdTRUE; + } + } + xTaskResumeAll(); + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + } while( xGotValue == pdFALSE ); + + if( ulReceivedValue != ulExpectedValue ) + { + if( xSuspendedQueueReceiveError == pdFALSE ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + } + xSuspendedQueueReceiveError = pdTRUE; + } + + ++ulExpectedValue; + } +} +/*-----------------------------------------------------------*/ + +static void prvChangePriorityWhenSuspendedTask( void *pvParameters ) +{ +const char * const pcTaskStartMsg = "Priority change when suspended task started.\r\n"; +const char * const pcTaskFailMsg = "Priority change when suspended task failed.\r\n"; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* Start with the counter at 0 so we know what the counter should be + when we check it next. */ + ulPrioritySetCounter = ( unsigned long ) 0; + + /* Resume the helper task. At this time it has a priority lower than + ours so no context switch should occur. */ + vTaskResume( xChangePriorityWhenSuspendedHandle ); + + /* Check to ensure the task just resumed has not executed. */ + portENTER_CRITICAL(); + { + if( ulPrioritySetCounter != ( unsigned long ) 0 ) + { + xPriorityRaiseWhenSuspendedError = pdTRUE; + vPrintDisplayMessage( &pcTaskFailMsg ); + } + } + portEXIT_CRITICAL(); + + /* Now try raising the priority while the scheduler is suspended. */ + vTaskSuspendAll(); + { + vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, ( configMAX_PRIORITIES - 1 ) ); + + /* Again, even though the helper task has a priority greater than + ours, it should not have executed yet because the scheduler is + suspended. */ + portENTER_CRITICAL(); + { + if( ulPrioritySetCounter != ( unsigned long ) 0 ) + { + xPriorityRaiseWhenSuspendedError = pdTRUE; + vPrintDisplayMessage( &pcTaskFailMsg ); + } + } + portEXIT_CRITICAL(); + } + xTaskResumeAll(); + + /* Now the scheduler has been resumed the helper task should + immediately preempt us and execute. When it executes it will increment + the ulPrioritySetCounter exactly once before suspending itself. + + We should now always find the counter set to 1. */ + portENTER_CRITICAL(); + { + if( ulPrioritySetCounter != ( unsigned long ) 1 ) + { + xPriorityRaiseWhenSuspendedError = pdTRUE; + vPrintDisplayMessage( &pcTaskFailMsg ); + } + } + portEXIT_CRITICAL(); + + /* Delay until we try this again. */ + vTaskDelay( priSLEEP_TIME * 2 ); + + /* Set the priority of the helper task back ready for the next + execution of this task. */ + vTaskSuspendAll(); + vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, tskIDLE_PRIORITY ); + xTaskResumeAll(); + } +} +/*-----------------------------------------------------------*/ + +static void prvChangePriorityHelperTask( void *pvParameters ) +{ + /* Just to stop warning messages. */ + ( void ) pvParameters; + + for( ;; ) + { + /* This is the helper task for prvChangePriorityWhenSuspendedTask(). + It has it's priority raised and lowered. When it runs it simply + increments the counter then suspends itself again. This allows + prvChangePriorityWhenSuspendedTask() to know how many times it has + executed. */ + ulPrioritySetCounter++; + vTaskSuspend( NULL ); + } +} +/*-----------------------------------------------------------*/ + +/* Called to check that all the created tasks are still running without error. */ +portBASE_TYPE xAreDynamicPriorityTasksStillRunning( void ) +{ +/* Keep a history of the check variables so we know if it has been incremented +since the last call. */ +static unsigned short usLastTaskCheck = ( unsigned short ) 0; +portBASE_TYPE xReturn = pdTRUE; + + /* Check the tasks are still running by ensuring the check variable + is still incrementing. */ + + if( usCheckVariable == usLastTaskCheck ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + if( xSuspendedQueueSendError == pdTRUE ) + { + xReturn = pdFALSE; + } + + if( xSuspendedQueueReceiveError == pdTRUE ) + { + xReturn = pdFALSE; + } + + if( xPriorityRaiseWhenSuspendedError == pdTRUE ) + { + xReturn = pdFALSE; + } + + usLastTaskCheck = usCheckVariable; + return xReturn; +} + + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/events.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/events.c new file mode 100644 index 0000000..307568e --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/events.c @@ -0,0 +1,406 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/** + * This file exercises the event mechanism whereby more than one task is + * blocked waiting for the same event. + * + * The demo creates five tasks - four 'event' tasks, and a controlling task. + * The event tasks have various different priorities and all block on reading + * the same queue. The controlling task writes data to the queue, then checks + * to see which of the event tasks read the data from the queue. The + * controlling task has the lowest priority of all the tasks so is guaranteed + * to always get preempted immediately upon writing to the queue. + * + * By selectively suspending and resuming the event tasks the controlling task + * can check that the highest priority task that is blocked on the queue is the + * task that reads the posted data from the queue. + * + * Two of the event tasks share the same priority. When neither of these tasks + * are suspended they should alternate - one reading one message from the queue, + * the other the next message, etc. + */ + +/* Standard includes. */ +#include +#include +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "mevents.h" +#include "print.h" + +/* Demo specific constants. */ +#define evtSTACK_SIZE ( ( unsigned portBASE_TYPE ) configMINIMAL_STACK_SIZE ) +#define evtNUM_TASKS ( 4 ) +#define evtQUEUE_LENGTH ( ( unsigned portBASE_TYPE ) 3 ) +#define evtNO_DELAY 0 + +/* Just indexes used to uniquely identify the tasks. Note that two tasks are +'highest' priority. */ +#define evtHIGHEST_PRIORITY_INDEX_2 3 +#define evtHIGHEST_PRIORITY_INDEX_1 2 +#define evtMEDIUM_PRIORITY_INDEX 1 +#define evtLOWEST_PRIORITY_INDEX 0 + +/* Each event task increments one of these counters each time it reads data +from the queue. */ +static volatile portBASE_TYPE xTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 }; + +/* Each time the controlling task posts onto the queue it increments the +expected count of the task that it expected to read the data from the queue +(i.e. the task with the highest priority that should be blocked on the queue). + +xExpectedTaskCounters are incremented from the controlling task, and +xTaskCounters are incremented from the individual event tasks - therefore +comparing xTaskCounters to xExpectedTaskCounters shows whether or not the +correct task was unblocked by the post. */ +static portBASE_TYPE xExpectedTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 }; + +/* Handles to the four event tasks. These are required to suspend and resume +the tasks. */ +static TaskHandle_t xCreatedTasks[ evtNUM_TASKS ]; + +/* The single queue onto which the controlling task posts, and the four event +tasks block. */ +static QueueHandle_t xQueue; + +/* Flag used to indicate whether or not an error has occurred at any time. +An error is either the queue being full when not expected, or an unexpected +task reading data from the queue. */ +static portBASE_TYPE xHealthStatus = pdPASS; + +/*-----------------------------------------------------------*/ + +/* Function that implements the event task. This is created four times. */ +static void prvMultiEventTask( void *pvParameters ); + +/* Function that implements the controlling task. */ +static void prvEventControllerTask( void *pvParameters ); + +/* This is a utility function that posts data to the queue, then compares +xExpectedTaskCounters with xTaskCounters to ensure everything worked as +expected. + +The event tasks all have higher priorities the controlling task. Therefore +the controlling task will always get preempted between writhing to the queue +and checking the task counters. + +@param xExpectedTask The index to the task that the controlling task thinks + should be the highest priority task waiting for data, and + therefore the task that will unblock. + +@param xIncrement The number of items that should be written to the queue. +*/ +static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask, portBASE_TYPE xIncrement ); + +/* This is just incremented each cycle of the controlling tasks function so +the main application can ensure the test is still running. */ +static portBASE_TYPE xCheckVariable = 0; + +/*-----------------------------------------------------------*/ + +void vStartMultiEventTasks( void ) +{ + /* Create the queue to be used for all the communications. */ + xQueue = xQueueCreate( evtQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) ); + + /* Start the controlling task. This has the idle priority to ensure it is + always preempted by the event tasks. */ + xTaskCreate( prvEventControllerTask, "EvntCTRL", evtSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + + /* Start the four event tasks. Note that two have priority 3, one + priority 2 and the other priority 1. */ + xTaskCreate( prvMultiEventTask, "Event0", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 0 ] ), 1, &( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ) ); + xTaskCreate( prvMultiEventTask, "Event1", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 1 ] ), 2, &( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ) ); + xTaskCreate( prvMultiEventTask, "Event2", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 2 ] ), 3, &( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ) ); + xTaskCreate( prvMultiEventTask, "Event3", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 3 ] ), 3, &( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] ) ); +} +/*-----------------------------------------------------------*/ + +static void prvMultiEventTask( void *pvParameters ) +{ +portBASE_TYPE *pxCounter; +unsigned portBASE_TYPE uxDummy; +const char * const pcTaskStartMsg = "Multi event task started.\r\n"; + + /* The variable this task will increment is passed in as a parameter. */ + pxCounter = ( portBASE_TYPE * ) pvParameters; + + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* Block on the queue. */ + if( xQueueReceive( xQueue, &uxDummy, portMAX_DELAY ) ) + { + /* We unblocked by reading the queue - so simply increment + the counter specific to this task instance. */ + ( *pxCounter )++; + } + else + { + xHealthStatus = pdFAIL; + } + } +} +/*-----------------------------------------------------------*/ + +static void prvEventControllerTask( void *pvParameters ) +{ +const char * const pcTaskStartMsg = "Multi event controller task started.\r\n"; +portBASE_TYPE xDummy = 0; + + /* Just to stop warnings. */ + ( void ) pvParameters; + + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* All tasks are blocked on the queue. When a message is posted one of + the two tasks that share the highest priority should unblock to read + the queue. The next message written should unblock the other task with + the same high priority, and so on in order. No other task should + unblock to read data as they have lower priorities. */ + + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_2, 1 ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_2, 1 ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + + /* For the rest of these tests we don't need the second 'highest' + priority task - so it is suspended. */ + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] ); + + + + /* Now suspend the other highest priority task. The medium priority + task will then be the task with the highest priority that remains + blocked on the queue. */ + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + + /* This time, when we post onto the queue we will expect the medium + priority task to unblock and preempt us. */ + prvCheckTaskCounters( evtMEDIUM_PRIORITY_INDEX, 1 ); + + /* Now try resuming the highest priority task while the scheduler is + suspended. The task should start executing as soon as the scheduler + is resumed - therefore when we post to the queue again, the highest + priority task should again preempt us. */ + vTaskSuspendAll(); + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + xTaskResumeAll(); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + + /* Now we are going to suspend the high and medium priority tasks. The + low priority task should then preempt us. Again the task suspension is + done with the whole scheduler suspended just for test purposes. */ + vTaskSuspendAll(); + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + vTaskSuspend( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ); + xTaskResumeAll(); + prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, 1 ); + + /* Do the same basic test another few times - selectively suspending + and resuming tasks and each time calling prvCheckTaskCounters() passing + to the function the number of the task we expected to be unblocked by + the post. */ + + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + + vTaskSuspendAll(); /* Just for test. */ + vTaskSuspendAll(); /* Just for test. */ + vTaskSuspendAll(); /* Just for even more test. */ + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + xTaskResumeAll(); + xTaskResumeAll(); + xTaskResumeAll(); + prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, 1 ); + + vTaskResume( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ); + prvCheckTaskCounters( evtMEDIUM_PRIORITY_INDEX, 1 ); + + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + + /* Now a slight change, first suspend all tasks. */ + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + vTaskSuspend( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ); + vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ); + + /* Now when we resume the low priority task and write to the queue 3 + times. We expect the low priority task to service the queue three + times. */ + vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ); + prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, evtQUEUE_LENGTH ); + + /* Again suspend all tasks (only the low priority task is not suspended + already). */ + vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ); + + /* This time we are going to suspend the scheduler, resume the low + priority task, then resume the high priority task. In this state we + will write to the queue three times. When the scheduler is resumed + we expect the high priority task to service all three messages. */ + vTaskSuspendAll(); + { + vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ); + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + + for( xDummy = 0; xDummy < evtQUEUE_LENGTH; xDummy++ ) + { + if( xQueueSend( xQueue, &xDummy, evtNO_DELAY ) != pdTRUE ) + { + xHealthStatus = pdFAIL; + } + } + + /* The queue should not have been serviced yet!. The scheduler + is still suspended. */ + if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) ) + { + xHealthStatus = pdFAIL; + } + } + xTaskResumeAll(); + + /* We should have been preempted by resuming the scheduler - so by the + time we are running again we expect the high priority task to have + removed three items from the queue. */ + xExpectedTaskCounters[ evtHIGHEST_PRIORITY_INDEX_1 ] += evtQUEUE_LENGTH; + if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) ) + { + xHealthStatus = pdFAIL; + } + + /* The medium priority and second high priority tasks are still + suspended. Make sure to resume them before starting again. */ + vTaskResume( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ); + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] ); + + /* Just keep incrementing to show the task is still executing. */ + xCheckVariable++; + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask, portBASE_TYPE xIncrement ) +{ +portBASE_TYPE xDummy = 0; + + /* Write to the queue the requested number of times. The data written is + not important. */ + for( xDummy = 0; xDummy < xIncrement; xDummy++ ) + { + if( xQueueSend( xQueue, &xDummy, evtNO_DELAY ) != pdTRUE ) + { + /* Did not expect to ever find the queue full. */ + xHealthStatus = pdFAIL; + } + } + + /* All the tasks blocked on the queue have a priority higher than the + controlling task. Writing to the queue will therefore have caused this + task to be preempted. By the time this line executes the event task will + have executed and incremented its counter. Increment the expected counter + to the same value. */ + ( xExpectedTaskCounters[ xExpectedTask ] ) += xIncrement; + + /* Check the actual counts and expected counts really are the same. */ + if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) ) + { + /* The counters were not the same. This means a task we did not expect + to unblock actually did unblock. */ + xHealthStatus = pdFAIL; + } +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xAreMultiEventTasksStillRunning( void ) +{ +static portBASE_TYPE xPreviousCheckVariable = 0; + + /* Called externally to periodically check that this test is still + operational. */ + + if( xPreviousCheckVariable == xCheckVariable ) + { + xHealthStatus = pdFAIL; + } + + xPreviousCheckVariable = xCheckVariable; + + return xHealthStatus; +} + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flash.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flash.c new file mode 100644 index 0000000..db94755 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flash.c @@ -0,0 +1,166 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +/** + * Creates eight tasks, each of which flash an LED at a different rate. The first + * LED flashes every 125ms, the second every 250ms, the third every 375ms, etc. + * + * The LED flash tasks provide instant visual feedback. They show that the scheduler + * is still operational. + * + * The PC port uses the standard parallel port for outputs, the Flashlite 186 port + * uses IO port F. + * + * \page flashC flash.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. + +Changes from V2.1.1 + + + The stack size now uses configMINIMAL_STACK_SIZE. + + String constants made file scope to decrease stack depth on 8051 port. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "partest.h" +#include "flash.h" +#include "print.h" + +#define ledSTACK_SIZE configMINIMAL_STACK_SIZE + +/* Structure used to pass parameters to the LED tasks. */ +typedef struct LED_PARAMETERS +{ + unsigned portBASE_TYPE uxLED; /*< The output the task should use. */ + TickType_t xFlashRate; /*< The rate at which the LED should flash. */ +} xLEDParameters; + +/* The task that is created eight times - each time with a different xLEDParaemtes +structure passed in as the parameter. */ +static void vLEDFlashTask( void *pvParameters ); + +/* String to print if USE_STDIO is defined. */ +const char * const pcTaskStartMsg = "LED flash task started.\r\n"; + +/*-----------------------------------------------------------*/ + +void vStartLEDFlashTasks( unsigned portBASE_TYPE uxPriority ) +{ +unsigned portBASE_TYPE uxLEDTask; +xLEDParameters *pxLEDParameters; +const unsigned portBASE_TYPE uxNumOfLEDs = 8; +const TickType_t xFlashRate = 125; + + /* Create the eight tasks. */ + for( uxLEDTask = 0; uxLEDTask < uxNumOfLEDs; ++uxLEDTask ) + { + /* Create and complete the structure used to pass parameters to the next + created task. */ + pxLEDParameters = ( xLEDParameters * ) pvPortMalloc( sizeof( xLEDParameters ) ); + pxLEDParameters->uxLED = uxLEDTask; + pxLEDParameters->xFlashRate = ( xFlashRate + ( xFlashRate * ( TickType_t ) uxLEDTask ) ); + pxLEDParameters->xFlashRate /= portTICK_PERIOD_MS; + + /* Spawn the task. */ + xTaskCreate( vLEDFlashTask, "LEDx", ledSTACK_SIZE, ( void * ) pxLEDParameters, uxPriority, ( TaskHandle_t * ) NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void vLEDFlashTask( void *pvParameters ) +{ +xLEDParameters *pxParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + pxParameters = ( xLEDParameters * ) pvParameters; + + for(;;) + { + /* Delay for half the flash period then turn the LED on. */ + vTaskDelay( pxParameters->xFlashRate / ( TickType_t ) 2 ); + vParTestToggleLED( pxParameters->uxLED ); + + /* Delay for half the flash period then turn the LED off. */ + vTaskDelay( pxParameters->xFlashRate / ( TickType_t ) 2 ); + vParTestToggleLED( pxParameters->uxLED ); + } +} + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flop.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flop.c new file mode 100644 index 0000000..c516ff6 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flop.c @@ -0,0 +1,369 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* +Changes from V1.2.3 + + + The created tasks now include calls to tskYIELD(), allowing them to be used + with the cooperative scheduler. +*/ + +/** + * Creates eight tasks, each of which loops continuously performing an (emulated) + * floating point calculation. + * + * All the tasks run at the idle priority and never block or yield. This causes + * all eight tasks to time slice with the idle task. Running at the idle priority + * means that these tasks will get pre-empted any time another task is ready to run + * or a time slice occurs. More often than not the pre-emption will occur mid + * calculation, creating a good test of the schedulers context switch mechanism - a + * calculation producing an unexpected result could be a symptom of a corruption in + * the context of a task. + * + * \page FlopC flop.c + * \ingroup DemoFiles + *
+ */ + +#include +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "print.h" + +/* Demo program include files. */ +#include "flop.h" + +#define mathSTACK_SIZE ( ( unsigned short ) 512 ) +#define mathNUMBER_OF_TASKS ( 8 ) + +/* Four tasks, each of which performs a different floating point calculation. +Each of the four is created twice. */ +static void vCompetingMathTask1( void *pvParameters ); +static void vCompetingMathTask2( void *pvParameters ); +static void vCompetingMathTask3( void *pvParameters ); +static void vCompetingMathTask4( void *pvParameters ); + +/* These variables are used to check that all the tasks are still running. If a +task gets a calculation wrong it will +stop incrementing its check variable. */ +static volatile unsigned short usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartMathTasks( unsigned portBASE_TYPE uxPriority ) +{ + xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask1, "Math5", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, "Math6", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, "Math7", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, "Math8", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static void vCompetingMathTask1( void *pvParameters ) +{ +portDOUBLE d1, d2, d3, d4; +volatile unsigned short *pusTaskCheckVariable; +const portDOUBLE dAnswer = ( 123.4567 + 2345.6789 ) * -918.222; +const char * const pcTaskStartMsg = "Math task 1 started.\r\n"; +const char * const pcTaskFailMsg = "Math task 1 failed.\r\n"; +short sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for(;;) + { + d1 = 123.4567; + d2 = 2345.6789; + d3 = -918.222; + + d4 = ( d1 + d2 ) * d3; + + taskYIELD(); + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( d4 - dAnswer ) > 0.001 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + + taskYIELD(); + } +} +/*-----------------------------------------------------------*/ + +static void vCompetingMathTask2( void *pvParameters ) +{ +portDOUBLE d1, d2, d3, d4; +volatile unsigned short *pusTaskCheckVariable; +const portDOUBLE dAnswer = ( -389.38 / 32498.2 ) * -2.0001; +const char * const pcTaskStartMsg = "Math task 2 started.\r\n"; +const char * const pcTaskFailMsg = "Math task 2 failed.\r\n"; +short sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for( ;; ) + { + d1 = -389.38; + d2 = 32498.2; + d3 = -2.0001; + + d4 = ( d1 / d2 ) * d3; + + taskYIELD(); + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( d4 - dAnswer ) > 0.001 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know + this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + + taskYIELD(); + } +} +/*-----------------------------------------------------------*/ + +static void vCompetingMathTask3( void *pvParameters ) +{ +portDOUBLE *pdArray, dTotal1, dTotal2, dDifference; +volatile unsigned short *pusTaskCheckVariable; +const unsigned short usArraySize = 250; +unsigned short usPosition; +const char * const pcTaskStartMsg = "Math task 3 started.\r\n"; +const char * const pcTaskFailMsg = "Math task 3 failed.\r\n"; +short sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + dTotal1 = 0.0; + dTotal2 = 0.0; + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + pdArray[ usPosition ] = ( portDOUBLE ) usPosition + 5.5; + dTotal1 += ( portDOUBLE ) usPosition + 5.5; + } + + taskYIELD(); + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + dTotal2 += pdArray[ usPosition ]; + } + + dDifference = dTotal1 - dTotal2; + if( fabs( dDifference ) > 0.001 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + taskYIELD(); + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static void vCompetingMathTask4( void *pvParameters ) +{ +portDOUBLE *pdArray, dTotal1, dTotal2, dDifference; +volatile unsigned short *pusTaskCheckVariable; +const unsigned short usArraySize = 250; +unsigned short usPosition; +const char * const pcTaskStartMsg = "Math task 4 started.\r\n"; +const char * const pcTaskFailMsg = "Math task 4 failed.\r\n"; +short sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + dTotal1 = 0.0; + dTotal2 = 0.0; + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + pdArray[ usPosition ] = ( portDOUBLE ) usPosition * 12.123; + dTotal1 += ( portDOUBLE ) usPosition * 12.123; + } + + taskYIELD(); + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + dTotal2 += pdArray[ usPosition ]; + } + + dDifference = dTotal1 - dTotal2; + if( fabs( dDifference ) > 0.001 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + taskYIELD(); + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreMathsTaskStillRunning( void ) +{ +/* Keep a history of the check variables so we know if they have been incremented +since the last call. */ +static unsigned short usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 }; +portBASE_TYPE xReturn = pdTRUE, xTask; + + /* Check the maths tasks are still running by ensuring their check variables + are still incrementing. */ + for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ ) + { + if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ]; + } + + return xReturn; +} + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/integer.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/integer.c new file mode 100644 index 0000000..8a16e04 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/integer.c @@ -0,0 +1,365 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* +Changes from V1.2.3 + + + The created tasks now include calls to tskYIELD(), allowing them to be used + with the cooperative scheduler. +*/ + +/** + * This does the same as flop. c, but uses variables of type long instead of + * type double. + * + * As with flop. c, the tasks created in this file are a good test of the + * scheduler context switch mechanism. The processor has to access 32bit + * variables in two or four chunks (depending on the processor). The low + * priority of these tasks means there is a high probability that a context + * switch will occur mid calculation. See the flop. c documentation for + * more information. + * + * \page IntegerC integer.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V1.2.1 + + + The constants used in the calculations are larger to ensure the + optimiser does not truncate them to 16 bits. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "print.h" + +/* Demo program include files. */ +#include "integer.h" + +#define intgSTACK_SIZE ( ( unsigned short ) 256 ) +#define intgNUMBER_OF_TASKS ( 8 ) + +/* Four tasks, each of which performs a different calculation on four byte +variables. Each of the four is created twice. */ +static void vCompeteingIntMathTask1( void *pvParameters ); +static void vCompeteingIntMathTask2( void *pvParameters ); +static void vCompeteingIntMathTask3( void *pvParameters ); +static void vCompeteingIntMathTask4( void *pvParameters ); + +/* These variables are used to check that all the tasks are still running. If a +task gets a calculation wrong it will stop incrementing its check variable. */ +static volatile unsigned short usTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned short ) 0 }; +/*-----------------------------------------------------------*/ + +void vStartIntegerMathTasks( unsigned portBASE_TYPE uxPriority ) +{ + xTaskCreate( vCompeteingIntMathTask1, "IntMath1", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask2, "IntMath2", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask3, "IntMath3", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask4, "IntMath4", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask1, "IntMath5", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask2, "IntMath6", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask3, "IntMath7", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask4, "IntMath8", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static void vCompeteingIntMathTask1( void *pvParameters ) +{ +long l1, l2, l3, l4; +short sError = pdFALSE; +volatile unsigned short *pusTaskCheckVariable; +const long lAnswer = ( ( long ) 74565L + ( long ) 1234567L ) * ( long ) -918L; +const char * const pcTaskStartMsg = "Integer math task 1 started.\r\n"; +const char * const pcTaskFailMsg = "Integer math task 1 failed.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for(;;) + { + l1 = ( long ) 74565L; + l2 = ( long ) 1234567L; + l3 = ( long ) -918L; + + l4 = ( l1 + l2 ) * l3; + + taskYIELD(); + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( l4 != lAnswer ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static void vCompeteingIntMathTask2( void *pvParameters ) +{ +long l1, l2, l3, l4; +short sError = pdFALSE; +volatile unsigned short *pusTaskCheckVariable; +const long lAnswer = ( ( long ) -389000L / ( long ) 329999L ) * ( long ) -89L; +const char * const pcTaskStartMsg = "Integer math task 2 started.\r\n"; +const char * const pcTaskFailMsg = "Integer math task 2 failed.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for( ;; ) + { + l1 = -389000L; + l2 = 329999L; + l3 = -89L; + + l4 = ( l1 / l2 ) * l3; + + taskYIELD(); + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( l4 != lAnswer ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static void vCompeteingIntMathTask3( void *pvParameters ) +{ +long *plArray, lTotal1, lTotal2; +short sError = pdFALSE; +volatile unsigned short *pusTaskCheckVariable; +const unsigned short usArraySize = ( unsigned short ) 250; +unsigned short usPosition; +const char * const pcTaskStartMsg = "Integer math task 3 started.\r\n"; +const char * const pcTaskFailMsg = "Integer math task 3 failed.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + /* Create the array we are going to use for our check calculation. */ + plArray = ( long * ) pvPortMalloc( ( size_t ) 250 * sizeof( long ) ); + + /* Keep filling the array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + lTotal1 = ( long ) 0; + lTotal2 = ( long ) 0; + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + plArray[ usPosition ] = ( long ) usPosition + ( long ) 5; + lTotal1 += ( long ) usPosition + ( long ) 5; + } + + taskYIELD(); + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + lTotal2 += plArray[ usPosition ]; + } + + if( lTotal1 != lTotal2 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + taskYIELD(); + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static void vCompeteingIntMathTask4( void *pvParameters ) +{ +long *plArray, lTotal1, lTotal2; +short sError = pdFALSE; +volatile unsigned short *pusTaskCheckVariable; +const unsigned short usArraySize = 250; +unsigned short usPosition; +const char * const pcTaskStartMsg = "Integer math task 4 started.\r\n"; +const char * const pcTaskFailMsg = "Integer math task 4 failed.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + /* Create the array we are going to use for our check calculation. */ + plArray = ( long * ) pvPortMalloc( ( size_t ) 250 * sizeof( long ) ); + + /* Keep filling the array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + lTotal1 = ( long ) 0; + lTotal2 = ( long ) 0; + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + plArray[ usPosition ] = ( long ) usPosition * ( long ) 12; + lTotal1 += ( long ) usPosition * ( long ) 12; + } + + taskYIELD(); + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + lTotal2 += plArray[ usPosition ]; + } + + + if( lTotal1 != lTotal2 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + taskYIELD(); + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreIntegerMathsTaskStillRunning( void ) +{ +/* Keep a history of the check variables so we know if they have been incremented +since the last call. */ +static unsigned short usLastTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned short ) 0 }; +portBASE_TYPE xReturn = pdTRUE, xTask; + + /* Check the maths tasks are still running by ensuring their check variables + are still incrementing. */ + for( xTask = 0; xTask < intgNUMBER_OF_TASKS; xTask++ ) + { + if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ]; + } + + return xReturn; +} diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/print.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/print.c new file mode 100644 index 0000000..3d554a1 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/print.c @@ -0,0 +1,144 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/** + * Manages a queue of strings that are waiting to be displayed. This is used to + * ensure mutual exclusion of console output. + * + * A task wishing to display a message will call vPrintDisplayMessage (), with a + * pointer to the string as the parameter. The pointer is posted onto the + * xPrintQueue queue. + * + * The task spawned in main. c blocks on xPrintQueue. When a message becomes + * available it calls pcPrintGetNextMessage () to obtain a pointer to the next + * string, then uses the functions defined in the portable layer FileIO. c to + * display the message. + * + * NOTE: + * Using console IO can disrupt real time performance - depending on the port. + * Standard C IO routines are not designed for real time applications. While + * standard IO is useful for demonstration and debugging an alternative method + * should be used if you actually require console IO as part of your application. + * + * \page PrintC print.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "queue.h" + +/* Demo program include files. */ +#include "print.h" + +static QueueHandle_t xPrintQueue; + +/*-----------------------------------------------------------*/ + +void vPrintInitialise( void ) +{ +const unsigned portBASE_TYPE uxQueueSize = 20; + + /* Create the queue on which errors will be reported. */ + xPrintQueue = xQueueCreate( uxQueueSize, ( unsigned portBASE_TYPE ) sizeof( char * ) ); +} +/*-----------------------------------------------------------*/ + +void vPrintDisplayMessage( const char * const * ppcMessageToSend ) +{ + #ifdef USE_STDIO + xQueueSend( xPrintQueue, ( void * ) ppcMessageToSend, ( TickType_t ) 0 ); + #else + /* Stop warnings. */ + ( void ) ppcMessageToSend; + #endif +} +/*-----------------------------------------------------------*/ + +const char *pcPrintGetNextMessage( TickType_t xPrintRate ) +{ +char *pcMessage; + + if( xQueueReceive( xPrintQueue, &pcMessage, xPrintRate ) == pdPASS ) + { + return pcMessage; + } + else + { + return NULL; + } +} + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/semtest.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/semtest.c new file mode 100644 index 0000000..f874162 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/semtest.c @@ -0,0 +1,323 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/** + * Creates two sets of two tasks. The tasks within a set share a variable, access + * to which is guarded by a semaphore. + * + * Each task starts by attempting to obtain the semaphore. On obtaining a + * semaphore a task checks to ensure that the guarded variable has an expected + * value. It then clears the variable to zero before counting it back up to the + * expected value in increments of 1. After each increment the variable is checked + * to ensure it contains the value to which it was just set. When the starting + * value is again reached the task releases the semaphore giving the other task in + * the set a chance to do exactly the same thing. The starting value is high + * enough to ensure that a tick is likely to occur during the incrementing loop. + * + * An error is flagged if at any time during the process a shared variable is + * found to have a value other than that expected. Such an occurrence would + * suggest an error in the mutual exclusion mechanism by which access to the + * variable is restricted. + * + * The first set of two tasks poll their semaphore. The second set use blocking + * calls. + * + * \page SemTestC semtest.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V1.2.0: + + + The tasks that operate at the idle priority now use a lower expected + count than those running at a higher priority. This prevents the low + priority tasks from signaling an error because they have not been + scheduled enough time for each of them to count the shared variable to + the high value. + +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. + +Changes from V2.1.1 + + + The stack size now uses configMINIMAL_STACK_SIZE. + + String constants made file scope to decrease stack depth on 8051 port. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "semtest.h" +#include "print.h" + +/* The value to which the shared variables are counted. */ +#define semtstBLOCKING_EXPECTED_VALUE ( ( unsigned long ) 0xfff ) +#define semtstNON_BLOCKING_EXPECTED_VALUE ( ( unsigned long ) 0xff ) + +#define semtstSTACK_SIZE configMINIMAL_STACK_SIZE + +#define semtstNUM_TASKS ( 4 ) + +#define semtstDELAY_FACTOR ( ( TickType_t ) 10 ) + +/* The task function as described at the top of the file. */ +static void prvSemaphoreTest( void *pvParameters ); + +/* Structure used to pass parameters to each task. */ +typedef struct SEMAPHORE_PARAMETERS +{ + SemaphoreHandle_t xSemaphore; + volatile unsigned long *pulSharedVariable; + TickType_t xBlockTime; +} xSemaphoreParameters; + +/* Variables used to check that all the tasks are still running without errors. */ +static volatile short sCheckVariables[ semtstNUM_TASKS ] = { 0 }; +static volatile short sNextCheckVariable = 0; + +/* Strings to print if USE_STDIO is defined. */ +const char * const pcPollingSemaphoreTaskError = "Guarded shared variable in unexpected state.\r\n"; +const char * const pcSemaphoreTaskStart = "Guarded shared variable task started.\r\n"; + +/*-----------------------------------------------------------*/ + +void vStartSemaphoreTasks( unsigned portBASE_TYPE uxPriority ) +{ +xSemaphoreParameters *pxFirstSemaphoreParameters, *pxSecondSemaphoreParameters; +const TickType_t xBlockTime = ( TickType_t ) 100; + + /* Create the structure used to pass parameters to the first two tasks. */ + pxFirstSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) ); + + if( pxFirstSemaphoreParameters != NULL ) + { + /* Create the semaphore used by the first two tasks. */ + vSemaphoreCreateBinary( pxFirstSemaphoreParameters->xSemaphore ); + + if( pxFirstSemaphoreParameters->xSemaphore != NULL ) + { + /* Create the variable which is to be shared by the first two tasks. */ + pxFirstSemaphoreParameters->pulSharedVariable = ( unsigned long * ) pvPortMalloc( sizeof( unsigned long ) ); + + /* Initialise the share variable to the value the tasks expect. */ + *( pxFirstSemaphoreParameters->pulSharedVariable ) = semtstNON_BLOCKING_EXPECTED_VALUE; + + /* The first two tasks do not block on semaphore calls. */ + pxFirstSemaphoreParameters->xBlockTime = ( TickType_t ) 0; + + /* Spawn the first two tasks. As they poll they operate at the idle priority. */ + xTaskCreate( prvSemaphoreTest, "PolSEM1", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL ); + xTaskCreate( prvSemaphoreTest, "PolSEM2", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL ); + } + } + + /* Do exactly the same to create the second set of tasks, only this time + provide a block time for the semaphore calls. */ + pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) ); + if( pxSecondSemaphoreParameters != NULL ) + { + vSemaphoreCreateBinary( pxSecondSemaphoreParameters->xSemaphore ); + + if( pxSecondSemaphoreParameters->xSemaphore != NULL ) + { + pxSecondSemaphoreParameters->pulSharedVariable = ( unsigned long * ) pvPortMalloc( sizeof( unsigned long ) ); + *( pxSecondSemaphoreParameters->pulSharedVariable ) = semtstBLOCKING_EXPECTED_VALUE; + pxSecondSemaphoreParameters->xBlockTime = xBlockTime / portTICK_PERIOD_MS; + + xTaskCreate( prvSemaphoreTest, "BlkSEM1", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL ); + xTaskCreate( prvSemaphoreTest, "BlkSEM2", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL ); + } + } +} +/*-----------------------------------------------------------*/ + +static void prvSemaphoreTest( void *pvParameters ) +{ +xSemaphoreParameters *pxParameters; +volatile unsigned long *pulSharedVariable, ulExpectedValue; +unsigned long ulCounter; +short sError = pdFALSE, sCheckVariableToUse; + + /* See which check variable to use. sNextCheckVariable is not semaphore + protected! */ + portENTER_CRITICAL(); + sCheckVariableToUse = sNextCheckVariable; + sNextCheckVariable++; + portEXIT_CRITICAL(); + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcSemaphoreTaskStart ); + + /* A structure is passed in as the parameter. This contains the shared + variable being guarded. */ + pxParameters = ( xSemaphoreParameters * ) pvParameters; + pulSharedVariable = pxParameters->pulSharedVariable; + + /* If we are blocking we use a much higher count to ensure loads of context + switches occur during the count. */ + if( pxParameters->xBlockTime > ( TickType_t ) 0 ) + { + ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE; + } + else + { + ulExpectedValue = semtstNON_BLOCKING_EXPECTED_VALUE; + } + + for( ;; ) + { + /* Try to obtain the semaphore. */ + if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS ) + { + /* We have the semaphore and so expect any other tasks using the + shared variable to have left it in the state we expect to find + it. */ + if( *pulSharedVariable != ulExpectedValue ) + { + vPrintDisplayMessage( &pcPollingSemaphoreTaskError ); + sError = pdTRUE; + } + + /* Clear the variable, then count it back up to the expected value + before releasing the semaphore. Would expect a context switch or + two during this time. */ + for( ulCounter = ( unsigned long ) 0; ulCounter <= ulExpectedValue; ulCounter++ ) + { + *pulSharedVariable = ulCounter; + if( *pulSharedVariable != ulCounter ) + { + if( sError == pdFALSE ) + { + vPrintDisplayMessage( &pcPollingSemaphoreTaskError ); + } + sError = pdTRUE; + } + } + + /* Release the semaphore, and if no errors have occurred increment the check + variable. */ + if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE ) + { + vPrintDisplayMessage( &pcPollingSemaphoreTaskError ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + if( sCheckVariableToUse < semtstNUM_TASKS ) + { + ( sCheckVariables[ sCheckVariableToUse ] )++; + } + } + + /* If we have a block time then we are running at a priority higher + than the idle priority. This task takes a long time to complete + a cycle (deliberately so to test the guarding) so will be starving + out lower priority tasks. Block for some time to allow give lower + priority tasks some processor time. */ + vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR ); + } + else + { + if( pxParameters->xBlockTime == ( TickType_t ) 0 ) + { + /* We have not got the semaphore yet, so no point using the + processor. We are not blocking when attempting to obtain the + semaphore. */ + taskYIELD(); + } + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreSemaphoreTasksStillRunning( void ) +{ +static short sLastCheckVariables[ semtstNUM_TASKS ] = { 0 }; +portBASE_TYPE xTask, xReturn = pdTRUE; + + for( xTask = 0; xTask < semtstNUM_TASKS; xTask++ ) + { + if( sLastCheckVariables[ xTask ] == sCheckVariables[ xTask ] ) + { + xReturn = pdFALSE; + } + + sLastCheckVariables[ xTask ] = sCheckVariables[ xTask ]; + } + + return xReturn; +} + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlckQ.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlckQ.c new file mode 100644 index 0000000..a1d2cd0 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlckQ.c @@ -0,0 +1,332 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * This is a version of BlockQ.c that uses the alternative (Alt) API. + * + * Creates six tasks that operate on three queues as follows: + * + * The first two tasks send and receive an incrementing number to/from a queue. + * One task acts as a producer and the other as the consumer. The consumer is a + * higher priority than the producer and is set to block on queue reads. The queue + * only has space for one item - as soon as the producer posts a message on the + * queue the consumer will unblock, pre-empt the producer, and remove the item. + * + * The second two tasks work the other way around. Again the queue used only has + * enough space for one item. This time the consumer has a lower priority than the + * producer. The producer will try to post on the queue blocking when the queue is + * full. When the consumer wakes it will remove the item from the queue, causing + * the producer to unblock, pre-empt the consumer, and immediately re-fill the + * queue. + * + * The last two tasks use the same queue producer and consumer functions. This time the queue has + * enough space for lots of items and the tasks operate at the same priority. The + * producer will execute, placing items into the queue. The consumer will start + * executing when either the queue becomes full (causing the producer to block) or + * a context switch occurs (tasks of the same priority will time slice). + * + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "AltBlckQ.h" + +#define blckqSTACK_SIZE configMINIMAL_STACK_SIZE +#define blckqNUM_TASK_SETS ( 3 ) + +/* Structure used to pass parameters to the blocking queue tasks. */ +typedef struct BLOCKING_QUEUE_PARAMETERS +{ + QueueHandle_t xQueue; /*< The queue to be used by the task. */ + TickType_t xBlockTime; /*< The block time to use on queue reads/writes. */ + volatile short *psCheckVariable; /*< Incremented on each successful cycle to check the task is still running. */ +} xBlockingQueueParameters; + +/* Task function that creates an incrementing number and posts it on a queue. */ +static portTASK_FUNCTION_PROTO( vBlockingQueueProducer, pvParameters ); + +/* Task function that removes the incrementing number from a queue and checks that +it is the expected number. */ +static portTASK_FUNCTION_PROTO( vBlockingQueueConsumer, pvParameters ); + +/* Variables which are incremented each time an item is removed from a queue, and +found to be the expected value. +These are used to check that the tasks are still running. */ +static volatile short sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; + +/* Variable which are incremented each time an item is posted on a queue. These +are used to check that the tasks are still running. */ +static volatile short sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartAltBlockingQueueTasks( UBaseType_t uxPriority ) +{ +xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2; +xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4; +xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6; +const UBaseType_t uxQueueSize1 = 1, uxQueueSize5 = 5; +const TickType_t xBlockTime = ( TickType_t ) 1000 / portTICK_PERIOD_MS; +const TickType_t xDontBlock = ( TickType_t ) 0; + + /* Create the first two tasks as described at the top of the file. */ + + /* First create the structure used to pass parameters to the consumer tasks. */ + pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Create the queue used by the first two tasks to pass the incrementing number. + Pass a pointer to the queue in the parameter structure. */ + pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) ); + + /* The consumer is created first so gets a block time as described above. */ + pxQueueParameters1->xBlockTime = xBlockTime; + + /* Pass in the variable that this task is going to increment so we can check it + is still running. */ + pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] ); + + /* Create the structure used to pass parameters to the producer task. */ + pxQueueParameters2 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Pass the queue to this task also, using the parameter structure. */ + pxQueueParameters2->xQueue = pxQueueParameters1->xQueue; + + /* The producer is not going to block - as soon as it posts the consumer will + wake and remove the item so the producer should always have room to post. */ + pxQueueParameters2->xBlockTime = xDontBlock; + + /* Pass in the variable that this task is going to increment so we can check + it is still running. */ + pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] ); + + + /* Note the producer has a lower priority than the consumer when the tasks are + spawned. */ + xTaskCreate( vBlockingQueueConsumer, "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL ); + xTaskCreate( vBlockingQueueProducer, "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL ); + + + + /* Create the second two tasks as described at the top of the file. This uses + the same mechanism but reverses the task priorities. */ + + pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) ); + pxQueueParameters3->xBlockTime = xDontBlock; + pxQueueParameters3->psCheckVariable = &( sBlockingProducerCount[ 1 ] ); + + pxQueueParameters4 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters4->xQueue = pxQueueParameters3->xQueue; + pxQueueParameters4->xBlockTime = xBlockTime; + pxQueueParameters4->psCheckVariable = &( sBlockingConsumerCount[ 1 ] ); + + xTaskCreate( vBlockingQueueConsumer, "QProdB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueProducer, "QConsB4", blckqSTACK_SIZE, ( void * ) pxQueueParameters4, uxPriority, NULL ); + + + + /* Create the last two tasks as described above. The mechanism is again just + the same. This time both parameter structures are given a block time. */ + pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( UBaseType_t ) sizeof( uint16_t ) ); + pxQueueParameters5->xBlockTime = xBlockTime; + pxQueueParameters5->psCheckVariable = &( sBlockingProducerCount[ 2 ] ); + + pxQueueParameters6 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters6->xQueue = pxQueueParameters5->xQueue; + pxQueueParameters6->xBlockTime = xBlockTime; + pxQueueParameters6->psCheckVariable = &( sBlockingConsumerCount[ 2 ] ); + + xTaskCreate( vBlockingQueueProducer, "QProdB5", blckqSTACK_SIZE, ( void * ) pxQueueParameters5, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueConsumer, "QConsB6", blckqSTACK_SIZE, ( void * ) pxQueueParameters6, tskIDLE_PRIORITY, NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vBlockingQueueProducer, pvParameters ) +{ +uint16_t usValue = 0; +xBlockingQueueParameters *pxQueueParameters; +short sErrorEverOccurred = pdFALSE; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt blocking queue producer task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + for( ;; ) + { + if( xQueueAltSendToBack( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS ) + { + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully posted a message, so increment the variable + used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the variable we are going to post next time round. The + consumer will expect the numbers to follow in numerical order. */ + ++usValue; + } + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vBlockingQueueConsumer, pvParameters ) +{ +uint16_t usData, usExpectedValue = 0; +xBlockingQueueParameters *pxQueueParameters; +short sErrorEverOccurred = pdFALSE; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt blocking queue consumer task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + for( ;; ) + { + if( xQueueAltReceive( pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + /* Catch-up. */ + usExpectedValue = usData; + + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully received a message, so increment the + variable used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the value we expect to remove from the queue next time + round. */ + ++usExpectedValue; + } + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreAltBlockingQueuesStillRunning( void ) +{ +static short sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; +static short sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; +BaseType_t xReturn = pdPASS, xTasks; + + /* Not too worried about mutual exclusion on these variables as they are 16 + bits and we are only reading them. We also only care to see if they have + changed or not. + + Loop through each check variable to and return pdFALSE if any are found not + to have changed since the last call. */ + + for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ ) + { + if( sBlockingConsumerCount[ xTasks ] == sLastBlockingConsumerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ]; + + + if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ]; + } + + return xReturn; +} + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlock.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlock.c new file mode 100644 index 0000000..f19e3f4 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlock.c @@ -0,0 +1,549 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * This is a version of BlockTim.c that uses the light weight API. + * + * This file contains some test scenarios that ensure tasks do not exit queue + * send or receive functions prematurely. A description of the tests is + * included within the code. + */ + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo includes. */ +#include "AltBlock.h" + +/* Task priorities. */ +#define bktPRIMARY_PRIORITY ( 3 ) +#define bktSECONDARY_PRIORITY ( 2 ) + +/* Task behaviour. */ +#define bktQUEUE_LENGTH ( 5 ) +#define bktSHORT_WAIT ( ( ( TickType_t ) 20 ) / portTICK_PERIOD_MS ) +#define bktPRIMARY_BLOCK_TIME ( 10 ) +#define bktALLOWABLE_MARGIN ( 12 ) +#define bktTIME_TO_BLOCK ( 175 ) +#define bktDONT_BLOCK ( ( TickType_t ) 0 ) +#define bktRUN_INDICATOR ( ( UBaseType_t ) 0x55 ) + +/* The queue on which the tasks block. */ +static QueueHandle_t xTestQueue; + +/* Handle to the secondary task is required by the primary task for calls +to vTaskSuspend/Resume(). */ +static TaskHandle_t xSecondary; + +/* Used to ensure that tasks are still executing without error. */ +static BaseType_t xPrimaryCycles = 0, xSecondaryCycles = 0; +static BaseType_t xErrorOccurred = pdFALSE; + +/* Provides a simple mechanism for the primary task to know when the +secondary task has executed. */ +static volatile UBaseType_t xRunIndicator; + +/* The two test tasks. Their behaviour is commented within the files. */ +static void vPrimaryBlockTimeTestTask( void *pvParameters ); +static void vSecondaryBlockTimeTestTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +void vCreateAltBlockTimeTasks( void ) +{ + /* Create the queue on which the two tasks block. */ + xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( BaseType_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xTestQueue, "AltBlockQueue" ); + + + /* Create the two test tasks. */ + xTaskCreate( vPrimaryBlockTimeTestTask, "FBTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL ); + xTaskCreate( vSecondaryBlockTimeTestTask, "FBTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary ); +} +/*-----------------------------------------------------------*/ + +static void vPrimaryBlockTimeTestTask( void *pvParameters ) +{ +BaseType_t xItem, xData; +TickType_t xTimeWhenBlocking; +TickType_t xTimeToBlock, xBlockedTime; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt primary block time test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + ( void ) pvParameters; + + for( ;; ) + { + /********************************************************************* + Test 1 + + Simple block time wakeup test on queue receives. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* The queue is empty. Attempt to read from the queue using a block + time. When we wake, ensure the delta in time is as expected. */ + xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem; + + /* A critical section is used to minimise the jitter in the time + measurements. */ + portENTER_CRITICAL(); + { + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after xTimeToBlock having not received + anything on the queue. */ + if( xQueueAltReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we blocked for? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + } + portEXIT_CRITICAL(); + + if( xBlockedTime < xTimeToBlock ) + { + /* Should not have blocked for less than we requested. */ + xErrorOccurred = pdTRUE; + } + + if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) ) + { + /* Should not have blocked for longer than we requested, + although we would not necessarily run as soon as we were + unblocked so a margin is allowed. */ + xErrorOccurred = pdTRUE; + } + } + + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + /********************************************************************* + Test 2 + + Simple block time wakeup test on queue sends. + + First fill the queue. It should be empty so all sends should pass. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + } + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* The queue is full. Attempt to write to the queue using a block + time. When we wake, ensure the delta in time is as expected. */ + xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem; + + portENTER_CRITICAL(); + { + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after xTimeToBlock having not received + anything on the queue. */ + if( xQueueAltSendToBack( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we blocked for? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + } + portEXIT_CRITICAL(); + + if( xBlockedTime < xTimeToBlock ) + { + /* Should not have blocked for less than we requested. */ + xErrorOccurred = pdTRUE; + } + + if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) ) + { + /* Should not have blocked for longer than we requested, + although we would not necessarily run as soon as we were + unblocked so a margin is allowed. */ + xErrorOccurred = pdTRUE; + } + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + /********************************************************************* + Test 3 + + Wake the other task, it will block attempting to post to the queue. + When we read from the queue the other task will wake, but before it + can run we will post to the queue again. When the other task runs it + will find the queue still full, even though it was woken. It should + recognise that its block time has not expired and return to block for + the remains of its block time. + + Wake the other task so it blocks attempting to post to the already + full queue. */ + xRunIndicator = 0; + vTaskResume( xSecondary ); + + /* We need to wait a little to ensure the other task executes. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + /* The other task has not yet executed. */ + vTaskDelay( bktSHORT_WAIT ); + } + /* Make sure the other task is blocked on the queue. */ + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* Now when we make space on the queue the other task should wake + but not execute as this task has higher priority. */ + if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Now fill the queue again before the other task gets a chance to + execute. If the other task had executed we would find the queue + full ourselves, and the other task have set xRunIndicator. */ + if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed. */ + xErrorOccurred = pdTRUE; + } + + /* Raise the priority of the other task so it executes and blocks + on the queue again. */ + vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 ); + + /* The other task should now have re-blocked without exiting the + queue function. */ + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed outside of the + queue function. */ + xErrorOccurred = pdTRUE; + } + + /* Set the priority back down. */ + vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); + } + + /* Let the other task timeout. When it unblockes it will check that it + unblocked at the correct time, then suspend itself. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /********************************************************************* + Test 4 + + As per test 3 - but with the send and receive the other way around. + The other task blocks attempting to read from the queue. + + Empty the queue. We should find that it is full. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + } + + /* Wake the other task so it blocks attempting to read from the + already empty queue. */ + vTaskResume( xSecondary ); + + /* We need to wait a little to ensure the other task executes. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* Now when we place an item on the queue the other task should + wake but not execute as this task has higher priority. */ + if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Now empty the queue again before the other task gets a chance to + execute. If the other task had executed we would find the queue + empty ourselves, and the other task would be suspended. */ + if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed. */ + xErrorOccurred = pdTRUE; + } + + /* Raise the priority of the other task so it executes and blocks + on the queue again. */ + vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 ); + + /* The other task should now have re-blocked without exiting the + queue function. */ + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed outside of the + queue function. */ + xErrorOccurred = pdTRUE; + } + vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); + } + + /* Let the other task timeout. When it unblockes it will check that it + unblocked at the correct time, then suspend itself. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + + xPrimaryCycles++; + } +} +/*-----------------------------------------------------------*/ + +static void vSecondaryBlockTimeTestTask( void *pvParameters ) +{ +TickType_t xTimeWhenBlocking, xBlockedTime; +BaseType_t xData; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt secondary block time test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + ( void ) pvParameters; + + for( ;; ) + { + /********************************************************************* + Test 1 and 2 + + This task does does not participate in these tests. */ + vTaskSuspend( NULL ); + + /********************************************************************* + Test 3 + + The first thing we do is attempt to read from the queue. It should be + full so we block. Note the time before we block so we can check the + wake time is as per that expected. */ + portENTER_CRITICAL(); + { + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after bktTIME_TO_BLOCK having not received + anything on the queue. */ + xData = 0; + xRunIndicator = bktRUN_INDICATOR; + if( xQueueAltSendToBack( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we inside the send function? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + } + portEXIT_CRITICAL(); + + /* We should not have blocked for less time than bktTIME_TO_BLOCK. */ + if( xBlockedTime < bktTIME_TO_BLOCK ) + { + xErrorOccurred = pdTRUE; + } + + /* We should of not blocked for much longer than bktALLOWABLE_MARGIN + either. A margin is permitted as we would not necessarily run as + soon as we unblocked. */ + if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) ) + { + xErrorOccurred = pdTRUE; + } + + /* Suspend ready for test 3. */ + xRunIndicator = bktRUN_INDICATOR; + vTaskSuspend( NULL ); + + /********************************************************************* + Test 4 + + As per test three, but with the send and receive reversed. */ + portENTER_CRITICAL(); + { + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after bktTIME_TO_BLOCK having not received + anything on the queue. */ + xRunIndicator = bktRUN_INDICATOR; + if( xQueueAltReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY ) + { + xErrorOccurred = pdTRUE; + } + + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + } + portEXIT_CRITICAL(); + + /* We should not have blocked for less time than bktTIME_TO_BLOCK. */ + if( xBlockedTime < bktTIME_TO_BLOCK ) + { + xErrorOccurred = pdTRUE; + } + + /* We should of not blocked for much longer than bktALLOWABLE_MARGIN + either. A margin is permitted as we would not necessarily run as soon + as we unblocked. */ + if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) ) + { + xErrorOccurred = pdTRUE; + } + + xRunIndicator = bktRUN_INDICATOR; + + xSecondaryCycles++; + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreAltBlockTimeTestTasksStillRunning( void ) +{ +static BaseType_t xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0; +BaseType_t xReturn = pdPASS; + + /* Have both tasks performed at least one cycle since this function was + last called? */ + if( xPrimaryCycles == xLastPrimaryCycleCount ) + { + xReturn = pdFAIL; + } + + if( xSecondaryCycles == xLastSecondaryCycleCount ) + { + xReturn = pdFAIL; + } + + if( xErrorOccurred == pdTRUE ) + { + xReturn = pdFAIL; + } + + xLastSecondaryCycleCount = xSecondaryCycles; + xLastPrimaryCycleCount = xPrimaryCycles; + + return xReturn; +} diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltPollQ.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltPollQ.c new file mode 100644 index 0000000..57b7322 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltPollQ.c @@ -0,0 +1,275 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * This is a version of PollQ.c that uses the alternative (Alt) API. + * + * Creates two tasks that communicate over a single queue. One task acts as a + * producer, the other a consumer. + * + * The producer loops for three iteration, posting an incrementing number onto the + * queue each cycle. It then delays for a fixed period before doing exactly the + * same again. + * + * The consumer loops emptying the queue. Each item removed from the queue is + * checked to ensure it contains the expected value. When the queue is empty it + * blocks for a fixed period, then does the same again. + * + * All queue access is performed without blocking. The consumer completely empties + * the queue each time it runs so the producer should never find the queue full. + * + * An error is flagged if the consumer obtains an unexpected value or the producer + * find the queue is full. + */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than uint32_t. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "AltPollQ.h" + +#define pollqSTACK_SIZE configMINIMAL_STACK_SIZE +#define pollqQUEUE_SIZE ( 10 ) +#define pollqPRODUCER_DELAY ( ( TickType_t ) 200 / portTICK_PERIOD_MS ) +#define pollqCONSUMER_DELAY ( pollqPRODUCER_DELAY - ( TickType_t ) ( 20 / portTICK_PERIOD_MS ) ) +#define pollqNO_DELAY ( ( TickType_t ) 0 ) +#define pollqVALUES_TO_PRODUCE ( ( BaseType_t ) 3 ) +#define pollqINITIAL_VALUE ( ( BaseType_t ) 0 ) + +/* The task that posts the incrementing number onto the queue. */ +static portTASK_FUNCTION_PROTO( vPolledQueueProducer, pvParameters ); + +/* The task that empties the queue. */ +static portTASK_FUNCTION_PROTO( vPolledQueueConsumer, pvParameters ); + +/* Variables that are used to check that the tasks are still running with no +errors. */ +static volatile BaseType_t xPollingConsumerCount = pollqINITIAL_VALUE, xPollingProducerCount = pollqINITIAL_VALUE; + +/*-----------------------------------------------------------*/ + +void vStartAltPolledQueueTasks( UBaseType_t uxPriority ) +{ +static QueueHandle_t xPolledQueue; + + /* Create the queue used by the producer and consumer. */ + xPolledQueue = xQueueCreate( pollqQUEUE_SIZE, ( UBaseType_t ) sizeof( uint16_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xPolledQueue, "AltPollQueue" ); + + + /* Spawn the producer and consumer. */ + xTaskCreate( vPolledQueueConsumer, "QConsNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( TaskHandle_t * ) NULL ); + xTaskCreate( vPolledQueueProducer, "QProdNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( TaskHandle_t * ) NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vPolledQueueProducer, pvParameters ) +{ +uint16_t usValue = ( uint16_t ) 0; +BaseType_t xError = pdFALSE, xLoop; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt polling queue producer task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + for( ;; ) + { + for( xLoop = 0; xLoop < pollqVALUES_TO_PRODUCE; xLoop++ ) + { + /* Send an incrementing number on the queue without blocking. */ + if( xQueueAltSendToBack( *( ( QueueHandle_t * ) pvParameters ), ( void * ) &usValue, pollqNO_DELAY ) != pdPASS ) + { + /* We should never find the queue full so if we get here there + has been an error. */ + xError = pdTRUE; + } + else + { + if( xError == pdFALSE ) + { + /* If an error has ever been recorded we stop incrementing the + check variable. */ + portENTER_CRITICAL(); + xPollingProducerCount++; + portEXIT_CRITICAL(); + } + + /* Update the value we are going to post next time around. */ + usValue++; + } + } + + /* Wait before we start posting again to ensure the consumer runs and + empties the queue. */ + vTaskDelay( pollqPRODUCER_DELAY ); + } +} /*lint !e818 Function prototype must conform to API. */ +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vPolledQueueConsumer, pvParameters ) +{ +uint16_t usData, usExpectedValue = ( uint16_t ) 0; +BaseType_t xError = pdFALSE; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt blocking queue consumer task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + for( ;; ) + { + /* Loop until the queue is empty. */ + while( uxQueueMessagesWaiting( *( ( QueueHandle_t * ) pvParameters ) ) ) + { + if( xQueueAltReceive( *( ( QueueHandle_t * ) pvParameters ), &usData, pollqNO_DELAY ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + /* This is not what we expected to receive so an error has + occurred. */ + xError = pdTRUE; + + /* Catch-up to the value we received so our next expected + value should again be correct. */ + usExpectedValue = usData; + } + else + { + if( xError == pdFALSE ) + { + /* Only increment the check variable if no errors have + occurred. */ + portENTER_CRITICAL(); + xPollingConsumerCount++; + portEXIT_CRITICAL(); + } + } + + /* Next time round we would expect the number to be one higher. */ + usExpectedValue++; + } + } + + /* Now the queue is empty we block, allowing the producer to place more + items in the queue. */ + vTaskDelay( pollqCONSUMER_DELAY ); + } +} /*lint !e818 Function prototype must conform to API. */ +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running with no errors. */ +BaseType_t xAreAltPollingQueuesStillRunning( void ) +{ +BaseType_t xReturn; + + /* Check both the consumer and producer poll count to check they have both + been changed since out last trip round. We do not need a critical section + around the check variables as this is called from a higher priority than + the other tasks that access the same variables. */ + if( ( xPollingConsumerCount == pollqINITIAL_VALUE ) || + ( xPollingProducerCount == pollqINITIAL_VALUE ) + ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + /* Set the check variables back down so we know if they have been + incremented the next time around. */ + xPollingConsumerCount = pollqINITIAL_VALUE; + xPollingProducerCount = pollqINITIAL_VALUE; + + return xReturn; +} diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltQTest.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltQTest.c new file mode 100644 index 0000000..188d3b0 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltQTest.c @@ -0,0 +1,587 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +/* + * This file implements the same demo and test as GenQTest.c, but uses the + * light weight API in place of the fully featured API. + * + * See the comments at the top of GenQTest.c for a description. + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +/* Demo program include files. */ +#include "AltQTest.h" + +#define genqQUEUE_LENGTH ( 5 ) +#define genqNO_BLOCK ( 0 ) + +#define genqMUTEX_LOW_PRIORITY ( tskIDLE_PRIORITY ) +#define genqMUTEX_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define genqMUTEX_MEDIUM_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define genqMUTEX_HIGH_PRIORITY ( tskIDLE_PRIORITY + 3 ) + +/*-----------------------------------------------------------*/ + +/* + * Tests the behaviour of the xQueueAltSendToFront() and xQueueAltSendToBack() + * macros by using both to fill a queue, then reading from the queue to + * check the resultant queue order is as expected. Queue data is also + * peeked. + */ +static void prvSendFrontAndBackTest( void *pvParameters ); + +/* + * The following three tasks are used to demonstrate the mutex behaviour. + * Each task is given a different priority to demonstrate the priority + * inheritance mechanism. + * + * The low priority task obtains a mutex. After this a high priority task + * attempts to obtain the same mutex, causing its priority to be inherited + * by the low priority task. The task with the inherited high priority then + * resumes a medium priority task to ensure it is not blocked by the medium + * priority task while it holds the inherited high priority. Once the mutex + * is returned the task with the inherited priority returns to its original + * low priority, and is therefore immediately preempted by first the high + * priority task and then the medium prioroity task before it can continue. + */ +static void prvLowPriorityMutexTask( void *pvParameters ); +static void prvMediumPriorityMutexTask( void *pvParameters ); +static void prvHighPriorityMutexTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdTRUE should any unexpected behaviour be +detected in any of the tasks. */ +static BaseType_t xErrorDetected = pdFALSE; + +/* Counters that are incremented on each cycle of a test. This is used to +detect a stalled task - a test that is no longer running. */ +static volatile uint32_t ulLoopCounter = 0; +static volatile uint32_t ulLoopCounter2 = 0; + +/* The variable that is guarded by the mutex in the mutex demo tasks. */ +static volatile uint32_t ulGuardedVariable = 0; + +/* Handles used in the mutext test to suspend and resume the high and medium +priority mutex test tasks. */ +static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask; + +/*-----------------------------------------------------------*/ + +void vStartAltGenericQueueTasks( UBaseType_t uxPriority ) +{ +QueueHandle_t xQueue; +SemaphoreHandle_t xMutex; + + /* Create the queue that we are going to use for the + prvSendFrontAndBackTest demo. */ + xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( uint32_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xQueue, "Alt_Gen_Test_Queue" ); + + /* Create the demo task and pass it the queue just created. We are + passing the queue handle by value so it does not matter that it is + declared on the stack here. */ + xTaskCreate( prvSendFrontAndBackTest, "FGenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL ); + + /* Create the mutex used by the prvMutexTest task. */ + xMutex = xSemaphoreCreateMutex(); + + /* vQueueAddToRegistry() adds the mutex to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate mutex and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Alt_Q_Mutex" ); + + /* Create the mutex demo tasks and pass it the mutex just created. We are + passing the mutex handle by value so it does not matter that it is declared + on the stack here. */ + xTaskCreate( prvLowPriorityMutexTask, "FMuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL ); + xTaskCreate( prvMediumPriorityMutexTask, "FMuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask ); + xTaskCreate( prvHighPriorityMutexTask, "FMuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask ); +} +/*-----------------------------------------------------------*/ + +static void prvSendFrontAndBackTest( void *pvParameters ) +{ +uint32_t ulData, ulData2; +QueueHandle_t xQueue; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt queue SendToFront/SendToBack/Peek test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + xQueue = ( QueueHandle_t ) pvParameters; + + for( ;; ) + { + /* The queue is empty, so sending an item to the back of the queue + should have the same efect as sending it to the front of the queue. + + First send to the front and check everything is as expected. */ + xQueueAltSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK ); + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* The data we sent to the queue should equal the data we just received + from the queue. */ + if( ulLoopCounter != ulData ) + { + xErrorDetected = pdTRUE; + } + + /* Then do the same, sending the data to the back, checking everything + is as expected. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + xQueueAltSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK ); + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* The data we sent to the queue should equal the data we just received + from the queue. */ + if( ulLoopCounter != ulData ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + + /* Place 2, 3, 4 into the queue, adding items to the back of the queue. */ + for( ulData = 2; ulData < 5; ulData++ ) + { + xQueueAltSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + } + + /* Now the order in the queue should be 2, 3, 4, with 2 being the first + thing to be read out. Now add 1 then 0 to the front of the queue. */ + if( uxQueueMessagesWaiting( xQueue ) != 3 ) + { + xErrorDetected = pdTRUE; + } + ulData = 1; + xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + ulData = 0; + xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + + /* Now the queue should be full, and when we read the data out we + should receive 0, 1, 2, 3, 4. */ + if( uxQueueMessagesWaiting( xQueue ) != 5 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the data we read out is in the expected order. */ + for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ ) + { + /* Try peeking the data first. */ + if( xQueueAltPeek( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + + + /* Now try receiving the data for real. The value should be the + same. Clobber the value first so we know we really received it. */ + ulData2 = ~ulData2; + if( xQueueAltReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + } + + /* The queue should now be empty again. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + /* Our queue is empty once more, add 10, 11 to the back. */ + ulData = 10; + if( xQueueAltSendToBack( xQueue, &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + ulData = 11; + if( xQueueAltSendToBack( xQueue, &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 2 ) + { + xErrorDetected = pdTRUE; + } + + /* Now we should have 10, 11 in the queue. Add 7, 8, 9 to the + front. */ + for( ulData = 9; ulData >= 7; ulData-- ) + { + if( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + } + + /* Now check that the queue is full, and that receiving data provides + the expected sequence of 7, 8, 9, 10, 11. */ + if( uxQueueMessagesWaiting( xQueue ) != 5 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the data we read out is in the expected order. */ + for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ ) + { + if( xQueueAltReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + } + + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvLowPriorityMutexTask( void *pvParameters ) +{ +SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Fast mutex with priority inheritance test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + ( void ) pvParameters; + + + for( ;; ) + { + /* Take the mutex. It should be available now. */ + if( xSemaphoreAltTake( xMutex, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* Set our guarded variable to a known start value. */ + ulGuardedVariable = 0; + + /* Our priority should be as per that assigned when the task was + created. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the high priority task. This will attempt to take the + mutex, and block when it finds it cannot obtain it. */ + vTaskResume( xHighPriorityMutexTask ); + + /* We should now have inherited the prioritoy of the high priority task, + as by now it will have attempted to get the mutex. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* We can attempt to set our priority to the test priority - between the + idle priority and the medium/high test priorities, but our actual + prioroity should remain at the high priority. */ + vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY ); + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the medium priority task. This should not run as our + inherited priority is above that of the medium priority task. */ + vTaskResume( xMediumPriorityMutexTask ); + + /* If the did run then it will have incremented our guarded variable. */ + if( ulGuardedVariable != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* When we give back the semaphore our priority should be disinherited + back to the priority to which we attempted to set ourselves. This means + that when the high priority task next blocks, the medium priority task + should execute and increment the guarded variable. When we next run + both the high and medium priority tasks will have been suspended again. */ + if( xSemaphoreAltGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* Check that the guarded variable did indeed increment... */ + if( ulGuardedVariable != 1 ) + { + xErrorDetected = pdTRUE; + } + + /* ... and that our priority has been disinherited to + genqMUTEX_TEST_PRIORITY. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Set our priority back to our original priority ready for the next + loop around this test. */ + vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY ); + + /* Just to show we are still running. */ + ulLoopCounter2++; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +static void prvMediumPriorityMutexTask( void *pvParameters ) +{ + ( void ) pvParameters; + + for( ;; ) + { + /* The medium priority task starts by suspending itself. The low + priority task will unsuspend this task when required. */ + vTaskSuspend( NULL ); + + /* When this task unsuspends all it does is increment the guarded + variable, this is so the low priority task knows that it has + executed. */ + ulGuardedVariable++; + } +} +/*-----------------------------------------------------------*/ + +static void prvHighPriorityMutexTask( void *pvParameters ) +{ +SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters; + + ( void ) pvParameters; + + for( ;; ) + { + /* The high priority task starts by suspending itself. The low + priority task will unsuspend this task when required. */ + vTaskSuspend( NULL ); + + /* When this task unsuspends all it does is attempt to obtain + the mutex. It should find the mutex is not available so a + block time is specified. */ + if( xSemaphoreAltTake( xMutex, portMAX_DELAY ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* When we eventually obtain the mutex we just give it back then + return to suspend ready for the next test. */ + if( xSemaphoreAltGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreAltGenericQueueTasksStillRunning( void ) +{ +static uint32_t ulLastLoopCounter = 0, ulLastLoopCounter2 = 0; + + /* If the demo task is still running then we expect the loopcounters to + have incremented since this function was last called. */ + if( ulLastLoopCounter == ulLoopCounter ) + { + xErrorDetected = pdTRUE; + } + + if( ulLastLoopCounter2 == ulLoopCounter2 ) + { + xErrorDetected = pdTRUE; + } + + ulLastLoopCounter = ulLoopCounter; + ulLastLoopCounter2 = ulLoopCounter2; + + /* Errors detected in the task itself will have latched xErrorDetected + to true. */ + + return !xErrorDetected; +} + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/BlockQ.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/BlockQ.c new file mode 100644 index 0000000..b8db390 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/BlockQ.c @@ -0,0 +1,324 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * Creates six tasks that operate on three queues as follows: + * + * The first two tasks send and receive an incrementing number to/from a queue. + * One task acts as a producer and the other as the consumer. The consumer is a + * higher priority than the producer and is set to block on queue reads. The queue + * only has space for one item - as soon as the producer posts a message on the + * queue the consumer will unblock, pre-empt the producer, and remove the item. + * + * The second two tasks work the other way around. Again the queue used only has + * enough space for one item. This time the consumer has a lower priority than the + * producer. The producer will try to post on the queue blocking when the queue is + * full. When the consumer wakes it will remove the item from the queue, causing + * the producer to unblock, pre-empt the consumer, and immediately re-fill the + * queue. + * + * The last two tasks use the same queue producer and consumer functions. This time the queue has + * enough space for lots of items and the tasks operate at the same priority. The + * producer will execute, placing items into the queue. The consumer will start + * executing when either the queue becomes full (causing the producer to block) or + * a context switch occurs (tasks of the same priority will time slice). + * + */ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "BlockQ.h" + +#define blckqSTACK_SIZE configMINIMAL_STACK_SIZE +#define blckqNUM_TASK_SETS ( 3 ) + +/* Structure used to pass parameters to the blocking queue tasks. */ +typedef struct BLOCKING_QUEUE_PARAMETERS +{ + QueueHandle_t xQueue; /*< The queue to be used by the task. */ + TickType_t xBlockTime; /*< The block time to use on queue reads/writes. */ + volatile short *psCheckVariable; /*< Incremented on each successful cycle to check the task is still running. */ +} xBlockingQueueParameters; + +/* Task function that creates an incrementing number and posts it on a queue. */ +static portTASK_FUNCTION_PROTO( vBlockingQueueProducer, pvParameters ); + +/* Task function that removes the incrementing number from a queue and checks that +it is the expected number. */ +static portTASK_FUNCTION_PROTO( vBlockingQueueConsumer, pvParameters ); + +/* Variables which are incremented each time an item is removed from a queue, and +found to be the expected value. +These are used to check that the tasks are still running. */ +static volatile short sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; + +/* Variable which are incremented each time an item is posted on a queue. These +are used to check that the tasks are still running. */ +static volatile short sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartBlockingQueueTasks( UBaseType_t uxPriority ) +{ +xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2; +xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4; +xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6; +const UBaseType_t uxQueueSize1 = 1, uxQueueSize5 = 5; +const TickType_t xBlockTime = ( TickType_t ) 1000 / portTICK_PERIOD_MS; +const TickType_t xDontBlock = ( TickType_t ) 0; + + /* Create the first two tasks as described at the top of the file. */ + + /* First create the structure used to pass parameters to the consumer tasks. */ + pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Create the queue used by the first two tasks to pass the incrementing number. + Pass a pointer to the queue in the parameter structure. */ + pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) ); + + /* The consumer is created first so gets a block time as described above. */ + pxQueueParameters1->xBlockTime = xBlockTime; + + /* Pass in the variable that this task is going to increment so we can check it + is still running. */ + pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] ); + + /* Create the structure used to pass parameters to the producer task. */ + pxQueueParameters2 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Pass the queue to this task also, using the parameter structure. */ + pxQueueParameters2->xQueue = pxQueueParameters1->xQueue; + + /* The producer is not going to block - as soon as it posts the consumer will + wake and remove the item so the producer should always have room to post. */ + pxQueueParameters2->xBlockTime = xDontBlock; + + /* Pass in the variable that this task is going to increment so we can check + it is still running. */ + pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] ); + + + /* Note the producer has a lower priority than the consumer when the tasks are + spawned. */ + xTaskCreate( vBlockingQueueConsumer, "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL ); + xTaskCreate( vBlockingQueueProducer, "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL ); + + + + /* Create the second two tasks as described at the top of the file. This uses + the same mechanism but reverses the task priorities. */ + + pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) ); + pxQueueParameters3->xBlockTime = xDontBlock; + pxQueueParameters3->psCheckVariable = &( sBlockingProducerCount[ 1 ] ); + + pxQueueParameters4 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters4->xQueue = pxQueueParameters3->xQueue; + pxQueueParameters4->xBlockTime = xBlockTime; + pxQueueParameters4->psCheckVariable = &( sBlockingConsumerCount[ 1 ] ); + + xTaskCreate( vBlockingQueueConsumer, "QConsB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueProducer, "QProdB4", blckqSTACK_SIZE, ( void * ) pxQueueParameters4, uxPriority, NULL ); + + + + /* Create the last two tasks as described above. The mechanism is again just + the same. This time both parameter structures are given a block time. */ + pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( UBaseType_t ) sizeof( uint16_t ) ); + pxQueueParameters5->xBlockTime = xBlockTime; + pxQueueParameters5->psCheckVariable = &( sBlockingProducerCount[ 2 ] ); + + pxQueueParameters6 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters6->xQueue = pxQueueParameters5->xQueue; + pxQueueParameters6->xBlockTime = xBlockTime; + pxQueueParameters6->psCheckVariable = &( sBlockingConsumerCount[ 2 ] ); + + xTaskCreate( vBlockingQueueProducer, "QProdB5", blckqSTACK_SIZE, ( void * ) pxQueueParameters5, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueConsumer, "QConsB6", blckqSTACK_SIZE, ( void * ) pxQueueParameters6, tskIDLE_PRIORITY, NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vBlockingQueueProducer, pvParameters ) +{ +uint16_t usValue = 0; +xBlockingQueueParameters *pxQueueParameters; +short sErrorEverOccurred = pdFALSE; + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + for( ;; ) + { + if( xQueueSend( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS ) + { + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully posted a message, so increment the variable + used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the variable we are going to post next time round. The + consumer will expect the numbers to follow in numerical order. */ + ++usValue; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vBlockingQueueConsumer, pvParameters ) +{ +uint16_t usData, usExpectedValue = 0; +xBlockingQueueParameters *pxQueueParameters; +short sErrorEverOccurred = pdFALSE; + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + for( ;; ) + { + if( xQueueReceive( pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + /* Catch-up. */ + usExpectedValue = usData; + + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully received a message, so increment the + variable used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the value we expect to remove from the queue next time + round. */ + ++usExpectedValue; + } + + #if configUSE_PREEMPTION == 0 + { + if( pxQueueParameters->xBlockTime == 0 ) + { + taskYIELD(); + } + } + #endif + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreBlockingQueuesStillRunning( void ) +{ +static short sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; +static short sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; +BaseType_t xReturn = pdPASS, xTasks; + + /* Not too worried about mutual exclusion on these variables as they are 16 + bits and we are only reading them. We also only care to see if they have + changed or not. + + Loop through each check variable to and return pdFALSE if any are found not + to have changed since the last call. */ + + for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ ) + { + if( sBlockingConsumerCount[ xTasks ] == sLastBlockingConsumerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ]; + + + if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ]; + } + + return xReturn; +} + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/EventGroupsDemo.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/EventGroupsDemo.c new file mode 100644 index 0000000..64d7430 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/EventGroupsDemo.c @@ -0,0 +1,1074 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + + +/* +* This file contains fairly comprehensive checks on the behaviour of event +* groups. It is not intended to be a user friendly demonstration of the +* event groups API. +* +* NOTE: The tests implemented in this file are informal 'sanity' tests +* only and are not part of the module tests that make use of the +* mtCOVERAGE_TEST_MARKER macro within the event groups implementation. +*/ + + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "event_groups.h" + +/* Demo app includes. */ +#include "EventGroupsDemo.h" + +#if( INCLUDE_eTaskGetState != 1 ) + #error INCLUDE_eTaskGetState must be set to 1 in FreeRTOSConfig.h to use this demo file. +#endif + +/* Priorities used by the tasks. */ +#define ebSET_BIT_TASK_PRIORITY ( tskIDLE_PRIORITY ) +#define ebWAIT_BIT_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) + +/* Generic bit definitions. */ +#define ebBIT_0 ( 0x01UL ) +#define ebBIT_1 ( 0x02UL ) +#define ebBIT_2 ( 0x04UL ) +#define ebBIT_3 ( 0x08UL ) +#define ebBIT_4 ( 0x10UL ) +#define ebBIT_5 ( 0x20UL ) +#define ebBIT_6 ( 0x40UL ) +#define ebBIT_7 ( 0x80UL ) + +/* Combinations of bits used in the demo. */ +#define ebCOMBINED_BITS ( ebBIT_1 | ebBIT_5 | ebBIT_7 ) +#define ebALL_BITS ( ebBIT_0 | ebBIT_1 | ebBIT_2 | ebBIT_3 | ebBIT_4 | ebBIT_5 | ebBIT_6 | ebBIT_7 ) + +/* Associate a bit to each task. These bits are used to identify all the tasks +that synchronise with the xEventGroupSync() function. */ +#define ebSET_BIT_TASK_SYNC_BIT ebBIT_0 +#define ebWAIT_BIT_TASK_SYNC_BIT ebBIT_1 +#define ebRENDESVOUS_TASK_1_SYNC_BIT ebBIT_2 +#define ebRENDESVOUS_TASK_2_SYNC_BIT ebBIT_3 +#define ebALL_SYNC_BITS ( ebSET_BIT_TASK_SYNC_BIT | ebWAIT_BIT_TASK_SYNC_BIT | ebRENDESVOUS_TASK_1_SYNC_BIT | ebRENDESVOUS_TASK_2_SYNC_BIT ) + +/* A block time of zero simply means "don't block". */ +#define ebDONT_BLOCK ( 0 ) + +/* A 5ms delay. */ +#define ebSHORT_DELAY ( 5 / portTICK_PERIOD_MS ) + +/* Used in the selective bits test which checks no, one or both tasks blocked on +event bits in a group are unblocked as appropriate as different bits get set. */ +#define ebSELECTIVE_BITS_1 0x03 +#define ebSELECTIVE_BITS_2 0x05 + +/*-----------------------------------------------------------*/ + +/* + * NOTE: The tests implemented in this function are informal 'sanity' tests + * only and are not part of the module tests that make use of the + * mtCOVERAGE_TEST_MARKER macro within the event groups implementation. + * + * The master test task. This task: + * + * 1) Calls prvSelectiveBitsTestMasterFunction() to test the behaviour when two + * tasks are blocked on different bits in an event group. The counterpart of + * this test is implemented by the prvSelectiveBitsTestSlaveFunction() + * function (which is called by the two tasks that block on the event group). + * + * 2) Calls prvBitCombinationTestMasterFunction() to test the behaviour when + * just one task is blocked on various combinations of bits within an event + * group. The counterpart of this test is implemented within the 'test + * slave' task. + * + * 3) Calls prvPerformTaskSyncTests() to test task synchronisation behaviour. + */ +static void prvTestMasterTask( void *pvParameters ); + +/* + * A helper task that enables the 'test master' task to perform several + * behavioural tests. See the comments above the prvTestMasterTask() prototype + * above. + */ +static void prvTestSlaveTask( void *pvParameters ); + +/* + * The part of the test that is performed between the 'test master' task and the + * 'test slave' task to test the behaviour when the slave blocks on various + * event bit combinations. + */ +static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle ); + +/* + * The part of the test that uses all the tasks to test the task synchronisation + * behaviour. + */ +static BaseType_t prvPerformTaskSyncTests( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle ); + +/* + * Two instances of prvSyncTask() are created. They start by calling + * prvSelectiveBitsTestSlaveFunction() to act as slaves when the test master is + * executing the prvSelectiveBitsTestMasterFunction() function. They then loop + * to test the task synchronisation (rendezvous) behaviour. + */ +static void prvSyncTask( void *pvParameters ); + +/* + * Functions used in a test that blocks two tasks on various different bits + * within an event group - then sets each bit in turn and checks that the + * correct tasks unblock at the correct times. + */ +static BaseType_t prvSelectiveBitsTestMasterFunction( void ); +static void prvSelectiveBitsTestSlaveFunction( void ); + +/*-----------------------------------------------------------*/ + +/* Variables that are incremented by the tasks on each cycle provided no errors +have been found. Used to detect an error or stall in the test cycling. */ +static volatile uint32_t ulTestMasterCycles = 0, ulTestSlaveCycles = 0, ulISRCycles = 0; + +/* The event group used by all the task based tests. */ +static EventGroupHandle_t xEventGroup = NULL; + +/* The event group used by the interrupt based tests. */ +static EventGroupHandle_t xISREventGroup = NULL; + +/* Handles to the tasks that only take part in the synchronisation calls. */ +static TaskHandle_t xSyncTask1 = NULL, xSyncTask2 = NULL; + +/*-----------------------------------------------------------*/ + +void vStartEventGroupTasks( void ) +{ +TaskHandle_t xTestSlaveTaskHandle; + + /* + * This file contains fairly comprehensive checks on the behaviour of event + * groups. It is not intended to be a user friendly demonstration of the + * event groups API. + * + * NOTE: The tests implemented in this file are informal 'sanity' tests + * only and are not part of the module tests that make use of the + * mtCOVERAGE_TEST_MARKER macro within the event groups implementation. + * + * Create the test tasks as described at the top of this file. + */ + xTaskCreate( prvTestSlaveTask, "WaitO", configMINIMAL_STACK_SIZE, NULL, ebWAIT_BIT_TASK_PRIORITY, &xTestSlaveTaskHandle ); + xTaskCreate( prvTestMasterTask, "SetB", configMINIMAL_STACK_SIZE, ( void * ) xTestSlaveTaskHandle, ebSET_BIT_TASK_PRIORITY, NULL ); + xTaskCreate( prvSyncTask, "Rndv", configMINIMAL_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_1_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask1 ); + xTaskCreate( prvSyncTask, "Rndv", configMINIMAL_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_2_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask2 ); + + /* If the last task was created then the others will have been too. */ + configASSERT( xSyncTask2 ); + + /* Create the event group used by the ISR tests. The event group used by + the tasks is created by the tasks themselves. */ + xISREventGroup = xEventGroupCreate(); + configASSERT( xISREventGroup ); +} +/*-----------------------------------------------------------*/ + +static void prvTestMasterTask( void *pvParameters ) +{ +BaseType_t xError; + +/* The handle to the slave task is passed in as the task parameter. */ +TaskHandle_t xTestSlaveTaskHandle = ( TaskHandle_t ) pvParameters; + + /* Avoid compiler warnings. */ + ( void ) pvParameters; + + /* Create the event group used by the tasks ready for the initial tests. */ + xEventGroup = xEventGroupCreate(); + configASSERT( xEventGroup ); + + /* Perform the tests that block two tasks on different combinations of bits, + then set each bit in turn and check the correct tasks unblock at the correct + times. */ + xError = prvSelectiveBitsTestMasterFunction(); + + for( ;; ) + { + /* Recreate the event group ready for the next cycle. */ + xEventGroup = xEventGroupCreate(); + configASSERT( xEventGroup ); + + /* Perform the tests that check the behaviour when a single task is + blocked on various combinations of event bits. */ + xError = prvBitCombinationTestMasterFunction( xError, xTestSlaveTaskHandle ); + + /* Perform the task synchronisation tests. */ + xError = prvPerformTaskSyncTests( xError, xTestSlaveTaskHandle ); + + /* Delete the event group. */ + vEventGroupDelete( xEventGroup ); + + /* Now all the other tasks should have completed and suspended + themselves ready for the next go around the loop. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eSuspended ) + { + xError = pdTRUE; + } + + /* Only increment the cycle variable if no errors have been detected. */ + if( xError == pdFALSE ) + { + ulTestMasterCycles++; + } + + configASSERT( xError == pdFALSE ); + } +} +/*-----------------------------------------------------------*/ + +static void prvSyncTask( void *pvParameters ) +{ +EventBits_t uxSynchronisationBit, uxReturned; + + /* A few tests that check the behaviour when two tasks are blocked on + various different bits within an event group are performed before this task + enters its infinite loop to carry out its main demo function. */ + prvSelectiveBitsTestSlaveFunction(); + + /* The bit to use to indicate this task is at the synchronisation point is + passed in as the task parameter. */ + uxSynchronisationBit = ( EventBits_t ) pvParameters; + + for( ;; ) + { + /* Now this task takes part in a task synchronisation - sometimes known + as a 'rendezvous'. Its execution pattern is controlled by the 'test + master' task, which is responsible for taking this task out of the + Suspended state when it is time to test the synchronisation behaviour. + See: http://www.freertos.org/xEventGroupSync.html. */ + vTaskSuspend( NULL ); + + /* Set the bit that indicates this task is at the synchronisation + point. The first time this is done the 'test master' task has a lower + priority than this task so this task will get to the sync point before + the set bits task. */ + uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */ + uxSynchronisationBit, /* The bit to set in the event group to indicate this task is at the sync point. */ + ebALL_SYNC_BITS,/* The bits to wait for - these bits are set by the other tasks taking part in the sync. */ + portMAX_DELAY );/* The maximum time to wait for the sync condition to be met before giving up. */ + + /* A max delay was used, so this task should only exit the above + function call when the sync condition is met. Check this is the + case. */ + configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS ); + + /* Remove compiler warning if configASSERT() is not defined. */ + ( void ) uxReturned; + + /* Wait until the 'test master' task unsuspends this task again. */ + vTaskSuspend( NULL ); + + /* Set the bit that indicates this task is at the synchronisation + point again. This time the 'test master' task has a higher priority + than this task so will get to the sync point before this task. */ + uxReturned = xEventGroupSync( xEventGroup, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY ); + + /* Again a max delay was used, so this task should only exit the above + function call when the sync condition is met. Check this is the + case. */ + configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS ); + + /* Block on the event group again. This time the event group is going + to be deleted while this task is blocked on it so it is expected that 0 + be returned. */ + uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY ); + configASSERT( uxReturned == 0 ); + } +} +/*-----------------------------------------------------------*/ + +static void prvTestSlaveTask( void *pvParameters ) +{ +EventBits_t uxReturned; +BaseType_t xError = pdFALSE; + + /* Avoid compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /********************************************************************** + * Part 1: This section is the counterpart to the + * prvBitCombinationTestMasterFunction() function which is called by the + * test master task. + *********************************************************************** + + This task is controller by the 'test master' task (which is + implemented by prvTestMasterTask()). Suspend until resumed by the + 'test master' task. */ + vTaskSuspend( NULL ); + + /* Wait indefinitely for one of the bits in ebCOMBINED_BITS to get + set. Clear the bit on exit. */ + uxReturned = xEventGroupWaitBits( xEventGroup, /* The event group that contains the event bits being queried. */ + ebBIT_1, /* The bit to wait for. */ + pdTRUE, /* Clear the bit on exit. */ + pdTRUE, /* Wait for all the bits (only one in this case anyway). */ + portMAX_DELAY ); /* Block indefinitely to wait for the condition to be met. */ + + /* The 'test master' task set all the bits defined by ebCOMBINED_BITS, + only one of which was being waited for by this task. The return value + shows the state of the event bits when the task was unblocked, however + because the task was waiting for ebBIT_1 and 'clear on exit' was set to + the current state of the event bits will have ebBIT_1 clear. */ + if( uxReturned != ebCOMBINED_BITS ) + { + xError = pdTRUE; + } + + /* Now call xEventGroupWaitBits() again, this time waiting for all the + bits in ebCOMBINED_BITS to be set. This call should block until the + 'test master' task sets ebBIT_1 - which was the bit cleared in the call + to xEventGroupWaitBits() above. */ + uxReturned = xEventGroupWaitBits( xEventGroup, + ebCOMBINED_BITS, /* The bits being waited on. */ + pdFALSE, /* Don't clear the bits on exit. */ + pdTRUE, /* All the bits must be set to unblock. */ + portMAX_DELAY ); + + /* Were all the bits set? */ + if( ( uxReturned & ebCOMBINED_BITS ) != ebCOMBINED_BITS ) + { + xError = pdTRUE; + } + + /* Suspend again to wait for the 'test master' task. */ + vTaskSuspend( NULL ); + + /* Now call xEventGroupWaitBits() again, again waiting for all the bits + in ebCOMBINED_BITS to be set, but this time clearing the bits when the + task is unblocked. */ + uxReturned = xEventGroupWaitBits( xEventGroup, + ebCOMBINED_BITS, /* The bits being waited on. */ + pdTRUE, /* Clear the bits on exit. */ + pdTRUE, /* All the bits must be set to unblock. */ + portMAX_DELAY ); + + /* The 'test master' task set all the bits in the event group, so that + is the value that should have been returned. The bits defined by + ebCOMBINED_BITS will have been clear again in the current value though + as 'clear on exit' was set to pdTRUE. */ + if( uxReturned != ebALL_BITS ) + { + xError = pdTRUE; + } + + + + + + /********************************************************************** + * Part 2: This section is the counterpart to the + * prvPerformTaskSyncTests() function which is called by the + * test master task. + *********************************************************************** + + + Once again wait for the 'test master' task to unsuspend this task + when it is time for the next test. */ + vTaskSuspend( NULL ); + + /* Now peform a synchronisation with all the other tasks. At this point + the 'test master' task has the lowest priority so will get to the sync + point after all the other synchronising tasks. */ + uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the sync. */ + ebWAIT_BIT_TASK_SYNC_BIT, /* The bit in the event group used to indicate this task is at the sync point. */ + ebALL_SYNC_BITS, /* The bits to wait for. These bits are set by the other tasks taking part in the sync. */ + portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met before giving up. */ + + /* A sync with a max delay should only exit when all the synchronisation + bits are set... */ + if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS ) + { + xError = pdTRUE; + } + + /* ...but now the synchronisation bits should be clear again. Read back + the current value of the bits within the event group to check that is + the case. Setting the bits to zero will return the bits previous value + then leave all the bits clear. */ + if( xEventGroupSetBits( xEventGroup, 0x00 ) != 0 ) + { + xError = pdTRUE; + } + + /* Check the bits are indeed 0 now by simply reading then. */ + if( xEventGroupGetBits( xEventGroup ) != 0 ) + { + xError = pdTRUE; + } + + if( xError == pdFALSE ) + { + /* This task is still cycling without finding an error. */ + ulTestSlaveCycles++; + } + + vTaskSuspend( NULL ); + + /* This time sync when the 'test master' task has the highest priority + at the point where it sets its sync bit - so this time the 'test master' + task will get to the sync point before this task. */ + uxReturned = xEventGroupSync( xEventGroup, ebWAIT_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY ); + + /* A sync with a max delay should only exit when all the synchronisation + bits are set... */ + if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS ) + { + xError = pdTRUE; + } + + /* ...but now the sync bits should be clear again. */ + if( xEventGroupSetBits( xEventGroup, 0x00 ) != 0 ) + { + xError = pdTRUE; + } + + /* Block on the event group again. This time the event group is going + to be deleted while this task is blocked on it, so it is expected that 0 + will be returned. */ + uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY ); + + if( uxReturned != 0 ) + { + xError = pdTRUE; + } + + if( xError == pdFALSE ) + { + /* This task is still cycling without finding an error. */ + ulTestSlaveCycles++; + } + + configASSERT( xError == pdFALSE ); + } +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvPerformTaskSyncTests( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle ) +{ +EventBits_t uxBits; + + /* The three tasks that take part in the synchronisation (rendezvous) are + expected to be in the suspended state at the start of the test. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eSuspended ) + { + xError = pdTRUE; + } + + /* Try a synch with no other tasks involved. First set all the bits other + than this task's bit. */ + xEventGroupSetBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) ); + + /* Then wait on just one bit - the bit that is being set. */ + uxBits = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */ + ebSET_BIT_TASK_SYNC_BIT,/* The bit set by this task when it reaches the sync point. */ + ebSET_BIT_TASK_SYNC_BIT,/* The bits to wait for - in this case it is just waiting for itself. */ + portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met. */ + + /* A sync with a max delay should only exit when all the synchronise + bits are set...check that is the case. In this case there is only one + sync bit anyway. */ + if( ( uxBits & ebSET_BIT_TASK_SYNC_BIT ) != ebSET_BIT_TASK_SYNC_BIT ) + { + xError = pdTRUE; + } + + /* ...but now the sync bits should be clear again, leaving all the other + bits set (as only one bit was being waited for). */ + if( xEventGroupGetBits( xEventGroup ) != ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) ) + { + xError = pdTRUE; + } + + /* Clear all the bits to zero again. */ + xEventGroupClearBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) ); + if( xEventGroupGetBits( xEventGroup ) != 0 ) + { + xError = pdTRUE; + } + + /* Unsuspend the other tasks then check they have executed up to the + synchronisation point. */ + vTaskResume( xTestSlaveTaskHandle ); + vTaskResume( xSyncTask1 ); + vTaskResume( xSyncTask2 ); + + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Set this task's sync bit. */ + uxBits = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */ + ebSET_BIT_TASK_SYNC_BIT,/* The bit set by this task when it reaches the sync point. */ + ebALL_SYNC_BITS, /* The bits to wait for - these bits are set by the other tasks that take part in the sync. */ + portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met. */ + + /* A sync with a max delay should only exit when all the synchronise + bits are set...check that is the case. */ + if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS ) + { + xError = pdTRUE; + } + + /* ...but now the sync bits should be clear again. */ + if( xEventGroupGetBits( xEventGroup ) != 0 ) + { + xError = pdTRUE; + } + + + /* The other tasks should now all be suspended again, ready for the next + synchronisation. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eSuspended ) + { + xError = pdTRUE; + } + + + /* Sync again - but this time set the last necessary bit as the + highest priority task, rather than the lowest priority task. Unsuspend + the other tasks then check they have executed up to the synchronisation + point. */ + vTaskResume( xTestSlaveTaskHandle ); + vTaskResume( xSyncTask1 ); + vTaskResume( xSyncTask2 ); + + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Raise the priority of this task above that of the other tasks. */ + vTaskPrioritySet( NULL, ebWAIT_BIT_TASK_PRIORITY + 1 ); + + /* Set this task's sync bit. */ + uxBits = xEventGroupSync( xEventGroup, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY ); + + /* A sync with a max delay should only exit when all the synchronisation + bits are set... */ + if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS ) + { + xError = pdTRUE; + } + + /* ...but now the sync bits should be clear again. */ + if( xEventGroupGetBits( xEventGroup ) != 0 ) + { + xError = pdTRUE; + } + + + /* The other tasks should now all be in the ready state again, but not + executed yet as this task still has a higher relative priority. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eReady ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eReady ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eReady ) + { + xError = pdTRUE; + } + + + /* Reset the priority of this task back to its original value. */ + vTaskPrioritySet( NULL, ebSET_BIT_TASK_PRIORITY ); + + /* Now all the other tasks should have reblocked on the event bits + to test the behaviour when the event bits are deleted. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eBlocked ) + { + xError = pdTRUE; + } + + return xError; +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle ) +{ +EventBits_t uxBits; + + /* Resume the other task. It will block, pending a single bit from + within ebCOMBINED_BITS. */ + vTaskResume( xTestSlaveTaskHandle ); + + /* Ensure the other task is blocked on the task. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Set all the bits in ebCOMBINED_BITS - the 'test slave' task is only + blocked waiting for one of them. */ + xEventGroupSetBits( xEventGroup, ebCOMBINED_BITS ); + + /* The 'test slave' task should now have executed, clearing ebBIT_1 (the + bit it was blocked on), then re-entered the Blocked state to wait for + all the other bits in ebCOMBINED_BITS to be set again. First check + ebBIT_1 is clear. */ + uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK ); + + if( uxBits != ( ebCOMBINED_BITS & ~ebBIT_1 ) ) + { + xError = pdTRUE; + } + + /* Ensure the other task is still in the blocked state. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Set all the bits other than ebBIT_1 - which is the bit that must be + set before the other task unblocks. */ + xEventGroupSetBits( xEventGroup, ebALL_BITS & ~ebBIT_1 ); + + /* Ensure all the expected bits are still set. */ + uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK ); + + if( uxBits != ( ebALL_BITS & ~ebBIT_1 ) ) + { + xError = pdTRUE; + } + + /* Ensure the other task is still in the blocked state. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Now also set ebBIT_1, which should unblock the other task, which will + then suspend itself. */ + xEventGroupSetBits( xEventGroup, ebBIT_1 ); + + /* Ensure the other task is suspended. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended ) + { + xError = pdTRUE; + } + + /* The other task should not have cleared the bits - so all the bits + should still be set. */ + if( xEventGroupSetBits( xEventGroup, 0x00 ) != ebALL_BITS ) + { + xError = pdTRUE; + } + + /* Clear ebBIT_1 again. */ + if( xEventGroupClearBits( xEventGroup, ebBIT_1 ) != ebALL_BITS ) + { + xError = pdTRUE; + } + + /* Resume the other task - which will wait on all the ebCOMBINED_BITS + again - this time clearing the bits when it is unblocked. */ + vTaskResume( xTestSlaveTaskHandle ); + + /* Ensure the other task is blocked once again. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Set the bit the other task is waiting for. */ + xEventGroupSetBits( xEventGroup, ebBIT_1 ); + + /* Ensure the other task is suspended once again. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended ) + { + xError = pdTRUE; + } + + /* The other task should have cleared the bits in ebCOMBINED_BITS. + Clear the remaining bits. */ + uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK ); + + if( uxBits != ( ebALL_BITS & ~ebCOMBINED_BITS ) ) + { + xError = pdTRUE; + } + + /* Clear all bits ready for the sync with the other three tasks. The + value returned is the value prior to the bits being cleared. */ + if( xEventGroupClearBits( xEventGroup, ebALL_BITS ) != ( ebALL_BITS & ~ebCOMBINED_BITS ) ) + { + xError = pdTRUE; + } + + /* The bits should be clear now. */ + if( xEventGroupGetBits( xEventGroup ) != 0x00 ) + { + xError = pdTRUE; + } + + return xError; +} +/*-----------------------------------------------------------*/ + +static void prvSelectiveBitsTestSlaveFunction( void ) +{ +EventBits_t uxPendBits, uxReturned; + + /* Used in a test that blocks two tasks on various different bits within an + event group - then sets each bit in turn and checks that the correct tasks + unblock at the correct times. + + This function is called by two different tasks - each of which will use a + different bit. Check the task handle to see which task the function was + called by. */ + if( xTaskGetCurrentTaskHandle() == xSyncTask1 ) + { + uxPendBits = ebSELECTIVE_BITS_1; + } + else + { + uxPendBits = ebSELECTIVE_BITS_2; + } + + for( ;; ) + { + /* Wait until it is time to perform the next cycle of the test. The + task is unsuspended by the tests implemented in the + prvSelectiveBitsTestMasterFunction() function. */ + vTaskSuspend( NULL ); + uxReturned = xEventGroupWaitBits( xEventGroup, uxPendBits, pdTRUE, pdFALSE, portMAX_DELAY ); + + if( uxReturned == ( EventBits_t ) 0 ) + { + break; + } + } +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvSelectiveBitsTestMasterFunction( void ) +{ +BaseType_t xError = pdFALSE; +EventBits_t uxBit; + + /* Used in a test that blocks two tasks on various different bits within an + event group - then sets each bit in turn and checks that the correct tasks + unblock at the correct times. The two other tasks (xSyncTask1 and + xSyncTask2) call prvSelectiveBitsTestSlaveFunction() to perform their parts in + this test. + + Both other tasks should start in the suspended state. */ + if( eTaskGetState( xSyncTask1 ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eSuspended ) + { + xError = pdTRUE; + } + + /* Test each bit in the byte individually. */ + for( uxBit = 0x01; uxBit < 0x100; uxBit <<= 1 ) + { + /* Resume both tasks. */ + vTaskResume( xSyncTask1 ); + vTaskResume( xSyncTask2 ); + + /* Now both tasks should be blocked on the event group. */ + if( eTaskGetState( xSyncTask1 ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Set one bit. */ + xEventGroupSetBits( xEventGroup, uxBit ); + + /* Is the bit set in the first set of selective bits? If so the first + sync task should have unblocked and returned to the suspended state. */ + if( ( uxBit & ebSELECTIVE_BITS_1 ) == 0 ) + { + /* Task should not have unblocked. */ + if( eTaskGetState( xSyncTask1 ) != eBlocked ) + { + xError = pdTRUE; + } + } + else + { + /* Task should have unblocked and returned to the suspended state. */ + if( eTaskGetState( xSyncTask1 ) != eSuspended ) + { + xError = pdTRUE; + } + } + + /* Same checks for the second sync task. */ + if( ( uxBit & ebSELECTIVE_BITS_2 ) == 0 ) + { + /* Task should not have unblocked. */ + if( eTaskGetState( xSyncTask2 ) != eBlocked ) + { + xError = pdTRUE; + } + } + else + { + /* Task should have unblocked and returned to the suspended state. */ + if( eTaskGetState( xSyncTask2 ) != eSuspended ) + { + xError = pdTRUE; + } + } + } + + /* Ensure both tasks are blocked on the event group again, then delete the + event group so the other tasks leave this portion of the test. */ + vTaskResume( xSyncTask1 ); + vTaskResume( xSyncTask2 ); + + /* Deleting the event group is the signal that the two other tasks should + leave the prvSelectiveBitsTestSlaveFunction() function and continue to the main + part of their functionality. */ + vEventGroupDelete( xEventGroup ); + + return xError; +} +/*-----------------------------------------------------------*/ + +void vPeriodicEventGroupsProcessing( void ) +{ +static BaseType_t xCallCount = 0, xISRTestError = pdFALSE; +const BaseType_t xSetBitCount = 100, xGetBitsCount = 200, xClearBitsCount = 300; +const EventBits_t uxBitsToSet = 0x12U; +EventBits_t uxReturned; +BaseType_t xMessagePosted; + + /* Called periodically from the tick hook to exercise the "FromISR" + functions. */ + + xCallCount++; + + if( xCallCount == xSetBitCount ) + { + /* All the event bits should start clear. */ + uxReturned = xEventGroupGetBitsFromISR( xISREventGroup ); + if( uxReturned != 0x00 ) + { + xISRTestError = pdTRUE; + } + else + { + /* Set the bits. This is called from the tick hook so it is not + necessary to use the last parameter to ensure a context switch + occurs immediately. */ + xMessagePosted = xEventGroupSetBitsFromISR( xISREventGroup, uxBitsToSet, NULL ); + if( xMessagePosted != pdPASS ) + { + xISRTestError = pdTRUE; + } + } + } + else if( xCallCount == xGetBitsCount ) + { + /* Check the bits were set as expected. */ + uxReturned = xEventGroupGetBitsFromISR( xISREventGroup ); + if( uxReturned != uxBitsToSet ) + { + xISRTestError = pdTRUE; + } + } + else if( xCallCount == xClearBitsCount ) + { + /* Clear the bits again. */ + uxReturned = xEventGroupClearBitsFromISR( xISREventGroup, uxBitsToSet ); + + /* Check the message was posted. */ + if( uxReturned != pdPASS ) + { + xISRTestError = pdTRUE; + } + + /* Go back to the start. */ + xCallCount = 0; + + /* If no errors have been detected then increment the count of test + cycles. */ + if( xISRTestError == pdFALSE ) + { + ulISRCycles++; + } + } + else + { + /* Nothing else to do. */ + } +} + +/*-----------------------------------------------------------*/ +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreEventGroupTasksStillRunning( void ) +{ +static uint32_t ulPreviousWaitBitCycles = 0, ulPreviousSetBitCycles = 0, ulPreviousISRCycles = 0; +BaseType_t xStatus = pdPASS; + + /* Check the tasks are still cycling without finding any errors. */ + if( ulPreviousSetBitCycles == ulTestMasterCycles ) + { + xStatus = pdFAIL; + } + ulPreviousSetBitCycles = ulTestMasterCycles; + + if( ulPreviousWaitBitCycles == ulTestSlaveCycles ) + { + xStatus = pdFAIL; + } + ulPreviousWaitBitCycles = ulTestSlaveCycles; + + if( ulPreviousISRCycles == ulISRCycles ) + { + xStatus = pdFAIL; + } + ulPreviousISRCycles = ulISRCycles; + + return xStatus; +} + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/GenQTest.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/GenQTest.c new file mode 100644 index 0000000..3da052a --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/GenQTest.c @@ -0,0 +1,857 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +/* + * Tests the extra queue functionality introduced in FreeRTOS.org V4.5.0 - + * including xQueueSendToFront(), xQueueSendToBack(), xQueuePeek() and + * mutex behaviour. + * + * See the comments above the prvSendFrontAndBackTest() and + * prvLowPriorityMutexTask() prototypes below for more information. + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +/* Demo program include files. */ +#include "GenQTest.h" + +#define genqQUEUE_LENGTH ( 5 ) +#define genqNO_BLOCK ( 0 ) + +#define genqMUTEX_LOW_PRIORITY ( tskIDLE_PRIORITY ) +#define genqMUTEX_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define genqMUTEX_MEDIUM_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define genqMUTEX_HIGH_PRIORITY ( tskIDLE_PRIORITY + 3 ) + +#define genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ( 100 ) +/*-----------------------------------------------------------*/ + +/* + * Tests the behaviour of the xQueueSendToFront() and xQueueSendToBack() + * macros by using both to fill a queue, then reading from the queue to + * check the resultant queue order is as expected. Queue data is also + * peeked. + */ +static void prvSendFrontAndBackTest( void *pvParameters ); + +/* + * The following three tasks are used to demonstrate the mutex behaviour. + * Each task is given a different priority to demonstrate the priority + * inheritance mechanism. + * + * The low priority task obtains a mutex. After this a high priority task + * attempts to obtain the same mutex, causing its priority to be inherited + * by the low priority task. The task with the inherited high priority then + * resumes a medium priority task to ensure it is not blocked by the medium + * priority task while it holds the inherited high priority. Once the mutex + * is returned the task with the inherited priority returns to its original + * low priority, and is therefore immediately preempted by first the high + * priority task and then the medium prioroity task before it can continue. + */ +static void prvLowPriorityMutexTask( void *pvParameters ); +static void prvMediumPriorityMutexTask( void *pvParameters ); +static void prvHighPriorityMutexTask( void *pvParameters ); + +/* + * Exercises the priority inheritance when a task takes two mutexes, returning + * them in a different order to which they were taken. + */ +static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex ); + +/* + * Exercises the priority inheritance when a task takes two mutexes, returning + * them in the same order in which they were taken. + */ +static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex ); + +/* + * Task that receives an a mutex that is given from an interrupt - although + * generally mutexes should not be used given in interrupts (and definitely + * never taken in an interrupt) there are some circumstances when it may be + * desirable. NOTE: This function is not declared static to prevent compiler + * warnings being generated in demos where the function is declared but not + * used. + */ +void vInterruptMutexTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdTRUE should any unexpected behaviour be +detected in any of the tasks. */ +static volatile BaseType_t xErrorDetected = pdFALSE; + +/* Counters that are incremented on each cycle of a test. This is used to +detect a stalled task - a test that is no longer running. */ +static volatile uint32_t ulLoopCounter = 0; +static volatile uint32_t ulLoopCounter2 = 0; + +/* The variable that is guarded by the mutex in the mutex demo tasks. */ +static volatile uint32_t ulGuardedVariable = 0; + +/* Handles used in the mutext test to suspend and resume the high and medium +priority mutex test tasks. */ +static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask; + +/* A mutex which is given from an interrupt - although generally mutexes should +not be used given in interrupts (and definitely never taken in an interrupt) +there are some circumstances when it may be desirable. */ +static SemaphoreHandle_t xISRMutex = NULL; + +/*-----------------------------------------------------------*/ + +void vStartGenericQueueTasks( UBaseType_t uxPriority ) +{ +QueueHandle_t xQueue; +SemaphoreHandle_t xMutex; + + xISRMutex = xSemaphoreCreateMutex(); + configASSERT( xISRMutex ); + + /* Create the queue that we are going to use for the + prvSendFrontAndBackTest demo. */ + xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( uint32_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xQueue, "Gen_Queue_Test" ); + + /* Create the demo task and pass it the queue just created. We are + passing the queue handle by value so it does not matter that it is + declared on the stack here. */ + xTaskCreate( prvSendFrontAndBackTest, "GenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL ); + + /* Create the mutex used by the prvMutexTest task. */ + xMutex = xSemaphoreCreateMutex(); + + /* vQueueAddToRegistry() adds the mutex to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate mutexes and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Gen_Queue_Mutex" ); + + /* Create the mutex demo tasks and pass it the mutex just created. We are + passing the mutex handle by value so it does not matter that it is declared + on the stack here. */ + xTaskCreate( prvLowPriorityMutexTask, "MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL ); + xTaskCreate( prvMediumPriorityMutexTask, "MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask ); + xTaskCreate( prvHighPriorityMutexTask, "MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask ); + + /* Only when the windows simulator is being used - create the task that + receives a mutex from an interrupt. */ + #ifdef _WINDOWS_ + { + xTaskCreate( vInterruptMutexTask, "IntMu", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, NULL ); + } + #endif /* __WINDOWS__ */ +} +/*-----------------------------------------------------------*/ + +static void prvSendFrontAndBackTest( void *pvParameters ) +{ +uint32_t ulData, ulData2; +QueueHandle_t xQueue; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Queue SendToFront/SendToBack/Peek test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + xQueue = ( QueueHandle_t ) pvParameters; + + for( ;; ) + { + /* The queue is empty, so sending an item to the back of the queue + should have the same efect as sending it to the front of the queue. + + First send to the front and check everything is as expected. */ + xQueueSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK ); + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* The data we sent to the queue should equal the data we just received + from the queue. */ + if( ulLoopCounter != ulData ) + { + xErrorDetected = pdTRUE; + } + + /* Then do the same, sending the data to the back, checking everything + is as expected. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + xQueueSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK ); + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* The data we sent to the queue should equal the data we just received + from the queue. */ + if( ulLoopCounter != ulData ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + + /* Place 2, 3, 4 into the queue, adding items to the back of the queue. */ + for( ulData = 2; ulData < 5; ulData++ ) + { + xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + } + + /* Now the order in the queue should be 2, 3, 4, with 2 being the first + thing to be read out. Now add 1 then 0 to the front of the queue. */ + if( uxQueueMessagesWaiting( xQueue ) != 3 ) + { + xErrorDetected = pdTRUE; + } + ulData = 1; + xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + ulData = 0; + xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + + /* Now the queue should be full, and when we read the data out we + should receive 0, 1, 2, 3, 4. */ + if( uxQueueMessagesWaiting( xQueue ) != 5 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the data we read out is in the expected order. */ + for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ ) + { + /* Try peeking the data first. */ + if( xQueuePeek( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + + + /* Now try receiving the data for real. The value should be the + same. Clobber the value first so we know we really received it. */ + ulData2 = ~ulData2; + if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + } + + /* The queue should now be empty again. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + /* Our queue is empty once more, add 10, 11 to the back. */ + ulData = 10; + if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + ulData = 11; + if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 2 ) + { + xErrorDetected = pdTRUE; + } + + /* Now we should have 10, 11 in the queue. Add 7, 8, 9 to the + front. */ + for( ulData = 9; ulData >= 7; ulData-- ) + { + if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + } + + /* Now check that the queue is full, and that receiving data provides + the expected sequence of 7, 8, 9, 10, 11. */ + if( uxQueueMessagesWaiting( xQueue ) != 5 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the data we read out is in the expected order. */ + for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ ) + { + if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + } + + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex ) +{ + /* Take the mutex. It should be available now. */ + if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* Set the guarded variable to a known start value. */ + ulGuardedVariable = 0; + + /* This task's priority should be as per that assigned when the task was + created. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the high priority task. This will attempt to take the + mutex, and block when it finds it cannot obtain it. */ + vTaskResume( xHighPriorityMutexTask ); + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Ensure the task is reporting its priority as blocked and not + suspended (as it would have done in versions up to V7.5.3). */ + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* The priority of the high priority task should now have been inherited + as by now it will have attempted to get the mutex. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Attempt to set the priority of this task to the test priority - + between the idle priority and the medium/high test priorities, but the + actual priority should remain at the high priority. */ + vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY ); + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the medium priority task. This should not run as the + inherited priority of this task is above that of the medium priority + task. */ + vTaskResume( xMediumPriorityMutexTask ); + + /* If the medium priority task did run then it will have incremented the + guarded variable. */ + if( ulGuardedVariable != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* Take the local mutex too, so two mutexes are now held. */ + if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* When the semaphore is given back the priority of this task should not + yet be disinherited because the local mutex is still held. This is a + simplification to allow FreeRTOS to be integrated with middleware that + attempts to hold multiple mutexes without bloating the code with complex + algorithms. It is possible that the high priority mutex task will + execute as it shares a priority with this task. */ + if( xSemaphoreGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* The guarded variable is only incremented by the medium priority task, + which still should not have executed as this task should remain at the + higher priority, ensure this is the case. */ + if( ulGuardedVariable != 0 ) + { + xErrorDetected = pdTRUE; + } + + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now also give back the local mutex, taking the held count back to 0. + This time the priority of this task should be disinherited back to the + priority to which it was set while the mutex was held. This means + the medium priority task should execute and increment the guarded + variable. When this task next runs both the high and medium priority + tasks will have been suspended again. */ + if( xSemaphoreGive( xLocalMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the guarded variable did indeed increment... */ + if( ulGuardedVariable != 1 ) + { + xErrorDetected = pdTRUE; + } + + /* ... and that the priority of this task has been disinherited to + genqMUTEX_TEST_PRIORITY. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Set the priority of this task back to its original value, ready for + the next loop around this test. */ + vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY ); +} +/*-----------------------------------------------------------*/ + +static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex ) +{ + /* Take the mutex. It should be available now. */ + if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* Set the guarded variable to a known start value. */ + ulGuardedVariable = 0; + + /* This task's priority should be as per that assigned when the task was + created. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the high priority task. This will attempt to take the + mutex, and block when it finds it cannot obtain it. */ + vTaskResume( xHighPriorityMutexTask ); + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Ensure the task is reporting its priority as blocked and not + suspended (as it would have done in versions up to V7.5.3). */ + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* The priority of the high priority task should now have been inherited + as by now it will have attempted to get the mutex. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the medium priority task. This should not run as the + inherited priority of this task is above that of the medium priority + task. */ + vTaskResume( xMediumPriorityMutexTask ); + + /* If the medium priority task did run then it will have incremented the + guarded variable. */ + if( ulGuardedVariable != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* Take the local mutex too, so two mutexes are now held. */ + if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* When the local semaphore is given back the priority of this task should + not yet be disinherited because the shared mutex is still held. This is a + simplification to allow FreeRTOS to be integrated with middleware that + attempts to hold multiple mutexes without bloating the code with complex + algorithms. It is possible that the high priority mutex task will + execute as it shares a priority with this task. */ + if( xSemaphoreGive( xLocalMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* The guarded variable is only incremented by the medium priority task, + which still should not have executed as this task should remain at the + higher priority, ensure this is the case. */ + if( ulGuardedVariable != 0 ) + { + xErrorDetected = pdTRUE; + } + + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now also give back the shared mutex, taking the held count back to 0. + This time the priority of this task should be disinherited back to the + priority at which it was created. This means the medium priority task + should execute and increment the guarded variable. When this task next runs + both the high and medium priority tasks will have been suspended again. */ + if( xSemaphoreGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the guarded variable did indeed increment... */ + if( ulGuardedVariable != 1 ) + { + xErrorDetected = pdTRUE; + } + + /* ... and that the priority of this task has been disinherited to + genqMUTEX_LOW_PRIORITY. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY ) + { + xErrorDetected = pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +static void prvLowPriorityMutexTask( void *pvParameters ) +{ +SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Mutex with priority inheritance test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + /* The local mutex is used to check the 'mutexs held' count. */ + xLocalMutex = xSemaphoreCreateMutex(); + configASSERT( xLocalMutex ); + + for( ;; ) + { + /* The first tests exercise the priority inheritance when two mutexes + are taken then returned in a different order to which they were + taken. */ + prvTakeTwoMutexesReturnInDifferentOrder( xMutex, xLocalMutex ); + + /* Just to show this task is still running. */ + ulLoopCounter2++; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* The second tests exercise the priority inheritance when two mutexes + are taken then returned in the same order in which they were taken. */ + prvTakeTwoMutexesReturnInSameOrder( xMutex, xLocalMutex ); + + /* Just to show this task is still running. */ + ulLoopCounter2++; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +static void prvMediumPriorityMutexTask( void *pvParameters ) +{ + ( void ) pvParameters; + + for( ;; ) + { + /* The medium priority task starts by suspending itself. The low + priority task will unsuspend this task when required. */ + vTaskSuspend( NULL ); + + /* When this task unsuspends all it does is increment the guarded + variable, this is so the low priority task knows that it has + executed. */ + ulGuardedVariable++; + } +} +/*-----------------------------------------------------------*/ + +static void prvHighPriorityMutexTask( void *pvParameters ) +{ +SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters; + + for( ;; ) + { + /* The high priority task starts by suspending itself. The low + priority task will unsuspend this task when required. */ + vTaskSuspend( NULL ); + + /* When this task unsuspends all it does is attempt to obtain + the mutex. It should find the mutex is not available so a + block time is specified. */ + if( xSemaphoreTake( xMutex, portMAX_DELAY ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* When the mutex is eventually obtained it is just given back before + returning to suspend ready for the next cycle. */ + if( xSemaphoreGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + } +} +/*-----------------------------------------------------------*/ + +/* NOTE: This function is not declared static to prevent compiler warnings in +demos where the function is declared but not used. */ +void vInterruptMutexTask( void *pvParameters ) +{ +const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ); +volatile uint32_t ulLoops = 0; + + /* Just to avoid compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Has to wait longer than the time between gives to make sure it + should definitely have received the mutex. */ + if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + else + { + ulLoops++; + } + } +} +/*-----------------------------------------------------------*/ + +void vMutexISRInteractionTest( void ) +{ +static TickType_t xLastGiveTime = 0; +TickType_t xTimeNow; + + xTimeNow = xTaskGetTickCountFromISR(); + if( ( xTimeNow - xLastGiveTime ) >= pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ) ) + { + configASSERT( xISRMutex ); + xSemaphoreGiveFromISR( xISRMutex, NULL ); + xLastGiveTime = xTimeNow; + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreGenericQueueTasksStillRunning( void ) +{ +static uint32_t ulLastLoopCounter = 0, ulLastLoopCounter2 = 0; + + /* If the demo task is still running then we expect the loop counters to + have incremented since this function was last called. */ + if( ulLastLoopCounter == ulLoopCounter ) + { + xErrorDetected = pdTRUE; + } + + if( ulLastLoopCounter2 == ulLoopCounter2 ) + { + xErrorDetected = pdTRUE; + } + + ulLastLoopCounter = ulLoopCounter; + ulLastLoopCounter2 = ulLoopCounter2; + + /* Errors detected in the task itself will have latched xErrorDetected + to true. */ + + return ( BaseType_t ) !xErrorDetected; +} + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/IntQueue.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/IntQueue.c new file mode 100644 index 0000000..fcb7157 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/IntQueue.c @@ -0,0 +1,760 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * This file defines one of the more complex set of demo/test tasks. They are + * designed to stress test the queue implementation though pseudo simultaneous + * multiple reads and multiple writes from both tasks of varying priority and + * interrupts. The interrupts are prioritised such to ensure that nesting + * occurs (for those ports that support it). + * + * The test ensures that, while being accessed from three tasks and two + * interrupts, all the data sent to the queues is also received from + * the same queue, and that no duplicate items are either sent or received. + * The tests also ensure that a low priority task is never able to successfully + * read from or write to a queue when a task of higher priority is attempting + * the same operation. + */ + +/* Standard includes. */ +#include + +/* SafeRTOS includes. */ +#include "FreeRTOS.h" +#include "queue.h" +#include "task.h" + +/* Demo app includes. */ +#include "IntQueue.h" +#include "IntQueueTimer.h" + +#if( INCLUDE_eTaskGetState != 1 ) + #error INCLUDE_eTaskGetState must be set to 1 in FreeRTOSConfig.h to use this demo file. +#endif + +/* Priorities used by test tasks. */ +#ifndef intqHIGHER_PRIORITY + #define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 2 ) +#endif +#define intqLOWER_PRIORITY ( tskIDLE_PRIORITY ) + +/* The number of values to send/receive before checking that all values were +processed as expected. */ +#define intqNUM_VALUES_TO_LOG ( 200 ) +#define intqSHORT_DELAY ( 140 ) + +/* The value by which the value being sent to or received from a queue should +increment past intqNUM_VALUES_TO_LOG before we check that all values have been +sent/received correctly. This is done to ensure that all tasks and interrupts +accessing the queue have completed their accesses with the +intqNUM_VALUES_TO_LOG range. */ +#define intqVALUE_OVERRUN ( 50 ) + +/* The delay used by the polling task. A short delay is used for code +coverage. */ +#define intqONE_TICK_DELAY ( 1 ) + +/* Each task and interrupt is given a unique identifier. This value is used to +identify which task sent or received each value. The identifier is also used +to distinguish between two tasks that are running the same task function. */ +#define intqHIGH_PRIORITY_TASK1 ( ( UBaseType_t ) 1 ) +#define intqHIGH_PRIORITY_TASK2 ( ( UBaseType_t ) 2 ) +#define intqLOW_PRIORITY_TASK ( ( UBaseType_t ) 3 ) +#define intqFIRST_INTERRUPT ( ( UBaseType_t ) 4 ) +#define intqSECOND_INTERRUPT ( ( UBaseType_t ) 5 ) +#define intqQUEUE_LENGTH ( ( UBaseType_t ) 10 ) + +/* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received +from each queue by each task, otherwise an error is detected. */ +#define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 ) + +/* Send the next value to the queue that is normally empty. This is called +from within the interrupts. */ +#define timerNORMALLY_EMPTY_TX() \ + if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \ + { \ + UBaseType_t uxSavedInterruptStatus; \ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \ + { \ + uxValueForNormallyEmptyQueue++; \ + xQueueSendFromISR( xNormallyEmptyQueue, ( void * ) &uxValueForNormallyEmptyQueue, &xHigherPriorityTaskWoken ); \ + } \ + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ + } \ + +/* Send the next value to the queue that is normally full. This is called +from within the interrupts. */ +#define timerNORMALLY_FULL_TX() \ + if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \ + { \ + UBaseType_t uxSavedInterruptStatus; \ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \ + { \ + uxValueForNormallyFullQueue++; \ + xQueueSendFromISR( xNormallyFullQueue, ( void * ) &uxValueForNormallyFullQueue, &xHigherPriorityTaskWoken ); \ + } \ + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ + } \ + +/* Receive a value from the normally empty queue. This is called from within +an interrupt. */ +#define timerNORMALLY_EMPTY_RX() \ + if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \ + { \ + prvQueueAccessLogError( __LINE__ ); \ + } \ + else \ + { \ + prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT ); \ + } + +/* Receive a value from the normally full queue. This is called from within +an interrupt. */ +#define timerNORMALLY_FULL_RX() \ + if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \ + { \ + prvRecordValue_NormallyFull( uxRxedValue, intqSECOND_INTERRUPT ); \ + } \ + + +/*-----------------------------------------------------------*/ + +/* The two queues used by the test. */ +static QueueHandle_t xNormallyEmptyQueue, xNormallyFullQueue; + +/* Variables used to detect a stall in one of the tasks. */ +static UBaseType_t uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0; + +/* Any unexpected behaviour sets xErrorStatus to fail and log the line that +caused the error in xErrorLine. */ +static BaseType_t xErrorStatus = pdPASS; +static volatile UBaseType_t xErrorLine = ( UBaseType_t ) 0; + +/* Used for sequencing between tasks. */ +static BaseType_t xWasSuspended = pdFALSE; + +/* The values that are sent to the queues. An incremented value is sent each +time to each queue. */ +volatile UBaseType_t uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0; + +/* A handle to some of the tasks is required so they can be suspended/resumed. */ +TaskHandle_t xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2; + +/* When a value is received in a queue the value is ticked off in the array +the array position of the value is set to a the identifier of the task or +interrupt that accessed the queue. This way missing or duplicate values can be +detected. */ +static uint8_t ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 }; +static uint8_t ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 }; + +/* The test tasks themselves. */ +static void prvLowerPriorityNormallyEmptyTask( void *pvParameters ); +static void prvLowerPriorityNormallyFullTask( void *pvParameters ); +static void prvHigherPriorityNormallyEmptyTask( void *pvParameters ); +static void prv1stHigherPriorityNormallyFullTask( void *pvParameters ); +static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters ); + +/* Used to mark the positions within the ucNormallyEmptyReceivedValues and +ucNormallyFullReceivedValues arrays, while checking for duplicates. */ +static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource ); +static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource ); + +/* Logs the line on which an error occurred. */ +static void prvQueueAccessLogError( UBaseType_t uxLine ); + +/*-----------------------------------------------------------*/ + +void vStartInterruptQueueTasks( void ) +{ + /* Start the test tasks. */ + xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H1QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask1 ); + xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H2QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask2 ); + xTaskCreate( prvLowerPriorityNormallyEmptyTask, "L1QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL ); + xTaskCreate( prv1stHigherPriorityNormallyFullTask, "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask1 ); + xTaskCreate( prv2ndHigherPriorityNormallyFullTask, "H2QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask2 ); + xTaskCreate( prvLowerPriorityNormallyFullTask, "L2QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL ); + + /* Create the queues that are accessed by multiple tasks and multiple + interrupts. */ + xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) ); + xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xNormallyFullQueue, "NormallyFull" ); + vQueueAddToRegistry( xNormallyEmptyQueue, "NormallyEmpty" ); +} +/*-----------------------------------------------------------*/ + +static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource ) +{ + if( uxValue < intqNUM_VALUES_TO_LOG ) + { + /* We don't expect to receive the same value twice, so if the value + has already been marked as received an error has occurred. */ + if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 ) + { + prvQueueAccessLogError( __LINE__ ); + } + + /* Log that this value has been received. */ + ucNormallyFullReceivedValues[ uxValue ] = ( uint8_t ) uxSource; + } +} +/*-----------------------------------------------------------*/ + +static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource ) +{ + if( uxValue < intqNUM_VALUES_TO_LOG ) + { + /* We don't expect to receive the same value twice, so if the value + has already been marked as received an error has occurred. */ + if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 ) + { + prvQueueAccessLogError( __LINE__ ); + } + + /* Log that this value has been received. */ + ucNormallyEmptyReceivedValues[ uxValue ] = ( uint8_t ) uxSource; + } +} +/*-----------------------------------------------------------*/ + +static void prvQueueAccessLogError( UBaseType_t uxLine ) +{ + /* Latch the line number that caused the error. */ + xErrorLine = uxLine; + xErrorStatus = pdFAIL; +} +/*-----------------------------------------------------------*/ + +static void prvHigherPriorityNormallyEmptyTask( void *pvParameters ) +{ +UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErrorCount2 = 0; + + /* The timer should not be started until after the scheduler has started. + More than one task is running this code so we check the parameter value + to determine which task should start the timer. */ + if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 ) + { + vInitialiseTimerForIntQueueTest(); + } + + for( ;; ) + { + /* Block waiting to receive a value from the normally empty queue. + Interrupts will write to the queue so we should receive a value. */ + if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS ) + { + prvQueueAccessLogError( __LINE__ ); + } + else + { + /* Note which value was received so we can check all expected + values are received and no values are duplicated. */ + prvRecordValue_NormallyEmpty( uxRxed, ( UBaseType_t ) pvParameters ); + } + + /* Ensure the other task running this code gets a chance to execute. */ + taskYIELD(); + + if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 ) + { + /* Have we received all the expected values? */ + if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) ) + { + vTaskSuspend( xHighPriorityNormallyEmptyTask2 ); + + uxTask1 = 0; + uxTask2 = 0; + uxInterrupts = 0; + + /* Loop through the array, checking that both tasks have + placed values into the array, and that no values are missing. + Start at 1 as we expect position 0 to be unused. */ + for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ ) + { + if( ucNormallyEmptyReceivedValues[ ux ] == 0 ) + { + /* A value is missing. */ + prvQueueAccessLogError( __LINE__ ); + } + else + { + if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK1 ) + { + /* Value was placed into the array by task 1. */ + uxTask1++; + } + else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK2 ) + { + /* Value was placed into the array by task 2. */ + uxTask2++; + } + else if( ucNormallyEmptyReceivedValues[ ux ] == intqSECOND_INTERRUPT ) + { + uxInterrupts++; + } + } + } + + if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT ) + { + /* Only task 2 seemed to log any values. */ + uxErrorCount1++; + if( uxErrorCount1 > 2 ) + { + prvQueueAccessLogError( __LINE__ ); + } + } + else + { + uxErrorCount1 = 0; + } + + if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT ) + { + /* Only task 1 seemed to log any values. */ + uxErrorCount2++; + if( uxErrorCount2 > 2 ) + { + prvQueueAccessLogError( __LINE__ ); + } + } + else + { + uxErrorCount2 = 0; + } + + if( uxInterrupts == 0 ) + { + prvQueueAccessLogError( __LINE__ ); + } + + /* Clear the array again, ready to start a new cycle. */ + memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) ); + + uxHighPriorityLoops1++; + uxValueForNormallyEmptyQueue = 0; + + /* Suspend ourselves, allowing the lower priority task to + actually receive something from the queue. Until now it + will have been prevented from doing so by the higher + priority tasks. The lower priority task will resume us + if it receives something. We will then resume the other + higher priority task. */ + vTaskSuspend( NULL ); + vTaskResume( xHighPriorityNormallyEmptyTask2 ); + } + } + } +} +/*-----------------------------------------------------------*/ + +static void prvLowerPriorityNormallyEmptyTask( void *pvParameters ) +{ +UBaseType_t uxValue, uxRxed; + + /* The parameters are not being used so avoid compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) != errQUEUE_EMPTY ) + { + /* A value should only be obtained when the high priority task is + suspended. */ + if( eTaskGetState( xHighPriorityNormallyEmptyTask1 ) != eSuspended ) + { + prvQueueAccessLogError( __LINE__ ); + } + + prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIORITY_TASK ); + + /* Wake the higher priority task again. */ + vTaskResume( xHighPriorityNormallyEmptyTask1 ); + uxLowPriorityLoops1++; + } + else + { + /* Raise our priority while we send so we can preempt the higher + priority task, and ensure we get the Tx value into the queue. */ + vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 ); + + portENTER_CRITICAL(); + { + uxValueForNormallyEmptyQueue++; + uxValue = uxValueForNormallyEmptyQueue; + } + portEXIT_CRITICAL(); + + if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS ) + { + prvQueueAccessLogError( __LINE__ ); + } + + vTaskPrioritySet( NULL, intqLOWER_PRIORITY ); + } + } +} +/*-----------------------------------------------------------*/ + +static void prv1stHigherPriorityNormallyFullTask( void *pvParameters ) +{ +UBaseType_t uxValueToTx, ux, uxInterrupts; + + /* The parameters are not being used so avoid compiler warnings. */ + ( void ) pvParameters; + + /* Make sure the queue starts full or near full. >> 1 as there are two + high priority tasks. */ + for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ ) + { + portENTER_CRITICAL(); + { + uxValueForNormallyFullQueue++; + uxValueToTx = uxValueForNormallyFullQueue; + } + portEXIT_CRITICAL(); + + xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ); + } + + for( ;; ) + { + portENTER_CRITICAL(); + { + uxValueForNormallyFullQueue++; + uxValueToTx = uxValueForNormallyFullQueue; + } + portEXIT_CRITICAL(); + + if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS ) + { + /* intqHIGH_PRIORITY_TASK2 is never suspended so we would not + expect it to ever time out. */ + prvQueueAccessLogError( __LINE__ ); + } + + /* Allow the other task running this code to run. */ + taskYIELD(); + + /* Have all the expected values been sent to the queue? */ + if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) ) + { + /* Make sure the other high priority task completes its send of + any values below intqNUM_VALUE_TO_LOG. */ + vTaskDelay( intqSHORT_DELAY ); + + vTaskSuspend( xHighPriorityNormallyFullTask2 ); + + if( xWasSuspended == pdTRUE ) + { + /* We would have expected the other high priority task to have + set this back to false by now. */ + prvQueueAccessLogError( __LINE__ ); + } + + /* Set the suspended flag so an error is not logged if the other + task recognises a time out when it is unsuspended. */ + xWasSuspended = pdTRUE; + + /* Check interrupts are also sending. */ + uxInterrupts = 0U; + + /* Start at 1 as we expect position 0 to be unused. */ + for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ ) + { + if( ucNormallyFullReceivedValues[ ux ] == 0 ) + { + /* A value was missing. */ + prvQueueAccessLogError( __LINE__ ); + } + else if( ucNormallyFullReceivedValues[ ux ] == intqSECOND_INTERRUPT ) + { + uxInterrupts++; + } + } + + if( uxInterrupts == 0 ) + { + /* No writes from interrupts were found. Are interrupts + actually running? */ + prvQueueAccessLogError( __LINE__ ); + } + + /* Reset the array ready for the next cycle. */ + memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) ); + + uxHighPriorityLoops2++; + uxValueForNormallyFullQueue = 0; + + /* Suspend ourselves, allowing the lower priority task to + actually receive something from the queue. Until now it + will have been prevented from doing so by the higher + priority tasks. The lower priority task will resume us + if it receives something. We will then resume the other + higher priority task. */ + vTaskSuspend( NULL ); + vTaskResume( xHighPriorityNormallyFullTask2 ); + } + } +} +/*-----------------------------------------------------------*/ + +static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters ) +{ +UBaseType_t uxValueToTx, ux; + + /* The parameters are not being used so avoid compiler warnings. */ + ( void ) pvParameters; + + /* Make sure the queue starts full or near full. >> 1 as there are two + high priority tasks. */ + for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ ) + { + portENTER_CRITICAL(); + { + uxValueForNormallyFullQueue++; + uxValueToTx = uxValueForNormallyFullQueue; + } + portEXIT_CRITICAL(); + + xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ); + } + + for( ;; ) + { + portENTER_CRITICAL(); + { + uxValueForNormallyFullQueue++; + uxValueToTx = uxValueForNormallyFullQueue; + } + portEXIT_CRITICAL(); + + if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS ) + { + if( xWasSuspended != pdTRUE ) + { + /* It is ok to time out if the task has been suspended. */ + prvQueueAccessLogError( __LINE__ ); + } + } + + xWasSuspended = pdFALSE; + + taskYIELD(); + } +} +/*-----------------------------------------------------------*/ + +static void prvLowerPriorityNormallyFullTask( void *pvParameters ) +{ +UBaseType_t uxValue, uxTxed = 9999; + + /* The parameters are not being used so avoid compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + if( xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) != errQUEUE_FULL ) + { + /* Should only succeed when the higher priority task is suspended */ + if( eTaskGetState( xHighPriorityNormallyFullTask1 ) != eSuspended ) + { + prvQueueAccessLogError( __LINE__ ); + } + + vTaskResume( xHighPriorityNormallyFullTask1 ); + uxLowPriorityLoops2++; + } + else + { + /* Raise our priority while we receive so we can preempt the higher + priority task, and ensure we get the value from the queue. */ + vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 ); + + if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS ) + { + prvQueueAccessLogError( __LINE__ ); + } + else + { + prvRecordValue_NormallyFull( uxValue, intqLOW_PRIORITY_TASK ); + } + + vTaskPrioritySet( NULL, intqLOWER_PRIORITY ); + } + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xFirstTimerHandler( void ) +{ +BaseType_t xHigherPriorityTaskWoken = pdFALSE; +UBaseType_t uxRxedValue; +static UBaseType_t uxNextOperation = 0; + + /* Called from a timer interrupt. Perform various read and write + accesses on the queues. */ + + uxNextOperation++; + + if( uxNextOperation & ( UBaseType_t ) 0x01 ) + { + timerNORMALLY_EMPTY_TX(); + timerNORMALLY_EMPTY_TX(); + timerNORMALLY_EMPTY_TX(); + } + else + { + timerNORMALLY_FULL_RX(); + timerNORMALLY_FULL_RX(); + timerNORMALLY_FULL_RX(); + } + + return xHigherPriorityTaskWoken; +} +/*-----------------------------------------------------------*/ + +BaseType_t xSecondTimerHandler( void ) +{ +UBaseType_t uxRxedValue; +BaseType_t xHigherPriorityTaskWoken = pdFALSE; +static UBaseType_t uxNextOperation = 0; + + /* Called from a timer interrupt. Perform various read and write + accesses on the queues. */ + + uxNextOperation++; + + if( uxNextOperation & ( UBaseType_t ) 0x01 ) + { + timerNORMALLY_EMPTY_TX(); + timerNORMALLY_EMPTY_TX(); + + timerNORMALLY_EMPTY_RX(); + timerNORMALLY_EMPTY_RX(); + } + else + { + timerNORMALLY_FULL_RX(); + timerNORMALLY_FULL_TX(); + timerNORMALLY_FULL_TX(); + timerNORMALLY_FULL_TX(); + timerNORMALLY_FULL_TX(); + } + + return xHigherPriorityTaskWoken; +} +/*-----------------------------------------------------------*/ + + +BaseType_t xAreIntQueueTasksStillRunning( void ) +{ +static UBaseType_t uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0; + + /* xErrorStatus can be set outside of this function. This function just + checks that all the tasks are still cycling. */ + + if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 ) + { + /* The high priority 1 task has stalled. */ + prvQueueAccessLogError( __LINE__ ); + } + + uxLastHighPriorityLoops1 = uxHighPriorityLoops1; + + if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 ) + { + /* The high priority 2 task has stalled. */ + prvQueueAccessLogError( __LINE__ ); + } + + uxLastHighPriorityLoops2 = uxHighPriorityLoops2; + + if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 ) + { + /* The low priority 1 task has stalled. */ + prvQueueAccessLogError( __LINE__ ); + } + + uxLastLowPriorityLoops1 = uxLowPriorityLoops1; + + if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 ) + { + /* The low priority 2 task has stalled. */ + prvQueueAccessLogError( __LINE__ ); + } + + uxLastLowPriorityLoops2 = uxLowPriorityLoops2; + + return xErrorStatus; +} + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/PollQ.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/PollQ.c new file mode 100644 index 0000000..4782f61 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/PollQ.c @@ -0,0 +1,258 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * This version of PollQ. c is for use on systems that have limited stack + * space and no display facilities. The complete version can be found in + * the Demo/Common/Full directory. + * + * Creates two tasks that communicate over a single queue. One task acts as a + * producer, the other a consumer. + * + * The producer loops for three iteration, posting an incrementing number onto the + * queue each cycle. It then delays for a fixed period before doing exactly the + * same again. + * + * The consumer loops emptying the queue. Each item removed from the queue is + * checked to ensure it contains the expected value. When the queue is empty it + * blocks for a fixed period, then does the same again. + * + * All queue access is performed without blocking. The consumer completely empties + * the queue each time it runs so the producer should never find the queue full. + * + * An error is flagged if the consumer obtains an unexpected value or the producer + * find the queue is full. + */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than uint32_t. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "PollQ.h" + +#define pollqSTACK_SIZE configMINIMAL_STACK_SIZE +#define pollqQUEUE_SIZE ( 10 ) +#define pollqPRODUCER_DELAY ( ( TickType_t ) 200 / portTICK_PERIOD_MS ) +#define pollqCONSUMER_DELAY ( pollqPRODUCER_DELAY - ( TickType_t ) ( 20 / portTICK_PERIOD_MS ) ) +#define pollqNO_DELAY ( ( TickType_t ) 0 ) +#define pollqVALUES_TO_PRODUCE ( ( BaseType_t ) 3 ) +#define pollqINITIAL_VALUE ( ( BaseType_t ) 0 ) + +/* The task that posts the incrementing number onto the queue. */ +static portTASK_FUNCTION_PROTO( vPolledQueueProducer, pvParameters ); + +/* The task that empties the queue. */ +static portTASK_FUNCTION_PROTO( vPolledQueueConsumer, pvParameters ); + +/* Variables that are used to check that the tasks are still running with no +errors. */ +static volatile BaseType_t xPollingConsumerCount = pollqINITIAL_VALUE, xPollingProducerCount = pollqINITIAL_VALUE; + +/*-----------------------------------------------------------*/ + +void vStartPolledQueueTasks( UBaseType_t uxPriority ) +{ +static QueueHandle_t xPolledQueue; + + /* Create the queue used by the producer and consumer. */ + xPolledQueue = xQueueCreate( pollqQUEUE_SIZE, ( UBaseType_t ) sizeof( uint16_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xPolledQueue, "Poll_Test_Queue" ); + + /* Spawn the producer and consumer. */ + xTaskCreate( vPolledQueueConsumer, "QConsNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( TaskHandle_t * ) NULL ); + xTaskCreate( vPolledQueueProducer, "QProdNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( TaskHandle_t * ) NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vPolledQueueProducer, pvParameters ) +{ +uint16_t usValue = ( uint16_t ) 0; +BaseType_t xError = pdFALSE, xLoop; + + for( ;; ) + { + for( xLoop = 0; xLoop < pollqVALUES_TO_PRODUCE; xLoop++ ) + { + /* Send an incrementing number on the queue without blocking. */ + if( xQueueSend( *( ( QueueHandle_t * ) pvParameters ), ( void * ) &usValue, pollqNO_DELAY ) != pdPASS ) + { + /* We should never find the queue full so if we get here there + has been an error. */ + xError = pdTRUE; + } + else + { + if( xError == pdFALSE ) + { + /* If an error has ever been recorded we stop incrementing the + check variable. */ + portENTER_CRITICAL(); + xPollingProducerCount++; + portEXIT_CRITICAL(); + } + + /* Update the value we are going to post next time around. */ + usValue++; + } + } + + /* Wait before we start posting again to ensure the consumer runs and + empties the queue. */ + vTaskDelay( pollqPRODUCER_DELAY ); + } +} /*lint !e818 Function prototype must conform to API. */ +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vPolledQueueConsumer, pvParameters ) +{ +uint16_t usData, usExpectedValue = ( uint16_t ) 0; +BaseType_t xError = pdFALSE; + + for( ;; ) + { + /* Loop until the queue is empty. */ + while( uxQueueMessagesWaiting( *( ( QueueHandle_t * ) pvParameters ) ) ) + { + if( xQueueReceive( *( ( QueueHandle_t * ) pvParameters ), &usData, pollqNO_DELAY ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + /* This is not what we expected to receive so an error has + occurred. */ + xError = pdTRUE; + + /* Catch-up to the value we received so our next expected + value should again be correct. */ + usExpectedValue = usData; + } + else + { + if( xError == pdFALSE ) + { + /* Only increment the check variable if no errors have + occurred. */ + portENTER_CRITICAL(); + xPollingConsumerCount++; + portEXIT_CRITICAL(); + } + } + + /* Next time round we would expect the number to be one higher. */ + usExpectedValue++; + } + } + + /* Now the queue is empty we block, allowing the producer to place more + items in the queue. */ + vTaskDelay( pollqCONSUMER_DELAY ); + } +} /*lint !e818 Function prototype must conform to API. */ +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running with no errors. */ +BaseType_t xArePollingQueuesStillRunning( void ) +{ +BaseType_t xReturn; + + /* Check both the consumer and producer poll count to check they have both + been changed since out last trip round. We do not need a critical section + around the check variables as this is called from a higher priority than + the other tasks that access the same variables. */ + if( ( xPollingConsumerCount == pollqINITIAL_VALUE ) || + ( xPollingProducerCount == pollqINITIAL_VALUE ) + ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + /* Set the check variables back down so we know if they have been + incremented the next time around. */ + xPollingConsumerCount = pollqINITIAL_VALUE; + xPollingProducerCount = pollqINITIAL_VALUE; + + return xReturn; +} diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QPeek.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QPeek.c new file mode 100644 index 0000000..4f4caa9 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QPeek.c @@ -0,0 +1,474 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +/* + * Tests the behaviour when data is peeked from a queue when there are + * multiple tasks blocked on the queue. + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +/* Demo program include files. */ +#include "QPeek.h" + +#define qpeekQUEUE_LENGTH ( 5 ) +#define qpeekNO_BLOCK ( 0 ) +#define qpeekSHORT_DELAY ( 10 ) + +#define qpeekLOW_PRIORITY ( tskIDLE_PRIORITY + 0 ) +#define qpeekMEDIUM_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define qpeekHIGH_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define qpeekHIGHEST_PRIORITY ( tskIDLE_PRIORITY + 3 ) + +/*-----------------------------------------------------------*/ + +/* + * The following three tasks are used to demonstrate the peeking behaviour. + * Each task is given a different priority to demonstrate the order in which + * tasks are woken as data is peeked from a queue. + */ +static void prvLowPriorityPeekTask( void *pvParameters ); +static void prvMediumPriorityPeekTask( void *pvParameters ); +static void prvHighPriorityPeekTask( void *pvParameters ); +static void prvHighestPriorityPeekTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdTRUE should any unexpected behaviour be +detected in any of the tasks. */ +static volatile BaseType_t xErrorDetected = pdFALSE; + +/* Counter that is incremented on each cycle of a test. This is used to +detect a stalled task - a test that is no longer running. */ +static volatile uint32_t ulLoopCounter = 0; + +/* Handles to the test tasks. */ +TaskHandle_t xMediumPriorityTask, xHighPriorityTask, xHighestPriorityTask; +/*-----------------------------------------------------------*/ + +void vStartQueuePeekTasks( void ) +{ +QueueHandle_t xQueue; + + /* Create the queue that we are going to use for the test/demo. */ + xQueue = xQueueCreate( qpeekQUEUE_LENGTH, sizeof( uint32_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xQueue, "QPeek_Test_Queue" ); + + /* Create the demo tasks and pass it the queue just created. We are + passing the queue handle by value so it does not matter that it is declared + on the stack here. */ + xTaskCreate( prvLowPriorityPeekTask, "PeekL", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekLOW_PRIORITY, NULL ); + xTaskCreate( prvMediumPriorityPeekTask, "PeekM", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekMEDIUM_PRIORITY, &xMediumPriorityTask ); + xTaskCreate( prvHighPriorityPeekTask, "PeekH1", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGH_PRIORITY, &xHighPriorityTask ); + xTaskCreate( prvHighestPriorityPeekTask, "PeekH2", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGHEST_PRIORITY, &xHighestPriorityTask ); +} +/*-----------------------------------------------------------*/ + +static void prvHighestPriorityPeekTask( void *pvParameters ) +{ +QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters; +uint32_t ulValue; + + #ifdef USE_STDIO + { + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Queue peek test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + } + #endif + + for( ;; ) + { + /* Try peeking from the queue. The queue should be empty so we will + block, allowing the high priority task to execute. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + /* We expected to have received something by the time we unblock. */ + xErrorDetected = pdTRUE; + } + + /* When we reach here the high and medium priority tasks should still + be blocked on the queue. We unblocked because the low priority task + wrote a value to the queue, which we should have peeked. Peeking the + data (rather than receiving it) will leave the data on the queue, so + the high priority task should then have also been unblocked, but not + yet executed. */ + if( ulValue != 0x11223344 ) + { + /* We did not receive the expected value. */ + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + /* The message should have been left on the queue. */ + xErrorDetected = pdTRUE; + } + + /* Now we are going to actually receive the data, so when the high + priority task runs it will find the queue empty and return to the + blocked state. */ + ulValue = 0; + if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We expected to receive the value. */ + xErrorDetected = pdTRUE; + } + + if( ulValue != 0x11223344 ) + { + /* We did not receive the expected value - which should have been + the same value as was peeked. */ + xErrorDetected = pdTRUE; + } + + /* Now we will block again as the queue is once more empty. The low + priority task can then execute again. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + /* We expected to have received something by the time we unblock. */ + xErrorDetected = pdTRUE; + } + + /* When we get here the low priority task should have again written to the + queue. */ + if( ulValue != 0x01234567 ) + { + /* We did not receive the expected value. */ + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + /* The message should have been left on the queue. */ + xErrorDetected = pdTRUE; + } + + /* We only peeked the data, so suspending ourselves now should enable + the high priority task to also peek the data. The high priority task + will have been unblocked when we peeked the data as we left the data + in the queue. */ + vTaskSuspend( NULL ); + + + + /* This time we are going to do the same as the above test, but the + high priority task is going to receive the data, rather than peek it. + This means that the medium priority task should never peek the value. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulValue != 0xaabbaabb ) + { + xErrorDetected = pdTRUE; + } + + vTaskSuspend( NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvHighPriorityPeekTask( void *pvParameters ) +{ +QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters; +uint32_t ulValue; + + for( ;; ) + { + /* Try peeking from the queue. The queue should be empty so we will + block, allowing the medium priority task to execute. Both the high + and highest priority tasks will then be blocked on the queue. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + /* We expected to have received something by the time we unblock. */ + xErrorDetected = pdTRUE; + } + + /* When we get here the highest priority task should have peeked the data + (unblocking this task) then suspended (allowing this task to also peek + the data). */ + if( ulValue != 0x01234567 ) + { + /* We did not receive the expected value. */ + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + /* The message should have been left on the queue. */ + xErrorDetected = pdTRUE; + } + + /* We only peeked the data, so suspending ourselves now should enable + the medium priority task to also peek the data. The medium priority task + will have been unblocked when we peeked the data as we left the data + in the queue. */ + vTaskSuspend( NULL ); + + + /* This time we are going actually receive the value, so the medium + priority task will never peek the data - we removed it from the queue. */ + if( xQueueReceive( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulValue != 0xaabbaabb ) + { + xErrorDetected = pdTRUE; + } + + vTaskSuspend( NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvMediumPriorityPeekTask( void *pvParameters ) +{ +QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters; +uint32_t ulValue; + + for( ;; ) + { + /* Try peeking from the queue. The queue should be empty so we will + block, allowing the low priority task to execute. The highest, high + and medium priority tasks will then all be blocked on the queue. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + /* We expected to have received something by the time we unblock. */ + xErrorDetected = pdTRUE; + } + + /* When we get here the high priority task should have peeked the data + (unblocking this task) then suspended (allowing this task to also peek + the data). */ + if( ulValue != 0x01234567 ) + { + /* We did not receive the expected value. */ + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + /* The message should have been left on the queue. */ + xErrorDetected = pdTRUE; + } + + /* Just so we know the test is still running. */ + ulLoopCounter++; + + /* Now we can suspend ourselves so the low priority task can execute + again. */ + vTaskSuspend( NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvLowPriorityPeekTask( void *pvParameters ) +{ +QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters; +uint32_t ulValue; + + for( ;; ) + { + /* Write some data to the queue. This should unblock the highest + priority task that is waiting to peek data from the queue. */ + ulValue = 0x11223344; + if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We were expecting the queue to be empty so we should not of + had a problem writing to the queue. */ + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* By the time we get here the data should have been removed from + the queue. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* Write another value to the queue, again waking the highest priority + task that is blocked on the queue. */ + ulValue = 0x01234567; + if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We were expecting the queue to be empty so we should not of + had a problem writing to the queue. */ + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* All the other tasks should now have successfully peeked the data. + The data is still in the queue so we should be able to receive it. */ + ulValue = 0; + if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We expected to receive the data. */ + xErrorDetected = pdTRUE; + } + + if( ulValue != 0x01234567 ) + { + /* We did not receive the expected value. */ + } + + /* Lets just delay a while as this is an intensive test as we don't + want to starve other tests of processing time. */ + vTaskDelay( qpeekSHORT_DELAY ); + + /* Unsuspend the other tasks so we can repeat the test - this time + however not all the other tasks will peek the data as the high + priority task is actually going to remove it from the queue. Send + to front is used just to be different. As the queue is empty it + makes no difference to the result. */ + vTaskResume( xMediumPriorityTask ); + vTaskResume( xHighPriorityTask ); + vTaskResume( xHighestPriorityTask ); + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + + ulValue = 0xaabbaabb; + if( xQueueSendToFront( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We were expecting the queue to be empty so we should not of + had a problem writing to the queue. */ + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* This time we should find that the queue is empty. The high priority + task actually removed the data rather than just peeking it. */ + if( xQueuePeek( xQueue, &ulValue, qpeekNO_BLOCK ) != errQUEUE_EMPTY ) + { + /* We expected to receive the data. */ + xErrorDetected = pdTRUE; + } + + /* Unsuspend the highest and high priority tasks so we can go back + and repeat the whole thing. The medium priority task should not be + suspended as it was not able to peek the data in this last case. */ + vTaskResume( xHighPriorityTask ); + vTaskResume( xHighestPriorityTask ); + + /* Lets just delay a while as this is an intensive test as we don't + want to starve other tests of processing time. */ + vTaskDelay( qpeekSHORT_DELAY ); + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreQueuePeekTasksStillRunning( void ) +{ +static uint32_t ulLastLoopCounter = 0; + + /* If the demo task is still running then we expect the loopcounter to + have incremented since this function was last called. */ + if( ulLastLoopCounter == ulLoopCounter ) + { + xErrorDetected = pdTRUE; + } + + ulLastLoopCounter = ulLoopCounter; + + /* Errors detected in the task itself will have latched xErrorDetected + to true. */ + + return ( BaseType_t ) !xErrorDetected; +} + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueOverwrite.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueOverwrite.c new file mode 100644 index 0000000..15ffb34 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueOverwrite.c @@ -0,0 +1,268 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * Basic task to demonstrate the xQueueOverwrite() function. See the comments + * in the function itself. + */ + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "QueueOverwrite.h" + +/* A block time of 0 just means "don't block". */ +#define qoDONT_BLOCK 0 + +/* Number of times to overwrite the value in the queue. */ +#define qoLOOPS 5 + +/* The task that uses the queue. */ +static void prvQueueOverwriteTask( void *pvParameters ); + +/* Variable that is incremented on each loop of prvQueueOverwriteTask() provided +prvQueueOverwriteTask() has not found any errors. */ +static uint32_t ulLoopCounter = 0; + +/* Set to pdFALSE if an error is discovered by the +vQueueOverwritePeriodicISRDemo() function. */ +static BaseType_t xISRTestStatus = pdPASS; + +/* The queue that is accessed from the ISR. The queue accessed by the task is +created inside the task itself. */ +static QueueHandle_t xISRQueue = NULL; + +/*-----------------------------------------------------------*/ + +void vStartQueueOverwriteTask( UBaseType_t uxPriority ) +{ +const UBaseType_t uxQueueLength = 1; + + /* Create the queue used by the ISR. xQueueOverwriteFromISR() should only + be used on queues that have a length of 1. */ + xISRQueue = xQueueCreate( uxQueueLength, ( UBaseType_t ) sizeof( uint32_t ) ); + + /* Create the test task. The queue used by the test task is created inside + the task itself. */ + xTaskCreate( prvQueueOverwriteTask, "QOver", configMINIMAL_STACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL ); +} +/*-----------------------------------------------------------*/ + +static void prvQueueOverwriteTask( void *pvParameters ) +{ +QueueHandle_t xTaskQueue; +const UBaseType_t uxQueueLength = 1; +uint32_t ulValue, ulStatus = pdPASS, x; + + /* The parameter is not used. */ + ( void ) pvParameters; + + /* Create the queue. xQueueOverwrite() should only be used on queues that + have a length of 1. */ + xTaskQueue = xQueueCreate( uxQueueLength, ( UBaseType_t ) sizeof( uint32_t ) ); + configASSERT( xTaskQueue ); + + for( ;; ) + { + /* The queue is empty. Writing to the queue then reading from the queue + should return the item written. */ + ulValue = 10; + xQueueOverwrite( xTaskQueue, &ulValue ); + + ulValue = 0; + xQueueReceive( xTaskQueue, &ulValue, qoDONT_BLOCK ); + + if( ulValue != 10 ) + { + ulStatus = pdFAIL; + } + + /* Now try writing to the queue several times. Each time the value + in the queue should get overwritten. */ + for( x = 0; x < qoLOOPS; x++ ) + { + /* Write to the queue. */ + xQueueOverwrite( xTaskQueue, &x ); + + /* Check the value in the queue is that written, even though the + queue was not necessarily empty. */ + xQueuePeek( xTaskQueue, &ulValue, qoDONT_BLOCK ); + if( ulValue != x ) + { + ulStatus = pdFAIL; + } + + /* There should always be one item in the queue. */ + if( uxQueueMessagesWaiting( xTaskQueue ) != uxQueueLength ) + { + ulStatus = pdFAIL; + } + } + + /* Empty the queue again. */ + xQueueReceive( xTaskQueue, &ulValue, qoDONT_BLOCK ); + + if( uxQueueMessagesWaiting( xTaskQueue ) != 0 ) + { + ulStatus = pdFAIL; + } + + if( ulStatus != pdFAIL ) + { + /* Increment a counter to show this task is still running without + error. */ + ulLoopCounter++; + } + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xIsQueueOverwriteTaskStillRunning( void ) +{ +BaseType_t xReturn; + + if( xISRTestStatus != pdPASS ) + { + xReturn = pdFAIL; + } + else if( ulLoopCounter > 0 ) + { + xReturn = pdPASS; + } + else + { + /* The task has either stalled of discovered an error. */ + xReturn = pdFAIL; + } + + ulLoopCounter = 0; + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vQueueOverwritePeriodicISRDemo( void ) +{ +static uint32_t ulCallCount = 0; +const uint32_t ulTx1 = 10UL, ulTx2 = 20UL, ulNumberOfSwitchCases = 3UL; +uint32_t ulRx; + + /* This function should be called from an interrupt, such as the tick hook + function vApplicationTickHook(). */ + + configASSERT( xISRQueue ); + + switch( ulCallCount ) + { + case 0: + /* The queue is empty. Write ulTx1 to the queue. In this demo the + last parameter is not used because there are no tasks blocked on + this queue. */ + xQueueOverwriteFromISR( xISRQueue, &ulTx1, NULL ); + + /* Peek the queue to check it holds the expected value. */ + xQueuePeekFromISR( xISRQueue, &ulRx ); + if( ulRx != ulTx1 ) + { + xISRTestStatus = pdFAIL; + } + break; + + case 1: + /* The queue already holds ulTx1. Overwrite the value in the queue + with ulTx2. */ + xQueueOverwriteFromISR( xISRQueue, &ulTx2, NULL ); + break; + + case 2: + /* Read from the queue to empty the queue again. The value read + should be ulTx2. */ + xQueueReceiveFromISR( xISRQueue, &ulRx, NULL ); + + if( ulRx != ulTx2 ) + { + xISRTestStatus = pdFAIL; + } + break; + } + + /* Run the next case in the switch statement above next time this function + is called. */ + ulCallCount++; + + if( ulCallCount >= ulNumberOfSwitchCases ) + { + /* Go back to the start. */ + ulCallCount = 0; + } +} + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueSet.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueSet.c new file mode 100644 index 0000000..bc8f0e7 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueSet.c @@ -0,0 +1,715 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * Tests the use of queue sets. + * + * A receive task creates a number of queues and adds them to a queue set before + * blocking on the queue set receive. A transmit task and (optionally) an + * interrupt repeatedly unblocks the receive task by sending messages to the + * queues in a pseudo random order. The receive task removes the messages from + * the queues and flags an error if the received message does not match that + * expected. The task sends values in the range 0 to + * queuesetINITIAL_ISR_TX_VALUE, and the ISR sends value in the range + * queuesetINITIAL_ISR_TX_VALUE to ULONG_MAX. + */ + + +/* Standard includes. */ +#include +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo includes. */ +#include "QueueSet.h" + +/* The number of queues that are created and added to the queue set. */ +#define queuesetNUM_QUEUES_IN_SET 3 + +/* The length of each created queue. */ +#define queuesetQUEUE_LENGTH 3 + +/* Block times used in this demo. A block time or 0 means "don't block". */ +#define queuesetSHORT_DELAY 200 +#define queuesetDONT_BLOCK 0 + +/* Messages are sent in incrementing order from both a task and an interrupt. +The task sends values in the range 0 to 0xfffe, and the interrupt sends values +in the range of 0xffff to ULONG_MAX. */ +#define queuesetINITIAL_ISR_TX_VALUE 0xffffUL + +/* The priorities used in this demo. */ +#define queuesetLOW_PRIORITY ( tskIDLE_PRIORITY ) +#define queuesetMEDIUM_PRIORITY ( queuesetLOW_PRIORITY + 1 ) + +/* For test purposes the priority of the sending task is changed after every +queuesetPRIORITY_CHANGE_LOOPS number of values are sent to a queue. */ +#define queuesetPRIORITY_CHANGE_LOOPS ( ( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH ) * 2 ) + +/* The ISR sends to the queue every queuesetISR_TX_PERIOD ticks. */ +#define queuesetISR_TX_PERIOD ( 100UL ) + +/* A delay inserted when the Tx task changes its priority to be above the idle +task priority to ensure the idle priority tasks get some CPU time before the +next iteration of the queue set Tx task. */ +#define queuesetTX_LOOP_DELAY ( 200 / portTICK_PERIOD_MS ) + +/* The allowable maximum deviation between a received value and the expected +received value. A deviation will occur when data is received from a queue +inside an ISR in between a task receiving from a queue and the task checking +the received value. */ +#define queuesetALLOWABLE_RX_DEVIATION 3 + +/* Ignore values that are at the boundaries of allowable values to make the +testing of limits easier (don't have to deal with wrapping values). */ +#define queuesetIGNORED_BOUNDARY ( queuesetALLOWABLE_RX_DEVIATION * 2 ) + +typedef enum +{ + eEqualPriority = 0, /* Tx and Rx tasks have the same priority. */ + eTxHigherPriority, /* The priority of the Tx task is above that of the Rx task. */ + eTxLowerPriority /* The priority of the Tx task is below that of the Rx task. */ +} eRelativePriorities; + +/* + * The task that periodically sends to the queue set. + */ +static void prvQueueSetSendingTask( void *pvParameters ); + +/* + * The task that reads from the queue set. + */ +static void prvQueueSetReceivingTask( void *pvParameters ); + +/* + * Check the value received from a queue is the expected value. Some values + * originate from the send task, some values originate from the ISR, with the + * range of the value being used to distinguish between the two message + * sources. + */ +static void prvCheckReceivedValue( uint32_t ulReceived ); + +/* + * For purposes of test coverage, functions that read from and write to a + * queue set from an ISR respectively. + */ +static void prvReceiveFromQueueInSetFromISR( void ); +static void prvSendToQueueInSetFromISR( void ); + +/* + * Create the queues and add them to a queue set before resuming the Tx + * task. + */ +static void prvSetupTest( void ); + +/* + * Checks a value received from a queue falls within the range of expected + * values. + */ +static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived, uint32_t ulExpectedReceived ); + +/* + * Increase test coverage by occasionally change the priorities of the two tasks + * relative to each other. */ +static void prvChangeRelativePriorities( void ); + +/* + * Local pseudo random number seed and return functions. Used to avoid calls + * to the standard library. + */ +static uint32_t prvRand( void ); +static void prvSRand( uint32_t ulSeed ); + +/*-----------------------------------------------------------*/ + +/* The queues that are added to the set. */ +static QueueHandle_t xQueues[ queuesetNUM_QUEUES_IN_SET ] = { 0 }; + +/* Counts how many times each queue in the set is used to ensure all the +queues are used. */ +static uint32_t ulQueueUsedCounter[ queuesetNUM_QUEUES_IN_SET ] = { 0 }; + +/* The handle of the queue set to which the queues are added. */ +static QueueSetHandle_t xQueueSet; + +/* If the prvQueueSetReceivingTask() task has not detected any errors then +it increments ulCycleCounter on each iteration. +xAreQueueSetTasksStillRunning() returns pdPASS if the value of +ulCycleCounter has changed between consecutive calls, and pdFALSE if +ulCycleCounter has stopped incrementing (indicating an error condition). */ +static volatile uint32_t ulCycleCounter = 0UL; + +/* Set to pdFAIL if an error is detected by any queue set task. +ulCycleCounter will only be incremented if xQueueSetTasksSatus equals pdPASS. */ +static volatile BaseType_t xQueueSetTasksStatus = pdPASS; + +/* Just a flag to let the function that writes to a queue from an ISR know that +the queues are setup and can be used. */ +static volatile BaseType_t xSetupComplete = pdFALSE; + +/* The value sent to the queue from the ISR is file scope so the +xAreQueeuSetTasksStillRunning() function can check it is incrementing as +expected. */ +static volatile uint32_t ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE; + +/* Used by the pseudo random number generator. */ +static uint32_t ulNextRand = 0; + +/* The task handles are stored so their priorities can be changed. */ +TaskHandle_t xQueueSetSendingTask, xQueueSetReceivingTask; + +/*-----------------------------------------------------------*/ + +void vStartQueueSetTasks( void ) +{ + /* Create the tasks. */ + xTaskCreate( prvQueueSetSendingTask, "SetTx", configMINIMAL_STACK_SIZE, NULL, queuesetMEDIUM_PRIORITY, &xQueueSetSendingTask ); + xTaskCreate( prvQueueSetReceivingTask, "SetRx", configMINIMAL_STACK_SIZE, ( void * ) xQueueSetSendingTask, queuesetMEDIUM_PRIORITY, &xQueueSetReceivingTask ); + + /* It is important that the sending task does not attempt to write to a + queue before the queue has been created. It is therefore placed into the + suspended state before the scheduler has started. It is resumed by the + receiving task after the receiving task has created the queues and added the + queues to the queue set. */ + vTaskSuspend( xQueueSetSendingTask ); +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreQueueSetTasksStillRunning( void ) +{ +static uint32_t ulLastCycleCounter, ulLastISRTxValue = 0; +static uint32_t ulLastQueueUsedCounter[ queuesetNUM_QUEUES_IN_SET ] = { 0 }; +BaseType_t xReturn = pdPASS, x; + + if( ulLastCycleCounter == ulCycleCounter ) + { + /* The cycle counter is no longer being incremented. Either one of the + tasks is stalled or an error has been detected. */ + xReturn = pdFAIL; + } + + ulLastCycleCounter = ulCycleCounter; + + /* Ensure that all the queues in the set have been used. This ensures the + test is working as intended and guards against the rand() in the Tx task + missing some values. */ + for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ ) + { + if( ulLastQueueUsedCounter[ x ] == ulQueueUsedCounter[ x ] ) + { + xReturn = pdFAIL; + } + + ulLastQueueUsedCounter[ x ] = ulQueueUsedCounter[ x ]; + } + + /* Check the global status flag. */ + if( xQueueSetTasksStatus != pdPASS ) + { + xReturn = pdFAIL; + } + + /* Check that the ISR is still sending values to the queues too. */ + if( ulISRTxValue == ulLastISRTxValue ) + { + xReturn = pdFAIL; + } + else + { + ulLastISRTxValue = ulISRTxValue; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static void prvQueueSetSendingTask( void *pvParameters ) +{ +uint32_t ulTaskTxValue = 0, ulQueueToWriteTo; +QueueHandle_t xQueueInUse; + + /* Remove compiler warning about the unused parameter. */ + ( void ) pvParameters; + + /* Seed mini pseudo random number generator. */ + prvSRand( ( uint32_t ) &ulTaskTxValue ); + + for( ;; ) + { + /* Generate the index for the queue to which a value is to be sent. */ + ulQueueToWriteTo = prvRand() % queuesetNUM_QUEUES_IN_SET; + xQueueInUse = xQueues[ ulQueueToWriteTo ]; + + /* Note which index is being written to to ensure all the queues are + used. */ + ( ulQueueUsedCounter[ ulQueueToWriteTo ] )++; + + /* Send to the queue to unblock the task that is waiting for data to + arrive on a queue within the queue set to which this queue belongs. */ + if( xQueueSendToBack( xQueueInUse, &ulTaskTxValue, portMAX_DELAY ) != pdPASS ) + { + /* The send should always pass as an infinite block time was + used. */ + xQueueSetTasksStatus = pdFAIL; + } + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + + ulTaskTxValue++; + + /* If the Tx value has reached the range used by the ISR then set it + back to 0. */ + if( ulTaskTxValue == queuesetINITIAL_ISR_TX_VALUE ) + { + ulTaskTxValue = 0; + } + + /* Increase test coverage by occasionally change the priorities of the + two tasks relative to each other. */ + prvChangeRelativePriorities(); + } +} +/*-----------------------------------------------------------*/ + +static void prvChangeRelativePriorities( void ) +{ +static UBaseType_t ulLoops = 0; +static eRelativePriorities ePriorities = eEqualPriority; + + /* Occasionally change the task priority relative to the priority of + the receiving task. */ + ulLoops++; + if( ulLoops >= queuesetPRIORITY_CHANGE_LOOPS ) + { + ulLoops = 0; + + switch( ePriorities ) + { + case eEqualPriority: + /* Both tasks are running with medium priority. Now lower the + priority of the receiving task so the Tx task has the higher + relative priority. */ + vTaskPrioritySet( xQueueSetReceivingTask, queuesetLOW_PRIORITY ); + ePriorities = eTxHigherPriority; + break; + + case eTxHigherPriority: + /* The Tx task is running with a higher priority than the Rx + task. Switch the priorities around so the Rx task has the + higher relative priority. */ + vTaskPrioritySet( xQueueSetReceivingTask, queuesetMEDIUM_PRIORITY ); + vTaskPrioritySet( xQueueSetSendingTask, queuesetLOW_PRIORITY ); + ePriorities = eTxLowerPriority; + break; + + case eTxLowerPriority: + /* The Tx task is running with a lower priority than the Rx + task. Make the priorities equal again. */ + vTaskPrioritySet( xQueueSetSendingTask, queuesetMEDIUM_PRIORITY ); + ePriorities = eEqualPriority; + + /* When both tasks are using a non-idle priority the queue set + tasks will starve idle priority tasks of execution time - so + relax a bit before the next iteration to minimise the impact. */ + vTaskDelay( queuesetTX_LOOP_DELAY ); + + break; + } + } +} +/*-----------------------------------------------------------*/ + +static void prvQueueSetReceivingTask( void *pvParameters ) +{ +uint32_t ulReceived; +QueueHandle_t xActivatedQueue; + + /* Remove compiler warnings. */ + ( void ) pvParameters; + + /* Create the queues and add them to the queue set before resuming the Tx + task. */ + prvSetupTest(); + + for( ;; ) + { + /* Wait for a message to arrive on one of the queues in the set. */ + xActivatedQueue = xQueueSelectFromSet( xQueueSet, portMAX_DELAY ); + configASSERT( xActivatedQueue ); + + if( xActivatedQueue == NULL ) + { + /* This should not happen as an infinite delay was used. */ + xQueueSetTasksStatus = pdFAIL; + } + else + { + /* Reading from the queue should pass with a zero block time as + this task will only run when something has been posted to a task + in the queue set. */ + if( xQueueReceive( xActivatedQueue, &ulReceived, queuesetDONT_BLOCK ) != pdPASS ) + { + xQueueSetTasksStatus = pdFAIL; + } + + /* Ensure the value received was the value expected. This function + manipulates file scope data and is also called from an ISR, hence + the critical section. */ + taskENTER_CRITICAL(); + { + prvCheckReceivedValue( ulReceived ); + } + taskEXIT_CRITICAL(); + } + + if( xQueueSetTasksStatus == pdPASS ) + { + ulCycleCounter++; + } + } +} +/*-----------------------------------------------------------*/ + +void vQueueSetAccessQueueSetFromISR( void ) +{ +static uint32_t ulCallCount = 0; + + /* xSetupComplete is set to pdTRUE when the queues have been created and + are available for use. */ + if( xSetupComplete == pdTRUE ) + { + /* It is intended that this function is called from the tick hook + function, so each call is one tick period apart. */ + ulCallCount++; + if( ulCallCount > queuesetISR_TX_PERIOD ) + { + ulCallCount = 0; + + /* First attempt to read from the queue set. */ + prvReceiveFromQueueInSetFromISR(); + + /* Then write to the queue set. */ + prvSendToQueueInSetFromISR(); + } + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckReceivedValue( uint32_t ulReceived ) +{ +static uint32_t ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE; + + /* Values are received in tasks and interrupts. It is likely that the + receiving task will sometimes get preempted by the receiving interrupt + between reading a value from the queue and calling this function. When + that happens, if the receiving interrupt calls this function the values + will get passed into this function slightly out of order. For that + reason the value passed in is tested against a small range of expected + values, rather than a single absolute value. To make the range testing + easier values in the range limits are ignored. */ + + /* If the received value is equal to or greater than + queuesetINITIAL_ISR_TX_VALUE then it was sent by an ISR. */ + if( ulReceived >= queuesetINITIAL_ISR_TX_VALUE ) + { + /* The value was sent from the ISR. */ + if( ( ulReceived - queuesetINITIAL_ISR_TX_VALUE ) < queuesetIGNORED_BOUNDARY ) + { + /* The value received is at the lower limit of the expected range. + Don't test it and expect to receive one higher next time. */ + } + else if( ( ULONG_MAX - ulReceived ) <= queuesetIGNORED_BOUNDARY ) + { + /* The value received is at the higher limit of the expected range. + Don't test it and expect to wrap soon. */ + } + else + { + /* Check the value against its expected value range. */ + if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromISR ) != pdPASS ) + { + xQueueSetTasksStatus = pdFAIL; + } + } + + configASSERT( xQueueSetTasksStatus ); + + /* It is expected to receive an incrementing number. */ + ulExpectedReceivedFromISR++; + if( ulExpectedReceivedFromISR == 0 ) + { + ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE; + } + } + else + { + /* The value was sent from the Tx task. */ + if( ulReceived < queuesetIGNORED_BOUNDARY ) + { + /* The value received is at the lower limit of the expected range. + Don't test it, and expect to receive one higher next time. */ + } + else if( ( ( queuesetINITIAL_ISR_TX_VALUE - 1 ) - ulReceived ) <= queuesetIGNORED_BOUNDARY ) + { + /* The value received is at the higher limit of the expected range. + Don't test it and expect to wrap soon. */ + } + else + { + /* Check the value against its expected value range. */ + if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromTask ) != pdPASS ) + { + xQueueSetTasksStatus = pdFAIL; + } + } + + configASSERT( xQueueSetTasksStatus ); + + /* It is expected to receive an incrementing number. */ + ulExpectedReceivedFromTask++; + if( ulExpectedReceivedFromTask >= queuesetINITIAL_ISR_TX_VALUE ) + { + ulExpectedReceivedFromTask = 0; + } + } +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived, uint32_t ulExpectedReceived ) +{ +BaseType_t xReturn = pdPASS; + + if( ulReceived > ulExpectedReceived ) + { + configASSERT( ( ulReceived - ulExpectedReceived ) <= queuesetALLOWABLE_RX_DEVIATION ); + if( ( ulReceived - ulExpectedReceived ) > queuesetALLOWABLE_RX_DEVIATION ) + { + xReturn = pdFALSE; + } + } + else + { + configASSERT( ( ulExpectedReceived - ulReceived ) <= queuesetALLOWABLE_RX_DEVIATION ); + if( ( ulExpectedReceived - ulReceived ) > queuesetALLOWABLE_RX_DEVIATION ) + { + xReturn = pdFALSE; + } + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static void prvReceiveFromQueueInSetFromISR( void ) +{ +QueueSetMemberHandle_t xActivatedQueue; +uint32_t ulReceived; + + /* See if any of the queues in the set contain data. */ + xActivatedQueue = xQueueSelectFromSetFromISR( xQueueSet ); + + if( xActivatedQueue != NULL ) + { + /* Reading from the queue for test purposes only. */ + if( xQueueReceiveFromISR( xActivatedQueue, &ulReceived, NULL ) != pdPASS ) + { + /* Data should have been available as the handle was returned from + xQueueSelectFromSetFromISR(). */ + xQueueSetTasksStatus = pdFAIL; + } + + /* Ensure the value received was the value expected. */ + prvCheckReceivedValue( ulReceived ); + } +} +/*-----------------------------------------------------------*/ + +static void prvSendToQueueInSetFromISR( void ) +{ +static BaseType_t xQueueToWriteTo = 0; + + if( xQueueSendFromISR( xQueues[ xQueueToWriteTo ], ( void * ) &ulISRTxValue, NULL ) == pdPASS ) + { + ulISRTxValue++; + + /* If the Tx value has wrapped then set it back to its + initial value. */ + if( ulISRTxValue == 0UL ) + { + ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE; + } + + /* Use a different queue next time. */ + xQueueToWriteTo++; + if( xQueueToWriteTo >= queuesetNUM_QUEUES_IN_SET ) + { + xQueueToWriteTo = 0; + } + } +} +/*-----------------------------------------------------------*/ + +static void prvSetupTest( void ) +{ +BaseType_t x; +uint32_t ulValueToSend = 0; + + /* Ensure the queues are created and the queue set configured before the + sending task is unsuspended. + + First Create the queue set such that it will be able to hold a message for + every space in every queue in the set. */ + xQueueSet = xQueueCreateSet( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH ); + + for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ ) + { + /* Create the queue and add it to the set. The queue is just holding + uint32_t value. */ + xQueues[ x ] = xQueueCreate( queuesetQUEUE_LENGTH, sizeof( uint32_t ) ); + configASSERT( xQueues[ x ] ); + if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdPASS ) + { + xQueueSetTasksStatus = pdFAIL; + } + else + { + /* The queue has now been added to the queue set and cannot be added to + another. */ + if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdFAIL ) + { + xQueueSetTasksStatus = pdFAIL; + } + } + } + + /* Attempt to remove a queue from a queue set it does not belong + to (NULL being passed as the queue set in this case). */ + if( xQueueRemoveFromSet( xQueues[ 0 ], NULL ) != pdFAIL ) + { + /* It is not possible to successfully remove a queue from a queue + set it does not belong to. */ + xQueueSetTasksStatus = pdFAIL; + } + + /* Attempt to remove a queue from the queue set it does belong to. */ + if( xQueueRemoveFromSet( xQueues[ 0 ], xQueueSet ) != pdPASS ) + { + /* It should be possible to remove the queue from the queue set it + does belong to. */ + xQueueSetTasksStatus = pdFAIL; + } + + /* Add an item to the queue before attempting to add it back into the + set. */ + xQueueSend( xQueues[ 0 ], ( void * ) &ulValueToSend, 0 ); + if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdFAIL ) + { + /* Should not be able to add a non-empty queue to a set. */ + xQueueSetTasksStatus = pdFAIL; + } + + /* Remove the item from the queue before adding the queue back into the + set so the dynamic tests can begin. */ + xQueueReceive( xQueues[ 0 ], &ulValueToSend, 0 ); + if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdPASS ) + { + /* If the queue was successfully removed from the queue set then it + should be possible to add it back in again. */ + xQueueSetTasksStatus = pdFAIL; + } + + /* The task that sends to the queues is not running yet, so attempting to + read from the queue set should fail. */ + if( xQueueSelectFromSet( xQueueSet, queuesetSHORT_DELAY ) != NULL ) + { + xQueueSetTasksStatus = pdFAIL; + } + + /* Resume the task that writes to the queues. */ + vTaskResume( xQueueSetSendingTask ); + + /* Let the ISR access the queues also. */ + xSetupComplete = pdTRUE; +} +/*-----------------------------------------------------------*/ + +static uint32_t prvRand( void ) +{ + ulNextRand = ( ulNextRand * 1103515245UL ) + 12345UL; + return ( ulNextRand / 65536UL ) % 32768UL; +} +/*-----------------------------------------------------------*/ + +static void prvSRand( uint32_t ulSeed ) +{ + ulNextRand = ulSeed; +} + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/TimerDemo.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/TimerDemo.c new file mode 100644 index 0000000..68ece37 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/TimerDemo.c @@ -0,0 +1,1079 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +/* + * Tests the behaviour of timers. Some timers are created before the scheduler + * is started, and some after. + */ + +/* Standard includes. */ +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" + +/* Demo program include files. */ +#include "TimerDemo.h" + +#if ( configTIMER_TASK_PRIORITY < 1 ) + #error configTIMER_TASK_PRIORITY must be set to at least 1 for this test/demo to function correctly. +#endif + +#define tmrdemoDONT_BLOCK ( ( TickType_t ) 0 ) +#define tmrdemoONE_SHOT_TIMER_PERIOD ( xBasePeriod * ( TickType_t ) 3 ) +#define trmdemoNUM_TIMER_RESETS ( ( uint8_t ) 10 ) + +/*-----------------------------------------------------------*/ + +/* The callback functions used by the timers. These each increment a counter +to indicate which timer has expired. The auto-reload timers that are used by +the test task (as opposed to being used from an ISR) all share the same +prvAutoReloadTimerCallback() callback function, and use the ID of the +pxExpiredTimer parameter passed into that function to know which counter to +increment. The other timers all have their own unique callback function and +simply increment their counters without using the callback function parameter. */ +static void prvAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer ); +static void prvOneShotTimerCallback( TimerHandle_t pxExpiredTimer ); +static void prvTimerTestTask( void *pvParameters ); +static void prvISRAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer ); +static void prvISROneShotTimerCallback( TimerHandle_t pxExpiredTimer ); + +/* The test functions used by the timer test task. These manipulate the auto +reload and one shot timers in various ways, then delay, then inspect the timers +to ensure they have behaved as expected. */ +static void prvTest1_CreateTimersWithoutSchedulerRunning( void ); +static void prvTest2_CheckTaskAndTimersInitialState( void ); +static void prvTest3_CheckAutoReloadExpireRates( void ); +static void prvTest4_CheckAutoReloadTimersCanBeStopped( void ); +static void prvTest5_CheckBasicOneShotTimerBehaviour( void ); +static void prvTest6_CheckAutoReloadResetBehaviour( void ); +static void prvResetStartConditionsForNextIteration( void ); + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdFAIL should any unexpected behaviour be +detected in any of the demo tests. */ +static volatile BaseType_t xTestStatus = pdPASS; + +/* Counter that is incremented on each cycle of a test. This is used to +detect a stalled task - a test that is no longer running. */ +static volatile uint32_t ulLoopCounter = 0; + +/* A set of auto reload timers - each of which use the same callback function. +The callback function uses the timer ID to index into, and then increment, a +counter in the ucAutoReloadTimerCounters[] array. The auto reload timers +referenced from xAutoReloadTimers[] are used by the prvTimerTestTask task. */ +static TimerHandle_t xAutoReloadTimers[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 }; +static uint8_t ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 }; + +/* The one shot timer is configured to use a callback function that increments +ucOneShotTimerCounter each time it gets called. */ +static TimerHandle_t xOneShotTimer = NULL; +static uint8_t ucOneShotTimerCounter = ( uint8_t ) 0; + +/* The ISR reload timer is controlled from the tick hook to exercise the timer +API functions that can be used from an ISR. It is configured to increment +ucISRReloadTimerCounter each time its callback function is executed. */ +static TimerHandle_t xISRAutoReloadTimer = NULL; +static uint8_t ucISRAutoReloadTimerCounter = ( uint8_t ) 0; + +/* The ISR one shot timer is controlled from the tick hook to exercise the timer +API functions that can be used from an ISR. It is configured to increment +ucISRReloadTimerCounter each time its callback function is executed. */ +static TimerHandle_t xISROneShotTimer = NULL; +static uint8_t ucISROneShotTimerCounter = ( uint8_t ) 0; + +/* The period of all the timers are a multiple of the base period. The base +period is configured by the parameter to vStartTimerDemoTask(). */ +static TickType_t xBasePeriod = 0; + +/*-----------------------------------------------------------*/ + +void vStartTimerDemoTask( TickType_t xBasePeriodIn ) +{ + /* Start with the timer and counter arrays clear - this is only necessary + where the compiler does not clear them automatically on start up. */ + memset( ucAutoReloadTimerCounters, 0x00, sizeof( ucAutoReloadTimerCounters ) ); + memset( xAutoReloadTimers, 0x00, sizeof( xAutoReloadTimers ) ); + + /* Store the period from which all the timer periods will be generated from + (multiples of). */ + xBasePeriod = xBasePeriodIn; + + /* Create a set of timers for use by this demo/test. */ + prvTest1_CreateTimersWithoutSchedulerRunning(); + + /* Create the task that will control and monitor the timers. This is + created at a lower priority than the timer service task to ensure, as + far as it is concerned, commands on timers are actioned immediately + (sending a command to the timer service task will unblock the timer service + task, which will then preempt this task). */ + if( xTestStatus != pdFAIL ) + { + xTaskCreate( prvTimerTestTask, "Tmr Tst", configMINIMAL_STACK_SIZE, NULL, configTIMER_TASK_PRIORITY - 1, NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvTimerTestTask( void *pvParameters ) +{ + ( void ) pvParameters; + + /* Create a one-shot timer for use later on in this test. */ + xOneShotTimer = xTimerCreate( "Oneshot Timer", /* Text name to facilitate debugging. The kernel does not use this itself. */ + tmrdemoONE_SHOT_TIMER_PERIOD, /* The period for the timer. */ + pdFALSE, /* Don't auto-reload - hence a one shot timer. */ + ( void * ) 0, /* The timer identifier. In this case this is not used as the timer has its own callback. */ + prvOneShotTimerCallback ); /* The callback to be called when the timer expires. */ + + if( xOneShotTimer == NULL ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + + /* Ensure all the timers are in their expected initial state. This + depends on the timer service task having a higher priority than this task. */ + prvTest2_CheckTaskAndTimersInitialState(); + + for( ;; ) + { + /* Check the auto reload timers expire at the expected/correct rates. */ + prvTest3_CheckAutoReloadExpireRates(); + + /* Check the auto reload timers can be stopped correctly, and correctly + report their state. */ + prvTest4_CheckAutoReloadTimersCanBeStopped(); + + /* Check the one shot timer only calls its callback once after it has been + started, and that it reports its state correctly. */ + prvTest5_CheckBasicOneShotTimerBehaviour(); + + /* Check timer reset behaviour. */ + prvTest6_CheckAutoReloadResetBehaviour(); + + /* Start the timers again to restart all the tests over again. */ + prvResetStartConditionsForNextIteration(); + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that the created task is still running and has not +detected any errors. */ +BaseType_t xAreTimerDemoTasksStillRunning( TickType_t xCycleFrequency ) +{ +static uint32_t ulLastLoopCounter = 0UL; +TickType_t xMaxBlockTimeUsedByTheseTests, xLoopCounterIncrementTimeMax; +static TickType_t xIterationsWithoutCounterIncrement = ( TickType_t ) 0, xLastCycleFrequency; + + if( xLastCycleFrequency != xCycleFrequency ) + { + /* The cycle frequency has probably become much faster due to an error + elsewhere. Start counting Iterations again. */ + xIterationsWithoutCounterIncrement = ( TickType_t ) 0; + xLastCycleFrequency = xCycleFrequency; + } + + /* Calculate the maximum number of times that it is permissible for this + function to be called without ulLoopCounter being incremented. This is + necessary because the tests in this file block for extended periods, and the + block period might be longer than the time between calls to this function. */ + xMaxBlockTimeUsedByTheseTests = ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod; + xLoopCounterIncrementTimeMax = ( xMaxBlockTimeUsedByTheseTests / xCycleFrequency ) + 1; + + /* If the demo task is still running then the loop counter is expected to + have incremented every xLoopCounterIncrementTimeMax calls. */ + if( ulLastLoopCounter == ulLoopCounter ) + { + xIterationsWithoutCounterIncrement++; + if( xIterationsWithoutCounterIncrement > xLoopCounterIncrementTimeMax ) + { + /* The tests appear to be no longer running (stalled). */ + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else + { + /* ulLoopCounter changed, so the count of times this function was called + without a change can be reset to zero. */ + xIterationsWithoutCounterIncrement = ( TickType_t ) 0; + } + + ulLastLoopCounter = ulLoopCounter; + + /* Errors detected in the task itself will have latched xTestStatus + to pdFAIL. */ + + return xTestStatus; +} +/*-----------------------------------------------------------*/ + +static void prvTest1_CreateTimersWithoutSchedulerRunning( void ) +{ +UBaseType_t xTimer; + + for( xTimer = 0; xTimer < configTIMER_QUEUE_LENGTH; xTimer++ ) + { + /* As the timer queue is not yet full, it should be possible to both create + and start a timer. These timers are being started before the scheduler has + been started, so their block times should get set to zero within the timer + API itself. */ + xAutoReloadTimers[ xTimer ] = xTimerCreate( "FR Timer", /* Text name to facilitate debugging. The kernel does not use this itself. */ + ( ( xTimer + ( TickType_t ) 1 ) * xBasePeriod ),/* The period for the timer. The plus 1 ensures a period of zero is not specified. */ + pdTRUE, /* Auto-reload is set to true. */ + ( void * ) xTimer, /* An identifier for the timer as all the auto reload timers use the same callback. */ + prvAutoReloadTimerCallback ); /* The callback to be called when the timer expires. */ + + configASSERT( strcmp( pcTimerGetTimerName( xAutoReloadTimers[ xTimer ] ), "FR Timer" ) == 0 ); + + if( xAutoReloadTimers[ xTimer ] == NULL ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + else + { + /* The scheduler has not yet started, so the block period of + portMAX_DELAY should just get set to zero in xTimerStart(). Also, + the timer queue is not yet full so xTimerStart() should return + pdPASS. */ + if( xTimerStart( xAutoReloadTimers[ xTimer ], portMAX_DELAY ) != pdPASS ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + } + + /* The timers queue should now be full, so it should be possible to create + another timer, but not possible to start it (the timer queue will not get + drained until the scheduler has been started. */ + xAutoReloadTimers[ configTIMER_QUEUE_LENGTH ] = xTimerCreate( "FR Timer", /* Text name to facilitate debugging. The kernel does not use this itself. */ + ( configTIMER_QUEUE_LENGTH * xBasePeriod ), /* The period for the timer. */ + pdTRUE, /* Auto-reload is set to true. */ + ( void * ) xTimer, /* An identifier for the timer as all the auto reload timers use the same callback. */ + prvAutoReloadTimerCallback ); /* The callback executed when the timer expires. */ + + if( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH ] == NULL ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + else + { + if( xTimerStart( xAutoReloadTimers[ xTimer ], portMAX_DELAY ) == pdPASS ) + { + /* This time it would not be expected that the timer could be + started at this point. */ + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + + /* Create the timers that are used from the tick interrupt to test the timer + API functions that can be called from an ISR. */ + xISRAutoReloadTimer = xTimerCreate( "ISR AR", /* The text name given to the timer. */ + 0xffff, /* The timer is not given a period yet - this will be done from the tick hook, but a period of 0 is invalid. */ + pdTRUE, /* This is an auto reload timer. */ + ( void * ) NULL, /* The identifier is not required. */ + prvISRAutoReloadTimerCallback ); /* The callback that is executed when the timer expires. */ + + xISROneShotTimer = xTimerCreate( "ISR OS", /* The text name given to the timer. */ + 0xffff, /* The timer is not given a period yet - this will be done from the tick hook, but a period of 0 is invalid. */ + pdFALSE, /* This is a one shot timer. */ + ( void * ) NULL, /* The identifier is not required. */ + prvISROneShotTimerCallback ); /* The callback that is executed when the timer expires. */ + + if( ( xISRAutoReloadTimer == NULL ) || ( xISROneShotTimer == NULL ) ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } +} +/*-----------------------------------------------------------*/ + +static void prvTest2_CheckTaskAndTimersInitialState( void ) +{ +uint8_t ucTimer; + + /* Ensure all the timers are in their expected initial state. This depends + on the timer service task having a higher priority than this task. + + auto reload timers 0 to ( configTIMER_QUEUE_LENGTH - 1 ) should now be active, + and auto reload timer configTIMER_QUEUE_LENGTH should not yet be active (it + could not be started prior to the scheduler being started when it was + created). */ + for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ ) + { + if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + + if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH ] ) != pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } +} +/*-----------------------------------------------------------*/ + +static void prvTest3_CheckAutoReloadExpireRates( void ) +{ +uint8_t ucMaxAllowableValue, ucMinAllowableValue, ucTimer; +TickType_t xBlockPeriod, xTimerPeriod, xExpectedNumber; + + /* Check the auto reload timers expire at the expected rates. */ + + + /* Delaying for configTIMER_QUEUE_LENGTH * xBasePeriod ticks should allow + all the auto reload timers to expire at least once. */ + xBlockPeriod = ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod; + vTaskDelay( xBlockPeriod ); + + /* Check that all the auto reload timers have called their callback + function the expected number of times. */ + for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ ) + { + /* The expected number of expiries is equal to the block period divided + by the timer period. */ + xTimerPeriod = ( ( ( TickType_t ) ucTimer + ( TickType_t ) 1 ) * xBasePeriod ); + xExpectedNumber = xBlockPeriod / xTimerPeriod; + + ucMaxAllowableValue = ( ( uint8_t ) xExpectedNumber ) ; + ucMinAllowableValue = ( uint8_t ) ( ( uint8_t ) xExpectedNumber - ( uint8_t ) 1 ); /* Weird casting to try and please all compilers. */ + + if( ( ucAutoReloadTimerCounters[ ucTimer ] < ucMinAllowableValue ) || + ( ucAutoReloadTimerCounters[ ucTimer ] > ucMaxAllowableValue ) + ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + + if( xTestStatus == pdPASS ) + { + /* No errors have been reported so increment the loop counter so the + check task knows this task is still running. */ + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvTest4_CheckAutoReloadTimersCanBeStopped( void ) +{ +uint8_t ucTimer; + + /* Check the auto reload timers can be stopped correctly, and correctly + report their state. */ + + /* Stop all the active timers. */ + for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ ) + { + /* The timer has not been stopped yet! */ + if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Now stop the timer. This will appear to happen immediately to + this task because this task is running at a priority below the + timer service task. */ + xTimerStop( xAutoReloadTimers[ ucTimer ], tmrdemoDONT_BLOCK ); + + /* The timer should now be inactive. */ + if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) != pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + + taskENTER_CRITICAL(); + { + /* The timer in array position configTIMER_QUEUE_LENGTH should not + be active. The critical section is used to ensure the timer does + not call its callback between the next line running and the array + being cleared back to zero, as that would mask an error condition. */ + if( ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH ] != ( uint8_t ) 0 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Clear the timer callback count. */ + memset( ( void * ) ucAutoReloadTimerCounters, 0, sizeof( ucAutoReloadTimerCounters ) ); + } + taskEXIT_CRITICAL(); + + /* The timers are now all inactive, so this time, after delaying, none + of the callback counters should have incremented. */ + vTaskDelay( ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod ); + for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ ) + { + if( ucAutoReloadTimerCounters[ ucTimer ] != ( uint8_t ) 0 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + + if( xTestStatus == pdPASS ) + { + /* No errors have been reported so increment the loop counter so + the check task knows this task is still running. */ + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvTest5_CheckBasicOneShotTimerBehaviour( void ) +{ + /* Check the one shot timer only calls its callback once after it has been + started, and that it reports its state correctly. */ + + /* The one shot timer should not be active yet. */ + if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucOneShotTimerCounter != ( uint8_t ) 0 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Start the one shot timer and check that it reports its state correctly. */ + xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK ); + if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Delay for three times as long as the one shot timer period, then check + to ensure it has only called its callback once, and is now not in the + active state. */ + vTaskDelay( tmrdemoONE_SHOT_TIMER_PERIOD * ( TickType_t ) 3 ); + + if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucOneShotTimerCounter != ( uint8_t ) 1 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + else + { + /* Reset the one shot timer callback count. */ + ucOneShotTimerCounter = ( uint8_t ) 0; + } + + if( xTestStatus == pdPASS ) + { + /* No errors have been reported so increment the loop counter so the + check task knows this task is still running. */ + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvTest6_CheckAutoReloadResetBehaviour( void ) +{ +uint8_t ucTimer; + + /* Check timer reset behaviour. */ + + /* Restart the one shot timer and check it reports its status correctly. */ + xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK ); + if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Restart one of the auto reload timers and check that it reports its + status correctly. */ + xTimerStart( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK ); + if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + for( ucTimer = 0; ucTimer < trmdemoNUM_TIMER_RESETS; ucTimer++ ) + { + /* Delay for half as long as the one shot timer period, then reset it. + It should never expire while this is done, so its callback count should + never increment. */ + vTaskDelay( tmrdemoONE_SHOT_TIMER_PERIOD / 2 ); + + /* Check both running timers are still active, but have not called their + callback functions. */ + if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucOneShotTimerCounter != ( uint8_t ) 0 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] != ( uint8_t ) 0 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Reset both running timers. */ + xTimerReset( xOneShotTimer, tmrdemoDONT_BLOCK ); + xTimerReset( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK ); + + if( xTestStatus == pdPASS ) + { + /* No errors have been reported so increment the loop counter so + the check task knows this task is still running. */ + ulLoopCounter++; + } + } + + /* Finally delay long enough for both running timers to expire. */ + vTaskDelay( ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod ); + + /* The timers were not reset during the above delay period so should now + both have called their callback functions. */ + if( ucOneShotTimerCounter != ( uint8_t ) 1 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] == 0 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* The one shot timer should no longer be active, while the auto reload + timer should still be active. */ + if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( xTimerIsTimerActive( xOneShotTimer ) == pdTRUE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Stop the auto reload timer again. */ + xTimerStop( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK ); + + if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) != pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Clear the timer callback counts, ready for another iteration of these + tests. */ + ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] = ( uint8_t ) 0; + ucOneShotTimerCounter = ( uint8_t ) 0; + + if( xTestStatus == pdPASS ) + { + /* No errors have been reported so increment the loop counter so the check + task knows this task is still running. */ + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvResetStartConditionsForNextIteration( void ) +{ +uint8_t ucTimer; + + /* Start the timers again to start all the tests over again. */ + + /* Start the timers again. */ + for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ ) + { + /* The timer has not been started yet! */ + if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) != pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Now start the timer. This will appear to happen immediately to + this task because this task is running at a priority below the timer + service task. */ + xTimerStart( xAutoReloadTimers[ ucTimer ], tmrdemoDONT_BLOCK ); + + /* The timer should now be active. */ + if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + + if( xTestStatus == pdPASS ) + { + /* No errors have been reported so increment the loop counter so the + check task knows this task is still running. */ + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +void vTimerPeriodicISRTests( void ) +{ +static TickType_t uxTick = ( TickType_t ) -1; + +#if( configTIMER_TASK_PRIORITY != ( configMAX_PRIORITIES - 1 ) ) + /* The timer service task is not the highest priority task, so it cannot + be assumed that timings will be exact. Timers should never call their + callback before their expiry time, but a margin is permissible for calling + their callback after their expiry time. If exact timing is required then + configTIMER_TASK_PRIORITY must be set to ensure the timer service task + is the highest priority task in the system. + + This function is called from the tick hook. The tick hook is called + even when the scheduler is suspended. Therefore it is possible that the + uxTick count maintained in this function is temporarily ahead of the tick + count maintained by the kernel. When this is the case a message posted from + this function will assume a time stamp in advance of the real time stamp, + which can result in a timer being processed before this function expects it + to. For example, if the kernel's tick count was 100, and uxTick was 102, + then this function will not expect the timer to have expired until the + kernel's tick count is (102 + xBasePeriod), whereas in reality the timer + will expire when the kernel's tick count is (100 + xBasePeriod). For this + reason xMargin is used as an allowable margin for premature timer expiries + as well as late timer expiries. */ + const TickType_t xMargin = 6; +#else + #ifdef _WINDOWS_ + /* Windows is not real real time. */ + const TickType_t xMargin = 8; + #else + const TickType_t xMargin = 4; + #endif /* _WINDOWS_ */ +#endif + + + uxTick++; + + if( uxTick == 0 ) + { + /* The timers will have been created, but not started. Start them now + by setting their period. */ + ucISRAutoReloadTimerCounter = 0; + ucISROneShotTimerCounter = 0; + + /* It is possible that the timer task has not yet made room in the + timer queue. If the timers cannot be started then reset uxTick so + another attempt is made later. */ + uxTick = ( TickType_t ) -1; + + /* Try starting first timer. */ + if( xTimerChangePeriodFromISR( xISRAutoReloadTimer, xBasePeriod, NULL ) == pdPASS ) + { + /* First timer was started, try starting the second timer. */ + if( xTimerChangePeriodFromISR( xISROneShotTimer, xBasePeriod, NULL ) == pdPASS ) + { + /* Both timers were started, so set the uxTick back to its + proper value. */ + uxTick = 0; + } + else + { + /* Second timer could not be started, so stop the first one + again. */ + xTimerStopFromISR( xISRAutoReloadTimer, NULL ); + } + } + } + else if( uxTick == ( xBasePeriod - xMargin ) ) + { + /* Neither timer should have expired yet. */ + if( ( ucISRAutoReloadTimerCounter != 0 ) || ( ucISROneShotTimerCounter != 0 ) ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( xBasePeriod + xMargin ) ) + { + /* Both timers should now have expired once. The auto reload timer will + still be active, but the one shot timer should now have stopped. */ + if( ( ucISRAutoReloadTimerCounter != 1 ) || ( ucISROneShotTimerCounter != 1 ) ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( ( 2 * xBasePeriod ) - xMargin ) ) + { + /* The auto reload timer will still be active, but the one shot timer + should now have stopped - however, at this time neither of the timers + should have expired again since the last test. */ + if( ( ucISRAutoReloadTimerCounter != 1 ) || ( ucISROneShotTimerCounter != 1 ) ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( ( 2 * xBasePeriod ) + xMargin ) ) + { + /* The auto reload timer will still be active, but the one shot timer + should now have stopped. At this time the auto reload timer should have + expired again, but the one shot timer count should not have changed. */ + if( ucISRAutoReloadTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 1 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( ( 2 * xBasePeriod ) + ( xBasePeriod >> ( TickType_t ) 2U ) ) ) + { + /* The auto reload timer will still be active, but the one shot timer + should now have stopped. Again though, at this time, neither timer call + back should have been called since the last test. */ + if( ucISRAutoReloadTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 1 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( 3 * xBasePeriod ) ) + { + /* Start the one shot timer again. */ + xTimerStartFromISR( xISROneShotTimer, NULL ); + } + else if( uxTick == ( ( 3 * xBasePeriod ) + xMargin ) ) + { + /* The auto reload timer and one shot timer will be active. At + this time the auto reload timer should have expired again, but the one + shot timer count should not have changed yet. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 1 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Now stop the auto reload timer. The one shot timer was started + a few ticks ago. */ + xTimerStopFromISR( xISRAutoReloadTimer, NULL ); + } + else if( uxTick == ( 4 * ( xBasePeriod - xMargin ) ) ) + { + /* The auto reload timer is now stopped, and the one shot timer is + active, but at this time neither timer should have expired since the + last test. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 1 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( ( 4 * xBasePeriod ) + xMargin ) ) + { + /* The auto reload timer is now stopped, and the one shot timer is + active. The one shot timer should have expired again, but the auto + reload timer should not have executed its callback. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( 8 * xBasePeriod ) ) + { + /* The auto reload timer is now stopped, and the one shot timer has + already expired and then stopped itself. Both callback counters should + not have incremented since the last test. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Now reset the one shot timer. */ + xTimerResetFromISR( xISROneShotTimer, NULL ); + } + else if( uxTick == ( ( 9 * xBasePeriod ) - xMargin ) ) + { + /* Only the one shot timer should be running, but it should not have + expired since the last test. Check the callback counters have not + incremented, then reset the one shot timer again. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + xTimerResetFromISR( xISROneShotTimer, NULL ); + } + else if( uxTick == ( ( 10 * xBasePeriod ) - ( 2 * xMargin ) ) ) + { + /* Only the one shot timer should be running, but it should not have + expired since the last test. Check the callback counters have not + incremented, then reset the one shot timer again. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + xTimerResetFromISR( xISROneShotTimer, NULL ); + } + else if( uxTick == ( ( 11 * xBasePeriod ) - ( 3 * xMargin ) ) ) + { + /* Only the one shot timer should be running, but it should not have + expired since the last test. Check the callback counters have not + incremented, then reset the one shot timer once again. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + xTimerResetFromISR( xISROneShotTimer, NULL ); + } + else if( uxTick == ( ( 12 * xBasePeriod ) - ( 2 * xMargin ) ) ) + { + /* Only the one shot timer should have been running and this time it + should have expired. Check its callback count has been incremented. + The auto reload timer is still not running so should still have the same + count value. This time the one shot timer is not reset so should not + restart from its expiry period again. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( 15 * xBasePeriod ) ) + { + /* Neither timer should be running now. Check neither callback count + has incremented, then go back to the start to run these tests all + over again. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + uxTick = ( TickType_t ) -1; + } +} +/*-----------------------------------------------------------*/ + +/*** Timer callback functions are defined below here. ***/ + +static void prvAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer ) +{ +uint32_t ulTimerID; + + ulTimerID = ( uint32_t ) pvTimerGetTimerID( pxExpiredTimer ); + if( ulTimerID <= ( configTIMER_QUEUE_LENGTH + 1 ) ) + { + ( ucAutoReloadTimerCounters[ ulTimerID ] )++; + } + else + { + /* The timer ID appears to be unexpected (invalid). */ + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } +} +/*-----------------------------------------------------------*/ + +static void prvOneShotTimerCallback( TimerHandle_t pxExpiredTimer ) +{ + /* The parameter is not used in this case as only one timer uses this + callback function. */ + ( void ) pxExpiredTimer; + + ucOneShotTimerCounter++; +} +/*-----------------------------------------------------------*/ + +static void prvISRAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer ) +{ + /* The parameter is not used in this case as only one timer uses this + callback function. */ + ( void ) pxExpiredTimer; + + ucISRAutoReloadTimerCounter++; +} +/*-----------------------------------------------------------*/ + +static void prvISROneShotTimerCallback( TimerHandle_t pxExpiredTimer ) +{ + /* The parameter is not used in this case as only one timer uses this + callback function. */ + ( void ) pxExpiredTimer; + + ucISROneShotTimerCounter++; +} +/*-----------------------------------------------------------*/ + + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/blocktim.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/blocktim.c new file mode 100644 index 0000000..2528317 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/blocktim.c @@ -0,0 +1,505 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * This file contains some test scenarios that ensure tasks do not exit queue + * send or receive functions prematurely. A description of the tests is + * included within the code. + */ + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo includes. */ +#include "blocktim.h" + +/* Task priorities. Allow these to be overridden. */ +#ifndef bktPRIMARY_PRIORITY + #define bktPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 ) +#endif + +#ifndef bktSECONDARY_PRIORITY + #define bktSECONDARY_PRIORITY ( configMAX_PRIORITIES - 4 ) +#endif + +/* Task behaviour. */ +#define bktQUEUE_LENGTH ( 5 ) +#define bktSHORT_WAIT ( ( ( TickType_t ) 20 ) / portTICK_PERIOD_MS ) +#define bktPRIMARY_BLOCK_TIME ( 10 ) +#define bktALLOWABLE_MARGIN ( 15 ) +#define bktTIME_TO_BLOCK ( 175 ) +#define bktDONT_BLOCK ( ( TickType_t ) 0 ) +#define bktRUN_INDICATOR ( ( UBaseType_t ) 0x55 ) + +/* The queue on which the tasks block. */ +static QueueHandle_t xTestQueue; + +/* Handle to the secondary task is required by the primary task for calls +to vTaskSuspend/Resume(). */ +static TaskHandle_t xSecondary; + +/* Used to ensure that tasks are still executing without error. */ +static volatile BaseType_t xPrimaryCycles = 0, xSecondaryCycles = 0; +static volatile BaseType_t xErrorOccurred = pdFALSE; + +/* Provides a simple mechanism for the primary task to know when the +secondary task has executed. */ +static volatile UBaseType_t xRunIndicator; + +/* The two test tasks. Their behaviour is commented within the files. */ +static void vPrimaryBlockTimeTestTask( void *pvParameters ); +static void vSecondaryBlockTimeTestTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +void vCreateBlockTimeTasks( void ) +{ + /* Create the queue on which the two tasks block. */ + xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( BaseType_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xTestQueue, "Block_Time_Queue" ); + + /* Create the two test tasks. */ + xTaskCreate( vPrimaryBlockTimeTestTask, "BTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL ); + xTaskCreate( vSecondaryBlockTimeTestTask, "BTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary ); +} +/*-----------------------------------------------------------*/ + +static void vPrimaryBlockTimeTestTask( void *pvParameters ) +{ +BaseType_t xItem, xData; +TickType_t xTimeWhenBlocking; +TickType_t xTimeToBlock, xBlockedTime; + + ( void ) pvParameters; + + for( ;; ) + { + /********************************************************************* + Test 1 + + Simple block time wakeup test on queue receives. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* The queue is empty. Attempt to read from the queue using a block + time. When we wake, ensure the delta in time is as expected. */ + xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem ); + + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after xTimeToBlock having not received + anything on the queue. */ + if( xQueueReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we blocked for? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + + if( xBlockedTime < xTimeToBlock ) + { + /* Should not have blocked for less than we requested. */ + xErrorOccurred = pdTRUE; + } + + if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) ) + { + /* Should not have blocked for longer than we requested, + although we would not necessarily run as soon as we were + unblocked so a margin is allowed. */ + xErrorOccurred = pdTRUE; + } + } + + /********************************************************************* + Test 2 + + Simple block time wakeup test on queue sends. + + First fill the queue. It should be empty so all sends should pass. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* The queue is full. Attempt to write to the queue using a block + time. When we wake, ensure the delta in time is as expected. */ + xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem ); + + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after xTimeToBlock having not received + anything on the queue. */ + if( xQueueSend( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we blocked for? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + + if( xBlockedTime < xTimeToBlock ) + { + /* Should not have blocked for less than we requested. */ + xErrorOccurred = pdTRUE; + } + + if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) ) + { + /* Should not have blocked for longer than we requested, + although we would not necessarily run as soon as we were + unblocked so a margin is allowed. */ + xErrorOccurred = pdTRUE; + } + } + + /********************************************************************* + Test 3 + + Wake the other task, it will block attempting to post to the queue. + When we read from the queue the other task will wake, but before it + can run we will post to the queue again. When the other task runs it + will find the queue still full, even though it was woken. It should + recognise that its block time has not expired and return to block for + the remains of its block time. + + Wake the other task so it blocks attempting to post to the already + full queue. */ + xRunIndicator = 0; + vTaskResume( xSecondary ); + + /* We need to wait a little to ensure the other task executes. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + /* The other task has not yet executed. */ + vTaskDelay( bktSHORT_WAIT ); + } + /* Make sure the other task is blocked on the queue. */ + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* Now when we make space on the queue the other task should wake + but not execute as this task has higher priority. */ + if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Now fill the queue again before the other task gets a chance to + execute. If the other task had executed we would find the queue + full ourselves, and the other task have set xRunIndicator. */ + if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed. */ + xErrorOccurred = pdTRUE; + } + + /* Raise the priority of the other task so it executes and blocks + on the queue again. */ + vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 ); + + /* The other task should now have re-blocked without exiting the + queue function. */ + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed outside of the + queue function. */ + xErrorOccurred = pdTRUE; + } + + /* Set the priority back down. */ + vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); + } + + /* Let the other task timeout. When it unblockes it will check that it + unblocked at the correct time, then suspend itself. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + + /********************************************************************* + Test 4 + + As per test 3 - but with the send and receive the other way around. + The other task blocks attempting to read from the queue. + + Empty the queue. We should find that it is full. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + } + + /* Wake the other task so it blocks attempting to read from the + already empty queue. */ + vTaskResume( xSecondary ); + + /* We need to wait a little to ensure the other task executes. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* Now when we place an item on the queue the other task should + wake but not execute as this task has higher priority. */ + if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Now empty the queue again before the other task gets a chance to + execute. If the other task had executed we would find the queue + empty ourselves, and the other task would be suspended. */ + if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed. */ + xErrorOccurred = pdTRUE; + } + + /* Raise the priority of the other task so it executes and blocks + on the queue again. */ + vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 ); + + /* The other task should now have re-blocked without exiting the + queue function. */ + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed outside of the + queue function. */ + xErrorOccurred = pdTRUE; + } + vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); + } + + /* Let the other task timeout. When it unblockes it will check that it + unblocked at the correct time, then suspend itself. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + + xPrimaryCycles++; + } +} +/*-----------------------------------------------------------*/ + +static void vSecondaryBlockTimeTestTask( void *pvParameters ) +{ +TickType_t xTimeWhenBlocking, xBlockedTime; +BaseType_t xData; + + ( void ) pvParameters; + + for( ;; ) + { + /********************************************************************* + Test 1 and 2 + + This task does does not participate in these tests. */ + vTaskSuspend( NULL ); + + /********************************************************************* + Test 3 + + The first thing we do is attempt to read from the queue. It should be + full so we block. Note the time before we block so we can check the + wake time is as per that expected. */ + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after bktTIME_TO_BLOCK having not sent + anything to the queue. */ + xData = 0; + xRunIndicator = bktRUN_INDICATOR; + if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we inside the send function? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + + /* We should not have blocked for less time than bktTIME_TO_BLOCK. */ + if( xBlockedTime < bktTIME_TO_BLOCK ) + { + xErrorOccurred = pdTRUE; + } + + /* We should of not blocked for much longer than bktALLOWABLE_MARGIN + either. A margin is permitted as we would not necessarily run as + soon as we unblocked. */ + if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) ) + { + xErrorOccurred = pdTRUE; + } + + /* Suspend ready for test 3. */ + xRunIndicator = bktRUN_INDICATOR; + vTaskSuspend( NULL ); + + /********************************************************************* + Test 4 + + As per test three, but with the send and receive reversed. */ + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after bktTIME_TO_BLOCK having not received + anything on the queue. */ + xRunIndicator = bktRUN_INDICATOR; + if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY ) + { + xErrorOccurred = pdTRUE; + } + + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + + /* We should not have blocked for less time than bktTIME_TO_BLOCK. */ + if( xBlockedTime < bktTIME_TO_BLOCK ) + { + xErrorOccurred = pdTRUE; + } + + /* We should of not blocked for much longer than bktALLOWABLE_MARGIN + either. A margin is permitted as we would not necessarily run as soon + as we unblocked. */ + if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) ) + { + xErrorOccurred = pdTRUE; + } + + xRunIndicator = bktRUN_INDICATOR; + + xSecondaryCycles++; + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreBlockTimeTestTasksStillRunning( void ) +{ +static BaseType_t xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0; +BaseType_t xReturn = pdPASS; + + /* Have both tasks performed at least one cycle since this function was + last called? */ + if( xPrimaryCycles == xLastPrimaryCycleCount ) + { + xReturn = pdFAIL; + } + + if( xSecondaryCycles == xLastSecondaryCycleCount ) + { + xReturn = pdFAIL; + } + + if( xErrorOccurred == pdTRUE ) + { + xReturn = pdFAIL; + } + + xLastSecondaryCycleCount = xSecondaryCycles; + xLastPrimaryCycleCount = xPrimaryCycles; + + return xReturn; +} diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest.c new file mode 100644 index 0000000..2a1542a --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest.c @@ -0,0 +1,303 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +/* + * This version of comtest. c is for use on systems that have limited stack + * space and no display facilities. The complete version can be found in + * the Demo/Common/Full directory. + * + * Creates two tasks that operate on an interrupt driven serial port. A + * loopback connector should be used so that everything that is transmitted is + * also received. The serial port does not use any flow control. On a + * standard 9way 'D' connector pins two and three should be connected together. + * + * The first task posts a sequence of characters to the Tx queue, toggling an + * LED on each successful post. At the end of the sequence it sleeps for a + * pseudo-random period before resending the same sequence. + * + * The UART Tx end interrupt is enabled whenever data is available in the Tx + * queue. The Tx end ISR removes a single character from the Tx queue and + * passes it to the UART for transmission. + * + * The second task blocks on the Rx queue waiting for a character to become + * available. When the UART Rx end interrupt receives a character it places + * it in the Rx queue, waking the second task. The second task checks that the + * characters removed from the Rx queue form the same sequence as those posted + * to the Tx queue, and toggles an LED for each correct character. + * + * The receiving task is spawned with a higher priority than the transmitting + * task. The receiver will therefore wake every time a character is + * transmitted so neither the Tx or Rx queue should ever hold more than a few + * characters. + * + */ + +/* Scheduler include files. */ +#include +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "serial.h" +#include "comtest.h" +#include "partest.h" + +#define comSTACK_SIZE configMINIMAL_STACK_SIZE +#define comTX_LED_OFFSET ( 0 ) +#define comRX_LED_OFFSET ( 1 ) +#define comTOTAL_PERMISSIBLE_ERRORS ( 2 ) + +/* The Tx task will transmit the sequence of characters at a pseudo random +interval. This is the maximum and minimum block time between sends. */ +#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x96 ) +#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0x32 ) +#define comOFFSET_TIME ( ( TickType_t ) 3 ) + +/* We should find that each character can be queued for Tx immediately and we +don't have to block to send. */ +#define comNO_BLOCK ( ( TickType_t ) 0 ) + +/* The Rx task will block on the Rx queue for a long period. */ +#define comRX_BLOCK_TIME ( ( TickType_t ) 0xffff ) + +/* The sequence transmitted is from comFIRST_BYTE to and including comLAST_BYTE. */ +#define comFIRST_BYTE ( 'A' ) +#define comLAST_BYTE ( 'X' ) + +#define comBUFFER_LEN ( ( UBaseType_t ) ( comLAST_BYTE - comFIRST_BYTE ) + ( UBaseType_t ) 1 ) +#define comINITIAL_RX_COUNT_VALUE ( 0 ) + +/* Handle to the com port used by both tasks. */ +static xComPortHandle xPort = NULL; + +/* The transmit task as described at the top of the file. */ +static portTASK_FUNCTION_PROTO( vComTxTask, pvParameters ); + +/* The receive task as described at the top of the file. */ +static portTASK_FUNCTION_PROTO( vComRxTask, pvParameters ); + +/* The LED that should be toggled by the Rx and Tx tasks. The Rx task will +toggle LED ( uxBaseLED + comRX_LED_OFFSET). The Tx task will toggle LED +( uxBaseLED + comTX_LED_OFFSET ). */ +static UBaseType_t uxBaseLED = 0; + +/* Check variable used to ensure no error have occurred. The Rx task will +increment this variable after every successfully received sequence. If at any +time the sequence is incorrect the the variable will stop being incremented. */ +static volatile UBaseType_t uxRxLoops = comINITIAL_RX_COUNT_VALUE; + +/*-----------------------------------------------------------*/ + +void vAltStartComTestTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED ) +{ + /* Initialise the com port then spawn the Rx and Tx tasks. */ + uxBaseLED = uxLED; + xSerialPortInitMinimal( ulBaudRate, comBUFFER_LEN ); + + /* The Tx task is spawned with a lower priority than the Rx task. */ + xTaskCreate( vComTxTask, "COMTx", comSTACK_SIZE, NULL, uxPriority - 1, ( TaskHandle_t * ) NULL ); + xTaskCreate( vComRxTask, "COMRx", comSTACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vComTxTask, pvParameters ) +{ +char cByteToSend; +TickType_t xTimeToWait; + + /* Just to stop compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Simply transmit a sequence of characters from comFIRST_BYTE to + comLAST_BYTE. */ + for( cByteToSend = comFIRST_BYTE; cByteToSend <= comLAST_BYTE; cByteToSend++ ) + { + if( xSerialPutChar( xPort, cByteToSend, comNO_BLOCK ) == pdPASS ) + { + vParTestToggleLED( uxBaseLED + comTX_LED_OFFSET ); + } + } + + /* Turn the LED off while we are not doing anything. */ + vParTestSetLED( uxBaseLED + comTX_LED_OFFSET, pdFALSE ); + + /* We have posted all the characters in the string - wait before + re-sending. Wait a pseudo-random time as this will provide a better + test. */ + xTimeToWait = xTaskGetTickCount() + comOFFSET_TIME; + + /* Make sure we don't wait too long... */ + xTimeToWait %= comTX_MAX_BLOCK_TIME; + + /* ...but we do want to wait. */ + if( xTimeToWait < comTX_MIN_BLOCK_TIME ) + { + xTimeToWait = comTX_MIN_BLOCK_TIME; + } + + vTaskDelay( xTimeToWait ); + } +} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */ +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vComRxTask, pvParameters ) +{ +signed char cExpectedByte, cByteRxed; +BaseType_t xResyncRequired = pdFALSE, xErrorOccurred = pdFALSE; + + /* Just to stop compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* We expect to receive the characters from comFIRST_BYTE to + comLAST_BYTE in an incrementing order. Loop to receive each byte. */ + for( cExpectedByte = comFIRST_BYTE; cExpectedByte <= comLAST_BYTE; cExpectedByte++ ) + { + /* Block on the queue that contains received bytes until a byte is + available. */ + if( xSerialGetChar( xPort, &cByteRxed, comRX_BLOCK_TIME ) ) + { + /* Was this the byte we were expecting? If so, toggle the LED, + otherwise we are out on sync and should break out of the loop + until the expected character sequence is about to restart. */ + if( cByteRxed == cExpectedByte ) + { + vParTestToggleLED( uxBaseLED + comRX_LED_OFFSET ); + } + else + { + xResyncRequired = pdTRUE; + break; /*lint !e960 Non-switch break allowed. */ + } + } + } + + /* Turn the LED off while we are not doing anything. */ + vParTestSetLED( uxBaseLED + comRX_LED_OFFSET, pdFALSE ); + + /* Did we break out of the loop because the characters were received in + an unexpected order? If so wait here until the character sequence is + about to restart. */ + if( xResyncRequired == pdTRUE ) + { + while( cByteRxed != comLAST_BYTE ) + { + /* Block until the next char is available. */ + xSerialGetChar( xPort, &cByteRxed, comRX_BLOCK_TIME ); + } + + /* Note that an error occurred which caused us to have to resync. + We use this to stop incrementing the loop counter so + sAreComTestTasksStillRunning() will return false - indicating an + error. */ + xErrorOccurred++; + + /* We have now resynced with the Tx task and can continue. */ + xResyncRequired = pdFALSE; + } + else + { + if( xErrorOccurred < comTOTAL_PERMISSIBLE_ERRORS ) + { + /* Increment the count of successful loops. As error + occurring (i.e. an unexpected character being received) will + prevent this counter being incremented for the rest of the + execution. Don't worry about mutual exclusion on this + variable - it doesn't really matter as we just want it + to change. */ + uxRxLoops++; + } + } + } +} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */ +/*-----------------------------------------------------------*/ + +BaseType_t xAreComTestTasksStillRunning( void ) +{ +BaseType_t xReturn; + + /* If the count of successful reception loops has not changed than at + some time an error occurred (i.e. a character was received out of sequence) + and we will return false. */ + if( uxRxLoops == comINITIAL_RX_COUNT_VALUE ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + /* Reset the count of successful Rx loops. When this function is called + again we expect this to have been incremented. */ + uxRxLoops = comINITIAL_RX_COUNT_VALUE; + + return xReturn; +} + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest_strings.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest_strings.c new file mode 100644 index 0000000..0e84b12 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest_strings.c @@ -0,0 +1,349 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +/* + * Creates a task and a timer that operate on an interrupt driven serial port. + * This demo assumes that the characters transmitted on a port will also be + * received on the same port. Therefore, the UART must either be connected to + * an echo server, or the uart connector must have a loopback connector fitted. + * See http://www.serialporttool.com/CommEcho.htm for a suitable echo server + * for Windows hosts. + * + * The timer sends a string to the UART, toggles an LED, then resets itself by + * changing its own period. The period is calculated as a pseudo random number + * between comTX_MAX_BLOCK_TIME and comTX_MIN_BLOCK_TIME. + * + * The task blocks on an Rx queue waiting for a character to become available. + * Received characters are checked to ensure they match those transmitted by the + * Tx timer. An error is latched if characters are missing, incorrect, or + * arrive too slowly. + * + * How characters are actually transmitted and received is port specific. Demos + * that include this test/demo file will provide example drivers. The Tx timer + * executes in the context of the timer service (daemon) task, and must + * therefore never attempt to block. + * + */ + +/* Scheduler include files. */ +#include +#include +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" + +#ifndef configUSE_TIMERS + #error This demo uses timers. configUSE_TIMERS must be set to 1 in FreeRTOSConfig.h. +#endif + +#if configUSE_TIMERS != 1 + #error This demo uses timers. configUSE_TIMERS must be set to 1 in FreeRTOSConfig.h. +#endif + + +/* Demo program include files. */ +#include "serial.h" +#include "comtest_strings.h" +#include "partest.h" + +/* The size of the stack given to the Rx task. */ +#define comSTACK_SIZE configMINIMAL_STACK_SIZE + +/* See the comment above the declaraction of the uxBaseLED variable. */ +#define comTX_LED_OFFSET ( 0 ) +#define comRX_LED_OFFSET ( 1 ) + +/* The Tx timer transmits the sequence of characters at a pseudo random +interval that is capped between comTX_MAX_BLOCK_TIME and +comTX_MIN_BLOCK_TIME. */ +#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x96 ) +#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0x32 ) +#define comOFFSET_TIME ( ( TickType_t ) 3 ) + +/* States for the simple state machine implemented in the Rx task. */ +#define comtstWAITING_START_OF_STRING 0 +#define comtstWAITING_END_OF_STRING 1 + +/* A short delay in ticks - this delay is used to allow the Rx queue to fill up +a bit so more than one character can be processed at a time. This is relative +to comTX_MIN_BLOCK_TIME to ensure it is never longer than the shortest gap +between transmissions. It could be worked out more scientifically from the +baud rate being used. */ +#define comSHORT_DELAY ( comTX_MIN_BLOCK_TIME >> ( TickType_t ) 2 ) + +/* The string that is transmitted and received. */ +#define comTRANSACTED_STRING "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" + +/* A block time of 0 simply means "don't block". */ +#define comtstDONT_BLOCK ( TickType_t ) 0 + +/* Handle to the com port used by both tasks. */ +static xComPortHandle xPort = NULL; + +/* The callback function allocated to the transmit timer, as described in the +comments at the top of this file. */ +static void prvComTxTimerCallback( TimerHandle_t xTimer ); + +/* The receive task as described in the comments at the top of this file. */ +static void vComRxTask( void *pvParameters ); + +/* The Rx task will toggle LED ( uxBaseLED + comRX_LED_OFFSET). The Tx task +will toggle LED ( uxBaseLED + comTX_LED_OFFSET ). */ +static UBaseType_t uxBaseLED = 0; + +/* The Rx task toggles uxRxLoops on each successful iteration of its defined +function - provided no errors have ever been latched. If this variable stops +incrementing, then an error has occurred. */ +static volatile UBaseType_t uxRxLoops = 0UL; + +/* The timer used to periodically transmit the string. This is the timer that +has prvComTxTimerCallback allocated to it as its callback function. */ +static TimerHandle_t xTxTimer = NULL; + +/* The string length is held at file scope so the Tx timer does not need to +calculate it each time it executes. */ +static size_t xStringLength = 0U; + +/*-----------------------------------------------------------*/ + +void vStartComTestStringsTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED ) +{ + /* Store values that are used at run time. */ + uxBaseLED = uxLED; + + /* Calculate the string length here, rather than each time the Tx timer + executes. */ + xStringLength = strlen( comTRANSACTED_STRING ); + + /* Include the null terminator in the string length as this is used to + detect the end of the string in the Rx task. */ + xStringLength++; + + /* Initialise the com port, then spawn the Rx task and create the Tx + timer. */ + xSerialPortInitMinimal( ulBaudRate, ( xStringLength * 2U ) ); + + /* Create the Rx task and the Tx timer. The timer is started from the + Rx task. */ + xTaskCreate( vComRxTask, "COMRx", comSTACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL ); + xTxTimer = xTimerCreate( "TxTimer", comTX_MIN_BLOCK_TIME, pdFALSE, NULL, prvComTxTimerCallback ); + configASSERT( xTxTimer ); +} +/*-----------------------------------------------------------*/ + +static void prvComTxTimerCallback( TimerHandle_t xTimer ) +{ +TickType_t xTimeToWait; + + /* The parameter is not used in this case. */ + ( void ) xTimer; + + /* Send the string. How this is actually performed depends on the + sample driver provided with this demo. However - as this is a timer, + it executes in the context of the timer task and therefore must not + block. */ + vSerialPutString( xPort, comTRANSACTED_STRING, xStringLength ); + + /* Toggle an LED to give a visible indication that another transmission + has been performed. */ + vParTestToggleLED( uxBaseLED + comTX_LED_OFFSET ); + + /* Wait a pseudo random time before sending the string again. */ + xTimeToWait = xTaskGetTickCount() + comOFFSET_TIME; + + /* Ensure the time to wait is not greater than comTX_MAX_BLOCK_TIME. */ + xTimeToWait %= comTX_MAX_BLOCK_TIME; + + /* Ensure the time to wait is not less than comTX_MIN_BLOCK_TIME. */ + if( xTimeToWait < comTX_MIN_BLOCK_TIME ) + { + xTimeToWait = comTX_MIN_BLOCK_TIME; + } + + /* Reset the timer to run again xTimeToWait ticks from now. This function + is called from the context of the timer task, so the block time must not + be anything other than zero. */ + xTimerChangePeriod( xTxTimer, xTimeToWait, comtstDONT_BLOCK ); +} +/*-----------------------------------------------------------*/ + +static void vComRxTask( void *pvParameters ) +{ +BaseType_t xState = comtstWAITING_START_OF_STRING, xErrorOccurred = pdFALSE; +char *pcExpectedByte, cRxedChar; +const xComPortHandle xPort = NULL; + + /* The parameter is not used in this example. */ + ( void ) pvParameters; + + /* Start the Tx timer. This only needs to be started once, as it will + reset itself thereafter. */ + xTimerStart( xTxTimer, portMAX_DELAY ); + + /* The first expected Rx character is the first in the string that is + transmitted. */ + pcExpectedByte = comTRANSACTED_STRING; + + for( ;; ) + { + /* Wait for the next character. */ + if( xSerialGetChar( xPort, &cRxedChar, ( comTX_MAX_BLOCK_TIME * 2 ) ) == pdFALSE ) + { + /* A character definitely should have been received by now. As a + character was not received an error must have occurred (which might + just be that the loopback connector is not fitted). */ + xErrorOccurred = pdTRUE; + } + + switch( xState ) + { + case comtstWAITING_START_OF_STRING: + if( cRxedChar == *pcExpectedByte ) + { + /* The received character was the first character of the + string. Move to the next state to check each character + as it comes in until the entire string has been received. */ + xState = comtstWAITING_END_OF_STRING; + pcExpectedByte++; + + /* Block for a short period. This just allows the Rx queue + to contain more than one character, and therefore prevent + thrashing reads to the queue, and repetitive context + switches as each character is received. */ + vTaskDelay( comSHORT_DELAY ); + } + break; + + case comtstWAITING_END_OF_STRING: + if( cRxedChar == *pcExpectedByte ) + { + /* The received character was the expected character. Was + it the last character in the string - i.e. the null + terminator? */ + if( cRxedChar == 0x00 ) + { + /* The entire string has been received. If no errors + have been latched, then increment the loop counter to + show this task is still healthy. */ + if( xErrorOccurred == pdFALSE ) + { + uxRxLoops++; + + /* Toggle an LED to give a visible sign that a + complete string has been received. */ + vParTestToggleLED( uxBaseLED + comRX_LED_OFFSET ); + } + + /* Go back to wait for the start of the next string. */ + pcExpectedByte = comTRANSACTED_STRING; + xState = comtstWAITING_START_OF_STRING; + } + else + { + /* Wait for the next character in the string. */ + pcExpectedByte++; + } + } + else + { + /* The character received was not that expected. */ + xErrorOccurred = pdTRUE; + } + break; + + default: + /* Should not get here. Stop the Rx loop counter from + incrementing to latch the error. */ + xErrorOccurred = pdTRUE; + break; + } + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreComTestTasksStillRunning( void ) +{ +BaseType_t xReturn; + + /* If the count of successful reception loops has not changed than at + some time an error occurred (i.e. a character was received out of sequence) + and false is returned. */ + if( uxRxLoops == 0UL ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + /* Reset the count of successful Rx loops. When this function is called + again it should have been incremented again. */ + uxRxLoops = 0UL; + + return xReturn; +} + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/countsem.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/countsem.c new file mode 100644 index 0000000..aa33933 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/countsem.c @@ -0,0 +1,322 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +/* + * Simple demonstration of the usage of counting semaphore. + */ + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo program include files. */ +#include "countsem.h" + +/* The maximum count value that the semaphore used for the demo can hold. */ +#define countMAX_COUNT_VALUE ( 200 ) + +/* Constants used to indicate whether or not the semaphore should have been +created with its maximum count value, or its minimum count value. These +numbers are used to ensure that the pointers passed in as the task parameters +are valid. */ +#define countSTART_AT_MAX_COUNT ( 0xaa ) +#define countSTART_AT_ZERO ( 0x55 ) + +/* Two tasks are created for the test. One uses a semaphore created with its +count value set to the maximum, and one with the count value set to zero. */ +#define countNUM_TEST_TASKS ( 2 ) +#define countDONT_BLOCK ( 0 ) + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdTRUE should any unexpected behaviour be +detected in any of the tasks. */ +static volatile BaseType_t xErrorDetected = pdFALSE; + +/*-----------------------------------------------------------*/ + +/* + * The demo task. This simply counts the semaphore up to its maximum value, + * the counts it back down again. The result of each semaphore 'give' and + * 'take' is inspected, with an error being flagged if it is found not to be + * the expected result. + */ +static void prvCountingSemaphoreTask( void *pvParameters ); + +/* + * Utility function to increment the semaphore count value up from zero to + * countMAX_COUNT_VALUE. + */ +static void prvIncrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter ); + +/* + * Utility function to decrement the semaphore count value up from + * countMAX_COUNT_VALUE to zero. + */ +static void prvDecrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter ); + +/*-----------------------------------------------------------*/ + +/* The structure that is passed into the task as the task parameter. */ +typedef struct COUNT_SEM_STRUCT +{ + /* The semaphore to be used for the demo. */ + SemaphoreHandle_t xSemaphore; + + /* Set to countSTART_AT_MAX_COUNT if the semaphore should be created with + its count value set to its max count value, or countSTART_AT_ZERO if it + should have been created with its count value set to 0. */ + UBaseType_t uxExpectedStartCount; + + /* Incremented on each cycle of the demo task. Used to detect a stalled + task. */ + UBaseType_t uxLoopCounter; +} xCountSemStruct; + +/* Two structures are defined, one is passed to each test task. */ +static volatile xCountSemStruct xParameters[ countNUM_TEST_TASKS ]; + +/*-----------------------------------------------------------*/ + +void vStartCountingSemaphoreTasks( void ) +{ + /* Create the semaphores that we are going to use for the test/demo. The + first should be created such that it starts at its maximum count value, + the second should be created such that it starts with a count value of zero. */ + xParameters[ 0 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, countMAX_COUNT_VALUE ); + xParameters[ 0 ].uxExpectedStartCount = countSTART_AT_MAX_COUNT; + xParameters[ 0 ].uxLoopCounter = 0; + + xParameters[ 1 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, 0 ); + xParameters[ 1 ].uxExpectedStartCount = 0; + xParameters[ 1 ].uxLoopCounter = 0; + + /* vQueueAddToRegistry() adds the semaphore to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate semaphores and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( QueueHandle_t ) xParameters[ 0 ].xSemaphore, "Counting_Sem_1" ); + vQueueAddToRegistry( ( QueueHandle_t ) xParameters[ 1 ].xSemaphore, "Counting_Sem_2" ); + + + /* Were the semaphores created? */ + if( ( xParameters[ 0 ].xSemaphore != NULL ) || ( xParameters[ 1 ].xSemaphore != NULL ) ) + { + /* Create the demo tasks, passing in the semaphore to use as the parameter. */ + xTaskCreate( prvCountingSemaphoreTask, "CNT1", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 0 ] ), tskIDLE_PRIORITY, NULL ); + xTaskCreate( prvCountingSemaphoreTask, "CNT2", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 1 ] ), tskIDLE_PRIORITY, NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvDecrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter ) +{ +UBaseType_t ux; + + /* If the semaphore count is at its maximum then we should not be able to + 'give' the semaphore. */ + if( xSemaphoreGive( xSemaphore ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* We should be able to 'take' the semaphore countMAX_COUNT_VALUE times. */ + for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ ) + { + if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) != pdPASS ) + { + /* We expected to be able to take the semaphore. */ + xErrorDetected = pdTRUE; + } + + ( *puxLoopCounter )++; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the semaphore count is zero then we should not be able to 'take' + the semaphore. */ + if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +static void prvIncrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter ) +{ +UBaseType_t ux; + + /* If the semaphore count is zero then we should not be able to 'take' + the semaphore. */ + if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* We should be able to 'give' the semaphore countMAX_COUNT_VALUE times. */ + for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ ) + { + if( xSemaphoreGive( xSemaphore ) != pdPASS ) + { + /* We expected to be able to take the semaphore. */ + xErrorDetected = pdTRUE; + } + + ( *puxLoopCounter )++; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the semaphore count is at its maximum then we should not be able to + 'give' the semaphore. */ + if( xSemaphoreGive( xSemaphore ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +static void prvCountingSemaphoreTask( void *pvParameters ) +{ +xCountSemStruct *pxParameter; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Counting semaphore demo started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + /* The semaphore to be used was passed as the parameter. */ + pxParameter = ( xCountSemStruct * ) pvParameters; + + /* Did we expect to find the semaphore already at its max count value, or + at zero? */ + if( pxParameter->uxExpectedStartCount == countSTART_AT_MAX_COUNT ) + { + prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) ); + } + + /* Now we expect the semaphore count to be 0, so this time there is an + error if we can take the semaphore. */ + if( xSemaphoreTake( pxParameter->xSemaphore, 0 ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } + + for( ;; ) + { + prvIncrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) ); + prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) ); + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreCountingSemaphoreTasksStillRunning( void ) +{ +static UBaseType_t uxLastCount0 = 0, uxLastCount1 = 0; +BaseType_t xReturn = pdPASS; + + /* Return fail if any 'give' or 'take' did not result in the expected + behaviour. */ + if( xErrorDetected != pdFALSE ) + { + xReturn = pdFAIL; + } + + /* Return fail if either task is not still incrementing its loop counter. */ + if( uxLastCount0 == xParameters[ 0 ].uxLoopCounter ) + { + xReturn = pdFAIL; + } + else + { + uxLastCount0 = xParameters[ 0 ].uxLoopCounter; + } + + if( uxLastCount1 == xParameters[ 1 ].uxLoopCounter ) + { + xReturn = pdFAIL; + } + else + { + uxLastCount1 = xParameters[ 1 ].uxLoopCounter; + } + + return xReturn; +} + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crflash.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crflash.c new file mode 100644 index 0000000..4507f1c --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crflash.c @@ -0,0 +1,246 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * This demo application file demonstrates the use of queues to pass data + * between co-routines. + * + * N represents the number of 'fixed delay' co-routines that are created and + * is set during initialisation. + * + * N 'fixed delay' co-routines are created that just block for a fixed + * period then post the number of an LED onto a queue. Each such co-routine + * uses a different block period. A single 'flash' co-routine is also created + * that blocks on the same queue, waiting for the number of the next LED it + * should flash. Upon receiving a number it simply toggle the instructed LED + * then blocks on the queue once more. In this manner each LED from LED 0 to + * LED N-1 is caused to flash at a different rate. + * + * The 'fixed delay' co-routines are created with co-routine priority 0. The + * flash co-routine is created with co-routine priority 1. This means that + * the queue should never contain more than a single item. This is because + * posting to the queue will unblock the 'flash' co-routine, and as this has + * a priority greater than the tasks posting to the queue it is guaranteed to + * have emptied the queue and blocked once again before the queue can contain + * any more date. An error is indicated if an attempt to post data to the + * queue fails - indicating that the queue is already full. + * + */ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "croutine.h" +#include "queue.h" + +/* Demo application includes. */ +#include "partest.h" +#include "crflash.h" + +/* The queue should only need to be of length 1. See the description at the +top of the file. */ +#define crfQUEUE_LENGTH 1 + +#define crfFIXED_DELAY_PRIORITY 0 +#define crfFLASH_PRIORITY 1 + +/* Only one flash co-routine is created so the index is not significant. */ +#define crfFLASH_INDEX 0 + +/* Don't allow more than crfMAX_FLASH_TASKS 'fixed delay' co-routines to be +created. */ +#define crfMAX_FLASH_TASKS 8 + +/* We don't want to block when posting to the queue. */ +#define crfPOSTING_BLOCK_TIME 0 + +/* + * The 'fixed delay' co-routine as described at the top of the file. + */ +static void prvFixedDelayCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ); + +/* + * The 'flash' co-routine as described at the top of the file. + */ +static void prvFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ); + +/* The queue used to pass data between the 'fixed delay' co-routines and the +'flash' co-routine. */ +static QueueHandle_t xFlashQueue; + +/* This will be set to pdFALSE if we detect an error. */ +static BaseType_t xCoRoutineFlashStatus = pdPASS; + +/*-----------------------------------------------------------*/ + +/* + * See the header file for details. + */ +void vStartFlashCoRoutines( UBaseType_t uxNumberToCreate ) +{ +UBaseType_t uxIndex; + + if( uxNumberToCreate > crfMAX_FLASH_TASKS ) + { + uxNumberToCreate = crfMAX_FLASH_TASKS; + } + + /* Create the queue used to pass data between the co-routines. */ + xFlashQueue = xQueueCreate( crfQUEUE_LENGTH, sizeof( UBaseType_t ) ); + + if( xFlashQueue ) + { + /* Create uxNumberToCreate 'fixed delay' co-routines. */ + for( uxIndex = 0; uxIndex < uxNumberToCreate; uxIndex++ ) + { + xCoRoutineCreate( prvFixedDelayCoRoutine, crfFIXED_DELAY_PRIORITY, uxIndex ); + } + + /* Create the 'flash' co-routine. */ + xCoRoutineCreate( prvFlashCoRoutine, crfFLASH_PRIORITY, crfFLASH_INDEX ); + } +} +/*-----------------------------------------------------------*/ + +static void prvFixedDelayCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) +{ +/* Even though this is a co-routine the xResult variable does not need to be +static as we do not need it to maintain its state between blocks. */ +BaseType_t xResult; +/* The uxIndex parameter of the co-routine function is used as an index into +the xFlashRates array to obtain the delay period to use. */ +static const TickType_t xFlashRates[ crfMAX_FLASH_TASKS ] = { 150 / portTICK_PERIOD_MS, + 200 / portTICK_PERIOD_MS, + 250 / portTICK_PERIOD_MS, + 300 / portTICK_PERIOD_MS, + 350 / portTICK_PERIOD_MS, + 400 / portTICK_PERIOD_MS, + 450 / portTICK_PERIOD_MS, + 500 / portTICK_PERIOD_MS }; + + /* Co-routines MUST start with a call to crSTART. */ + crSTART( xHandle ); + + for( ;; ) + { + /* Post our uxIndex value onto the queue. This is used as the LED to + flash. */ + crQUEUE_SEND( xHandle, xFlashQueue, ( void * ) &uxIndex, crfPOSTING_BLOCK_TIME, &xResult ); + + if( xResult != pdPASS ) + { + /* For the reasons stated at the top of the file we should always + find that we can post to the queue. If we could not then an error + has occurred. */ + xCoRoutineFlashStatus = pdFAIL; + } + + crDELAY( xHandle, xFlashRates[ uxIndex ] ); + } + + /* Co-routines MUST end with a call to crEND. */ + crEND(); +} +/*-----------------------------------------------------------*/ + +static void prvFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) +{ +/* Even though this is a co-routine the variable do not need to be +static as we do not need it to maintain their state between blocks. */ +BaseType_t xResult; +UBaseType_t uxLEDToFlash; + + /* Co-routines MUST start with a call to crSTART. */ + crSTART( xHandle ); + ( void ) uxIndex; + + for( ;; ) + { + /* Block to wait for the number of the LED to flash. */ + crQUEUE_RECEIVE( xHandle, xFlashQueue, &uxLEDToFlash, portMAX_DELAY, &xResult ); + + if( xResult != pdPASS ) + { + /* We would not expect to wake unless we received something. */ + xCoRoutineFlashStatus = pdFAIL; + } + else + { + /* We received the number of an LED to flash - flash it! */ + vParTestToggleLED( uxLEDToFlash ); + } + } + + /* Co-routines MUST end with a call to crEND. */ + crEND(); +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreFlashCoRoutinesStillRunning( void ) +{ + /* Return pdPASS or pdFAIL depending on whether an error has been detected + or not. */ + return xCoRoutineFlashStatus; +} + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crhook.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crhook.c new file mode 100644 index 0000000..1e3a18e --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crhook.c @@ -0,0 +1,270 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * This demo file demonstrates how to send data between an ISR and a + * co-routine. A tick hook function is used to periodically pass data between + * the RTOS tick and a set of 'hook' co-routines. + * + * hookNUM_HOOK_CO_ROUTINES co-routines are created. Each co-routine blocks + * to wait for a character to be received on a queue from the tick ISR, checks + * to ensure the character received was that expected, then sends the number + * back to the tick ISR on a different queue. + * + * The tick ISR checks the numbers received back from the 'hook' co-routines + * matches the number previously sent. + * + * If at any time a queue function returns unexpectedly, or an incorrect value + * is received either by the tick hook or a co-routine then an error is + * latched. + * + * This demo relies on each 'hook' co-routine to execute between each + * hookTICK_CALLS_BEFORE_POST tick interrupts. This and the heavy use of + * queues from within an interrupt may result in an error being detected on + * slower targets simply due to timing. + */ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "croutine.h" +#include "queue.h" + +/* Demo application includes. */ +#include "crhook.h" + +/* The number of 'hook' co-routines that are to be created. */ +#define hookNUM_HOOK_CO_ROUTINES ( 4 ) + +/* The number of times the tick hook should be called before a character is +posted to the 'hook' co-routines. */ +#define hookTICK_CALLS_BEFORE_POST ( 500 ) + +/* There should never be more than one item in any queue at any time. */ +#define hookHOOK_QUEUE_LENGTH ( 1 ) + +/* Don't block when initially posting to the queue. */ +#define hookNO_BLOCK_TIME ( 0 ) + +/* The priority relative to other co-routines (rather than tasks) that the +'hook' co-routines should take. */ +#define mainHOOK_CR_PRIORITY ( 1 ) +/*-----------------------------------------------------------*/ + +/* + * The co-routine function itself. + */ +static void prvHookCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ); + + +/* + * The tick hook function. This receives a number from each 'hook' co-routine + * then sends a number to each co-routine. An error is flagged if a send or + * receive fails, or an unexpected number is received. + */ +void vApplicationTickHook( void ); + +/*-----------------------------------------------------------*/ + +/* Queues used to send data FROM a co-routine TO the tick hook function. +The hook functions received (Rx's) on these queues. One queue per +'hook' co-routine. */ +static QueueHandle_t xHookRxQueues[ hookNUM_HOOK_CO_ROUTINES ]; + +/* Queues used to send data FROM the tick hook TO a co-routine function. +The hood function transmits (Tx's) on these queues. One queue per +'hook' co-routine. */ +static QueueHandle_t xHookTxQueues[ hookNUM_HOOK_CO_ROUTINES ]; + +/* Set to true if an error is detected at any time. */ +static BaseType_t xCoRoutineErrorDetected = pdFALSE; + +/*-----------------------------------------------------------*/ + +void vStartHookCoRoutines( void ) +{ +UBaseType_t uxIndex, uxValueToPost = 0; + + for( uxIndex = 0; uxIndex < hookNUM_HOOK_CO_ROUTINES; uxIndex++ ) + { + /* Create a queue to transmit to and receive from each 'hook' + co-routine. */ + xHookRxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) ); + xHookTxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) ); + + /* To start things off the tick hook function expects the queue it + uses to receive data to contain a value. */ + xQueueSend( xHookRxQueues[ uxIndex ], &uxValueToPost, hookNO_BLOCK_TIME ); + + /* Create the 'hook' co-routine itself. */ + xCoRoutineCreate( prvHookCoRoutine, mainHOOK_CR_PRIORITY, uxIndex ); + } +} +/*-----------------------------------------------------------*/ + +static UBaseType_t uxCallCounter = 0, uxNumberToPost = 0; +void vApplicationTickHook( void ) +{ +UBaseType_t uxReceivedNumber; +BaseType_t xIndex, xCoRoutineWoken; + + /* Is it time to talk to the 'hook' co-routines again? */ + uxCallCounter++; + if( uxCallCounter >= hookTICK_CALLS_BEFORE_POST ) + { + uxCallCounter = 0; + + for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ ) + { + xCoRoutineWoken = pdFALSE; + if( crQUEUE_RECEIVE_FROM_ISR( xHookRxQueues[ xIndex ], &uxReceivedNumber, &xCoRoutineWoken ) != pdPASS ) + { + /* There is no reason why we would not expect the queue to + contain a value. */ + xCoRoutineErrorDetected = pdTRUE; + } + else + { + /* Each queue used to receive data from the 'hook' co-routines + should contain the number we last posted to the same co-routine. */ + if( uxReceivedNumber != uxNumberToPost ) + { + xCoRoutineErrorDetected = pdTRUE; + } + + /* Nothing should be blocked waiting to post to the queue. */ + if( xCoRoutineWoken != pdFALSE ) + { + xCoRoutineErrorDetected = pdTRUE; + } + } + } + + /* Start the next cycle by posting the next number onto each Tx queue. */ + uxNumberToPost++; + + for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ ) + { + if( crQUEUE_SEND_FROM_ISR( xHookTxQueues[ xIndex ], &uxNumberToPost, pdFALSE ) != pdTRUE ) + { + /* Posting to the queue should have woken the co-routine that + was blocked on the queue. */ + xCoRoutineErrorDetected = pdTRUE; + } + } + } +} +/*-----------------------------------------------------------*/ + +static void prvHookCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) +{ +static UBaseType_t uxReceivedValue[ hookNUM_HOOK_CO_ROUTINES ]; +BaseType_t xResult; + + /* Each co-routine MUST start with a call to crSTART(); */ + crSTART( xHandle ); + + for( ;; ) + { + /* Wait to receive a value from the tick hook. */ + xResult = pdFAIL; + crQUEUE_RECEIVE( xHandle, xHookTxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), portMAX_DELAY, &xResult ); + + /* There is no reason why we should not have received something on + the queue. */ + if( xResult != pdPASS ) + { + xCoRoutineErrorDetected = pdTRUE; + } + + /* Send the same number back to the idle hook so it can verify it. */ + xResult = pdFAIL; + crQUEUE_SEND( xHandle, xHookRxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), hookNO_BLOCK_TIME, &xResult ); + if( xResult != pdPASS ) + { + /* There is no reason why we should not have been able to post to + the queue. */ + xCoRoutineErrorDetected = pdTRUE; + } + } + + /* Each co-routine MUST end with a call to crEND(). */ + crEND(); +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreHookCoRoutinesStillRunning( void ) +{ + if( xCoRoutineErrorDetected ) + { + return pdFALSE; + } + else + { + return pdTRUE; + } +} + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/death.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/death.c new file mode 100644 index 0000000..d567971 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/death.c @@ -0,0 +1,254 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/** + * Create a single persistent task which periodically dynamically creates another + * two tasks. The original task is called the creator task, the two tasks it + * creates are called suicidal tasks. + * + * One of the created suicidal tasks kill one other suicidal task before killing + * itself - leaving just the original task remaining. + * + * The creator task must be spawned after all of the other demo application tasks + * as it keeps a check on the number of tasks under the scheduler control. The + * number of tasks it expects to see running should never be greater than the + * number of tasks that were in existence when the creator task was spawned, plus + * one set of four suicidal tasks. If this number is exceeded an error is flagged. + * + * \page DeathC death.c + * \ingroup DemoFiles + *
+ */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "death.h" + +#define deathSTACK_SIZE ( configMINIMAL_STACK_SIZE + 60 ) + +/* The task originally created which is responsible for periodically dynamically +creating another four tasks. */ +static portTASK_FUNCTION_PROTO( vCreateTasks, pvParameters ); + +/* The task function of the dynamically created tasks. */ +static portTASK_FUNCTION_PROTO( vSuicidalTask, pvParameters ); + +/* A variable which is incremented every time the dynamic tasks are created. This +is used to check that the task is still running. */ +static volatile uint16_t usCreationCount = 0; + +/* Used to store the number of tasks that were originally running so the creator +task can tell if any of the suicidal tasks have failed to die. +*/ +static volatile UBaseType_t uxTasksRunningAtStart = 0; + +/* Tasks are deleted by the idle task. Under heavy load the idle task might +not get much processing time, so it would be legitimate for several tasks to +remain undeleted for a short period. */ +static const UBaseType_t uxMaxNumberOfExtraTasksRunning = 3; + +/* Used to store a handle to the task that should be killed by a suicidal task, +before it kills itself. */ +TaskHandle_t xCreatedTask; + +/*-----------------------------------------------------------*/ + +void vCreateSuicidalTasks( UBaseType_t uxPriority ) +{ +UBaseType_t *puxPriority; + + /* Create the Creator tasks - passing in as a parameter the priority at which + the suicidal tasks should be created. */ + puxPriority = ( UBaseType_t * ) pvPortMalloc( sizeof( UBaseType_t ) ); + *puxPriority = uxPriority; + + 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 + suicidal tasks have failed to be killed. */ + uxTasksRunningAtStart = ( UBaseType_t ) uxTaskGetNumberOfTasks(); + + /* FreeRTOS.org versions before V3.0 started the idle-task as the very + first task. The idle task was then already included in uxTasksRunningAtStart. + From FreeRTOS V3.0 on, the idle task is started when the scheduler is + started. Therefore the idle task is not yet accounted for. We correct + this by increasing uxTasksRunningAtStart by 1. */ + uxTasksRunningAtStart++; + + /* From FreeRTOS version 7.0.0 can optionally create a timer service task. + If this is done, then uxTasksRunningAtStart needs incrementing again as that + too is created when the scheduler is started. */ + #if configUSE_TIMERS == 1 + uxTasksRunningAtStart++; + #endif +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vSuicidalTask, pvParameters ) +{ +volatile long l1, l2; +TaskHandle_t xTaskToKill; +const TickType_t xDelay = ( TickType_t ) 200 / portTICK_PERIOD_MS; + + if( pvParameters != NULL ) + { + /* This task is periodically created four times. Two created tasks are + passed a handle to the other task so it can kill it before killing itself. + The other task is passed in null. */ + xTaskToKill = *( TaskHandle_t* )pvParameters; + } + else + { + xTaskToKill = NULL; + } + + for( ;; ) + { + /* Do something random just to use some stack and registers. */ + l1 = 2; + l2 = 89; + l2 *= l1; + vTaskDelay( xDelay ); + + if( xTaskToKill != NULL ) + { + /* Make sure the other task has a go before we delete it. */ + vTaskDelay( ( TickType_t ) 0 ); + + /* Kill the other task that was created by vCreateTasks(). */ + vTaskDelete( xTaskToKill ); + + /* Kill ourselves. */ + vTaskDelete( NULL ); + } + } +}/*lint !e818 !e550 Function prototype must be as per standard for task functions. */ +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCreateTasks, pvParameters ) +{ +const TickType_t xDelay = ( TickType_t ) 1000 / portTICK_PERIOD_MS; +UBaseType_t uxPriority; + + uxPriority = *( UBaseType_t * ) pvParameters; + vPortFree( pvParameters ); + + for( ;; ) + { + /* Just loop round, delaying then creating the four suicidal tasks. */ + vTaskDelay( xDelay ); + + xCreatedTask = NULL; + + xTaskCreate( vSuicidalTask, "SUICID1", configMINIMAL_STACK_SIZE, NULL, uxPriority, &xCreatedTask ); + xTaskCreate( vSuicidalTask, "SUICID2", configMINIMAL_STACK_SIZE, &xCreatedTask, uxPriority, NULL ); + + ++usCreationCount; + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that the creator task is still running and that there +are not any more than four extra tasks. */ +BaseType_t xIsCreateTaskStillRunning( void ) +{ +static uint16_t usLastCreationCount = 0xfff; +BaseType_t xReturn = pdTRUE; +static UBaseType_t uxTasksRunningNow; + + if( usLastCreationCount == usCreationCount ) + { + xReturn = pdFALSE; + } + else + { + usLastCreationCount = usCreationCount; + } + + uxTasksRunningNow = ( UBaseType_t ) uxTaskGetNumberOfTasks(); + + if( uxTasksRunningNow < uxTasksRunningAtStart ) + { + xReturn = pdFALSE; + } + else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning ) + { + xReturn = pdFALSE; + } + else + { + /* Everything is okay. */ + } + + return xReturn; +} + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/dynamic.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/dynamic.c new file mode 100644 index 0000000..29ef3ef --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/dynamic.c @@ -0,0 +1,511 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * The first test creates three tasks - two counter tasks (one continuous count + * and one limited count) and one controller. A "count" variable is shared + * between all three tasks. The two counter tasks should never be in a "ready" + * state at the same time. The controller task runs at the same priority as + * the continuous count task, and at a lower priority than the limited count + * task. + * + * One counter task loops indefinitely, incrementing the shared count variable + * on each iteration. To ensure it has exclusive access to the variable it + * raises its priority above that of the controller task before each + * increment, lowering it again to its original priority before starting the + * next iteration. + * + * The other counter task increments the shared count variable on each + * iteration of its loop until the count has reached a limit of 0xff - at + * which point it suspends itself. It will not start a new loop until the + * controller task has made it "ready" again by calling vTaskResume(). + * This second counter task operates at a higher priority than controller + * task so does not need to worry about mutual exclusion of the counter + * variable. + * + * The controller task is in two sections. The first section controls and + * monitors the continuous count task. When this section is operational the + * limited count task is suspended. Likewise, the second section controls + * and monitors the limited count task. When this section is operational the + * continuous count task is suspended. + * + * In the first section the controller task first takes a copy of the shared + * count variable. To ensure mutual exclusion on the count variable it + * suspends the continuous count task, resuming it again when the copy has been + * taken. The controller task then sleeps for a fixed period - during which + * the continuous count task will execute and increment the shared variable. + * When the controller task wakes it checks that the continuous count task + * has executed by comparing the copy of the shared variable with its current + * value. This time, to ensure mutual exclusion, the scheduler itself is + * suspended with a call to vTaskSuspendAll (). This is for demonstration + * purposes only and is not a recommended technique due to its inefficiency. + * + * After a fixed number of iterations the controller task suspends the + * continuous count task, and moves on to its second section. + * + * At the start of the second section the shared variable is cleared to zero. + * The limited count task is then woken from its suspension by a call to + * vTaskResume (). As this counter task operates at a higher priority than + * the controller task the controller task should not run again until the + * shared variable has been counted up to the limited value causing the counter + * task to suspend itself. The next line after vTaskResume () is therefore + * a check on the shared variable to ensure everything is as expected. + * + * + * The second test consists of a couple of very simple tasks that post onto a + * queue while the scheduler is suspended. This test was added to test parts + * of the scheduler not exercised by the first test. + * + */ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "dynamic.h" + +/* Function that implements the "limited count" task as described above. */ +static portTASK_FUNCTION_PROTO( vLimitedIncrementTask, pvParameters ); + +/* Function that implements the "continuous count" task as described above. */ +static portTASK_FUNCTION_PROTO( vContinuousIncrementTask, pvParameters ); + +/* Function that implements the controller task as described above. */ +static portTASK_FUNCTION_PROTO( vCounterControlTask, pvParameters ); + +static portTASK_FUNCTION_PROTO( vQueueReceiveWhenSuspendedTask, pvParameters ); +static portTASK_FUNCTION_PROTO( vQueueSendWhenSuspendedTask, pvParameters ); + +/* Demo task specific constants. */ +#define priSTACK_SIZE ( configMINIMAL_STACK_SIZE ) +#define priSLEEP_TIME ( ( TickType_t ) 128 / portTICK_PERIOD_MS ) +#define priLOOPS ( 5 ) +#define priMAX_COUNT ( ( uint32_t ) 0xff ) +#define priNO_BLOCK ( ( TickType_t ) 0 ) +#define priSUSPENDED_QUEUE_LENGTH ( 1 ) + +/*-----------------------------------------------------------*/ + +/* Handles to the two counter tasks. These could be passed in as parameters +to the controller task to prevent them having to be file scope. */ +static TaskHandle_t xContinuousIncrementHandle, xLimitedIncrementHandle; + +/* The shared counter variable. This is passed in as a parameter to the two +counter variables for demonstration purposes. */ +static volatile uint32_t ulCounter; + +/* Variables used to check that the tasks are still operating without error. +Each complete iteration of the controller task increments this variable +provided no errors have been found. The variable maintaining the same value +is therefore indication of an error. */ +static volatile uint16_t usCheckVariable = ( uint16_t ) 0; +static volatile BaseType_t xSuspendedQueueSendError = pdFALSE; +static volatile BaseType_t xSuspendedQueueReceiveError = pdFALSE; + +/* Queue used by the second test. */ +QueueHandle_t xSuspendedTestQueue; + +/* The value the queue receive task expects to receive next. This is file +scope so xAreDynamicPriorityTasksStillRunning() can ensure it is still +incrementing. */ +static uint32_t ulExpectedValue = ( uint32_t ) 0; + +/*-----------------------------------------------------------*/ +/* + * Start the three tasks as described at the top of the file. + * Note that the limited count task is given a higher priority. + */ +void vStartDynamicPriorityTasks( void ) +{ + xSuspendedTestQueue = xQueueCreate( priSUSPENDED_QUEUE_LENGTH, sizeof( uint32_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xSuspendedTestQueue, "Suspended_Test_Queue" ); + + xTaskCreate( vContinuousIncrementTask, "CNT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinuousIncrementHandle ); + xTaskCreate( vLimitedIncrementTask, "LIM_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY + 1, &xLimitedIncrementHandle ); + xTaskCreate( vCounterControlTask, "C_CTRL", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vQueueSendWhenSuspendedTask, "SUSP_TX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vQueueReceiveWhenSuspendedTask, "SUSP_RX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); +} +/*-----------------------------------------------------------*/ + +/* + * Just loops around incrementing the shared variable until the limit has been + * reached. Once the limit has been reached it suspends itself. + */ +static portTASK_FUNCTION( vLimitedIncrementTask, pvParameters ) +{ +uint32_t *pulCounter; + + /* Take a pointer to the shared variable from the parameters passed into + the task. */ + pulCounter = ( uint32_t * ) pvParameters; + + /* This will run before the control task, so the first thing it does is + suspend - the control task will resume it when ready. */ + vTaskSuspend( NULL ); + + for( ;; ) + { + /* Just count up to a value then suspend. */ + ( *pulCounter )++; + + if( *pulCounter >= priMAX_COUNT ) + { + vTaskSuspend( NULL ); + } + } +} +/*-----------------------------------------------------------*/ + +/* + * Just keep counting the shared variable up. The control task will suspend + * this task when it wants. + */ +static portTASK_FUNCTION( vContinuousIncrementTask, pvParameters ) +{ +volatile uint32_t *pulCounter; +UBaseType_t uxOurPriority; + + /* Take a pointer to the shared variable from the parameters passed into + the task. */ + pulCounter = ( uint32_t * ) pvParameters; + + /* Query our priority so we can raise it when exclusive access to the + shared variable is required. */ + uxOurPriority = uxTaskPriorityGet( NULL ); + + for( ;; ) + { + /* Raise the priority above the controller task to ensure a context + switch does not occur while the variable is being accessed. */ + vTaskPrioritySet( NULL, uxOurPriority + 1 ); + { + configASSERT( ( uxTaskPriorityGet( NULL ) == ( uxOurPriority + 1 ) ) ); + ( *pulCounter )++; + } + vTaskPrioritySet( NULL, uxOurPriority ); + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + + configASSERT( ( uxTaskPriorityGet( NULL ) == uxOurPriority ) ); + } +} +/*-----------------------------------------------------------*/ + +/* + * Controller task as described above. + */ +static portTASK_FUNCTION( vCounterControlTask, pvParameters ) +{ +uint32_t ulLastCounter; +short sLoops; +short sError = pdFALSE; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Start with the counter at zero. */ + ulCounter = ( uint32_t ) 0; + + /* First section : */ + + /* Check the continuous count task is running. */ + for( sLoops = 0; sLoops < priLOOPS; sLoops++ ) + { + /* Suspend the continuous count task so we can take a mirror of the + shared variable without risk of corruption. This is not really + needed as the other task raises its priority above this task's + priority. */ + vTaskSuspend( xContinuousIncrementHandle ); + { + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xContinuousIncrementHandle ) == eSuspended ); + } + #endif /* INCLUDE_eTaskGetState */ + + ulLastCounter = ulCounter; + } + vTaskResume( xContinuousIncrementHandle ); + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xContinuousIncrementHandle ) == eReady ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* Now delay to ensure the other task has processor time. */ + vTaskDelay( priSLEEP_TIME ); + + /* Check the shared variable again. This time to ensure mutual + exclusion the whole scheduler will be locked. This is just for + demo purposes! */ + vTaskSuspendAll(); + { + if( ulLastCounter == ulCounter ) + { + /* The shared variable has not changed. There is a problem + with the continuous count task so flag an error. */ + sError = pdTRUE; + } + } + xTaskResumeAll(); + } + + /* Second section: */ + + /* Suspend the continuous counter task so it stops accessing the shared + variable. */ + vTaskSuspend( xContinuousIncrementHandle ); + + /* Reset the variable. */ + ulCounter = ( uint32_t ) 0; + + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xLimitedIncrementHandle ) == eSuspended ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* Resume the limited count task which has a higher priority than us. + We should therefore not return from this call until the limited count + task has suspended itself with a known value in the counter variable. */ + vTaskResume( xLimitedIncrementHandle ); + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + + /* This task should not run again until xLimitedIncrementHandle has + suspended itself. */ + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xLimitedIncrementHandle ) == eSuspended ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* Does the counter variable have the expected value? */ + if( ulCounter != priMAX_COUNT ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If no errors have occurred then increment the check variable. */ + portENTER_CRITICAL(); + usCheckVariable++; + portEXIT_CRITICAL(); + } + + /* Resume the continuous count task and do it all again. */ + vTaskResume( xContinuousIncrementHandle ); + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vQueueSendWhenSuspendedTask, pvParameters ) +{ +static uint32_t ulValueToSend = ( uint32_t ) 0; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + for( ;; ) + { + vTaskSuspendAll(); + { + /* We must not block while the scheduler is suspended! */ + if( xQueueSend( xSuspendedTestQueue, ( void * ) &ulValueToSend, priNO_BLOCK ) != pdTRUE ) + { + xSuspendedQueueSendError = pdTRUE; + } + } + xTaskResumeAll(); + + vTaskDelay( priSLEEP_TIME ); + + ++ulValueToSend; + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vQueueReceiveWhenSuspendedTask, pvParameters ) +{ +uint32_t ulReceivedValue; +BaseType_t xGotValue; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + for( ;; ) + { + do + { + /* Suspending the scheduler here is fairly pointless and + undesirable for a normal application. It is done here purely + to test the scheduler. The inner xTaskResumeAll() should + never return pdTRUE as the scheduler is still locked by the + outer call. */ + vTaskSuspendAll(); + { + vTaskSuspendAll(); + { + xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK ); + } + if( xTaskResumeAll() != pdFALSE ) + { + xSuspendedQueueReceiveError = pdTRUE; + } + } + xTaskResumeAll(); + + #if configUSE_PREEMPTION == 0 + { + taskYIELD(); + } + #endif + + } while( xGotValue == pdFALSE ); + + if( ulReceivedValue != ulExpectedValue ) + { + xSuspendedQueueReceiveError = pdTRUE; + } + + if( xSuspendedQueueReceiveError != pdTRUE ) + { + /* Only increment the variable if an error has not occurred. This + allows xAreDynamicPriorityTasksStillRunning() to check for stalled + tasks as well as explicit errors. */ + ++ulExpectedValue; + } + } +} +/*-----------------------------------------------------------*/ + +/* Called to check that all the created tasks are still running without error. */ +BaseType_t xAreDynamicPriorityTasksStillRunning( void ) +{ +/* Keep a history of the check variables so we know if it has been incremented +since the last call. */ +static uint16_t usLastTaskCheck = ( uint16_t ) 0; +static uint32_t ulLastExpectedValue = ( uint32_t ) 0U; +BaseType_t xReturn = pdTRUE; + + /* Check the tasks are still running by ensuring the check variable + is still incrementing. */ + + if( usCheckVariable == usLastTaskCheck ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + if( ulExpectedValue == ulLastExpectedValue ) + { + /* The value being received by the queue receive task has not + incremented so an error exists. */ + xReturn = pdFALSE; + } + + if( xSuspendedQueueSendError == pdTRUE ) + { + xReturn = pdFALSE; + } + + if( xSuspendedQueueReceiveError == pdTRUE ) + { + xReturn = pdFALSE; + } + + usLastTaskCheck = usCheckVariable; + ulLastExpectedValue = ulExpectedValue; + + return xReturn; +} diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash.c new file mode 100644 index 0000000..8689707 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash.c @@ -0,0 +1,157 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/** + * This version of flash .c is for use on systems that have limited stack space + * and no display facilities. The complete version can be found in the + * Demo/Common/Full directory. + * + * Three tasks are created, each of which flash an LED at a different rate. The first + * LED flashes every 200ms, the second every 400ms, the third every 600ms. + * + * The LED flash tasks provide instant visual feedback. They show that the scheduler + * is still operational. + * + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "partest.h" +#include "flash.h" + +#define ledSTACK_SIZE configMINIMAL_STACK_SIZE +#define ledNUMBER_OF_LEDS ( 3 ) +#define ledFLASH_RATE_BASE ( ( TickType_t ) 333 ) + +/* Variable used by the created tasks to calculate the LED number to use, and +the rate at which they should flash the LED. */ +static volatile UBaseType_t uxFlashTaskNumber = 0; + +/* The task that is created three times. */ +static portTASK_FUNCTION_PROTO( vLEDFlashTask, pvParameters ); + +/*-----------------------------------------------------------*/ + +void vStartLEDFlashTasks( UBaseType_t uxPriority ) +{ +BaseType_t xLEDTask; + + /* Create the three tasks. */ + for( xLEDTask = 0; xLEDTask < ledNUMBER_OF_LEDS; ++xLEDTask ) + { + /* Spawn the task. */ + xTaskCreate( vLEDFlashTask, "LEDx", ledSTACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL ); + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vLEDFlashTask, pvParameters ) +{ +TickType_t xFlashRate, xLastFlashTime; +UBaseType_t uxLED; + + /* The parameters are not used. */ + ( void ) pvParameters; + + /* Calculate the LED and flash rate. */ + portENTER_CRITICAL(); + { + /* See which of the eight LED's we should use. */ + uxLED = uxFlashTaskNumber; + + /* Update so the next task uses the next LED. */ + uxFlashTaskNumber++; + } + portEXIT_CRITICAL(); + + xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( TickType_t ) uxLED ); + xFlashRate /= portTICK_PERIOD_MS; + + /* We will turn the LED on and off again in the delay period, so each + delay is only half the total period. */ + xFlashRate /= ( TickType_t ) 2; + + /* We need to initialise xLastFlashTime prior to the first call to + vTaskDelayUntil(). */ + xLastFlashTime = xTaskGetTickCount(); + + for(;;) + { + /* Delay for half the flash period then turn the LED on. */ + vTaskDelayUntil( &xLastFlashTime, xFlashRate ); + vParTestToggleLED( uxLED ); + + /* Delay for half the flash period then turn the LED off. */ + vTaskDelayUntil( &xLastFlashTime, xFlashRate ); + vParTestToggleLED( uxLED ); + } +} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */ + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash_timer.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash_timer.c new file mode 100644 index 0000000..b54a866 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash_timer.c @@ -0,0 +1,136 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/** + * Repeatedly toggles one or more LEDs using software timers - one timer per + * LED. + */ + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "timers.h" + +/* Demo program include files. */ +#include "partest.h" +#include "flash_timer.h" + +/* The toggle rates are all a multple of ledFLASH_RATE_BASE. */ +#define ledFLASH_RATE_BASE ( ( ( TickType_t ) 333 ) / portTICK_PERIOD_MS ) + +/* A block time of zero simple means "don't block". */ +#define ledDONT_BLOCK ( ( TickType_t ) 0 ) + +/*-----------------------------------------------------------*/ + +/* + * The callback function used by each LED flashing timer. All the timers use + * this function, and the timer ID is used within the function to determine + * which timer has actually expired. + */ +static void prvLEDTimerCallback( TimerHandle_t xTimer ); + +/*-----------------------------------------------------------*/ + +void vStartLEDFlashTimers( UBaseType_t uxNumberOfLEDs ) +{ +UBaseType_t uxLEDTimer; +TimerHandle_t xTimer; + + /* Create and start the requested number of timers. */ + for( uxLEDTimer = 0; uxLEDTimer < uxNumberOfLEDs; ++uxLEDTimer ) + { + /* Create the timer. */ + xTimer = xTimerCreate( "Flasher", /* A text name, purely to help debugging. */ + ledFLASH_RATE_BASE * ( uxLEDTimer + 1 ),/* The timer period, which is a multiple of ledFLASH_RATE_BASE. */ + pdTRUE, /* This is an auto-reload timer, so xAutoReload is set to pdTRUE. */ + ( void * ) uxLEDTimer, /* The ID is used to identify the timer within the timer callback function, as each timer uses the same callback. */ + prvLEDTimerCallback /* Each timer uses the same callback. */ + ); + + /* If the timer was created successfully, attempt to start it. If the + scheduler has not yet been started then the timer command queue must + be long enough to hold each command sent to it until such time that the + scheduler is started. The timer command queue length is set by + configTIMER_QUEUE_LENGTH in FreeRTOSConfig.h. */ + if( xTimer != NULL ) + { + xTimerStart( xTimer, ledDONT_BLOCK ); + } + } +} +/*-----------------------------------------------------------*/ + +static void prvLEDTimerCallback( TimerHandle_t xTimer ) +{ +BaseType_t xTimerID; + + /* The timer ID is used to identify the timer that has actually expired as + each timer uses the same callback. The ID is then also used as the number + of the LED that is to be toggled. */ + xTimerID = ( BaseType_t ) pvTimerGetTimerID( xTimer ); + vParTestToggleLED( xTimerID ); +} + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flop.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flop.c new file mode 100644 index 0000000..438cf02 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flop.c @@ -0,0 +1,383 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * Creates eight tasks, each of which loops continuously performing a floating + * point calculation. + * + * All the tasks run at the idle priority and never block or yield. This causes + * all eight tasks to time slice with the idle task. Running at the idle + * priority means that these tasks will get pre-empted any time another task is + * ready to run or a time slice occurs. More often than not the pre-emption + * will occur mid calculation, creating a good test of the schedulers context + * switch mechanism - a calculation producing an unexpected result could be a + * symptom of a corruption in the context of a task. + */ + +#include +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "flop.h" + +#define mathSTACK_SIZE configMINIMAL_STACK_SIZE +#define mathNUMBER_OF_TASKS ( 4 ) + +/* Four tasks, each of which performs a different floating point calculation. +Each of the four is created twice. */ +static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters ); + +/* These variables are used to check that all the tasks are still running. If a +task gets a calculation wrong it will stop setting its check variable. */ +static volatile uint16_t usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartMathTasks( UBaseType_t uxPriority ) +{ + xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask1, pvParameters ) +{ +volatile portDOUBLE d1, d2, d3, d4; +volatile uint16_t *pusTaskCheckVariable; +volatile portDOUBLE dAnswer; +short sError = pdFALSE; + + /* Some ports require that tasks that use a hardware floating point unit + tell the kernel that they require a floating point context before any + floating point instructions are executed. */ + portTASK_USES_FLOATING_POINT(); + + d1 = 123.4567; + d2 = 2345.6789; + d3 = -918.222; + + dAnswer = ( d1 + d2 ) * d3; + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for(;;) + { + d1 = 123.4567; + d2 = 2345.6789; + d3 = -918.222; + + d4 = ( d1 + d2 ) * d3; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( d4 - dAnswer ) > 0.001 ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct then set set the check + variable. The check variable will get set to pdFALSE each time + xAreMathsTaskStillRunning() is executed. */ + ( *pusTaskCheckVariable ) = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask2, pvParameters ) +{ +volatile portDOUBLE d1, d2, d3, d4; +volatile uint16_t *pusTaskCheckVariable; +volatile portDOUBLE dAnswer; +short sError = pdFALSE; + + /* Some ports require that tasks that use a hardware floating point unit + tell the kernel that they require a floating point context before any + floating point instructions are executed. */ + portTASK_USES_FLOATING_POINT(); + + d1 = -389.38; + d2 = 32498.2; + d3 = -2.0001; + + dAnswer = ( d1 / d2 ) * d3; + + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for( ;; ) + { + d1 = -389.38; + d2 = 32498.2; + d3 = -2.0001; + + d4 = ( d1 / d2 ) * d3; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( d4 - dAnswer ) > 0.001 ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct then set set the check + variable. The check variable will get set to pdFALSE each time + xAreMathsTaskStillRunning() is executed. */ + ( *pusTaskCheckVariable ) = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask3, pvParameters ) +{ +volatile portDOUBLE *pdArray, dTotal1, dTotal2, dDifference; +volatile uint16_t *pusTaskCheckVariable; +const size_t xArraySize = 10; +size_t xPosition; +short sError = pdFALSE; + + /* Some ports require that tasks that use a hardware floating point unit + tell the kernel that they require a floating point context before any + floating point instructions are executed. */ + portTASK_USES_FLOATING_POINT(); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + dTotal1 = 0.0; + dTotal2 = 0.0; + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + pdArray[ xPosition ] = ( portDOUBLE ) xPosition + 5.5; + dTotal1 += ( portDOUBLE ) xPosition + 5.5; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + dTotal2 += pdArray[ xPosition ]; + } + + dDifference = dTotal1 - dTotal2; + if( fabs( dDifference ) > 0.001 ) + { + sError = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct then set set the check + variable. The check variable will get set to pdFALSE each time + xAreMathsTaskStillRunning() is executed. */ + ( *pusTaskCheckVariable ) = pdTRUE; + } + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask4, pvParameters ) +{ +volatile portDOUBLE *pdArray, dTotal1, dTotal2, dDifference; +volatile uint16_t *pusTaskCheckVariable; +const size_t xArraySize = 10; +size_t xPosition; +short sError = pdFALSE; + + /* Some ports require that tasks that use a hardware floating point unit + tell the kernel that they require a floating point context before any + floating point instructions are executed. */ + portTASK_USES_FLOATING_POINT(); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + dTotal1 = 0.0; + dTotal2 = 0.0; + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + pdArray[ xPosition ] = ( portDOUBLE ) xPosition * 12.123; + dTotal1 += ( portDOUBLE ) xPosition * 12.123; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + dTotal2 += pdArray[ xPosition ]; + } + + dDifference = dTotal1 - dTotal2; + if( fabs( dDifference ) > 0.001 ) + { + sError = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct then set set the check + variable. The check variable will get set to pdFALSE each time + xAreMathsTaskStillRunning() is executed. */ + ( *pusTaskCheckVariable ) = pdTRUE; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreMathsTaskStillRunning( void ) +{ +BaseType_t xReturn = pdPASS, xTask; + + /* Check the maths tasks are still running by ensuring their check variables + have been set to pdPASS. */ + for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ ) + { + if( usTaskCheck[ xTask ] != pdTRUE ) + { + /* The check has not been set so the associated task has either + stalled or detected an error. */ + xReturn = pdFAIL; + } + else + { + /* Reset the variable so it can be checked again the next time this + function is executed. */ + usTaskCheck[ xTask ] = pdFALSE; + } + } + + return xReturn; +} + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/integer.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/integer.c new file mode 100644 index 0000000..a276613 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/integer.c @@ -0,0 +1,201 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * Creates one or more tasks that repeatedly perform a set of integer + * calculations. The result of each run-time calculation is compared to the + * known expected result - with a mismatch being indicative of an error in the + * context switch mechanism. + */ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "integer.h" + +/* The constants used in the calculation. */ +#define intgCONST1 ( ( long ) 123 ) +#define intgCONST2 ( ( long ) 234567 ) +#define intgCONST3 ( ( long ) -3 ) +#define intgCONST4 ( ( long ) 7 ) +#define intgEXPECTED_ANSWER ( ( ( intgCONST1 + intgCONST2 ) * intgCONST3 ) / intgCONST4 ) + +#define intgSTACK_SIZE configMINIMAL_STACK_SIZE + +/* As this is the minimal version, we will only create one task. */ +#define intgNUMBER_OF_TASKS ( 1 ) + +/* The task function. Repeatedly performs a 32 bit calculation, checking the +result against the expected result. If the result is incorrect then the +context switch must have caused some corruption. */ +static portTASK_FUNCTION_PROTO( vCompeteingIntMathTask, pvParameters ); + +/* Variables that are set to true within the calculation task to indicate +that the task is still executing. The check task sets the variable back to +false, flagging an error if the variable is still false the next time it +is called. */ +static volatile BaseType_t xTaskCheck[ intgNUMBER_OF_TASKS ] = { ( BaseType_t ) pdFALSE }; + +/*-----------------------------------------------------------*/ + +void vStartIntegerMathTasks( UBaseType_t uxPriority ) +{ +short sTask; + + for( sTask = 0; sTask < intgNUMBER_OF_TASKS; sTask++ ) + { + xTaskCreate( vCompeteingIntMathTask, "IntMath", intgSTACK_SIZE, ( void * ) &( xTaskCheck[ sTask ] ), uxPriority, ( TaskHandle_t * ) NULL ); + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompeteingIntMathTask, pvParameters ) +{ +/* These variables are all effectively set to constants so they are volatile to +ensure the compiler does not just get rid of them. */ +volatile long lValue; +short sError = pdFALSE; +volatile BaseType_t *pxTaskHasExecuted; + + /* Set a pointer to the variable we are going to set to true each + iteration. This is also a good test of the parameter passing mechanism + within each port. */ + pxTaskHasExecuted = ( volatile BaseType_t * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for( ;; ) + { + /* Perform the calculation. This will store partial value in + registers, resulting in a good test of the context switch mechanism. */ + lValue = intgCONST1; + lValue += intgCONST2; + + /* Yield in case cooperative scheduling is being used. */ + #if configUSE_PREEMPTION == 0 + { + taskYIELD(); + } + #endif + + /* Finish off the calculation. */ + lValue *= intgCONST3; + lValue /= intgCONST4; + + /* If the calculation is found to be incorrect we stop setting the + TaskHasExecuted variable so the check task can see an error has + occurred. */ + if( lValue != intgEXPECTED_ANSWER ) /*lint !e774 volatile used to prevent this being optimised out. */ + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* We have not encountered any errors, so set the flag that show + we are still executing. This will be periodically cleared by + the check task. */ + portENTER_CRITICAL(); + *pxTaskHasExecuted = pdTRUE; + portEXIT_CRITICAL(); + } + + /* Yield in case cooperative scheduling is being used. */ + #if configUSE_PREEMPTION == 0 + { + taskYIELD(); + } + #endif + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreIntegerMathsTaskStillRunning( void ) +{ +BaseType_t xReturn = pdTRUE; +short sTask; + + /* Check the maths tasks are still running by ensuring their check variables + are still being set to true. */ + for( sTask = 0; sTask < intgNUMBER_OF_TASKS; sTask++ ) + { + if( xTaskCheck[ sTask ] == pdFALSE ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + /* Reset the check variable so we can tell if it has been set by + the next time around. */ + xTaskCheck[ sTask ] = pdFALSE; + } + + return xReturn; +} + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/recmutex.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/recmutex.c new file mode 100644 index 0000000..69a6f9d --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/recmutex.c @@ -0,0 +1,440 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + The tasks defined on this page demonstrate the use of recursive mutexes. + + For recursive mutex functionality the created mutex should be created using + xSemaphoreCreateRecursiveMutex(), then be manipulated + using the xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() API + functions. + + This demo creates three tasks all of which access the same recursive mutex: + + prvRecursiveMutexControllingTask() has the highest priority so executes + first and grabs the mutex. It then performs some recursive accesses - + between each of which it sleeps for a short period to let the lower + priority tasks execute. When it has completed its demo functionality + it gives the mutex back before suspending itself. + + prvRecursiveMutexBlockingTask() attempts to access the mutex by performing + a blocking 'take'. The blocking task has a lower priority than the + controlling task so by the time it executes the mutex has already been + taken by the controlling task, causing the blocking task to block. It + does not unblock until the controlling task has given the mutex back, + and it does not actually run until the controlling task has suspended + itself (due to the relative priorities). When it eventually does obtain + the mutex all it does is give the mutex back prior to also suspending + itself. At this point both the controlling task and the blocking task are + suspended. + + prvRecursiveMutexPollingTask() runs at the idle priority. It spins round + a tight loop attempting to obtain the mutex with a non-blocking call. As + the lowest priority task it will not successfully obtain the mutex until + both the controlling and blocking tasks are suspended. Once it eventually + does obtain the mutex it first unsuspends both the controlling task and + blocking task prior to giving the mutex back - resulting in the polling + task temporarily inheriting the controlling tasks priority. +*/ + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "recmutex.h" + +/* Priorities assigned to the three tasks. recmuCONTROLLING_TASK_PRIORITY can +be overridden by a definition in FreeRTOSConfig.h. */ +#ifndef recmuCONTROLLING_TASK_PRIORITY + #define recmuCONTROLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#endif +#define recmuBLOCKING_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define recmuPOLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 0 ) + +/* The recursive call depth. */ +#define recmuMAX_COUNT ( 10 ) + +/* Misc. */ +#define recmuSHORT_DELAY ( 20 / portTICK_PERIOD_MS ) +#define recmuNO_DELAY ( ( TickType_t ) 0 ) +#define recmuEIGHT_TICK_DELAY ( ( TickType_t ) 8 ) + +/* The three tasks as described at the top of this file. */ +static void prvRecursiveMutexControllingTask( void *pvParameters ); +static void prvRecursiveMutexBlockingTask( void *pvParameters ); +static void prvRecursiveMutexPollingTask( void *pvParameters ); + +/* The mutex used by the demo. */ +static SemaphoreHandle_t xMutex; + +/* Variables used to detect and latch errors. */ +static volatile BaseType_t xErrorOccurred = pdFALSE, xControllingIsSuspended = pdFALSE, xBlockingIsSuspended = pdFALSE; +static volatile UBaseType_t uxControllingCycles = 0, uxBlockingCycles = 0, uxPollingCycles = 0; + +/* Handles of the two higher priority tasks, required so they can be resumed +(unsuspended). */ +static TaskHandle_t xControllingTaskHandle, xBlockingTaskHandle; + +/*-----------------------------------------------------------*/ + +void vStartRecursiveMutexTasks( void ) +{ + /* Just creates the mutex and the three tasks. */ + + xMutex = xSemaphoreCreateRecursiveMutex(); + + /* vQueueAddToRegistry() adds the mutex to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate mutex and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Recursive_Mutex" ); + + + if( xMutex != NULL ) + { + xTaskCreate( prvRecursiveMutexControllingTask, "Rec1", configMINIMAL_STACK_SIZE, NULL, recmuCONTROLLING_TASK_PRIORITY, &xControllingTaskHandle ); + xTaskCreate( prvRecursiveMutexBlockingTask, "Rec2", configMINIMAL_STACK_SIZE, NULL, recmuBLOCKING_TASK_PRIORITY, &xBlockingTaskHandle ); + xTaskCreate( prvRecursiveMutexPollingTask, "Rec3", configMINIMAL_STACK_SIZE, NULL, recmuPOLLING_TASK_PRIORITY, NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvRecursiveMutexControllingTask( void *pvParameters ) +{ +UBaseType_t ux; + + /* Just to remove compiler warning. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Should not be able to 'give' the mutex, as we have not yet 'taken' + it. The first time through, the mutex will not have been used yet, + subsequent times through, at this point the mutex will be held by the + polling task. */ + if( xSemaphoreGiveRecursive( xMutex ) == pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + for( ux = 0; ux < recmuMAX_COUNT; ux++ ) + { + /* We should now be able to take the mutex as many times as + we like. + + The first time through the mutex will be immediately available, on + subsequent times through the mutex will be held by the polling task + at this point and this Take will cause the polling task to inherit + the priority of this task. In this case the block time must be + long enough to ensure the polling task will execute again before the + block time expires. If the block time does expire then the error + flag will be set here. */ + if( xSemaphoreTakeRecursive( xMutex, recmuEIGHT_TICK_DELAY ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Ensure the other task attempting to access the mutex (and the + other demo tasks) are able to execute to ensure they either block + (where a block time is specified) or return an error (where no + block time is specified) as the mutex is held by this task. */ + vTaskDelay( recmuSHORT_DELAY ); + } + + /* For each time we took the mutex, give it back. */ + for( ux = 0; ux < recmuMAX_COUNT; ux++ ) + { + /* Ensure the other task attempting to access the mutex (and the + other demo tasks) are able to execute. */ + vTaskDelay( recmuSHORT_DELAY ); + + /* We should now be able to give the mutex as many times as we + took it. When the mutex is available again the Blocking task + should be unblocked but not run because it has a lower priority + than this task. The polling task should also not run at this point + as it too has a lower priority than this task. */ + if( xSemaphoreGiveRecursive( xMutex ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + } + + /* Having given it back the same number of times as it was taken, we + should no longer be the mutex owner, so the next give should fail. */ + if( xSemaphoreGiveRecursive( xMutex ) == pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Keep count of the number of cycles this task has performed so a + stall can be detected. */ + uxControllingCycles++; + + /* Suspend ourselves so the blocking task can execute. */ + xControllingIsSuspended = pdTRUE; + vTaskSuspend( NULL ); + xControllingIsSuspended = pdFALSE; + } +} +/*-----------------------------------------------------------*/ + +static void prvRecursiveMutexBlockingTask( void *pvParameters ) +{ + /* Just to remove compiler warning. */ + ( void ) pvParameters; + + for( ;; ) + { + /* This task will run while the controlling task is blocked, and the + controlling task will block only once it has the mutex - therefore + this call should block until the controlling task has given up the + mutex, and not actually execute past this call until the controlling + task is suspended. portMAX_DELAY - 1 is used instead of portMAX_DELAY + to ensure the task's state is reported as Blocked and not Suspended in + a later call to configASSERT() (within the polling task). */ + if( xSemaphoreTakeRecursive( xMutex, ( portMAX_DELAY - 1 ) ) == pdPASS ) + { + if( xControllingIsSuspended != pdTRUE ) + { + /* Did not expect to execute until the controlling task was + suspended. */ + xErrorOccurred = pdTRUE; + } + else + { + /* Give the mutex back before suspending ourselves to allow + the polling task to obtain the mutex. */ + if( xSemaphoreGiveRecursive( xMutex ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + xBlockingIsSuspended = pdTRUE; + vTaskSuspend( NULL ); + xBlockingIsSuspended = pdFALSE; + } + } + else + { + /* We should not leave the xSemaphoreTakeRecursive() function + until the mutex was obtained. */ + xErrorOccurred = pdTRUE; + } + + /* The controlling and blocking tasks should be in lock step. */ + if( uxControllingCycles != ( uxBlockingCycles + 1 ) ) + { + xErrorOccurred = pdTRUE; + } + + /* Keep count of the number of cycles this task has performed so a + stall can be detected. */ + uxBlockingCycles++; + } +} +/*-----------------------------------------------------------*/ + +static void prvRecursiveMutexPollingTask( void *pvParameters ) +{ + /* Just to remove compiler warning. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Keep attempting to obtain the mutex. We should only obtain it when + the blocking task has suspended itself, which in turn should only + happen when the controlling task is also suspended. */ + if( xSemaphoreTakeRecursive( xMutex, recmuNO_DELAY ) == pdPASS ) + { + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xControllingTaskHandle ) == eSuspended ); + configASSERT( eTaskGetState( xBlockingTaskHandle ) == eSuspended ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* Is the blocking task suspended? */ + if( ( xBlockingIsSuspended != pdTRUE ) || ( xControllingIsSuspended != pdTRUE ) ) + { + xErrorOccurred = pdTRUE; + } + else + { + /* Keep count of the number of cycles this task has performed + so a stall can be detected. */ + uxPollingCycles++; + + /* We can resume the other tasks here even though they have a + higher priority than the polling task. When they execute they + will attempt to obtain the mutex but fail because the polling + task is still the mutex holder. The polling task (this task) + will then inherit the higher priority. The Blocking task will + block indefinitely when it attempts to obtain the mutex, the + Controlling task will only block for a fixed period and an + error will be latched if the polling task has not returned the + mutex by the time this fixed period has expired. */ + vTaskResume( xBlockingTaskHandle ); + vTaskResume( xControllingTaskHandle ); + + /* The other two tasks should now have executed and no longer + be suspended. */ + if( ( xBlockingIsSuspended == pdTRUE ) || ( xControllingIsSuspended == pdTRUE ) ) + { + xErrorOccurred = pdTRUE; + } + + #if( INCLUDE_uxTaskPriorityGet == 1 ) + { + /* Check priority inherited. */ + configASSERT( uxTaskPriorityGet( NULL ) == recmuCONTROLLING_TASK_PRIORITY ); + } + #endif /* INCLUDE_uxTaskPriorityGet */ + + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xControllingTaskHandle ) == eBlocked ); + configASSERT( eTaskGetState( xBlockingTaskHandle ) == eBlocked ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* Release the mutex, disinheriting the higher priority again. */ + if( xSemaphoreGiveRecursive( xMutex ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + #if( INCLUDE_uxTaskPriorityGet == 1 ) + { + /* Check priority disinherited. */ + configASSERT( uxTaskPriorityGet( NULL ) == recmuPOLLING_TASK_PRIORITY ); + } + #endif /* INCLUDE_uxTaskPriorityGet */ + } + } + + #if configUSE_PREEMPTION == 0 + { + taskYIELD(); + } + #endif + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreRecursiveMutexTasksStillRunning( void ) +{ +BaseType_t xReturn; +static UBaseType_t uxLastControllingCycles = 0, uxLastBlockingCycles = 0, uxLastPollingCycles = 0; + + /* Is the controlling task still cycling? */ + if( uxLastControllingCycles == uxControllingCycles ) + { + xErrorOccurred = pdTRUE; + } + else + { + uxLastControllingCycles = uxControllingCycles; + } + + /* Is the blocking task still cycling? */ + if( uxLastBlockingCycles == uxBlockingCycles ) + { + xErrorOccurred = pdTRUE; + } + else + { + uxLastBlockingCycles = uxBlockingCycles; + } + + /* Is the polling task still cycling? */ + if( uxLastPollingCycles == uxPollingCycles ) + { + xErrorOccurred = pdTRUE; + } + else + { + uxLastPollingCycles = uxPollingCycles; + } + + if( xErrorOccurred == pdTRUE ) + { + xReturn = pdFAIL; + } + else + { + xReturn = pdTRUE; + } + + return xReturn; +} + + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/semtest.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/semtest.c new file mode 100644 index 0000000..5e43e4a --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/semtest.c @@ -0,0 +1,298 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * Creates two sets of two tasks. The tasks within a set share a variable, access + * to which is guarded by a semaphore. + * + * Each task starts by attempting to obtain the semaphore. On obtaining a + * semaphore a task checks to ensure that the guarded variable has an expected + * value. It then clears the variable to zero before counting it back up to the + * expected value in increments of 1. After each increment the variable is checked + * to ensure it contains the value to which it was just set. When the starting + * value is again reached the task releases the semaphore giving the other task in + * the set a chance to do exactly the same thing. The starting value is high + * enough to ensure that a tick is likely to occur during the incrementing loop. + * + * An error is flagged if at any time during the process a shared variable is + * found to have a value other than that expected. Such an occurrence would + * suggest an error in the mutual exclusion mechanism by which access to the + * variable is restricted. + * + * The first set of two tasks poll their semaphore. The second set use blocking + * calls. + * + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "semtest.h" + +/* The value to which the shared variables are counted. */ +#define semtstBLOCKING_EXPECTED_VALUE ( ( uint32_t ) 0xfff ) +#define semtstNON_BLOCKING_EXPECTED_VALUE ( ( uint32_t ) 0xff ) + +#define semtstSTACK_SIZE configMINIMAL_STACK_SIZE + +#define semtstNUM_TASKS ( 4 ) + +#define semtstDELAY_FACTOR ( ( TickType_t ) 10 ) + +/* The task function as described at the top of the file. */ +static portTASK_FUNCTION_PROTO( prvSemaphoreTest, pvParameters ); + +/* Structure used to pass parameters to each task. */ +typedef struct SEMAPHORE_PARAMETERS +{ + SemaphoreHandle_t xSemaphore; + volatile uint32_t *pulSharedVariable; + TickType_t xBlockTime; +} xSemaphoreParameters; + +/* Variables used to check that all the tasks are still running without errors. */ +static volatile short sCheckVariables[ semtstNUM_TASKS ] = { 0 }; +static volatile short sNextCheckVariable = 0; + +/*-----------------------------------------------------------*/ + +void vStartSemaphoreTasks( UBaseType_t uxPriority ) +{ +xSemaphoreParameters *pxFirstSemaphoreParameters, *pxSecondSemaphoreParameters; +const TickType_t xBlockTime = ( TickType_t ) 100; + + /* Create the structure used to pass parameters to the first two tasks. */ + pxFirstSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) ); + + if( pxFirstSemaphoreParameters != NULL ) + { + /* Create the semaphore used by the first two tasks. */ + pxFirstSemaphoreParameters->xSemaphore = xSemaphoreCreateBinary(); + xSemaphoreGive( pxFirstSemaphoreParameters->xSemaphore ); + + if( pxFirstSemaphoreParameters->xSemaphore != NULL ) + { + /* Create the variable which is to be shared by the first two tasks. */ + pxFirstSemaphoreParameters->pulSharedVariable = ( uint32_t * ) pvPortMalloc( sizeof( uint32_t ) ); + + /* Initialise the share variable to the value the tasks expect. */ + *( pxFirstSemaphoreParameters->pulSharedVariable ) = semtstNON_BLOCKING_EXPECTED_VALUE; + + /* The first two tasks do not block on semaphore calls. */ + pxFirstSemaphoreParameters->xBlockTime = ( TickType_t ) 0; + + /* Spawn the first two tasks. As they poll they operate at the idle priority. */ + xTaskCreate( prvSemaphoreTest, "PolSEM1", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL ); + xTaskCreate( prvSemaphoreTest, "PolSEM2", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL ); + } + } + + /* Do exactly the same to create the second set of tasks, only this time + provide a block time for the semaphore calls. */ + pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) ); + if( pxSecondSemaphoreParameters != NULL ) + { + pxSecondSemaphoreParameters->xSemaphore = xSemaphoreCreateBinary(); + xSemaphoreGive( pxSecondSemaphoreParameters->xSemaphore ); + + if( pxSecondSemaphoreParameters->xSemaphore != NULL ) + { + pxSecondSemaphoreParameters->pulSharedVariable = ( uint32_t * ) pvPortMalloc( sizeof( uint32_t ) ); + *( pxSecondSemaphoreParameters->pulSharedVariable ) = semtstBLOCKING_EXPECTED_VALUE; + pxSecondSemaphoreParameters->xBlockTime = xBlockTime / portTICK_PERIOD_MS; + + xTaskCreate( prvSemaphoreTest, "BlkSEM1", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL ); + xTaskCreate( prvSemaphoreTest, "BlkSEM2", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL ); + } + } + + /* vQueueAddToRegistry() adds the semaphore to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate semaphores and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( QueueHandle_t ) pxFirstSemaphoreParameters->xSemaphore, "Counting_Sem_1" ); + vQueueAddToRegistry( ( QueueHandle_t ) pxSecondSemaphoreParameters->xSemaphore, "Counting_Sem_2" ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( prvSemaphoreTest, pvParameters ) +{ +xSemaphoreParameters *pxParameters; +volatile uint32_t *pulSharedVariable, ulExpectedValue; +uint32_t ulCounter; +short sError = pdFALSE, sCheckVariableToUse; + + /* See which check variable to use. sNextCheckVariable is not semaphore + protected! */ + portENTER_CRITICAL(); + sCheckVariableToUse = sNextCheckVariable; + sNextCheckVariable++; + portEXIT_CRITICAL(); + + /* A structure is passed in as the parameter. This contains the shared + variable being guarded. */ + pxParameters = ( xSemaphoreParameters * ) pvParameters; + pulSharedVariable = pxParameters->pulSharedVariable; + + /* If we are blocking we use a much higher count to ensure loads of context + switches occur during the count. */ + if( pxParameters->xBlockTime > ( TickType_t ) 0 ) + { + ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE; + } + else + { + ulExpectedValue = semtstNON_BLOCKING_EXPECTED_VALUE; + } + + for( ;; ) + { + /* Try to obtain the semaphore. */ + if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS ) + { + /* We have the semaphore and so expect any other tasks using the + shared variable to have left it in the state we expect to find + it. */ + if( *pulSharedVariable != ulExpectedValue ) + { + sError = pdTRUE; + } + + /* Clear the variable, then count it back up to the expected value + before releasing the semaphore. Would expect a context switch or + two during this time. */ + for( ulCounter = ( uint32_t ) 0; ulCounter <= ulExpectedValue; ulCounter++ ) + { + *pulSharedVariable = ulCounter; + if( *pulSharedVariable != ulCounter ) + { + sError = pdTRUE; + } + } + + /* Release the semaphore, and if no errors have occurred increment the check + variable. */ + if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + if( sCheckVariableToUse < semtstNUM_TASKS ) + { + ( sCheckVariables[ sCheckVariableToUse ] )++; + } + } + + /* If we have a block time then we are running at a priority higher + than the idle priority. This task takes a long time to complete + a cycle (deliberately so to test the guarding) so will be starving + out lower priority tasks. Block for some time to allow give lower + priority tasks some processor time. */ + vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR ); + } + else + { + if( pxParameters->xBlockTime == ( TickType_t ) 0 ) + { + /* We have not got the semaphore yet, so no point using the + processor. We are not blocking when attempting to obtain the + semaphore. */ + taskYIELD(); + } + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreSemaphoreTasksStillRunning( void ) +{ +static short sLastCheckVariables[ semtstNUM_TASKS ] = { 0 }; +BaseType_t xTask, xReturn = pdTRUE; + + for( xTask = 0; xTask < semtstNUM_TASKS; xTask++ ) + { + if( sLastCheckVariables[ xTask ] == sCheckVariables[ xTask ] ) + { + xReturn = pdFALSE; + } + + sLastCheckVariables[ xTask ] = sCheckVariables[ xTask ]; + } + + return xReturn; +} + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/sp_flop.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/sp_flop.c new file mode 100644 index 0000000..44cdd6f --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/sp_flop.c @@ -0,0 +1,365 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * Creates eight tasks, each of which loops continuously performing a floating + * point calculation - using single precision variables. + * + * All the tasks run at the idle priority and never block or yield. This causes + * all eight tasks to time slice with the idle task. Running at the idle priority + * means that these tasks will get pre-empted any time another task is ready to run + * or a time slice occurs. More often than not the pre-emption will occur mid + * calculation, creating a good test of the schedulers context switch mechanism - a + * calculation producing an unexpected result could be a symptom of a corruption in + * the context of a task. + */ + +#include +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "flop.h" + +#define mathSTACK_SIZE configMINIMAL_STACK_SIZE +#define mathNUMBER_OF_TASKS ( 8 ) + +/* Four tasks, each of which performs a different floating point calculation. +Each of the four is created twice. */ +static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters ); + +/* These variables are used to check that all the tasks are still running. If a +task gets a calculation wrong it will +stop incrementing its check variable. */ +static volatile uint16_t usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartMathTasks( UBaseType_t uxPriority ) +{ + xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask1, "Math5", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, "Math6", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, "Math7", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, "Math8", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask1, pvParameters ) +{ +volatile float f1, f2, f3, f4; +volatile uint16_t *pusTaskCheckVariable; +volatile float fAnswer; +short sError = pdFALSE; + + f1 = 123.4567F; + f2 = 2345.6789F; + f3 = -918.222F; + + fAnswer = ( f1 + f2 ) * f3; + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for(;;) + { + f1 = 123.4567F; + f2 = 2345.6789F; + f3 = -918.222F; + + f4 = ( f1 + f2 ) * f3; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( f4 - fAnswer ) > 0.001F ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask2, pvParameters ) +{ +volatile float f1, f2, f3, f4; +volatile uint16_t *pusTaskCheckVariable; +volatile float fAnswer; +short sError = pdFALSE; + + f1 = -389.38F; + f2 = 32498.2F; + f3 = -2.0001F; + + fAnswer = ( f1 / f2 ) * f3; + + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for( ;; ) + { + f1 = -389.38F; + f2 = 32498.2F; + f3 = -2.0001F; + + f4 = ( f1 / f2 ) * f3; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( f4 - fAnswer ) > 0.001F ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know + this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask3, pvParameters ) +{ +volatile float *pfArray, fTotal1, fTotal2, fDifference, fPosition; +volatile uint16_t *pusTaskCheckVariable; +const size_t xArraySize = 10; +size_t xPosition; +short sError = pdFALSE; + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + pfArray = ( float * ) pvPortMalloc( xArraySize * sizeof( float ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + fTotal1 = 0.0F; + fTotal2 = 0.0F; + fPosition = 0.0F; + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + pfArray[ xPosition ] = fPosition + 5.5F; + fTotal1 += fPosition + 5.5F; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + fTotal2 += pfArray[ xPosition ]; + } + + fDifference = fTotal1 - fTotal2; + if( fabs( fDifference ) > 0.001F ) + { + sError = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask4, pvParameters ) +{ +volatile float *pfArray, fTotal1, fTotal2, fDifference, fPosition; +volatile uint16_t *pusTaskCheckVariable; +const size_t xArraySize = 10; +size_t xPosition; +short sError = pdFALSE; + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + pfArray = ( float * ) pvPortMalloc( xArraySize * sizeof( float ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + fTotal1 = 0.0F; + fTotal2 = 0.0F; + fPosition = 0.0F; + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + pfArray[ xPosition ] = fPosition * 12.123F; + fTotal1 += fPosition * 12.123F; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + fTotal2 += pfArray[ xPosition ]; + } + + fDifference = fTotal1 - fTotal2; + if( fabs( fDifference ) > 0.001F ) + { + sError = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreMathsTaskStillRunning( void ) +{ +/* Keep a history of the check variables so we know if they have been incremented +since the last call. */ +static uint16_t usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 }; +BaseType_t xReturn = pdTRUE, xTask; + + /* Check the maths tasks are still running by ensuring their check variables + are still incrementing. */ + for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ ) + { + if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ]; + } + + return xReturn; +} + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlckQ.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlckQ.h new file mode 100644 index 0000000..5e5eb3f --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlckQ.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef ALT_BLOCK_Q_H +#define ALT_BLOCK_Q_H + +void vStartAltBlockingQueueTasks( UBaseType_t uxPriority ); +BaseType_t xAreAltBlockingQueuesStillRunning( void ); + +#endif + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlock.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlock.h new file mode 100644 index 0000000..7946734 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlock.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef FAST_BLOCK_TIME_TEST_H +#define FAST_BLOCK_TIME_TEST_H + +void vCreateAltBlockTimeTasks( void ); +BaseType_t xAreAltBlockTimeTestTasksStillRunning( void ); + +#endif + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltPollQ.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltPollQ.h new file mode 100644 index 0000000..ce6af62 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltPollQ.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef ALT_POLLED_Q_H +#define ALT_POLLED_Q_H + +void vStartAltPolledQueueTasks( UBaseType_t uxPriority ); +BaseType_t xAreAltPollingQueuesStillRunning( void ); + +#endif + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltQTest.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltQTest.h new file mode 100644 index 0000000..cf50026 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltQTest.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef FAST_GEN_Q_TEST_H +#define FAST_GEN_Q_TEST_H + +void vStartAltGenericQueueTasks( UBaseType_t uxPriority ); +BaseType_t xAreAltGenericQueueTasksStillRunning( void ); + +#endif /* GEN_Q_TEST_H */ + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/BlockQ.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/BlockQ.h new file mode 100644 index 0000000..7a6ea01 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/BlockQ.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef BLOCK_Q_H +#define BLOCK_Q_H + +void vStartBlockingQueueTasks( UBaseType_t uxPriority ); +BaseType_t xAreBlockingQueuesStillRunning( void ); + +#endif + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/EventGroupsDemo.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/EventGroupsDemo.h new file mode 100644 index 0000000..1b5c49c --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/EventGroupsDemo.h @@ -0,0 +1,82 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + + +/* + * This file contains fairly comprehensive checks on the behaviour of event + * groups. It is not intended to be a user friendly demonstration of the event + * groups API. + */ + +#ifndef EVENT_GROUPS_DEMO_H +#define EVENT_GROUPS_DEMO_H + +void vStartEventGroupTasks( void ); +BaseType_t xAreEventGroupTasksStillRunning( void ); +void vPeriodicEventGroupsProcessing( void ); + +#endif /* EVENT_GROUPS_DEMO_H */ + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/GenQTest.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/GenQTest.h new file mode 100644 index 0000000..a832900 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/GenQTest.h @@ -0,0 +1,76 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef GEN_Q_TEST_H +#define GEN_Q_TEST_H + +void vStartGenericQueueTasks( UBaseType_t uxPriority ); +BaseType_t xAreGenericQueueTasksStillRunning( void ); +void vMutexISRInteractionTest( void ); + +#endif /* GEN_Q_TEST_H */ + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/IntQueue.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/IntQueue.h new file mode 100644 index 0000000..77fae82 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/IntQueue.h @@ -0,0 +1,80 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef QUEUE_ACCESS_TEST +#define QUEUE_ACCESS_TEST + +void vStartInterruptQueueTasks( void ); +BaseType_t xAreIntQueueTasksStillRunning( void ); +BaseType_t xFirstTimerHandler( void ); +BaseType_t xSecondTimerHandler( void ); + +#endif /* QUEUE_ACCESS_TEST */ + + + + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/PollQ.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/PollQ.h new file mode 100644 index 0000000..5a6dc8e --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/PollQ.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef POLLED_Q_H +#define POLLED_Q_H + +void vStartPolledQueueTasks( UBaseType_t uxPriority ); +BaseType_t xArePollingQueuesStillRunning( void ); + +#endif + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QPeek.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QPeek.h new file mode 100644 index 0000000..b9b8525 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QPeek.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef Q_PEEK_TEST_H +#define Q_PEEK_TEST_H + +void vStartQueuePeekTasks( void ); +BaseType_t xAreQueuePeekTasksStillRunning( void ); + +#endif /* Q_PEEK_TEST_H */ + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueOverwrite.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueOverwrite.h new file mode 100644 index 0000000..1d79247 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueOverwrite.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef QUEUE_OVERWRITE_H +#define QUEUE_OVERWRITE_H + +void vStartQueueOverwriteTask( UBaseType_t uxPriority ); +BaseType_t xIsQueueOverwriteTaskStillRunning( void ); +void vQueueOverwritePeriodicISRDemo( void ); + +#endif /* QUEUE_OVERWRITE_H */ + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueSet.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueSet.h new file mode 100644 index 0000000..16c4623 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueSet.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef QUEUE_WAIT_MULTIPLE_H +#define QUEUE_WAIT_MULTIPLE_H + +void vStartQueueSetTasks( void ); +BaseType_t xAreQueueSetTasksStillRunning( void ); +void vQueueSetAccessQueueSetFromISR( void ); + +#endif /* QUEUE_WAIT_MULTIPLE_H */ + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/TimerDemo.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/TimerDemo.h new file mode 100644 index 0000000..d005a64 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/TimerDemo.h @@ -0,0 +1,76 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef TIMER_DEMO_H +#define TIMER_DEMO_H + +void vStartTimerDemoTask( TickType_t xBaseFrequencyIn ); +BaseType_t xAreTimerDemoTasksStillRunning( TickType_t xCycleFrequency ); +void vTimerPeriodicISRTests( void ); + +#endif /* TIMER_DEMO_H */ + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/blocktim.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/blocktim.h new file mode 100644 index 0000000..fb56df4 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/blocktim.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef BLOCK_TIME_TEST_H +#define BLOCK_TIME_TEST_H + +void vCreateBlockTimeTasks( void ); +BaseType_t xAreBlockTimeTestTasksStillRunning( void ); + +#endif + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest.h new file mode 100644 index 0000000..43d92c8 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef COMTEST_H +#define COMTEST_H + +void vAltStartComTestTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED ); +void vStartComTestTasks( UBaseType_t uxPriority, eCOMPort ePort, eBaud eBaudRate ); +BaseType_t xAreComTestTasksStillRunning( void ); +void vComTestUnsuspendTask( void ); + +#endif + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest2.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest2.h new file mode 100644 index 0000000..43e9993 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest2.h @@ -0,0 +1,73 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef COMTEST_H +#define COMTEST_H + +void vAltStartComTestTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED ); +BaseType_t xAreComTestTasksStillRunning( void ); + +#endif + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest_strings.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest_strings.h new file mode 100644 index 0000000..0d72615 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest_strings.h @@ -0,0 +1,73 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef COMTEST_STRINGS_H +#define COMTEST_STRINGS_H + +void vStartComTestStringsTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED ); +BaseType_t xAreComTestTasksStillRunning( void ); + +#endif + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/countsem.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/countsem.h new file mode 100644 index 0000000..484a23a --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/countsem.h @@ -0,0 +1,73 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef COUNT_SEMAPHORE_TEST_H +#define COUNT_SEMAPHORE_TEST_H + +void vStartCountingSemaphoreTasks( void ); +BaseType_t xAreCountingSemaphoreTasksStillRunning( void ); + +#endif + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crflash.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crflash.h new file mode 100644 index 0000000..3d51635 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crflash.h @@ -0,0 +1,85 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef CRFLASH_LED_H +#define CRFLASH_LED_H + +/* + * Create the co-routines used to flash the LED's at different rates. + * + * @param uxPriority The number of 'fixed delay' co-routines to create. This + * also effects the number of LED's that will be utilised. For example, + * passing in 3 will cause LED's 0 to 2 to be utilised. + */ +void vStartFlashCoRoutines( UBaseType_t uxPriority ); + +/* + * Return pdPASS or pdFAIL depending on whether an error has been detected + * or not. + */ +BaseType_t xAreFlashCoRoutinesStillRunning( void ); + +#endif + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crhook.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crhook.h new file mode 100644 index 0000000..d56ee65 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crhook.h @@ -0,0 +1,81 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef CRHOOK_H +#define CRHOOK_H + +/* + * Create the co-routines used to communicate wit the tick hook. + */ +void vStartHookCoRoutines( void ); + +/* + * Return pdPASS or pdFAIL depending on whether an error has been detected + * or not. + */ +BaseType_t xAreHookCoRoutinesStillRunning( void ); + +#endif + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/death.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/death.h new file mode 100644 index 0000000..5d08038 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/death.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef SUICIDE_TASK_H +#define SUICIDE_TASK_H + +void vCreateSuicidalTasks( UBaseType_t uxPriority ); +BaseType_t xIsCreateTaskStillRunning( void ); + +#endif + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/dynamic.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/dynamic.h new file mode 100644 index 0000000..a923c20 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/dynamic.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef DYNAMIC_MANIPULATION_H +#define DYNAMIC_MANIPULATION_H + +void vStartDynamicPriorityTasks( void ); +BaseType_t xAreDynamicPriorityTasksStillRunning( void ); + +#endif + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/fileIO.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/fileIO.h new file mode 100644 index 0000000..afcf005 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/fileIO.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef FILE_IO_H +#define FILE_OI_H + +void vDisplayMessage( const char * const pcMessageToPrint ); +void vWriteMessageToDisk( const char * const pcMessage ); +void vWriteBufferToDisk( const char * const pcBuffer, uint32_t ulBufferLength ); + +#endif + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash.h new file mode 100644 index 0000000..41ea2f6 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash.h @@ -0,0 +1,72 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef FLASH_LED_H +#define FLASH_LED_H + +void vStartLEDFlashTasks( UBaseType_t uxPriority ); + +#endif + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash_timer.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash_timer.h new file mode 100644 index 0000000..2e7a230 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash_timer.h @@ -0,0 +1,79 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef FLASH_TIMER_H +#define FLASH_TIMER_H + +/* + * Creates the LED flashing timers. xNumberOfLEDs specifies how many timers to + * create, with each timer toggling a different LED. The first LED to be + * toggled is LED 0, with subsequent LEDs following on in numerical order. Each + * timer uses the exact same callback function, with the timer ID being used + * within the callback function to determine which timer has actually expired + * (and therefore which LED to toggle). + */ +void vStartLEDFlashTimers( UBaseType_t uxNumberOfLEDs ); + +#endif /* FLASH_TIMER_H */ diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flop.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flop.h new file mode 100644 index 0000000..ef6fe64 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flop.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef FLOP_TASKS_H +#define FLOP_TASKS_H + +void vStartMathTasks( UBaseType_t uxPriority ); +BaseType_t xAreMathsTaskStillRunning( void ); + +#endif + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/integer.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/integer.h new file mode 100644 index 0000000..8b0d960 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/integer.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef INTEGER_TASKS_H +#define INTEGER_TASKS_H + +void vStartIntegerMathTasks( UBaseType_t uxPriority ); +BaseType_t xAreIntegerMathsTaskStillRunning( void ); + +#endif + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/mevents.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/mevents.h new file mode 100644 index 0000000..fed650e --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/mevents.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef EVENTS_TEST_H +#define EVENTS_TEST_H + +void vStartMultiEventTasks( void ); +BaseType_t xAreMultiEventTasksStillRunning( void ); + +#endif + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/partest.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/partest.h new file mode 100644 index 0000000..0886481 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/partest.h @@ -0,0 +1,76 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef PARTEST_H +#define PARTEST_H + +#define partstDEFAULT_PORT_ADDRESS ( ( uint16_t ) 0x378 ) + +void vParTestInitialise( void ); +void vParTestSetLED( UBaseType_t uxLED, BaseType_t xValue ); +void vParTestToggleLED( UBaseType_t uxLED ); + +#endif + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/print.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/print.h new file mode 100644 index 0000000..562b1e7 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/print.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef PRINT_H +#define PRINT_H + +void vPrintInitialise( void ); +void vPrintDisplayMessage( const char * const * pcMessageToSend ); +const char *pcPrintGetNextMessage( TickType_t xPrintRate ); + +#endif + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/recmutex.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/recmutex.h new file mode 100644 index 0000000..82eee1f --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/recmutex.h @@ -0,0 +1,73 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef RECURSIVE_MUTEX_TEST_H +#define RECURSIVE_MUTEX_TEST_H + +void vStartRecursiveMutexTasks( void ); +BaseType_t xAreRecursiveMutexTasksStillRunning( void ); + +#endif + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/semtest.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/semtest.h new file mode 100644 index 0000000..4c7ffb3 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/semtest.h @@ -0,0 +1,73 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef SEMAPHORE_TEST_H +#define SEMAPHORE_TEST_H + +void vStartSemaphoreTasks( UBaseType_t uxPriority ); +BaseType_t xAreSemaphoreTasksStillRunning( void ); + +#endif + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/serial.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/serial.h new file mode 100644 index 0000000..838ccd3 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/serial.h @@ -0,0 +1,136 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#ifndef SERIAL_COMMS_H +#define SERIAL_COMMS_H + +typedef void * xComPortHandle; + +typedef enum +{ + serCOM1, + serCOM2, + serCOM3, + serCOM4, + serCOM5, + serCOM6, + serCOM7, + serCOM8 +} eCOMPort; + +typedef enum +{ + serNO_PARITY, + serODD_PARITY, + serEVEN_PARITY, + serMARK_PARITY, + serSPACE_PARITY +} eParity; + +typedef enum +{ + serSTOP_1, + serSTOP_2 +} eStopBits; + +typedef enum +{ + serBITS_5, + serBITS_6, + serBITS_7, + serBITS_8 +} eDataBits; + +typedef enum +{ + ser50, + ser75, + ser110, + ser134, + ser150, + ser200, + ser300, + ser600, + ser1200, + ser1800, + ser2400, + ser4800, + ser9600, + ser19200, + ser38400, + ser57600, + ser115200 +} eBaud; + +xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength ); +xComPortHandle xSerialPortInit( eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned portBASE_TYPE uxBufferLength ); +void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength ); +signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime ); +signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime ); +portBASE_TYPE xSerialWaitForSemaphore( xComPortHandle xPort ); +void vSerialClose( xComPortHandle xPort ); + +#endif + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/Makefile b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/Makefile new file mode 100644 index 0000000..08c16c5 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/Makefile @@ -0,0 +1,48 @@ + +include $(MAKE_INCLUDE_GEN) + +.PHONY: all clean + +MODULE_IFLAGS = -I./include + + +#*****************************************************************************# +# Object FILE LIST # +#*****************************************************************************# +OBJS = tasks.o list.o croutine.o queue.o timers.o event_groups.o +ifeq ($(CONFIG_RELEASE_BUILD),y) + OBJS = +else +endif + + +#*****************************************************************************# +# RULES TO GENERATE TARGETS # +#*****************************************************************************# + +# Define the Rules to build the core targets +#all: CORE_TARGETS COPY_RAM_OBJS +all: CORE_TARGETS COPY_RAM_OBJS + make -C portable/MemMang all + make -C portable/GCC/ARM_CM4F all + + + +#*****************************************************************************# +# GENERATE OBJECT FILE +#*****************************************************************************# +CORE_TARGETS: $(OBJS) + + +#*****************************************************************************# +# RULES TO CLEAN TARGETS # +#*****************************************************************************# +clean: + make -C portable/MemMang clean + make -C portable/GCC/ARM_CM4F clean + $(REMOVE) *.o + $(REMOVE) *.i + $(REMOVE) *.s + $(REMOVE) *.d + +-include $(DEPS) diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/include/stdint.readme b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/include/stdint.readme new file mode 100644 index 0000000..4414c29 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/include/stdint.readme @@ -0,0 +1,27 @@ + +#ifndef FREERTOS_STDINT +#define FREERTOS_STDINT + +/******************************************************************************* + * THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions + * necessary to build the FreeRTOS code. It is provided to allow FreeRTOS to be + * built using compilers that do not provide their own stdint.h definition. + * + * To use this file: + * + * 1) Copy this file into the directory that contains your FreeRTOSConfig.h + * header file, as that directory will already be in the compilers include + * path. + * + * 2) Rename the copied file stdint.h. + * + */ + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef long int32_t; +typedef unsigned long uint32_t; + +#endif /* FREERTOS_STDINT */ diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3/Makefile b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3/Makefile new file mode 100644 index 0000000..1d72f14 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3/Makefile @@ -0,0 +1,33 @@ + +include $(MAKE_INCLUDE_GEN) + +.PHONY: all clean + +MODULE_IFLAGS = + + +#*****************************************************************************# +# Object FILE LIST # +#*****************************************************************************# +OBJS = port.o + +#*****************************************************************************# +# RULES TO GENERATE TARGETS # +#*****************************************************************************# + +# Define the Rules to build the core targets +all: CORE_TARGETS COPY_RAM_OBJS + + +#*****************************************************************************# +# GENERATE OBJECT FILE +#*****************************************************************************# +CORE_TARGETS: $(OBJS) + +clean: + $(REMOVE) *.o + $(REMOVE) *.i + $(REMOVE) *.s + $(REMOVE) *.d + +-include $(DEPS) diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/port.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/port.c new file mode 100644 index 0000000..1e1aa88 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/port.c @@ -0,0 +1,1246 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM3 port. + *----------------------------------------------------------*/ + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* Constants required to access and manipulate the NVIC. */ +#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 ) +#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 ) +#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 ) +#define portNVIC_SYSPRI1 ( ( volatile uint32_t * ) 0xe000ed1c ) +#define portNVIC_SYS_CTRL_STATE ( ( volatile uint32_t * ) 0xe000ed24 ) +#define portNVIC_MEM_FAULT_ENABLE ( 1UL << 16UL ) + +/* Constants required to access and manipulate the MPU. */ +#define portMPU_TYPE ( ( volatile uint32_t * ) 0xe000ed90 ) +#define portMPU_REGION_BASE_ADDRESS ( ( volatile uint32_t * ) 0xe000ed9C ) +#define portMPU_REGION_ATTRIBUTE ( ( volatile uint32_t * ) 0xe000edA0 ) +#define portMPU_CTRL ( ( volatile uint32_t * ) 0xe000ed94 ) +#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */ +#define portMPU_ENABLE ( 0x01UL ) +#define portMPU_BACKGROUND_ENABLE ( 1UL << 2UL ) +#define portPRIVILEGED_EXECUTION_START_ADDRESS ( 0UL ) +#define portMPU_REGION_VALID ( 0x10UL ) +#define portMPU_REGION_ENABLE ( 0x01UL ) +#define portPERIPHERALS_START_ADDRESS 0x40000000UL +#define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL + +/* Constants required to access and manipulate the SysTick. */ +#define portNVIC_SYSTICK_CLK ( 0x00000004UL ) +#define portNVIC_SYSTICK_INT ( 0x00000002UL ) +#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL ) +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) +#define portNVIC_SVC_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) +#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 ) +#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 ) + +/* Offsets in the stack to the parameters when inside the SVC handler. */ +#define portOFFSET_TO_PC ( 6 ) + +/* Set the privilege level to user mode if xRunningPrivileged is false. */ +#define portRESET_PRIVILEGE( xRunningPrivileged ) if( xRunningPrivileged != pdTRUE ) __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0" :::"r0" ) + +/* Each task maintains its own interrupt status in the critical nesting +variable. Note this is not saved as part of the task context as context +switches can only occur when uxCriticalNesting is zero. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. + */ +static void prvSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION; + +/* + * Configure a number of standard MPU regions that are used by all tasks. + */ +static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; + +/* + * Return the smallest MPU region size that a given number of bytes will fit + * into. The region size is returned as the value that should be programmed + * into the region attribute register for that region. + */ +static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVILEGED_FUNCTION; + +/* + * Checks to see if being called from the context of an unprivileged task, and + * if so raises the privilege level and returns false - otherwise does nothing + * other than return true. + */ +static BaseType_t prvRaisePrivilege( void ) __attribute__(( naked )); + +/* + * Standard FreeRTOS exception handlers. + */ +void xPortPendSVHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void xPortSysTickHandler( void ) __attribute__ ((optimize("3"))) PRIVILEGED_FUNCTION; +void vPortSVCHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; + +/* + * Starts the scheduler by restoring the context of the first task to run. + */ +static void prvRestoreContextOfFirstTask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION; + +/* + * C portion of the SVC handler. The SVC handler is split between an asm entry + * and a C wrapper for simplicity of coding and maintenance. + */ +static void prvSVCHandler( uint32_t *pulRegisters ) __attribute__(( noinline )) PRIVILEGED_FUNCTION; + +/* + * Prototypes for all the MPU wrappers. + */ +BaseType_t MPU_xTaskGenericCreate( TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask, StackType_t *puxStackBuffer, const MemoryRegion_t * const xRegions ); +void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const xRegions ); +void MPU_vTaskDelete( TaskHandle_t pxTaskToDelete ); +void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, TickType_t xTimeIncrement ); +void MPU_vTaskDelay( TickType_t xTicksToDelay ); +UBaseType_t MPU_uxTaskPriorityGet( TaskHandle_t pxTask ); +void MPU_vTaskPrioritySet( TaskHandle_t pxTask, UBaseType_t uxNewPriority ); +eTaskState MPU_eTaskGetState( TaskHandle_t pxTask ); +void MPU_vTaskSuspend( TaskHandle_t pxTaskToSuspend ); +void MPU_vTaskResume( TaskHandle_t pxTaskToResume ); +void MPU_vTaskSuspendAll( void ); +BaseType_t MPU_xTaskResumeAll( void ); +TickType_t MPU_xTaskGetTickCount( void ); +UBaseType_t MPU_uxTaskGetNumberOfTasks( void ); +void MPU_vTaskList( char *pcWriteBuffer ); +void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer ); +void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxTagValue ); +TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ); +BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ); +UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ); +TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ); +BaseType_t MPU_xTaskGetSchedulerState( void ); +TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ); +UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t *pxTaskStatusArray, UBaseType_t uxArraySize, uint32_t *pulTotalRunTime ); +QueueHandle_t MPU_xQueueGenericCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize, uint8_t ucQueueType ); +BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition ); +BaseType_t MPU_xQueueGenericReset( QueueHandle_t pxQueue, BaseType_t xNewQueue ); +UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t pxQueue ); +BaseType_t MPU_xQueueGenericReceive( QueueHandle_t pxQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking ); +QueueHandle_t MPU_xQueueCreateMutex( void ); +QueueHandle_t MPU_xQueueCreateCountingSemaphore( UBaseType_t uxCountValue, UBaseType_t uxInitialCount ); +BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xBlockTime ); +BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t xMutex ); +BaseType_t MPU_xQueueAltGenericSend( QueueHandle_t pxQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition ); +BaseType_t MPU_xQueueAltGenericReceive( QueueHandle_t pxQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking ); +void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, char *pcName ); +void MPU_vQueueDelete( QueueHandle_t xQueue ); +void *MPU_pvPortMalloc( size_t xSize ); +void MPU_vPortFree( void *pv ); +void MPU_vPortInitialiseBlocks( void ); +size_t MPU_xPortGetFreeHeapSize( void ); +QueueSetHandle_t MPU_xQueueCreateSet( UBaseType_t uxEventQueueLength ); +QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t xBlockTimeTicks ); +BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ); +BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ); +BaseType_t MPU_xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ); +void* MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ); + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = 0; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + if( xRunPrivileged == pdTRUE ) + { + *pxTopOfStack = portINITIAL_CONTROL_IF_PRIVILEGED; + } + else + { + *pxTopOfStack = portINITIAL_CONTROL_IF_UNPRIVILEGED; + } + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +void vPortSVCHandler( void ) +{ + /* Assumes psp was in use. */ + __asm volatile + ( + #ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */ + " tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + #else + " mrs r0, psp \n" + #endif + " b %0 \n" + ::"i"(prvSVCHandler):"r0" + ); +} +/*-----------------------------------------------------------*/ + +static void prvSVCHandler( uint32_t *pulParam ) +{ +uint8_t ucSVCNumber; + + /* The stack contains: r0, r1, r2, r3, r12, r14, the return address and + xPSR. The first argument (r0) is pulParam[ 0 ]. */ + ucSVCNumber = ( ( uint8_t * ) pulParam[ portOFFSET_TO_PC ] )[ -2 ]; + switch( ucSVCNumber ) + { + case portSVC_START_SCHEDULER : *(portNVIC_SYSPRI1) |= portNVIC_SVC_PRI; + prvRestoreContextOfFirstTask(); + break; + + case portSVC_YIELD : *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; + /* Barriers are normally not required + but do ensure the code is completely + within the specified behaviour for the + architecture. */ + __asm volatile( "dsb" ); + __asm volatile( "isb" ); + + break; + + case portSVC_RAISE_PRIVILEGE : __asm volatile + ( + " mrs r1, control \n" /* Obtain current control value. */ + " bic r1, #1 \n" /* Set privilege bit. */ + " msr control, r1 \n" /* Write back new control value. */ + :::"r1" + ); + break; + + default : /* Unknown SVC call. */ + break; + } +} +/*-----------------------------------------------------------*/ + +static void prvRestoreContextOfFirstTask( void ) +{ + __asm volatile + ( + " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n" /* Move onto the second item in the TCB... */ + " ldr r2, =0xe000ed9c \n" /* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */ + " stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */ + " ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */ + " msr control, r3 \n" + " msr psp, r0 \n" /* Restore the task stack pointer. */ + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldr r14, =0xfffffffd \n" /* Load exec return code. */ + " bx r14 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See + http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ); + + /* Make PendSV and SysTick the same priority as the kernel. */ + *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; + *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; + + /* Configure the regions in the MPU that are common to all tasks. */ + prvSetupMPU(); + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + prvSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + __asm volatile( " svc %0 \n" + :: "i" (portSVC_START_SCHEDULER) ); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +void xPortPendSVHandler( void ) +{ + /* This is a naked function. */ + + __asm volatile + ( + " mrs r0, psp \n" + " \n" + " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " mrs r1, control \n" + " stmdb r0!, {r1, r4-r11} \n" /* Save the remaining registers. */ + " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ + " \n" + " stmdb sp!, {r3, r14} \n" + " mov r0, %0 \n" + " msr basepri, r0 \n" + " bl vTaskSwitchContext \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldmia sp!, {r3, r14} \n" + " \n" /* Restore the context. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n" /* Move onto the second item in the TCB... */ + " ldr r2, =0xe000ed9c \n" /* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */ + " stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */ + " ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */ + " msr control, r3 \n" + " \n" + " msr psp, r0 \n" + " bx r14 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) + ); +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ +uint32_t ulDummy; + + ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Pend a context switch. */ + *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); +} +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +static void prvSetupTimerInterrupt( void ) +{ + /* Configure SysTick to interrupt at the requested rate. */ + *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; +} +/*-----------------------------------------------------------*/ + +static void prvSetupMPU( void ) +{ +extern uint32_t __privileged_functions_end__[]; +extern uint32_t __FLASH_segment_start__[]; +extern uint32_t __FLASH_segment_end__[]; +extern uint32_t __privileged_data_start__[]; +extern uint32_t __privileged_data_end__[]; + + /* Check the expected MPU is present. */ + if( *portMPU_TYPE == portEXPECTED_MPU_TYPE_VALUE ) + { + /* First setup the entire flash for unprivileged read only access. */ + *portMPU_REGION_BASE_ADDRESS = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portUNPRIVILEGED_FLASH_REGION ); + + *portMPU_REGION_ATTRIBUTE = ( portMPU_REGION_READ_ONLY ) | + ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | + ( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) | + ( portMPU_REGION_ENABLE ); + + /* Setup the first 16K for privileged only access (even though less + than 10K is actually being used). This is where the kernel code is + placed. */ + *portMPU_REGION_BASE_ADDRESS = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portPRIVILEGED_FLASH_REGION ); + + *portMPU_REGION_ATTRIBUTE = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) | + ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | + ( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) | + ( portMPU_REGION_ENABLE ); + + /* Setup the privileged data RAM region. This is where the kernel data + is placed. */ + *portMPU_REGION_BASE_ADDRESS = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portPRIVILEGED_RAM_REGION ); + + *portMPU_REGION_ATTRIBUTE = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | + ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | + prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | + ( portMPU_REGION_ENABLE ); + + /* By default allow everything to access the general peripherals. The + system peripherals and registers are protected. */ + *portMPU_REGION_BASE_ADDRESS = ( portPERIPHERALS_START_ADDRESS ) | + ( portMPU_REGION_VALID ) | + ( portGENERAL_PERIPHERALS_REGION ); + + *portMPU_REGION_ATTRIBUTE = ( portMPU_REGION_READ_WRITE | portMPU_REGION_EXECUTE_NEVER ) | + ( prvGetMPURegionSizeSetting( portPERIPHERALS_END_ADDRESS - portPERIPHERALS_START_ADDRESS ) ) | + ( portMPU_REGION_ENABLE ); + + /* Enable the memory fault exception. */ + *portNVIC_SYS_CTRL_STATE |= portNVIC_MEM_FAULT_ENABLE; + + /* Enable the MPU with the background region configured. */ + *portMPU_CTRL |= ( portMPU_ENABLE | portMPU_BACKGROUND_ENABLE ); + } +} +/*-----------------------------------------------------------*/ + +static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) +{ +uint32_t ulRegionSize, ulReturnValue = 4; + + /* 32 is the smallest region size, 31 is the largest valid value for + ulReturnValue. */ + for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) ) + { + if( ulActualSizeInBytes <= ulRegionSize ) + { + break; + } + else + { + ulReturnValue++; + } + } + + /* Shift the code by one before returning so it can be written directly + into the the correct bit position of the attribute register. */ + return ( ulReturnValue << 1UL ); +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvRaisePrivilege( void ) +{ + __asm volatile + ( + " mrs r0, control \n" + " tst r0, #1 \n" /* Is the task running privileged? */ + " itte ne \n" + " movne r0, #0 \n" /* CONTROL[0]!=0, return false. */ + " svcne %0 \n" /* Switch to privileged. */ + " moveq r0, #1 \n" /* CONTROL[0]==0, return true. */ + " bx lr \n" + :: "i" (portSVC_RAISE_PRIVILEGE) : "r0" + ); + + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint16_t usStackDepth ) +{ +extern uint32_t __SRAM_segment_start__[]; +extern uint32_t __SRAM_segment_end__[]; +extern uint32_t __privileged_data_start__[]; +extern uint32_t __privileged_data_end__[]; +int32_t lIndex; +uint32_t ul; + + if( xRegions == NULL ) + { + /* No MPU regions are specified so allow access to all RAM. */ + xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = + ( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portSTACK_REGION ); + + xMPUSettings->xRegion[ 0 ].ulRegionAttribute = + ( portMPU_REGION_READ_WRITE ) | + ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | + ( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) | + ( portMPU_REGION_ENABLE ); + + /* Re-instate the privileged only RAM region as xRegion[ 0 ] will have + just removed the privileged only parameters. */ + xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress = + ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portSTACK_REGION + 1 ); + + xMPUSettings->xRegion[ 1 ].ulRegionAttribute = + ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | + ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | + prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | + ( portMPU_REGION_ENABLE ); + + /* Invalidate all other regions. */ + for( ul = 2; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ ) + { + xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID; + xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL; + } + } + else + { + /* This function is called automatically when the task is created - in + which case the stack region parameters will be valid. At all other + times the stack parameters will not be valid and it is assumed that the + stack region has already been configured. */ + if( usStackDepth > 0 ) + { + /* Define the region that allows access to the stack. */ + xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = + ( ( uint32_t ) pxBottomOfStack ) | + ( portMPU_REGION_VALID ) | + ( portSTACK_REGION ); /* Region number. */ + + xMPUSettings->xRegion[ 0 ].ulRegionAttribute = + ( portMPU_REGION_READ_WRITE ) | /* Read and write. */ + ( prvGetMPURegionSizeSetting( ( uint32_t ) usStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) | + ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | + ( portMPU_REGION_ENABLE ); + } + + lIndex = 0; + + for( ul = 1; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ ) + { + if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL ) + { + /* Translate the generic region definition contained in + xRegions into the CM3 specific MPU settings that are then + stored in xMPUSettings. */ + xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = + ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) | + ( portMPU_REGION_VALID ) | + ( portSTACK_REGION + ul ); /* Region number. */ + + xMPUSettings->xRegion[ ul ].ulRegionAttribute = + ( prvGetMPURegionSizeSetting( xRegions[ lIndex ].ulLengthInBytes ) ) | + ( xRegions[ lIndex ].ulParameters ) | + ( portMPU_REGION_ENABLE ); + } + else + { + /* Invalidate the region. */ + xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID; + xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL; + } + + lIndex++; + } + } +} +/*-----------------------------------------------------------*/ + +BaseType_t MPU_xTaskGenericCreate( TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask, StackType_t *puxStackBuffer, const MemoryRegion_t * const xRegions ) +{ +BaseType_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskGenericCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, puxStackBuffer, xRegions ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const xRegions ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskAllocateMPURegions( xTask, xRegions ); + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelete == 1 ) + void MPU_vTaskDelete( TaskHandle_t pxTaskToDelete ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskDelete( pxTaskToDelete ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelayUntil == 1 ) + void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, TickType_t xTimeIncrement ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelay == 1 ) + void MPU_vTaskDelay( TickType_t xTicksToDelay ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskDelay( xTicksToDelay ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskPriorityGet == 1 ) + UBaseType_t MPU_uxTaskPriorityGet( TaskHandle_t pxTask ) + { + UBaseType_t uxReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + uxReturn = uxTaskPriorityGet( pxTask ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return uxReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskPrioritySet == 1 ) + void MPU_vTaskPrioritySet( TaskHandle_t pxTask, UBaseType_t uxNewPriority ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskPrioritySet( pxTask, uxNewPriority ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_eTaskGetState == 1 ) + eTaskState MPU_eTaskGetState( TaskHandle_t pxTask ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + eTaskState eReturn; + + eReturn = eTaskGetState( pxTask ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return eReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) + { + TaskHandle_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskGetIdleTaskHandle(); + portRESET_PRIVILEGE( xRunningPrivileged ); + return eReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + void MPU_vTaskSuspend( TaskHandle_t pxTaskToSuspend ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskSuspend( pxTaskToSuspend ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + void MPU_vTaskResume( TaskHandle_t pxTaskToResume ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskResume( pxTaskToResume ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +void MPU_vTaskSuspendAll( void ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskSuspendAll(); + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +BaseType_t MPU_xTaskResumeAll( void ) +{ +BaseType_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskResumeAll(); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +TickType_t MPU_xTaskGetTickCount( void ) +{ +TickType_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskGetTickCount(); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) +{ +UBaseType_t uxReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + uxReturn = uxTaskGetNumberOfTasks(); + portRESET_PRIVILEGE( xRunningPrivileged ); + return uxReturn; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + void MPU_vTaskList( char *pcWriteBuffer ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskList( pcWriteBuffer ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskGetRunTimeStats( pcWriteBuffer ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxTagValue ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskSetApplicationTaskTag( xTask, pxTagValue ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ) + { + TaskHookFunction_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskGetApplicationTaskTag( xTask ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskCallApplicationTaskHook( xTask, pvParameter ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t *pxTaskStatusArray, UBaseType_t uxArraySize, uint32_t *pulTotalRunTime ) + { + UBaseType_t uxReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + uxReturn = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) + UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) + { + UBaseType_t uxReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + uxReturn = uxTaskGetStackHighWaterMark( xTask ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return uxReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) + TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) + { + TaskHandle_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskGetCurrentTaskHandle(); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetSchedulerState == 1 ) + BaseType_t MPU_xTaskGetSchedulerState( void ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskGetSchedulerState(); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +QueueHandle_t MPU_xQueueGenericCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize, uint8_t ucQueueType ) +{ +QueueHandle_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t MPU_xQueueGenericReset( QueueHandle_t pxQueue, BaseType_t xNewQueue ) +{ +BaseType_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueGenericReset( pxQueue, xNewQueue ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition ) +{ +BaseType_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, xCopyPosition ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t pxQueue ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); +UBaseType_t uxReturn; + + uxReturn = uxQueueMessagesWaiting( pxQueue ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return uxReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t MPU_xQueueGenericReceive( QueueHandle_t pxQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); +BaseType_t xReturn; + + xReturn = xQueueGenericReceive( pxQueue, pvBuffer, xTicksToWait, xJustPeeking ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t MPU_xQueuePeekFromISR( QueueHandle_t pxQueue, void * const pvBuffer ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); +BaseType_t xReturn; + + xReturn = xQueuePeekFromISR( pxQueue, pvBuffer ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +void* MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); +void * xReturn; + + xReturn = ( void * ) xQueueGetMutexHolder( xSemaphore ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + QueueHandle_t MPU_xQueueCreateMutex( void ) + { + QueueHandle_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if configUSE_COUNTING_SEMAPHORES == 1 + QueueHandle_t MPU_xQueueCreateCountingSemaphore( UBaseType_t uxCountValue, UBaseType_t uxInitialCount ) + { + QueueHandle_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueCreateCountingSemaphore( uxCountValue, uxInitialCount ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xBlockTime ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueTakeMutexRecursive( xMutex, xBlockTime ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t xMutex ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueGiveMutexRecursive( xMutex ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + QueueSetHandle_t MPU_xQueueCreateSet( UBaseType_t uxEventQueueLength ) + { + QueueSetHandle_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueCreateSet( uxEventQueueLength ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t xBlockTimeTicks ) + { + QueueSetMemberHandle_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueSelectFromSet( xQueueSet, xBlockTimeTicks ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueAddToSet( xQueueOrSemaphore, xQueueSet ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueRemoveFromSet( xQueueOrSemaphore, xQueueSet ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if configUSE_ALTERNATIVE_API == 1 + BaseType_t MPU_xQueueAltGenericSend( QueueHandle_t pxQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = BaseType_t xQueueAltGenericSend( pxQueue, pvItemToQueue, xTicksToWait, xCopyPosition ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if configUSE_ALTERNATIVE_API == 1 + BaseType_t MPU_xQueueAltGenericReceive( QueueHandle_t pxQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueAltGenericReceive( pxQueue, pvBuffer, xTicksToWait, xJustPeeking ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if configQUEUE_REGISTRY_SIZE > 0 + void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, char *pcName ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vQueueAddToRegistry( xQueue, pcName ); + + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +void MPU_vQueueDelete( QueueHandle_t xQueue ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vQueueDelete( xQueue ); + + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +void *MPU_pvPortMalloc( size_t xSize ) +{ +void *pvReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + pvReturn = pvPortMalloc( xSize ); + + portRESET_PRIVILEGE( xRunningPrivileged ); + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void MPU_vPortFree( void *pv ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vPortFree( pv ); + + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +void MPU_vPortInitialiseBlocks( void ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vPortInitialiseBlocks(); + + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +size_t MPU_xPortGetFreeHeapSize( void ) +{ +size_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xPortGetFreeHeapSize(); + + portRESET_PRIVILEGE( xRunningPrivileged ); + + return xReturn; +} + +/* Functions that the application writer wants to execute in privileged mode +can be defined in application_defined_privileged_functions.h. The functions +must take the same format as those above whereby the privilege state on exit +equals the privilege state on entry. For example: + +void MPU_FunctionName( [parameters ] ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + FunctionName( [parameters ] ); + + portRESET_PRIVILEGE( xRunningPrivileged ); +} +*/ + +#if configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS == 1 + #include "application_defined_privileged_functions.h" +#endif + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/portmacro.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/portmacro.h new file mode 100644 index 0000000..ee06be9 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/portmacro.h @@ -0,0 +1,218 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +/* MPU specific constants. */ +#define portUSING_MPU_WRAPPERS 1 +#define portPRIVILEGE_BIT ( 0x80000000UL ) + +#define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL ) +#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL ) +#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL ) + +#define portUNPRIVILEGED_FLASH_REGION ( 0UL ) +#define portPRIVILEGED_FLASH_REGION ( 1UL ) +#define portPRIVILEGED_RAM_REGION ( 2UL ) +#define portGENERAL_PERIPHERALS_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( 7UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ + +#define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0 " :::"r0" ) + +typedef struct MPU_REGION_REGISTERS +{ + uint32_t ulRegionBaseAddress; + uint32_t ulRegionAttribute; +} xMPU_REGION_REGISTERS; + +/* Plus 1 to create space for the stack region. */ +typedef struct MPU_SETTINGS +{ + xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ]; +} xMPU_SETTINGS; + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* SVC numbers for various services. */ +#define portSVC_START_SCHEDULER 0 +#define portSVC_YIELD 1 +#define portSVC_RAISE_PRIVILEGE 2 + +/* Scheduler utilities. */ + +#define portYIELD() __asm volatile ( " SVC %0 \n" :: "i" (portSVC_YIELD) ) +#define portYIELD_WITHIN_API() *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET + +#define portNVIC_INT_CTRL ( ( volatile uint32_t *) 0xe000ed04 ) +#define portNVIC_PENDSVSET 0x10000000 +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + + +/* Critical section management. */ + +/* + * Set basepri to portMAX_SYSCALL_INTERRUPT_PRIORITY without effecting other + * registers. r0 is clobbered. + */ +#define portSET_INTERRUPT_MASK() \ + __asm volatile \ + ( \ + " mov r0, %0 \n" \ + " msr basepri, r0 \n" \ + ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY):"r0" \ + ) + +/* + * Set basepri back to 0 without effective other registers. + * r0 is clobbered. FAQ: Setting BASEPRI to 0 is not a bug. Please see + * http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. + */ +#define portCLEAR_INTERRUPT_MASK() \ + __asm volatile \ + ( \ + " mov r0, #0 \n" \ + " msr basepri, r0 \n" \ + :::"r0" \ + ) + +/* FAQ: Setting BASEPRI to 0 is not a bug. Please see +http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */ +#define portSET_INTERRUPT_MASK_FROM_ISR() 0;portSET_INTERRUPT_MASK() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK();(void)x + + +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); + +#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK() +#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK() +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) + +#define portNOP() + + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/Makefile b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/Makefile new file mode 100644 index 0000000..1d72f14 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/Makefile @@ -0,0 +1,33 @@ + +include $(MAKE_INCLUDE_GEN) + +.PHONY: all clean + +MODULE_IFLAGS = + + +#*****************************************************************************# +# Object FILE LIST # +#*****************************************************************************# +OBJS = port.o + +#*****************************************************************************# +# RULES TO GENERATE TARGETS # +#*****************************************************************************# + +# Define the Rules to build the core targets +all: CORE_TARGETS COPY_RAM_OBJS + + +#*****************************************************************************# +# GENERATE OBJECT FILE +#*****************************************************************************# +CORE_TARGETS: $(OBJS) + +clean: + $(REMOVE) *.o + $(REMOVE) *.i + $(REMOVE) *.s + $(REMOVE) *.d + +-include $(DEPS) diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/port.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/port.c new file mode 100644 index 0000000..90f07d2 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/port.c @@ -0,0 +1,784 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM4F port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +#ifndef __VFP_FP__ + #error This port can only be used when the project options are configured to enable hardware floating point support. +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + /* The way the SysTick is clocked is not modified in case it is not the same + as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) + +/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ +#define portVECTACTIVE_MASK ( 0x1FUL ) + +/* Constants required to manipulate the VFP. */ +#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */ +#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) +#define portINITIAL_EXEC_RETURN ( 0xfffffffd ) + +/* The systick is a 24-bit counter. */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/* A fiddle factor to estimate the number of SysTick counts that would have +occurred while the SysTick counter is stopped during tickless idle +calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) + +/* Let the user override the pre-loading of the initial LR with the address of +prvTaskExitError() in case is messes up unwinding of the stack in the +debugger. */ +#ifdef configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS +#else + #define portTASK_RETURN_ADDRESS prvTaskExitError +#endif + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ) __attribute__ (( naked )); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ) __attribute__ (( naked )); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +static void prvPortStartFirstTask( void ) __attribute__ (( naked )); + +/* + * Function to enable the VFP. + */ + static void vPortEnableVFP( void ) __attribute__ (( naked )); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulTimerCountsForOneTick = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * FreeRTOS API functions are not called from interrupts that have been assigned + * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. + */ +#if ( configASSERT_DEFINED == 1 ) + static uint8_t ucMaxSysCallPriority = 0; + static uint32_t ulMaxPRIGROUPValue = 0; + static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16; +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + + /* Offset added to account for the way the MCU uses the stack on entry/exit + of interrupts, and to ensure alignment. */ + pxTopOfStack--; + + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ + + /* Save code space by skipping register initialisation. */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + + /* A save method is being used that requires each task to maintain its + own exec return value. */ + pxTopOfStack--; + *pxTopOfStack = portINITIAL_EXEC_RETURN; + + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void vPortSVCHandler( void ) +{ + __asm volatile ( + " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ + " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " msr psp, r0 \n" /* Restore the task stack pointer. */ + " isb \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " bx r14 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); +} +/*-----------------------------------------------------------*/ + +static void prvPortStartFirstTask( void ) +{ + __asm volatile( + " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " cpsie i \n" /* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc 0 \n" /* System call to start first task. */ + " nop \n" + ); +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. + See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); + + #if( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + functions can be called. ISR safe functions are those that end in + "FromISR". FreeRTOS maintains separate thread and ISR API functions to + ensure interrupt entry is as fast and simple as possible. + + Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to all + possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Calculate the maximum acceptable priority group value for the number + of bits read back. */ + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulMaxPRIGROUPValue--; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + /* Shift the priority group value back to its position within the AIRCR + register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ + + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + vPortSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Ensure the VFP is enabled - it should be anyway. */ + vPortEnableVFP(); + + /* Lazy save always. */ + *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; + + /* Start the first task. */ + prvPortStartFirstTask(); + + /* Should never get here as the tasks will now be executing! Call the task + exit error function to prevent compiler warnings about a static function + not being called in the case that the application writer overrides this + functionality by defining configTASK_RETURN_ADDRESS. */ + prvTaskExitError(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is completely + within the specified behaviour for the architecture. */ + __asm volatile( "dsb" ); + __asm volatile( "isb" ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __asm volatile( "dsb" ); + __asm volatile( "isb" ); + + /* This is not the interrupt safe version of the enter critical function so + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +__attribute__(( naked )) uint32_t ulPortSetInterruptMask( void ) +{ + __asm volatile \ + ( \ + " mrs r0, basepri \n" \ + " mov r1, %0 \n" \ + " msr basepri, r1 \n" \ + " bx lr \n" \ + :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "r0", "r1" \ + ); + + /* This return will not be reached but is necessary to prevent compiler + warnings. */ + return 0; +} +/*-----------------------------------------------------------*/ + +__attribute__(( naked )) void vPortClearInterruptMask( uint32_t ulNewMaskValue ) +{ + __asm volatile \ + ( \ + " msr basepri, r0 \n" \ + " bx lr \n" \ + :::"r0" \ + ); + + /* Just to avoid compiler warnings. */ + ( void ) ulNewMaskValue; +} +/*-----------------------------------------------------------*/ + +void xPortPendSVHandler( void ) +{ + /* This is a naked function. */ + + __asm volatile + ( + " mrs r0, psp \n" + " isb \n" + " \n" + " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */ + " it eq \n" + " vstmdbeq r0!, {s16-s31} \n" + " \n" + " stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */ + " \n" + " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ + " \n" + " stmdb sp!, {r3} \n" + " mov r0, %0 \n" + " msr basepri, r0 \n" + " bl vTaskSwitchContext \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldmia sp!, {r3} \n" + " \n" + " ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldr r0, [r1] \n" + " \n" + " ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */ + " \n" + " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */ + " it eq \n" + " vldmiaeq r0!, {s16-s31} \n" + " \n" + " msr psp, r0 \n" + " isb \n" + " \n" + #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ + #if WORKAROUND_PMU_CM001 == 1 + " push { r14 } \n" + " pop { pc } \n" + #endif + #endif + " \n" + " bx r14 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) + ); +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + /* The SysTick runs at the lowest interrupt priority, so when this interrupt + executes all interrupts must be unmasked. There is therefore no need to + save and then restore the interrupt mask value as its value is already + known. */ + ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* A context switch is required. Context switching is performed in + the PendSV interrupt. Pend the PendSV interrupt. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + method as that will mask interrupts that should exit sleep mode. */ + __asm volatile( "cpsid i" ); + + /* If a context switch is pending or a task is waiting for the scheduler + to be unsuspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above the cpsid instruction() + above. */ + __asm volatile( "cpsie i" ); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + set its parameter to 0 to indicate that its implementation contains + its own wait for interrupt or wait for event instruction, and so wfi + should not be executed again. However, the original expected idle + time variable must remain unmodified, so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + if( xModifiableIdleTime > 0 ) + { + __asm volatile( "dsb" ); + __asm volatile( "wfi" ); + __asm volatile( "isb" ); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); + + /* Re-enable interrupts - see comments above the cpsid instruction() + above. */ + __asm volatile( "cpsie i" ); + + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt has already executed, and the SysTick + count reloaded with ulReloadValue. Reset the + portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + underflowed because the post sleep hook did something + that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted rounded to complete tick + periods (not the ulReload value which accounted for part + ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. The critical section is used to ensure the tick interrupt + can only execute once in the case that the reload register is near + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portENTER_CRITICAL(); + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + } + portEXIT_CRITICAL(); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) +{ + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); +} +/*-----------------------------------------------------------*/ + +/* This is a naked function. */ +static void vPortEnableVFP( void ) +{ + __asm volatile + ( + " ldr.w r0, =0xE000ED88 \n" /* The FPU enable bits are in the CPACR. */ + " ldr r1, [r0] \n" + " \n" + " orr r1, r1, #( 0xf << 20 ) \n" /* Enable CP10 and CP11 coprocessors, then save back. */ + " str r1, [r0] \n" + " bx r14 " + ); +} +/*-----------------------------------------------------------*/ + +#if( configASSERT_DEFINED == 1 ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + an interrupt that has been assigned a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + function. ISR safe FreeRTOS API functions must *only* be called + from interrupts that have been assigned a priority at or below + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Numerically low interrupt priority numbers represent logically high + interrupt priorities, therefore the priority of the interrupt must + be set to a value equal to or numerically *higher* than + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Interrupts that use the FreeRTOS API must not be left at their + default priority of zero as that is the highest possible priority, + which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + and therefore also guaranteed to be invalid. + + FreeRTOS maintains separate thread and ISR API functions to ensure + interrupt entry is as fast and simple as possible. + + The following links provide detailed information: + http://www.freertos.org/RTOS-Cortex-M3-M4.html + http://www.freertos.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + that define each interrupt's priority to be split between bits that + define the interrupt's pre-emption priority bits and bits that define + the interrupt's sub-priority. For simplicity all bits must be defined + to be pre-emption priority bits. The following assertion will fail if + this is not the case (if some bits represent a sub-priority). + + If the application only uses CMSIS libraries for interrupt + configuration then the correct setting can be achieved on all Cortex-M + devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + scheduler. Note however that some vendor specific peripheral libraries + assume a non-zero priority group setting, in which cases using a value + of zero will result in unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* configASSERT_DEFINED */ + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/portmacro.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/portmacro.h new file mode 100644 index 0000000..ea4a54d --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/portmacro.h @@ -0,0 +1,196 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + + +/* Scheduler utilities. */ +extern void vPortYield( void ); +#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portYIELD() vPortYield() +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + +/* Critical section management. */ +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); +extern uint32_t ulPortSetInterruptMask( void ); +extern void vPortClearInterruptMask( uint32_t ulNewMaskValue ); +#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) +#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() +#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() + +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/*-----------------------------------------------------------*/ + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + + /* Generic helper function. */ + __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint8_t ucReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) ); + return ucReturn; + } + + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /*-----------------------------------------------------------*/ + + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + +#ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +#endif + +/* portNOP() is not required by this port. */ +#define portNOP() + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/port.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/port.c new file mode 100644 index 0000000..6014eb6 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/port.c @@ -0,0 +1,655 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM3 port. + *----------------------------------------------------------*/ + +/* IAR includes. */ +#include + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Platform includes */ +#include "platform_autoconf.h" + +#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 + #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + /* The way the SysTick is clocked is not modified in case it is not the same + as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) + +/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ +#define portVECTACTIVE_MASK ( 0x1FUL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) + +/* The systick is a 24-bit counter. */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/* A fiddle factor to estimate the number of SysTick counts that would have +occurred while the SysTick counter is stopped during tickless idle +calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) + +/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is +defined. The value 255 should also ensure backward compatibility. +FreeRTOS.org versions prior to V4.3.0 did not include this definition. */ +#ifndef configKERNEL_INTERRUPT_PRIORITY + #define configKERNEL_INTERRUPT_PRIORITY 255 +#endif + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortSysTickHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +extern void vPortStartFirstTask( void ); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulTimerCountsForOneTick = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * FreeRTOS API functions are not called from interrupts that have been assigned + * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. + */ +#if ( configASSERT_DEFINED == 1 ) + static uint8_t ucMaxSysCallPriority = 0; + static uint32_t ulMaxPRIGROUPValue = 0; + static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16; +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + #if( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + functions can be called. ISR safe functions are those that end in + "FromISR". FreeRTOS maintains separate thread and ISR API functions to + ensure interrupt entry is as fast and simple as possible. + + Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to all + possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Calculate the maximum acceptable priority group value for the number + of bits read back. */ + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulMaxPRIGROUPValue--; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + /* Shift the priority group value back to its position within the AIRCR + register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ + + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + vPortSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + vPortStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is completely + within the specified behaviour for the architecture. */ + __DSB(); + __ISB(); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __DSB(); + __ISB(); + + /* This is not the interrupt safe version of the enter critical function so + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + /* The SysTick runs at the lowest interrupt priority, so when this interrupt + executes all interrupts must be unmasked. There is therefore no need to + save and then restore the interrupt mask value as its value is already + known. */ + ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* A context switch is required. Context switching is performed in + the PendSV interrupt. Pend the PendSV interrupt. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + method as that will mask interrupts that should exit sleep mode. */ + __disable_interrupt(); + + /* If a context switch is pending or a task is waiting for the scheduler + to be unsuspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above __disable_interrupt() + call above. */ + __enable_interrupt(); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + set its parameter to 0 to indicate that its implementation contains + its own wait for interrupt or wait for event instruction, and so wfi + should not be executed again. However, the original expected idle + time variable must remain unmodified, so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + if( xModifiableIdleTime > 0 ) + { + __DSB(); + __WFI(); + __ISB(); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); + + /* Re-enable interrupts - see comments above __disable_interrupt() + call above. */ + __enable_interrupt(); + + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt has already executed, and the SysTick + count reloaded with ulReloadValue. Reset the + portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + underflowed because the post sleep hook did something + that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted rounded to complete tick + periods (not the ulReload value which accounted for part + ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. The critical section is used to ensure the tick interrupt + can only execute once in the case that the reload register is near + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portENTER_CRITICAL(); + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + } + portEXIT_CRITICAL(); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +__weak void vPortSetupTimerInterrupt( void ) +{ + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); +#ifdef CONFIG_SOC_PS_MODULE + // RTK modified: max system timer can sleep up to 8355ms, set it to 8000 + xMaximumPossibleSuppressedTicks = 8000; +#else // Below is original code. It can only sleep 100ms in 166MHz + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; +#endif + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); +} +/*-----------------------------------------------------------*/ + +#if( configASSERT_DEFINED == 1 ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + an interrupt that has been assigned a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + function. ISR safe FreeRTOS API functions must *only* be called + from interrupts that have been assigned a priority at or below + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Numerically low interrupt priority numbers represent logically high + interrupt priorities, therefore the priority of the interrupt must + be set to a value equal to or numerically *higher* than + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Interrupts that use the FreeRTOS API must not be left at their + default priority of zero as that is the highest possible priority, + which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + and therefore also guaranteed to be invalid. + + FreeRTOS maintains separate thread and ISR API functions to ensure + interrupt entry is as fast and simple as possible. + + The following links provide detailed information: + http://www.freertos.org/RTOS-Cortex-M3-M4.html + http://www.freertos.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + that define each interrupt's priority to be split between bits that + define the interrupt's pre-emption priority bits and bits that define + the interrupt's sub-priority. For simplicity all bits must be defined + to be pre-emption priority bits. The following assertion will fail if + this is not the case (if some bits represent a sub-priority). + + If the application only uses CMSIS libraries for interrupt + configuration then the correct setting can be achieved on all Cortex-M + devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + scheduler. Note however that some vendor specific peripheral libraries + assume a non-zero priority group setting, in which cases using a value + of zero will result in unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ +void vApplicationIdleHook( void ) +{ + /* Use the idle task to place the CPU into a low power mode. Greater power + saving could be achieved by not including any demo tasks that never block. */ +} + +void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName ) +{ + /* This function will be called if a task overflows its stack, if + configCHECK_FOR_STACK_OVERFLOW != 0. It might be that the function + parameters have been corrupted, depending on the severity of the stack + overflow. When this is the case pxCurrentTCB can be inspected in the + debugger to find the offending task. */ +// DiagPrintf("\n\r[%s] STACK OVERFLOW - TaskName(%s)\n\r", __FUNCTION__, pcTaskName); + for( ;; ); +} + +/*-----------------------------------------------------------*/ + + + + + + + + + + + + + + + + + + + + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portasm.s b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portasm.s new file mode 100644 index 0000000..e98645c --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portasm.s @@ -0,0 +1,155 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#include + + RSEG CODE:CODE(2) + thumb + + EXTERN pxCurrentTCB + EXTERN vTaskSwitchContext + + PUBLIC xPortPendSVHandler + PUBLIC ulPortSetInterruptMask + PUBLIC vPortClearInterruptMask + PUBLIC vPortSVCHandler + PUBLIC vPortStartFirstTask + + + +/*-----------------------------------------------------------*/ + +xPortPendSVHandler: + mrs r0, psp + isb + ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ + ldr r2, [r3] + + stmdb r0!, {r4-r11} /* Save the remaining registers. */ + str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ + + stmdb sp!, {r3, r14} + mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r0 + bl vTaskSwitchContext + mov r0, #0 + msr basepri, r0 + ldmia sp!, {r3, r14} + + ldr r1, [r3] + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + ldmia r0!, {r4-r11} /* Pop the registers. */ + msr psp, r0 + isb + bx r14 + + +/*-----------------------------------------------------------*/ + +ulPortSetInterruptMask: + mrs r0, basepri + mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r1 + bx r14 + +/*-----------------------------------------------------------*/ + +vPortClearInterruptMask: + msr basepri, r0 + bx r14 + +/*-----------------------------------------------------------*/ + +vPortSVCHandler: + /* Get the location of the current TCB. */ + ldr r3, =pxCurrentTCB + ldr r1, [r3] + ldr r0, [r1] + /* Pop the core registers. */ + ldmia r0!, {r4-r11} + msr psp, r0 + isb + mov r0, #0 + msr basepri, r0 + orr r14, r14, #13 + bx r14 + +/*-----------------------------------------------------------*/ + +vPortStartFirstTask + /* Use the NVIC offset register to locate the stack. */ + ldr r0, =0xE000ED08 + ldr r0, [r0] + ldr r0, [r0] + /* Set the msp back to the start of the stack. */ + msr msp, r0 + /* Call SVC to start the first task, ensuring interrupts are enabled. */ + cpsie i + cpsie f + dsb + isb + svc 0 + + END diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portmacro.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portmacro.h new file mode 100644 index 0000000..df57a31 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portmacro.h @@ -0,0 +1,210 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_PLATFORM_8195A +// to prevent marco define use in standard header file +#define _NO_DEFINITIONS_IN_HEADER_FILES +#include +//#include "basic_types.h" +#include "hal_misc.h" +#if !defined(__IARSTDLIB__) +#ifndef memcmp +#define memcmp(dst, src, sz) _memcmp(dst, src, sz) +#endif +#ifndef memset +#define memset(dst, val, sz) _memset(dst, val, sz) +#endif +#ifndef memcpy +#define memcpy(dst, src, sz) _memcpy(dst, src, sz) +#endif +#endif +#endif +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* Scheduler utilities. */ +extern void vPortYield( void ); +#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04UL ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portYIELD() vPortYield() +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + +/* Architecture specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) ) + + /*-----------------------------------------------------------*/ + + #include + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + +/* Critical section management. */ +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); +extern uint32_t ulPortSetInterruptMask( void ); +extern void vPortClearInterruptMask( uint32_t ulNewMask ); + +#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() +#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask( x ) +/*-----------------------------------------------------------*/ + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/*-----------------------------------------------------------*/ + +#ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +#endif + +/* portNOP() is not required by this port. */ +#define portNOP() + +/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in +the source code because to do so would cause other compilers to generate +warnings. */ +#pragma diag_suppress=Pe191 +#pragma diag_suppress=Pa082 + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/port.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/port.c new file mode 100644 index 0000000..c746c30 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/port.c @@ -0,0 +1,659 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM4F port. + *----------------------------------------------------------*/ + +/* Compiler includes. */ +#include + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +#ifndef __ARMVFP__ + #error This port can only be used when the project options are configured to enable hardware floating point support. +#endif + +#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 + #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + /* The way the SysTick is clocked is not modified in case it is not the same + as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) + +/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ +#define portVECTACTIVE_MASK ( 0x1FUL ) + +/* Constants required to manipulate the VFP. */ +#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */ +#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) +#define portINITIAL_EXEC_RETURN ( 0xfffffffd ) + +/* The systick is a 24-bit counter. */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/* A fiddle factor to estimate the number of SysTick counts that would have +occurred while the SysTick counter is stopped during tickless idle +calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) + + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortSysTickHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +extern void vPortStartFirstTask( void ); + +/* + * Turn the VFP on. + */ +extern void vPortEnableVFP( void ); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulTimerCountsForOneTick = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * FreeRTOS API functions are not called from interrupts that have been assigned + * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. + */ +#if ( configASSERT_DEFINED == 1 ) + static uint8_t ucMaxSysCallPriority = 0; + static uint32_t ulMaxPRIGROUPValue = 0; + static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16; +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + + /* Offset added to account for the way the MCU uses the stack on entry/exit + of interrupts, and to ensure alignment. */ + pxTopOfStack--; + + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */ + + /* Save code space by skipping register initialisation. */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + + /* A save method is being used that requires each task to maintain its + own exec return value. */ + pxTopOfStack--; + *pxTopOfStack = portINITIAL_EXEC_RETURN; + + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + #if( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + functions can be called. ISR safe functions are those that end in + "FromISR". FreeRTOS maintains separate thread and ISR API functions to + ensure interrupt entry is as fast and simple as possible. + + Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to all + possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Calculate the maximum acceptable priority group value for the number + of bits read back. */ + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulMaxPRIGROUPValue--; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + /* Shift the priority group value back to its position within the AIRCR + register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ + + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + vPortSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Ensure the VFP is enabled - it should be anyway. */ + vPortEnableVFP(); + + /* Lazy save always. */ + *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; + + /* Start the first task. */ + vPortStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is completely + within the specified behaviour for the architecture. */ + __DSB(); + __ISB(); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __DSB(); + __ISB(); + + /* This is not the interrupt safe version of the enter critical function so + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + /* The SysTick runs at the lowest interrupt priority, so when this interrupt + executes all interrupts must be unmasked. There is therefore no need to + save and then restore the interrupt mask value as its value is already + known. */ + ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* A context switch is required. Context switching is performed in + the PendSV interrupt. Pend the PendSV interrupt. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + method as that will mask interrupts that should exit sleep mode. */ + __disable_interrupt(); + + /* If a context switch is pending or a task is waiting for the scheduler + to be unsuspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above __disable_interrupt() + call above. */ + __enable_interrupt(); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + set its parameter to 0 to indicate that its implementation contains + its own wait for interrupt or wait for event instruction, and so wfi + should not be executed again. However, the original expected idle + time variable must remain unmodified, so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + if( xModifiableIdleTime > 0 ) + { + __DSB(); + __WFI(); + __ISB(); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); + + /* Re-enable interrupts - see comments above __disable_interrupt() + call above. */ + __enable_interrupt(); + + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt has already executed, and the SysTick + count reloaded with ulReloadValue. Reset the + portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + underflowed because the post sleep hook did something + that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted rounded to complete tick + periods (not the ulReload value which accounted for part + ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. The critical section is used to ensure the tick interrupt + can only execute once in the case that the reload register is near + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portENTER_CRITICAL(); + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + } + portEXIT_CRITICAL(); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +__weak void vPortSetupTimerInterrupt( void ) +{ + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); +} +/*-----------------------------------------------------------*/ + +#if( configASSERT_DEFINED == 1 ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + an interrupt that has been assigned a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + function. ISR safe FreeRTOS API functions must *only* be called + from interrupts that have been assigned a priority at or below + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Numerically low interrupt priority numbers represent logically high + interrupt priorities, therefore the priority of the interrupt must + be set to a value equal to or numerically *higher* than + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Interrupts that use the FreeRTOS API must not be left at their + default priority of zero as that is the highest possible priority, + which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + and therefore also guaranteed to be invalid. + + FreeRTOS maintains separate thread and ISR API functions to ensure + interrupt entry is as fast and simple as possible. + + The following links provide detailed information: + http://www.freertos.org/RTOS-Cortex-M3-M4.html + http://www.freertos.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + that define each interrupt's priority to be split between bits that + define the interrupt's pre-emption priority bits and bits that define + the interrupt's sub-priority. For simplicity all bits must be defined + to be pre-emption priority bits. The following assertion will fail if + this is not the case (if some bits represent a sub-priority). + + If the application only uses CMSIS libraries for interrupt + configuration then the correct setting can be achieved on all Cortex-M + devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + scheduler. Note however that some vendor specific peripheral libraries + assume a non-zero priority group setting, in which cases using a value + of zero will result in unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* configASSERT_DEFINED */ + +void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName ) +{ + /* This function will be called if a task overflows its stack, if + configCHECK_FOR_STACK_OVERFLOW != 0 */ + + printf("\n\r[%s] STACK OVERFLOW - TaskName(%s)\n\r", __FUNCTION__, pcTaskName); + for( ;; ); +} + + + + + + + + + + + + + + + + + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portasm.s b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portasm.s new file mode 100644 index 0000000..d67bc5e --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portasm.s @@ -0,0 +1,195 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +#include + + RSEG CODE:CODE(2) + thumb + + EXTERN pxCurrentTCB + EXTERN vTaskSwitchContext + + PUBLIC xPortPendSVHandler + PUBLIC ulPortSetInterruptMask + PUBLIC vPortClearInterruptMask + PUBLIC vPortSVCHandler + PUBLIC vPortStartFirstTask + PUBLIC vPortEnableVFP + + +/*-----------------------------------------------------------*/ + +xPortPendSVHandler: + mrs r0, psp + isb + /* Get the location of the current TCB. */ + ldr r3, =pxCurrentTCB + ldr r2, [r3] + + /* Is the task using the FPU context? If so, push high vfp registers. */ + tst r14, #0x10 + it eq + vstmdbeq r0!, {s16-s31} + + /* Save the core registers. */ + stmdb r0!, {r4-r11, r14} + + /* Save the new top of stack into the first member of the TCB. */ + str r0, [r2] + + stmdb sp!, {r3} + mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r0 + bl vTaskSwitchContext + mov r0, #0 + msr basepri, r0 + ldmia sp!, {r3} + + /* The first item in pxCurrentTCB is the task top of stack. */ + ldr r1, [r3] + ldr r0, [r1] + + /* Pop the core registers. */ + ldmia r0!, {r4-r11, r14} + + /* Is the task using the FPU context? If so, pop the high vfp registers + too. */ + tst r14, #0x10 + it eq + vldmiaeq r0!, {s16-s31} + + msr psp, r0 + isb + #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */ + #if WORKAROUND_PMU_CM001 == 1 + push { r14 } + pop { pc } + #endif + #endif + + bx r14 + + +/*-----------------------------------------------------------*/ + +ulPortSetInterruptMask: + mrs r0, basepri + mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r1 + bx r14 + +/*-----------------------------------------------------------*/ + +vPortClearInterruptMask: + msr basepri, r0 + bx r14 + +/*-----------------------------------------------------------*/ + +vPortSVCHandler: + /* Get the location of the current TCB. */ + ldr r3, =pxCurrentTCB + ldr r1, [r3] + ldr r0, [r1] + /* Pop the core registers. */ + ldmia r0!, {r4-r11, r14} + msr psp, r0 + isb + mov r0, #0 + msr basepri, r0 + bx r14 + +/*-----------------------------------------------------------*/ + +vPortStartFirstTask + /* Use the NVIC offset register to locate the stack. */ + ldr r0, =0xE000ED08 + ldr r0, [r0] + ldr r0, [r0] + /* Set the msp back to the start of the stack. */ + msr msp, r0 + /* Call SVC to start the first task. */ + cpsie i + cpsie f + dsb + isb + svc 0 + +/*-----------------------------------------------------------*/ + +vPortEnableVFP: + /* The FPU enable bits are in the CPACR. */ + ldr.w r0, =0xE000ED88 + ldr r1, [r0] + + /* Enable CP10 and CP11 coprocessors, then save back. */ + orr r1, r1, #( 0xf << 20 ) + str r1, [r0] + bx r14 + + + + END + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portmacro.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portmacro.h new file mode 100644 index 0000000..24599a1 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portmacro.h @@ -0,0 +1,193 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* Scheduler utilities. */ +extern void vPortYield( void ); +#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portYIELD() vPortYield() +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + +/* Architecture specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /*-----------------------------------------------------------*/ + + #include + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + +/* Critical section management. */ +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); +extern uint32_t ulPortSetInterruptMask( void ); +extern void vPortClearInterruptMask( uint32_t ulNewMask ); + +#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() +#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask( x ) +/*-----------------------------------------------------------*/ + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif + +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/*-----------------------------------------------------------*/ + +#ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +#endif + +/* portNOP() is not required by this port. */ +#define portNOP() + +/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in +the source code because to do so would cause other compilers to generate +warnings. */ +#pragma diag_suppress=Pe191 +#pragma diag_suppress=Pa082 + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/Makefile b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/Makefile new file mode 100644 index 0000000..b0be4b9 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/Makefile @@ -0,0 +1,41 @@ + +include $(MAKE_INCLUDE_GEN) + +.PHONY: all clean + +MODULE_IFLAGS = -I../../include + + +#*****************************************************************************# +# Object FILE LIST # +#*****************************************************************************# +OBJS = heap_4.o +ifeq ($(CONFIG_RELEASE_BUILD),y) + OBJS = +else +endif + + +#*****************************************************************************# +# RULES TO GENERATE TARGETS # +#*****************************************************************************# + +# Define the Rules to build the core targets +all: CORE_TARGETS COPY_RAM_OBJS + + +#*****************************************************************************# +# GENERATE OBJECT FILE +#*****************************************************************************# +CORE_TARGETS: $(OBJS) + +-include $(DEPS) + +#*****************************************************************************# +# RULES TO CLEAN TARGETS # +#*****************************************************************************# +clean: + $(REMOVE) *.o + $(REMOVE) *.i + $(REMOVE) *.s + $(REMOVE) *.d \ No newline at end of file diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_1.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_1.c new file mode 100644 index 0000000..65d4f37 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_1.c @@ -0,0 +1,170 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +/* + * The simplest possible implementation of pvPortMalloc(). Note that this + * implementation does NOT allow allocated memory to be freed again. + * + * See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* A few bytes might be lost to byte aligning the heap start address. */ +#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) + +/* Allocate the memory for the heap. */ +static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; +static size_t xNextFreeByte = ( size_t ) 0; + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +void *pvReturn = NULL; +static uint8_t *pucAlignedHeap = NULL; + + /* Ensure that blocks are always aligned to the required number of bytes. */ + #if portBYTE_ALIGNMENT != 1 + if( xWantedSize & portBYTE_ALIGNMENT_MASK ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + } + #endif + + vTaskSuspendAll(); + { + if( pucAlignedHeap == NULL ) + { + /* Ensure the heap starts on a correctly aligned boundary. */ + pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); + } + + /* Check there is enough room left for the allocation. */ + if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) && + ( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) )/* Check for overflow. */ + { + /* Return the next free byte then increment the index past this + block. */ + pvReturn = pucAlignedHeap + xNextFreeByte; + xNextFreeByte += xWantedSize; + } + + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ + /* Memory cannot be freed using this scheme. See heap_2.c, heap_3.c and + heap_4.c for alternative implementations, and the memory management pages of + http://www.FreeRTOS.org for more information. */ + ( void ) pv; + + /* Force an assert as it is invalid to call this function. */ + configASSERT( pv == NULL ); +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* Only required when static memory is not cleared. */ + xNextFreeByte = ( size_t ) 0; +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return ( configADJUSTED_HEAP_SIZE - xNextFreeByte ); +} + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_2.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_2.c new file mode 100644 index 0000000..a28a560 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_2.c @@ -0,0 +1,299 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * A sample implementation of pvPortMalloc() and vPortFree() that permits + * allocated blocks to be freed, but does not combine adjacent free blocks + * into a single larger block (and so will fragment memory). See heap_4.c for + * an equivalent that does combine adjacent blocks into single larger blocks. + * + * See heap_1.c, heap_3.c and heap_4.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* A few bytes might be lost to byte aligning the heap start address. */ +#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) + +/* + * Initialises the heap structures before their first use. + */ +static void prvHeapInit( void ); + +/* Allocate the memory for the heap. */ +static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; + +/* Define the linked list structure. This is used to link free blocks in order +of their size. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ + size_t xBlockSize; /*<< The size of the free block. */ +} BlockLink_t; + + +static const uint16_t heapSTRUCT_SIZE = ( ( sizeof ( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK ); +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) ) + +/* Create a couple of list links to mark the start and end of the list. */ +static BlockLink_t xStart, xEnd; + +/* Keeps track of the number of free bytes remaining, but says nothing about +fragmentation. */ +static size_t xFreeBytesRemaining = configADJUSTED_HEAP_SIZE; + +/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */ + +/* + * Insert a block into the list of free blocks - which is ordered by size of + * the block. Small blocks at the start of the list and large blocks at the end + * of the list. + */ +#define prvInsertBlockIntoFreeList( pxBlockToInsert ) \ +{ \ +BlockLink_t *pxIterator; \ +size_t xBlockSize; \ + \ + xBlockSize = pxBlockToInsert->xBlockSize; \ + \ + /* Iterate through the list until a block is found that has a larger size */ \ + /* than the block we are inserting. */ \ + for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock ) \ + { \ + /* There is nothing to do here - just iterate to the correct position. */ \ + } \ + \ + /* Update the list to include the block being inserted in the correct */ \ + /* position. */ \ + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; \ + pxIterator->pxNextFreeBlock = pxBlockToInsert; \ +} +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; +static BaseType_t xHeapHasBeenInitialised = pdFALSE; +void *pvReturn = NULL; + + vTaskSuspendAll(); + { + /* If this is the first call to malloc then the heap will require + initialisation to setup the list of free blocks. */ + if( xHeapHasBeenInitialised == pdFALSE ) + { + prvHeapInit(); + xHeapHasBeenInitialised = pdTRUE; + } + + /* The wanted size is increased so it can contain a BlockLink_t + structure in addition to the requested amount of bytes. */ + if( xWantedSize > 0 ) + { + xWantedSize += heapSTRUCT_SIZE; + + /* Ensure that blocks are always aligned to the required number of bytes. */ + if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0 ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + } + } + + if( ( xWantedSize > 0 ) && ( xWantedSize < configADJUSTED_HEAP_SIZE ) ) + { + /* Blocks are stored in byte order - traverse the list from the start + (smallest) block until one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = xStart.pxNextFreeBlock; + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } + + /* If we found the end marker then a block of adequate size was not found. */ + if( pxBlock != &xEnd ) + { + /* Return the memory space - jumping over the BlockLink_t structure + at its start. */ + pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE ); + + /* This block is being returned for use so must be taken out of the + list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into two. */ + if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) + { + /* This block is to be split into two. Create a new block + following the number of bytes requested. The void cast is + used to prevent byte alignment warnings from the compiler. */ + pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); + + /* Calculate the sizes of two blocks split from the single + block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); + } + + xFreeBytesRemaining -= pxBlock->xBlockSize; + } + } + + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ +uint8_t *puc = ( uint8_t * ) pv; +BlockLink_t *pxLink; + + if( pv != NULL ) + { + /* The memory being freed will have an BlockLink_t structure immediately + before it. */ + puc -= heapSTRUCT_SIZE; + + /* This unexpected casting is to keep some compilers from issuing + byte alignment warnings. */ + pxLink = ( void * ) puc; + + vTaskSuspendAll(); + { + /* Add this block to the list of free blocks. */ + prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); + xFreeBytesRemaining += pxLink->xBlockSize; + traceFREE( pv, pxLink->xBlockSize ); + } + ( void ) xTaskResumeAll(); + } +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* This just exists to keep the linker quiet. */ +} +/*-----------------------------------------------------------*/ + +static void prvHeapInit( void ) +{ +BlockLink_t *pxFirstFreeBlock; +uint8_t *pucAlignedHeap; + + /* Ensure the heap starts on a correctly aligned boundary. */ + pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); + + /* xStart is used to hold a pointer to the first item in the list of free + blocks. The void cast is used to prevent compiler warnings. */ + xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap; + xStart.xBlockSize = ( size_t ) 0; + + /* xEnd is used to mark the end of the list of free blocks. */ + xEnd.xBlockSize = configADJUSTED_HEAP_SIZE; + xEnd.pxNextFreeBlock = NULL; + + /* To start with there is a single free block that is sized to take up the + entire heap space. */ + pxFirstFreeBlock = ( void * ) pucAlignedHeap; + pxFirstFreeBlock->xBlockSize = configADJUSTED_HEAP_SIZE; + pxFirstFreeBlock->pxNextFreeBlock = &xEnd; +} +/*-----------------------------------------------------------*/ diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_3.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_3.c new file mode 100644 index 0000000..8b948bf --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_3.c @@ -0,0 +1,131 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +/* + * Implementation of pvPortMalloc() and vPortFree() that relies on the + * compilers own malloc() and free() implementations. + * + * This file can only be used if the linker is configured to to generate + * a heap memory area. + * + * See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ + +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +void *pvReturn; + + vTaskSuspendAll(); + { + pvReturn = malloc( xWantedSize ); + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ + if( pv ) + { + vTaskSuspendAll(); + { + free( pv ); + traceFREE( pv, 0 ); + } + ( void ) xTaskResumeAll(); + } +} + + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_4.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_4.c new file mode 100644 index 0000000..7af6b6a --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_4.c @@ -0,0 +1,544 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/* + * A sample implementation of pvPortMalloc() and vPortFree() that combines + * (coalescences) adjacent memory blocks as they are freed, and in so doing + * limits memory fragmentation. + * + * See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* Block sizes must not get too small. */ +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize * 2 ) ) + +/* Assumes 8bit bytes! */ +#define heapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Allocate the memory for the heap. */ +//TODO: remove section when combine BD and BF +#if ((defined CONFIG_PLATFORM_8195A) || (defined CONFIG_PLATFORM_8711B)) +#include "section_config.h" +SRAM_BF_DATA_SECTION +#endif + +static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; + +/* Define the linked list structure. This is used to link free blocks in order +of their memory address. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ + size_t xBlockSize; /*<< The size of the free block. */ +} BlockLink_t; + +/*-----------------------------------------------------------*/ + +/* + * Inserts a block of memory that is being freed into the correct position in + * the list of free memory blocks. The block being freed will be merged with + * the block in front it and/or the block behind it if the memory blocks are + * adjacent to each other. + */ +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ); + +/* + * Called automatically to setup the required heap structures the first time + * pvPortMalloc() is called. + */ +static void prvHeapInit( void ); + +/*-----------------------------------------------------------*/ + +/* The size of the structure placed at the beginning of each allocated memory +block must by correctly byte aligned. */ +static const size_t xHeapStructSize = ( ( sizeof( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK ); + +/* Create a couple of list links to mark the start and end of the list. */ +static BlockLink_t xStart, *pxEnd = NULL; + +/* Keeps track of the number of free bytes remaining, but says nothing about +fragmentation. */ +static size_t xFreeBytesRemaining = 0U; +static size_t xMinimumEverFreeBytesRemaining = 0U; + +/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize +member of an BlockLink_t structure is set then the block belongs to the +application. When the bit is free the block is still part of the free heap +space. */ +static size_t xBlockAllocatedBit = 0; + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; +void *pvReturn = NULL; + + vTaskSuspendAll(); + { + /* If this is the first call to malloc then the heap will require + initialisation to setup the list of free blocks. */ + if( pxEnd == NULL ) + { + prvHeapInit(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Check the requested block size is not so large that the top bit is + set. The top bit of the block size member of the BlockLink_t structure + is used to determine who owns the block - the application or the + kernel, so it must be free. */ + if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + { + /* The wanted size is increased so it can contain a BlockLink_t + structure in addition to the requested amount of bytes. */ + if( xWantedSize > 0 ) + { + xWantedSize += xHeapStructSize; + + /* Ensure that blocks are always aligned to the required number + of bytes. */ + if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) + { + /* Traverse the list from the start (lowest address) block until + one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = xStart.pxNextFreeBlock; + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } + + /* If the end marker was reached then a block of adequate size + was not found. */ + if( pxBlock != pxEnd ) + { + /* Return the memory space pointed to - jumping over the + BlockLink_t structure at its start. */ + pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize ); + + /* This block is being returned for use so must be taken out + of the list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into + two. */ + if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) + { + /* This block is to be split into two. Create a new + block following the number of bytes requested. The void + cast is used to prevent byte alignment warnings from the + compiler. */ + pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); + configASSERT( ( ( ( uint32_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 ); + + /* Calculate the sizes of two blocks split from the + single block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xFreeBytesRemaining -= pxBlock->xBlockSize; + + if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) + { + xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The block is being returned - it is allocated and owned + by the application and has no "next" block. */ + pxBlock->xBlockSize |= xBlockAllocatedBit; + pxBlock->pxNextFreeBlock = NULL; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + configASSERT( ( ( ( uint32_t ) pvReturn ) & portBYTE_ALIGNMENT_MASK ) == 0 ); + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void __vPortFree( void *pv ) +{ +uint8_t *puc = ( uint8_t * ) pv; +BlockLink_t *pxLink; + + if( pv != NULL ) + { + /* The memory being freed will have an BlockLink_t structure immediately + before it. */ + puc -= xHeapStructSize; + + /* This casting is to keep the compiler from issuing warnings. */ + pxLink = ( void * ) puc; + + /* Check the block is actually allocated. */ + configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + configASSERT( pxLink->pxNextFreeBlock == NULL ); + + if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + { + if( pxLink->pxNextFreeBlock == NULL ) + { + /* The block is being returned to the heap - it is no longer + allocated. */ + pxLink->xBlockSize &= ~xBlockAllocatedBit; + + vTaskSuspendAll(); + { + /* Add this block to the list of free blocks. */ + xFreeBytesRemaining += pxLink->xBlockSize; + traceFREE( pv, pxLink->xBlockSize ); + prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); + } + ( void ) xTaskResumeAll(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } +} +/*-----------------------------------------------------------*/ +/* Add by Alfa 2015/02/04 -----------------------------------*/ +static void (*ext_free)( void *p ) = NULL; +static uint32_t ext_upper = 0; +static uint32_t ext_lower = 0; +void vPortSetExtFree( void (*free)( void *p ), uint32_t upper, uint32_t lower ) +{ + ext_free = free; + ext_upper = upper; + ext_lower = lower; +} + +void vPortFree( void *pv ) +{ + if( ((uint32_t)pv >= ext_lower) && ((uint32_t)pv < ext_upper) ){ + // use external free function + if( ext_free ) ext_free( pv ); + }else + __vPortFree( pv ); +} + +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +size_t xPortGetMinimumEverFreeHeapSize( void ) +{ + return xMinimumEverFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* This just exists to keep the linker quiet. */ +} +/*-----------------------------------------------------------*/ + +static void prvHeapInit( void ) +{ +BlockLink_t *pxFirstFreeBlock; +uint8_t *pucAlignedHeap; +uint32_t ulAddress; +size_t xTotalHeapSize = configTOTAL_HEAP_SIZE; + + /* Ensure the heap starts on a correctly aligned boundary. */ + ulAddress = ( uint32_t ) ucHeap; + + if( ( ulAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) + { + ulAddress += ( portBYTE_ALIGNMENT - 1 ); + ulAddress &= ~portBYTE_ALIGNMENT_MASK; + xTotalHeapSize -= ulAddress - ( uint32_t ) ucHeap; + } + + pucAlignedHeap = ( uint8_t * ) ulAddress; + + /* xStart is used to hold a pointer to the first item in the list of free + blocks. The void cast is used to prevent compiler warnings. */ + xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap; + xStart.xBlockSize = ( size_t ) 0; + + /* pxEnd is used to mark the end of the list of free blocks and is inserted + at the end of the heap space. */ + ulAddress = ( ( uint32_t ) pucAlignedHeap ) + xTotalHeapSize; + ulAddress -= xHeapStructSize; + ulAddress &= ~portBYTE_ALIGNMENT_MASK; + pxEnd = ( void * ) ulAddress; + pxEnd->xBlockSize = 0; + pxEnd->pxNextFreeBlock = NULL; + + /* To start with there is a single free block that is sized to take up the + entire heap space, minus the space taken by pxEnd. */ + pxFirstFreeBlock = ( void * ) pucAlignedHeap; + pxFirstFreeBlock->xBlockSize = ulAddress - ( uint32_t ) pxFirstFreeBlock; + pxFirstFreeBlock->pxNextFreeBlock = pxEnd; + + /* Only one block exists - and it covers the entire usable heap space. */ + xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; + xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; + + /* Work out the position of the top bit in a size_t variable. */ + xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); +} +/*-----------------------------------------------------------*/ + +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ) +{ +BlockLink_t *pxIterator; +uint8_t *puc; + + /* Iterate through the list until a block is found that has a higher address + than the block being inserted. */ + for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock ) + { + /* Nothing to do here, just iterate to the right position. */ + } + + /* Do the block being inserted, and the block it is being inserted after + make a contiguous block of memory? */ + puc = ( uint8_t * ) pxIterator; + if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) + { + pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; + pxBlockToInsert = pxIterator; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Do the block being inserted, and the block it is being inserted before + make a contiguous block of memory? */ + puc = ( uint8_t * ) pxBlockToInsert; + if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock ) + { + if( pxIterator->pxNextFreeBlock != pxEnd ) + { + /* Form one big block from the two blocks. */ + pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize; + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock; + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxEnd; + } + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; + } + + /* If the block being inserted plugged a gab, so was merged with the block + before and the block after, then it's pxNextFreeBlock pointer will have + already been set, and should not be set here as that would make it point + to itself. */ + if( pxIterator != pxBlockToInsert ) + { + pxIterator->pxNextFreeBlock = pxBlockToInsert; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +} + +void* pvPortReAlloc( void *pv, size_t xWantedSize ) +{ + BlockLink_t *pxLink; + + if( ((uint32_t)pv >= ext_lower) && ((uint32_t)pv < ext_upper) ){ + if( ext_free ) ext_free( pv ); + pv = NULL; + } + + unsigned char *puc = ( unsigned char * ) pv; + + if( pv ) + { + if( !xWantedSize ) + { + vPortFree( pv ); + return NULL; + } + + void *newArea = pvPortMalloc( xWantedSize ); + if( newArea ) + { + /* The memory being freed will have an xBlockLink structure immediately + before it. */ + puc -= xHeapStructSize; + + /* This casting is to keep the compiler from issuing warnings. */ + pxLink = ( void * ) puc; + + int oldSize = (pxLink->xBlockSize & ~xBlockAllocatedBit) - xHeapStructSize; + int copySize = ( oldSize < xWantedSize ) ? oldSize : xWantedSize; + memcpy( newArea, pv, copySize ); + + vTaskSuspendAll(); + { + /* Add this block to the list of free blocks. */ + pxLink->xBlockSize &= ~xBlockAllocatedBit; + xFreeBytesRemaining += pxLink->xBlockSize; + prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); + } + xTaskResumeAll(); + return newArea; + } + } + else if( xWantedSize ) + return pvPortMalloc( xWantedSize ); + else + return NULL; + + return NULL; +} + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_5.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_5.c index f2ce52c..1c10808 100644 --- a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_5.c +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_5.c @@ -680,6 +680,15 @@ void* pvPortReAlloc( void *pv, size_t xWantedSize ) return NULL; } +extern _LONG_CALL_ROM_ void *_memset( void *s, int c, SIZE_T n ); + +void *pvPortZalloc( size_t xWantedSize ) +{ + void * prt = pvPortMalloc(xWantedSize); + if(prt) _memset(prt, 0, xWantedSize); + return prt; +} + /* #ifdef ARDUINO_SDK int vPortAddHeapRegion(uint8_t *addr, size_t size) diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/port.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/port.c new file mode 100644 index 0000000..ccd2511 --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/port.c @@ -0,0 +1,724 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM3 port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +#ifndef configKERNEL_INTERRUPT_PRIORITY + #define configKERNEL_INTERRUPT_PRIORITY 255 +#endif + +#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 + #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + /* The way the SysTick is clocked is not modified in case it is not the same + as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif + +/* The __weak attribute does not work as you might expect with the Keil tools +so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if +the application writer wants to provide their own implementation of +vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION +is defined. */ +#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION + #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ +#define portVECTACTIVE_MASK ( 0x1FUL ) + +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) + +/* Constants used with memory barrier intrinsics. */ +#define portSY_FULL_READ_WRITE ( 15 ) + +/* The systick is a 24-bit counter. */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/* A fiddle factor to estimate the number of SysTick counts that would have +occurred while the SysTick counter is stopped during tickless idle +calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +static void prvStartFirstTask( void ); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulTimerCountsForOneTick = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * FreeRTOS API functions are not called from interrupts that have been assigned + * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. + */ +#if ( configASSERT_DEFINED == 1 ) + static uint8_t ucMaxSysCallPriority = 0; + static uint32_t ulMaxPRIGROUPValue = 0; + static const volatile uint8_t * const pcInterruptPriorityRegisters = ( uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */ + + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +__asm void vPortSVCHandler( void ) +{ + PRESERVE8 + + ldr r3, =pxCurrentTCB /* Restore the context. */ + ldr r1, [r3] /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + ldmia r0!, {r4-r11} /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + msr psp, r0 /* Restore the task stack pointer. */ + isb + mov r0, #0 + msr basepri, r0 + orr r14, #0xd + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm void prvStartFirstTask( void ) +{ + PRESERVE8 + + /* Use the NVIC offset register to locate the stack. */ + ldr r0, =0xE000ED08 + ldr r0, [r0] + ldr r0, [r0] + /* Set the msp back to the start of the stack. */ + msr msp, r0 + /* Globally enable interrupts. */ + cpsie i + cpsie f + dsb + isb + /* Call SVC to start the first task. */ + svc 0 + nop + nop +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + #if( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + functions can be called. ISR safe functions are those that end in + "FromISR". FreeRTOS maintains separate thread and ISR API functions to + ensure interrupt entry is as fast and simple as possible. + + Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to all + possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Calculate the maximum acceptable priority group value for the number + of bits read back. */ + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulMaxPRIGROUPValue--; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + /* Shift the priority group value back to its position within the AIRCR + register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ + + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + vPortSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + prvStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is completely + within the specified behaviour for the architecture. */ + __dsb( portSY_FULL_READ_WRITE ); + __isb( portSY_FULL_READ_WRITE ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __dsb( portSY_FULL_READ_WRITE ); + __isb( portSY_FULL_READ_WRITE ); + + /* This is not the interrupt safe version of the enter critical function so + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +__asm void xPortPendSVHandler( void ) +{ + extern uxCriticalNesting; + extern pxCurrentTCB; + extern vTaskSwitchContext; + + PRESERVE8 + + mrs r0, psp + isb + + ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ + ldr r2, [r3] + + stmdb r0!, {r4-r11} /* Save the remaining registers. */ + str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ + + stmdb sp!, {r3, r14} + mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r0 + bl vTaskSwitchContext + mov r0, #0 + msr basepri, r0 + ldmia sp!, {r3, r14} + + ldr r1, [r3] + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */ + msr psp, r0 + isb + bx r14 + nop +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + /* The SysTick runs at the lowest interrupt priority, so when this interrupt + executes all interrupts must be unmasked. There is therefore no need to + save and then restore the interrupt mask value as its value is already + known. */ + ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* A context switch is required. Context switching is performed in + the PendSV interrupt. Pend the PendSV interrupt. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + method as that will mask interrupts that should exit sleep mode. */ + __disable_irq(); + + /* If a context switch is pending or a task is waiting for the scheduler + to be unsuspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above __disable_irq() call + above. */ + __enable_irq(); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + set its parameter to 0 to indicate that its implementation contains + its own wait for interrupt or wait for event instruction, and so wfi + should not be executed again. However, the original expected idle + time variable must remain unmodified, so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + if( xModifiableIdleTime > 0 ) + { + __dsb( portSY_FULL_READ_WRITE ); + __wfi(); + __isb( portSY_FULL_READ_WRITE ); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); + + /* Re-enable interrupts - see comments above __disable_irq() call + above. */ + __enable_irq(); + + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt has already executed, and the SysTick + count reloaded with ulReloadValue. Reset the + portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + underflowed because the post sleep hook did something + that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted rounded to complete tick + periods (not the ulReload value which accounted for part + ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. The critical section is used to ensure the tick interrupt + can only execute once in the case that the reload register is near + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portENTER_CRITICAL(); + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + } + portEXIT_CRITICAL(); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ + +/*-----------------------------------------------------------*/ + +/* + * Setup the SysTick timer to generate the tick interrupts at the required + * frequency. + */ +#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 + + void vPortSetupTimerInterrupt( void ) + { + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); + } + +#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ +/*-----------------------------------------------------------*/ + +__asm uint32_t ulPortSetInterruptMask( void ) +{ + PRESERVE8 + + mrs r0, basepri + mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r1 + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm void vPortClearInterruptMask( uint32_t ulNewMask ) +{ + PRESERVE8 + + msr basepri, r0 + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm uint32_t vPortGetIPSR( void ) +{ + PRESERVE8 + + mrs r0, ipsr + bx r14 +} +/*-----------------------------------------------------------*/ + +#if( configASSERT_DEFINED == 1 ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + ulCurrentInterrupt = vPortGetIPSR(); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + an interrupt that has been assigned a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + function. ISR safe FreeRTOS API functions must *only* be called + from interrupts that have been assigned a priority at or below + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Numerically low interrupt priority numbers represent logically high + interrupt priorities, therefore the priority of the interrupt must + be set to a value equal to or numerically *higher* than + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Interrupts that use the FreeRTOS API must not be left at their + default priority of zero as that is the highest possible priority, + which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + and therefore also guaranteed to be invalid. + + FreeRTOS maintains separate thread and ISR API functions to ensure + interrupt entry is as fast and simple as possible. + + The following links provide detailed information: + http://www.freertos.org/RTOS-Cortex-M3-M4.html + http://www.freertos.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + that define each interrupt's priority to be split between bits that + define the interrupt's pre-emption priority bits and bits that define + the interrupt's sub-priority. For simplicity all bits must be defined + to be pre-emption priority bits. The following assertion will fail if + this is not the case (if some bits represent a sub-priority). + + If the application only uses CMSIS libraries for interrupt + configuration then the correct setting can be achieved on all Cortex-M + devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + scheduler. Note however that some vendor specific peripheral libraries + assume a non-zero priority group setting, in which cases using a value + of zero will result in unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* configASSERT_DEFINED */ + + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/portmacro.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/portmacro.h new file mode 100644 index 0000000..1e97c3e --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/portmacro.h @@ -0,0 +1,185 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* Scheduler utilities. */ +extern void vPortYield( void ); +#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portYIELD() vPortYield() +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + +/* Critical section management. */ +extern uint32_t ulPortSetInterruptMask( void ); +extern void vPortClearInterruptMask( uint32_t ulNewMask ); +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); + +#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() +#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) +/*-----------------------------------------------------------*/ + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif +/*-----------------------------------------------------------*/ + +/* Port specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /*-----------------------------------------------------------*/ + + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) ) + +#endif /* taskRECORD_READY_PRIORITY */ +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/*-----------------------------------------------------------*/ + +#ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +#endif + +/* portNOP() is not required by this port. */ +#define portNOP() + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/port.c b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/port.c new file mode 100644 index 0000000..939522b --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/port.c @@ -0,0 +1,803 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM4F port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +#ifndef __TARGET_FPU_VFP + #error This port can only be used when the project options are configured to enable hardware floating point support. +#endif + +#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 + #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + /* The way the SysTick is clocked is not modified in case it is not the same + as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif + +/* The __weak attribute does not work as you might expect with the Keil tools +so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if +the application writer wants to provide their own implementation of +vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION +is defined. */ +#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION + #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) + +/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ +#define portVECTACTIVE_MASK ( 0x1FUL ) + +/* Constants required to manipulate the VFP. */ +#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */ +#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) +#define portINITIAL_EXEC_RETURN ( 0xfffffffd ) + +/* Constants used with memory barrier intrinsics. */ +#define portSY_FULL_READ_WRITE ( 15 ) + +/* The systick is a 24-bit counter. */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/* A fiddle factor to estimate the number of SysTick counts that would have +occurred while the SysTick counter is stopped during tickless idle +calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +static void prvStartFirstTask( void ); + +/* + * Functions defined in portasm.s to enable the VFP. + */ +static void prvEnableVFP( void ); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulTimerCountsForOneTick = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * FreeRTOS API functions are not called from interrupts that have been assigned + * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. + */ +#if ( configASSERT_DEFINED == 1 ) + static uint8_t ucMaxSysCallPriority = 0; + static uint32_t ulMaxPRIGROUPValue = 0; + static const volatile uint8_t * const pcInterruptPriorityRegisters = ( uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + + /* Offset added to account for the way the MCU uses the stack on entry/exit + of interrupts, and to ensure alignment. */ + pxTopOfStack--; + + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */ + + /* Save code space by skipping register initialisation. */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + + /* A save method is being used that requires each task to maintain its + own exec return value. */ + pxTopOfStack--; + *pxTopOfStack = portINITIAL_EXEC_RETURN; + + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +__asm void vPortSVCHandler( void ) +{ + PRESERVE8 + + /* Get the location of the current TCB. */ + ldr r3, =pxCurrentTCB + ldr r1, [r3] + ldr r0, [r1] + /* Pop the core registers. */ + ldmia r0!, {r4-r11, r14} + msr psp, r0 + isb + mov r0, #0 + msr basepri, r0 + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm void prvStartFirstTask( void ) +{ + PRESERVE8 + + /* Use the NVIC offset register to locate the stack. */ + ldr r0, =0xE000ED08 + ldr r0, [r0] + ldr r0, [r0] + /* Set the msp back to the start of the stack. */ + msr msp, r0 + /* Globally enable interrupts. */ + cpsie i + cpsie f + dsb + isb + /* Call SVC to start the first task. */ + svc 0 + nop + nop +} +/*-----------------------------------------------------------*/ + +__asm void prvEnableVFP( void ) +{ + PRESERVE8 + + /* The FPU enable bits are in the CPACR. */ + ldr.w r0, =0xE000ED88 + ldr r1, [r0] + + /* Enable CP10 and CP11 coprocessors, then save back. */ + orr r1, r1, #( 0xf << 20 ) + str r1, [r0] + bx r14 + nop +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + #if( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + functions can be called. ISR safe functions are those that end in + "FromISR". FreeRTOS maintains separate thread and ISR API functions to + ensure interrupt entry is as fast and simple as possible. + + Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to all + possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Calculate the maximum acceptable priority group value for the number + of bits read back. */ + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulMaxPRIGROUPValue--; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + /* Shift the priority group value back to its position within the AIRCR + register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ + + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + vPortSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Ensure the VFP is enabled - it should be anyway. */ + prvEnableVFP(); + + /* Lazy save always. */ + *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; + + /* Start the first task. */ + prvStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is completely + within the specified behaviour for the architecture. */ + __dsb( portSY_FULL_READ_WRITE ); + __isb( portSY_FULL_READ_WRITE ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __dsb( portSY_FULL_READ_WRITE ); + __isb( portSY_FULL_READ_WRITE ); + + /* This is not the interrupt safe version of the enter critical function so + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +__asm void xPortPendSVHandler( void ) +{ + extern uxCriticalNesting; + extern pxCurrentTCB; + extern vTaskSwitchContext; + + PRESERVE8 + + mrs r0, psp + isb + /* Get the location of the current TCB. */ + ldr r3, =pxCurrentTCB + ldr r2, [r3] + + /* Is the task using the FPU context? If so, push high vfp registers. */ + tst r14, #0x10 + it eq + vstmdbeq r0!, {s16-s31} + + /* Save the core registers. */ + stmdb r0!, {r4-r11, r14} + + /* Save the new top of stack into the first member of the TCB. */ + str r0, [r2] + + stmdb sp!, {r3} + mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r0 + bl vTaskSwitchContext + mov r0, #0 + msr basepri, r0 + ldmia sp!, {r3} + + /* The first item in pxCurrentTCB is the task top of stack. */ + ldr r1, [r3] + ldr r0, [r1] + + /* Pop the core registers. */ + ldmia r0!, {r4-r11, r14} + + /* Is the task using the FPU context? If so, pop the high vfp registers + too. */ + tst r14, #0x10 + it eq + vldmiaeq r0!, {s16-s31} + + msr psp, r0 + isb + #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */ + #if WORKAROUND_PMU_CM001 == 1 + push { r14 } + pop { pc } + nop + #endif + #endif + + bx r14 + nop +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + /* The SysTick runs at the lowest interrupt priority, so when this interrupt + executes all interrupts must be unmasked. There is therefore no need to + save and then restore the interrupt mask value as its value is already + known. */ + ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* A context switch is required. Context switching is performed in + the PendSV interrupt. Pend the PendSV interrupt. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + method as that will mask interrupts that should exit sleep mode. */ + __disable_irq(); + + /* If a context switch is pending or a task is waiting for the scheduler + to be unsuspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above __disable_irq() call + above. */ + __enable_irq(); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + set its parameter to 0 to indicate that its implementation contains + its own wait for interrupt or wait for event instruction, and so wfi + should not be executed again. However, the original expected idle + time variable must remain unmodified, so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + if( xModifiableIdleTime > 0 ) + { + __dsb( portSY_FULL_READ_WRITE ); + __wfi(); + __isb( portSY_FULL_READ_WRITE ); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); + + /* Re-enable interrupts - see comments above __disable_irq() call + above. */ + __enable_irq(); + + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt has already executed, and the SysTick + count reloaded with ulReloadValue. Reset the + portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + underflowed because the post sleep hook did something + that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted rounded to complete tick + periods (not the ulReload value which accounted for part + ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. The critical section is used to ensure the tick interrupt + can only execute once in the case that the reload register is near + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portENTER_CRITICAL(); + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + } + portEXIT_CRITICAL(); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ + +/*-----------------------------------------------------------*/ + +/* + * Setup the SysTick timer to generate the tick interrupts at the required + * frequency. + */ +#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 + + void vPortSetupTimerInterrupt( void ) + { + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); + } + +#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ +/*-----------------------------------------------------------*/ + +__asm uint32_t ulPortSetInterruptMask( void ) +{ + PRESERVE8 + + mrs r0, basepri + mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r1 + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm void vPortClearInterruptMask( uint32_t ulNewMask ) +{ + PRESERVE8 + + msr basepri, r0 + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm uint32_t vPortGetIPSR( void ) +{ + PRESERVE8 + + mrs r0, ipsr + bx r14 +} +/*-----------------------------------------------------------*/ + +#if( configASSERT_DEFINED == 1 ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + ulCurrentInterrupt = vPortGetIPSR(); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + an interrupt that has been assigned a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + function. ISR safe FreeRTOS API functions must *only* be called + from interrupts that have been assigned a priority at or below + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Numerically low interrupt priority numbers represent logically high + interrupt priorities, therefore the priority of the interrupt must + be set to a value equal to or numerically *higher* than + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Interrupts that use the FreeRTOS API must not be left at their + default priority of zero as that is the highest possible priority, + which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + and therefore also guaranteed to be invalid. + + FreeRTOS maintains separate thread and ISR API functions to ensure + interrupt entry is as fast and simple as possible. + + The following links provide detailed information: + http://www.freertos.org/RTOS-Cortex-M3-M4.html + http://www.freertos.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + that define each interrupt's priority to be split between bits that + define the interrupt's pre-emption priority bits and bits that define + the interrupt's sub-priority. For simplicity all bits must be defined + to be pre-emption priority bits. The following assertion will fail if + this is not the case (if some bits represent a sub-priority). + + If the application only uses CMSIS libraries for interrupt + configuration then the correct setting can be achieved on all Cortex-M + devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + scheduler. Note however that some vendor specific peripheral libraries + assume a non-zero priority group setting, in which cases using a value + of zero will result in unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* configASSERT_DEFINED */ + +void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName ) +{ + /* This function will be called if a task overflows its stack, if + configCHECK_FOR_STACK_OVERFLOW != 0. It might be that the function + parameters have been corrupted, depending on the severity of the stack + overflow. When this is the case pxCurrentTCB can be inspected in the + debugger to find the offending task. */ + printf("\n\r[%s] STACK OVERFLOW - TaskName(%s)\n\r", __FUNCTION__, pcTaskName); + for( ;; ); +} diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/portmacro.h b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/portmacro.h new file mode 100644 index 0000000..91dfb7f --- /dev/null +++ b/RTL00_SDKV35a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/portmacro.h @@ -0,0 +1,186 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + 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! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* Scheduler utilities. */ +extern void vPortYield( void ); +#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portYIELD() vPortYield() +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + +/* Critical section management. */ +extern uint32_t ulPortSetInterruptMask( void ); +extern void vPortClearInterruptMask( uint32_t ulNewMask ); +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); + +#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() +#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) + +/*-----------------------------------------------------------*/ + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif +/*-----------------------------------------------------------*/ + +/* Port specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + + /* Check the configuration. */ + #if 0//( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /*-----------------------------------------------------------*/ + + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) ) + +#endif /* taskRECORD_READY_PRIORITY */ +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/*-----------------------------------------------------------*/ + +#ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +#endif + +/* portNOP() is not required by this port. */ +#define portNOP() + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/hal_adc.h b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/hal_adc.h index 925fa6d..fbea89e 100644 --- a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/hal_adc.h +++ b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/hal_adc.h @@ -39,7 +39,6 @@ typedef enum _ADC_DBG_LVL_ { VERI_ADC_LVL = 0x04, }ADC_DBG_LVL,*PADC_DBG_LVL; -#if CONFIG_DEBUG_LOG > 0 #ifdef CONFIG_DEBUG_LOG_ADC_HAL #define DBG_8195A_ADC(...) do{ \ @@ -58,7 +57,6 @@ typedef enum _ADC_DBG_LVL_ { #define DBG_8195A_ADC(...) #define DBG_8195A_ADC_LVL(...) #endif -#endif //================ ADC HAL Related Enumeration ================== @@ -292,8 +290,8 @@ RtkADCIdxChk( #endif #if !ADC3_USED - if (ADCIdx == ADC3_SEL) - return _EXIT_FAILURE; + if (ADCIdx == ADC3_SEL) + return _EXIT_FAILURE; #endif ADCIdx++; //for compile warning. return _EXIT_SUCCESS; diff --git a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/hal_log_uart.h b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/hal_log_uart.h index f4f5633..63e770b 100644 --- a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/hal_log_uart.h +++ b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/hal_log_uart.h @@ -146,5 +146,6 @@ VOID HalLogUartAbortIntRecv(HAL_LOG_UART_ADAPTER *pUartAdapter); HAL_Status HalLogUartRstFIFO(HAL_LOG_UART_ADAPTER *pUartAdapter, u8 RstCtrl); VOID HalLogUartEnable(HAL_LOG_UART_ADAPTER *pUartAdapter); VOID HalLogUartDisable(HAL_LOG_UART_ADAPTER *pUartAdapter); +VOID HalLogUartWaitTxFifoEmpty(VOID); #endif diff --git a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_ssi.c b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_ssi.c index 99e5568..f992d3d 100644 --- a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_ssi.c +++ b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_ssi.c @@ -111,7 +111,7 @@ VOID _SsiWriteInterruptRtl8195a(VOID *Adapter) if (pHalSsiAdapter->TxLength == 0) { pHalSsiAdapter->InterruptMask &= ~(BIT_IMR_TXEIM); HalSsiSetInterruptMaskRtl8195a((VOID*)pHalSsiAdapter); - for (i=0;i<1000000;i++) { + for (i=0;i<1000000;i++) { bus_busy = HAL_SSI_READ32(Index, REG_DW_SSI_SR) & BIT_SR_BUSY; if (!bus_busy) { break; // break the for loop diff --git a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/src/hal_adc.c b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/src/hal_adc.c index a91b7ab..ed21f08 100644 --- a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/src/hal_adc.c +++ b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/src/hal_adc.c @@ -259,7 +259,8 @@ VOID HalADCOpInit( // Author: // By Jason Deng, 2014-04-02. // -//--------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------- +#define sizealign4(x) ((sizeof(x) + 3) & (~3)) PSAL_ADC_MNGT_ADPT RtkADCGetMngtAdpt( IN u8 ADCIdx @@ -269,6 +270,40 @@ RtkADCGetMngtAdpt( /* If the kernel is available, Memory-allocation is used. */ #if (!ADC_STATIC_ALLOC) +#if 1 // pvvx + pSalADCMngtAdpt = (PSAL_ADC_MNGT_ADPT)RtlZmalloc( + sizealign4(SAL_ADC_MNGT_ADPT) + + sizealign4(SAL_ADC_HND_PRIV) + + sizealign4(HAL_ADC_INIT_DAT) + + sizealign4(HAL_ADC_OP) + + sizealign4(IRQ_HANDLE) + + sizealign4(SAL_ADC_USER_CB) + + sizealign4(HAL_GDMA_ADAPTER) + + sizealign4(HAL_GDMA_OP) + + sizealign4(IRQ_HANDLE) + + (sizealign4(SAL_ADC_USERCB_ADPT)*SAL_ADC_USER_CB_NUM)); + if(!pSalADCMngtAdpt) { + return pSalADCMngtAdpt; + }; + unsigned char *ptr = (unsigned char *)pSalADCMngtAdpt + sizeof(SAL_ADC_MNGT_ADPT); + pSalADCMngtAdpt->pSalHndPriv = (PSAL_ADC_HND_PRIV)ptr; + ptr += sizealign4(SAL_ADC_HND_PRIV); + pSalADCMngtAdpt->pHalInitDat = (PHAL_ADC_INIT_DAT)ptr; + ptr += sizealign4(HAL_ADC_INIT_DAT); + pSalADCMngtAdpt->pHalOp = (PHAL_ADC_OP)ptr; + ptr += sizealign4(HAL_ADC_OP); + pSalADCMngtAdpt->pIrqHnd = (PIRQ_HANDLE)ptr; + ptr += sizealign4(IRQ_HANDLE); + pSalADCMngtAdpt->pUserCB = (PSAL_ADC_USER_CB)ptr; + ptr += sizealign4(SAL_ADC_USER_CB); + pSalADCMngtAdpt->pHalGdmaAdp = (PHAL_GDMA_ADAPTER)ptr; + ptr += sizealign4(HAL_GDMA_ADAPTER); + pSalADCMngtAdpt->pHalGdmaOp = (PHAL_GDMA_OP)ptr; + ptr += sizealign4(HAL_GDMA_OP); + pSalADCMngtAdpt->pIrqGdmaHnd = (PIRQ_HANDLE)ptr; + ptr += sizealign4(IRQ_HANDLE); + pSalADCUserCBAdpt = (PSAL_ADC_USERCB_ADPT)ptr; +#else pSalADCMngtAdpt = (PSAL_ADC_MNGT_ADPT)RtlZmalloc(sizeof(SAL_ADC_MNGT_ADPT)); pSalADCMngtAdpt->pSalHndPriv = (PSAL_ADC_HND_PRIV)RtlZmalloc(sizeof(SAL_ADC_HND_PRIV)); pSalADCMngtAdpt->pHalInitDat = (PHAL_ADC_INIT_DAT)RtlZmalloc(sizeof(HAL_ADC_INIT_DAT)); @@ -279,6 +314,7 @@ RtkADCGetMngtAdpt( pSalADCMngtAdpt->pHalGdmaOp = (PHAL_GDMA_OP)RtlZmalloc(sizeof(HAL_GDMA_OP)); pSalADCMngtAdpt->pIrqGdmaHnd = (PIRQ_HANDLE)RtlZmalloc(sizeof(IRQ_HANDLE)); pSalADCUserCBAdpt = (PSAL_ADC_USERCB_ADPT)RtlZmalloc((sizeof(SAL_ADC_USERCB_ADPT)*SAL_ADC_USER_CB_NUM)); +#endif #else switch (ADCIdx){ case ADC0_SEL: @@ -408,6 +444,19 @@ RtkADCFreeMngtAdpt( IN PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt ){ #ifdef CONFIG_KERNEL +#if 1 // pvvx + RtlMfree((u8 *)pSalADCMngtAdpt, + sizealign4(SAL_ADC_MNGT_ADPT) + + sizealign4(SAL_ADC_HND_PRIV) + + sizealign4(HAL_ADC_INIT_DAT) + + sizealign4(HAL_ADC_OP) + + sizealign4(IRQ_HANDLE) + + sizealign4(SAL_ADC_USER_CB) + + sizealign4(HAL_GDMA_ADAPTER) + + sizealign4(HAL_GDMA_OP) + + sizealign4(IRQ_HANDLE) + + (sizealign4(SAL_ADC_USERCB_ADPT)*SAL_ADC_USER_CB_NUM)); +#else RtlMfree((u8 *)pSalADCMngtAdpt->pUserCB->pTXCB, (sizeof(SAL_ADC_USERCB_ADPT)*SAL_ADC_USER_CB_NUM)); RtlMfree((u8 *)pSalADCMngtAdpt->pIrqGdmaHnd, sizeof(IRQ_HANDLE)); RtlMfree((u8 *)pSalADCMngtAdpt->pHalGdmaOp, sizeof(HAL_GDMA_OP)); @@ -418,6 +467,7 @@ RtkADCFreeMngtAdpt( RtlMfree((u8 *)pSalADCMngtAdpt->pHalInitDat, sizeof(HAL_ADC_INIT_DAT)); RtlMfree((u8 *)pSalADCMngtAdpt->pSalHndPriv, sizeof(SAL_ADC_HND_PRIV)); RtlMfree((u8 *)pSalADCMngtAdpt, sizeof(SAL_ADC_MNGT_ADPT)); +#endif #else ; #endif diff --git a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/src/hal_log_uart.c b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/src/hal_log_uart.c index f813bc0..12fc92a 100644 --- a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/src/hal_log_uart.c +++ b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/src/hal_log_uart.c @@ -50,6 +50,14 @@ extern VOID UartLogIrqHandleRam(VOID * Data); // extern ConfigDebugInfo; // extern UartLogIrqHandleRam; //------------------------------------------------------------------------- +/* + * 16 bytes FIFO ... 16*11/38400 = 0.004583 sec + * (0.005/5)*166666666 = 166666.666 + */ +VOID HalLogUartWaitTxFifoEmpty(VOID) { + int x = 16384; + while((!(HAL_READ8(LOG_UART_REG_BASE, 0x14) & BIT6)) && x--); +} //----- HalLogUartIrqRxRdyHandle void HalLogUartIrqRxRdyHandle(HAL_LOG_UART_ADAPTER *pUartAdapter) { @@ -427,8 +435,7 @@ void HalInitLogUart(void) { //----- HalDeinitLogUart void HalDeinitLogUart(void) { - while (!(HAL_UART_READ32(UART_LINE_STATUS_REG_OFF) & LSR_TEMT)) // 40003014 & 0x40 - HalDelayUs(20); + HalLogUartWaitTxFifoEmpty(); HalPinCtrlRtl8195A(LOG_UART, 0, 0); } diff --git a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/src/hal_soc_ps_monitor.c b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/src/hal_soc_ps_monitor.c index 4fd2c2a..9d8605f 100644 --- a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/src/hal_soc_ps_monitor.c +++ b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/src/hal_soc_ps_monitor.c @@ -1520,7 +1520,7 @@ SleepCG( //Enable wake event WakeEvent |= BIT28; } - +/* while(1) { HalDelayUs(100); @@ -1530,7 +1530,8 @@ SleepCG( break; } } - +*/ + HalLogUartWaitTxFifoEmpty(); //Set Event HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, WakeEvent); @@ -1636,8 +1637,7 @@ SleepPG( //Enable wake event WakeEvent |= BIT28; } - - while(1) { +/* while(1) { HalDelayUs(100); @@ -1645,7 +1645,8 @@ SleepPG( break; } - } + } */ + HalLogUartWaitTxFifoEmpty(); //Set Event HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, WakeEvent); diff --git a/build/bin/ota.bin b/build/bin/ota.bin index 27212c4df2357b6ff9d2ff89d4fe5f3639acf667..bdbc7106d7235bf9a1f1ee4b4ec9fa47d28d3871 100644 GIT binary patch delta 26049 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 XD9(O|!`lH4I+GTtiBalykMrigT$P2C delta 26112 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 diff --git a/build/bin/ram_2.bin b/build/bin/ram_2.bin index 2f2341f749f4a0cc9902a96bea016b88b03f0358..26e4e3b2d9c894108ef1b5168efa79b49dca3eee 100644 GIT binary patch delta 26039 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 R`OSf+!W?v_ELD>e{srs!h3NnQ delta 26103 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 m{3XgXzzL9-$yvLDj diff --git a/build/bin/ram_2.ns.bin b/build/bin/ram_2.ns.bin index 18442140f89341800b65595fc5d49e39b5673f9b..b8d980584d6fd0b1b5d6394599c7ba28b34d6621 100644 GIT binary patch delta 26044 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 TD9(O|!`lH4I+GWwQBnT_-YtV) delta 26107 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�x&V@%X(5 zFZB>AO+=_exNruK@*nfU4WzIAf(UmIbO-RLeuW6jej@_hC4!-m2(#;mkV5k^a3DNS z4`pCE=h8bF{A+5q_rsR%iS>-V^3|UF68x0hu5N1Pi5MuVKE~fGlvmoR(3=nR_O=fb z)vgySyn)F0x}`TC7HVnc#Y6ZsMSCSsWRFw!;8O%OK29O>gJx54Z5d;@KomB&v2((9h-r-A%fz=J^SAU@l(>;cZEe_(6kT6&nyXQ&aF z3`F=DNuSUk5al%%sb)+TB4j?G!Grl8#P=K>Hkj|E>4h|pN%ZZ(DAh!-4CYVhHls0T zv5VZKd!ON}61z9+XRfha4>_e6n+q{^4P)`_k$-aL)0vPaZlC!`nSnRVG2$sDf-WoI z1A_dT)9^=Mv72T&m4G@|Y(Y!!uPxwH{pWwq3wMs;7V!u#J(uZV2z!4n8x5 zjpM%q)|SuV7)zz&$MX}3#!iop=TGWb({dkj*t=Fe≀&J)BnCGGL}o;5U+h+t#kF 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 TD9(O|!`lH4I+GWwQBnT_-YtV) delta 26107 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�x&V@%X(5 zFZB>AO+=_exNruK@*nfU4WzIAf(UmIbO-RLeuW6jej@_hC4!-m2(#;mkV5k^a3DNS z4`pCE=h8bF{A+5q_rsR%iS>-V^3|UF68x0hu5N1Pi5MuVKE~fGlvmoR(3=nR_O=fb z)vgySyn)F0x}`TC7HVnc#Y6ZsMSCSsWRFw!;8O%OK29O>gJx54Z5d;@KomB&v2((9h-r-A%fz=J^SAU@l(>;cZEe_(6kT6&nyXQ&aF z3`F=DNuSUk5al%%sb)+TB4j?G!Grl8#P=K>Hkj|E>4h|pN%ZZ(DAh!-4CYVhHls0T zv5VZKd!ON}61z9+XRfha4>_e6n+q{^4P)`_k$-aL)0vPaZlC!`nSnRVG2$sDf-WoI z1A_dT)9^=Mv72T&m4G@|Y(Y!!uPxwH{pWwq3wMs;7V!u#J(uZV2z!4n8x5 zjpM%q)|SuV7)zz&$MX}3#!iop=TGWb({dkj*t=Fe≀&J)BnCGGL}o;5U+h+t#kF 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 1 dump_mem_block_list(); tcm_heap_dump(); -#endif +#endif; printf("\n"); #if (configGENERATE_RUN_TIME_STATS == 1) char *cBuffer = pvPortMalloc(512); @@ -61,8 +63,6 @@ void fATST(int argc, char *argv[]) { } #endif } - - /*------------------------------------------------------------------------------------- Копирует данные из области align(4) (flash, registers, ...) в область align(1) (ram) --------------------------------------------------------------------------------------*/ @@ -147,8 +147,10 @@ void dump_bytes(uint32 addr, int size) size -= symbs_line; } } +//------------------------------------------------------------------------------ // Dump byte register -void fATSB(int argc, char *argv[]) +//------------------------------------------------------------------------------ +LOCAL void fATSB(int argc, char *argv[]) { int size = 16; uint32 addr = Strtoul(argv[1],0,16); @@ -160,8 +162,10 @@ void fATSB(int argc, char *argv[]) dump_bytes(addr, size); } +//------------------------------------------------------------------------------ // Dump dword register -void fATSD(int argc, char *argv[]) +//------------------------------------------------------------------------------ +LOCAL void fATSD(int argc, char *argv[]) { /* if (argc > 2) { @@ -172,8 +176,10 @@ void fATSD(int argc, char *argv[]) */ CmdDumpWord(argc-1, (unsigned char**)(argv+1)); } - -void fATSW(int argc, char *argv[]) +//------------------------------------------------------------------------------ +// Write dword register +//------------------------------------------------------------------------------ +LOCAL void fATSW(int argc, char *argv[]) { CmdWriteWord(argc-1, (unsigned char**)(argv+1)); } @@ -226,7 +232,7 @@ void print_udp_pcb(void) for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { rtl_printf("flg:%02x\t" IPSTR ":%d\t" IPSTR ":%d\trecv:%p\n", pcb->flags, IP2STR(&pcb->local_ip), pcb->local_port, IP2STR(&pcb->remote_ip), pcb->remote_port, pcb->recv ); prt_none = false; - } + }; if(prt_none) rtl_printf("none\n"); } /****************************************************************************** @@ -242,21 +248,21 @@ void print_tcp_pcb(void) for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]); prt_none = false; - } + }; if(prt_none) rtl_printf("none\n"); rtl_printf("Listen PCB states:\n"); prt_none = true; for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]); prt_none = false; - } + }; if(prt_none) rtl_printf("none\n"); rtl_printf("TIME-WAIT PCB states:\n"); prt_none = true; for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]); prt_none = false; - } + }; if(prt_none) rtl_printf("none\n"); } /****************************************************************************** @@ -264,40 +270,56 @@ void print_tcp_pcb(void) * Parameters : * Returns : *******************************************************************************/ -//------------------------------------------------------------------------------ -void fATLW(int argc, char *argv[]) // Info Lwip +LOCAL void fATLW(int argc, char *argv[]) // Info Lwip { print_udp_pcb(); print_tcp_pcb(); } - -void fATDS(int argc, char *argv[]) // Deep sleep +//------------------------------------------------------------------------------ +// Deep sleep +//------------------------------------------------------------------------------ +LOCAL void fATDS(int argc, char *argv[]) { - uint32 sleep_ms = 10000; - if(argc > 2) sleep_ms = atoi(argv[1]); -#if 0 - // turn off log uart - sys_log_uart_off(); - // initialize wakeup pin at PB_1 - gpio_t gpio_wake; - gpio_init(&gpio_wake, PB_1); - gpio_dir(&gpio_wake, PIN_INPUT); - gpio_mode(&gpio_wake, PullDown); + uint32 sleep_ms = 10000; + if(argc > 1) sleep_ms = atoi(argv[1]); +#if 0 + if(argc > 2) { + printf("%u ms waiting low level on PB_1 before launching Deep-Sleep...\n", sleep_ms); + // turn off log uart + HalDeinitLogUart(); // sys_log_uart_off(); - // enter deep sleep - deepsleep_ex(DSLEEP_WAKEUP_BY_GPIO | DSLEEP_WAKEUP_BY_TIMER, 10000); */ - // standby_wakeup_event_add(STANDBY_WAKEUP_BY_STIMER, 10000, 0); -// deepstandby_ex(); -// sleep_ex(SLEEP_WAKEUP_BY_STIMER, 8000); // sleep_ex can't be put in irq handler -// release_wakelock(WAKELOCK_OS); + // initialize wakeup pin + gpio_t gpio_wake; + gpio_init(&gpio_wake, PB_1); + gpio_dir(&gpio_wake, PIN_INPUT); + gpio_mode(&gpio_wake, PullDown); + TickType_t sttime = xTaskGetTickCount(); + + do { + if(gpio_read(&gpio_wake) == 0) { + // Enter deep sleep... Wait give rising edge at PB_1 to wakeup system. + deepsleep_ex(DSLEEP_WAKEUP_BY_GPIO, 0); + }; + vTaskDelay(1); + } while(xTaskGetTickCount() - sttime < sleep_ms); + HalInitLogUart(); // sys_log_uart_on(); + printf("No set pin low in deep sleep!\n"); + } + else { + printf("Deep-Sleep %u ms\n", sleep_ms); + HalLogUartWaitTxFifoEmpty(); + // Enter deep sleep... Wait timer ms + deepsleep_ex(DSLEEP_WAKEUP_BY_TIMER, sleep_ms); + } #else + HalLogUartWaitTxFifoEmpty(); deepsleep_ex(DSLEEP_WAKEUP_BY_TIMER, sleep_ms); -#endif +#endif } /*------------------------------------------------------------------------------ * power saving mode *----------------------------------------------------------------------------*/ -void fATSP(int argc, char *argv[]) +LOCAL void fATSP(int argc, char *argv[]) { if(argc > 2) { switch (argv[1][0]) { @@ -311,12 +333,13 @@ void fATSP(int argc, char *argv[]) release_wakelock(atoi(argv[2])); break; } - } - } + }; + }; printf("WakeLock Status %d\n", get_wakelock_status()); } - -MON_RAM_TAB_SECTION COMMAND_TABLE console_commands1[] = { +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_at[] = { {"ATST", 0, fATST, ": Memory info"}, {"ATLW", 0, fATLW, ": LwIP Info"}, {"ATSB", 1, fATSB, "=[,COUNT(dec)]: Dump byte register"}, diff --git a/project/src/user/wifi_console.c b/project/src/user/wifi_console.c index cc11f23..e667980 100644 --- a/project/src/user/wifi_console.c +++ b/project/src/user/wifi_console.c @@ -23,7 +23,7 @@ extern struct netif xnetif[NET_IF_NUM]; //--- CONSOLE -------------------------- // ATPN=[,password[,encryption[,auto reconnect[,reconnect pause]]]: WIFI Connect to AP -void fATPN(int argc, char *argv[]){ +LOCAL void fATPN(int argc, char *argv[]){ if(argc > 1) { if(argv[1][0] == '?') { show_wifi_st_cfg(); @@ -66,7 +66,7 @@ void fATPN(int argc, char *argv[]){ } // ATPA=[,password[,encryption[,channel[,hidden[,max connections]]]]]: Start WIFI AP -void fATPA(int argc, char *argv[]){ +LOCAL void fATPA(int argc, char *argv[]){ if(argc > 1) { if(argv[1][0] == '?') { show_wifi_ap_cfg(); @@ -115,23 +115,23 @@ void fATPA(int argc, char *argv[]){ } // WIFI Connect, Disconnect -void fATWR(int argc, char *argv[]){ +LOCAL void fATWR(int argc, char *argv[]){ rtw_mode_t mode = RTW_MODE_NONE; if(argc > 1) mode = atoi(argv[1]); wifi_run(mode); } // Close connections -void fATOF(int argc, char *argv[]){ +LOCAL void fATOF(int argc, char *argv[]){ connect_close(); } // Open connections -void fATON(int argc, char *argv[]){ +LOCAL void fATON(int argc, char *argv[]){ connect_start(); } -void fATWI(int argc, char *argv[]) { +LOCAL void fATWI(int argc, char *argv[]) { rtw_wifi_setting_t Setting; if((wifi_run_mode & RTW_MODE_AP) && wifi_get_setting(wlan_ap_name, &Setting) == 0) { @@ -155,18 +155,27 @@ void fATWI(int argc, char *argv[]) { printf(&str_rom_57ch3Dch0A[25]); // "================================\n" show_wifi_st_cfg(); printf("\n"); - if(argc > 1 - && (argv[1][0] == 's' - || argv[1][0] == 'S')) { - int i = atoi(argv[2]); - printf("Save configs(%d)..\n", i); - write_wifi_cfg(atoi(argv[2])); +#if 1 + if(argc > 2) { + uint8_t c = argv[1][0] | 0x20; + if(c == 's') { + int i = atoi(argv[2]); + printf("Save configs(%d)..\n", i); + write_wifi_cfg(atoi(argv[2])); + } + else if(c == 'l') { + wifi_cfg.load_flg = atoi(argv[2]); + } + else if(c == 'm') { + wifi_cfg.mode = atoi(argv[2]); + } } +#endif } extern uint8_t rtw_power_percentage_idx; -void fATWT(int argc, char *argv[]) { +LOCAL void fATWT(int argc, char *argv[]) { if(argc > 1) { int txpwr = atoi(argv[1]); debug_printf("set tx power (%d)...\n", txpwr); @@ -189,7 +198,7 @@ LOCAL uint64_t get_tsf(void) return *((uint64_t *)(WIFI_REG_BASE + REG_TSFTR)); } -void fATSF(int argc, char *argv[]) +LOCAL void fATSF(int argc, char *argv[]) { uint64_t tsf = get_tsf(); printf("\nTSF: %08x%08x\n", (uint32_t)(tsf>>32), (uint32_t)(tsf)); @@ -222,7 +231,7 @@ unsigned int *tab_code_rtw_secyrity[] = { volatile uint8_t scan_end; /* -------- WiFi Scan ------------------------------- */ -static rtw_result_t _scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result ) +LOCAL rtw_result_t _scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result ) { if (malloced_scan_result->scan_complete != RTW_TRUE) { rtw_scan_result_t* record = &malloced_scan_result->ap_details; @@ -249,7 +258,7 @@ static rtw_result_t _scan_result_handler( rtw_scan_handler_result_t* malloced_sc } /* -------- WiFi Scan ------------------------------- */ #define scan_channels 14 -void fATSN(int argc, char *argv[]) +LOCAL void fATSN(int argc, char *argv[]) { int i; u8 *channel_list = (u8*)pvPortMalloc(scan_channels*2); @@ -281,9 +290,9 @@ MON_RAM_TAB_SECTION COMMAND_TABLE console_cmd_wifi_api[] = { {"ATPN", 1, fATPN, "=[,password[,encryption[,auto-reconnect[,reconnect pause]]]: WIFI Connect to AP"}, {"ATPA", 1, fATPA, "=[,password[,encryption[,channel[,hidden[,max connections]]]]]: Start WIFI AP"}, {"ATWR", 0, fATWR, ": WIFI Connect, Disconnect"}, - {"ATON", 0, fATON, ": Open connections"}, - {"ATOF", 0, fATOF, ": Close connections"}, - {"ATWI", 0, fATWI, "=[s]: WiFi Info, s - save"}, +// {"ATON", 0, fATON, ": Open connections"}, +// {"ATOF", 0, fATOF, ": Close connections"}, + {"ATWI", 0, fATWI, ": WiFi Info"}, #if CONFIG_DEBUG_LOG > 3 {"ATWT", 1, fATWT, "=: WiFi tx power: 0 - 100%, 1 - 75%, 2 - 50%, 3 - 25%, 4 - 12.5%"}, {"ATSF", 0, fATSF, ": Test TSF value"}, diff --git a/sdkbuild.mk b/sdkbuild.mk index dafc499..5291d37 100644 --- a/sdkbuild.mk +++ b/sdkbuild.mk @@ -49,7 +49,8 @@ application: build_info $(SRC_O) $(DRAM_O) $(BOOT_O) @echo "Link ($(TARGET))" # @echo "===========================================================" @mkdir -p $(BIN_DIR) $(OBJ_DIR) - @$(LD) $(LFLAGS) -o $(ELFFILE) $(OBJ_LIST) $(LIBFLAGS) -T$(LDFILE) + @$(file > $(OBJ_DIR)/obj_list.lst,$(OBJ_LIST)) + @$(LD) $(LFLAGS) -o $(ELFFILE) @$(OBJ_DIR)/obj_list.lst $(LIBFLAGS) -T$(LDFILE) @$(OBJDUMP) -d $(ELFFILE) > $(OBJ_DIR)/$(TARGET).asm .PHONY: prerequirement