Портирование приложений FreeRTOS на процессоры RISC-V
Проверка портированной версии FreeRTOS на RISC-V
Пример портированной структуры FreeRTOS
Ниже приведена структура файлов FreeRTOS, портированных на RISC-V (извлеченная из примера Makefile).
CPPFLAGS = \
-D__riscv_float_abi_soft \
-DportasmHANDLE_INTERRUPT=handle_trap \
-I . -I ../Common/include \
-I $(RTOS_SOURCE_DIR)/include \
-I $(RTOS_SOURCE_DIR)/portable/GCC/RISC-V \
-I $(RTOS_SOURCE_DIR)/portable/GCC/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions
CFLAGS = -march=rv32ima -mabi=ilp32 -mcmodel=medany \
-Wall \
-fmessage-length=0 \
-ffunction-sections \
-fdata-sections \
-fno-builtin-printf
ASFLAGS = -march=rv32ima -mabi=ilp32 -mcmodel=medany
LDFLAGS = -nostartfiles -Tfake_rom.lds \
-Xlinker --gc-sections \
-Xlinker --defsym=__stack_size=300
ifeq ($(DEBUG), 1)
CFLAGS += -Og -ggdb3
else
CFLAGS += -O2
endif
SRCS = main.c main_blinky.c riscv-virt.c ns16550.c \
$(DEMO_SOURCE_DIR)/EventGroupsDemo.c \
$(DEMO_SOURCE_DIR)/TaskNotify.c \
$(DEMO_SOURCE_DIR)/TimerDemo.c \
$(DEMO_SOURCE_DIR)/blocktim.c \
$(DEMO_SOURCE_DIR)/dynamic.c \
$(DEMO_SOURCE_DIR)/recmutex.c \
$(RTOS_SOURCE_DIR)/event_groups.c \
$(RTOS_SOURCE_DIR)/list.c \
$(RTOS_SOURCE_DIR)/queue.c \
$(RTOS_SOURCE_DIR)/stream_buffer.c \
$(RTOS_SOURCE_DIR)/tasks.c \
$(RTOS_SOURCE_DIR)/timers.c \
$(RTOS_SOURCE_DIR)/portable/MemMang/heap_4.c \
$(RTOS_SOURCE_DIR)/portable/GCC/RISC-V/port.c
ASMS = start.S \
$(RTOS_SOURCE_DIR)/portable/GCC/RISC-V/portASM.S
Использование FreeRTOS на RISC-V
После завершения переноса на процессор пользователь может свободно создавать приложения, использующие FreeRTOS для управления потоком управления в программе. Ниже приведен простой пример приложения, которое поставляется с установкой FreeRTOS для проверки правильности переноса.
Это тестовое приложение называется программой blinky; оно имитирует мигание светодиода в целевой системе. Она включает две задачи FreeRTOS и планировщик, работающий между ними. Есть также очередь, которая используется для передачи управления между задачами. Поскольку у нас нет платы, в коде используются операторы отображения, чтобы продемонстрировать результат переключения потока выполнения между двумя задачами.
Следующий фрагмент кода показывает пример приложения и вывод, когда программа выполняется на процессоре:
int main_blinky( void )
{
vSendString( "Hello FreeRTOS!" );
/* Create the queue. */
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
if( xQueue != NULL )
{
/* Create and start the two tasks */
xTaskCreate( prvQueueReceiveTask, "Rx",
configMINIMAL_STACK_SIZE * 2U, NULL,
mainQUEUE_RECEIVE_TASK_PRIORITY, NULL );
xTaskCreate( prvQueueSendTask, "Tx",
configMINIMAL_STACK_SIZE * 2U, NULL,
mainQUEUE_SEND_TASK_PRIORITY, NULL );
}
/* Start the scheduler. */
vTaskStartScheduler();
return 0;
}
Вывод программы:
Пример сборки и запуска
Далее мы рассмотрим, как собрать и запустить результат портирования на RISC-V в QEMU.
Первым шагом будет выбор примера RISCV64 для RISC-V QEMU. Для этого возьмём пример из директории /FreeRTOS/Demo/RISC-V-Qemu-virt_GCC.
Для запуска понадобятся:
- тулчейн GNU RISC-V (можно скачать тулчейн RISC_V от SiFive по ссылке);
- qemu-riscv32-system;
- ОС Linux.
Настройка тулчейна
export PATH=<путь до тулчейна>/bin:$PATH
Сборка примера
make
Примечание переводчика
При сборке может возникнуть ошибка unrecognized opcode. Это происходит из-за того, что в Makefile указаны флаги компилятора и компоновщика -march=rv32imac, задающие архитектуру набора команд rv32imac со стандартными расширениями. Однако используемые в демо инструкции csrc и csrw являются частью расширения Zicsr, вынесенного из базовой ISA версии выше 2.2. И для gcc версии 11.1.0 и выше необходимо отдельно указывать расширение Zicsr. То есть необходимо в Makefile заменить все вхождения -march=rv32imac на -march=rv32ima_zicsr.
Также возможна ошибка компиляции из-за неопределенной константы configCLINT_BASE_ADDRESS. В таком случае необходимо определить её в файле FreeRTOSConfig.h, добавив после директив #include строку #define configCLINT_BASE_ADDRESS CLINT_ADDR.
Запуск примера
qemu-system-riscv32 -nographic -machine virt -net none \ -chardev stdio,id=con,mux=on -serial chardev:con \ -mon chardev=con,mode=readline -bios none \ -smp 4 -kernel ./build/RTOSDemo.axf
Более подробное описание сборки и запуска примера можно найти в файле /FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/Readme.md.
Контрольные вопросы
- Какие шаги нужно выполнить для портирования FreeRTOS на процессоры RISC-V?
- Какой заголовочный файл необходим для порта RISC-V, требующего расширения архитектуры?
- В каком случае в конфигурационном файле значения параметров configMTIME_BASE_ADDRESS и configMTIMECMP_BASE_ADDRESS должны быть установлены в 0?
- Как указать ядру FreeRTOS, какой обработчик внешних прерываний ему нужно вызвать?
