From 4629138a4208b7068e068b22ea69947aeed7a51e Mon Sep 17 00:00:00 2001
From: RichardBarry <3073890+RichardBarry@users.noreply.github.com>
Date: Wed, 26 Jan 2022 17:55:06 -0800
Subject: [PATCH] Extend qemu virt riscv demo (#774)
* Simple blinky demo working. Not tried full demo yet.
* Get the full demo running.
* Add Eclipse project to build the RISC-V_RV32_QEMU_VIRT_GCC gcc makefile.
* Add regtest tasks to the RISC-V_RV32_QEMU_VIRT_GCC demo.
* Update priority of the timer task.
* Adjust timer frequency and optimisation level before committing prior to rearranging the Eclipse project.
* Reorganise Eclipse project slightly.
* Add note to the RISC-V-Qemu-virt_GCC readme file about the updated version in RISC-V_RV32_QEMU_VIRT_GCC.
* Update headers in newly added source files so they pass the automated header check.
* Update lexicon to pass automated spell check.
Co-authored-by: none <>
---
FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/Readme.md | 3 +
.../FreeRTOSConfig.h | 125 ++++++
.../build/gcc/.cproject | 55 +++
.../build/gcc/.project | 181 ++++++++
.../build/gcc/Makefile | 140 ++++++
.../build/gcc/RTOSDemo Default.launch | 47 +++
.../build/gcc/RegTest.S | 265 ++++++++++++
.../build/gcc/fake_rom.ld | 117 +++++
.../build/gcc/output/placeholder.txt | 3 +
.../build/gcc/printf-stdarg.c | 314 ++++++++++++++
.../build/gcc/start.S | 85 ++++
.../Demo/RISC-V_RV32_QEMU_VIRT_GCC/main.c | 301 +++++++++++++
.../RISC-V_RV32_QEMU_VIRT_GCC/main_blinky.c | 235 +++++++++++
.../RISC-V_RV32_QEMU_VIRT_GCC/main_full.c | 398 ++++++++++++++++++
.../Demo/RISC-V_RV32_QEMU_VIRT_GCC/ns16550.c | 74 ++++
.../Demo/RISC-V_RV32_QEMU_VIRT_GCC/ns16550.h | 38 ++
.../RISC-V_RV32_QEMU_VIRT_GCC/riscv-reg.h | 42 ++
.../RISC-V_RV32_QEMU_VIRT_GCC/riscv-virt.c | 64 +++
.../RISC-V_RV32_QEMU_VIRT_GCC/riscv-virt.h | 54 +++
lexicon.txt | 1 +
20 files changed, 2542 insertions(+)
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/FreeRTOSConfig.h
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/.cproject
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/.project
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/Makefile
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/RTOSDemo Default.launch
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/RegTest.S
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/fake_rom.ld
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/output/placeholder.txt
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/printf-stdarg.c
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/start.S
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/main.c
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/main_blinky.c
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/main_full.c
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/ns16550.c
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/ns16550.h
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/riscv-reg.h
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/riscv-virt.c
create mode 100644 FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/riscv-virt.h
diff --git a/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/Readme.md b/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/Readme.md
index 86282ea67b..f5595417bb 100644
--- a/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/Readme.md
+++ b/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/Readme.md
@@ -1,3 +1,6 @@
+There is an updated version of this original submission from Katsuhiro Suzuki
+in the FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC directory.
+
# Emulating generic RISC-V 32bit machine on QEMU
## Requirements
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/FreeRTOSConfig.h b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/FreeRTOSConfig.h
new file mode 100644
index 0000000000..fa61c90afd
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/FreeRTOSConfig.h
@@ -0,0 +1,125 @@
+/*
+ * FreeRTOS V202112.00
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+
+#include "riscv-virt.h"
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html
+ *----------------------------------------------------------*/
+
+/* See https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html */
+#define configMTIME_BASE_ADDRESS ( CLINT_ADDR + CLINT_MTIME )
+#define configMTIMECMP_BASE_ADDRESS ( CLINT_ADDR + CLINT_MTIMECMP )
+#define configISR_STACK_SIZE_WORDS ( 300 )
+
+#define configUSE_PREEMPTION 1
+#define configUSE_IDLE_HOOK 0
+#define configUSE_TICK_HOOK 1
+#define configCPU_CLOCK_HZ ( ( unsigned long ) 25000000 )
+#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
+#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 120 )
+#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 80 * 1024 ) )
+#define configMAX_TASK_NAME_LEN ( 12 )
+#define configUSE_TRACE_FACILITY 0
+#define configUSE_16_BIT_TICKS 0
+#define configIDLE_SHOULD_YIELD 0
+#define configUSE_CO_ROUTINES 0
+#define configUSE_MUTEXES 1
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configCHECK_FOR_STACK_OVERFLOW 2
+#define configUSE_MALLOC_FAILED_HOOK 1
+#define configUSE_QUEUE_SETS 1
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
+
+#define configMAX_PRIORITIES ( 9UL )
+#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
+#define configQUEUE_REGISTRY_SIZE 10
+#define configSUPPORT_STATIC_ALLOCATION 1
+
+/* Timer related defines. */
+#define configUSE_TIMERS 1
+#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 3 )
+#define configTIMER_QUEUE_LENGTH 20
+#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
+
+#define configUSE_TASK_NOTIFICATIONS 1
+#define configTASK_NOTIFICATION_ARRAY_ENTRIES 3
+
+/* Set the following definitions to 1 to include the API function, or zero
+to exclude the API function. */
+
+#define INCLUDE_vTaskPrioritySet 1
+#define INCLUDE_uxTaskPriorityGet 1
+#define INCLUDE_vTaskDelete 1
+#define INCLUDE_vTaskCleanUpResources 0
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_uxTaskGetStackHighWaterMark 1
+#define INCLUDE_xTaskGetSchedulerState 1
+#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1
+#define INCLUDE_xTaskGetIdleTaskHandle 1
+#define INCLUDE_xSemaphoreGetMutexHolder 1
+#define INCLUDE_eTaskGetState 1
+#define INCLUDE_xTimerPendFunctionCall 1
+#define INCLUDE_xTaskAbortDelay 1
+#define INCLUDE_xTaskGetHandle 1
+
+/* This demo makes use of one or more example stats formatting functions. These
+format the raw data provided by the uxTaskGetSystemState() function in to human
+readable ASCII form. See the notes in the implementation of vTaskList() within
+FreeRTOS/Source/tasks.c for limitations. */
+#define configUSE_STATS_FORMATTING_FUNCTIONS 1
+
+/* The QEMU target is capable of running all the tests tasks at the same
+ * time. */
+#define configRUN_ADDITIONAL_TESTS 1
+
+void vAssertCalled( const char *pcFileName, uint32_t ulLine );
+#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ );
+
+/* The test that checks the trigger level on stream buffers requires an
+allowable margin of error on slower processors (slower than the Win32
+machine on which the test is developed). */
+#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN 2
+
+#define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 5 )
+#define bktPRIMARY_PRIORITY ( configMAX_PRIORITIES - 4 )
+#define bktSECONDARY_PRIORITY ( configMAX_PRIORITIES - 5 )
+
+#endif /* FREERTOS_CONFIG_H */
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/.cproject b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/.cproject
new file mode 100644
index 0000000000..804f7f7d15
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/.cproject
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/.project b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/.project
new file mode 100644
index 0000000000..e5260c8978
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/.project
@@ -0,0 +1,181 @@
+
+
+ RTOSDemo
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
+
+ FreeRTOS_kernel
+ 2
+ FREERTOS_ROOT/Source
+
+
+ Source
+ 2
+ virtual:/virtual
+
+
+ Source/Blinky_Demo
+ 2
+ virtual:/virtual
+
+
+ Source/FreeRTOSConfig.h
+ 1
+ PARENT-2-PROJECT_LOC/FreeRTOSConfig.h
+
+
+ Source/Full_Demo
+ 2
+ virtual:/virtual
+
+
+ Source/Makefile
+ 1
+ PROJECT_LOC/Makefile
+
+
+ Source/fake_rom.ld
+ 1
+ PROJECT_LOC/fake_rom.ld
+
+
+ Source/main.c
+ 1
+ PARENT-2-PROJECT_LOC/main.c
+
+
+ Source/ns16550.c
+ 1
+ PARENT-2-PROJECT_LOC/ns16550.c
+
+
+ Source/ns16550.h
+ 1
+ PARENT-2-PROJECT_LOC/ns16550.h
+
+
+ Source/printf-stdarg.c
+ 1
+ PROJECT_LOC/printf-stdarg.c
+
+
+ Source/riscv-reg.h
+ 1
+ PARENT-2-PROJECT_LOC/riscv-reg.h
+
+
+ Source/riscv-virt.c
+ 1
+ PARENT-2-PROJECT_LOC/riscv-virt.c
+
+
+ Source/riscv-virt.h
+ 1
+ PARENT-2-PROJECT_LOC/riscv-virt.h
+
+
+ Source/start.S
+ 1
+ PROJECT_LOC/start.S
+
+
+ Source/startfiles
+ 1
+ PROJECT_LOC/startfiles
+
+
+ Source/Blinky_Demo/main_blinky.c
+ 1
+ PARENT-2-PROJECT_LOC/main_blinky.c
+
+
+ Source/Full_Demo/CommonDemoSource
+ 2
+ FREERTOS_ROOT/Demo/Common/Minimal
+
+
+ Source/Full_Demo/RegTest.S
+ 1
+ PROJECT_LOC/RegTest.S
+
+
+ Source/Full_Demo/main_full.c
+ 1
+ PARENT-2-PROJECT_LOC/main_full.c
+
+
+
+
+ 1640399877287
+
+ 6
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-*
+
+
+
+ 1640399593493
+ FreeRTOS_kernel/portable
+ 9
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-GCC
+
+
+
+ 1640399593501
+ FreeRTOS_kernel/portable
+ 9
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-MemMang
+
+
+
+ 1640399614171
+ FreeRTOS_kernel/portable/GCC
+ 9
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-RISC-V
+
+
+
+ 1640399630077
+ FreeRTOS_kernel/portable/MemMang
+ 5
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-heap_4.c
+
+
+
+
+
+ FREERTOS_ROOT
+ $%7BPARENT-4-PROJECT_LOC%7D
+
+
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/Makefile b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/Makefile
new file mode 100644
index 0000000000..d7ed94b74e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/Makefile
@@ -0,0 +1,140 @@
+OUTPUT_DIR := ./output
+IMAGE := RTOSDemo.elf
+
+# The directory that contains the /source and /demo sub directories.
+FREERTOS_ROOT = ./../../../..
+
+CC = riscv64-unknown-elf-gcc
+LD = riscv64-unknown-elf-gcc
+SIZE = riscv64-unknown-elf-size
+MAKE = make
+
+CFLAGS += $(INCLUDE_DIRS) -DportasmHANDLE_INTERRUPT=handle_trap -fmessage-length=0 \
+ -march=rv32imac -mabi=ilp32 -mcmodel=medlow -ffunction-sections -fdata-sections \
+ --specs=nano.specs -fno-builtin-printf -Wno-unused-parameter -nostartfiles -g3 -Os
+
+LDFLAGS += -nostartfiles -Xlinker --gc-sections -Wl,-Map,$(OUTPUT_DIR)/RTOSDemo.map \
+ -T./fake_rom.ld -march=rv32imac -mabi=ilp32 -mcmodel=medlow -Xlinker \
+ --defsym=__stack_size=350 -Wl,--start-group -Wl,--end-group -Wl,--wrap=malloc \
+ -Wl,--wrap=free -Wl,--wrap=open -Wl,--wrap=lseek -Wl,--wrap=read -Wl,--wrap=write \
+ -Wl,--wrap=fstat -Wl,--wrap=stat -Wl,--wrap=close -Wl,--wrap=link -Wl,--wrap=unlink \
+ -Wl,--wrap=execve -Wl,--wrap=fork -Wl,--wrap=getpid -Wl,--wrap=kill -Wl,--wrap=wait \
+ -Wl,--wrap=isatty -Wl,--wrap=times -Wl,--wrap=sbrk -Wl,--wrap=puts -Wl,--wrap=_malloc \
+ -Wl,--wrap=_free -Wl,--wrap=_open -Wl,--wrap=_lseek -Wl,--wrap=_read -Wl,--wrap=_write \
+ -Wl,--wrap=_fstat -Wl,--wrap=_stat -Wl,--wrap=_close -Wl,--wrap=_link -Wl,--wrap=_unlink \
+ -Wl,--wrap=_execve -Wl,--wrap=_fork -Wl,--wrap=_getpid -Wl,--wrap=_kill -Wl,--wrap=_wait \
+ -Wl,--wrap=_isatty -Wl,--wrap=_times -Wl,--wrap=_sbrk -Wl,--wrap=__exit -Wl,--wrap=_puts
+
+# -Wl,--wrap=_exit
+#
+# Kernel build.
+#
+KERNEL_DIR = $(FREERTOS_ROOT)/Source
+KERNEL_PORT_DIR += $(KERNEL_DIR)/portable/GCC/RISC-V
+INCLUDE_DIRS += -I$(KERNEL_DIR)/include \
+ -I$(KERNEL_PORT_DIR) \
+ -I$(KERNEL_PORT_DIR)/chip_specific_extensions/RV32I_CLINT_no_extensions
+VPATH += $(KERNEL_DIR) $(KERNEL_PORT_DIR) $(KERNEL_DIR)/portable/MemMang
+SOURCE_FILES += $(KERNEL_DIR)/tasks.c
+SOURCE_FILES += $(KERNEL_DIR)/list.c
+SOURCE_FILES += $(KERNEL_DIR)/queue.c
+SOURCE_FILES += $(KERNEL_DIR)/timers.c
+SOURCE_FILES += $(KERNEL_DIR)/event_groups.c
+SOURCE_FILES += $(KERNEL_DIR)/stream_buffer.c
+SOURCE_FILES += $(KERNEL_DIR)/portable/MemMang/heap_4.c
+SOURCE_FILES += $(KERNEL_DIR)/portable/GCC/RISC-V/port.c
+ASM_SOURCE_FILES += $(KERNEL_DIR)/portable/GCC/RISC-V/portASM.S
+
+#
+# Common demo files for the "full" build, as opposed to the "blinky" build -
+# these files are build by all the FreeRTOS kernel demos.
+#
+DEMO_ROOT = $(FREERTOS_ROOT)/Demo
+COMMON_DEMO_FILES = $(DEMO_ROOT)/Common/Minimal
+INCLUDE_DIRS += -I$(DEMO_ROOT)/Common/include
+VPATH += $(COMMON_DEMO_FILES)
+SOURCE_FILES += (COMMON_DEMO_FILES)/AbortDelay.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/BlockQ.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/blocktim.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/countsem.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/death.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/dynamic.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/EventGroupsDemo.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/GenQTest.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/integer.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/IntSemTest.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/MessageBufferAMP.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/MessageBufferDemo.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/PollQ.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/QPeek.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/QueueOverwrite.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/QueueSet.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/QueueSetPolling.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/recmutex.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/semtest.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/StaticAllocation.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/StreamBufferDemo.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/StreamBufferInterrupt.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/TaskNotify.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/TaskNotifyArray.c
+SOURCE_FILES += (COMMON_DEMO_FILES)/TimerDemo.c
+
+#
+# Application entry point. main_blinky is self contained. main_full builds
+# the above common demo (and test) files too.
+#
+DEMO_PROJECT = $(DEMO_ROOT)/RISC-V_RV32_QEMU_VIRT_GCC
+VPATH += $(DEMO_PROJECT)
+INCLUDE_DIRS += -I$(DEMO_PROJECT)
+SOURCE_FILES += (DEMO_PROJECT)/main.c
+SOURCE_FILES += (DEMO_PROJECT)/main_blinky.c
+SOURCE_FILES += (DEMO_PROJECT)/main_full.c
+SOURCE_FILES += (DEMO_PROJECT)/ns16550.c
+SOURCE_FILES += (DEMO_PROJECT)/riscv-virt.c
+# Lightweight print formatting to use in place of the heavier GCC equivalent.
+SOURCE_FILES += ./printf-stdarg.c
+ASM_SOURCE_FILES += ./start.S
+ASM_SOURCE_FILES += ./RegTest.S
+
+
+#Create a list of object files with the desired output directory path.
+OBJS = $(SOURCE_FILES:%.c=%.o) $(ASM_SOURCE_FILES:%.S=%.o)
+OBJS_NO_PATH = $(notdir $(OBJS))
+OBJS_OUTPUT = $(OBJS_NO_PATH:%.o=$(OUTPUT_DIR)/%.o)
+
+#Create a list of dependency files with the desired output directory path.
+DEP_FILES := $(SOURCE_FILES:%.c=$(OUTPUT_DIR)/%.d) $(ASM_SOURCE_FILES:%.S=$(OUTPUT_DIR)/%.d)
+DEP_FILES_NO_PATH = $(notdir $(DEP_FILES))
+DEP_OUTPUT = $(DEP_FILES_NO_PATH:%.d=$(OUTPUT_DIR)/%.d)
+
+all: $(OUTPUT_DIR)/$(IMAGE)
+
+%.o : %.c
+$(OUTPUT_DIR)/%.o : %.c $(OUTPUT_DIR)/%.d Makefile
+ $(CC) $(CFLAGS) -MMD -MP -c $< -o $@
+
+%.o : %.S
+$(OUTPUT_DIR)/%.o: %.S $(OUTPUT_DIR)/%.d Makefile
+ $(CC) $(CFLAGS) -MMD -MP -c $< -o $@
+
+$(OUTPUT_DIR)/$(IMAGE): $(OBJS_OUTPUT) Makefile
+ @echo ""
+ @echo ""
+ @echo "--- Final linking ---"
+ @echo ""
+ $(LD) $(OBJS_OUTPUT) $(LDFLAGS) -o $(OUTPUT_DIR)/$(IMAGE)
+ $(SIZE) $(OUTPUT_DIR)/$(IMAGE)
+
+$(DEP_OUTPUT):
+include $(wildcard $(DEP_OUTPUT))
+
+clean:
+ rm -f $(OUTPUT_DIR)/$(IMAGE) $(OUTPUT_DIR)/*.o $(OUTPUT_DIR)/*.d $(OUTPUT_DIR)/*.map
+
+#use "make print-[VARIABLE_NAME] to print the value of a variable generated by
+#this makefile.
+print-% : ; @echo $* = $($*)
+
+.PHONY: all clean
+
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/RTOSDemo Default.launch b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/RTOSDemo Default.launch
new file mode 100644
index 0000000000..9c3da79d9c
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/RTOSDemo Default.launch
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/RegTest.S b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/RegTest.S
new file mode 100644
index 0000000000..66a085c7be
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/RegTest.S
@@ -0,0 +1,265 @@
+/*
+ * FreeRTOS V202112.00
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+ .extern ulRegTest1LoopCounter
+ .extern ulRegTest2LoopCounter
+
+ .global vRegTest1Implementation
+ .global vRegTest2Implementation
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The register check tasks are described in the comments at the top of
+ * main_full.c.
+ */
+
+.align( 4 )
+vRegTest1Implementation:
+
+ /* Fill the core registers with known values. */
+ li x5, 0x5
+ li x6, 0x6
+ li x7, 0x7
+ li x8, 0x8
+ li x9, 0x9
+ li x10, 0xa
+ li x11, 0xb
+ li x12, 0xc
+ li x13, 0xd
+ li x14, 0xe
+ li x15, 0xf
+ li x16, 0x10
+ li x17, 0x11
+ li x18, 0x12
+ li x19, 0x13
+ li x20, 0x14
+ li x21, 0x15
+ li x22, 0x16
+ li x23, 0x17
+ li x24, 0x18
+ li x25, 0x19
+ li x26, 0x1a
+ li x27, 0x1b
+ li x28, 0x1c
+ li x29, 0x1d
+ li x30, 0x1e
+
+reg1_loop:
+
+ /* Check each register still contains the expected known value.
+ vRegTest1Implementation uses x31 as the temporary, vRegTest2Implementation
+ uses x5 as the temporary. */
+ li x31, 0x5
+ bne x31, x5, reg1_error_loop
+ li x31, 0x6
+ bne x31, x6, reg1_error_loop
+ li x31, 0x7
+ bne x31, x7, reg1_error_loop
+ li x31, 0x8
+ bne x31, x8, reg1_error_loop
+ li x31, 0x9
+ bne x31, x9, reg1_error_loop
+ li x31, 0xa
+ bne x31, x10, reg1_error_loop
+ li x31, 0xb
+ bne x31, x11, reg1_error_loop
+ li x31, 0xc
+ bne x31, x12, reg1_error_loop
+ li x31, 0xd
+ bne x31, x13, reg1_error_loop
+ li x31, 0xe
+ bne x31, x14, reg1_error_loop
+ li x31, 0xf
+ bne x31, x15, reg1_error_loop
+ li x31, 0x10
+ bne x31, x16, reg1_error_loop
+ li x31, 0x11
+ bne x31, x17, reg1_error_loop
+ li x31, 0x12
+ bne x31, x18, reg1_error_loop
+ li x31, 0x13
+ bne x31, x19, reg1_error_loop
+ li x31, 0x14
+ bne x31, x20, reg1_error_loop
+ li x31, 0x15
+ bne x31, x21, reg1_error_loop
+ li x31, 0x16
+ bne x31, x22, reg1_error_loop
+ li x31, 0x17
+ bne x31, x23, reg1_error_loop
+ li x31, 0x18
+ bne x31, x24, reg1_error_loop
+ li x31, 0x19
+ bne x31, x25, reg1_error_loop
+ li x31, 0x1a
+ bne x31, x26, reg1_error_loop
+ li x31, 0x1b
+ bne x31, x27, reg1_error_loop
+ li x31, 0x1c
+ bne x31, x28, reg1_error_loop
+ li x31, 0x1d
+ bne x31, x29, reg1_error_loop
+ li x31, 0x1e
+ bne x31, x30, reg1_error_loop
+
+ /* Everything passed, increment the loop counter. */
+ lw x31, ulRegTest1LoopCounterConst
+ lw x30, 0(x31)
+ addi x30, x30, 1
+ sw x30, 0(x31)
+
+ /* Restore clobbered register reading for next loop. */
+ li x30, 0x1e
+
+ /* Yield to increase code coverage. */
+ ecall
+
+ /* Start again. */
+ jal reg1_loop
+
+reg1_error_loop:
+ /* Jump here if a register contains an uxpected value. This stops the loop
+ counter being incremented so the check task knows an error was found. */
+ ebreak
+ jal reg1_error_loop
+
+.align( 4 )
+ulRegTest1LoopCounterConst: .word ulRegTest1LoopCounter
+
+/*-----------------------------------------------------------*/
+
+.align( 4 )
+vRegTest2Implementation:
+
+ /* Fill the core registers with known values. */
+ li x6, 0x61
+ li x7, 0x71
+ li x8, 0x81
+ li x9, 0x91
+ li x10, 0xa1
+ li x11, 0xb1
+ li x12, 0xc1
+ li x13, 0xd1
+ li x14, 0xe1
+ li x15, 0xf1
+ li x16, 0x20
+ li x17, 0x21
+ li x18, 0x22
+ li x19, 0x23
+ li x20, 0x24
+ li x21, 0x25
+ li x22, 0x26
+ li x23, 0x27
+ li x24, 0x28
+ li x25, 0x29
+ li x26, 0x2a
+ li x27, 0x2b
+ li x28, 0x2c
+ li x29, 0x2d
+ li x30, 0x2e
+ li x31, 0x2f
+
+Reg2_loop:
+
+ /* Check each register still contains the expected known value.
+ vRegTest2Implementation uses x5 as the temporary, vRegTest1Implementation
+ uses x31 as the temporary. */
+ li x5, 0x61
+ bne x5, x6, reg2_error_loop
+ li x5, 0x71
+ bne x5, x7, reg2_error_loop
+ li x5, 0x81
+ bne x5, x8, reg2_error_loop
+ li x5, 0x91
+ bne x5, x9, reg2_error_loop
+ li x5, 0xa1
+ bne x5, x10, reg2_error_loop
+ li x5, 0xb1
+ bne x5, x11, reg2_error_loop
+ li x5, 0xc1
+ bne x5, x12, reg2_error_loop
+ li x5, 0xd1
+ bne x5, x13, reg2_error_loop
+ li x5, 0xe1
+ bne x5, x14, reg2_error_loop
+ li x5, 0xf1
+ bne x5, x15, reg2_error_loop
+ li x5, 0x20
+ bne x5, x16, reg2_error_loop
+ li x5, 0x21
+ bne x5, x17, reg2_error_loop
+ li x5, 0x22
+ bne x5, x18, reg2_error_loop
+ li x5, 0x23
+ bne x5, x19, reg2_error_loop
+ li x5, 0x24
+ bne x5, x20, reg2_error_loop
+ li x5, 0x25
+ bne x5, x21, reg2_error_loop
+ li x5, 0x26
+ bne x5, x22, reg2_error_loop
+ li x5, 0x27
+ bne x5, x23, reg2_error_loop
+ li x5, 0x28
+ bne x5, x24, reg2_error_loop
+ li x5, 0x29
+ bne x5, x25, reg2_error_loop
+ li x5, 0x2a
+ bne x5, x26, reg2_error_loop
+ li x5, 0x2b
+ bne x5, x27, reg2_error_loop
+ li x5, 0x2c
+ bne x5, x28, reg2_error_loop
+ li x5, 0x2d
+ bne x5, x29, reg2_error_loop
+ li x5, 0x2e
+ bne x5, x30, reg2_error_loop
+ li x5, 0x2f
+ bne x5, x31, reg2_error_loop
+
+ /* Everything passed, increment the loop counter. */
+ lw x5, ulRegTest2LoopCounterConst
+ lw x6, 0(x5)
+ addi x6, x6, 1
+ sw x6, 0(x5)
+
+ /* Restore clobbered register reading for next loop. */
+ li x6, 0x61
+
+ /* Start again. */
+ jal Reg2_loop
+
+reg2_error_loop:
+ /* Jump here if a register contains an uxpected value. This stops the loop
+ counter being incremented so the check task knows an error was found. */
+ ebreak
+ jal reg2_error_loop
+
+.align( 4 )
+ulRegTest2LoopCounterConst: .word ulRegTest2LoopCounter
+
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/fake_rom.ld b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/fake_rom.ld
new file mode 100644
index 0000000000..b63fad8f05
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/fake_rom.ld
@@ -0,0 +1,117 @@
+OUTPUT_ARCH( "riscv" )
+ENTRY( _start )
+
+MEMORY
+{
+ /* Fake ROM area */
+ rom (rxa) : ORIGIN = 0x80000000, LENGTH = 512K
+ ram (wxa) : ORIGIN = 0x80080000, LENGTH = 512K
+}
+
+SECTIONS
+{
+ .init :
+ {
+ _text = .;
+ KEEP (*(SORT_NONE(.init)))
+ } >rom AT>rom
+
+ .text :
+ {
+ *(.text.unlikely .text.unlikely.*)
+ *(.text.startup .text.startup.*)
+ *(.text .text.*)
+ *(.gnu.linkonce.t.*)
+ } >rom AT>rom
+
+ .fini :
+ {
+ KEEP (*(SORT_NONE(.fini)))
+ _etext = .;
+ } >rom AT>rom
+
+ .rodata.align :
+ {
+ . = ALIGN(4);
+ _rodata = .;
+ } >rom AT>rom
+
+ .rodata.start :
+ {
+ _rodata_lma = LOADADDR(.rodata.start);
+ } >rom AT>rom
+
+ .rodata :
+ {
+ *(.rdata)
+ *(.rodata .rodata.*)
+ *(.gnu.linkonce.r.*)
+
+ . = ALIGN(4);
+ _erodata = .;
+ } >rom AT>rom
+
+ .data.align :
+ {
+ . = ALIGN(4);
+ _data = .;
+ } >ram AT>rom
+
+ .data.start :
+ {
+ _data_lma = LOADADDR(.data.start);
+ } >ram AT>rom
+
+ .data :
+ {
+ *(.data .data.*)
+ *(.gnu.linkonce.d.*)
+ . = ALIGN(8);
+ PROVIDE( __global_pointer$ = . + 0x800 );
+ *(.sdata .sdata.*)
+ *(.sdata2 .sdata2.*)
+ *(.gnu.linkonce.s.*)
+ . = ALIGN(8);
+ *(.srodata.cst16)
+ *(.srodata.cst8)
+ *(.srodata.cst4)
+ *(.srodata.cst2)
+ *(.srodata .srodata.*)
+
+ . = ALIGN(4);
+ _edata = .;
+ } >ram AT>rom
+
+ .bss.align :
+ {
+ . = ALIGN(4);
+ _bss = .;
+ } >ram AT>rom
+
+ .bss.start :
+ {
+ _bss_lma = LOADADDR(.bss.start);
+ } >ram AT>rom
+
+ .bss :
+ {
+ *(.sbss*)
+ *(.gnu.linkonce.sb.*)
+ *(.bss .bss.*)
+ *(.gnu.linkonce.b.*)
+ *(COMMON)
+
+ . = ALIGN(4);
+ _ebss = .;
+ } >ram AT>rom
+
+ . = ALIGN(8);
+ _end = .;
+
+ .stack :
+ {
+ . = ALIGN(16);
+ . += __stack_size;
+ _stack_top = .;
+ } >ram AT>ram
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/output/placeholder.txt b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/output/placeholder.txt
new file mode 100644
index 0000000000..a3fb3f1613
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/output/placeholder.txt
@@ -0,0 +1,3 @@
+File included to ensure the "output" directory is not empty, and can therefore
+be checked into Git. This prevents the necessity to have a cross platform
+method of creating the directory from within the makefile.
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/printf-stdarg.c b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/printf-stdarg.c
new file mode 100644
index 0000000000..e8b3add570
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/printf-stdarg.c
@@ -0,0 +1,314 @@
+/*
+ Copyright 2001, 2002 Georges Menie (www.menie.org)
+ stdarg version contributed by Christian Ettinger
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/*
+ putchar is the only external dependency for this file,
+ if you have a working putchar, leave it commented out.
+ If not, uncomment the define below and
+ replace outbyte(c) by your own function call.
+
+*/
+
+#include
+#include "ns16550.h"
+#include "riscv-virt.h"
+
+#define putchar(c) vOutNS16550( &dev, c )
+
+static int tiny_print( char **out, const char *format, va_list args, unsigned int buflen );
+
+static struct device dev = { NS16550_ADDR };
+
+static void printchar(char **str, int c, char *buflimit)
+{
+ if (str) {
+ if( buflimit == ( char * ) 0 ) {
+ /* Limit of buffer not known, write charater to buffer. */
+ **str = (char)c;
+ ++(*str);
+ }
+ else if( ( ( unsigned long ) *str ) < ( ( unsigned long ) buflimit ) ) {
+ /* Within known limit of buffer, write character. */
+ **str = (char)c;
+ ++(*str);
+ }
+ }
+ else
+ {
+ putchar(c);
+ }
+}
+
+#define PAD_RIGHT 1
+#define PAD_ZERO 2
+
+static int prints(char **out, const char *string, int width, int pad, char *buflimit)
+{
+ register int pc = 0, padchar = ' ';
+
+ if (width > 0) {
+ register int len = 0;
+ register const char *ptr;
+ for (ptr = string; *ptr; ++ptr) ++len;
+ if (len >= width) width = 0;
+ else width -= len;
+ if (pad & PAD_ZERO) padchar = '0';
+ }
+ if (!(pad & PAD_RIGHT)) {
+ for ( ; width > 0; --width) {
+ printchar (out, padchar, buflimit);
+ ++pc;
+ }
+ }
+ for ( ; *string ; ++string) {
+ printchar (out, *string, buflimit);
+ ++pc;
+ }
+ for ( ; width > 0; --width) {
+ printchar (out, padchar, buflimit);
+ ++pc;
+ }
+
+ return pc;
+}
+
+/* the following should be enough for 32 bit int */
+#define PRINT_BUF_LEN 12
+
+static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase, char *buflimit)
+{
+ char print_buf[PRINT_BUF_LEN];
+ register char *s;
+ register int t, neg = 0, pc = 0;
+ register unsigned int u = (unsigned int)i;
+
+ if (i == 0) {
+ print_buf[0] = '0';
+ print_buf[1] = '\0';
+ return prints (out, print_buf, width, pad, buflimit);
+ }
+
+ if (sg && b == 10 && i < 0) {
+ neg = 1;
+ u = (unsigned int)-i;
+ }
+
+ s = print_buf + PRINT_BUF_LEN-1;
+ *s = '\0';
+
+ while (u) {
+ t = (unsigned int)u % b;
+ if( t >= 10 )
+ t += letbase - '0' - 10;
+ *--s = (char)(t + '0');
+ u /= b;
+ }
+
+ if (neg) {
+ if( width && (pad & PAD_ZERO) ) {
+ printchar (out, '-', buflimit);
+ ++pc;
+ --width;
+ }
+ else {
+ *--s = '-';
+ }
+ }
+
+ return pc + prints (out, s, width, pad, buflimit);
+}
+
+static int tiny_print( char **out, const char *format, va_list args, unsigned int buflen )
+{
+ register int width, pad;
+ register int pc = 0;
+ char scr[2], *buflimit;
+
+ if( buflen == 0 ){
+ buflimit = ( char * ) 0;
+ }
+ else {
+ /* Calculate the last valid buffer space, leaving space for the NULL
+ terminator. */
+ buflimit = ( *out ) + ( buflen - 1 );
+ }
+
+ for (; *format != 0; ++format) {
+ if (*format == '%') {
+ ++format;
+ width = pad = 0;
+ if (*format == '\0') break;
+ if (*format == '%') goto out;
+ if (*format == '-') {
+ ++format;
+ pad = PAD_RIGHT;
+ }
+ while (*format == '0') {
+ ++format;
+ pad |= PAD_ZERO;
+ }
+ for ( ; *format >= '0' && *format <= '9'; ++format) {
+ width *= 10;
+ width += *format - '0';
+ }
+ if( *format == 's' ) {
+ register char *s = (char *)va_arg( args, int );
+ pc += prints (out, s?s:"(null)", width, pad, buflimit);
+ continue;
+ }
+ if( *format == 'd' ) {
+ pc += printi (out, va_arg( args, int ), 10, 1, width, pad, 'a', buflimit);
+ continue;
+ }
+ if( *format == 'x' ) {
+ pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'a', buflimit);
+ continue;
+ }
+ if( *format == 'X' ) {
+ pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'A', buflimit);
+ continue;
+ }
+ if( *format == 'u' ) {
+ pc += printi (out, va_arg( args, int ), 10, 0, width, pad, 'a', buflimit);
+ continue;
+ }
+ if( *format == 'c' ) {
+ /* char are converted to int then pushed on the stack */
+ scr[0] = (char)va_arg( args, int );
+ scr[1] = '\0';
+ pc += prints (out, scr, width, pad, buflimit);
+ continue;
+ }
+ }
+ else {
+ out:
+ printchar (out, *format, buflimit);
+ ++pc;
+ }
+ }
+ if (out) **out = '\0';
+ va_end( args );
+ return pc;
+}
+
+int printf(const char *format, ...)
+{
+ va_list args;
+
+ va_start( args, format );
+ return tiny_print( 0, format, args, 0 );
+}
+
+int sprintf(char *out, const char *format, ...)
+{
+ va_list args;
+
+ va_start( args, format );
+ return tiny_print( &out, format, args, 0 );
+}
+
+
+int snprintf( char *buf, unsigned int count, const char *format, ... )
+{
+ va_list args;
+
+ ( void ) count;
+
+ va_start( args, format );
+ return tiny_print( &buf, format, args, count );
+}
+
+
+#ifdef TEST_PRINTF
+int main(void)
+{
+ char *ptr = "Hello world!";
+ char *np = 0;
+ int i = 5;
+ unsigned int bs = sizeof(int)*8;
+ int mi;
+ char buf[80];
+
+ mi = (1 << (bs-1)) + 1;
+ printf("%s\n", ptr);
+ printf("printf test\n");
+ printf("%s is null pointer\n", np);
+ printf("%d = 5\n", i);
+ printf("%d = - max int\n", mi);
+ printf("char %c = 'a'\n", 'a');
+ printf("hex %x = ff\n", 0xff);
+ printf("hex %02x = 00\n", 0);
+ printf("signed %d = unsigned %u = hex %x\n", -3, -3, -3);
+ printf("%d %s(s)%", 0, "message");
+ printf("\n");
+ printf("%d %s(s) with %%\n", 0, "message");
+ sprintf(buf, "justif: \"%-10s\"\n", "left"); printf("%s", buf);
+ sprintf(buf, "justif: \"%10s\"\n", "right"); printf("%s", buf);
+ sprintf(buf, " 3: %04d zero padded\n", 3); printf("%s", buf);
+ sprintf(buf, " 3: %-4d left justif.\n", 3); printf("%s", buf);
+ sprintf(buf, " 3: %4d right justif.\n", 3); printf("%s", buf);
+ sprintf(buf, "-3: %04d zero padded\n", -3); printf("%s", buf);
+ sprintf(buf, "-3: %-4d left justif.\n", -3); printf("%s", buf);
+ sprintf(buf, "-3: %4d right justif.\n", -3); printf("%s", buf);
+
+ return 0;
+}
+
+/*
+ * if you compile this file with
+ * gcc -Wall $(YOUR_C_OPTIONS) -DTEST_PRINTF -c printf.c
+ * you will get a normal warning:
+ * printf.c:214: warning: spurious trailing `%' in format
+ * this line is testing an invalid % at the end of the format string.
+ *
+ * this should display (on 32bit int machine) :
+ *
+ * Hello world!
+ * printf test
+ * (null) is null pointer
+ * 5 = 5
+ * -2147483647 = - max int
+ * char a = 'a'
+ * hex ff = ff
+ * hex 00 = 00
+ * signed -3 = unsigned 4294967293 = hex fffffffd
+ * 0 message(s)
+ * 0 message(s) with %
+ * justif: "left "
+ * justif: " right"
+ * 3: 0003 zero padded
+ * 3: 3 left justif.
+ * 3: 3 right justif.
+ * -3: -003 zero padded
+ * -3: -3 left justif.
+ * -3: -3 right justif.
+ */
+
+#endif
+
+
+/* To keep linker happy. */
+int write( int i, char* c, int n)
+{
+ (void)i;
+ (void)n;
+ (void)c;
+ return 0;
+}
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/start.S b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/start.S
new file mode 100644
index 0000000000..ec2aa5b5cb
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/start.S
@@ -0,0 +1,85 @@
+/*
+ * FreeRTOS V202112.00
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#include "riscv-virt.h"
+
+ .extern main
+ .section .init
+ .globl _start
+ .type _start,@function
+_start:
+ .cfi_startproc
+ .cfi_undefined ra
+.option push
+.option norelax
+ la gp, __global_pointer$
+.option pop
+
+ // Continue primary hart
+ csrr a0, mhartid
+ li a1, PRIM_HART
+ bne a0, a1, secondary
+
+ // Primary hart
+ la sp, _stack_top
+
+ // Load data section
+ la a0, _data_lma
+ la a1, _data
+ la a2, _edata
+ bgeu a1, a2, 2f
+1:
+ LOAD t0, (a0)
+ STOR t0, (a1)
+ addi a0, a0, REGSIZE
+ addi a1, a1, REGSIZE
+ bltu a1, a2, 1b
+2:
+
+ // Clear bss section
+ la a0, _bss
+ la a1, _ebss
+ bgeu a0, a1, 2f
+1:
+ STOR zero, (a0)
+ addi a0, a0, REGSIZE
+ bltu a0, a1, 1b
+2:
+
+ // argc, argv, envp is 0
+ li a0, 0
+ li a1, 0
+ li a2, 0
+ jal main
+1:
+ wfi
+ j 1b
+
+secondary:
+ // TODO: Multicore is not supported
+ wfi
+ j secondary
+ .cfi_endproc
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/main.c b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/main.c
new file mode 100644
index 0000000000..edcb0a956c
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/main.c
@@ -0,0 +1,301 @@
+/*
+ * FreeRTOS V202112.00
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+
+/******************************************************************************
+ * See https://www.freertos.org/freertos-on-qemu-mps2-an385-model.html for
+ * instructions.
+ *
+ * This project provides two demo applications. A simple blinky style project,
+ * and a more comprehensive test and demo application. The
+ * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY constant, defined in this file, is used to
+ * select between the two. The simply blinky demo is implemented and described
+ * in main_blinky.c. The more comprehensive test and demo application is
+ * implemented and described in main_full.c.
+ *
+ * This file implements the code that is not demo specific, including the
+ * hardware setup and FreeRTOS hook functions.
+ *
+ * Running in QEMU:
+ * Use the following commands to start the application running in a way that
+ * enables the debugger to connect, omit the "-s -S" to run the project without
+ * the debugger:
+ *
+ * qemu-system-riscv32 -machine virt -smp 1 -nographic -bios none -serial stdio -kernel [path-to]/RTOSDemo.elf -s -S
+ */
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* Standard includes. */
+#include
+#include
+
+/* This project provides two demo applications. A simple blinky style demo
+application, and a more comprehensive test and demo application. The
+mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is used to select between the two.
+
+If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is 1 then the blinky demo will be built.
+The blinky demo is implemented and described in main_blinky.c.
+
+If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is not 1 then the comprehensive test and
+demo application will be built. The comprehensive test and demo application is
+implemented and described in main_full.c. */
+#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 0
+
+/* printf() output uses the UART. These constants define the addresses of the
+required UART registers. */
+#define UART0_ADDRESS ( 0x40004000UL )
+#define UART0_DATA ( * ( ( ( volatile uint32_t * )( UART0_ADDRESS + 0UL ) ) ) )
+#define UART0_STATE ( * ( ( ( volatile uint32_t * )( UART0_ADDRESS + 4UL ) ) ) )
+#define UART0_CTRL ( * ( ( ( volatile uint32_t * )( UART0_ADDRESS + 8UL ) ) ) )
+#define UART0_BAUDDIV ( * ( ( ( volatile uint32_t * )( UART0_ADDRESS + 16UL ) ) ) )
+#define TX_BUFFER_MASK ( 1UL )
+
+/* Registers used to initialise the PLIC. */
+#define mainPLIC_PENDING_0 ( * ( ( volatile uint32_t * ) 0x0C001000UL ) )
+#define mainPLIC_PENDING_1 ( * ( ( volatile uint32_t * ) 0x0C001004UL ) )
+#define mainPLIC_ENABLE_0 ( * ( ( volatile uint32_t * ) 0x0C002000UL ) )
+#define mainPLIC_ENABLE_1 ( * ( ( volatile uint32_t * ) 0x0C002004UL ) )
+
+/*
+ * main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1.
+ * main_full() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0.
+ */
+extern void main_blinky( void );
+extern void main_full( void );
+
+/*
+ * Only the comprehensive demo uses application hook (callback) functions. See
+ * https://www.FreeRTOS.org/a00016.html for more information.
+ */
+void vFullDemoTickHookFunction( void );
+void vFullDemoIdleFunction( void );
+
+/*-----------------------------------------------------------*/
+
+void main( void )
+{
+ /* See https://www.freertos.org/freertos-on-qemu-mps2-an385-model.html for
+ instructions. */
+
+ /* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top
+ of this file. */
+ #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 )
+ {
+ main_blinky();
+ }
+ #else
+ {
+ main_full();
+ }
+ #endif
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationMallocFailedHook( void )
+{
+ /* vApplicationMallocFailedHook() will only be called if
+ configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
+ function that will get called if a call to pvPortMalloc() fails.
+ pvPortMalloc() is called internally by the kernel whenever a task, queue,
+ timer or semaphore is created using the dynamic allocation (as opposed to
+ static allocation) option. It is also called by various parts of the
+ demo application. If heap_1.c, heap_2.c or heap_4.c is being used, then the
+ size of the heap available to pvPortMalloc() is defined by
+ configTOTAL_HEAP_SIZE in FreeRTOSConfig.h, and the xPortGetFreeHeapSize()
+ API function can be used to query the size of free heap space that remains
+ (although it does not provide information on how the remaining heap might be
+ fragmented). See http://www.freertos.org/a00111.html for more
+ information. */
+ printf( "\r\n\r\nMalloc failed\r\n" );
+ portDISABLE_INTERRUPTS();
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationIdleHook( void )
+{
+ /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
+ to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
+ task. It is essential that code added to this hook function never attempts
+ to block in any way (for example, call xQueueReceive() with a block time
+ specified, or call vTaskDelay()). If application tasks make use of the
+ vTaskDelete() API function to delete themselves then it is also important
+ that vApplicationIdleHook() is permitted to return to its calling function,
+ because it is the responsibility of the idle task to clean up memory
+ allocated by the kernel to any task that has since deleted itself. */
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
+{
+ ( void ) pcTaskName;
+ ( void ) pxTask;
+
+ /* Run time stack overflow checking is performed if
+ configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
+ function is called if a stack overflow is detected. */
+ printf( "\r\n\r\nStack overflow in %s\r\n", pcTaskName );
+ portDISABLE_INTERRUPTS();
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationTickHook( void )
+{
+ /* This function will be called by each tick interrupt if
+ configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be
+ added here, but the tick hook is called from an interrupt context, so
+ code must not attempt to block, and only the interrupt safe FreeRTOS API
+ functions can be used (those that end in FromISR()). */
+
+ #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 )
+ {
+ extern void vFullDemoTickHookFunction( void );
+
+ vFullDemoTickHookFunction();
+ }
+ #endif /* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY */
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationDaemonTaskStartupHook( void )
+{
+ /* This function will be called once only, when the daemon task starts to
+ execute (sometimes called the timer task). This is useful if the
+ application includes initialisation code that would benefit from executing
+ after the scheduler has been started. */
+}
+/*-----------------------------------------------------------*/
+
+void vAssertCalled( const char *pcFileName, uint32_t ulLine )
+{
+volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0;
+
+ /* Called if an assertion passed to configASSERT() fails. See
+ http://www.freertos.org/a00110.html#configASSERT for more information. */
+
+ printf( "ASSERT! Line %d, file %s\r\n", ( int ) ulLine, pcFileName );
+
+ taskENTER_CRITICAL();
+ {
+ /* You can step out of this function to debug the assertion by using
+ the debugger to set ulSetToNonZeroInDebuggerToContinue to a non-zero
+ value. */
+ while( ulSetToNonZeroInDebuggerToContinue == 0 )
+ {
+ __asm volatile( "NOP" );
+ __asm volatile( "NOP" );
+ }
+ }
+ taskEXIT_CRITICAL();
+}
+/*-----------------------------------------------------------*/
+
+/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
+implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
+used by the Idle task. */
+void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
+{
+/* If the buffers to be provided to the Idle task are declared inside this
+function then they must be declared static - otherwise they will be allocated on
+the stack and so not exists after this function exits. */
+static StaticTask_t xIdleTaskTCB;
+static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
+
+ /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
+ state will be stored. */
+ *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
+
+ /* Pass out the array that will be used as the Idle task's stack. */
+ *ppxIdleTaskStackBuffer = uxIdleTaskStack;
+
+ /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
+ Note that, as the array is necessarily of type StackType_t,
+ configMINIMAL_STACK_SIZE is specified in words, not bytes. */
+ *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
+}
+/*-----------------------------------------------------------*/
+
+/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
+application must provide an implementation of vApplicationGetTimerTaskMemory()
+to provide the memory that is used by the Timer service task. */
+void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
+{
+/* If the buffers to be provided to the Timer task are declared inside this
+function then they must be declared static - otherwise they will be allocated on
+the stack and so not exists after this function exits. */
+static StaticTask_t xTimerTaskTCB;
+static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
+
+ /* Pass out a pointer to the StaticTask_t structure in which the Timer
+ task's state will be stored. */
+ *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
+
+ /* Pass out the array that will be used as the Timer task's stack. */
+ *ppxTimerTaskStackBuffer = uxTimerTaskStack;
+
+ /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
+ Note that, as the array is necessarily of type StackType_t,
+ configMINIMAL_STACK_SIZE is specified in words, not bytes. */
+ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
+}
+/*-----------------------------------------------------------*/
+
+int __write( int iFile, char *pcString, int iStringLength )
+{
+ int iNextChar;
+
+ /* Avoid compiler warnings about unused parameters. */
+ ( void ) iFile;
+
+ /* Output the formatted string to the UART. */
+ for( iNextChar = 0; iNextChar < iStringLength; iNextChar++ )
+ {
+ while( ( UART0_STATE & TX_BUFFER_MASK ) != 0 );
+ UART0_DATA = *pcString;
+ pcString++;
+ }
+
+ return iStringLength;
+}
+/*-----------------------------------------------------------*/
+
+void *malloc( size_t size )
+{
+ ( void ) size;
+
+ /* This project uses heap_4 so doesn't set up a heap for use by the C
+ library - but something is calling the C library malloc(). See
+ https://freertos.org/a00111.html for more information. */
+ printf( "\r\n\r\nUnexpected call to malloc() - should be usine pvPortMalloc()\r\n" );
+ portDISABLE_INTERRUPTS();
+ for( ;; );
+
+}
+/*-----------------------------------------------------------*/
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/main_blinky.c b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/main_blinky.c
new file mode 100644
index 0000000000..3ac9c8dcb1
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/main_blinky.c
@@ -0,0 +1,235 @@
+/*
+ * FreeRTOS V202112.00
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/******************************************************************************
+ * This project provides two demo applications. A simple blinky style project,
+ * and a more comprehensive test and demo application. The
+ * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select
+ * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY
+ * in main.c. This file implements the simply blinky version.
+ *
+ * This file only contains the source code that is specific to the basic demo.
+ * Generic functions, such FreeRTOS hook functions, are defined in main.c.
+ ******************************************************************************
+ *
+ * main_blinky() creates one queue, one software timer, and two tasks. It then
+ * starts the scheduler.
+ *
+ * The Queue Send Task:
+ * The queue send task is implemented by the prvQueueSendTask() function in
+ * this file. It uses vTaskDelayUntil() to create a periodic task that sends
+ * the value 100 to the queue every 200 (simulated) milliseconds.
+ *
+ * The Queue Send Software Timer:
+ * The timer is an auto-reload timer with a period of two (simulated) seconds.
+ * Its callback function writes the value 200 to the queue. The callback
+ * function is implemented by prvQueueSendTimerCallback() within this file.
+ *
+ * The Queue Receive Task:
+ * The queue receive task is implemented by the prvQueueReceiveTask() function
+ * in this file. prvQueueReceiveTask() waits for data to arrive on the queue.
+ * When data is received, the task checks the value of the data, then outputs a
+ * message to indicate if the data came from the queue send task or the queue
+ * send software timer.
+ */
+
+/* Standard includes. */
+#include
+
+/* Kernel includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "timers.h"
+#include "queue.h"
+
+/* Priorities at which the tasks are created. */
+#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
+#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
+
+/* The rate at which data is sent to the queue. The times are converted from
+milliseconds to ticks using the pdMS_TO_TICKS() macro. */
+#define mainTASK_SEND_FREQUENCY_MS pdMS_TO_TICKS( 200UL )
+#define mainTIMER_SEND_FREQUENCY_MS pdMS_TO_TICKS( 2000UL )
+
+/* The number of items the queue can hold at once. */
+#define mainQUEUE_LENGTH ( 2 )
+
+/* The values sent to the queue receive task from the queue send task and the
+queue send software timer respectively. */
+#define mainVALUE_SENT_FROM_TASK ( 100UL )
+#define mainVALUE_SENT_FROM_TIMER ( 200UL )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The tasks as described in the comments at the top of this file.
+ */
+static void prvQueueReceiveTask( void *pvParameters );
+static void prvQueueSendTask( void *pvParameters );
+
+/*
+ * The callback function executed when the software timer expires.
+ */
+static void prvQueueSendTimerCallback( TimerHandle_t xTimerHandle );
+
+/*-----------------------------------------------------------*/
+
+/* The queue used by both tasks. */
+static QueueHandle_t xQueue = NULL;
+
+/* A software timer that is started from the tick hook. */
+static TimerHandle_t xTimer = NULL;
+
+/*-----------------------------------------------------------*/
+
+/*** SEE THE COMMENTS AT THE TOP OF THIS FILE ***/
+void main_blinky( void )
+{
+const TickType_t xTimerPeriod = mainTIMER_SEND_FREQUENCY_MS;
+
+ /* Create the queue. */
+ xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
+
+ if( xQueue != NULL )
+ {
+ /* Start the two tasks as described in the comments at the top of this
+ file. */
+ xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */
+ "Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
+ configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
+ NULL, /* The parameter passed to the task - not used in this simple case. */
+ mainQUEUE_RECEIVE_TASK_PRIORITY,/* The priority assigned to the task. */
+ NULL ); /* The task handle is not required, so NULL is passed. */
+
+ xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
+
+ /* Create the software timer, but don't start it yet. */
+ xTimer = xTimerCreate( "Timer", /* The text name assigned to the software timer - for debug only as it is not used by the kernel. */
+ xTimerPeriod, /* The period of the software timer in ticks. */
+ pdTRUE, /* xAutoReload is set to pdTRUE, so this is an auto-reload timer. */
+ NULL, /* The timer's ID is not used. */
+ prvQueueSendTimerCallback );/* The function executed when the timer expires. */
+
+ xTimerStart( xTimer, 0 ); /* The scheduler has not started so use a block time of 0. */
+
+ /* Start the tasks and timer running. */
+ vTaskStartScheduler();
+ }
+
+ /* If all is well, the scheduler will now be running, and the following
+ line will never be reached. If the following line does execute, then
+ there was insufficient FreeRTOS heap memory available for the idle and/or
+ timer tasks to be created. See the memory management section on the
+ FreeRTOS web site for more details. NOTE: This demo uses static allocation
+ for the idle and timer tasks so this line should never execute. */
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+static void prvQueueSendTask( void *pvParameters )
+{
+TickType_t xNextWakeTime;
+const TickType_t xBlockTime = mainTASK_SEND_FREQUENCY_MS;
+const uint32_t ulValueToSend = mainVALUE_SENT_FROM_TASK;
+
+ /* Prevent the compiler warning about the unused parameter. */
+ ( void ) pvParameters;
+
+ /* Initialise xNextWakeTime - this only needs to be done once. */
+ xNextWakeTime = xTaskGetTickCount();
+
+ for( ;; )
+ {
+ /* Place this task in the blocked state until it is time to run again.
+ The block time is specified in ticks, pdMS_TO_TICKS() was used to
+ convert a time specified in milliseconds into a time specified in ticks.
+ While in the Blocked state this task will not consume any CPU time. */
+ vTaskDelayUntil( &xNextWakeTime, xBlockTime );
+
+ /* Send to the queue - causing the queue receive task to unblock and
+ write to the console. 0 is used as the block time so the send operation
+ will not block - it shouldn't need to block as the queue should always
+ have at least one space at this point in the code. */
+ xQueueSend( xQueue, &ulValueToSend, 0U );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvQueueSendTimerCallback( TimerHandle_t xTimerHandle )
+{
+const uint32_t ulValueToSend = mainVALUE_SENT_FROM_TIMER;
+
+ /* This is the software timer callback function. The software timer has a
+ period of two seconds and is reset each time a key is pressed. This
+ callback function will execute if the timer expires, which will only happen
+ if a key is not pressed for two seconds. */
+
+ /* Avoid compiler warnings resulting from the unused parameter. */
+ ( void ) xTimerHandle;
+
+ /* Send to the queue - causing the queue receive task to unblock and
+ write out a message. This function is called from the timer/daemon task, so
+ must not block. Hence the block time is set to 0. */
+ xQueueSend( xQueue, &ulValueToSend, 0U );
+}
+/*-----------------------------------------------------------*/
+
+static void prvQueueReceiveTask( void *pvParameters )
+{
+uint32_t ulReceivedValue;
+
+ /* Prevent the compiler warning about the unused parameter. */
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /* Wait until something arrives in the queue - this task will block
+ indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
+ FreeRTOSConfig.h. It will not use any CPU time while it is in the
+ Blocked state. */
+ xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
+
+ /* To get here something must have been received from the queue, but
+ is it an expected value? */
+ if( ulReceivedValue == mainVALUE_SENT_FROM_TASK )
+ {
+ /* It is normally not good to call printf() from an embedded system,
+ although it is ok in this simulated case. */
+ printf( "Message received from task\r\n" );
+ }
+ else if( ulReceivedValue == mainVALUE_SENT_FROM_TIMER )
+ {
+ printf( "Message received from software timer\r\n" );
+ }
+ else
+ {
+ printf( "Unexpected message\r\n" );
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/main_full.c b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/main_full.c
new file mode 100644
index 0000000000..205826752f
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/main_full.c
@@ -0,0 +1,398 @@
+/*
+ * FreeRTOS V202112.00
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+
+/*
+ *******************************************************************************
+ * This project provides two demo applications. A simple blinky style project,
+ * and a more comprehensive test and demo application. The
+ * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select
+ * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY
+ * in main.c. This file implements the comprehensive test and demo version.
+ *
+ * This file only contains the source code that is specific to the full demo.
+ * Generic functions, such FreeRTOS hook functions, are defined in main.c.
+ *******************************************************************************
+ *
+ * main() creates all the demo application tasks, then starts the scheduler.
+ * The web documentation provides more details of the standard demo application
+ * tasks, which provide no particular functionality but do provide a good
+ * example of how to use the FreeRTOS API.
+ *
+ * In addition to the standard demo tasks, the following tasks and tests are
+ * defined and/or created within this file:
+ *
+ * "Check" task - This only executes every five (simulated) seconds. Its main
+ * function is to check the tests running in the standard demo tasks have never
+ * failed and that all the tasks are still running. If that is the case the
+ * check task prints "PASS : nnnn (x)", where nnnn is the current tick count and
+ * x is the number of times the interrupt nesting test executed while interrupts
+ * were nested. If the check task discovers a failed test or a stalled task
+ * it prints a message that indicates which task reported the error or stalled.
+ * Normally the check task would have the highest priority to keep its timing
+ * jitter to a minimum. In this case the check task is run at the idle priority
+ * to ensure other tasks are not stalled by it writing to a slow UART using a
+ * polling driver.
+ *
+ */
+
+/* Standard includes. */
+#include
+#include
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+
+/* Demo app includes. */
+#include "death.h"
+#include "blocktim.h"
+#include "semtest.h"
+#include "PollQ.h"
+#include "GenQTest.h"
+#include "QPeek.h"
+#include "recmutex.h"
+#include "QueueSet.h"
+#include "EventGroupsDemo.h"
+#include "MessageBufferDemo.h"
+#include "StreamBufferDemo.h"
+#include "AbortDelay.h"
+#include "countsem.h"
+#include "dynamic.h"
+#include "MessageBufferAMP.h"
+#include "QueueOverwrite.h"
+#include "QueueSetPolling.h"
+#include "StaticAllocation.h"
+#include "TaskNotify.h"
+#include "TaskNotifyArray.h"
+#include "TimerDemo.h"
+#include "StreamBufferInterrupt.h"
+#include "IntSemTest.h"
+
+/*-----------------------------------------------------------*/
+
+/* Task priorities. */
+#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 )
+#define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
+#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
+#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
+#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )
+
+/* Stack sizes are defined relative to configMINIMAL_STACK_SIZE so they scale
+across projects that have that constant set differently - in this case the
+constant is different depending on the compiler in use. */
+#define mainMESSAGE_BUFFER_STACK_SIZE ( configMINIMAL_STACK_SIZE + ( configMINIMAL_STACK_SIZE >> 1 ) )
+#define mainCHECK_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE + ( configMINIMAL_STACK_SIZE >> 1 ) )
+#define mainREG_TEST_STACK_SIZE_WORDS 90
+
+/* Parameters that are passed into the register check tasks solely for the
+purpose of ensuring parameters are passed into tasks correctly. */
+#define mainREG_TEST_TASK_1_PARAMETER ( ( void * ) 0x12345678 )
+#define mainREG_TEST_TASK_2_PARAMETER ( ( void * ) 0x87654321 )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Register check tasks as described at the top of this file. The nature of
+ * these files necessitates that they are written in an assembly file, but the
+ * entry points are kept in the C file for the convenience of checking the task
+ * parameter.
+ */
+static void prvRegTestTaskEntry1( void *pvParameters );
+extern void vRegTest1Implementation( void );
+static void prvRegTestTaskEntry2( void *pvParameters );
+extern void vRegTest2Implementation( void );
+
+/* The task that checks the operation of all the other standard demo tasks, as
+ * described at the top of this file. */
+static void prvCheckTask( void *pvParameters );
+
+/*-----------------------------------------------------------*/
+
+/* The following two variables are used to communicate the status of the
+register check tasks to the check task. If the variables keep incrementing,
+then the register check tasks have not discovered any errors. If a variable
+stops incrementing, then an error has been found. */
+uint32_t ulRegTest1LoopCounter = 0UL, ulRegTest2LoopCounter = 0UL;
+volatile uint32_t *pulRegTest1LoopCounter = &ulRegTest1LoopCounter;
+volatile uint32_t *pulRegTest2LoopCounter = &ulRegTest2LoopCounter;
+
+/*-----------------------------------------------------------*/
+
+void main_full( void )
+{
+ /* Start the standard demo tasks. */
+ vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );
+ vStartRecursiveMutexTasks();
+ vCreateBlockTimeTasks();
+ vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
+ vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
+ vStartQueuePeekTasks();
+ vStartQueueSetTasks();
+ vStartEventGroupTasks();
+ vStartMessageBufferTasks( mainMESSAGE_BUFFER_STACK_SIZE );
+ vStartStreamBufferTasks();
+ vCreateAbortDelayTasks();
+ vStartCountingSemaphoreTasks();
+ vStartDynamicPriorityTasks();
+ vStartMessageBufferAMPTasks( configMINIMAL_STACK_SIZE );
+ vStartQueueOverwriteTask( tskIDLE_PRIORITY );
+ vStartQueueSetPollingTask();
+ vStartStaticallyAllocatedTasks();
+ vStartTaskNotifyTask();
+ vStartTaskNotifyArrayTask();
+ vStartTimerDemoTask( 50 );
+ vStartStreamBufferInterruptDemo();
+ vStartInterruptSemaphoreTasks();
+
+ /* Create the register check tasks, as described at the top of this file.
+ Use xTaskCreateStatic() to create a task using only statically allocated
+ memory. */
+ xTaskCreate( prvRegTestTaskEntry1, /* The function that implements the task. */
+ "Reg1", /* The name of the task. */
+ mainREG_TEST_STACK_SIZE_WORDS, /* Size of stack to allocate for the task - in words not bytes!. */
+ mainREG_TEST_TASK_1_PARAMETER, /* Parameter passed into the task. */
+ tskIDLE_PRIORITY, /* Priority of the task. */
+ NULL ); /* Can be used to pass out a handle to the created task. */
+ xTaskCreate( prvRegTestTaskEntry2, "Reg2", mainREG_TEST_STACK_SIZE_WORDS, mainREG_TEST_TASK_2_PARAMETER, tskIDLE_PRIORITY, NULL );
+
+ /* The suicide tasks must be created last as they need to know how many
+ tasks were running prior to their creation in order to ascertain whether
+ or not the correct/expected number of tasks are running at any given time. */
+ vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
+
+ xTaskCreate( prvCheckTask, "Check", mainCHECK_TASK_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+ /* Start the scheduler. */
+ vTaskStartScheduler();
+
+ /* If configSUPPORT_STATIC_ALLOCATION was false then execution would only
+ get here if there was insufficient heap memory to create either the idle or
+ timer tasks. As static allocation is used execution should never be able
+ to reach here. */
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+static void prvRegTestTaskEntry1( void *pvParameters )
+{
+ /* Although the regtest task is written in assembler, its entry point is
+ written in C for convenience of checking the task parameter is being passed
+ in correctly. */
+ if( pvParameters == mainREG_TEST_TASK_1_PARAMETER )
+ {
+ /* Start the part of the test that is written in assembler. */
+ vRegTest1Implementation();
+ }
+
+ /* The following line will only execute if the task parameter is found to
+ be incorrect. The check task will detect that the regtest loop counter is
+ not being incremented and flag an error. */
+ vTaskDelete( NULL );
+}
+/*-----------------------------------------------------------*/
+
+static void prvRegTestTaskEntry2( void *pvParameters )
+{
+ /* Although the regtest task is written in assembler, its entry point is
+ written in C for convenience of checking the task parameter is being passed
+ in correctly. */
+ if( pvParameters == mainREG_TEST_TASK_2_PARAMETER )
+ {
+ /* Start the part of the test that is written in assembler. */
+ vRegTest2Implementation();
+ }
+
+ /* The following line will only execute if the task parameter is found to
+ be incorrect. The check task will detect that the regtest loop counter is
+ not being incremented and flag an error. */
+ vTaskDelete( NULL );
+}
+/*-----------------------------------------------------------*/
+
+/* See the comments at the top of this file. */
+static void prvCheckTask( void *pvParameters )
+{
+static const char * pcMessage = "PASS";
+const TickType_t xTaskPeriod = pdMS_TO_TICKS( 5000UL );
+TickType_t xPreviousWakeTime;
+uint32_t ulLastRegTest1Value = 0, ulLastRegTest2Value = 0;
+
+ /* Avoid warning about unused parameter. */
+ ( void ) pvParameters;
+
+ xPreviousWakeTime = xTaskGetTickCount();
+
+ for( ;; )
+ {
+ vTaskDelayUntil( &xPreviousWakeTime, xTaskPeriod );
+
+ /* Has an error been found in any task? */
+ if( xAreStreamBufferTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreStreamBufferTasksStillRunning() returned false";
+ }
+ else if( xAreMessageBufferTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreMessageBufferTasksStillRunning() returned false";
+ }
+ if( xAreGenericQueueTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreGenericQueueTasksStillRunning() returned false";
+ }
+ else if( xIsCreateTaskStillRunning() != pdTRUE )
+ {
+ pcMessage = "xIsCreateTaskStillRunning() returned false";
+ }
+ else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreBlockTimeTestTasksStillRunning() returned false";
+ }
+ else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreSemaphoreTasksStillRunning() returned false";
+ }
+ else if( xArePollingQueuesStillRunning() != pdTRUE )
+ {
+ pcMessage = "xArePollingQueuesStillRunning() returned false";
+ }
+ else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreQueuePeekTasksStillRunning() returned false";
+ }
+ else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreRecursiveMutexTasksStillRunning() returned false";
+ }
+ else if( xAreQueueSetTasksStillRunning() != pdPASS )
+ {
+ pcMessage = "xAreQueueSetTasksStillRunning() returned false";
+ }
+ else if( xAreEventGroupTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreEventGroupTasksStillRunning() returned false";
+ }
+ else if( xAreAbortDelayTestTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreAbortDelayTestTasksStillRunning() returned false";
+ }
+ else if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreCountingSemaphoreTasksStillRunning() returned false";
+ }
+ else if( xAreDynamicPriorityTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreDynamicPriorityTasksStillRunning() returned false";
+ }
+ else if( xAreMessageBufferAMPTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreMessageBufferAMPTasksStillRunning() returned false";
+ }
+ else if( xIsQueueOverwriteTaskStillRunning() != pdTRUE )
+ {
+ pcMessage = "xIsQueueOverwriteTaskStillRunning() returned false";
+ }
+ else if( xAreQueueSetPollTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreQueueSetPollTasksStillRunning() returned false";
+ }
+ else if( xAreStaticAllocationTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreStaticAllocationTasksStillRunning() returned false";
+ }
+ else if( xAreTaskNotificationTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreTaskNotificationTasksStillRunning() returned false";
+ }
+ else if( xAreTaskNotificationArrayTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreTaskNotificationArrayTasksStillRunning() returned false";
+ }
+ else if( xAreTimerDemoTasksStillRunning( xTaskPeriod ) != pdTRUE )
+ {
+ pcMessage = "xAreTimerDemoTasksStillRunning() returned false";
+ }
+ else if( xIsInterruptStreamBufferDemoStillRunning() != pdTRUE )
+ {
+ pcMessage = "xIsInterruptStreamBufferDemoStillRunning() returned false";
+ }
+ else if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE )
+ {
+ pcMessage = "xAreInterruptSemaphoreTasksStillRunning() returned false";
+ }
+ else if( ulLastRegTest1Value == ulRegTest1LoopCounter ) /* Check that the register test 1 task is still running. */
+ {
+ pcMessage = "FreeRTOS Demo ERROR: Register test 1.\r\n";
+ }
+ else if( ulLastRegTest2Value == ulRegTest2LoopCounter ) /* Check that the register test 2 task is still running. */
+ {
+ pcMessage = "FreeRTOS Demo ERROR: Register test 2.\r\n";
+ }
+
+ ulLastRegTest1Value = ulRegTest1LoopCounter;
+ ulLastRegTest2Value = ulRegTest2LoopCounter;
+
+ /* It is normally not good to call printf() from an embedded system,
+ although it is ok in this simulated case. */
+ printf( "%s : %d\r\n", pcMessage, (int) xTaskGetTickCount() );
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vFullDemoTickHookFunction( void )
+{
+ /* Write to a queue that is in use as part of the queue set demo to
+ demonstrate using queue sets from an ISR. */
+ vQueueSetAccessQueueSetFromISR();
+
+ /* Call the event group ISR tests. */
+ vPeriodicEventGroupsProcessing();
+
+ /* Exercise stream buffers from interrupts. */
+ vPeriodicStreamBufferProcessing();
+
+ /* Exercise using queue overwrites from interrupts. */
+ vQueueOverwritePeriodicISRDemo();
+
+ /* Exercise using Queue Sets from interrupts. */
+ vQueueSetPollingInterruptAccess();
+
+ /* Exercise using task notifications from interrupts. */
+ xNotifyTaskFromISR();
+ xNotifyArrayTaskFromISR();
+
+ /* Exercise software timers from interrupts. */
+ vTimerPeriodicISRTests();
+
+ /* Exercise stream buffers from interrupts. */
+ vBasicStreamBufferSendFromISR();
+
+ /* Exercise semaphores from interrupts. */
+ vInterruptSemaphorePeriodicTest();
+}
+/*-----------------------------------------------------------*/
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/ns16550.c b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/ns16550.c
new file mode 100644
index 0000000000..7f81074bb8
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/ns16550.c
@@ -0,0 +1,74 @@
+/*
+ * FreeRTOS V202112.00
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#include
+
+#include "ns16550.h"
+
+/* register definitions */
+#define REG_RBR 0x00 /* Receiver buffer reg. */
+#define REG_THR 0x00 /* Transmitter holding reg. */
+#define REG_IER 0x01 /* Interrupt enable reg. */
+#define REG_IIR 0x02 /* Interrupt ID reg. */
+#define REG_FCR 0x02 /* FIFO control reg. */
+#define REG_LCR 0x03 /* Line control reg. */
+#define REG_MCR 0x04 /* Modem control reg. */
+#define REG_LSR 0x05 /* Line status reg. */
+#define REG_MSR 0x06 /* Modem status reg. */
+#define REG_SCR 0x07 /* Scratch reg. */
+#define REG_BRDL 0x00 /* Divisor latch (LSB) */
+#define REG_BRDH 0x01 /* Divisor latch (MSB) */
+
+/* Line status */
+#define LSR_DR 0x01 /* Data ready */
+#define LSR_OE 0x02 /* Overrun error */
+#define LSR_PE 0x04 /* Parity error */
+#define LSR_FE 0x08 /* Framing error */
+#define LSR_BI 0x10 /* Break interrupt */
+#define LSR_THRE 0x20 /* Transmitter holding register empty */
+#define LSR_TEMT 0x40 /* Transmitter empty */
+#define LSR_EIRF 0x80 /* Error in RCVR FIFO */
+
+static uint8_t readb( uintptr_t addr )
+{
+ return *( (uint8_t *) addr );
+}
+
+static void writeb( uint8_t b, uintptr_t addr )
+{
+ *( (uint8_t *) addr ) = b;
+}
+
+void vOutNS16550( struct device *dev, unsigned char c )
+{
+ uintptr_t addr = dev->addr;
+
+ while ( (readb( addr + REG_LSR ) & LSR_THRE) == 0 ) {
+ /* busy wait */
+ }
+
+ writeb( c, addr + REG_THR );
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/ns16550.h b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/ns16550.h
new file mode 100644
index 0000000000..8429c4a152
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/ns16550.h
@@ -0,0 +1,38 @@
+/*
+ * FreeRTOS V202112.00
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#ifndef NS16550_H_
+#define NS16550_H_
+
+#include
+
+struct device {
+ uintptr_t addr;
+};
+
+void vOutNS16550( struct device *dev, unsigned char c );
+
+#endif /* NS16550_H_ */
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/riscv-reg.h b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/riscv-reg.h
new file mode 100644
index 0000000000..c411231cd0
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/riscv-reg.h
@@ -0,0 +1,42 @@
+/*
+ * FreeRTOS V202112.00
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#ifndef RISCV_REG_H_
+#define RISCV_REG_H_
+
+#if __riscv_xlen == 32
+#define REGSIZE 4
+#define REGSHIFT 2
+#define LOAD lw
+#define STOR sw
+#elif __riscv_xlen == 64
+#define REGSIZE 8
+#define REGSHIFT 3
+#define LOAD ld
+#define STOR sd
+#endif /* __riscv_xlen */
+
+#endif /* RISCV_REG_H_ */
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/riscv-virt.c b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/riscv-virt.c
new file mode 100644
index 0000000000..5ae9946e74
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/riscv-virt.c
@@ -0,0 +1,64 @@
+/*
+ * FreeRTOS V202112.00
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#include
+
+#include
+
+#include "riscv-virt.h"
+#include "ns16550.h"
+
+int xGetCoreID( void )
+{
+int id;
+
+ __asm ("csrr %0, mhartid" : "=r" ( id ) );
+
+ return id;
+}
+
+void vSendString( const char *s )
+{
+struct device dev;
+size_t i;
+
+ dev.addr = NS16550_ADDR;
+
+ portENTER_CRITICAL();
+
+ for (i = 0; i < strlen(s); i++) {
+ vOutNS16550( &dev, s[i] );
+ }
+ vOutNS16550( &dev, '\n' );
+
+ portEXIT_CRITICAL();
+}
+
+void handle_trap(void)
+{
+ while (1)
+ ;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/riscv-virt.h b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/riscv-virt.h
new file mode 100644
index 0000000000..22f70130c2
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/riscv-virt.h
@@ -0,0 +1,54 @@
+/*
+ * FreeRTOS V202112.00
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#ifndef RISCV_VIRT_H_
+#define RISCV_VIRT_H_
+
+#include "riscv-reg.h"
+
+#ifdef __ASSEMBLER__
+#define CONS(NUM, TYPE)NUM
+#else
+#define CONS(NUM, TYPE)NUM##TYPE
+#endif /* __ASSEMBLER__ */
+
+#define PRIM_HART 0
+
+#define CLINT_ADDR CONS(0x02000000, UL)
+#define CLINT_MSIP CONS(0x0000, UL)
+#define CLINT_MTIMECMP CONS(0x4000, UL)
+#define CLINT_MTIME CONS(0xbff8, UL)
+
+#define NS16550_ADDR CONS(0x10000000, UL)
+
+#ifndef __ASSEMBLER__
+
+int xGetCoreID( void );
+void vSendString( const char * s );
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* RISCV_VIRT_H_ */
diff --git a/lexicon.txt b/lexicon.txt
index 3b39577c1b..07f758fe6f 100644
--- a/lexicon.txt
+++ b/lexicon.txt
@@ -117,6 +117,7 @@ binterfaceprotocol
binterfacesubclass
binterval
bio
+bios
bislisten
bitmasking
bitvalue