目前在GD32环境下需要移植一个shell终端,于是选择了Letter_Shell作为这个工具,具体移植步骤如下:
1、源码下载
在github上下载源代码(源代码各种平台都有,都能下载,能用就行)
zNevermindZZT/letter-shell: letter shellhttps://github.com/NevermindZZT/letter-shell2、文件拷贝
在自己的MDK工程中新建一个LetterShell文件夹,将源码中的src文件夹下的文件拷贝过去
接下来在提供的demo文件夹中找到跟自己开发环境相似文件夹进去复制port接口文件
同样放在之前新建的文件夹中,最终结果如下:
3、接口函数配置
对接口函数的配置主要是实现一个写函数,然后对其初始化
signed short userShellWrite(char *data, unsigned short length)
{
// 遍历发送每个字符
for (unsigned short i = 0; i < length; i++)
{
// 发送单个字符
usart_data_transmit(USART0, (uint8_t)data[i]);
// 等待发送缓冲区为空(TBE 标志置位)
while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
;
}
// 返回实际发送的字节数(假设全部发送成功)
return length;
}
在Init中将其注册,完成初始化、
4、MDK工程中实现串口配置
对串口的配置我选择的是查询发送+中断接收的方式
这里主要展示中断的配置,关键是将 shellHandler 添加到中断函数中
/* 中断回调函数 */
void UART_RxCpltCallback(void) {
/* 从 USART0 读取数据 */
uint8_t data = (uint8_t)(usart_data_receive(USART0) & 0xFF);
/* 将数据存入环形缓冲区 */
uint16_t next_head = (rx_buffer.head + 1) % RX_BUFFER_SIZE;
if (next_head != rx_buffer.tail) { // 防止缓冲区溢出
rx_buffer.buffer[rx_buffer.head] = data;
rx_buffer.head = next_head;
}
/* 调用 SHELL 处理函数 */
shellHandler(&shell, data); // 将数据传递给 SHELL
/* 重新使能接收中断(GD32 需手动清除标志位) */
usart_flag_clear(USART0, USART_FLAG_RBNE); // 清除 RBNE 标志
}
/* 中断服务函数(ISR) */
void USART0_IRQHandler(void) {
/* 检查是否为接收缓冲区非空中断 */
if (usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE) != RESET) {
UART_RxCpltCallback(); // 调用自定义回调函数
}
}
5、主函数中调用
编译、烧写,完成移植
6、总结
具体的移植操作还有诸多细节未展示,这是因为在实际操作中大家的环境与情况不一,不能起到很好的代表作用,移植的过程我也踩了几个坑,最后反思下关键点还是串口中断的配置(裸机)与接口写函数的实现,以及移植版本的问题(不同版本的写函数格式不一致,需要自己调整)
总之,网上例子庞杂繁多,但是值得关注的关键问题就这几个,后续我也会记录在RTOS中使用LetterShell的过程与心得