"); //-->
问题:
如何在原有的bsp/stm32/stm32f091-nucleo基础上,创建一个新的标准工程/stm32f030? 因为官方不可能提供所有的芯片的bsp模板,所以掌握创建自己的板子的bsp,是必须要掌握的。并且官方现在提供的教程太详细了,照葫芦画瓢,就可以搞定,这点给RT-Thread点个赞。这也是方便开展后续开发的基础,只有这个开头顺利完成,后面的就更方便,否则真的会打消使用的劲头。我是边写下面文档,边操作2个小时。快的话,半个小时。
我的项目只用到gpio 和串口2.
参考资料:STM32 系列 BSP 制作教程
https://github.com/RT-Thread/rt-thread/blob/master/bsp/stm32/docs/STM32%E7%B3%BB%E5%88%97BSP%E5%88%B6%E4%BD%9C%E6%95%99%E7%A8%8B.md
BSP 的制作过程分为如下五个步骤:
复制通用模板
使用 CubeMX 工具配置工程
修改 BSP 中的 Kconfig 文件
修改构建工程相关文件
重新生成工程
3.1复制通用模板
本次制作的 BSP 为 F0 系列,因此拷贝模板文件夹下的 stm32f0xx 文件夹,并将该文件夹的名称改为 stm32f020-miao ,如下图所示:
在接下来的 BSP 的制作过程中,将会修改 board 文件夹内的配置文件,将 F0 系列的 BSP 模板变成一个适用于正点原子 stm32f030-miao 开发板的 BSP ,下表总结了 board 文件夹中需要修改的内容:
项目 | 需要修改的内容说明 |
CubeMX_Config (文件夹) | CubeMX 工程 |
linker_scripts (文件夹) | BSP 特定的链接脚本 |
board.c/h | 系统时钟、GPIO 初始化函数、芯片存储器大小 |
Kconfig | 芯片型号、系列、外设资源 |
SConscript | 芯片启动文件、目标芯片型号 |
3.2 使用 CubeMX 配置工程
在制作 BSP 的第二步,需要创建一个基于目标芯片的 CubeMX 工程。默认的 CubeMX 工程在 CubeMX_Config 文件夹中,双击打开 CubeMX_Config.ioc 工程,如下图所示:
在 CubeMX 工程中将芯片型号为修改芯片型号为 STM32F030R8 。
1.引脚配置:
2.配置时钟:
3. 设置项目名称,并在指定地址重新生成 CubeMX 工程:
选择需要的依赖文件。
由于超时,暂时先不下载。也是可以的。
最终 CubeMX 生成的工程目录结构如下图所示:
3.2.2 拷贝初始化函数
在 board.c 文件中存放了函数 SystemClock_Config() ,该函数负责初始化系统时钟。当使用 CubeMX 工具对系统时钟重新配置的时候,需要更新这个函数。
该函数由 CubeMX 工具生成,默认存放在board/CubeMX_Config/Src/main.c 文件中。但是该文件并没有被包含到我们的工程中,因此需要将这个函数从 main.c 中拷贝到 board.c 文件中。在整个 BSP 的制作过程中,这个函数是唯一要要拷贝的函数,该函数内容如下所示:
#include "board.h"
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
在 board.h 文件中配置了 FLASH 和 RAM 的相关参数,这个文件中需要修改的是 STM32_FLASH_SIZE 和 STM32_SRAM_SIZE 这两个宏控制的参数。本次制作的 BSP 所用的 STM32F030R8T 芯片的 flash 大小为 64k,ram 的大小为 8k,因此对该文件作出如下的修改:
#define STM32_FLASH_START_ADRESS ((uint32_t)0x08000000)
#define STM32_FLASH_SIZE (64 * 1024)
#define STM32_FLASH_END_ADDRESS ((uint32_t)(STM32_FLASH_START_ADRESS + STM32_FLASH_SIZE))
/* Internal SRAM memory size[Kbytes] <8-64>, Default: 64*/
#define STM32_SRAM_SIZE 8
#define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024)
3.3 修改 Kconfig 选项
在本小节中修改 board/Kconfig 文件的内容有如下两点:
芯片型号和系列
BSP 上的外设支持选项
芯片型号和系列的修改如下表所示:
宏定义 | 意义 | 格式 |
SOC_STM32F030R8 | 芯片型号 | SOC_STM32xxx |
SOC_SERIES_STM32F0 | 芯片系列 | SOC_SERIES_STM32xx |
关于 BSP 上的外设支持选项,一个初次提交的 BSP 仅仅需要支持 GPIO 驱动和串口驱动即可,因此在配置选项中只需保留这两个驱动配置项,Kconfig如下图所示:
menu "Hardware Drivers Config"
config SOC_STM32F030R8
bool
select SOC_SERIES_STM32F0
default y
menu "Onboard Peripheral Drivers"
endmenu
menu "On-chip Peripheral Drivers"
config BSP_USING_GPIO
bool "Enable GPIO"
select RT_USING_PIN
default y
config BSP_USING_UART2
bool "Enable UART2"
select RT_USING_SERIAL
default y
endmenu
menu "Board extended module Drivers"
endmenu
endmenu
3.4 修改工程构建相关文件
接下来需要修改用于构建工程相关的文件。
3.4.1 修改链接脚本
linker_scripts 链接文件如下图所示:
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08000000 0x00010000 { ; load region size_region
ER_IROM1 0x08000000 0x00010000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00002000 { ; RW data
.ANY (+RW +ZI)
}
}
本次制作 BSP 使用的芯片为 STM32F030R8,FLASH 为 64k,因此修改 LR_IROM1 和 ER_IROM1 的参数为 0x00010000。RAM 的大小为8k, 因此修改 RW_IRAM1 的参数为 0x00002000。这样的修改方式在一般的应用下就够用了,后续如果有特殊要求,则需要按照链接脚本的语法来根据需求修改。
3.4.2 修改构建脚本
SConscript 脚本决定 MDK/IAR 工程的生成以及编译过程中要添加文件。
在这一步中需要修改芯片型号以及芯片启动文件的地址,修改内容如下图所示:
import os
import rtconfig
from building import *
Import('SDK_LIB')
cwd = GetCurrentDir()
# add general drivers
src = Split('''
board.c
CubeMX_Config/Src/stm32f0xx_hal_msp.c
''')
path = [cwd]
path += [cwd + '/CubeMX_Config/Inc']
startup_path_prefix = SDK_LIB
if rtconfig.CROSS_TOOL == 'gcc':
src += [startup_path_prefix + '/STM32F0xx_HAL/CMSIS/Device/ST/STM32F0xx/Source/Templates/gcc/startup_stm32f030x8.s']
elif rtconfig.CROSS_TOOL == 'keil':
src += [startup_path_prefix + '/STM32F0xx_HAL/CMSIS/Device/ST/STM32F0xx/Source/Templates/arm/startup_stm32f030x8.s']
elif rtconfig.CROSS_TOOL == 'iar':
src += [startup_path_prefix + '/STM32F0xx_HAL/CMSIS/Device/ST/STM32F0xx/Source/Templates/iar/startup_stm32f030x8.s']
# STM32F030x6 || STM32F030x8 || STM32F031x6
# STM32F038xx || STM32F042x6 || STM32F048xx
# STM32F070x6 || STM32F051x8 || STM32F058xx
# STM32F071xB || STM32F072xB || STM32F078xx
# STM32F070xB || STM32F091xC || STM32F098xx || STM32F030xC
# You can select chips from the list above
CPPDEFINES = ['STM32F030x8']
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES)
Return('group')
注意:如果在文件夹中找不到相应系列的 .s 文件,可能是多个系列的芯片重用了相同的启动文件,此时可以在 CubeMX 中生成目标芯片的工程,查看使用了哪个启动文件,然后再修改启动文件名。【就是在下面的文件夹下】
3.4.3 修改工程模板
template 文件是生成 MDK/IAR 工程的模板文件,通过修改该文件可以设置工程中使用的芯片型号以及下载方式。MDK4/MDK5/IAR 的工程模板文件,如下图所示:
下面以 MDK5 模板的修改为例,介绍如何修改模板配置:
选择芯片型号:
修改程序下载方式:
3.5 重新生成工程
重新生成工程需要使用 env 工具。
3.5.1 重新生成 rt_config.h 文件
在 env 界面输入命令 menuconfig 对工程进行配置,并生成新的 rt_config.h 文件。如下图所示:
我的为什么没有DMA?
说明:默认只初始化 GPIO 驱动和 FinSH 对应的串口驱动,不使用 DMA
在 rt_hw_board_init 中需要完成堆的初始化:调用 rt_system_heap_init
重新生成工程成功:
到这一步为止,新的 BSP 就可以使用了。
都得先用scons –target=mdk5,然后在mdk中编译才能通过。
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。