[学习资料] 【凌鸥创芯电机开发板LKS32MC071CBT8评测报告】5 rt-thread nano结合UART+DMA实现shell及注意事项

[复制链接]
2419|2
 楼主| 6552918 发表于 2023-8-1 00:51 | 显示全部楼层 |阅读模式
本帖最后由 6552918 于 2023-8-1 11:27 编辑

#申请原创# #技术资源# @21小跑堂

rt-thread OS是优秀的国产RTOS,但完成版的rt-thread耗费资源比较大,而且要使用全部功能需要厂家支持有完整额BSP才能很好的体验,才能体现出完整版的优势。针对LKS32MC07X厂家是没有BSP的,想体验rt-thread可以使用nano版本,nano版本使用MDK进行移植还是比较容易的,我看有其他同学已经有相关的移植帖子了,但由于LKS的库不是很健全,有些地方需要重点注意一下,所以还是要介绍一下移植过程,但本帖在内核移植上不是重点,重点是结合UART+DMA实现shell,实现和MCU的命令交互。
这里还先是简单介绍一下内核的移植过程,仅供参考。
Nano Pack 可以通过在 Keil MDK IDE 内进行安装,也可以手动安装。下面开始介绍两种安装方式。
方法一:在内安装
打开 MDK 软件,点击工具栏的 Pack Installer 图标:
56228ca8fae294372b611b8a26420f2f
点击右侧的 Pack,展开 Generic,可以找到 RealThread::RT-Thread,点击 Action 栏对应的 Install ,就可以在线安装 Nano Pack 了。另外,如果需要安装其他版本,则需要展开 RealThread::RT-Thread,进行选择,箭头所指代表已经安装的版本。
65167c50c1fc04b8017d63355035bd66
方法二:手动安装
我们也可以从官网下载安装文件,RT-Thread Nano rId10(https://www.rt-thread.org/download/mdk/RealThread.RT-Thread.3.1.5.pack),下载结束后双击文件进行安装:
bf09b0a7616cb24e1a0a3e40d433c46e
移植前需要准备一个能够正常运行的工程,我使用的是上篇帖子我做的UART+DMA的工程
78223dc5ac9bb08ee23b07d8e5049860
添加到工程
打开已经准备好的可以运行的裸机程序,将 RT-Thread 添加到工程。如下图,点击 Manage Run-Time Environment。
0b5e7fb0ce7e2abff0b3860e5ddb7ed8
点击OK,现在可以在 Project 看到 RT-Thread RTOS 已经添加进来了,展开 RTOS,可以看到添加到工程的文件:
0e918a280c04d121ea17fc11415248f4
board.c
rtconfig.h
这两个文件是系统的配置文件,修改相关的配置都在这两个文件内修改实现
中断与异常处理
RT-Thread 会接管异常处理函数 HardFault_Handler() 和悬挂处理函数 PendSV_Handler(),这两个函数已由 RT-Thread 实现,所以需要删除工程里中断服务例程文件中的这两个函数,避免在编译时产生重复定义。如果此时对工程进行编译,没有出现函数重复定义的错误,则不用做修改。LKS32MC07X的库文件中并没有这两个函数,因此无需处理。
系统时钟配置
需要在 board.c 中实现 系统时钟配置(为 MCU、外设提供工作时钟)与 os tick  的配置(为操作系统提供心跳 / 节拍)。
在board.c中添加芯片头文件
6c17ae5e5b61856531b754f7dd737496
添加OS Tick Configuration
1d365af9ac30a90b6c99dcdddad741b0
但在使用内核函数SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);发现两个问题,一个是SystemCoreClock咩有定义,和SysTick_Config函数没有定义
SystemCoreClock没定义需要在lks32mc07x_sys.c和lks32mc07x_sys.h内添加相应的定义即可
3b7e6b2868d7544c0bcd071782c97e85
357499f4ce2d7e8d5a51490a5e26fabe
SysTick_Config函数没有定义改如何解决呢?首先我们发现SysTick_Config这个函数依赖__Vendor_SysTickConfig这个宏,这个宏在core_cm0.h内有定义,但又依赖__CHECK_DEVICE_DEFINES这个宏,这个宏是没有定义的。
7309f80e7e8f4e215f5fc5e1516caeb4
c244c8e81d1253fb6d52a5736c74d4ad
于是我们在编译器设置内定义__CHECK_DEVICE_DEFINES这个宏
8a4f8688d23149523ce82aa07487af0e
定义完成,并将警告忽略(看着别扭的可以再想办法解决掉,因为core_cm0.h文件是只读的,我不想改变只读特性),这样SysTick_Config函数就可以正常使用了。
0af5dafdf3c3c0abe3c24f4e9ef0c051
6d435c37570a78a13196f96a1c152d21
在board.c内添加系统滴答定时器中断函数,实现系统时钟
08b1895d35a255a298601caaf31f1bf2
关掉interrupt.c文件内的void SysTick_Handler(void)函数定义
8b2d7eabe1009fa24ac10a6364d6eb9c
内存堆初始化
系统内存堆的初始化在 board.c 中的 rt_hw_board_init() 函数中完成,内存堆功能是否使用取决于宏 RT_USING_HEAP 是否开启,RT-Thread Nano 默认开启内存堆功能,需要关闭此宏,这样可以保持一个较小的体积。
397f98c2371323e71ab173539b201f40
至此,和内核相关的设置就配置完成,接下来我们要处理一些初始化函数,因为在rt-threadnano中的main函数是个线程,原来一些底层初始化再放在这个函数内就不太合适了,需要将初始化函数使用rt-thread的自动初始化功能放到板级初始化过程中。
8f229b0e8388713f51de467b12aeedff
通过进行串口收发测试,发送正常,间隔在500ms左右,说明程序已经运行起来了
6ec1bf489748735150ddfc6afbd69be5
接下来是在 RT-Thread Nano 上添加控制台与 FinSH
本篇文档分为两部分:
第一部分是添加 UART 控制台(实现打印):用来向控制台对接的终端输出打印信息;该部分只需要实现两个函数,串口初始化和系统输出函数,即可完成 UART 控制台打印功能。
第二部分是移植 FinSH 组件(实现命令输入),用以在控制台输入命令调试系统;该部分的实现基于第一部分,只需要添加 FinSH 组件源码并再对接一个系统输入函数即可实现。
下面将对这两部分进行说明。
在 Nano 上添加 UART 控制台(实现打印)
在 RT-Thread Nano 上添加 UART 控制台打印功能后,就可以在代码中使用 RT-Thread 提供的打印函数 rt_kprintf() 进行信息打印,从而获取自定义的打印信息,方便定位代码 bug 或者获取系统当前运行状态等。实现控制台打印(需要确认 rtconfig.h 中已使能 RT_USING_CONSOLE 宏定义),需要完成基本的硬件初始化,以及对接一个系统输出字符的函数,本小节将详细说明。
3d09f1af783b838d70c0f6fd1dabe098
实现串口初始化位置(注:此部分为 3.1.5 版本中 #error TODO 2 的部分:#error "TODO 2: Enable the hardware uart and config baudrate.")
使用串口对接控制台的打印,首先需要初始化串口,如引脚、波特率等。 初始化的串口函数有以下两种调用方式,二选一:
方法一:默认使用宏 INIT_BOARD_EXPORT() 进行自动初始化,不需要显式调用,如下所示。
be3d7bdbe1def69467f89842891781b0
方法二:可以使用显式调用:相关初始化函数,需要在 board.c 中的 rt_hw_board_init() 函数中调用。
82de4dce2bc3ebec662dbe21b44b063f
实现 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);
db6d5577da86c61df605ae8719b94cb8
添加完输出代码后,编译正常,但程序运缺出现问题
14c859bc4e0f437b465eaaecf1433784
经过各种折腾和测试,都要搞放弃了,最后测试发现和初始化函数内的全局IRQ开关有关
fb96519c755a73099631870f41b699d2
将相关操作关闭就正常了
9a07d355b049ad85a68ff0398241ce97
接下来在 Nano 上添加 FinSH 组件(实现命令输入)
RT-Thread FinSH 是 RT-Thread 的命令行组件(shell),提供一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。
在 RT-Thread Nano 上添加 FinSH 组件,实现 FinSH 功能的步骤主要如下:
添加 FinSH 源码到工程。
实现函数对接。
7a46443881250759efec948212095b45
然后在 rtconfig.h 中打开 finsh 相关选项,如下图:
c5c535ab86ff3eca1c9083475ef90c75
实现 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 组件功能:既可以打印也能输入命令进行调试,控制台已经实现了打印功能,现在还需要在 finsh_port.c  中对接控制台输入函数,实现字符输入:
/* 实现 3:finsh 获取一个字符,系统函数,函数名不可更改 */
char rt_hw_console_getchar(void);
rt_hw_console_getchar():控制台获取一个字符,即在该函数中实现 uart 获取字符,可以使用查询方式获取(注意不要死等,在未获取到字符时,需要让出 CPU),
这里我使用的是一种非常高效的方式-》信号量,获取字符的函数不会阻塞式等待,不会影响其他程序的响应
先关操作如下:
787f84b1ef47e523aebd99554a2dfda9
647179875e31c106153628352d864d07
db9bdf96a1ab488a8ef828f04d39b886
至此,移植rt-threadnano和使用UART+DMA实现shell的过程就完成了,其中有很多细节需要注意。

Demo30_rt-thread(UART+DMA).zip (1.76 MB, 下载次数: 23)

caigang13 发表于 2023-8-3 08:03 来自手机 | 显示全部楼层
这个是RT Tread自带shell,开源littleshell也不错。
 楼主| 6552918 发表于 2023-8-3 09:17 | 显示全部楼层
caigang13 发表于 2023-8-3 08:03
这个是RT Tread自带shell,开源littleshell也不错。

是的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

102

主题

1290

帖子

10

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