Портирование приложений 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, какой обработчик внешних прерываний ему нужно вызвать?