В этой лекции описывается, как FreeRTOS может быть портирована на процессор RISC-V. Это пошаговое справочное руководство.
Это руководство начинается с объяснения того, как получить необходимые файлы для портирования FreeRTOS и какие файлы нужно отредактировать для соответствия требованиям процессора RISC-V. Затем рассматривается, как эти файлы интегрируются в проект. В завершение главы демонстрируется, как скомпилировать и запустить портированное приложение на процессоре RISC-V в режиме эмуляции.
К концу этой лекции вы должны уметь:
FreeRTOS уже портирована на различные платформы RISC-V. Ниже приведены функции портированной на RISC-V версии, которые были реализованы.
Необходимые файлы RTOS - это файлы, перечисленные в предыдущей лекции. Либо выберите необходимые исходные файлы, либо выберите проект примера RISC-V и используйте его в качестве отправной точки.
Для всех портов RISC-V, требующих расширения архитектуры (что характерно для большинства чипов RISC-V), требуется один дополнительный файл. Этот дополнительный заголовочный файл называется freertos_risc_v_chip_specific_extensions.h. Существует одна реализация этого заголовочного файла для каждого поддерживаемого расширения архитектуры, причем все реализации расположены в подкаталогах каталога /FreeRTOS/Source/Portable/[compiler]/RISC-V/chip_specific_extensions, где [compiler] - ?используемый компилятор.
Чтобы включить файл для вашего процессора, включите путь к нему в путь включения ассемблера. Например:
/FreeRTOS/Source/Portable/[compiler]/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions в путь include ассемблера./FreeRTOS/Source/Portable/[compiler]/RISC-V/chip_specific_extensions/Pulpino_Vega_RV32M1RM в путь include ассемблера.Если ни одно из этих расширений не подходит для вашей реализации и у вас есть свои собственные расширения, то выполните действия, перечисленные в следующей статье: "Перенос на новые 32-битовые или 64-битовые реализации RISC-V". Это позволит вам создать файл freertos_risc_v_chip_specific_extensions.h, который будет соответствовать вашей конкретной архитектуре процессора. В приведенной выше ссылке описывается список параметров, которые необходимо определить для процессорных расширений, чтобы FreeRTOS могла обрабатывать эти расширения соответствующим образом.
Обратите внимание, что информация в этом разделе взята с сайта FreeRTOS.
Параметры configMTIME_BASE_ADDRESS и configMTIMECMP_BASE_ADDRESS должны быть определены в FreeRTOSConfig.h. Если целевой RISC-V чип включает машинный таймер (MTIME), то установите configMTIME_BASE_ADDRESS в базовый адрес MTIME, а configMTIMECMP_BASE_ADDRESS в адрес регистра сравнения MTIME (MTIMECMP). В противном случае установите оба значения в 0.
Например, если базовый адрес MTIME равен 0x2000BFF8, а адрес MTIMECMP равен 0x20004000, то добавьте следующие строки в FreeRTOSConfig.h:
#define configMTIME_BASE_ADDRESS ( 0x2000BFF8UL ) #define configMTIMECMP_BASE_ADDRESS ( 0x20004000UL )
Если MTIME нет, то добавьте следующие строки в FreeRTOSConfig.h:
#define configMTIME_BASE_ADDRESS ( 0 ) #define configMTIMECMP_BASE_ADDRESS ( 0 )
Порт FreeRTOS RISC-V использует выделенный стек прерываний перед вызовом любых функций C из процедуры обслуживания прерываний (interrupt service routine, ISR).
Память для использования в качестве стека прерываний может быть определена в скрипте компоновщика или объявлена на уровне портов FreeRTOS как статически выделенный массив.
Первый метод предпочтительнее для микроконтроллеров (MCU) с ограниченным объемом памяти, поскольку он позволяет использовать стек планировщика, используемый main() до запуска планировщика, в качестве стека прерываний, когда он больше не используется для первоначальной цели после запуска планировщика.
Чтобы использовать статически выделенный массив в качестве стека прерываний, определите configISR_STACK_SIZE_WORDS в FreeRTOSConfig.h как размер выделяемого стека прерываний. Обратите внимание, что размер определяется в словах, а не в байтах. Например, чтобы использовать статически выделяемый стек прерываний размером 500 слов (2000 байт на RV32, где каждое слово равно 4 байтам), добавьте следующее в FreeRTOSConfig.h:
#define configISR_STACK_SIZE_WORDS ( 500 )
Чтобы определить стек прерываний в сценарии компоновщика (обратите внимание, что на момент написания этой статьи, июнь 2022 года, этот метод поддерживается только в порте GCC), объявите переменную компоновщика под названием __freertos_irq_stack_top, которая будет содержать самый высокий адрес стека прерываний, а также убедитесь, что configISR_STACK_SIZE_WORDS не определена.
Использование этого метода требует редактирования скрипта компоновщика. Если вы не знакомы со скриптами компоновщика, то важно знать (по крайней мере, при использовании GCC), что ". " - это так называемый счетчик расположения, который содержит значение адреса памяти в данный момент в скрипте компоновщика. Пример управления местоположением показан ниже.
/* Define the start address and size of the two RAM regions not used by the linker. */
#define ( ( uint8_t * )
RAM2_START_ADDRESS 0x00020000 )
#define RAM2_SIZE ( 32 * 1024 )
#define ( ( uint8_t * )
RAM3_START_ADDRESS 0x00030000 )
#define RAM3_SIZE ( 32 * 1024 )
/* Declare an array that will be part of the heap used by heap_5. The array will be placed in RAM1 by the linker. */
#define RAM1_HEAP_SIZE ( 30 * 1024 )
static uint8_t ucHeap[ RAM1_HEAP_SIZE ];
/* Create an array of HeapRegion_t definitions. The HeapRegion_t structures must appear in start address order, with the structure that contains the lowest start address appearing first. */
const HeapRegion_t xHeapRegions[] =
{
{ ucHeap, RAM1_HEAP_SIZE },
{ RAM2_START_ADDRESS, RAM2_SIZE },
{ RAM3_START_ADDRESS, RAM3_SIZE },
{ NULL, 0 } /* Marks the end of the array. */
};
В этом разделе подробно описаны опции компилятора и ассемблера, которые должны быть установлены в командной строке перед выполнением. Это необходимо, поскольку различные реализации RISC-V предоставляют различные обработчики прерываний для своих внешних прерываний. Установка опций, соответствующих данной реализации, указывает ядру FreeRTOS, какой обработчик внешних прерываний ему нужно вызвать.
Чтобы задать обработчик внешнего прерывания, необходимо определить следующие параметры:
void ext_int_handler (uint32_t cause);portasmHANDLE_INTERRUPT, равный имени обработчика прерываний. Если вы используете GCC, этого можно добиться, добавив в командную строку ассемблера следующее, предполагая, что обработчик прерываний называется ext_int_handler: -DportasmHANDLE_INTERRUPT=ext_int_handler.Также не забудьте добавить заголовочный файл, специфичный для реализации процессора RISC-V, в путь включения ассемблера.
Последний необходимый шаг - установка обработчика прерываний FreeRTOS, freertos_risc_v_trap_handler(). Это центральная точка входа для всех прерываний и исключений. Обработчик ловушек FreeRTOS вызывает обработчик внешних прерываний, когда источником ловушки является внешнее прерывание.
Чтобы установить обработчик ловушек:
portasmHAS_SIFIVE_CLINT должен быть установлен в 1 в freertos_risc_v_chip_specific_extensions.h, что приводит к автоматической установке freertos_risc_v_trap_handler(). В этом случае никаких дополнительных действий не требуется.freertos_risc_v_trap_handler() вручную. Это можно сделать, отредактировав код запуска, предоставленный вашим поставщиком микросхем.Если чип RISC-V использует контроллер векторных прерываний, то установите freertos_risc_v_trap_handler() в качестве обработчика для каждого вектора.
Ниже приведена структура файлов 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 для управления потоком управления в программе. Ниже приведен простой пример приложения, которое поставляется с установкой 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.
Для запуска понадобятся:
Настройка тулчейна
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.
configMTIME_BASE_ADDRESS и configMTIMECMP_BASE_ADDRESS должны быть установлены в 0?В этой лекции описывается, как FreeRTOS может быть портирована на процессор RISC-V. Это пошаговое справочное руководство.
Это руководство начинается с объяснения того, как получить необходимые файлы для портирования FreeRTOS и какие файлы нужно отредактировать для соответствия требованиям процессора RISC-V. Затем рассматривается, как эти файлы интегрируются в проект. В завершение главы демонстрируется, как скомпилировать и запустить портированное приложение на процессоре RISC-V в режиме эмуляции.
К концу этой лекции вы должны уметь:
FreeRTOS уже портирована на различные платформы RISC-V. Ниже приведены функции портированной на RISC-V версии, которые были реализованы.
Необходимые файлы RTOS - это файлы, перечисленные в предыдущей лекции. Либо выберите необходимые исходные файлы, либо выберите проект примера RISC-V и используйте его в качестве отправной точки.
Для всех портов RISC-V, требующих расширения архитектуры (что характерно для большинства чипов RISC-V), требуется один дополнительный файл. Этот дополнительный заголовочный файл называется freertos_risc_v_chip_specific_extensions.h. Существует одна реализация этого заголовочного файла для каждого поддерживаемого расширения архитектуры, причем все реализации расположены в подкаталогах каталога /FreeRTOS/Source/Portable/[compiler]/RISC-V/chip_specific_extensions, где [compiler] - ?используемый компилятор.
Чтобы включить файл для вашего процессора, включите путь к нему в путь включения ассемблера. Например:
/FreeRTOS/Source/Portable/[compiler]/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions в путь include ассемблера./FreeRTOS/Source/Portable/[compiler]/RISC-V/chip_specific_extensions/Pulpino_Vega_RV32M1RM в путь include ассемблера.Если ни одно из этих расширений не подходит для вашей реализации и у вас есть свои собственные расширения, то выполните действия, перечисленные в следующей статье: "Перенос на новые 32-битовые или 64-битовые реализации RISC-V". Это позволит вам создать файл freertos_risc_v_chip_specific_extensions.h, который будет соответствовать вашей конкретной архитектуре процессора. В приведенной выше ссылке описывается список параметров, которые необходимо определить для процессорных расширений, чтобы FreeRTOS могла обрабатывать эти расширения соответствующим образом.
Обратите внимание, что информация в этом разделе взята с сайта FreeRTOS.
Параметры configMTIME_BASE_ADDRESS и configMTIMECMP_BASE_ADDRESS должны быть определены в FreeRTOSConfig.h. Если целевой RISC-V чип включает машинный таймер (MTIME), то установите configMTIME_BASE_ADDRESS в базовый адрес MTIME, а configMTIMECMP_BASE_ADDRESS в адрес регистра сравнения MTIME (MTIMECMP). В противном случае установите оба значения в 0.
Например, если базовый адрес MTIME равен 0x2000BFF8, а адрес MTIMECMP равен 0x20004000, то добавьте следующие строки в FreeRTOSConfig.h:
#define configMTIME_BASE_ADDRESS ( 0x2000BFF8UL ) #define configMTIMECMP_BASE_ADDRESS ( 0x20004000UL )
Если MTIME нет, то добавьте следующие строки в FreeRTOSConfig.h:
#define configMTIME_BASE_ADDRESS ( 0 ) #define configMTIMECMP_BASE_ADDRESS ( 0 )
Порт FreeRTOS RISC-V использует выделенный стек прерываний перед вызовом любых функций C из процедуры обслуживания прерываний (interrupt service routine, ISR).
Память для использования в качестве стека прерываний может быть определена в скрипте компоновщика или объявлена на уровне портов FreeRTOS как статически выделенный массив.
Первый метод предпочтительнее для микроконтроллеров (MCU) с ограниченным объемом памяти, поскольку он позволяет использовать стек планировщика, используемый main() до запуска планировщика, в качестве стека прерываний, когда он больше не используется для первоначальной цели после запуска планировщика.
Чтобы использовать статически выделенный массив в качестве стека прерываний, определите configISR_STACK_SIZE_WORDS в FreeRTOSConfig.h как размер выделяемого стека прерываний. Обратите внимание, что размер определяется в словах, а не в байтах. Например, чтобы использовать статически выделяемый стек прерываний размером 500 слов (2000 байт на RV32, где каждое слово равно 4 байтам), добавьте следующее в FreeRTOSConfig.h:
#define configISR_STACK_SIZE_WORDS ( 500 )
Чтобы определить стек прерываний в сценарии компоновщика (обратите внимание, что на момент написания этой статьи, июнь 2022 года, этот метод поддерживается только в порте GCC), объявите переменную компоновщика под названием __freertos_irq_stack_top, которая будет содержать самый высокий адрес стека прерываний, а также убедитесь, что configISR_STACK_SIZE_WORDS не определена.
Использование этого метода требует редактирования скрипта компоновщика. Если вы не знакомы со скриптами компоновщика, то важно знать (по крайней мере, при использовании GCC), что ". " - это так называемый счетчик расположения, который содержит значение адреса памяти в данный момент в скрипте компоновщика. Пример управления местоположением показан ниже.
/* Define the start address and size of the two RAM regions not used by the linker. */
#define ( ( uint8_t * )
RAM2_START_ADDRESS 0x00020000 )
#define RAM2_SIZE ( 32 * 1024 )
#define ( ( uint8_t * )
RAM3_START_ADDRESS 0x00030000 )
#define RAM3_SIZE ( 32 * 1024 )
/* Declare an array that will be part of the heap used by heap_5. The array will be placed in RAM1 by the linker. */
#define RAM1_HEAP_SIZE ( 30 * 1024 )
static uint8_t ucHeap[ RAM1_HEAP_SIZE ];
/* Create an array of HeapRegion_t definitions. The HeapRegion_t structures must appear in start address order, with the structure that contains the lowest start address appearing first. */
const HeapRegion_t xHeapRegions[] =
{
{ ucHeap, RAM1_HEAP_SIZE },
{ RAM2_START_ADDRESS, RAM2_SIZE },
{ RAM3_START_ADDRESS, RAM3_SIZE },
{ NULL, 0 } /* Marks the end of the array. */
};
В этом разделе подробно описаны опции компилятора и ассемблера, которые должны быть установлены в командной строке перед выполнением. Это необходимо, поскольку различные реализации RISC-V предоставляют различные обработчики прерываний для своих внешних прерываний. Установка опций, соответствующих данной реализации, указывает ядру FreeRTOS, какой обработчик внешних прерываний ему нужно вызвать.
Чтобы задать обработчик внешнего прерывания, необходимо определить следующие параметры:
void ext_int_handler (uint32_t cause);portasmHANDLE_INTERRUPT, равный имени обработчика прерываний. Если вы используете GCC, этого можно добиться, добавив в командную строку ассемблера следующее, предполагая, что обработчик прерываний называется ext_int_handler: -DportasmHANDLE_INTERRUPT=ext_int_handler.Также не забудьте добавить заголовочный файл, специфичный для реализации процессора RISC-V, в путь включения ассемблера.
Последний необходимый шаг - установка обработчика прерываний FreeRTOS, freertos_risc_v_trap_handler(). Это центральная точка входа для всех прерываний и исключений. Обработчик ловушек FreeRTOS вызывает обработчик внешних прерываний, когда источником ловушки является внешнее прерывание.
Чтобы установить обработчик ловушек:
portasmHAS_SIFIVE_CLINT должен быть установлен в 1 в freertos_risc_v_chip_specific_extensions.h, что приводит к автоматической установке freertos_risc_v_trap_handler(). В этом случае никаких дополнительных действий не требуется.freertos_risc_v_trap_handler() вручную. Это можно сделать, отредактировав код запуска, предоставленный вашим поставщиком микросхем.Если чип RISC-V использует контроллер векторных прерываний, то установите freertos_risc_v_trap_handler() в качестве обработчика для каждого вектора.
Ниже приведена структура файлов 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 для управления потоком управления в программе. Ниже приведен простой пример приложения, которое поставляется с установкой 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.
Для запуска понадобятся:
Настройка тулчейна
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.
configMTIME_BASE_ADDRESS и configMTIMECMP_BASE_ADDRESS должны быть установлены в 0?Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.