【GD32F4】移植 rt-thread(标准库)
目录
RT-Thread 简介
RT-Thread 是一款由中国开发者主导的开源实时操作系统(RTOS),具有高可定制性、微内核架构和丰富的组件支持。它适用于嵌入式系统,广泛应用于物联网设备、智能硬件、工业控制、汽车电子等领域。
移植前准备
我们先准备一个干净的工程,做到能跑流水灯即可,本文示例展示移植rt-thread 是基于GD32F4系列芯片移植。

标准库移植
文件裁剪
下面这个是github上地址,上面拉最新版本的rt-thread
Releases · RT-Thread/rt-thread
https://github.com/RT-Thread/rt-thread/releases
解压完之后发现有一点多个G,里面大部分文件我们是不要的,需要进行裁剪

下面介绍一下这些文件都是什么
| 目录/文件 | 类型 | 作用 | 移植时是否需 |
|---|---|---|---|
src/ | 目录 | 内核源码 | 需要 |
include/ | 目录 | 内核头文件 | 需要 |
libcpu/ | 目录 | CPU 移植层 | 需要 |
components/ | 目录 | 组件层:设备框架(drivers/)、FinSH、libc 适配、网络、文件系统等 | 按需 |
bsp/ | 目录 | 板级支持包,按芯片厂商分目录 | 参考/按需 |
Kconfig | 文件 | menuconfig 的总配置入口,定义有哪些配置项可选 | 可选(用 menuconfig 时需要) |
tools/ | 目录 | 构建、配置、脚本工具 | 可选 |
examples/ | 目录 | 官方示例代码,学习用,不参与编译 | 不需要 |
documentation/ | 目录 | 官方文档源码 | 不需要 |
.devcontainer/ | 目录 | VS Code 远程开发容器配置 | 不需要 |
.gitee/ | 目录 | Gitee 平台的 issue 模板、CI 配置 | 不需要 |
.github/ | 目录 | GitHub 平台的 issue 模板、CI 配置 | 不需要 |
.hooks/ | 目录 | Git 钩子脚本 | 不需要 |
.vscode/ | 目录 | VS Code 工程配置(调试、任务等) | 不需要 |
.clang-format | 文件 | 代码格式化规则 | 不需要 |
.gitattributes | 文件 | Git 文件属性规则 | 不需要 |
.gitignore | 文件 | Git 忽略规则 | 不需要 |
AGENTS.md | 文件 | 给 AI 编码助手看的说明文件 | 不需要 |
ChangeLog.md | 文件 | 版本变更日志 | 不需要 |
LICENSE | 文件 | 开源许可证(Apache-2.0) | 不需要 |
MAINTAINERS | 文件 | 各模块维护者名单 | 不需要 |
README.md | 文件 | 项目说明(英文) | 不需要 |
README_de.md | 文件 | 项目说明(德文) | 不需要 |
README_es.md | 文件 | 项目说明(西班牙文) | 不需要 |
其实大部分都是我们不需要的,我们进行部分裁剪

最后留这五个文件就行了,但是这个时候点进去看是有一点多个g,我们还需要对这个进行裁剪
BSP
首先点开这个bsp层,里面都是各大厂商的进行适配的一些驱动吧,下面随便列举前几个介绍一下,他给的这个驱动层,也是非常方便,基本上都帮你封装好了后续自己使用的话添加他的驱动然后自己填个引脚就能用,当然如果自己写驱动也是可以的,目前我们只是移植他的系统,不用他的驱动也行。
acm32 | 华大半导体 ACM32 | 国产 MCU |
airm2m | 合宙 AirM2M | 常用于 Cat.1 模组(如 Air724) |
allwinner | 全志科技 | 国产 SoC 厂商,常用于 Linux 级芯片 |
allwinner_tina | 全志 Tina Linux | 全志的 Linux 发行版 |
amebaz | Realtek Ameba Z | Realtek 的 IoT 芯片 |
apm32 | 极海半导体 APM32 | 国产 MCU,兼容 STM32 |
apollo2 | Ambiq Apollo2 | 超低功耗 MCU |
asm9260t | ASM9260T | 国产 ARM9 芯片 |
at32 | 雅特力科技 AT32 | 国产 MCU,兼容 STM32 |
本文是基于gd32f4移植的,所以我们找到gd32,然后把其他的都删除就好了。
删除完,我们的文件瞬间就小了

components

下面也是简单介绍一下这些文件都是什么
| 目录名 | 全称 | 作用 |
|---|---|---|
dfs | Device File System | 虚拟文件系统。对上提供 POSIX 风格的文件接口(open/read/write),对下支持挂载不同文件系统(FATFS、LittleFS、YAFFS 等)。 |
drivers | Device Drivers | 通用设备驱动框架。包含 device.c、pin.c、i2c.c、spi.c、serial.c、adc.c、pwm.c 等,对上提供统一的 rt_device 接口。你之前用的 drivers/ 分组就来自这里。 |
fal | Flash Abstraction Layer | Flash 抽象层。用来统一管理片内 Flash、片外 SPI Flash,配合分区表使用,是 OTA、文件系统的底层基础。 |
finsh | FinSH Shell | 命令行控制台。就是串口终端里那个 msh /> 命令行,可以输入命令查看系统状态、调用函数。 |
legacy | Legacy | 旧版本兼容层。存放已废弃但为了兼容老代码保留的 API。 |
libc | C Library | libc 适配层。里面包含 compilers/(armlibc、newlib、musl 等)和 common/ |
lwp | Light Weight Process | 轻量级进程。RT-Thread Smart 版本用的用户态进程支持,普通 MCU 移植用不到。 |
mm | Memory Management | 内存管理。包含 MMU/MPU 相关支持,用于带内存管理单元的芯片。 |
mprotect | Memory Protect | 内存保护。配合 MPU 使用的内存访问保护机制。 |
net | Network | 网络协议栈。包含 lwIP、AT Socket、SAL(套接字抽象层)、netdev(网卡抽象层)等。 |
rust | Rust | Rust 语言支持。让 RT-Thread 可以用 Rust 写应用/组件。 |
utilities | Utilities | 实用工具。包含 ulog(日志)、ulog_easyflash、utest(单元测试)、rt-link 等。 |
Kconfig | 配置文件 | menuconfig 的配置描述,定义 components 里各组件有哪些配置项。 |
SConscript | 构建脚本 | scons 构建系统用,不需要。 |
很明显我们只需要留

libcpu

老规矩
aarch64 | ARM 64 位 | Cortex-A53/A55 等,跑 Linux 级 SoC |
arc | Synopsys ARC | ARC 系列嵌入式内核 |
arm | ARM 32 位 | Cortex-M / Cortex-A / ARM7/9 等 |
avr32 | Atmel AVR32 | 已停产的 AVR32 架构 |
blackfin | Analog Devices Blackfin | ADI 的 DSP 架构 |
c-sky | 平头哥 C-SKY | 国产嵌入式内核 |
ia32 | Intel x86 32 位 | PC 平台仿真用 |
m16c | Renesas M16C | 瑞萨 16 位 MCU |
mips | MIPS | MIPS 架构处理器 |
nios | Altera Nios II | FPGA 软核 |
ppc | PowerPC | 经典嵌入式/工控架构 |
risc-v | RISC-V | 开源指令集,近年热门 |
rx | Renesas RX | 瑞萨 RX 系列 |
sim | 仿真器 | 在 PC 上模拟运行 RT-Thread,调试用 |
sparc-v8 | SPARC V8 | 航天/工控领域 |
ti-dsp | TI DSP | 德州仪器数字信号处理器 |
unicore32 | 国产 Unicore | 国产处理器 |
v850 | Renesas V850 | 瑞萨 V850 系列 |
xilinx | Xilinx | FPGA 里的 MicroBlaze 等软核 |
Kconfig | 配置文件 | menuconfig 里 CPU 相关的配置项 |
SConscript | 构建脚本 | scons 构建用,Keil 不需要 |
我们只保留arm
![]()
我们点开arm

| 目录名 | 对应内核 | 典型芯片/场景 |
|---|---|---|
cortex-m0 | Cortex-M0 | 极低端 MCU,如 STM32F0 |
cortex-m3 | Cortex-M3 | STM32F1、GD32F1 |
cortex-m4 | Cortex-M4 | GD32F4、STM32F4,高新能芯片 |
cortex-m7 | Cortex-M7 | STM32F7/H7,高性能 MCU |
cortex-m23 | Cortex-M23 | 低端 ARMv8-M |
cortex-m33 | Cortex-M33 | 带 TrustZone 的 ARMv8-M |
cortex-m85 | Cortex-M85 | 最新高性能 Cortex-M |
cortex-r4 | Cortex-R4 | 实时控制,如车载 |
cortex-r52 | Cortex-R52 | 实时安全,车规级 |
cortex-a | Cortex-A 系列 | 跑 Linux 的应用处理器 |
剩下的一些都是特殊芯片型号了,还有一个公共目录
| 目录名 | 作用 |
|---|---|
common | ARM 各内核的公共代码,如 div0.c(除零异常处理)、showmem.c(内存 dump)等 |
我们把 Cortex-M4 和 common 里面的文件移出来,方便我们后续在keil中添加,我这边是直接移植到libcpu目录下面了
需要注意的是,如果使用AC5编译器,.S文件要导入context_rvds.S;如果使用AC6编译器,.S文件要导入context_gcc.S这个。
其他
include 文件夹和 src 没有什么好裁剪的,到时候原封不动添加到我们工程就好了
总结一下才剪完就是

工程移植
内核文件
首先需要移植(添加的)的就是我们的内核文件,对应的就是文件里面的src文件夹,我们点开这个src文件

| 文件名 | 类型 | 作用 | 是否必须加入 Keil |
|---|---|---|---|
klibc/ | 文件夹 | RT-Thread 自带的一套 libc 实现 | 需要裁剪 |
utest/ | 文件夹 | 单元测试框架 | 否 |
clock.c | 源文件 | 软定时器管理(rt_timer_*) | 是 |
components.c | 源文件 | 自动初始化 + $Sub$$main → entry() 启动流程 | 是 |
cpu_mp.c | 源文件 | 多核 SMP 的 CPU 实现 | 选(多核) |
cpu_up.c | 源文件 | 单核的 CPU 实现 | 选(单核选它) |
defunct.c | 源文件 | 回收已删除线程的资源 | 是 |
idle.c | 源文件 | 空闲线程 | 是 |
ipc.c | 源文件 | 线程间通信:信号量、互斥量、事件集、邮箱、消息队列 | 是 |
irq.c | 源文件 | 中断管理:rt_interrupt_enter/leave | 是 |
kservice.c | 源文件 | 内核服务:rt_kprintf 等 | 是 |
mem.c | 源文件 | 动态内存堆管理(rt_malloc/rt_free) | 可选(三选一) |
memheap.c | 源文件 | 多内存堆管理 | 可选(三选一) |
mempool.c | 源文件 | 静态内存池 | 是 |
object.c | 源文件 | 内核对象容器 | 是 |
scheduler_comm.c | 源文件 | 调度器公共代码 | 是 |
scheduler_mp.c | 源文件 | 抢占式调度(支持 SMP 多核) | 二选一 |
scheduler_up.c | 源文件 | 非抢占式调度(单核) | 二选一 |
signal.c | 源文件 | POSIX 信号机制 | 可选 |
slab.c | 源文件 | SLAB 内存分配器 | 可选(三选一) |
thread.c | 源文件 | 线程管理 | 是 |
timer.c | 源文件 | 系统 tick 相关(rt_tick_increase 等) | 是 |
Kconfig | 文件 | menuconfig 配置描述 | 否 |
SConscript | 文件 | scons 构建脚本 | 否 |
因为我平时在项目中用这个freerots用的比较多,用抢占式比较方便本文展示的就是移植这个抢占式的方法,非抢占式的话高优先级也就是比低优先级在上电的时候提前运行一下子而已,而且还要主动放弃cpu占有才行,对我来说非抢占式还不如直接用裸机+中断可以实现,这样还不用移植这个操作系统了,所以平时用的比较少,移植抢占式的话的区别在于
就是上面标注的这个二选一的文件了
然后signal.c文件它面向带 MMU、跑多进程的场景,我们的gd32单核 MCU 裸跑工程用不到。这里也不添加
三种内存管理方式,slab的话内存开销会大很多,基本上都是碎片化的,对于工程文件需要经常申请和销毁内存的需求来说可以选这个,有一个memheap这个是可以把我们的多段碎片化的内存利用起来然后重新让你看起来是一个大内存空间,这个适用于比如说这个我们raw扩容了和外部的一起用之类的,这里我选动态分配这个mem,这个比较常用。
还有一个 klibc 文件

| 文件名 | 类型 | 作用 | 是否加入 Keil |
|---|---|---|---|
utest/ | 文件夹 | 单元测试相关 | 否 |
Kconfig | 文件 | menuconfig 配置描述 | 否 |
kerrno.c | 源文件 | 内核错误码(errno)实现 | 加 |
kstdio.c | 源文件 | 内核 rt_kprintf / rt_vsnprintf 相关实现 | 加 |
kstring.c | 源文件 | 内核字符串函数 rt_memset / rt_memcpy / rt_strlen | 加 |
rt_vsnprintf_std.c | 源文件 | 标准版 rt_vsnprintf,支持完整格式化(含浮点) | 二选一 |
rt_vsnprintf_tiny.c | 源文件 | 精简版 rt_vsnprintf,只支持基本格式 | 二选一 |
rt_vsscanf.c | 源文件 | 内核版 sscanf,解析字符串用 | 加 |
SConscript | 文件 | scons 构建脚本 | 否 |
我选择这个精简版rt_vsnprintf_tiny.c,基本上加上面说的那两个文件就行了,我有强迫症,裁剪完就是下面这样了

klibc文件

keil中的文件夹

cpu移植层
首先是这个libcpu/common 可以删除sconscript这个用不上,非抢占式的不用添加atomic_arm,c

在/libcpu/cortex-m4 下

可以把全部文件放到一起


设备驱动框架
drivers | Device Drivers | 通用设备驱动框架:把各种外设(GPIO、UART、SPI、I2C、ADC、CAN、SD、LCD 等)抽象成统一的 rt_device 接口 |
libc | C Library | 标准 C 库适配层:让 printf、malloc、open/read/write 这些标准函数能在 RT-Thread 上正常使用 |
这是刚刚裁剪的/components
点击/components/drivers,看到下面目录,先看前面几个有没有我们需要的
adc | ADC 设备框架 | 用到 ADC 时加 |
ata | ATA 硬盘设备框架 | 不需要 |
audio | 音频设备框架(IIS/SAI) | 不需要 |
block | 块设备框架(SD 卡、eMMC) | 用到 SD 卡时加 |
can | CAN 总线设备框架 | 用到 CAN 时加 |
clk | 时钟设备框架 | 一般不需要 |
clock_time | 时钟/时间设备 | 一般不需要 |
core | 设备框架核心(device.c 等) | ✅ |
dma | DMA 控制器框架 | 用到 DMA 时加 |
dvfs | 动态电压频率调节 | 不需要 |
ethernet | 以太网设备框架 | 用到网口时加 |
firmware | 固件加载框架 | 不需要 |
graphic | 图形设备框架(LCD/GPU) | 用到 LCD 时加 |
hwcache | 硬件缓存管理 | 不需要 |
hwcrypto | 硬件加解密框架 | 不需要 |
hwspinlock | 硬件自旋锁(多核用) | 不需要 |
i2c | I2C 总线框架 | 用到 I2C 时加 |
iio | 工业 IO 设备框架 | 一般不需要 |
include | 驱动框架公共头文件 | ✅ |
input | 输入设备框架(按键、触摸) | 用到时加 |
ipc | 设备层 IPC | ✅ |
ivshmem | 虚拟机共享内存 | 不需要 |
led | LED 设备框架 | 可选 |
mailbox | 邮箱设备框架(多核通信) | 不需要 |
mfd | 多功能设备框架(PMIC) | 不需要 |
misc | 杂项设备 | 一般不需要 |
mtd | NOR/NAND Flash 框架 | 用到 Flash 时加 |
基本上我们只需要这三个文件,如果需要实现,想用他的驱动库的话,记得在bsp文件里面添加源码的驱动库,然后这里也需要添加对应的驱动文件。

点开core核心文件
utest/ | 单元测试相关 | ❌ |
bus.c | 总线设备管理:把设备挂到总线上,实现总线-设备-驱动模型 | ✅不加也能跑 |
device.c | 设备框架核心:rt_device_register/find/open/read/write/control | ✅ |
dm.c | 设备模型(Device Model)相关,配合设备树 | 很少加 |
driver.c | 驱动注册相关 | ✅ 不加也能跑 |
Kconfig | menuconfig 配置描述 | |
mnt.c | 挂载点管理,配合文件系统 | |
numa.c | NUMA 架构支持(多核服务器用) | |
platform.c | 平台设备框架,配合设备树 | |
platform_ofw.c | 平台设备 + Open Firmware 支持 | |
power.c | 电源管理框架 | |
power_domain.c | 电源域管理 | |
SConscript | scons 构建脚本 |
我们这里把其他的文件删掉,只留一个device.c文件就行
然后点击ipc文件,这个文件几乎全部保留除了utest,然后completion刚刚前面选择的是什么,这里就选什么,我这里是抢占式单核选的是completion_comm.c + completion_up.c这里是选择一个单核加上一个公共文件

裁剪一下


整理一下

libc 适配层
点开/components/libc

这里我们只保留compilers
| 名称 | 类型 | 作用 | 是否加入 Keil |
|---|---|---|---|
compilers | 文件夹 | 各编译器的 libc 适配,如 armlibc(Keil ARMCC 用)、newlib、musl 等 | ✅ 按你用的编译器选一个 |
cplusplus | 文件夹 | C++ 支持,让 RT-Thread 能跑 C++ 代码(全局对象构造、new/delete 等) | 用 C++ 支持 |
posix | 文件夹 | POSIX 接口适配层,提供 pthread、mq_*、open/read/write 等类 Unix 接口 | 移植 POSIX 程序才加 |
Kconfig | 文件 | menuconfig 配置描述 | ❌ |
posix-info.txt | 文件 | POSIX 支持情况的说明文档 | ❌ |
SConscript | 文件 | scons 构建脚本 | ❌ |
点开这个compilers
| 名称 | 类型 | 作用 | 是否加入 Keil |
|---|---|---|---|
armlibc | 文件夹 | ARM Compiler(Keil MDK)专用的标准库适配 | ✅ |
common | 文件夹 | 所有 libc 共用的代码 | ✅ |
dlib | 文件夹 | ARM Compiler 的 Dlib 库适配(老版本 Keil 默认库) | 用 Dlib 才加 |
musl | 文件夹 | musl libc 适配,功能全但较重 | ❌ |
newlib | 文件夹 | newlib libc 适配,GCC / ARM GCC 用 | ❌ |
picolibc | 文件夹 | picolibc(newlib 的精简版)适配 | ❌ |
readme.md | 文件 | 说明文档 | ❌ |
SConscript | 文件 | scons 构建脚本 | ❌ |

最后我们添加这个bsp层方便以后我们添加驱动

添加.h文件地址
建议地址:

在keil中的魔法棒里面c/c++中的define添加RT_USING_LIBC, __CLK_TCK=RT_TICK_PER_SECOND, __RTTHREAD__,__STDC_LIMIT_MACROS, RT_USING_ARMLIBC这组宏是**告诉编译器“当前是 RT-Thread 环境,并且用 ARM 标准库”,从而让 RT-Thread 的代码、libc 适配层和 ARM C 库能正确对接,避免 `rt_vsnprintf`、`malloc` 等符号链接失败**。
应用层编写
我们需要创立三个文件,board的.c.h文件,还有一个类似于在freerots中的freerotsconfig.h的全局配置文件rtconfig.h
board.c文件主要是rt-thread让你提供你的系统时钟,以及后续想添加的各类驱动的基本引脚啊类型配置
下面提供一个写好的作为参考,也可以参考官方的一些写法,在bsp层下面有,参考目录
rt-thread-5.3.0\bsp\gd32\arm\gd32450z-eval\board
#include <rthw.h>
#include <rtthread.h>
#include "gd32f4xx.h"
#ifndef RT_WEAK
#define RT_WEAK __weak
#endif
#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
#define RT_HEAP_SIZE (15 * 1024)
static rt_uint8_t rt_heap[RT_HEAP_SIZE];
RT_WEAK void *rt_heap_begin_get(void)
{
return rt_heap;
}
RT_WEAK void *rt_heap_end_get(void)
{
return rt_heap + RT_HEAP_SIZE;
}
#endif
/* ===================== OS Tick 回调 ===================== */
/* 提前定义:中断服务函数中会调用它 */
void rt_os_tick_callback(void)
{
rt_interrupt_enter();
rt_tick_increase();
rt_interrupt_leave();
}
/* ===================== OS Tick 配置(TODO 1) ===================== */
/* 使用 TIMER5 作为系统 tick 定时器,可按需改成其它基本定时器 */
#define TICK_TIMER TIMER5
#define TICK_TIMER_CLK RCU_TIMER5
#define TICK_TIMER_IRQ TIMER5_DAC_IRQn
#define TICK_TIMER_IRQHandler TIMER5_DAC_IRQHandler
static void tick_timer_init(void)
{
timer_parameter_struct timer_initpara;
uint32_t prescaler;
rcu_periph_clock_enable(TICK_TIMER_CLK);
/* 目标:计数频率 = 1MHz,则 period = 1000000 / RT_TICK_PER_SECOND - 1
* 注意:SystemCoreClock 是内核时钟,定时器输入频率可能不同(APB1 x2)。
* 若定时器输入频率不是 SystemCoreClock,请修改下面的除数。 */
prescaler = (SystemCoreClock / 1000000U) - 1U;
timer_deinit(TICK_TIMER);
timer_initpara.prescaler = prescaler;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = (1000000U / RT_TICK_PER_SECOND) - 1U;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TICK_TIMER, &timer_initpara);
/* 使能更新中断 */
timer_interrupt_enable(TICK_TIMER, TIMER_INT_UP);
nvic_irq_enable(TICK_TIMER_IRQ, 0, 0);
timer_enable(TICK_TIMER);
}
/* 定时器中断服务函数 */
void TICK_TIMER_IRQHandler(void)
{
if (timer_interrupt_flag_get(TICK_TIMER, TIMER_INT_FLAG_UP) != RESET)
{
timer_interrupt_flag_clear(TICK_TIMER, TIMER_INT_FLAG_UP);
rt_os_tick_callback();
}
}
/**
* This function will initial your board.
*/
void rt_hw_board_init(void)
{
tick_timer_init();
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif
}
然后关于rt_config.h文件可以去看官方的目录下面一般也有,参考目录
\rt-thread-5.3.0\bsp\gd32\arm\gd32450z-eval

下面贴一个中文注释过的
/* RT-Thread 配置文件(自动生成,请勿手工编辑) */
#ifndef RT_CONFIG_H__
#define RT_CONFIG_H__
/* ---------- 内核基本配置 ---------- */
#define RT_NAME_MAX 12 /* 对象名最大长度 */
#define RT_CPUS_NR 1 /* CPU 核心数(单核) */
#define RT_ALIGN_SIZE 8 /* 字节对齐大小 */
#define RT_THREAD_PRIORITY_32 /* 使用 32 级优先级 */
#define RT_THREAD_PRIORITY_MAX 32 /* 优先级最大值 */
#define RT_TICK_PER_SECOND 1000 /* 每秒 1000 个 tick(1ms) */
/* ---------- 调试与钩子 ---------- */
#define RT_USING_OVERFLOW_CHECK /* 线程栈溢出检查 */
#define RT_USING_HOOK /* 启用钩子函数 */
#define RT_HOOK_USING_FUNC_PTR /* 钩子用函数指针实现 */
#define RT_USING_IDLE_HOOK /* 启用空闲钩子 */
#define RT_IDLE_HOOK_LIST_SIZE 4 /* 空闲钩子最大数量 */
#define IDLE_THREAD_STACK_SIZE 256 /* 空闲线程栈大小 */
/* ---------- 软件定时器 ---------- */
#define RT_USING_TIMER_SOFT /* 启用软件定时器线程 */
#define RT_TIMER_THREAD_PRIO 4 /* 定时器线程优先级 */
#define RT_TIMER_THREAD_STACK_SIZE 512 /* 定时器线程栈大小 */
/* ---------- 调试输出 ---------- */
#define RT_USING_DEBUG /* 启用调试 */
#define RT_DEBUGING_ASSERT /* 启用断言 */
#define RT_DEBUGING_COLOR /* 调试输出带颜色 */
#define RT_DEBUGING_CONTEXT /* 调试输出带上下文 */
/* ---------- 线程间通信(IPC) ---------- */
#define RT_USING_SEMAPHORE /* 信号量 */
#define RT_USING_MUTEX /* 互斥量 */
#define RT_USING_EVENT /* 事件集 */
#define RT_USING_MAILBOX /* 邮箱 */
#define RT_USING_MESSAGEQUEUE /* 消息队列 */
/* ---------- 内存管理 ---------- */
#define RT_USING_MEMPOOL /* 静态内存池 */
#define RT_USING_SMALL_MEM /* 小内存管理算法 */
#define RT_USING_SMALL_MEM_AS_HEAP /* 小内存算法作为堆 */
#define RT_USING_HEAP /* 启用动态堆 */
/* ---------- 设备与控制台 ---------- */
#define RT_USING_DEVICE /* 启用设备框架 */
#define RT_USING_CONSOLE /* 启用控制台 */
#define RT_CONSOLEBUF_SIZE 128 /* 控制台缓冲区大小 */
#define RT_CONSOLE_DEVICE_NAME "uart0" /* 控制台设备名 */
#define RT_USING_CONSOLE_OUTPUT_CTL /* 控制台输出控制 */
#define RT_VER_NUM 0x50300 /* RT-Thread 版本号(5.3.0) */
#define RT_BACKTRACE_LEVEL_MAX_NR 32 /* 回溯最大层数 */
/* ---------- 硬件原子操作 ---------- */
#define RT_USING_HW_ATOMIC /* 启用硬件原子操作 */
#define ARCH_USING_HW_ATOMIC_8 /* 8 位原子操作 */
#define ARCH_USING_HW_ATOMIC_16 /* 16 位原子操作 */
#define RT_USING_CPU_FFS /* 使用 CPU 的 find-first-set 指令 */
#define ARCH_ARM /* 架构:ARM */
#define ARCH_ARM_CORTEX_M /* 内核:Cortex-M */
#define ARCH_ARM_CORTEX_M4 /* 具体型号:Cortex-M4 */
/* ---------- 组件与主线程 ---------- */
#define RT_USING_COMPONENTS_INIT /* 启用组件自动初始化 */
#define RT_USING_USER_MAIN /* 使用用户 main */
#define RT_MAIN_THREAD_STACK_SIZE 2048 /* main 线程栈大小 */
#define RT_MAIN_THREAD_PRIORITY 10 /* main 线程优先级 */
/* ---------- FinSH / MSH 命令行 ---------- */
#define RT_USING_MSH /* 启用 MSH 命令行 */
#define RT_USING_FINSH /* 启用 FinSH */
#define FINSH_USING_MSH /* 使用 MSH 模式 */
#define FINSH_THREAD_NAME "tshell" /* FinSH 线程名 */
#define FINSH_THREAD_PRIORITY 20 /* FinSH 线程优先级 */
#define FINSH_THREAD_STACK_SIZE 4096 /* FinSH 线程栈大小 */
#define FINSH_USING_HISTORY /* 启用历史命令 */
#define FINSH_HISTORY_LINES 5 /* 历史命令条数 */
#define FINSH_USING_SYMTAB /* 启用符号表 */
#define FINSH_CMD_SIZE 80 /* 单条命令最大长度 */
#define MSH_USING_BUILT_IN_COMMANDS /* 启用内置命令 */
#define FINSH_USING_DESCRIPTION /* 命令带描述 */
#define FINSH_ARG_MAX 10 /* 最大参数个数 */
#define FINSH_USING_OPTION_COMPLETION /* 启用参数补全 */
/* ---------- DFS 虚拟文件系统 ---------- */
#define RT_USING_DFS /* 启用文件系统 */
#define DFS_USING_POSIX /* 使用 POSIX 接口 */
#define DFS_USING_WORKDIR /* 启用工作目录 */
#define DFS_FD_MAX 16 /* 最大文件描述符数 */
#define RT_USING_DFS_V1 /* DFS 版本 1 */
#define DFS_FILESYSTEMS_MAX 4 /* 最大文件系统数 */
#define DFS_FILESYSTEM_TYPES_MAX 4 /* 最大文件系统类型数 */
/* ---------- 设备驱动 ---------- */
#define RT_USING_DEVICE_IPC /* 设备 IPC */
#define RT_UNAMED_PIPE_NUMBER 64 /* 匿名管道数量 */
#define RT_USING_SERIAL /* 启用串口设备 */
#define RT_USING_SERIAL_V1 /* 串口驱动 V1 */
#define RT_SERIAL_USING_DMA /* 串口使用 DMA */
#define RT_SERIAL_RB_BUFSZ 64 /* 串口环形缓冲大小 */
#define RT_USING_PIN /* 启用 PIN 设备 */
/* ---------- libc 时区 ---------- */
#define RT_LIBC_USING_LIGHT_TZ_DST /* 启用轻量时区 */
#define RT_LIBC_TZ_DEFAULT_HOUR 8 /* 默认时区:东八区 */
#define RT_LIBC_TZ_DEFAULT_MIN 0
#define RT_LIBC_TZ_DEFAULT_SEC 0
/* ---------- GD32 软件包 ---------- */
#define PKG_USING_GD32_ARM_CMSIS_DRIVER /* 使用 GD32 CMSIS 驱动包 */
#define PKG_USING_GD32_ARM_CMSIS_DRIVER_LATEST_VERSION /* 使用最新版本 */
#define PKG_USING_GD32_ARM_SERIES_DRIVER /* 使用 GD32 系列驱动包 */
#define PKG_USING_GD32_ARM_SERIES_DRIVER_LATEST_VERSION /* 使用最新版本 */
/* ---------- 芯片与 BSP 硬件配置 ---------- */
#define SOC_FAMILY_GD32 /* 芯片家族:GD32 */
#define SOC_SERIES_GD32F4xx /* 芯片系列:GD32F4xx */
#define SOC_GD32F450ZK /* 具体型号:GD32F450ZK */
/* ---------- 片上外设驱动 ---------- */
#define BSP_USING_GPIO /* 启用 GPIO */
#define BSP_USING_UART /* 启用 UART */
#define BSP_USING_SERIAL_V1 /* 串口 V1 */
#define BSP_USING_UART0 /* 启用 UART0 */
#define BSP_UART0_TX_PIN "PA9" /* UART0 TX 引脚:PA9 */
#define BSP_UART0_RX_PIN "PA10" /* UART0 RX 引脚:PA10 */
#define BSP_UART0_AFIO "AF1" /* UART0 复用功能:AF1 */
#define BSP_USING_GD_DBG /* 启用 GD32 调试 */
#endif /* RT_CONFIG_H__ */
这种也是参考了,后续会更新如何通过配置工具配置这个rt-thread,配置工具下载地址参考:
rt-thread.org/download.html#download-rt-thread-env-tool
https://www.rt-thread.org/download.html#download-rt-thread-env-tool下面给的是我自己裁剪过的,直接用就好了
#ifndef RT_CONFIG_H__
#define RT_CONFIG_H__
/* ---------- 内核基本配置 ---------- */
#define RT_NAME_MAX 8 /* 对象名最大长度 */
#define RT_CPUS_NR 1 /* CPU 核心数(单核) */
#define RT_ALIGN_SIZE 8 /* 字节对齐大小 */
#define RT_THREAD_PRIORITY_32 /* 使用 32 级优先级 */
#define RT_THREAD_PRIORITY_MAX 32 /* 优先级最大值 */
#define RT_TICK_PER_SECOND 1000 /* 每秒 1000 个 tick(1ms) */
/* ---------- 调试与钩子 ---------- */
#define RT_USING_OVERFLOW_CHECK /* 线程栈溢出检查 */
#define RT_USING_HOOK /* 启用钩子函数 */
#define RT_HOOK_USING_FUNC_PTR /* 钩子用函数指针实现 */
#define RT_USING_IDLE_HOOK /* 启用空闲钩子 */
#define RT_IDLE_HOOK_LIST_SIZE 4 /* 空闲钩子最大数量 */
#define IDLE_THREAD_STACK_SIZE 256 /* 空闲线程栈大小 */
/* ---------- 软件定时器 ---------- */
#define RT_USING_TIMER_SOFT /* 启用软件定时器线程 */
#define RT_TIMER_THREAD_PRIO 4 /* 定时器线程优先级 */
#define RT_TIMER_THREAD_STACK_SIZE 512 /* 定时器线程栈大小 */
/* ---------- 内核服务优化 ---------- */
#define RT_KSERVICE_USING_STDLIB /* 内核服务使用标准库实现 */
/* ---------- 调试输出 ---------- */
#define RT_USING_DEBUG /* 启用调试 */
#define RT_DEBUGING_COLOR /* 调试输出带颜色 */
#define RT_DEBUGING_CONTEXT /* 调试输出带上下文 */
/* ---------- 线程间通信(IPC) ---------- */
#define RT_USING_SEMAPHORE /* 信号量 */
#define RT_USING_MUTEX /* 互斥量 */
#define RT_USING_EVENT /* 事件集 */
#define RT_USING_MAILBOX /* 邮箱 */
#define RT_USING_MESSAGEQUEUE /* 消息队列 */
/* ---------- 内存管理 ---------- */
#define RT_USING_MEMPOOL /* 静态内存池 */
#define RT_USING_SMALL_MEM /* 小内存管理算法 */
#define RT_USING_SMALL_MEM_AS_HEAP /* 小内存算法作为堆 */
#define RT_USING_HEAP /* 启用动态堆 */
/* ---------- 设备与控制台 ---------- */
#define RT_USING_DEVICE /* 启用设备框架 */
#define RT_USING_CONSOLE /* 启用控制台 */
#define RT_CONSOLEBUF_SIZE 128 /* 控制台缓冲区大小 */
#define RT_VER_NUM 0x50300 //
#define RT_BACKTRACE_LEVEL_MAX_NR 32 /* 回溯最大层数 */
/* ---------- 硬件原子操作---------- */
#define RT_USING_HW_ATOMIC /* 启用硬件原子操作 */
#define ARCH_USING_HW_ATOMIC_8 /* 8 位原子操作 */
#define ARCH_USING_HW_ATOMIC_16 /* 16 位原子操作 */
#define RT_USING_CPU_FFS /* 使用 CPU 的 find-first-set 指令 */
#define ARCH_ARM /* 架构:ARM */
#define ARCH_ARM_CORTEX_M /* 内核:Cortex-M */
#define ARCH_ARM_CORTEX_M4 /* 具体型号:Cortex-M4 */
/* ---------- 组件与主线程 ---------- */
#define RT_USING_COMPONENTS_INIT /* 启用组件自动初始化 */
#define RT_USING_USER_MAIN /* 使用用户 main */
#define RT_MAIN_THREAD_STACK_SIZE 2048 /* main 线程栈大小 */
#define RT_MAIN_THREAD_PRIORITY 10 /* main 线程优先级 */
/* ---------- 设备驱动 ---------- */
#define RT_USING_DEVICE_IPC /* 设备 IPC */
#define RT_UNAMED_PIPE_NUMBER 64 /* 匿名管道数量 */
#define RT_USING_SERIAL /* 启用串口设备 */
#define RT_USING_SERIAL_V1 /* 串口驱动 V1 */
#define RT_SERIAL_USING_DMA /* 串口使用 DMA */
#define RT_SERIAL_RB_BUFSZ 64 /* 串口环形缓冲大小 */
#define RT_USING_PIN /* 启用 PIN 设备 */
/* ---------- libc 时区 ---------- */
#define RT_LIBC_USING_LIGHT_TZ_DST /* 启用轻量时区 */
#define RT_LIBC_TZ_DEFAULT_HOUR 8 /* 默认时区:东八区 */
#define RT_LIBC_TZ_DEFAULT_MIN 0
#define RT_LIBC_TZ_DEFAULT_SEC 0
/* ---------- 内核源码标记 ---------- */
#define __RT_KERNEL_SOURCE__ /* 标记为内核源码 */
#define __RT_IPC_SOURCE__ /* 标记为 IPC 源码 */
/* ---------- 芯片与 BSP 硬件配置 ---------- */
#define SOC_SERIES_GD32F4xx /* 芯片系列:GD32F4xx */
#define SOC_GD32450V
#endif /* RT_CONFIG_H__ */
应用层测试
#include "main.h"
#include <rtthread.h>
#include "SEGGER_RTT.h"
void Led_Init(void)
{
rcu_periph_clock_enable(RCU_GPIOD);
gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_14);
gpio_bit_set(GPIOD, GPIO_PIN_14);
}
static void led_thread_entry(void *parameter)
{
Led_Init();
while (1)
{
gpio_bit_set(GPIOD, GPIO_PIN_14);
rt_thread_mdelay(125);
gpio_bit_reset(GPIOD, GPIO_PIN_14);
rt_thread_mdelay(125);
SEGGER_RTT_printf(0,"opening\n");
}
}
static void rtt_thread_entry(void *parameter)
{
while (1)
{
SEGGER_RTT_printf(0,"Ready\n");
rt_thread_mdelay(125);
}
}
int main(void)
{
rt_thread_t tid_led,tid_rtt;
SEGGER_RTT_Init();
SEGGER_RTT_printf(0,"\nReady\n");
tid_led = rt_thread_create("led",
led_thread_entry,
RT_NULL,
512,
20,
10);
tid_rtt = rt_thread_create("rtt",
rtt_thread_entry,
RT_NULL,
512,
20,
10);
if (tid_led != RT_NULL)
rt_thread_startup(tid_led);
if (tid_rtt != RT_NULL)
rt_thread_startup(tid_rtt);
return 0;
}

这个rtt测试打印也是没有什么问题,移植到这里就算成功了 。
驱动层添加
添加bsp文件 drv_gpio.c 参考路径 \rt-thread-5.3.0\bsp\gd32\arm\libraries\gd32_drivers
![]()
添加.h文件


恢复一下刚刚的pin文件
添加

如何使用这个驱动,以刚刚的gpio 的led为例子
void Led_Init(void)
{
rcu_periph_clock_enable(RCU_GPIOD);
gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_14);
gpio_bit_set(GPIOD, GPIO_PIN_14);
}
这是原来的led配置
然后添加了头文件#include <rtdevice.h>之后改成
#define LED_PIN 62
void Led_Init(void)
{
rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
}
这个62要去drv_gpio.c里面看,可以查看到我们的对应编号,上面初始化只需要一句话就行了,如果点进去看,发现这个函数已经帮我初始化时钟之类的都配置好了。

static void led_thread_entry(void *parameter)
{
Led_Init();
while (1)
{
rt_pin_write(LED_PIN, PIN_HIGH);
rt_thread_mdelay(125);
rt_pin_write(LED_PIN, PIN_LOW);
rt_thread_mdelay(125);
SEGGER_RTT_printf(0,"opening\n");
}
}
简单的置高置低电平
结语
保持好奇,持续学习,一起努力。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)