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地…...
vue-axios+springboot实现文件流下载
前端vue代码: <template><div class"app-container documentation-container"><div><el-button type"primary" click"downloadFile(test.xlsx)">下载test.xlsx</el-button></div></div> …...
vue预览和下载 pdf、ppt、word、excel文档,文件类型为链接或者base64格式或者文件流,
** 方法1:word、xls、ppt、pdf 这些文件, 如果预览的文件是链接可以直接打开,可用微软官方的预览地址 ** <iframe width"100%" :src"textVisibleURl " id"myFramePPT" style"border: none;backgroun…...
GIS 文件格式 及 常规应用总结
文章目录 GIS 中常见的文件格式 以及 再次打开注意事项资源网站应用地图瓦片数据地形数据倾斜模型 QGS 应用矢量数据格式栅格数据格式数据库格式更改图层样式更改图层范围导出为不同分辨率图片导出矢量文件直接保存图层通过打印布局导出使用插件导出 tiff 图片前端处理方式 GIS…...
《Pytorch框架CV开发-从入门到实战》
目录 1.环境部署2.自动梯度计算张量 tensor3.线性回归4.逻辑回归6.人工神经网络的基本概念6.1 感知器6.2 激活函数6.3多层感知器6.4 反向传播算法——前向传播6.5 反向传播算法——反向传播6.6 反向传播算法——训练方法7.Pytorch基础数据集8.手写数字识别人工神经网络训练8.1 …...
element-ui的el-select多选同时获取label与value值
直接上代码: <!DOCTYPE html> <html><head><meta charset"utf-8"><!-- 引入 Element UI 的 CSS --><link rel"stylesheet" href"https://unpkg.com/element-ui/lib/theme-chalk/index.css"><…...
跨站请求伪造之基本介绍
一.基本概念 1.定义 跨站请求伪造(Cross - Site Request Forgery,缩写为 CSRF)漏洞是一种网络安全漏洞。它是指攻击者通过诱导用户访问一个恶意网站,利用用户在被信任网站(如银行网站、社交网站等)的登录状…...
干部大数据分析系统如何助力构建选人用人的逻辑框架
在当今信息化快速发展的时代,干部大数据分析系统作为一种创新的管理工具,正在逐步改变传统的选人用人方式。这一系统融合了大数据、人工智能等现代信息技术,为组织部门提供了一个强大的辅助决策工具,有助于构建更加科学、准确和公…...
今天最新早上好问候语精选大全,每天问候,相互牵挂,彼此祝福
1、朋友相伴,友谊真诚永不变!彼此扶持绿树荫,共度快乐雨后天!一同分享的表情,愿我们友情长存,一生相伴永相连! 2、人生几十年,苦累伴酸甜,风华不再茂,雄心非当…...
Android开发环境搭建和编译系统
1 工具使用 1.1 将dos格式的文件转换为unix格式文件 直接执行 dos2unix file 例如: dos2unix InotifyMon/AndroidManifest.xml 1.2 Linux Shell FTP使用 ftp <IP addr> 输入ID和password prompt off // 下载文件到本地 mget * 1.3 Linux sed 1.3.1 Linux命令之…...
autMan奥特曼机器人-autMan的PHP环境
直装版请自行安装php环境。 docker版本预置了php环境,如下图: 如果使用插件"test php"测试环境时,实时日志有报错如下: 可进入终端,输入两条命令 apk add curl apk add php-curl...
路径规划之启发式算法之二十:麻雀搜索算法(Sparrow Search Algorithm,SSA)
麻雀搜索算法(Sparrow Search Algorithm,SSA)是一种受麻雀觅食和反捕食行为启发的新型的群智能优化算法,它模拟了麻雀种群的觅食行为和反捕食行为的生物学群体特征。该算法由薛建凯在2020年首次提出,旨在解决全局优化问题,具有求解精度高、效率高等特点。 一、算法原理 S…...
Vue+element 回车查询页面刷新
问题描述: form 表单出查询条件需要实现 input 输入完成后键盘回车查询:keyup.enter“handleQuery”,如果 form 里只有一个input,回车没有触发事件,而是刷新页面,放两个input就没问题 问题原因࿱…...
为何页面搜索应避免左模糊和全模糊查询???
前言 在构建高效且可扩展的Web应用程序时,数据库查询的性能是影响用户体验的关键因素之一。特别是对于涉及大量数据的页面搜索功能,选择正确的查询方式不仅可以提升应用的速度,还能显著改善用户交互体验。 B-Tree索引与最左前缀匹配特性 1…...
源码分析之Openlayers中ZoomSlider滑块缩放控件
概述 ZoomSlider滑块缩放控件就是Zoom缩放控件的异形体,通过滑块的拖动或者点击滑槽,实现地图的缩放;另外其他方式控制地图缩放时,也会引起滑块在滑槽中的位置改变;即ZoomSlider滑块缩放控件会监听地图的缩放级别&…...
Cherno C++学习笔记 P46 箭头运算符
这一篇文章我们讲一下箭头运算符的使用。在之前的一些场景下,我们已经使用到了箭头运算符,这次我们可以更深入的聊一下箭头运算符应该如何使用,以及我们如何实现自己的箭头指针。 我们还是以一个最简单的Entity类举例: class En…...
项目转换微服务架构
文章目录 1.sun-dependencies引入SpringCloud的版本2. 创建sun-cloud-home微服务1.创建maven项目2.目录概览3.pom.xml4.application.yml5.application-prod.yml6.HomeApplicaion.java7.HomeController.java8.测试访问9.打包测试 3.创建sun-cloud-sku微服务1.磁盘将这个sun-clou…...
WebRTC搭建与应用(五)-Coturn踩坑记
WebRTC搭建与应用(五)-Coturn踩坑记 近期由于项目需要在研究前端WebGL渲染转为云渲染,借此机会对WebRTC等有了初步了解,在此记录一下,以防遗忘。 第五章 WebRTC搭建与应用(五)-Coturn踩坑记 文章目录 WebRTC搭建与应用(五)-Coturn踩坑记前…...
Uniapp 手机基座调试App 打包成Apk文件,并上传到应用商店
1.Uniapp手机基座调试App。 1.1 以下是我另一篇文章 讲解 uniapp连接手机基座调试App、 Hbuildx使用SUB运行到手机基座测试_hbuilder基座-CSDN博客 2.打包本地的uniapp项目为apk文件。 打包的方式有很多种,我们可以选择本地打包和远程云端打包两种方式。 我们在打包…...
【AI日记】24.12.24 kaggle 比赛 2-12
【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 工作 参加:kaggle 比赛 Regression with an Insurance Dataset时间:3 小时 读书 书名:我们能做什么 : 胡适与中国青年最真诚的分享时间:2 小时 律己 工作时…...
教师如何打造专属私密成绩查询系统?
期末的校园,被一种特殊的氛围所笼罩。老师们如同辛勤的工匠,精心打磨着每一个教学环节。复习阶段,他们在知识的宝库中精挑细选,把一学期的重点内容一一梳理,为学生们打造出系统的复习框架。课堂上,他们激情…...
【linux】NFS实验
NFS服务 NFS是Network File System(网络文件系统)的缩写。它是一种用于在计算机网络中共享文件和目录的协议。NFS允许计算机上的用户访问和操作远程计算机上的文件,就像访问本地文件一样。它使用客户端-服务端模型,其中客户端机器…...
ubuntu22.04安装PaddleX3
PaddleOCR 安装过程可以参考PaddleX本地安装教程 我的电脑环境配置: ubuntu22.04 cuda11.8(之前安装的是12.4没有匹配的paddle-gpu;这里改成11.8) 一、安装基础环境 1、 conda create -n ppx1 python3.10 2、 conda activate ppx1 3、…...
无标记动作捕捉系统如何赋能体育运动分析,推动体育科学发展?
随着技术的不断发展与社会的需要,健康、科学运动成为了大众关注的一个热词。在韩国首尔的中央大学,其生物运动临床康复实验室和运动训练中心就致力于通过生物力学分析来研究与运动相关的伤害,并通过定制科学的训练计划来帮助运动员改进他们的…...
JavaScript 标准内置对象——Array
1、构造函数 2、静态方法 // 从可迭代或类数组对象创建一个新的浅拷贝的数组实例 // arrayLike 想要转换成数组的类数组或可迭代对象 Array.from(arrayLike, mapFn, thisArg) Array.fromAsync(arrayLike, mapFn, thisArg) // 异步Array.isArray(value) // 判断传递的值是否是一…...
Python超能力:高级技巧让你的代码飞起来
文章一览 前言一、with1.1 基本用法1.2 示例自定义上下文管理器 二、条件表达式三、列表式推导式与 zip 结合 四、map() 函数(内置函数)map用于数据清洗1. 数据清洗:字母大小写规范2. filter() 函数 五、匿名函数 lambda5.1 lambda的参数&…...
move生态
move生态 Move 生态主要围绕着 Move 编程语言及其相关的区块链平台构建,这些平台旨在提供更高的安全性、可扩展性和开发者友好性。以下是关于 Move 生态的一些关键点: 1. 核心区块链平台 Aptos:Aptos 是一个 Layer 1 区块链,专注…...
使用插件时要注意
在使用插件时,需要注意一些关键事项,确保插件能够稳定、安全地工作,并且不会给系统带来风险或负担。以下是使用插件时需要注意的几个重要方面: 1. 插件来源与信任度 官方渠道与可靠来源:总是选择来自官方网站、知名平…...
JVM对象分配内存如何保证线程安全?
大家好,我是锋哥。今天分享关于【JVM对象分配内存如何保证线程安全?】面试题。希望对大家有帮助; JVM对象分配内存如何保证线程安全? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在JVM中,对象的内存分配…...
ApacheStruts2 目录遍历与文件上传漏洞复现(CVE-2024-53677,S2-067)(附脚本)
0x01 产品描述: Apache Struts 2 是一个用于JAVA的MVC框架,它用于快速开发web应用。它的设计目标是使得开发者能够更容易的处理web应用的展现层,数据层,和业务层。0x02 漏洞描述: CVE-2024-53677 漏洞的根本原因是 Struts 框架中不安全的文件上传处理机制。攻击者利用 CVE…...
Scala字符串连接方法—mkString—用法详解
Scala字符串连接方法—mkString—用法详解 在 Scala 中,mkString 是集合(如数组、列表、字符串等)的一种方法,用于将集合中的元素连接成一个字符串。 def mkString(sep: String): Stringdef mkString(start: String, sep: String…...
[实战]Spring Boot启动卡在Root WebApplicationContext initialization completed in
Spring Boot启动 打印Root WebApplicationContext: initialization completed in…这行日志完成后需要等很长时间才能真正启动完成。 分析一下发现是连接某个机器的MySQL就会出现这种情况。使用客户端软件连接MySQL时也很慢,但连接完成后执行MySQL各种语句非常看。…...
什么样的LabVIEW控制算自动控制?
自动控制是指系统通过预先设计的算法和逻辑,在无人工干预的情况下对被控对象的状态进行实时监测、决策和调整,达到预期目标的过程。LabVIEW作为一种图形化编程工具,非常适合开发自动控制系统。那么,什么样的LabVIEW控制算作“自动…...
xshell下载和安装(超详细)
参考:https://blog.csdn.net/hffh123/article/details/135885175 一、xshell官网下载 下载官网:https://www.xshell.com/zh/free-for-home-school/ 二、安装步骤 (一)、直接打开.exe文件 (二)、点击下一步ÿ…...
NS3学习——tcpVegas算法代码详解(2)
NS3学习——tcpVegas算法代码详解(1)-CSDN博客 目录 4.TcpVegas类中成员函数 (5) CongestionStateSet函数 (6) IncreaseWindow函数 1.检查是否启用 Vgas 2.判断是否完成了一个“Vegas 周期” 2.1--if:判断RTT样本数量是否足够 2.2--e…...
PyTorch 神经网络回归(Regression)任务:关系拟合与优化过程
PyTorch 神经网络回归(Regression)任务:关系拟合与优化过程 本教程介绍了如何使用 PyTorch 构建一个简单的神经网络来实现关系拟合,具体演示了从数据准备到模型训练和可视化的完整过程。首先,利用一维线性空间生成带噪…...
链原生 Web3 AI 网络 Chainbase 推出 AVS 主网, 拓展 EigenLayer AVS 场景
在 12 月 4 日,链原生的 Web3 AI 数据网络 Chainbase 正式启动了 Chainbase AVS 主网,同时发布了首批 20 个 AVS 节点运营商名单。Chainbase AVS 是 EigenLayer AVS 中首个以数据智能为应用导向的主网 AVS,其采用四层网络架构,其中…...
es 3期 第18节-分页查询使用避坑的一些事
#### 1.Elasticsearch是数据库,不是普通的Java应用程序,传统数据库需要的硬件资源同样需要,提升性能最有效的就是升级硬件。 #### 2.Elasticsearch是文档型数据库,不是关系型数据库,不具备严格的ACID事务特性ÿ…...
linux检测硬盘
通过fdisk 查看显示所有磁盘或闪存的信息 fdisk -l /dev/sd*使用 badlocks检查 linux 硬盘上的坏道/坏块。也可以修复坏道,但仅限于逻辑坏道,物理坏道只能更换硬盘 badblocks -s -v /dev/vdb1 > /badblocks-vdb1.txt tail -f badblocks-vdb1.txt #检…...
Unity3d 基于UGUI和VideoPlayer 实现一个多功能视频播放器功能(含源码)
前言 随着Unity3d引擎在数字沙盘、智慧工厂、数字孪生等场景的广泛应用,视频已成为系统程序中展示时,不可或缺的一部分。在 Unity3d 中,我们可以通过强大的 VideoPlayer 组件和灵活的 UGUI 系统,将视频播放功能无缝集成到用户界面…...
Ubuntu22.04 LTS 安装nvidia显卡驱动
准备跑老师给定的Github上的多模态源码,但是用了这么久ubuntu还没有尝试过安装nvidia驱动,好在也是一次成功,于是记录下来。 借鉴的是Ubuntu22.04安装显卡驱动(高速、避错版)-CSDN博客这篇文章,按照流程来基本没有问题,不过个人觉得有些步骤比较冗余,所以记录下来 主要…...
Linux编程(清华大学出版社2019年1月第1版)第5章课后作业
5.1 对于执行在时间上有重叠的逻辑流,称为并发流,并发流是并发的 并发不并发并发 5.2 几个箭头几个状态转换关系,箭头上写了可能原因。 在就绪状态不会执行指令,不会有IO请求或主动wait的情况,不会有从就绪状态到阻…...
相机雷达外参标定综述“Automatic targetless LiDAR–camera calibration: a survey“
相机雷达外参标定综述--Automatic targetless LiDAR–camera calibration: a survey 前言1 Introduction2 Background3 Automatic targetless LiDAR–camera calibration3.1 Information theory based method(信息论方法)3.1.1 Pairs of point cloud and image attributes(属性…...
JSON 系列之1:将 JSON 数据存储在 Oracle 数据库中
本文为Oracle数据库JSON学习系列的第一篇,讲述如何将JSON文档存储到数据库中,包括了版本为19c和23ai的情形。 19c中的JSON 先来看一下数据库版本为19c时的情形。 创建表colortab,其中color列的长度设为4000。若color的长度需要设为32767&a…...
分布式专题(10)之ShardingSphere分库分表实战指南
一、ShardingSphere产品介绍 Apache ShardingSphere 是一款分布式的数据库生态系统, 可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。Apache ShardingSphere 设计哲学为 Database Plus,旨在…...
支付宝订单码支付
1.订单码支付,首先下载官方网站提供的sdk包到你的项目中。 2.选择控制器复制官方文档的获取二维码相关的代码示例。打开sdk包中v2的index.php文件,这个才是你选择语言的具体代码。 3.引用里面所需要的类文件,文件下载到你的项目中后…...
使用 Django 和 AWS ECR 实现容器化应用的管理
在现代云原生应用的开发和部署中,容器化技术已经成为主流。Amazon Elastic Container Registry (ECR) 是一种完全管理的 Docker 容器注册表服务,可以与 Amazon ECS、EKS 和其他容器服务无缝集成。在这篇文章中,我们将介绍如何使用 Django 和 AWS ECR 实现集成管理,包括创建、更…...
DeepWalk 原理详解
概述: DeepWalk 是一种流行的图嵌入方法,用于学习图结构数据中节点的低维表示。它通过将图的节点视作序列数据,利用自然语言处理中的技术(类似于word2vec算法)来捕捉节点间的关系,可以帮助我们理解和利用图…...
深入理解批量归一化(BN):原理、缺陷与跨小批量归一化(CmBN)
在训练深度神经网络时,批量归一化(Batch Normalization,简称BN)是一种常用且有效的技术,它帮助解决了深度学习中训练过程中的梯度消失、梯度爆炸和训练不稳定等。然而,BN也有一些局限性,特别是在…...
基于Spring Boot的雅苑小区管理系统
一、系统背景与意义 随着信息化技术的快速发展,传统的小区物业管理方式已经难以满足现代居民对于高效、便捷服务的需求。因此,开发一款基于Spring Boot的小区管理系统显得尤为重要。该系统旨在通过信息化手段,实现小区物业管理的智能化、自动…...