[活动专区] 【AT-START-WB415测评】移植rt-thread nano+shell及注意事项

[复制链接]
1258|9
 楼主| 6552918 发表于 2022-9-12 09:48 | 显示全部楼层 |阅读模式
#技术资源# #申请原创# 本文的移植是在官方蓝牙例程的MCU部分例程上进行了移植,现在对移植过程和注意事项在此说明一下。
移植的环境是MDK,并已提前安装了rt-threadnano的支持包
b400d77613b018680bb35276b95bd4ab
在 Manage Rum-Time Environment 里 "Software Component" 栏找到 RTOS,Variant 栏选择 RT-Thread,然后勾选 kernel,点击 "OK" 就添加 RT-Thread 内核到工程了。
2684c8d6aef0eb891f5473f074035c3d
现在可以在 Project 看到 RT-Thread RTOS 已经添加进来了,展开 RTOS,可以看到添加到工程的文件:
文件图标上带钥匙的是只读文件,属于系统内核文件,我们不需要修改,只有board.c和rtconfig.h这两个文件有我们需要修改和配置的地方
084ce24009ee34050d4a0771ec8cc0ee
中断与异常处理
RT-Thread 会接管异常处理函数 HardFault_Handler() 和悬挂处理函数 PendSV_Handler(),这两个函数已由 RT-Thread 实现,所以需要删除工程里中断服务例程文件中的这两个函数,避免在编译时产生重复定义。如果此时对工程进行编译,没有出现函数重复定义的错误,则不用做修改。这两个函数在at32wb415_int.c文件内
b85a7fae462b9c2f8c9121658a1e9ec2
32d2e3fb6d1d10366c82677be09a5722
系统时钟配置
需要在 board.c 中实现 系统时钟配置(为 MCU、外设提供工作时钟)与 os tick  的配置(为操作系统提供心跳 / 节拍)。需要将原来在main.c内的system_clock_config();函数去掉
d0e023e0ffb8cb23bd0734cf0df7a017
225f62c5d2cc8eb4be6d9f18fd8fd08d
如下代码所示,用户需要在 board.c 文件中系统初始化和 OS Tick 的配置,用户需在 timer 定时器中断服务函数调用 rt_os_tick_callback function,cortex-m 架构使用 SysTick_Handler()
823c1be0f05d9689662c049f82ba0f87
973cb9c527e9357617c624650277be98
内存堆初始化
系统内存堆的初始化在 board.c 中的 rt_hw_board_init() 函数中完成,内存堆功能是否使用取决于宏 RT_USING_HEAP 是否开启,RT-Thread Nano 默认开启内存堆功能,需要关闭此宏,这样可以保持一个较小的体积。
cc8b05671fa2209c9dad991743d24862
ab998b25f1783b453f85d2fb8500a487
至此,和内核相关的设置就配置完成,接下来我们要处理一些初始化函数,因为在rt-threadnano中的main函数是个线程,原来一些底层初始化再放在这个函数内就不太合适了,需要将初始化函数使用rt-thread的自动初始化功能放到板级初始化过程中
7169fbf98158ff6131f61dc05da20065
c57053908fa4a85f6e55b69872260921
还需要在main.c的while (1)内添加一个系统延时函数,好让此线程挂起,让系统能够实现调度,这点非常重要!!!
4065b67c4713d5a3d7d7d21b25defcb9
另外,at32_board_init内的delay_init();函数要关闭,因为里面用到SysTick,会干扰系统,这里一定要注意!!!at32wb415_board.c里的延时函数也都不要用,也都是由SysTick实现的,和系统有冲突。
7b8269d3678d6b79759c1692bfafb4bd
7aac7c21bddf32a40917783607729f86
4b876d8ab8d6876bcd9689486f08b081
17e99f2153ebea8cdc8710b4b8568049
在 RT-Thread Nano 上添加控制台与 FinSH
本篇文档分为两部分:
第一部分是添加 UART 控制台(实现打印):用来向控制台对接的终端输出打印信息;该部分只需要实现两个函数,串口初始化和系统输出函数,即可完成 UART 控制台打印功能。
第二部分是移植 FinSH 组件(实现命令输入),用以在控制台输入命令调试系统;该部分的实现基于第一部分,只需要添加 FinSH 组件源码并再对接一个系统输入函数即可实现。
下面将对这两部分进行说明。
在 Nano 上添加 UART 控制台(实现打印)
在 RT-Thread Nano 上添加 UART 控制台打印功能后,就可以在代码中使用 RT-Thread 提供的打印函数 rt_kprintf() 进行信息打印,从而获取自定义的打印信息,方便定位代码 bug 或者获取系统当前运行状态等。实现控制台打印(需要确认 rtconfig.h 中已使能 RT_USING_CONSOLE 宏定义),需要完成基本的硬件初始化,以及对接一个系统输出字符的函数,本小节将详细说明。
实现串口初始化
注:此部分为 3.1.5 版本中 #error TODO 2 的部分:#error "TODO 2: Enable the hardware uart and config baudrate."
使用串口对接控制台的打印,首先需要初始化串口,如引脚、波特率等。 初始化的串口函数 uart_init() 有以下两种调用方式,二选一:
方法一:默认使用宏 INIT_BOARD_EXPORT() 进行自动初始化,不需要显式调用,如下所示。
方法二:可以使用显式调用:uart_init() 需要在 board.c 中的 rt_hw_board_init() 函数中调用。
串口初始化时在板级自动初始化中实现了,使用的是串口1中断+DMA方式,具体配置可以看一下我之前的帖子。
d221dc52414841585cfe0651ee8c94d7
2033d1f0499b42246b9cd9b3fbce3185
08bafc2a1d72db656e8a42de7443778a
046c3a9da79b958afd338a9b00aaf2d9
实现 rt_hw_console_output
注:此部分为 3.1.5 版本中 #error TODO 3 的部分:#error "TODO 3: Output the string 'str' through the uart."
实现 finsh 组件输出一个字符,即在该函数中实现 uart 输出字符:
/* 实现 2:输出一个字符,系统函数,函数名不可更改 */
void rt_hw_console_output(const char *str);
6215fabc35e137c3c0af22b9b310e2fc
实现效果如下
4755b7e12d1c82af7fb43526f21aadb4
在 Nano 上添加 FinSH 组件(实现命令输入)
RT-Thread FinSH 是 RT-Thread 的命令行组件(shell),提供一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。
在 RT-Thread Nano 上添加 FinSH 组件,实现 FinSH 功能的步骤主要如下:
添加 FinSH 源码到工程。
实现函数对接。
添加 FinSH 源码到工程
点击 Manage Run-Environment:
8a4b1978202baa6b8e3da79987a631b9
勾选 shell,这将自动把 FinSH 组件的源码到工程:
5be4b56457ca4de346a7861da4f46629
然后在 rtconfig.h 中打开 finsh 相关选项,如下图:
80093a4e4c28230a66c7e241b09e62ec
实现 rt_hw_console_getchar
注:此部分为 3.1.5 版本中 #error TODO 4 的部分:#error "TODO 4: Read a char from the uart and assign it to 'ch'."
要实现 FinSH 组件功能:既可以打印也能输入命令进行调试,控制台已经实现了打印功能,现在还需要在 board.c 中对接控制台输入函数,实现字符输入:
/* 实现 3:finsh 获取一个字符,系统函数,函数名不可更改 */
char rt_hw_console_getchar(void);
rt_hw_console_getchar():控制台获取一个字符,即在该函数中实现 uart 获取字符,可以使用查询方式获取(注意不要死等,在未获取到字符时,需要让出 CPU),推荐使用中断方式获取(我这里用的是中断+DMA方式)。
e21555e889e21d8281e3d1a394504af8
f41834a0015e31bd433718e4e109b5ad
这里我使用了ringbuffer和信号量来处理中断+DMA接收的数据,数据接收完成后释放信号量通知rt_hw_console_getchar()读取收到的数据
c0c1e0b68f03cd5ba40dd9e0bd89e777
DMA收到的数据批量写入ringbuffer,中断+DMA的实现查看我之前的帖子。
b9cb7e890714ef5d0e3ea775402f5e38
e0d7e4162e77de5f7b6a961a061118b1
到这里所以的移植就都结束了,实现了内核移植,并使用串口中断+DMA的方式实现了shell收发。
835ce61ed64c5f9c03ae2c23dac56a52





Undshing 发表于 2022-10-5 20:57 | 显示全部楼层
学习一下
sdlls 发表于 2022-11-1 14:30 | 显示全部楼层
        rt thread 文件系统能同时读写多个文件吗
 楼主| 6552918 发表于 2022-11-1 14:46 | 显示全部楼层
sdlls 发表于 2022-11-1 14:30
rt thread 文件系统能同时读写多个文件吗

可以,但要在完整版或在nano版自行移植文件系统
ulystronglll 发表于 2022-11-1 15:18 | 显示全部楼层
        RT-Thread移植到WB415,难度大吗
cashrwood 发表于 2022-11-1 15:52 | 显示全部楼层
推荐 RT-Thread内核实现与应用开发实战指南学习一下。   
 楼主| 6552918 发表于 2022-11-1 16:14 | 显示全部楼层
ulystronglll 发表于 2022-11-1 15:18
RT-Thread移植到WB415,难度大吗

移植完整版,工作量很大,不建议新手做移植。
lzbf 发表于 2022-11-1 16:26 | 显示全部楼层
个人认为RT-Thread是一个非常好的系统。
youtome 发表于 2022-11-1 17:04 | 显示全部楼层
rt-thread 怎么确定线程栈大小
 楼主| 6552918 发表于 2022-11-1 17:46 | 显示全部楼层
youtome 发表于 2022-11-1 17:04
rt-thread 怎么确定线程栈大小

可以通过shell打印线程栈用量,根据实际情况调整,一般控制在60%比较好
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:北京汇冠触摸技术有限公司/电子工程师
简介:电子工程师,嵌入式应用爱好者。

102

主题

1290

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部