iis6建设网站浏览,东莞市网站推广,网站简历导出,怎么自己电脑做网站服务器这篇文章分享一个简单的串口IAP Demo#xff0c;实现使用串口更新我们自己的App程序。 目录 一、IAP简介二、Stm32CubeMx配置三、Boot代码及配置1、代码2、配置 四、App代码及配置1、代码2、配置 五、效果展示 一、IAP简介
IAP介绍可以在网上找找#xff0c;相关资料很多实现使用串口更新我们自己的App程序。 目录 一、IAP简介二、Stm32CubeMx配置三、Boot代码及配置1、代码2、配置 四、App代码及配置1、代码2、配置 五、效果展示 一、IAP简介
IAP介绍可以在网上找找相关资料很多如 https://blog.csdn.net/ba_wang_mao/article/details/110401656
二、Stm32CubeMx配置
1、RCC开启外部高速时钟略 2、配置STLink调试口略 3、配置串口方便调试输出略 4、配置工程名、生成路径之后生成工程(略 1-4步的基础配置可以参考前面的文章《STM32基础工程模板创建》 Boot和App的工程配置是一样的配置好时钟、usart1即可
三、Boot代码及配置
1、代码
#include stdio.h
#include string.h
#include stdio.h#define NVIC_VectTab_RAM_Start ((uint32_t)0x20000000) //RAM起始地址
#define NVIC_VectTab_RAM_End ((uint32_t)0x20020000) //RAM结束地址大小为128K根据自己的实际芯片大小修改
#define NVIC_VectTab_FLASH ((uint32_t)0x08000000) //Flash起始地址
#define BOOT_SIZE 0x3000 //Boot大小12KB0--12页共128页
#define ApplicationAddress (NVIC_VectTab_FLASH BOOT_SIZE) //App的起始地址
#define USER_FLASH_PAGES 52 //App所占大小52KB
//#define FLASH_PAGE_SIZE 1024 //每页所占的字节大小和系统库定义重复了注释掉
#define UPDATE_CMD update //升级擦除指令
#define FLASH_USER_END_ADDR \((FLASH_PAGE_SIZE*USER_FLASH_PAGES)ApplicationAddress) //App结束地址typedef void (*iapfun)(void);
void SystemClock_Config(void);int fputc(int ch, FILE *f)
{HAL_UART_Transmit(huart1, (uint8_t *)ch, 1, 0xffff);return ch;
}iapfun jump2app;
unsigned int count2 0;
unsigned char datatemp[256] {0};
unsigned char boot_flag 0;
unsigned char time_out_flag 0;int main(void)
{unsigned char i;HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART1_UART_Init();printf(boot start\r\n);printf(input \update\ to erasure user flash, or wait 10s to start user app\r\n);for(i 0; i10; i){//上电后每秒阻塞接收升级指令连续10秒未收到则跳转App10秒内收到则接收App数据并写入HAL_UART_Receive(huart1, datatemp, 256, 1000); if(strstr((const char *)datatemp, UPDATE_CMD) ! NULL){// 擦除App区域FLASH_EraseInitTypeDef EraseInitStruct;unsigned int PageError;HAL_FLASH_Unlock();EraseInitStruct.TypeErase FLASH_TYPEERASE_PAGES;EraseInitStruct.PageAddress ApplicationAddress;EraseInitStruct.NbPages USER_FLASH_PAGES;if(HAL_FLASHEx_Erase(EraseInitStruct, PageError) ! HAL_OK){HAL_FLASH_Lock();printf(Erase fail at:0x%x\n\r,PageError);return 0;}HAL_FLASH_Lock();boot_flag 1;printf(Erase OK\n\r); break; }}if(boot_flag 1){HAL_StatusTypeDef temp;unsigned int Address;unsigned int data_32;unsigned char j 0;printf(ready to receive bin, please send in 30s\n\r);Address ApplicationAddress; temp HAL_UART_Receive(huart1, datatemp, 256, 30*1000); 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();for(i0; i64; i){data_32 *(unsigned int *)(datatemp[i2]);if(Address FLASH_USER_END_ADDR){if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, data_32)HAL_OK){Address Address 4;}else {HAL_FLASH_Lock();printf(write fail at: 0x%x\n\r, Address);return 0;} } }HAL_FLASH_Lock(); printf(write 256 btye OK: 0x%x\t%d\n\r,Address,j);//最后一包数据不足256字节时会接收超时防止app数据不完整不足256字节数据接收完以后处理一次下一次接收超时认为接收完成跳转Apptemp 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中的地址APP把中断向量表ApplicationAddress开始的位置而中断向量表前4字节存储的是栈顶地址这里的目的是判断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)){ // disable irq, if use this, must enable irq at app//__disable_irq(); //ApplicationAddress4放的是中断向量表的第二项“复位地址”__set_MSP(*(unsigned int *)ApplicationAddress); jump2app(iapfun)*(unsigned int *)(ApplicationAddress4);jump2app(); }else{printf(no user app\n\r);return 0;}}while (1){}
}2、配置 四、App代码及配置
1、代码
#include stdio.h#define NVIC_VectTab_FLASH ((uint32_t)0x08000000) //Flash起始地址
#define BOOT_SIZE 0x3000 //Boot大小void SystemClock_Config(void);
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(huart1, (uint8_t *)ch, 1, 0xffff);return ch;
}int main(void)
{uint32_t Count 0;/* 设置中断向量偏移地址 */SCB-VTOR NVIC_VectTab_FLASH | BOOT_SIZE;HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART1_UART_Init();printf(\n\rapp start\n\r);while (1){HAL_Delay(10);if(Count%100 0){printf(this is app!\t%d\n\r,Count/100);}Count;}
}2、配置 //添加这条命令生成bin文件
$K\ARM\ARMCC\bin\fromelf.exe --bin --outputBin\L.bin !L五、效果展示
1、先使用Keil将Boot程序烧录进单片机串口提示请在10s内输入升级命令 2、串口发送“update”命令提示成功在30s内发送bin文件 3、配置串口发送延时为100ms.因为stm32是接收一包写一包的比较耗时。 4、选择并发送文件开始打印接收升级日志 5、全部接收完成后会跳转到App并打印App内的日志