构建基于 RISC-V 64 的 FreeRTOS¶
FreeRTOS 是一个轻量级的完全免费的实时操作系统内核,源码公开、可裁减,包括了任务管理、时间管理、信号量、消息队列、内存管理、记录功能等,可移植到各种单片机上运行,可基本满足较小系统的需要。
FreeRTOS 特性¶
开源、免费的嵌入式实时操作系统。
支持抢占式、合作式和时间片三种调度方式。
提供了一个用于低功耗的 Tickless 模式。
系统的组件在创建时可以选择动态或者静态的RAM,比如任务、消息队列、信号量、软件定时器等等。
系统简单、小巧、易用,通常情况下内核占用 4k-9k 字节的空间。
支持市面上的多达35种芯片架构,如Cortex-M 、Cortex-R 、Cortex-A、RISC-V等。
高可移植性,代码主要 C 语言编写。
强大的跟踪执行功能。
环境准备¶
目前官方提供的 Demo 中已经包含了基于 QEMU 的 RISC-V 32 架构的 FreeRTOS ,只需在其基础上进行 RISC-V 64 架构的适配即可,选择 Poky 作为构建工程,构建主机使用 Ubuntu-20.04 版本,此外还应满足以下需求:
50G 空闲的磁盘空间
Git 1.8.3.1 或更高版本
tar 1.28 或更高版本
Python 3.6.0 或更高版本
gcc 5.0 或更高版本
满足以上条件后,需在主机上安装必要的工具包:
sudo apt install gawk wget git diffstat unzip texinfo gcc build-essential chrpath socat cpio python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev pylint3 xterm python3-subunit mesa-common-dev zstd liblz4-tool
为了支持 RISC-V 64 架构,还需安装 RISC-V 编译工具链,具体步骤如下:
cd /opt/
curl -O -L "https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-20181030-x86_64-linux-ubuntu14.tar.gz"
tar xzf riscv64-unknown-elf-gcc-20181030-x86_64-linux-ubuntu14.tar.gz
sudo mv riscv64-unknown-elf-gcc-20181030-x86_64-linux-ubuntu14 riscv-new
export PATH="$PATH:/opt/riscv-new/bin"
移植 FreeRTOS¶
经验证测试,以官方 FreeRTOS 工程 release-candidate 分支为基础,进行 RISC-V 64 架构的 FreeRTOS 移植工作,首先获取 FreeRTOS 工程,并切换到 release-candidate 分支:
git clone https://github.com/FreeRTOS/FreeRTOS.git --recurse-submodules
cd FreeRTOS
sudo git checkout -b tflite remotes/origin/release-candidate
主要关注 FreeRTOS 下的文件,官方提供的Demo中已经包含了基于 QEMU 的 RISC-V 32 架构的 FreeRTOS ,其相关的目录结构如下图所示:
![]()
RISC-V 32 架构 FreeRTOS 目录结构¶
为了适配 RISC-V 64 架构,对 RISC-V-Qemu-virt_GCC 下的 Makefile 进行更改, git diff 输出如下:
diff --git a/git/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/Makefile b/git/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/Makefile
index 4d806bf49..695434a14 100644
--- a/git/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/Makefile
+++ b/git/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/Makefile
@@ -1,4 +1,4 @@
-CROSS = riscv64-unknown-elf-
+CROSS ?= /opt/riscv-new/bin/riscv64-unknown-elf-
CC = $(CROSS)gcc
OBJCOPY = $(CROSS)objcopy
ARCH = $(CROSS)ar
@@ -14,13 +14,13 @@ CPPFLAGS = \
-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 \
+CFLAGS = -march=rv64imafdc -mabi=lp64d -mcmodel=medany \
-Wall \
-fmessage-length=0 \
-ffunction-sections \
-fdata-sections \
-fno-builtin-printf
-ASFLAGS = -march=rv32ima -mabi=ilp32 -mcmodel=medany
+ASFLAGS = -march=rv64imafdc -mabi=lp64d -mcmodel=medany
LDFLAGS = -nostartfiles -Tfake_rom.lds \
-Xlinker --gc-sections \
-Xlinker --defsym=__stack_size=300
@@ -53,8 +53,14 @@ ASMS = start.S \
OBJS = $(SRCS:%.c=$(BUILD_DIR)/%.o) $(ASMS:%.S=$(BUILD_DIR)/%.o)
DEPS = $(SRCS:%.c=$(BUILD_DIR)/%.d) $(ASMS:%.S=$(BUILD_DIR)/%.d)
-$(BUILD_DIR)/RTOSDemo.axf: $(OBJS) fake_rom.lds Makefile
-$(CC) $(LDFLAGS) $(OBJS) -o $@
+TARGET = RTOSDemo.bin
+ELF_IMAGE = RTOSDemo.elf
+
+$(BUILD_DIR)/$(TARGET):$(BUILD_DIR)/$(ELF_IMAGE)
+$(OBJCOPY) $(BUILD_DIR)/$(ELF_IMAGE) -O binary $(BUILD_DIR)/$(TARGET)
+
+$(BUILD_DIR)/$(ELF_IMAGE): $(OBJS) fake_rom.lds Makefile
+$(CC) $(LDFLAGS) $(OBJS) -o $@
最终得到补丁文件 0001-modify-Makefile-to-adapt-riscv64.patch
。
定制 RISC-V 64 FreeRTOS Layer¶
获取 meta-freertos
为了能够在 Poky 工程下使用 QEMU 运行 FreeRTOS ,以 “OpenEmbedded layer index” 内现存的 meta-freertos 为基础进行 RISC-V64 架构的适配。首先在已搭建的 Poky 工程目录下获取 meta-freertos :
sudo git clone https://github.com/aehs29/meta-freertos.git
为了精简 meta-freertos ,删除本地测试 BB 文件和 CI 文件:
sudo rm CI/ -rf
sudo rm recipes-freertos/freertos-demo-local/ -rf
修改 classes
接下来需要修改 classes 文件夹下的类文件 freertos-image.bbclass
和 freertos-armv5.bbclass
,由于更改了 FreeRTOS 源且计划在 QEMU 下运行基于 RISC-V64 架构的 Demo RISC-V-Qemu-virt_GCC
,因此需要进行相应的修改适配,freertos-image.bbclass
修改后的 git diff 输出如下:
diff --git a/classes/freertos-image.bbclass b/classes/freertos-image.bbclass
old mode 100644
new mode 100755
index c3cf49f..a3a63c4
--- a/classes/freertos-image.bbclass
+++ b/classes/freertos-image.bbclass
@@ -13,26 +13,26 @@
# And we get the app code from a different repo (app recipe)
# FreeRTOS kernel version (FreeRTOS.h)
-FREERTOS_VERSION = "FreeRTOSv10.4.3"
-SRCBRANCH = "202012-LTS"
+FREERTOS_VERSION = "FreeRTOSv10.4.6"
+SRCBRANCH = "release-candidate"
LICENSE = "MIT"
# FreeRTOS License, careful here, the gitsm fetcher does not work properly with license checking
# double check this manually after an upgrade
-LIC_FILES_CHKSUM = "file://../freertos/LICENSE;md5=7ae2be7fb1637141840314b51970a9f7"
+LIC_FILES_CHKSUM = "file://${S}/git/LICENSE.md;md5=7ae2be7fb1637141840314b51970a9f7"
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI = " \
- gitsm://github.com/FreeRTOS/FreeRTOS-LTS.git;name=freertos;destsuffix=freertos;branch=${SRCBRANCH};protocol=https \
+ gitsm://github.com/FreeRTOS/FreeRTOS.git;branch=${SRCBRANCH};protocol=https \
"
SRCREV_FORMAT ?= "freertos_bsp"
-SRCREV_freertos ?= "1bb18c8dfbf8f0445e873b20cec7d6091771f9e9"
+SRCPV ?= "4a4abbfe207e83f615ea629a5ce7f2c9fc52eafb"
PV = "${FREERTOS_VERSION}+git${SRCPV}"
-FREERTOS_KERNEL_SRC = "${WORKDIR}/freertos/FreeRTOS/FreeRTOS-Kernel/"
+FREERTOS_SRC = "${S}/git"
IMAGE_BASENAME = "freertos-image"
BAREMETAL_BINNAME ?= "${IMAGE_BASENAME}"
@@ -43,20 +43,27 @@ IMAGE_LINK_NAME ?= "${IMAGE_BASENAME}-${MACHINE}"
CFLAGS:remove = "-O2"
# Extra CFLAGS required for FreeRTOS include files
-CFLAGS:append = " -I${FREERTOS_KERNEL_SRC} -I${FREERTOS_KERNEL_SRC}/include/"
+CFLAGS:append = " -I${FREERTOS_SRC}/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC -I${FREERTOS_SRC}/FreeRTOS/Source/include -I${FREERTOS_SRC}/FreeRTOS/Demo/Common/include -I${FREERTOS_SRC}/FreeRTOS/Source/portable/GCC/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions -I${FREERTOS_SRC}/FreeRTOS/Source/portable/GCC/RISC-V"
# We need to define the FreeRTOS source code location, the port we'll be using
# should be defined on the specific bsp class
-EXTRA_OEMAKE = " FREERTOS_SRC=${FREERTOS_KERNEL_SRC} 'CFLAGS=${CFLAGS}'"
+EXTRA_OEMAKE = "FREERTOS_SRC=${FREERTOS_SRC} 'CFLAGS=${CFLAGS}'"
+
+cmake_do_configure(){
+ -DCMAKE_NO_SYSTEM_FROM_IMPORTED=1 \
+ ${EXTRA_OECMAKE} \
+ -Wno-dev
+}
do_compile(){
- oe_runmake ${EXTRA_OEMAKE}
+ cd ${FREERTOS_SRC}
+ make -C ./FreeRTOS/Demo/RISC-V-Qemu-virt_GCC
}
do_install(){
- install -d ${D}/${base_libdir}/firmware
- install -m 755 ${B}/image.bin ${D}/${base_libdir}/firmware/${BAREMETAL_BINNAME}.bin
- install -m 755 ${B}/image.elf ${D}/${base_libdir}/firmware/${BAREMETAL_BINNAME}.elf
+ install -d ${D}${base_libdir}/firmware
+ install -m 755 ${S}/git/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/build/RTOSDemo.bin ${D}${base_libdir}/firmware/${BAREMETAL_BINNAME}.bin
+ install -m 755 ${S}/git/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/build/RTOSDemo.elf ${D}${base_libdir}/firmware/${BAREMETAL_BINNAME}.elf
}
@@ -66,10 +73,12 @@ FILES:${PN}:append = " \
"
# QEMU generic FreeRTOS parameters
-QB_DEFAULT_KERNEL = "${IMAGE_LINK_NAME}.bin"
-QB_MEM = "-m 128"
+QB_DEFAULT_KERNEL = "${IMAGE_LINK_NAME}.elf"
+QB_MEM = "-m 256"
QB_OPT_APPEND = "-nographic"
-QB_DEFAULT_FSTYPE = "bin"
+QB_DEFAULT_FSTYPE = "elf"
+QB_SMP = "-smp 8"
+QB_SERIAL_OPT = "-serial chardev:con"
inherit baremetal-image
将 freertos-armv5.bbclass
文件名修改为 freertos-riscv.bbclass
:
sudo mv freertos-armv5.bbclass freertos-riscv.bbclass
修改后的 freertos-riscv.bbclass
内容如下:
inherit freertos-image BSP_REPO ?= "../bsp" SRC_URI = " \ gitsm://github.com/FreeRTOS/FreeRTOS.git;branch=release-candidate;protocol=https \ " # BSP repo License LIC_FILES_CHKSUM = "file://${S}/git/LICENSE.md;md5=7ae2be7fb1637141840314b51970a9f7" SRCREV = "${AUTOREV}" S="${WORKDIR}" # QEMU parameters specific for this PORT QB_SYSTEM_NAME = "qemu-system-riscv64" QB_MACHINE = "-machine virt" QB_DTB = ""
修改 recipes-freertos
为了引入上面移植好的 FreeRTOS ,使用补丁文件 0001-modify-Makefile-to-adapt-riscv64.patch
替换 recipes-freertos/freertos-demo/files/
路径下的补丁文件 use-newlib-as-libc.patch
,修改后的 freertos-demo_git.bb
如下所示:
inherit freertos-riscv # App can be replaced by using a different repo FILESEXTRAPATHS:prepend := "${THISDIR}/file:" SRC_URI = " gitsm://github.com/FreeRTOS/FreeRTOS.git;branch=release-candidate;protocol=https \ file://0001-modify-Makefile-to-adapt-riscv64.patch \ " SRCREV = "${AUTOREV}" S="${WORKDIR}" SRCREV_app = "4a4abbfe207e83f615ea629a5ce7f2c9fc52eafb" EXTRA_OEMAKE += "APP_SRC=${S}/git/FreeRTOS/ 'STAGING_LIBDIR=${STAGING_LIBDIR}'"
经过上述的更改,已完成了基于 RISC-V 64 架构的 FreeRTOS Layer 定制,为了与原 meta-freertos
区分开,将定制好的 meta-freertos
更名为 meta-freertos-riscv
。
构建 Poky¶
在满足构建环境后,需要获取 Poky 工程,使用下面命令获取 Poky:
git clone git://git.yoctoproject.org/poky
切换至 kirkstone
分支,选择与最新稳定版本兼容的版本:
cd poky
git checkout -t origin/kirkstone -b my-kirkstone
上面的 git checkout 命令创建了一个名为 my-kirkstone
的分支。该分支中可供您使用的文件与 kirkstone
发布分支中的文件完全匹配。
测试 meta-freertos-riscv¶
现在,我们将在 Poky 工程下测试运行 meta-freertos-riscv
,首先,需要初始化构建环境,进入 poky
目录,运行 oe-init-build-env
环境设置脚本,自动创建并进入 build
目录:
cd poky source oe-init-build-env
增加图层 meta-freertos-riscv
到配置文件,并启动构建:
bitbake-layers add-layer ../meta-freertos-riscv echo "MACHINE = \"qemuriscv64\"" >> ./conf/local.conf echo "DISTRO = \"freertos\"" >> ./conf/local.conf bitbake freertos-demo
最后使用 QEMU 模拟器来运行生成的镜像:
runqemu nographic
启动后的结果如下图所示,在 FreeRTOS 系统下运行了发送和接收任务:
![]()
RISC-V 64 架构的 FreeRTOS Layer 运行结果¶
至此,完成了基于RISC-V 64 的 FreeRTOS Layer 的定制,为后续集成 TensorFlow Lite 功能提供了基础。