bsp
的应用程序都是基于rt-thread
设备驱动框架建立的,所以需要了解rt-thread
设备驱动框架的请参考设备和驱动。env
工具的使用请参考env视频教程以及env用户手册。BSP模版
步骤比较多,但是整体并没有难度,只需要细心点、有耐心点就没有任何问题。BSP模版
建好之后,以后就不用再建立了,所有的应用功能,我们都会在该模版下完成。一次建立,永久享用。rt-thread\bsp\stm32\libraries\templates
下复制文件夹stm32f4xx
,粘贴至rt-thread\bsp\stm32
目录下。stm32f429-hlg-v1.0
。也可以命名为其他名字。stm32f429-hlg-v1.0\applications
目录下新建两个文件夹bsp_inc
和bsp_src
,以及一个main.h
文件;其中bsp_inc
中未来放的是用户程序的所有头文件,对应的bsp_src
里面放的当然是用户程序的所有源文件。文件main.h
是用来管理所有的头文件的。最终该目录下的文件结构如下图所示:说明:主要是给env工具编译工程时的链接脚本添加用户程序的源文件及头文件路径
说明:作用同上图
说明:以后用户应用程序所有的头文件全部包含在这里面
打开stm32f429-hlg-v1.0\board\CubeMX_Config
目录下的CubeMX_Config.ioc
工程。
说明:BSP模版的FinSH终端默认使用USART1,因此需要先使能该串口。当然也可以根据硬件情况更改为其他串口。
其中序号2
、3
分别为外部输入低速时钟、高速时钟,根据晶振实际参数填写。序号6
可以直接填入系统支持的最大时钟值,STM32F429支持180MHz,所以此处填入180后直接回车,软件会自动计算各个参数。
第八步:
打开stm32f429-hlg-v1.0\board\CubeMX_Config\Src
路径下的main.c
文件,复制该文件里面的void SystemClock_Config(void)
函数的全部内容;替换掉stm32f429-hlg-v1.0\board
路径下的board.c
文件里面的void SystemClock_Config(void)
函数的全部内容。该函数初始化了MCU系统的时钟,如果重新利用第五步方法更改了时钟,那么需要重新替换该函数。
第九步:
修改stm32f429-hlg-v1.0\board
路径下的board.h
文件。该文件里面定义了MCU的FLASH
的起始、停止地址的宏以及大小的宏(STM32_FLASH_SIZE
),RAM
的起始、停止地址的宏以及大小的宏(STM32_SRAM_SIZE
)。根据定义内容,我们只需要修改其大小就可以了。因为他们的起始地址操作系统里面的STM32F4模版已经给定,况且F4系列的起始地址都一样。而截至地址是根据起始地址和大小自动计算出来的。故我们根据不同的MCU型号只需要修改其FLASH
和RAM
的大小即可。下图为STM32F429数据手册里的内存映射图,根据该图可知FLASH
和RAM
的所有情况。
由图知FLASH
的大小为 0x2FFFFF Byte
,即为
2 × 1 6 5 B y t e = 2 × 2 20 B y t e = 2 M B 2\times16^5 Byte=2\times2^{20}Byte=2MB 2×165Byte=2×220Byte=2MB
由图知RAM
的大小为 0x2FFFFF Byte
,即为
3 × 1 6 4 B y t e = 3 × 64 × 2 10 B y t e = 192 K B 3\times16^4 Byte=3\times64\times2^{10}Byte=192KB 3×164Byte=3×64×210Byte=192KB
对应的修改board.h
里面的STM32_FLASH_SIZE
和STM32_SRAM_SIZE
如下图所示:
为 BSP 添加驱动时,STM32CubeMX 工具可以快速的完成
使能外设
和配置管脚
的工作。而外设初始化,中断配置,DMA配置等等则由 RT-Thread 提供的驱动文件来完成。也就是说,虽然 STM32CubeMX 生成了多个文件用来初始化外设,但 RT-Thread 只使用了 STM32CubeMX 生成的 stm32fxx_hal_msp.c 文件和 stm32fxx_hal_conf.h 文件。
上面的这段话在后面具体的BSP过程中就会理解。
打开stm32f429-hlg-v1.0\board
路径下的Kconfig
文件,该文件是使用env
工具进行开启或者关闭一些功能的配置文件,根据该文件的配置情况,通过env
工具开启或者关闭某些功能以后,操作系统会自动更新系统头文件rtconfig.h
,该文件位于stm32f429-hlg-v1.0
目录下。
在"Hardware Drivers Config"
(硬件驱动配置)配置里面主要包括以下三个配置项:
"Onboard Peripheral Drivers"
(板级外设驱动),顾名思义,这里面一般用来配置开发板上现有的外设;"On-chip Peripheral Drivers"
(片上外设驱动),顾名思义,这里面一般用来配置MCU内部的外设;"Board extended module Drivers"
(板级外扩模块的驱动),顾名思义,这里面一般用来配置外扩设备的.其余的配置项里面的内容可以删掉,也可以保留,不影响。
说明:uart1
指的是我们在UART设备里面使用串口设备的名字,就是说在这里我们用的USART1转串口功能,被注册为一个UART设备,该设备的名字是uart1
。
再在Kconfig
文件后面增加一个模块,我这里命名为BSP module
用来配置一些我们自己增加的功能,方便env工具配置。比如后面我们添加一个led灯的bsp,就可以通过在这个模块下增加对应的led宏,方便env
开启或者关闭该bsp,这样在keil工程里就会自动添加或者移除led的相关文件。
编译器链接脚本位于stm32f429-hlg-v1.0\board\linker_scripts
下,共有三个:
link.icf
为IAR的编译链接文件;link.lds
为GCC的编译链接文件;link.sct
为MDK的编译链接文件。不管是哪一种编译链接,修改的都是MCU的内存情况,参考图13.STM32F429内存映射图
进行修改:
link.icf
修改情况如下图:
修改位于stm32f429-hlg-v1.0\board
目录下的SConscript
文件,该文件指定了各种编译器编译时使用的芯片的启动文件和芯片型号。该BSP的芯片启动文件位于stm32f429-hlg-v1.0\board\CubeMX_Config\MDK-ARM
目录下,为startup_stm32f429xx.s
。
修改情况如下图:
修改IAR
和keil
工程模版配置的目的是方便后面每次重新生成工程以后,每次打开工程不需要重新配置。模版和工程都位于stm32f429-hlg-v1.0
文件内。
关于工程和模板说明如下图:
打开keil5
模板template.uvprojx
,更改芯片型号如下图:
说明: keil4和iar模版修改类似keil5。下载方式当然也可以选择其他方式,如Jlink等,
在stm32f429-hlg-v1.0
目录下打开env
工具(切记切记是在该目录下打开env,后面所有的env操作,都得在该目录下打开才行);输入menuconfig
回车进入Hardware Drivers Config
下,可以看到如下图信息:
其中能够看到我们在前面添加的 BSP module
模块。
然后按Esc
键,返回至图25
界面。
进入片上外设驱动配置目录,开启我们在Kconfig
配置里面添加的GPIO片上外设
和UART片上外设
,如下图:
进一步进入UART
外设下面,确定开启对应的UART口。如下图:
该片上外设默认被选中是因为我们在Kconfig
文件里面,把该外设的默认配置方式设置为y
(default y
),即是默认开启的。如果想手动开启,可以把默认方式设置为n
(default n
)即可。
这样我们刚刚配置相关选项在env
里就保存好了。如果选得是No
则放弃本次选中的配置。
在env
里面输入scons --target=mdk5
则生成keil5
工程,输入scons --target=mdk4
则生成keil4
工程,输入scons --target=iar
则生成iar
工程。输入scons --target=vsc
则更新VSCode
的头文件路径,方便我们直接用VSCode
来写代码。
切记: 一定要输入生成工程指令,不然前面所有的工作在工程里并不能自动实现。
到了这一步,就剩下编译了,前面的步骤到底对不对,编译一下就知道了。
编译有以下三种方法:
keil
编译;VSCode
的终端输入scons
进行编译env
里面输入scons
进行编译再次提醒: 一定要在stm32f429-hlg-v1.0
目录下打开env
工具。
keil打开工程编译,不是工程模板,请看图22
。编译情况如下图:
在env
里面输入code .
,这样就利用VSCode打开了工程。然后在teminal
里面输入scons
就可以开始编译工程了,编译结果如下图:
出现红框部分代表编译成功。
出现这种结果其实是编译成功了,是重复编译而已。因为在上面使用了VSCode
的teminal
编译,同样用的scons
指令,两个调用的编译环境其实是一样的,所以这里就是重复编译,也成功了。
然后我们在main.h里面写如下代码:
#ifndef __MAIN_H
#define __MAIN_H
#include /* 操作系统头文件 */
#include /* 操作系统设备头文件 */
#include /* 操作系统板级初始化头文件 */
/* 声明logo函数 */
static void bsp_show_logo(void);
#endif
然后我们在main.c里面写如下代码:
#include "main.h"
#define EXAMPLE_NAME "V1.0-STM32F429IGT HLG_BSP RT-Thread"
#define EXAMPLE_DATE "2019-6-12"
#define DEMO_VER "1.0"
/***************************************************************
* 函数: int main(int argc, char *argv[])
* 参数: int argc, char *argv[]
* 返回值:int 型
* 功能: 主函数
*****************************************************************/
int main(int argc, char *argv[])
{
return RT_EOK;
}
/***************************************************************
* 函数: static void bsp_show_logo(void)
* 参数: 无
* 返回值:无
* 功能: 获取MCU的唯一ID号,并且显示出来,再打印一些其他信息
*****************************************************************/
static void bsp_show_logo(void)
{
rt_uint32_t U_ID0 = 0, U_ID1 = 0, U_ID2 = 0;
U_ID0 = *(__IO rt_uint32_t *)(0x1FFF7A10);
U_ID1 = *(__IO rt_uint32_t *)(0x1FFF7A10 + 0x04);
U_ID2 = *(__IO rt_uint32_t *)(0x1FFF7A10 + 0x08);
rt_kprintf("\n\r");
rt_kprintf("**************************CPU相关信息**************************\n\r");
rt_kprintf("* CPU: STM32F429IGT, LQFP176, CoreFrequency: %d MHz\r\n", SystemCoreClock/1000000);
rt_kprintf("* UID = %08x %08x %08x\n\r", U_ID2, U_ID1, U_ID0);
rt_kprintf("**************************例程相关信息*************************\n\r");
rt_kprintf("* DemoName : %s\r\n", EXAMPLE_NAME);
rt_kprintf("* DemoVersion : %s\r\n", DEMO_VER);
rt_kprintf("* DemoDate : %s\r\n", EXAMPLE_DATE);
rt_kprintf("* STM32CubeMX : (STM32CubeMX FW_F4 V1.24.1)\r\n");
rt_kprintf("* \r\n");
rt_kprintf("* QQ : 358445145 \r\n");
rt_kprintf("* Email : [email protected] \r\n");
rt_kprintf("*************************************************************\n\r");
}
/* 导出bsp_show_logo至FinSH终端 */
MSH_CMD_EXPORT(bsp_show_logo, show STM32F4IGTX logo);
编译下载之后,在终端里面输入help
,或者按Tab
键,可以看到暂时FinSH终端
支持的指令。如下图:
其中红色框里面的是我们刚刚导出至终端的命令。
在终端里输入bsp_show_logo
回车,我们将会看到如下信息:
到这里一个新的BSP模版就彻底的建立好了,后面我们添加的任何应用程序,无非就是在这个基础上增加一些文件而已,不用再次建立模版。最最最最大的好处是,以后我们把添加的任何应用程序,只要放入我们的bsp_src(用户源文件)和bsp_inc(用户头文件夹)文件夹里面,然后在stm32f429-hlg-v1.0\board
下的Kconfig
文件里设置好相应的宏,再在stm32f429-hlg-v1.0\applications
下的SConscript
里面添加该宏和对应的源文件,那么使用env
可以非常方便的建立keil
工程。简直不能再好用。
RT-Thread官网
env用户手册
env构建工具
STM32 系列 BSP 制作教程