STM32CUBEMX+STM32H743ZIT6+IAP+UART在线升级初始化和代码解析
1、STM32H7带的ITCM,DTCM,AXI SRAM,SRAM1,SRAM2,SRAM3,SRAM4和备份SRAM五块。
其中,
①TCM区包括ITCM和DTCM,这两个是直连CPU的。 速率与CPU一致,最高能到480MHz。
DTCM地址:0x2000 0000,大小128KB。
ITCM地址:0x0000 0000,大小64KB。
②AXI SRAM总线所外挂的外设
外接的主控是LTDC,DMA2D,MDMA,SDMMC1,AXIM和D2-to-D1 AHB 总线。
外接的从设备是AHB3总线,Flash A,Flash B,FMC总线,QSPI和AXI SRAM。另外AHB3也是由AXI总线分支出来的,然后再由AHB3分支出APB3总线。
速度:240MHz。
地址:0x2400 0000,大小512KB。
用途:用途不限,可以用于用户应用数据存储或者LCD显存。
③SRAM1,SRAM2和SRAM3区外接的主控是D1-to-D2 AHB 总线,AHBP总线,DMA1,DMA2,Ethernet MAC,SDMMC2,USB HS1和USB HS2。外接的从设备是SRAM1,SRMA2,SRAM3,AHB1,AHB2,APB1,APB2,D2-to-D1 AHB总线和D2-to-D3 AHB总线。
速度:240MHz。
SRAM1:地址0x3000 0000,大小128KB,用途不限,可用于D2域中的DMA缓冲,也可以当D1域断电后用于运行程序代码。
SRAM2:地址0x3002 0000,大小128KB,用途不限,可用于D2域中的DMA缓冲,也可以用于用户数据存取。
SRAM3:地址0x3004 0000,大小32KB,用途不限,主要用于以太网和USB的缓冲。
④ SRAM4区
位于D3域,数据带宽是32bit,挂在AHB总线上,大部分主控都能访这块SRAM区。
速度:240MHz。
地址:0x3800 0000,大小64KB。
用途:用途不限,可以用于D3域中的DMA缓冲,也可以当D1和D2域进入DStandby待机方式后,继续保存用户数据。
⑤ Backup SRAM区
备份RAM区,位于D3域,数据带宽是32bit,挂在AHB总线上,大部分主控都能访问这块SRAM区。
速度:240MHz。
地址:0x3880 0000,大小4KB。
用途:用途不限,主要用于系统进入低功耗模式后,继续保存数据(Vbat引脚外接电池)。
2、FLASH
STM32H743ZIT6 的 FLASH 容量为 2048K 字节(2MB), STM32H743 的闪存模块组织如表所示
分为两个BANK,每个BANK均分为8个扇区。每个扇区的大小为128KB。
这次我们实现IAP,通过bootloader和APP两个程序来实现。bootloader程序存放BANK1的扇区0,APP程序存放在BANK1的扇区1。FLASHA和FLASHB对应的总线是AXI SRAM,生成的BIN文件对应的栈顶地址也落在AXI_SRAM内。我们打开APP的BIN文件,即可看到栈顶地址为0x240005A0。
综上。stm32H743ZIT6的内存和闪存地址
ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
AXI_SRAM (xrw) : ORIGIN = 0x24000000, LENGTH = 512K
SRAM1 (xrw) : ORIGIN = 0x30000000, LENGTH = 128K
SRAM2 (xrw) : ORIGIN = 0x30020000, LENGTH = 128K
SRAM3 (xrw) : ORIGIN = 0x30040000, LENGTH = 32K
SRAM4 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
flash擦写
flash擦写分为四步
FLASH写入的时候,需要先解锁,接着擦除,然后写入,最后给FLASH上锁。
1、解锁
HAL_FLASH_Unlock( );
2、擦除
HAL_FLASHEx_Erase(&EraseInitStruct,&SectorError);
FLASH_EraseInitTypeDef EraseInitStruct;
EraseInitStruct.Banks = FLASH_BANK_1;//擦除对应的BANK
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS ;//擦除模式按照扇区
EraseInitStruct.Sector = FLASH_SECTOR_1;//APP占用的起始地址所在的扇区
EraseInitStruct.NbSectors = 1; //APP占用的扇区数
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; //供电电压
回顾STM32F103的Flash擦除的最小单位是页,也就是每次一擦除,都会把擦除地址所在页的整页数据擦掉;
STM32F407的Flash擦除的最小单位是扇区,也就是每次一擦除,都会把擦除地址所在扇区的扇区数据擦掉;
3、写入
if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD,Address, data_Address) == HAL_OK) //写入函数,按照字格式写入,每次写入8个字,即32个字节
{ Address = Address + 4 * 8;
data_Address = data_Address + 4 * 8;
}
回顾F1和F4,每次写入4字节。
4、上锁
HAL_FLASH_Lock( );
stm32cubemx配置
-
bootloader配置
①MPU配置
②RCC配置
③串口配置
④烧写配置
⑤时钟树配置
⑥KEIL配置
-
IAP程序配置
和BOOTLOADER的stmcubemx配置一样
KEIL配置
添加
$K\ARM\ARMCC\bin\fromelf.exe --bin --output=Bin\@L.bin !L
代码
-
IAP代码
/* USER CODE BEGIN Header *//********************************************************************************* @file : main.c* @brief : Main program body******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************//* USER CODE END Header *//* Includes ------------------------------------------------------------------*/#include "main.h"#include "dma.h"#include "memorymap.h"#include "usart.h"#include "gpio.h"/* Private includes ----------------------------------------------------------*//* USER CODE BEGIN Includes */#include "stdio.h"#include "string.h"#include "stm32h7xx_ll_rcc.h"#define ENABLE_INT() __set_PRIMASK(0) /* 使能全局中断 */#define DISABLE_INT() __set_PRIMASK(1) /* 禁止全局中断 */#if 1//下面两个变量放进函数内部会跳转失败,跳件错误中断!void (*JumpToNewAPP_ResetHandler)(void); /* 声明一个函数指针 */void JumpToAddr_NewAPP(uint32_t Addr_APP_Start);__IO uint32_t BootAddr = 0x08020000;//0x1FFFF000; /* 的系统 BootLoader 地址 *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*//* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*//* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*//* USER CODE BEGIN PM */#define NVIC_VectTab_RAM_Start ((uint32_t)0x24000000) //RAM起始地址#define NVIC_VectTab_RAM_End ((uint32_t)0x24020000) //RAM结束地址,大小为512K,根据自己的实际芯片大小修改#define NVIC_VectTab_FLASH ((uint32_t)0x08000000) //Flash起始地址#define BOOT_SIZE 0x20000 //Boot大小,128KB,占用第一个扇区#define ApplicationAddress (NVIC_VectTab_FLASH + BOOT_SIZE) //APP的起始地址#define Application_SIZE 0x20000 //APP大小为128KB。占用第二个扇区#define FLASH_USER_END_ADDR (ApplicationAddress+Application_SIZE) //APP的结束地址#define UPDATE_CMD "update" //升级擦除指令typedef void (*iapfun)(void);void SystemClock_Config(void);/* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV */uint32_t SectorError = 0 ; //擦除错误的扇区地址,擦除成功时候该值为0xffffffffiapfun jump2app; //用函数指针指向复位函数入口地址// unsigned int count2 = 0;unsigned char datatemp[256] = {0};//用于存放串口接收缓冲区,存放256B数据。unsigned char boot_flag = 0;//擦除完成标志unsigned char time_out_flag = 0;//接收串口数据超时标志/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/void SystemClock_Config(void);static void MPU_Config(void);/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*//* USER CODE BEGIN 0 */int fputc(int ch, FILE *f){HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);return ch;}uint32_t STMFLASH_ReadWord(uint32_t faddr){return *(uint32_t *)faddr;}/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/int main(void){/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MPU Configuration--------------------------------------------------------*/MPU_Config();/* Enable the CPU Cache *//* Enable I-Cache---------------------------------------------------------*/SCB_EnableICache();/* Enable D-Cache---------------------------------------------------------*/SCB_EnableDCache();/* 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_DMA_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */unsigned char i;printf("boot start\r\n");printf("input \"update\"\t to erasure user flash, or wait 10s to start user app\r\n");//提示输出指令“update”,10s内没接收到指令,开始启动APPfor (int j = 0; j < 18 * 1024 / 4; j++){uint32_t tempSTM32flash1 = STMFLASH_ReadWord(0x08020000 + j * 4);uint32_t tempSTM32flash2 = STMFLASH_ReadWord(0x08040000 + j * 4);if (tempSTM32flash1 != tempSTM32flash2){printf("not same Addr=0x%08X\r\n", 0x08040000 + j * 4);}}for (i = 0; i < 10; i++){//上电后每秒阻塞接收升级指令,连续10秒未收到则跳转App,10秒内收到则接收App数据并写入for (int count = 0; count < 256; count++){datatemp[count] = 0xFF;}HAL_UART_Receive(&huart1, datatemp, 256, 1000);if (strstr((const char *)datatemp, UPDATE_CMD) != NULL) //查询接收的数据是否包含指令。{// 擦除App区域FLASH_EraseInitTypeDef EraseInitStruct;EraseInitStruct.Banks = FLASH_BANK_1;//擦除对应的BANKEraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS ;//擦除模式按照扇区EraseInitStruct.Sector = FLASH_SECTOR_1;//APP占用的起始地址所在的扇区// EraseInitStruct.Sector = FLASH_SECTOR_2;//APP占用的起始地址所在的扇区EraseInitStruct.NbSectors = 1; //APP占用的扇区数EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; //供电电压HAL_FLASH_Unlock();//解锁// SCB_CleanInvalidateDCache();if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) //如果擦除不成功,上锁{HAL_FLASH_Lock();printf("Erase fail at:0x%x\n\r", SectorError); //返回擦除失败的扇区位置return 0;}FLASH_WaitForLastOperation(5000 * 10, FLASH_BANK_1);printf("当SectorError=0x%X\t;表示擦除成功\r\n", SectorError);boot_flag = 1;//擦除成功,开始升级printf("Erase OK\n\r");break;}}if (boot_flag == 1){HAL_StatusTypeDef temp;//状态标志符unsigned int Address;//地址变量unsigned int data_32;//按照字写入,也就是4Bunsigned int buff_32[8];//按照字写入,也就是32Bunsigned char j = 0;//printf("ready to receive bin, please send in 30s\n\r");//提示在30s内发送2进制APP文件Address = ApplicationAddress; //指向预留存放APP的FLASH地址for (int count = 0; count < 256; count++){datatemp[count] = 0xFF;}temp = HAL_UART_Receive(&huart1, datatemp, 256, 30 * 1000); //在30s内通过串口1发送2进制APP文件if (temp == HAL_TIMEOUT){//阻塞30S,未收到App数据则退出printf("time out, end wait to receive bin\n\r");return 0;}else if (temp == HAL_OK){//收到则循环接收,每秒阻塞接收256字节,并写入Flashwhile (1){unsigned char i;HAL_FLASH_Unlock();//解锁uint32_t data_Address = (uint32_t)(&datatemp);for (i = 0; i < 8; i++) //把接收的256字节,按照每次写入32字节,写入8次{if (Address < FLASH_USER_END_ADDR) //写入地址未超出预留区域{if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, Address, data_Address) == HAL_OK) //写入函数,按照字格式写入,每次写入32个字{Address = Address + 4 * 8;data_Address = data_Address + 4 * 8;}else{HAL_FLASH_Lock();printf("write fail at: 0x%x\n\r", Address);return 0;}}elseprintf("写入的升级程序超出预留APP区域\r\n");}HAL_FLASH_Lock();printf("write 256 btye OK: 0x%x\t%d\n\r", Address, j++);//循环调用串口接收函数。最后一包数据不足256字节时会接收超时,防止app数据不完整,不足256字节数据接收完以后处理一次,下一次接收超时认为接收完成,跳转Appfor (int count = 0; count < 256; count++){datatemp[count] = 0xFF;}temp = HAL_UART_Receive(&huart1, datatemp, 256, 2 * 1000);if (temp == HAL_TIMEOUT){time_out_flag++;if (time_out_flag == 2){printf("End write OK\n\r");goto START_APP;}}}}}else if (boot_flag == 0) //没有收到升级命令{START_APP:printf("start user app\n\r");HAL_Delay(10);/*判断App的栈顶指针是否合法(即是否有App)。ApplicationAddress为App在flash中的地址,(*(volatile u32*)ApplicationAddress)的意思取用户程序首地址里面的数据,这个数据就是用户代码的堆栈地址,堆栈地址指向RAM,而RAM的起始地址是0x20000000,因此上面的判断语句执行:判断用户代码的堆栈地址是否落在:0x20000000~0x2001ffff区间中这里的目的是判断App的栈顶指针是否在0x20000000到0x2001FFFF之间,在的话就认为有App,不在就没有*/printf("ApplicationAddress:%0x\r\n", (*(unsigned int *)ApplicationAddress));if (((*(unsigned int *)ApplicationAddress) >= NVIC_VectTab_RAM_Start) &&((*(unsigned int *)ApplicationAddress) <= NVIC_VectTab_RAM_End)){__set_MSP(*(unsigned int *)ApplicationAddress); //调用__set_MSP重新设定栈顶代地址,把栈顶地址设置为APP代码指向的栈顶地址。jump2app = (iapfun) * (unsigned int *)(ApplicationAddress + 4); //获得新的复位函数入口地址,让jump2这个函数指针指向复位函数入口地址。jump2app(); //跳转到新的复位函数}else{printf("no user app\n\r");return 0;}}/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */}/*** @brief System Clock Configuration* @retval None*/void SystemClock_Config(void){RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Supply configuration update enable*/HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);/** Configure the main internal regulator output voltage*/__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}__HAL_RCC_SYSCFG_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/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.PLLM = 1;RCC_OscInitStruct.PLL.PLLN = 120;RCC_OscInitStruct.PLL.PLLP = 2;RCC_OscInitStruct.PLL.PLLQ = 2;RCC_OscInitStruct.PLL.PLLR = 2;RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;RCC_OscInitStruct.PLL.PLLFRACN = 0;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2| RCC_CLOCKTYPE_D3PCLK1 | RCC_CLOCKTYPE_D1PCLK1;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK){Error_Handler();}}/* USER CODE BEGIN 4 */void JumpToAddr_NewAPP(uint32_t Addr_APP_Start){uint32_t i = 0;// Cache_Disable();/* 关闭全局中断 *///DISABLE_INT();/** 关闭全局中断 */__disable_irq();/* 关闭滴答定时器,复位到默认值 */SysTick->CTRL = 0;SysTick->LOAD = 0;SysTick->VAL = 0;/* 设置所有时钟到默认状态, 使用 HSI 时钟 *///LL_RCC_DeInit();HAL_RCC_DeInit();/* 关闭所有中断,清除所有中断挂起标志 */for (i = 0; i < 8; i++){NVIC->ICER[i] = 0xFFFFFFFF;NVIC->ICPR[i] = 0xFFFFFFFF;}/* 使能全局中断 *///ENABLE_INT();/** 使能全局中断 */__enable_irq();/* 跳转到系统 BootLoader,首地址是 MSP,地址+4 是复位中断服务程序地址 */JumpToNewAPP_ResetHandler = (void (*)(void))(*((uint32_t *)(Addr_APP_Start + 4)));/* 设置主堆栈指针 */__set_MSP(*(uint32_t *)Addr_APP_Start);/* 跳转到系统 BootLoader */JumpToNewAPP_ResetHandler();/* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */while (1){}}#endif/* USER CODE END 4 *//* MPU Configuration */void MPU_Config(void){MPU_Region_InitTypeDef MPU_InitStruct = {0};/* Disables the MPU */HAL_MPU_Disable();/** Initializes and configures the Region and the memory to be protected*/MPU_InitStruct.Enable = MPU_REGION_ENABLE;MPU_InitStruct.Number = MPU_REGION_NUMBER0;MPU_InitStruct.BaseAddress = 0x24000000;MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;MPU_InitStruct.SubRegionDisable = 0x0;MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;HAL_MPU_ConfigRegion(&MPU_InitStruct);/* Enables the MPU */HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);}/*** @brief This function is executed in case of error occurrence.* @retval None*/void Error_Handler(void){/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */}#ifdef USE_FULL_ASSERT/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/void assert_failed(uint8_t *file, uint32_t line){/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */}#endif /* USE_FULL_ASSERT */
-
APP代码
/* USER CODE BEGIN Header *//********************************************************************************* @file : main.c* @brief : Main program body******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************//* USER CODE END Header *//* Includes ------------------------------------------------------------------*/#include "main.h"#include "dma.h"#include "memorymap.h"#include "usart.h"#include "gpio.h"/* Private includes ----------------------------------------------------------*//* USER CODE BEGIN Includes */#include <stdio.h>/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*//* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*//* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*//* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/void SystemClock_Config(void);static void MPU_Config(void);/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*//* USER CODE BEGIN 0 */#define NVIC_VectTab_FLASH ((uint32_t)0x08000000) //Flash起始地址#define BOOT_SIZE 0x20000 //Boot大小 128KBint fputc(int ch, FILE *f){HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);return ch;}/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/int main(void){/* USER CODE BEGIN 1 */SCB->VTOR = NVIC_VectTab_FLASH | BOOT_SIZE; /* 设置中断向量偏移地址 *//* USER CODE END 1 *//* MPU Configuration--------------------------------------------------------*/MPU_Config();/* Enable the CPU Cache *//* Enable I-Cache---------------------------------------------------------*/SCB_EnableICache();/* Enable D-Cache---------------------------------------------------------*/SCB_EnableDCache();/* 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_DMA_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */uint32_t Count = 0;printf("\n\r app start\n\r");/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */HAL_Delay(10);if(Count%100 == 0){printf("this is app!\t%d\n\r",Count/100);}Count++;}/* USER CODE END 3 */}/*** @brief System Clock Configuration* @retval None*/void SystemClock_Config(void){RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Supply configuration update enable*/HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);/** Configure the main internal regulator output voltage*/__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}__HAL_RCC_SYSCFG_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/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.PLLM = 1;RCC_OscInitStruct.PLL.PLLN = 120;RCC_OscInitStruct.PLL.PLLP = 2;RCC_OscInitStruct.PLL.PLLQ = 2;RCC_OscInitStruct.PLL.PLLR = 2;RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;RCC_OscInitStruct.PLL.PLLFRACN = 0;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK){Error_Handler();}}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//* MPU Configuration */void MPU_Config(void){MPU_Region_InitTypeDef MPU_InitStruct = {0};/* Disables the MPU */HAL_MPU_Disable();/** Initializes and configures the Region and the memory to be protected*/MPU_InitStruct.Enable = MPU_REGION_ENABLE;MPU_InitStruct.Number = MPU_REGION_NUMBER0;MPU_InitStruct.BaseAddress = 0x24000000;MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;MPU_InitStruct.SubRegionDisable = 0x0;MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;HAL_MPU_ConfigRegion(&MPU_InitStruct);/* Enables the MPU */HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);}/*** @brief This function is executed in case of error occurrence.* @retval None*/void Error_Handler(void){/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */}#ifdef USE_FULL_ASSERT/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/void assert_failed(uint8_t *file, uint32_t line){/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */}#endif /* USE_FULL_ASSERT */
运行结果
- 烧写boot程序
用sscom打开串口。输入指令,注意只要输入的内容包含update即可匹配
-
发送设置
-
发送bin文件
-
app烧录完成,并运行
相关文章:

STM32CUBEMX+STM32H743ZIT6+IAP+UART在线升级初始化和代码解析
1、STM32H7带的ITCM,DTCM,AXI SRAM,SRAM1,SRAM2,SRAM3,SRAM4和备份SRAM五块。 其中, ①TCM区包括ITCM和DTCM,这两个是直连CPU的。 速率与CPU一致,最高能到480MHz。 DTCM地…...

半连接转内连接 | OceanBase SQL 查询改写
查询优化器是关系型数据库系统的核心模块,是数据库内核开发的重点和难点,也是衡量整个数据库系统成熟度的“试金石”。为了帮助大家更好地理解 OceanBase 查询优化器,我们撰写了查询改写系列文章,带大家更好地掌握查询改写的精髓&…...

Git使用经历
目录 1、先创建文件夹 2、仓库初始化 3、配置gitee用户名和密码 4、克隆指定仓库的中指定分支到本地仓库 5、查看当前所在分支、切换分支 6、查看状态,判断是否有修改 7、把更新的内容添加到缓存区 8、把缓存区的数据提交 9、把数据推送到远程仓库 10、把…...

永磁同步电机控制算法-自适应带宽LADRC转速控制器
一、原理介绍 设计了自适应带宽 LADRC 控制方法,继承了 LADRC 优点的同时,加入自适应带宽控制,提出运用 Softsign 函数设计带宽自适应函数,根据电机转速自动调节控制带宽,解决了永磁同步电机在复杂且多变的环境下受到…...

基于springboot+vue实现的博物馆游客预约系统 (源码+L文+ppt)4-127
摘 要 旅游行业的快速发展使得博物馆游客预约系统成为了一个必不可少的工具。基于Java的博物馆游客预约系统旨在提供高效、准确和便捷的适用博物馆游客预约服务。本文讲述了基于java语言开发,后台数据库选择MySQL进行数据的存储。该软件的主要功能是进行博物馆游客…...
LeetCode 1705.吃苹果的最大数目:贪心(优先队列) - 清晰题解
【LetMeFly】1705.吃苹果的最大数目:贪心(优先队列) - 清晰题解 力扣题目链接:https://leetcode.cn/problems/maximum-number-of-eaten-apples/ 有一棵特殊的苹果树,一连 n 天,每天都可以长出若干个苹果。在第 i 天,…...
vim多窗格
vim打开文件分为三个阶段:buffer、window与tab buffer就是在同一个界面打开的文件window就是使用水平分割与垂直分割的窗口tab则是可以是上述两者的总集合 buffer :e filename在已打开文件的界面中再打开一个新文件,显示这个新文件,原文件被隐…...

ubuntu paddle ocr 部署bug问题解决
ubuntu paddle ocr 部署会出现异常报错。 尝试安装以下版本: pip install paddlepaddle2.5.2 -i https://pypi.tuna.tsinghua.edu.cn/simpl 助力快速掌握数据集的信息和使用方式。 数据可以如此美好!...

OpenFeign快速入门 示例:黑马商城
使用起因 之前我们利用了Nacos实现了服务的治理,利用RestTemplate实现了服务的远程调用。这样一来购物车虽然通过远程调用实现了调用商品服务的方法,但是远程调用的代码太复杂了: 解决方法 并且这种调用方式比较复杂,一会儿远程调用,一会儿本地调用。 因…...

【C++】ceil 和 floor 函数的实现与分析
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯ceil 和 floor 函数的基础介绍1. ceil 函数定义与功能示例代码输出结果功能分析使用场景 2. floor 函数定义与功能示例代码输出结果功能分析使用场景 💯自行实现…...

zabbix监控山石系列Hillstone配置模版(适用于zabbix6及以上)
监控项: 触发器: 监控数据:...

在瑞芯微RK3588平台上使用RKNN部署YOLOv8Pose模型的C++实战指南
在人工智能和计算机视觉领域,人体姿态估计是一项极具挑战性的任务,它对于理解人类行为、增强人机交互等方面具有重要意义。YOLOv8Pose作为YOLO系列中的新成员,以其高效和准确性在人体姿态估计任务中脱颖而出。本文将详细介绍如何在瑞芯微RK3588平台上,使用RKNN(Rockchip N…...

CTFHub disable_functions通关
LD_PRELOAD 来到首页发现有一句话直接就可以用蚁剑连接 根目录里有/flag但是不能看;命令也被ban了就需要绕过了 绕过工具在插件市场就可以下载 如果进不去的话 项目地址: #本地仓库;插件存放 antSword\antData\plugins 绕过选择 上传后我们点进去可以看到多了一个绕过的文件;…...

Chromium GN 目标指南 - view_example 计数器示例 (七)
1. 引言 在前面的文章中,我们学习了如何在 views_examples 中添加自定义 Button 示例。在本篇文章中,我们将继续探索 Views 框架的应用,创建一个简单的计数器示例,以学习如何使用 Label 和 Button 控件进行交互,以及如…...
一步一步写线程之十六线程的安全退出之二例程
一、说明 在一篇分析了多线程的安全退出的相关机制和方式,那么本篇就针对前一篇的相关的分析进行举例分析。因为有些方法实现的方法类似,可能就不一一重复列举了,相关的例程主要以在Linux上的运行为主。 二、实例 线程间的同步,…...

【Linux系列】Shell 脚本中的条件判断:`[ ]`与`[[ ]]`的比较
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

ArcGIS+MIKE21 洪水淹没分析、溃坝分析,洪水淹没动态效果
洪水淹没分析过程: 一、所需数据: 1.分析区域DEM数据 二、ArcGIS软件 1.提取分析区域DEM(水库坝下区域) 2.DEM栅格转点 3.计算转换后几何点的x和y坐标值(精度20、小数位3) 4.导出属性表,形式…...
Git 的基本概念和使用
Git是一个分布式版本控制系统,它可以帮助开发人员追踪和管理代码的修改。下面是Git的基本概念和使用方式的解释: 仓库(Repository):Git使用仓库来存储代码和版本历史记录。仓库可以位于本地计算机上,也可以…...
*【每日一题 基础题】 [蓝桥杯 2024 省 B] 好数
[蓝桥杯 2024 省 B] 好数 好数 一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位……)上的数字是奇数,偶数位(十位、千位、十万位……)上的数字是偶数,我们就称之为“好数”。 给定一…...

对中文汉字排序的方法总结
写在前面 在各个系统中,都随处可见根据某个字段进行升序(ASC)或降序(DESC)进行排序展示。但进行中文汉字排序和查找的时候,对中文汉字的排序和查找结果往往都是错误的。 为了尽量提供全面的解决方法,本文会从各个层面出发告知有需要的人对应…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
【深尚想】TPS54618CQRTERQ1汽车级同步降压转换器电源芯片全面解析
1. 元器件定义与技术特点 TPS54618CQRTERQ1 是德州仪器(TI)推出的一款 汽车级同步降压转换器(DC-DC开关稳压器),属于高性能电源管理芯片。核心特性包括: 输入电压范围:2.95V–6V,输…...