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