STM32 BootLoader 刷新项目 (三) 程序框架搭建及刷新演示

STM32 Customer BootLoader 刷新项目 (三) 程序框架搭建

文章目录

  • STM32 Customer BootLoader 刷新项目 (三) 程序框架搭建
      • 典型工作流程
    • 1. 硬件原理图介绍
      • 1.1 USART硬件介绍
      • 1.2 LED和按键介绍
    • 2. STM32 CubeMX工程搭建
      • 2.1 创建工程
      • 2.2 系统配置
      • 2.3 USART串口配置
      • 2.4 配置按键GPIO和LED灯
      • 2.5 配置CRC
      • 2.6 时钟树配置
      • 2.5 工程导出设置
    • 3. 代码编写
    • 4. 工程下载、调试和演示

首先用STM32CubeMX 软件搭建基础工程,来作为二级BootLoader,一级BootLoader是STM32官方自带的startup_stm32f407zgtx.s。我们基于上述最小工程来实现Customer BootLoader的功能。本项目采用的是通过串口实现固件刷新。

image-20240622200254124

下面简单介绍一下二级BootLoder的功能与作用:

二级Customer BootLoader(CBL,Customer BootLoader)是一种在嵌入式系统中常见的软件组件。它主要负责在系统启动时执行初始引导操作,加载和运行应用程序代码。二级Customer BootLoader与一级BootLoader(通常称为Primary BootLoader, PBL)一起工作,提供了更灵活和复杂的引导机制。

典型工作流程

  1. 系统加电后,一级BootLoader(PBL)启动
    • 负责基本硬件初始化(如设置堆栈指针、初始化RAM等)。
    • 加载并执行二级BootLoader(CBL)。
  2. 二级BootLoader启动
    • 执行更详细的硬件初始化。
    • 验证固件的完整性和合法性。
    • 根据系统配置和状态,选择合适的固件或操作系统进行引导。
    • 加载并启动应用程序或操作系统。

目前本项目的Customer BootLoader具备:

  1. 获取软件版本;
  2. 读芯片Chip ID;
  3. 获取Flash Read Protection等级;
  4. 擦除指定Flash Sector;
  5. 更新指定Flash Sector内容;
  6. 使能读/写保护;

下面开始我们本章内容的工程搭建,其中部分图借用洋桃电子杜老师的STM F4系列的课程内容。

1. 硬件原理图介绍

1.1 USART硬件介绍

本项目采用正点原子探索者v2开发板,选用其中的左下角的USB串口进行和上位机之间的串口通信。

image-20240608085309250

正点原子STM32F4 探索者V2开发板,如下图所示,通过短接PA9-RXD,短接PA10-TXD,即将USART1与CH340芯片连接在一起,串口USART1与上位机可通过USB进行通信。

image-20240601085106572

如下图电路所示,使用一根MicroUSB结构的USB数据线,一端连接计算机的USB口,一端连接开发版左下角的USB_232口上,就可以在计算机上虚拟出一个串口,通过这个虚拟串口可以进行计算机与开发板之间的串口通信。

image-20240601085723436

image-20240601185940740

1.2 LED和按键介绍

从正点原子的原理图中,选择4个按键,2个LED灯作为本次实验的对象,用1个按键来控制是否进入Customer BootLoader。用2个LED灯的亮灭来显示进入到不同模式的情况。

image-20231214223415136

下图所示是1个按键KEY_up和两个LED灯对应的原理图,及相应的配置功能

名称端口引脚功能特性初始电平
KEY_UPPA0Input modePull-down 下拉N/A
LED1PF9OutputPushpull推挽输出,初始低电平
LED2PF10OutputPushpull推挽输出,初始低电平

2. STM32 CubeMX工程搭建

2.1 创建工程

打开STM32CubdeMX,点击New Project创建新工程

image-20240519214220349

选择 STM32F407 ZGT6

image-20240520070646930

2.2 系统配置

点击左侧System Core,选择RCC,将HSE和LSE都设置为Crystal/Ceramic Resonator(晶体/陶瓷振荡器)

image-20240604074221880

点击SYS,选择Debug功能为JTAG(5 pins),跟板子调试口对应image-20240604075633710

2.3 USART串口配置

下图是CB的架构图,整个刷新和操作MCU都是通过USART来操作,其中USART1是主要和MCU进行通信、刷新和发送命令的串口,而USART2是Debug 端口,只在调试的时候使用用来输出打印信息,开发阶段完成后,USART2则不再使用。image-20240621072252557

首先,先配置USART1,选择左侧的Connecttivity选项,点击USART1,如下图所示,点击Mode开始配置

image-20240604080347571

STM32对USART模块提供了下面的这些模式,根据需求选择相应模式,本项目选择的是异步模式Asynchronous。

image-20240604080404318

下面我们来对USART进行配置,首先开发板上的串口对应的USART1串口,Mode配置为异步模式Asynchronous,STMCubeMX会自动分配引脚,目前分配的USART1_RX对于PA10,USART1_TX对于PA9,和我们开发板的引脚正好对应,如果不对应的话,可以根据芯片的data Sheet改成相应的引脚。

下面的参数配置Parameter Settings按照默认配置来,波特率为 115200 bit/s,这里确保主从机是一致的,才能通信成功,数据位 8,无校验位,停止位1,数据方向:Receive and Transmit,采样:16.

image-20240604080436567

点击下方的GPIO Settings,可以看到为USART1自动分配的默认引脚

image-20240604080454808

配置USART2,将其配置为异步通信。image-20240713100429531

2.4 配置按键GPIO和LED灯

按照1.2节的硬件说明,进行GPIO和LED灯配置,配置内容如下。

image-20240713101449299

2.5 配置CRC

由于在上位机和单片机传输中,需要对发送的数据进行CRC校验,所以需要将CRC功能激活。激活方法如下

image-20240713102335927

2.6 时钟树配置

点击上方的Clock Configuration,开始配置时钟

image-20240611074559483

下面我们来看一下时钟树的结构,如下图所示

image-20240604081134525

现在开始配置开发板相关的时钟频率,首先选择做左边的Input frequency,选择外部8M的晶振,选择HSE,选择PLLCLK,在HCLK处将时钟敲定为168MHz,即STM32F407可支持的最大时钟频率

image-20240604081430121

2.5 工程导出设置

如下图所示,设置工程

image-20240604213948820

代码生成设置

image-20240604214023852

高级设置Advanced Settings

image-20240604214510752

点击右上角,生成代码GENERATE CODE

image-20240611075023223

点击Open Project,本项目是使用STM32CubeIDE作为集成开发环境,做到编译和调试代码的工具

image-20240604214643976

3. 代码编写

我们目前使用的是Hal库进行的工程实现,如下图所示,是串口轮询发送函数HAL_UART_Transmit(),在发送的过程中,会一直在该函数中进行发送,是Polling Mode。

image-20240608084049717

下图是串口接收函数 HAL_UART_Receive(),也是Polling Mode,在接收数据的过程中,CPU无法被抢占,一直需要等到数据被发送完成后才可退出该函数

image-20240608084138029

下面是在main.c中的代码实现:

引用c标准头文件

image-20240611080012875

宏定义,BL_DEBUG_MSG_EN是为调试用的,重定义huart1,设置数据bl_rx_buffer

image-20240713103012848

在main()函数中调用bootloader_uart_read_data()函数进行数据接收和发送

image-20240713102835072

bootloader_uart_read_data()函数中先接收在发送。来判断上位机发送来的命令类型,在执行相应的操作

void  bootloader_uart_read_data(void)
{uint8_t rcv_len=0;printmsg_Host("BL_DEBUG_MSG: Receive CMD\n\r");while (1){HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);memset(bl_rx_buffer, 0, 200);//here we will read and decode the commands coming from host//first read only one byte from the host , which is the "length" field of the command packetHAL_UART_Receive(C_UART,bl_rx_buffer,1,HAL_MAX_DELAY);rcv_len= bl_rx_buffer[0];HAL_UART_Receive(C_UART,&bl_rx_buffer[1],rcv_len,HAL_MAX_DELAY);switch(bl_rx_buffer[1]){case BL_GET_VER:bootloader_handle_getver_cmd(bl_rx_buffer);break;case BL_GET_HELP:bootloader_handle_gethelp_cmd(bl_rx_buffer);break;case BL_GET_CID:bootloader_handle_getcid_cmd(bl_rx_buffer);break;case BL_GET_RDP_STATUS:bootloader_handle_getrdp_cmd(bl_rx_buffer);break;case BL_GO_TO_ADDR:bootloader_handle_go_cmd(bl_rx_buffer);break;case BL_FLASH_ERASE:bootloader_handle_flash_erase_cmd(bl_rx_buffer);break;case BL_MEM_WRITE:bootloader_handle_mem_write_cmd(bl_rx_buffer);break;case BL_EN_RW_PROTECT:bootloader_handle_en_rw_protect(bl_rx_buffer);break;case BL_MEM_READ:bootloader_handle_mem_read(bl_rx_buffer);break;case BL_READ_SECTOR_P_STATUS:bootloader_handle_read_sector_protection_status(bl_rx_buffer);break;case BL_OTP_READ:bootloader_handle_read_otp(bl_rx_buffer);break;case BL_DIS_R_W_PROTECT:bootloader_handle_dis_rw_protect(bl_rx_buffer);break;default:printmsg("BL_DEBUG_MSG:Invalid command code received from host \n");break;}}}

如果没有按键按下,则跳转到APP程序,进行执行应用层程序。

/*code to jump to user application*Here we are assuming FLASH_SECTOR2_BASE_ADDRESS*is where the user application is stored*/
void bootloader_jump_to_user_app(void)
{//just a function pointer to hold the address of the reset handler of the user app.void (*app_reset_handler)(void);printmsg("BL_DEBUG_MSG:bootloader_jump_to_user_app\n");// 1. configure the MSP by reading the value from the base address of the sector 2uint32_t msp_value = *(volatile uint32_t *)FLASH_SECTOR2_BASE_ADDRESS;printmsg("BL_DEBUG_MSG:MSP value : %#x\n",msp_value);//This function comes from CMSIS.__set_MSP(msp_value);//SCB->VTOR = FLASH_SECTOR1_BASE_ADDRESS;/* 2. Now fetch the reset handler address of the user application* from the location FLASH_SECTOR2_BASE_ADDRESS+4*/uint32_t resethandler_address = *(volatile uint32_t *) (FLASH_SECTOR2_BASE_ADDRESS + 4);app_reset_handler = (void*) resethandler_address;printmsg("BL_DEBUG_MSG: app reset handler addr : %#x\n",app_reset_handler);//3. jump to reset handler of the user applicationapp_reset_handler();}

下面是printmsg()打印数据函数实现。

/* prints formatted string to console over UART */
void printmsg(char *format,...)
{
#ifdef BL_DEBUG_MSG_ENchar str[80];/*Extract the the argument list using VA apis */va_list args;va_start(args, format);vsprintf(str, format,args);HAL_UART_Transmit(D_UART,(uint8_t *)str, strlen(str),HAL_MAX_DELAY);va_end(args);
#endif
}

下面是mainh函数中的完整代码:

int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();MX_USART2_UART_Init();MX_CRC_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* Lets check whether button is pressed or not, if not pressed jump to user application */if ( HAL_GPIO_ReadPin(KeyUp_GPIO_Port, KeyUp_Pin) == GPIO_PIN_SET ){printmsg("BL_DEBUG_MSG:Button is pressed .. going to BL mode\n\r");/* Use Usart to Read PC transmit CMD */bootloader_uart_read_data();}else{HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);printmsg("BL_DEBUG_MSG:Button is not pressed .. executing user app\n");//jump to user applicationbootloader_jump_to_user_app();}/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

4. 工程下载、调试和演示

将工程编译,之后下载到板子中。

image-20240608084959855

打开设备管理器,查看串口的端口号COM

image-20240608084402078

打开正点原子的串口调试助手,选择刚才设备管理器中串口的COM号,波特率设置为115200,其他默认,打开串口,随便发送一个数据,开发板接收到这个数据,都会原封不动的将该数据打印出来,然后在执行打印Going to BL mode,说明能够接收并发送数据,至此,我们开发Customer BootLoader的第一步,最小工程代码已经搭建完成,后续我们进行上位机与开发板之间的通信协议开发。

image-20240608084720673

一开始程序先跳转至APP层。

image-20240713103936091

复位开发板,下面上电按下KeyUP按键,进入到Customer BootLoader中。

image-20240713104148618

下面打开上位机,连接上位机和开发板连接的串口,根据显示的指令,进行相应的操作。

image-20240713104433991

下面我们展示一下读取版本号的功能,输入1,获取版本号为0x10.

image-20240713104633571

下面我们在试一个刷新命令。下面是录制的一整个执行的流程。

BootLoader串口刷新

如果大家有什么疑问,请随时私信联系我。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GD32 MCU上电跌落导致启动异常如何解决

大家是否碰到过MCU上电过程中存在电源波动或者电压跌落导致MCU启动异常的问题?本视频将会为大家讲解可能的原因以及解决方法: GD32 MCU上下电复位波形如下图所示,上电过程中如果存在吃电的模块,比如wifi模块/4G模块/开启某块电路…

10校大满贯!中国内地高校2024年1-6月CNS发文统计出炉

随着全球科研竞争的日趋激烈,CNS(Cell、Nature、Science)作为科学领域的三大顶级期刊,不仅是科研成果的展示平台,更是各国科研实力比拼的重要战场。近年来,中国高校在国际科研舞台上的表现愈发抢眼&#xf…

排队问题--逆序对应用

对于逆序对,我们可以用树状数组的方式来求,但是值得注意的是,我们逆序对一般求的是比这个元素小的个数(位置可以是前或者后),那么求比这个元素大的个数怎么办,我们可以用 i - query() !!! 每个元…

生物安全柜验证:气流流型、粒子、浮游菌等参考标准

生物安全柜也是制药行业常见设备,根据GMP的要求,需对生物安全柜定期进行验证确认,确保生物安全柜的性能满足GMP洁净厂房的相关要求。 生物安全柜是实验室的基本设备,也是生物安全实验室的一级安全隔离屏障。其最重要的作用就是气流…

Windows与Linux双机热备软件推荐

网络数据安全在如今信息化的时代越来越变得举足轻重,因此服务器维护和管理也成为企业健康稳定运营的一项重要工作。但实际情况是很多公司并没有配备专业的运维人员,一般都会通过一些管理软件维护或者主机托管给服务商。整理6款服务器的Windows与Linux双机…

JAVA-----异常处理

一、定义 在 Java 中,异常(Exception)是指程序在执行过程中遇到的不正常情况,这些情况可能导致程序无法继续执行或产生错误的结果。异常可以是 Java 标准库中提供的内置异常类,也可以是开发人员自定义的异常类。 二、…

PyTorch面部表情识别项目实战

新书速览|PyTorch深度学习与企业级项目实战-CSDN博客 本书案例比较丰富、比较完整,可以用于课题研究、毕业论文素材,值得大家收藏。 人脸表情是人类信息交流的重要方式,它所包含的人体行为信息与人的情感状态、精神状态、健康状态等有着极为…

关于Ubuntu22.04中的Command ‘vim‘ not found, but can be installed with:

前言 在Ubuntu终端编辑文本内容时需要利用vim,但新安装的虚拟机中并未配置vim,本文记录了vim的安装过程。 打开终端后,在home目录中输入 vim test.txt但提示报错,提示我们没有找到vim,需要通过以下命令进行安装&…

yearrecord——一个类似痕迹墙的React数据展示组件

介绍一下自己做的一个类似于力扣个人主页提交记录和GitHub主页贡献记录的React组件。 下图分别是力扣个人主页提交记录和GitHub个人主页的贡献记录,像这样类似痕迹墙的形式可以比较直观且高效得展示一段时间内得数据记录。 然而要从0实现这个功能还是有一些麻烦得…

等保-Linux等保测评

等保-Linux等保测评 1.查看相应文件,账户xiaoming的密码设定多久过期 rootdengbap:~# chage -l xiaoming Last password change : password must be changed Password expires : pass…

mysql5.7版本字符集编码

默认character_set_databaselatin1 当你字段插入中文值的时候,会报错。 所以修改为了character_set_databaseutf8既可以。 character_set_server他的范围更大,属于服务器级别。

LeetCode 852, 20, 51

目录 852. 山脉数组的峰顶索引题目链接标签二分思路代码 三分思路代码 20. 有效的括号题目链接标签思路代码 51. N 皇后题目链接标签思路回溯如何保证皇后之间无法互相攻击 代码 852. 山脉数组的峰顶索引 题目链接 852. 山脉数组的峰顶索引 标签 数组 二分查找 二分 思路…

逍遥模拟器安装Magisk和EDXPosed教程

资源下载: 逍遥模拟器安装Magisk和EDXPosed教程 - 多开鸭资源下载: MagiskEDXP教程文件 单独的逍遥模拟器使用的版本EDXPosed打包下载(下载之后解压出来一共4个文件): 如果要按本教程安装就务必使用这里的安装包&…

爬虫(一)——爬取快手无水印视频

前言 最近对爬虫比较感兴趣,于是浅浅学习了一些关于爬虫的知识。爬虫可以实现很多功能,非常有意思,在这里也分享给大家。由于爬虫能实现的功能太多,而且具体的实现方式也有所不同,所以这里开辟了一个新的系列——爬虫…

用AI生成Springboot单元测试代码太香了

你好,我是柳岸花开。 在当今软件开发过程中,单元测试已经成为保证代码质量的重要环节。然而,编写单元测试代码却常常让开发者头疼。幸运的是,随着AI技术的发展,我们可以利用AI工具来自动生成单元测试代码,极…

基于单片机的停车场车位管理系统设计

1.简介 停车场车位管理系统是日常中随处可见的一种智能化车位管理技术,使用该技术可以提高车位管理效率,从而减轻人员车位管理工作负荷。本系统集成车牌识别、自动放行、自助缴费等技术,并且具备车位占用状态实时监测与车位数量实时统计、查询…

Java SpringAOP简介

简介 官方介绍: SpringAOP的全称是(Aspect Oriented Programming)中文翻译过来是面向切面编程,AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生…

SpringBatch文件读写ItemWriter,ItemReader使用详解

SpringBatch文件读写ItemWriter,ItemReader使用详解 1. ItemReaders 和 ItemWriters1.1. ItemReader1.2. ItemWriter1.3. ItemProcessor 2.FlatFileItemReader 和 FlatFileItemWriter2.1.平面文件2.1.1. FieldSet 2.2. FlatFileItemReader2.3. FlatFileItemWriter 3…

AI 绘画|Midjourney设计Logo提示词

你是否已经看过许多别人分享的 MJ 咒语,却仍无法按照自己的想法画图?通过学习 MJ 的提示词逻辑后,你将能够更好地理解并创作自己的“咒语”。本文将详细拆解使用 MJ 设计 Logo 的逻辑,让你在阅读后即可轻松上手,制作出…

打包一个自己的Vivado IP核

写在前面 模块复用是逻辑设计人员必须掌握的一个基本功,通过将成熟模块打包成IP核,可实现重复利用,避免重复造轮子,大幅提高我们的开发效率。 接下来将之前设计的串口接收模块和串口发送模块打包成IP核,再分别调用…