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 <>
pull/779/head
RichardBarry 3 years ago committed by GitHub
parent 0744c28749
commit 4629138a42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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

@ -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 */

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="0.208514950">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="0.208514950" moduleId="org.eclipse.cdt.core.settings" name="Default">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration buildProperties="" description="" id="0.208514950" name="Default" optionalBuildProperties="" parent="org.eclipse.cdt.build.core.prefbase.cfg">
<folderInfo id="0.208514950." name="/" resourcePath="">
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.1104818234" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
<targetPlatform id="org.eclipse.cdt.build.core.prefbase.toolchain.1104818234.1571743114" name=""/>
<builder id="org.eclipse.cdt.build.core.settings.default.builder.1258987068" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.1255019096" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.2025884899" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.876141242" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
</tool>
<tool id="org.eclipse.cdt.build.core.settings.holder.2088826057" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.707688561" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
</tool>
<tool id="org.eclipse.cdt.build.core.settings.holder.1095452603" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1783280172" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
</tool>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="RTOSDemo.null.342773888" name="RTOSDemo"/>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="0.208514950">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Default">
<resource resourceType="PROJECT" workspacePath="/RTOSDemo"/>
</configuration>
</storageModule>
</cproject>

@ -0,0 +1,181 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>RTOSDemo</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<linkedResources>
<link>
<name>FreeRTOS_kernel</name>
<type>2</type>
<locationURI>FREERTOS_ROOT/Source</locationURI>
</link>
<link>
<name>Source</name>
<type>2</type>
<locationURI>virtual:/virtual</locationURI>
</link>
<link>
<name>Source/Blinky_Demo</name>
<type>2</type>
<locationURI>virtual:/virtual</locationURI>
</link>
<link>
<name>Source/FreeRTOSConfig.h</name>
<type>1</type>
<locationURI>PARENT-2-PROJECT_LOC/FreeRTOSConfig.h</locationURI>
</link>
<link>
<name>Source/Full_Demo</name>
<type>2</type>
<locationURI>virtual:/virtual</locationURI>
</link>
<link>
<name>Source/Makefile</name>
<type>1</type>
<locationURI>PROJECT_LOC/Makefile</locationURI>
</link>
<link>
<name>Source/fake_rom.ld</name>
<type>1</type>
<locationURI>PROJECT_LOC/fake_rom.ld</locationURI>
</link>
<link>
<name>Source/main.c</name>
<type>1</type>
<locationURI>PARENT-2-PROJECT_LOC/main.c</locationURI>
</link>
<link>
<name>Source/ns16550.c</name>
<type>1</type>
<locationURI>PARENT-2-PROJECT_LOC/ns16550.c</locationURI>
</link>
<link>
<name>Source/ns16550.h</name>
<type>1</type>
<locationURI>PARENT-2-PROJECT_LOC/ns16550.h</locationURI>
</link>
<link>
<name>Source/printf-stdarg.c</name>
<type>1</type>
<locationURI>PROJECT_LOC/printf-stdarg.c</locationURI>
</link>
<link>
<name>Source/riscv-reg.h</name>
<type>1</type>
<locationURI>PARENT-2-PROJECT_LOC/riscv-reg.h</locationURI>
</link>
<link>
<name>Source/riscv-virt.c</name>
<type>1</type>
<locationURI>PARENT-2-PROJECT_LOC/riscv-virt.c</locationURI>
</link>
<link>
<name>Source/riscv-virt.h</name>
<type>1</type>
<locationURI>PARENT-2-PROJECT_LOC/riscv-virt.h</locationURI>
</link>
<link>
<name>Source/start.S</name>
<type>1</type>
<locationURI>PROJECT_LOC/start.S</locationURI>
</link>
<link>
<name>Source/startfiles</name>
<type>1</type>
<locationURI>PROJECT_LOC/startfiles</locationURI>
</link>
<link>
<name>Source/Blinky_Demo/main_blinky.c</name>
<type>1</type>
<locationURI>PARENT-2-PROJECT_LOC/main_blinky.c</locationURI>
</link>
<link>
<name>Source/Full_Demo/CommonDemoSource</name>
<type>2</type>
<locationURI>FREERTOS_ROOT/Demo/Common/Minimal</locationURI>
</link>
<link>
<name>Source/Full_Demo/RegTest.S</name>
<type>1</type>
<locationURI>PROJECT_LOC/RegTest.S</locationURI>
</link>
<link>
<name>Source/Full_Demo/main_full.c</name>
<type>1</type>
<locationURI>PARENT-2-PROJECT_LOC/main_full.c</locationURI>
</link>
</linkedResources>
<filteredResources>
<filter>
<id>1640399877287</id>
<name></name>
<type>6</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-*</arguments>
</matcher>
</filter>
<filter>
<id>1640399593493</id>
<name>FreeRTOS_kernel/portable</name>
<type>9</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-GCC</arguments>
</matcher>
</filter>
<filter>
<id>1640399593501</id>
<name>FreeRTOS_kernel/portable</name>
<type>9</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-MemMang</arguments>
</matcher>
</filter>
<filter>
<id>1640399614171</id>
<name>FreeRTOS_kernel/portable/GCC</name>
<type>9</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-RISC-V</arguments>
</matcher>
</filter>
<filter>
<id>1640399630077</id>
<name>FreeRTOS_kernel/portable/MemMang</name>
<type>5</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-heap_4.c</arguments>
</matcher>
</filter>
</filteredResources>
<variableList>
<variable>
<name>FREERTOS_ROOT</name>
<value>$%7BPARENT-4-PROJECT_LOC%7D</value>
</variable>
</variableList>
</projectDescription>

@ -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

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.cdt.debug.gdbjtag.launchConfigurationType">
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.connection" value="gdb:localhost:1234#"/>
<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.delay" value="0"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doHalt" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doReset" value="false"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageOffset" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.initCommands" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.jtagDeviceId" value="org.eclipse.cdt.debug.gdbjtag.core.jtagdevice.genericDevice"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadImage" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadSymbols" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.pcRegister" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.runCommands" value=""/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setPcRegister" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setResume" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setStopAt" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.stopAt" value="main"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsOffset" value=""/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForImage" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForSymbols" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForImage" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForSymbols" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useRemoteTarget" value="true"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="riscv64-unknown-elf-gdb"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.REMOTE_TIMEOUT_ENABLED" value="false"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.REMOTE_TIMEOUT_VALUE" value=""/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.UPDATE_THREADLIST_ON_SUSPEND" value="false"/>
<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="0"/>
<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_START_MODE" value="remote"/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="./output/RTOSDemo.elf"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="RTOSDemo"/>
<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="true"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value=""/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/RTOSDemo"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<stringAttribute key="org.eclipse.debug.core.source_locator_id" value="org.eclipse.cdt.debug.core.sourceLocator"/>
<stringAttribute key="org.eclipse.debug.core.source_locator_memento" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;sourceLookupDirector&gt;&#13;&#10; &lt;sourceContainers duplicates=&quot;false&quot;&gt;&#13;&#10; &lt;container memento=&quot;AbsolutePath&quot; typeId=&quot;org.eclipse.cdt.debug.core.containerType.absolutePath&quot;/&gt;&#13;&#10; &lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;default/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.debug.core.containerType.default&quot;/&gt;&#13;&#10; &lt;/sourceContainers&gt;&#13;&#10;&lt;/sourceLookupDirector&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&lt;memoryBlockExpressionList context=&quot;reserved-for-future-use&quot;/&gt;"/>
<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>
</launchConfiguration>

@ -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

@ -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
}

@ -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.

@ -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 <stdarg.h>
#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;
}

@ -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

@ -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 <stdio.h>
#include <string.h>
/* 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( ;; );
}
/*-----------------------------------------------------------*/

@ -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 <stdio.h>
/* 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" );
}
}
}
/*-----------------------------------------------------------*/

@ -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 <stdio.h>
#include <string.h>
/* 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();
}
/*-----------------------------------------------------------*/

@ -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 <stdint.h>
#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 );
}

@ -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 <stdint.h>
struct device {
uintptr_t addr;
};
void vOutNS16550( struct device *dev, unsigned char c );
#endif /* NS16550_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_ */

@ -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 <FreeRTOS.h>
#include <string.h>
#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)
;
}

@ -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_ */

@ -117,6 +117,7 @@ binterfaceprotocol
binterfacesubclass
binterval
bio
bios
bislisten
bitmasking
bitvalue

Loading…
Cancel
Save