Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
GD32
RT-Thread Nano
原创征文
梁山派GD32F450/470-RT-Thread Nano 移植 (三)
发布于 2023-09-25 16:59:53 浏览:154
订阅该版
这是梁山派移植RT-Thread Nano的第三篇文章,也是最后一篇,将FinSH组件也移植进来 还没看过前两篇的建议先去看前两篇,链接如下: [梁山派GD32F450/470-RT-Thread Nano 移植(一)](https://club.rt-thread.org/ask/article/2d32c106484f38da.html "梁山派GD32F450/470-RT-Thread Nano 移植(一)") [梁山派GD32F450/470-RT-Thread Nano 移植 (二)](https://club.rt-thread.org/ask/article/8e181bf9fab39879.html "梁山派GD32F450/470-RT-Thread Nano 移植 (二)") ------------ 下面是FinSH组件的简介 RT-Thread FinSH 是 RT-Thread 的命令行组件(shell),提供一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。它可以使用串口 / 以太网 / USB 等与 PC 机进行通信,使用 FinSH 组件基本命令的效果图如下所示:  来源:[RT-Thread文档中心-在 Nano 上添加 FinSH 组件(实现命令输入)](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-nano/finsh-port/an0045-finsh-port?id=%e5%9c%a8-nano-%e4%b8%8a%e6%b7%bb%e5%8a%a0-finsh-%e7%bb%84%e4%bb%b6%ef%bc%88%e5%ae%9e%e7%8e%b0%e5%91%bd%e4%bb%a4%e8%be%93%e5%85%a5%ef%bc%89 "RT-Thread文档中心-在 Nano 上添加 FinSH 组件(实现命令输入)") ------------ [Nano移植文件(三).7z](https://club.rt-thread.org/file_download/767231c2c7926ff7) 老规矩,先给文件 文件信息如下  移植步骤如下: 1、在keil中添加FinSH源码 打开未移植FinSH的keil工程,按图中将shell勾选上,这会把FinSH组件的源码添加到工程中  然后在rtconfig.h中将#include "finsh_config.h"的注释释放掉,如下图所示  2、ringbuffer实现部分 这一部分我也不是很明白,不过也不需要太明白,官方有示例,直接复制过来即可,这个不会因为芯片不同而产生区别,只把它当作一个缓冲区就可以了 移植代码直接粘贴到finsh_port.c文件中即可  代码如下: ```c /* 第一部分:ringbuffer 实现部分 */ #include
#include
#define rt_ringbuffer_space_len(rb) ((rb)->buffer_size - rt_ringbuffer_data_len(rb)) struct rt_ringbuffer { rt_uint8_t *buffer_ptr; rt_uint16_t read_mirror : 1; rt_uint16_t read_index : 15; rt_uint16_t write_mirror : 1; rt_uint16_t write_index : 15; rt_int16_t buffer_size; }; enum rt_ringbuffer_state { RT_RINGBUFFER_EMPTY, RT_RINGBUFFER_FULL, /* half full is neither full nor empty */ RT_RINGBUFFER_HALFFULL, }; rt_inline enum rt_ringbuffer_state rt_ringbuffer_status(struct rt_ringbuffer *rb) { if (rb->read_index == rb->write_index) { if (rb->read_mirror == rb->write_mirror) return RT_RINGBUFFER_EMPTY; else return RT_RINGBUFFER_FULL; } return RT_RINGBUFFER_HALFFULL; } /** * get the size of data in rb */ rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb) { switch (rt_ringbuffer_status(rb)) { case RT_RINGBUFFER_EMPTY: return 0; case RT_RINGBUFFER_FULL: return rb->buffer_size; case RT_RINGBUFFER_HALFFULL: default: if (rb->write_index > rb->read_index) return rb->write_index - rb->read_index; else return rb->buffer_size - (rb->read_index - rb->write_index); }; } void rt_ringbuffer_init(struct rt_ringbuffer *rb, rt_uint8_t *pool, rt_int16_t size) { RT_ASSERT(rb != RT_NULL); RT_ASSERT(size > 0); /* initialize read and write index */ rb->read_mirror = rb->read_index = 0; rb->write_mirror = rb->write_index = 0; /* set buffer pool and size */ rb->buffer_ptr = pool; rb->buffer_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE); } /** * put a character into ring buffer */ rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch) { RT_ASSERT(rb != RT_NULL); /* whether has enough space */ if (!rt_ringbuffer_space_len(rb)) return 0; rb->buffer_ptr[rb->write_index] = ch; /* flip mirror */ if (rb->write_index == rb->buffer_size-1) { rb->write_mirror = ~rb->write_mirror; rb->write_index = 0; } else { rb->write_index++; } return 1; } /** * get a character from a ringbuffer */ rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch) { RT_ASSERT(rb != RT_NULL); /* ringbuffer is empty */ if (!rt_ringbuffer_data_len(rb)) return 0; /* put character */ *ch = rb->buffer_ptr[rb->read_index]; if (rb->read_index == rb->buffer_size-1) { rb->read_mirror = ~rb->read_mirror; rb->read_index = 0; } else { rb->read_index++; } return 1; } ``` 3、finsh 移植对接部分 在这一部分我们开始对接finSH组件,对接finSH组件的一个大致流程如下: 当有数据通过串口输入时,进入串口中断,在中断服务函数中将数据存入ringbuffer缓冲区,等数据传输完毕,会触发另一个串口中断并进入中断服务函数,告诉finSH组件数据接收完毕,然后finSH组件开始读取ringbuffer缓冲区中的数据 下面是该部分的移植 3.1 初始化串口中断 在前两篇中,我们已经做好了串口初始化,所以我们在这里直接剪切过来即可,将写图中代码剪切  粘贴到下图中的位置  在finsh_port.c文件中引入串口的头文件,如图所示 ```c #include "bsp_usart.h" ```  然后我们定义几个需要用到的变量 UART_RX_BUF_LEN是串口接收数据长度宏定义 uart_rx_buf是串口接收缓冲区 uart_rxcb是ringbuffer cb(这个不是很懂,个人理解是用来管理串口接收缓冲区的) shell_rx_sem是信号量,当串口接收完成后中断函数会释放信号量,而finSH组件会接收该信号量,然后读取接收到的数据 ```c #define UART_RX_BUF_LEN 16 rt_uint8_t uart_rx_buf[UART_RX_BUF_LEN] = {0}; struct rt_ringbuffer uart_rxcb; /* 定义一个 ringbuffer cb */ static struct rt_semaphore shell_rx_sem; /* 定义一个静态信号量 */ ``` 将他们放到下图中的位置  在串口初始化函数中初始化ringbuffer cb变量uart_rxcb和信号量shell_rx_sem ```c /* 初始化串口接收 ringbuffer */ rt_ringbuffer_init(&uart_rxcb, uart_rx_buf, UART_RX_BUF_LEN); /* 初始化串口接收数据的信号量 */ rt_sem_init(&(shell_rx_sem), "shell_rx", 0, 0); ``` 将他们放到下图中的位置  编写串口中断服务函数 ```c /* uart 中断 */ void USART0_IRQHandler(void) { int ch; /* enter interrupt */ rt_interrupt_enter(); //在中断中一定要调用这对函数,进入中断 if (usart_interrupt_flag_get(BSP_USART,USART_INT_FLAG_RBNE) == SET) // 接收缓冲区不为空 { ch = usart_data_receive(BSP_USART); } if (usart_interrupt_flag_get(BSP_USART,USART_INT_FLAG_IDLE) == SET) // 检测到帧中断 { usart_data_receive(BSP_USART); // 必须要读,读出来的值不能要 ch = '\0'; // 数据接收完毕,数组结束标志 rt_sem_release(&shell_rx_sem); } /* 读取到数据,将数据存入 ringbuffer */ rt_ringbuffer_putchar(&uart_rxcb, ch); /* leave interrupt */ rt_interrupt_leave(); //在中断中一定要调用这对函数,离开中断 } ``` 将他们放到下图中的位置  并将bsp_usart文件中的串口中断函数注释掉,如下面图片所示   3.2 rt_hw_console_getchar函数实现 经过以上的步骤,已成功将官方示例的基础移植完成,这里只需要将官方示例中的rt_hw_console_getchar函数直接复制过来即可 ```c /* 移植 FinSH,实现命令行交互, 需要添加 FinSH 源码,然后再对接 rt_hw_console_getchar */ /* 中断方式 */ char rt_hw_console_getchar(void) { char ch = 0; /* 从 ringbuffer 中拿出数据 */ while (rt_ringbuffer_getchar(&uart_rxcb, (rt_uint8_t *)&ch) != 1) { rt_sem_take(&shell_rx_sem, RT_WAITING_FOREVER); } return ch; } ``` 将上面代码放置到下图中的位置  以上就实现了在梁山派的Nano上添加FinSH组件(实现命令输入) ------------ 这里直接烧录通过串口查看即可(记得注释掉main函数中的rt_kprintf打印函数,实验现象会明显一些) 实验现象如下图:  总结如下: 以上就是在梁山派的Nano上添加FinSH组件(实现命令输入)的全过程,也是梁山派GD32F450/470-RT-Thread Nano 移植的最后一篇 实现了梁山派RT-Thread Nano版本的移植,梁山派Nano上UART控制台的添加以及梁山派Nano上FinSH组件的添加 并针对每一部分的移植实现了该部分的示例 参考资料: 1、[基于 Keil MDK 移植 RT-Thread Nano](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-nano/nano-port-keil/an0039-nano-port-keil "基于 Keil MDK 移植 RT-Thread Nano") 2、[立创开发板-梁山派教程文档](https://lckfb.com/docs/lckfb_lspi/#/ "立创开发板-梁山派教程文档") 3、[立创梁山派](https://lceda001.feishu.cn/wiki/JNDHwxPWWi99CJk6SkMc6Z3Yn2e "立创梁山派") 4、[梁山派GD32F450/470-RT-Thread Nano 移植(一)](https://club.rt-thread.org/ask/article/2d32c106484f38da.html "梁山派GD32F450/470-RT-Thread Nano 移植(一)") 5、[梁山派GD32F450/470-RT-Thread Nano 移植 (二)](https://club.rt-thread.org/ask/article/8e181bf9fab39879.html "梁山派GD32F450/470-RT-Thread Nano 移植 (二)")
1
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
子牧r
这家伙很懒,什么也没写!
文章
5
回答
5
被采纳
0
关注TA
发私信
相关文章
1
求高手指点,RTThread下nanosleep()函数功能如何实现?在线等啊
2
RTT1.2.2在新塘Nano130KE3BN的移植中始终出现栈溢出的问题
3
官方能否出一个nano在mdk下移植finsh到stm32的教程
4
从裸机开始,创建一个RT-Thread Nano系统工程
5
Nano版如何启用shell
6
项目从RTT 2.x NANO移植到 RTT 3.x ENV 环境
7
nano 版本有没有集成到 IAR 中啊?
8
关于MDK5的RT-THREAD NANO中添加MSH组件的例程
9
rtt_nano版本,源代码在哪里下载啊?
10
RTT Nano 在keil 使用C++11 的问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
机器人操作系统 (ROS2) 和 RT-Thread 通信
4
五分钟玩转RT-Thread新社区
5
国产MCU移植系列教程汇总,欢迎查看!
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
LWIP
Env
AT
SPI
Bootloader
FinSH
ART-Pi
CAN总线
Hardfault
USB
文件系统
RT-Thread
DMA
SCons
线程
MQTT
RT-Thread Nano
STM32
RTC
rt-smart
ESP8266
flash
ota在线升级
WIZnet_W5500
FAL
I2C
packages_软件包
UART
cubemx
freemodbus
潘多拉开发板_Pandora
定时器
BSP
PWM
ADC
socket
中断
rt_mq_消息队列_msg_queue
keil_MDK
SDIO
Debug
AB32VG1
MicroPython
编译报错
C++_cpp
msh
ulog
QEMU
本月问答贡献
出出啊
1501
个答案
338
次被采纳
小小李sunny
1390
个答案
276
次被采纳
张世争
715
个答案
157
次被采纳
crystal266
522
个答案
153
次被采纳
whj467467222
1216
个答案
146
次被采纳
本月文章贡献
出出啊
1
篇文章
12
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
2
篇文章
2
次点赞
crystal266
2
篇文章
5
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部