RT-Thread Studio与CubeMX联合编程

本文章参考以下文章:

https://blog.csdn.net/qq_40824852/article/details/122596043
https://zhuanlan.zhihu.com/p/395106066
https://blog.csdn.net/m0_37697335/article/details/108890584

一、简介

经过上次对RT-Thread Studio的初步尝试,发现RT-Thread Studio中存在官方支持的CubeMx选项,本次将利用RT-Thread Studio与CubeMX进行联合编程。
由于目前RT-Thread Studio版本变化,在以往版本中与本文章使用版本不同可能会出现不一样的效果,建议升级RT-Thread Studio至最新或与本文保持一致。

 RT-Thread Studio版本:

在这里插入图片描述

CubeMx版本:

在这里插入图片描述

二、硬件环境

本次测试的硬件环境为自己设备的一块测试板,芯片为STM32G474VET6,采用24M有源晶振和32.7k的低频无源晶振,调试串口为LPUART1,波特率115200。

原理图:

在这里插入图片描述

实物3D:

在这里插入图片描述

三、安装环境

1.安装RT-Thread Studio。
在这里插入图片描述

2.安装CubeMX。

在这里插入图片描述

四、新建工程

  1. 启动RT-Thread Studio;
  2. 点击创建RT-Thread项目 ;
    在这里插入图片描述
  3. 构建工程,并下载确保工程和硬件本身没有问题

在这里插入图片描述
如果没有遇到同类问题,跳过本步骤!!
软件编译本身没有问题,在使用ST-Link下载程序时,RT-Thread Studio控制台输出:

在debug configration中将reset mode由默认的“hardware reset”改为“system reset”

在这里插入图片描述
解决方法:
点击图标->打开调试配置->点击Download->更改复位模式为system reset->确定退出
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
再次构建并烧写程序。

  1. 打开终端查看现象

在这里插入图片描述
配置正确的串口和波特率,点击确定。
在这里插入图片描述
代码中的指令就是打印字符。
在这里插入图片描述
打开终端,开始是现象不正确,是由于原始的RT-Thread Studio的配置不正确,后续加入CubeMx代码后就正常了。
在这里插入图片描述
正常现象就是打印出Hello RT-Thread!
在这里插入图片描述

五、CubeMx配置

  1. 双击项目资源管理器中的CubeMxSetting,打开CubeMx。

在这里插入图片描述

  1. 进入CubeMx后配置烧写、时钟、串口。

配置烧写方式:
在这里插入图片描述
配置时钟输入:
在这里插入图片描述
配置时钟树:
在这里插入图片描述
串口配置:
在这里插入图片描述

  1. 进入Project Manager修改配置

修改输出工程方式:在这里插入图片描述
修改生成文件的方式:
在这里插入图片描述
4. 保存配置。并生成代码,关闭CubeMX。
在这里插入图片描述
代码生成后回到RT-Thread Studio工程,提示stm32f4xx_hal_conf.h改为stm32f4xx_hal_conf_bak.h备份文件,是因为conf内存储着stm32的hal库配置信息,RT-Thread做了一个备份,不用管。

六、编译并做相关操作

  1. 配置完CubeMx后,点击构建,报错一大堆,别慌,好戏开始!!!
    在这里插入图片描述
  2. 添加cubemx文件夹下的SConscript文件
    先检查cubemx文件夹下有没有SConscript文件,如果有就跳过创建环节,检查内容。
    在这里插入图片描述
    选择cubemx文件,右键->新建->文件。
    在这里插入图片描述
    输入文件名SConscript,点击完成。

在这里插入图片描述
SConscript文件中粘贴代码。
在这里插入图片描述
注意需要使用的c文件一定要包含在代码段中,否则就算c文件在该文件夹下也不会参与编译,从而导致编译报错!!
代码如下:

import os
#引入os模块
from building import *
#导入building的所有模块

cwd = GetCurrentDir()
#获取获取当前路径,并保存至变量cwd
src  = Glob('*.c')
#获取当前目录下的所有 C 文件,并保存至src变量

# add cubemx drivers
#由于RT-Thread工程中存在部分相同函数文件,所以对src重新赋值
#文件中的stm32g4xx_it.c 、 system_stm32g4xx.c不加入构建
#其余文件按相同格式填写到下述括号内
src = Split('''
Src/stm32g4xx_hal_msp.c
Src/main.c
Src/dma.c
Src/gpio.c
Src/usart.c
''')

#创建路径列表,并保存至path中
path = [cwd]
path += [cwd + '/Inc']
#这是 RT-Thread 基于 SCons 扩展的一个方法(函数)。
group = DefineGroup('cubemx', src, depend = [''], CPPPATH = path)

Return('group')
#这部分代码文章最后有解释
上述代码属于SCons 。SCons 是一套由 Python 语言编写的开源构建系统,类似于 GNU Make。
它采用不同于通常 Makefile 文件的方式,而是使用 SConstruct  SConscript 文件来替代。
这些文件也是 Python 脚本,能够使用标准的 Python 语法来编写。
所以在 SConstruct、SConscript 文件中可以调用 Python 标准库进行各类复杂的处理,而不局限于 Makefile 设定的规则。

保存文件,右键空白处更新软件包。
在这里插入图片描述

  1. 再次构建工程
    在这里插入图片描述
    没有出现错误,如果出现错误,则大概率是函数重复定义导致,比如multiple definition of main
    在这里插入图片描述
    则找到cubemx文件夹下的main函数,给他增加弱定义__weak,再次构建则不会报错。
    在这里插入图片描述

七、在RT-Thread中调用CubeMx生成的函数

  1. 检查时钟配置,打开drv_clk.c,发现RT-Thread Studio已经自动将CubeMx的时钟配置更新到RT-Thread工程中。
    在这里插入图片描述
  2. 如果没有正常的更新过来,需要将cubemx中main.c中的void SystemClock_Config(void)函数代码复制到drv_clk.c中的void system_clock_config(int target_freq_mhz)函数中。
  3. 调用HAL库的串口发送函数
    将cubemx中main.c中头文件和相关函数复制到applications-main.c-main函数中。
    调用HAL_UART_Transmit函数,所有操作与keil5的实现方式一致。
    在这里插入图片描述
    代码片段:
#include <rtthread.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#include "main.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"

int main(void)
{
    HAL_Init();
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_LPUART1_UART_Init();

//    打印时钟信息
    LOG_D("System Clock information");
    LOG_D("SYSCLK_Frequency = %d", HAL_RCC_GetSysClockFreq());
    LOG_D("HCLK_Frequency   = %d", HAL_RCC_GetHCLKFreq());
    LOG_D("PCLK1_Frequency  = %d", HAL_RCC_GetPCLK1Freq());
    LOG_D("PCLK2_Frequency  = %d", HAL_RCC_GetPCLK2Freq());
    
    HAL_UART_Transmit(&hlpuart1, (uint8_t*)"zhuzhu\r\n", 8, 10);
    
    int count = 1;

    while (count++)
    {
//        LOG_D("Hello RT-Thread!");


        rt_thread_mdelay(1000);
    }

    return RT_EOK;
}

八、输出现象

下载程序,点击终端查看输出现象:

在这里插入图片描述

时钟与CubeMx配置的时钟树一致、
串口打印字符一致、
能执行FinSH指令,
说明代码和工程配置正确,能实现RT-Thread Studio与CubeMX联合编程,可以通过RT-Thread调用hal库函数。

工程文件链接:

https://download.csdn.net/download/qq_40824852/81893468

九、SCons详细介绍

SCons 内置函数
如果想要将自己的一些源代码加入到 SCons 编译环境中,一般可以创建或修改已有 SConscript 文件。SConscript 文件可以控制源码文件的加入,并且可以指定文件的 Group(与 MDK/IAR 等 IDE 中的 Group 的概念类似)。

SCons 提供了很多内置函数可以帮助我们快速添加源码程序,利用这些函数,再配合一些简单的 Python 语句我们就能随心所欲向项目中添加或者删除源码。下面将简单介绍一些常用函数。

GetCurrentDir()
获取当前路径。

Glob(‘*.c’)
获取当前目录下的所有 C 文件。修改参数的值为其他后缀就可以匹配当前目录下的所有某类型的文件。

GetDepend(macro)
该函数定义在 tools 目录下的脚本文件中,它会从 rtconfig.h 文件读取配置信息,其参数为 rtconfig.h 中的宏名。如果 rtconfig.h 打开了某个宏,则这个方法(函数)返回真,否则返回假。

Split(str)
将字符串 str 分割成一个列表 list。

DefineGroup(name, src, depend,**parameters)
这是 RT-Thread 基于 SCons 扩展的一个方法(函数)。DefineGroup 用于定义一个组件。组件可以是一个目录(下的文件或子目录),也是后续一些 IDE 工程文件中的一个 Group 或文件夹。

DefineGroup() 函数的参数描述:
在这里插入图片描述
parameters 可加入的参数:

在这里插入图片描述
SConscript(dirs,variant_dir,duplicate)
读取新的 SConscript 文件,SConscript() 函数的参数描述如下所示:
在这里插入图片描述

十、 RT-Thread的内置FinSH指令集合

RT-Thread shell commands:
clear            - clear the terminal screen
version          - show RT-Thread version information
list_thread      - list thread
list_sem         - list semaphore in system
list_event       - list event in system
list_mutex       - list mutex in system
list_mailbox     - list mail box in system
list_msgqueue    - list message queue in system
list_mempool     - list memory pool in system
list_timer       - list timer in system
list_device      - list device in system
help             - RT-Thread shell help.
ps               - List threads in the system.
free             - Show the memory usage in the system.
reboot           - Reboot System

看到这里就说明已经没有了。
在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐