RT-Thread 2. GD32在 RT-Thread Nano上添加控制台与 FinSH

本篇文档分为两部分:

第一部分是添加 UART 控制台(实现打印):用来向控制台对接的终端输出打印信息;该部分只需要实现两个函数,串口初始化和系统输出函数,即可完成 UART 控制台打印功能。
第二部分是移植 FinSH 组件(实现命令输入),用以在控制台输入命令调试系统;该部分的实现基于第一部分,只需要添加 FinSH 组件源码并再对接一个系统输入函数即可实现。

1. 在 Nano 上添加 UART 控制台(实现打印)

1)代码

使用串口1作为控制台输出串口

方法一:默认使用宏 INIT_BOARD_EXPORT() 进行自动初始化,不需要显式调用,如下所示。
方法二:可以使用显式调用:uart_init() 需要在 board.c 中的 rt_hw_board_init() 函数中调用。

//main.c 实现串口初始化、rt_hw_console_output
#include "gd32f3x0.h"
#include "gd32f330c_start.h"
#include "systick.h"
#include <rtthread.h>

#define delay_ms(x)   rt_thread_mdelay(x)

/*!
    \brief      configure the USART0 GPIO ports
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usart1_gpio_config(void)
{
    /* enable COM GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOA);

    /* connect port to USARTx_Tx */
    gpio_af_set(GPIOA, GPIO_AF_4, GPIO_PIN_8);

    /* connect port to USARTx_Rx */
    gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_15);

    /* configure USART Tx as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_8);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_8);

    /* configure USART Rx as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_15);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_15);
}

/*!
    \brief      configure the USART0
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usart1_config(void)
{
    /* enable USART clock */
    rcu_periph_clock_enable(RCU_USART1);

    /* USART configure */
    usart_deinit(USART1);
    usart_word_length_set(USART1, USART_WL_8BIT);
    usart_stop_bit_set(USART1, USART_STB_1BIT);
    usart_parity_config(USART1, USART_PM_NONE);
    usart_baudrate_set(USART1, 115200U);
    usart_receive_config(USART1, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);

    usart_enable(USART1);
}

void uart1_init(void)
{
  usart1_gpio_config();
  usart1_config();
}

void rt_hw_console_output(const char *str)
{
    rt_size_t i = 0, size = 0;
    char a = '\r';

    size = rt_strlen(str);
    for (i = 0; i < size; i++)
    {
        if (*(str + i) == '\n')
        {
            usart_data_transmit(USART1, a);
          while(RESET == usart_flag_get(USART1,USART_FLAG_TBE));
        }
        usart_data_transmit(USART1, *(str + i));
          while(RESET == usart_flag_get(USART1,USART_FLAG_TBE));
    }  
  
}


/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/

int main(void)
{
  
    /* enable the LED GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOB);
    /* configure led GPIO port */ 
    gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_1);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
    
    gpio_bit_set(GPIOB, GPIO_PIN_1);
    
    while(1){
        /* turn on led1 */
        gpio_bit_write(GPIOB, GPIO_PIN_1, RESET);
        rt_kprintf("Hello\n");
        delay_ms(1000);
        
        /* turn off led1 */
        gpio_bit_write(GPIOB, GPIO_PIN_1, SET);
        delay_ms(1000);
    }
}
Note

注:注意:RT-Thread 系统中已有的打印均以 \n 结尾,而并非 \r\n,所以在字符输出时,需要在输出 \n 之前输出 \r,完成回车与换行,否则系统打印出来的信息将只有换行。

//board.c 在 board.c 中的 rt_hw_board_init() 函数中调用
/*
 * Copyright (c) 2006-2019, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2017-07-24     Tanek        the first version
 * 2018-11-12     Ernest Chen  modify copyright
 */
 
#include <stdint.h>
#include <rthw.h>
#include <rtthread.h>

#define _SCB_BASE       (0xE000E010UL)
#define _SYSTICK_CTRL   (*(rt_uint32_t *)(_SCB_BASE + 0x0))
#define _SYSTICK_LOAD   (*(rt_uint32_t *)(_SCB_BASE + 0x4))
#define _SYSTICK_VAL    (*(rt_uint32_t *)(_SCB_BASE + 0x8))
#define _SYSTICK_CALIB  (*(rt_uint32_t *)(_SCB_BASE + 0xC))
#define _SYSTICK_PRI    (*(rt_uint8_t  *)(0xE000ED23UL))

void uart1_init(void);

// Updates the variable SystemCoreClock and must be called 
// whenever the core clock is changed during program execution.
extern void SystemCoreClockUpdate(void);

// Holds the system core clock, which is the system clock 
// frequency supplied to the SysTick timer and the processor 
// core clock.
extern uint32_t SystemCoreClock;

static uint32_t _SysTick_Config(rt_uint32_t ticks)
{
    if ((ticks - 1) > 0xFFFFFF)
    {
        return 1;
    }
    
    _SYSTICK_LOAD = ticks - 1; 
    _SYSTICK_PRI = 0xFF;
    _SYSTICK_VAL  = 0;
    _SYSTICK_CTRL = 0x07;  
    
    return 0;
}

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
#define RT_HEAP_SIZE 1024
static uint32_t rt_heap[RT_HEAP_SIZE];     // heap default size: 4K(1024 * 4)
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

/**
 * This function will initial your board.
 */
void rt_hw_board_init()
{
    /* System Clock Update */
    SystemCoreClockUpdate();
    
    /* System Tick Configuration */
    _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
  
  	uart1_init();

    /* Call components board initial (use INIT_BOARD_EXPORT()) */
#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
}

void SysTick_Handler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();

    rt_tick_increase();

    /* leave interrupt */
    rt_interrupt_leave();
}
2)编译

在这里插入图片描述

3) 运行

在这里插入图片描述

2. 在 Nano 上添加 FinSH 组件(实现命令输入)

RT-Thread FinSH 是 RT-Thread 的命令行组件(shell),提供一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。它可以使用串口 / 以太网 / USB 等与 PC 机进行通信,使用 FinSH 组件基本命令的效果图如下所示:
本文以串口 UART 作为 FinSH 的输入输出端口与 PC 进行通信,描述如何在 Nano 上实现 FinSH shell 功能。
在 RT-Thread Nano 上添加 FinSH 组件,实现 FinSH 功能的步骤主要如下:
添加 FinSH 源码到工程。
实现函数对接。

1)复制 FinSH 源码到目标裸机工程:直接复制 Nano 源码中 rtthread-nano/components 文件夹下的 finsh 文件夹到工程中

在这里插入图片描述

2)finsh_port.c

注释掉RT_WEAK char rt_hw_console_getchar(void)

#include <rthw.h>
#include <rtconfig.h>

#ifndef RT_USING_FINSH
#error Please uncomment the line <#include "finsh_config.h"> in the rtconfig.h 
#endif

#ifdef RT_USING_FINSH

//RT_WEAK char rt_hw_console_getchar(void)
//{
//    /* Note: the initial value of ch must < 0 */
//    int ch = -1;

//#error "TODO 4: Read a char from the uart and assign it to 'ch'."

//    return ch;
//}

#endif /* RT_USING_FINSH */
3) rtconfig.h

增加 #define RT_USING_FINSH

4)main.c
#include "gd32f3x0.h"
#include "gd32f330c_start.h"
#include "systick.h"
#include <rtthread.h>

#define delay_ms(x)   rt_thread_mdelay(x)

/*!
    \brief      configure the USART0 GPIO ports
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usart1_gpio_config(void)
{
    /* enable COM GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOA);

    /* connect port to USARTx_Tx */
    gpio_af_set(GPIOA, GPIO_AF_4, GPIO_PIN_8);

    /* connect port to USARTx_Rx */
    gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_15);

    /* configure USART Tx as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_8);

    /* configure USART Rx as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_15);
}

/*!
    \brief      configure the USART0
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usart1_config(void)
{
    /* enable USART clock */
    rcu_periph_clock_enable(RCU_USART1);

    /* USART configure */
    usart_deinit(USART1);
    usart_word_length_set(USART1, USART_WL_8BIT);
    usart_stop_bit_set(USART1, USART_STB_1BIT);
    usart_parity_config(USART1, USART_PM_NONE);
    usart_baudrate_set(USART1, 115200U);
    usart_receive_config(USART1, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);

    usart_enable(USART1);
}

void uart1_init(void)
{
  usart1_gpio_config();
  usart1_config();
}

void rt_hw_console_output(const char *str)
{
    rt_size_t i = 0, size = 0;
    char a = '\r';

    size = rt_strlen(str);
    for (i = 0; i < size; i++)
    {
        if (*(str + i) == '\n')
        {
            usart_data_transmit(USART1, a);
          while(RESET == usart_flag_get(USART1,USART_FLAG_TBE));
        }
        usart_data_transmit(USART1, *(str + i));
          while(RESET == usart_flag_get(USART1,USART_FLAG_TBE));
    }  
  
}

char rt_hw_console_getchar(void)
{
    int ch = -1;

    if (usart_flag_get(USART1, USART_FLAG_RBNE) != RESET)
    {
        ch = usart_data_receive(USART1);
    }
    else
    {
        if(usart_flag_get(USART1, USART_FLAG_ORERR) != RESET)
        {
            usart_flag_clear(USART1,USART_FLAG_ORERR);
        }
        rt_thread_mdelay(10);
    }
    return ch;
}



/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/

int main(void)
{
  
    /* enable the LED GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOB);
    /* configure led GPIO port */ 
    gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_1);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
    
    gpio_bit_set(GPIOB, GPIO_PIN_1);
    
    while(1){
        /* turn on led1 */
        gpio_bit_write(GPIOB, GPIO_PIN_1, RESET);
//        rt_kprintf("Hello\n");
        delay_ms(1000);
        
        /* turn off led1 */
        gpio_bit_write(GPIOB, GPIO_PIN_1, SET);
        delay_ms(1000);
    }
}
5)finsh_config.h

屏蔽 #define FINSH_THREAD_PRIORITY 21
屏蔽 //#define FINSH_THREAD_STACK_SIZE 1024

/* FinSH config file */

#ifndef __MSH_CFG_H__
#define __MSH_CFG_H__

// <<< Use Configuration Wizard in Context Menu >>>
#define RT_USING_FINSH
#define FINSH_USING_MSH
#define FINSH_USING_MSH_ONLY
// <h>FinSH Configuration
// <o>the priority of finsh thread <1-30>
//  <i>the priority of finsh thread
//  <i>Default: 21
//#define FINSH_THREAD_PRIORITY       21
// <o>the stack of finsh thread <1-4096>
//  <i>the stack of finsh thread
//  <i>Default: 4096  (4096Byte)
//#define FINSH_THREAD_STACK_SIZE     1024

#define FINSH_USING_SYMTAB
// <c1>Enable command description
//  <i>Enable command description
#define FINSH_USING_DESCRIPTION
//  </c>
// </h>

// <<< end of configuration section >>>
#endif
6)编译

在这里插入图片描述

7) 在超级终端中使用FinSH
 \ | /
- RT -     Thread Operating System
 / | \     3.1.5 build May 17 2023
 2006 - 2020 Copyright by rt-thread team
msh >help
RT-Thread shell commands:
version          - show RT-Thread version information
list_thread      - list thread
list_sem         - list semaphore in system
list_mailbox     - list mail box in system
list_timer       - list timer in system
help             - RT-Thread shell help.
ps               - List threads in the system.

msh >ps
thread   pri  status      sp     stack size max used left tick  error
-------- ---  ------- ---------- ----------  ------  ---------- ---
tshell     6  ready   0x0000008c 0x00000200    98%   0x00000004 000
tidle      7  ready   0x00000040 0x00000080    50%   0x0000001e 000
main       2  suspend 0x00000080 0x00000100    96%   0x00000013 000
msh >

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/20747.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

全景 I 0基础学习VR全景制作,第26章热点功能-文档

本期为大家带来蛙色VR平台&#xff0c;热点功能—文档功能操作。 功能位置示意 热点&#xff0c;指在全景作品中添加各种类型图标的按钮&#xff0c;引导用户通过按钮产生更多的交互&#xff0c;增加用户的多元化体验。 文档热点&#xff0c;即点击热点后会嵌入式弹出所选文档…

基于Java+SpringMVC+vue+element实现前后端分离校园失物招领系统详细设计

基于JavaSpringMVCvueelement实现前后端分离校园失物招领系统详细设计 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获…

WPF MaterialDesign 初学项目实战(3)动态侧边栏

其他文章 WPF MaterialDesign 初学项目实战&#xff08;0&#xff09;:github 项目Demo运行 WPF MaterialDesign 初学项目实战&#xff08;1&#xff09;首页搭建 WPF MaterialDesign 初学项目实战&#xff08;2&#xff09;首页导航栏样式 创建侧边栏实体类 新建MenuBar文件…

基于MWORKS的电动汽车电平衡分析

1 引言 随着电动汽车的快速发展、电池技术的进步和智能电力管理系统的应用&#xff0c;电动汽车电平衡已经成为了电动汽车技术研究中的重要问题之一。 电动汽车电平衡是指车辆发电机、蓄电池、整车用电器在一定时间内的电能供给与消耗达到平衡状态。如果车辆电能产生与消耗无法…

国产游戏引擎,竟然用来搞民航

​本文源自量子位 | 公众号 QbitAI 只是给飞行员做个“装备”&#xff0c;竟然突破了国内民用航空领域的一大技术难题&#xff1f;&#xff01; 这是一群游戏技术开发者的真实经历。 他们用自研游戏引擎开发了一个飞行模拟软件&#xff0c;能够第一视角模拟飞行员起飞、着陆…

mysql 分组语句测试

建表 建表语句&#xff1a; CREATE TABLE student( id int not null, name char(12), sex char(1) ); 预置数据 insert into student values(1, wh, 1); insert into student values(2, wh1, 0); insert into student values(3, zyx, 0); commit; 增加字段 alt…

Linux -- 进程信号

文章目录 1. 信号量1.1 进程互斥概念1.2 认识信号量 2. 信号入门2.1 信号概念2.2 见一见2.3 signal()系统调用2.4 宏定义信号 3. 信号产生方式3.1 键盘产生信号3.2 系统调用产生信号3.3 软件条件产生信号3.4 硬件异常产生信号3.5 Core dump 4. 阻塞信号4.1 相关概念4.2 信号在内…

1066 Root of AVL Tree(51行代码+超详细注释)

分数 25 全屏浏览题目 切换布局 作者 CHEN, Yue 单位 浙江大学 An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebala…

马斯克们叫停 GPT-5,更像是场行为艺术

目录 01 联名信说了什么&#xff1f; 02 发起方是谁&#xff1f; 03 谁签署了联名信&#xff1f; 04 联名信有哪些问题&#xff1f;三巨头的另外两位 Sam Altman 的表态 其他值得关注的署名者 比如马斯克。 另一个位于前列的署名者是 Stability AI 的创始人 Emad Most…

MySQL---存储函数、触发器

1. 存储函数 MySQL存储函数&#xff08;自定义函数&#xff09;&#xff0c;函数一般用于计算和返回一个值&#xff0c;可以将经常需要使用的计算 或功能写成一个函数。 存储函数和存储过程一样&#xff0c;都是在数据库中定义一些 SQL 语句的集合。 存储函数与存储过程的区…

初识kubernetes

初识kubernetes 1.应用部署方式演变 在部署应用程序的方式上&#xff0c;主要经历了三个时代&#xff1a; 传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物理机上 优点&#xff1a;简单&#xff0c;不需要其它技术的参与缺点&#xff1a;不能为应用程…

MySQL基础-事务详解

本文主要介绍MySQL事务 文章目录 前言事务定义事务四大特性&#xff08;ACID&#xff09; 事务操作事务并发问题事务隔离级别 前言 参考链接&#xff1a; 链接1链接2 事务定义 事务是一组操作的集合&#xff0c;他是一个不可分割的工作单位&#xff0c;事务会把所有的操作作…

二叉树总结

文章目录 树需要掌握的基本概念二叉树基本特点满二叉树性质 完全二叉树性质 二叉搜索树&#xff08;二叉排序树&#xff09;Binary Search Tree(BST)性质 平衡二叉树性质 红黑树五大性质 B树 二叉树的存储方式链式存储顺序存储 二叉树的遍历 树需要掌握的基本概念 1、节点、根…

Java版spring cloud 本工程项目管理系统源码-全面的工程项目管理

​ ​工程项目管理系统是指从事工程项目管理的企业&#xff08;以下简称工程项目管理企业&#xff09;受业主委托&#xff0c;按照合同约定&#xff0c;代表业主对工程项目的组织实施进行全过程或若干阶段的管理和服务。 如今建筑行业竞争激烈&#xff0c;内卷严重&#xff0c…

接口自动化测试神器:Python+Requests+Unittest让你的测试用例飞起来

B站首推&#xff01;2023最详细自动化测试合集&#xff0c;小白皆可掌握&#xff0c;让测试变得简单、快捷、可靠 随着互联网的发展&#xff0c;越来越多的应用程序采用了分布式架构&#xff0c;并通过API接口进行数据交换。因此&#xff0c;接口自动化测试已经成为了保证软件质…

【探索SpringCloud】服务发现

前言 今天&#xff0c;我们来聊聊SpringCloud服务发现。主要有如下几个议题&#xff1a; 一、服务发现的概念与方案&#xff1b;二、SpringCloud是如何与各个服务注册厂商进行集成的。 服务发现 在微服务架构中&#xff0c;我们不可避免的需要通过服务间的调用来完成系统功能…

蓝牙网状网络的基本原理及应用开发

借助蓝牙 5 的网状网络功能&#xff0c;开发人员可以增强无线连接系统&#xff08;如物联网设备&#xff09;的通信范围和网络可用性。但是&#xff0c;网状网络的低功耗无线硬件设计与网状网络软件开发之间存在着复杂的层次&#xff0c;这可能会使开发人员迅速陷入混乱并危及项…

今年的面试难度有点大....

大家好&#xff0c;最近有不少小伙伴在后台留言&#xff0c;又得准备面试了&#xff0c;不知道从何下手&#xff01; 不论是跳槽涨薪&#xff0c;还是学习提升&#xff01;先给自己定一个小目标&#xff0c;然后再朝着目标去努力就完事儿了&#xff01; 为了帮大家节约时间&a…

Windows Cygwin 配置

Windows Cygwin 配置 一、什么是Cygwin&#xff1f; Cygwin&#xff0c;原Cygnus出品&#xff08;已被红帽收购&#xff09;&#xff0c;目前是RedHat名下的项目。项目的目的是提供运行于 Windows 平台的类 Unix 环境&#xff08;以 GNU 工具为代表&#xff09;。为了达到这个…

一天吃透SpringCloud面试八股文

1、什么是Spring Cloud &#xff1f; Spring cloud 流应用程序启动器是基于 Spring Boot 的 Spring 集成应用程序&#xff0c;提供与外部系统的集成。Spring cloud Task&#xff0c;一个生命周期短暂的微服务框架&#xff0c;用于快速构建执行有限数据处理的应用程序。 Sprin…