> 文章列表 > stm32cubemx IAP升级(一)

stm32cubemx IAP升级(一)

stm32cubemx IAP升级(一)

stm32cubemx IAP升级- Bootloader的制作

板卡:Nucleo-L412
平台:macbook pro
工具:vscode stm32cubemx stm32cubeProgramer cmake toolchain

分区

L412 自带128K的flash,所以我们可以这样分区,
printf(“|============ flash pration table ============|\\r\\n”);
printf(“| name | offset | size |\\r\\n”);
printf(“|---------------------------------------------|\\r\\n”);
printf(“| bootloader | 0x08000000 | 0x00005000 20K | \\r\\n”);
printf(“| setting | 0x08005000 | 0x00002000 8K |\\r\\n”);
printf(“| App | 0x08007000 | 0x0000C800 50K |\\r\\n”);
printf(“| download | 0x08013800 | 0x0000C800 50K |\\r\\n”);

bootloader从0x08000000-0x08005000 大小20K
setting 从0x08005000-0x08007000 大小08K
App 从0x08007000-0x08013800大小50K
Download 从0x08013800-0x08020000大小50k

整体思路

Bootloader从0x08000000地址运行,而App程序从地址0x8007000运行。
App运行时,可通过iic或者uart接收到上位机升级的指令。App接收到要升级的程序,存在Download分区,并要setting区升级标志位置为1,重启。bootloader从Setting读取升级标志位,如果升级位为1,从Download分区copy数据到App区,copy完成后跳转到0x08007000地址,实现App的升级。

Stm32cubemx配置

1、设置时钟源跟配置时钟树,这个根据自己的平台配置即可。
2、配置一路串口,用作打印用。
3、配置一路定时器,用于改变led灯闪烁频率,来区分正常启动还是升级的指示灯。
4、生成代码选择Makefile,因为一直做linux开发,实在用不惯keil。

Bootloader代码

1、开机打印分区信息

void print_text_message(void)
{#ifdef USER_APPLICATION_CODE   printf("|------------- Enter Application -------------|\\r\\n");#endif#ifdef USER_BOOTLOADER_CODE printf("|------------- Enter BootLoader --------------|\\r\\n");#endifprintf("\\r\\n");printf("Version: %s %s\\r\\n",APPCATION_VERSION_DATE,APPCATION_VERSION_TIME);printf("\\r\\n");printf("|----------L412 flash toal size 128K----------|\\r\\n");printf("\\r\\n");printf("|============ flash pration table ============|\\r\\n");printf("| name       | offset     | size              |\\r\\n");printf("|---------------------------------------------|\\r\\n");printf("| bootloader | 0x08000000 | 0x00005000   20K  | \\r\\n");printf("| setting    | 0x08005000 | 0x00002000   8K   |\\r\\n");printf("| App        | 0x08007000 | 0x0000C800   50K  |\\r\\n");printf("| download   | 0x08013800 | 0x0000C800   50K  |\\r\\n");printf("|=============================================|\\r\\n");
}

其实IAP升级是两个工程,两个工程里都有自己的Makefile。而有一部分代码是两个工程共用的,所以我们可以将共用代码放在另外一个目录里,在Makefile里引用或者编译成静态库即可。
整个工程的代码架构是这样的。Common里即是boot跟app共用的代码。
stm32cubemx IAP升级(一)
2、重定向printf函数 main.c里添加

#ifdef USE_UART_PRINTF  //Uart使用
int _write(int fd, char *ch, int len)
{HAL_UART_Transmit(&huart1, (uint8_t*)ch, len, 0xFFFF);return len;
}
#endif#ifdef USE_SVO_PRINTF //Swv log使用
int _write(int file, char *ptr, int len)
{int DataIdx;for (DataIdx = 0; DataIdx < len; DataIdx++){ITM_SendChar(*ptr++);       // 把printf函数重定向到ITM_SendChar}return len;
}
#endif

3、定时器
定时器开启函数 : HAL_TIM_Base_Start_IT(&htim2);
定时器回调函数:

led_freq为LED_TOGGLE_100_MS时 100ms闪烁一次
LED_TOGGLE_500_MS 时500ms闪烁一次int led_cnt = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if (htim->Instance == htim2.Instance){if (led_freq == LED_TOGGLE_100_MS){HAL_GPIO_TogglePin(UserLed_GPIO_Port,UserLed_Pin);led_cnt = 0;}else if (led_freq == LED_TOGGLE_500_MS){if (led_cnt == LED_TOGGLE_500_MS){HAL_GPIO_TogglePin(UserLed_GPIO_Port,UserLed_Pin);led_cnt = 0;}}led_cnt++;}
}

3、读取升级标志位:

system_info_get_update_flag(&update_flag);MI_BOOL system_info_get_update_flag(MI_U8 *flag)
{MI_SystemInfo system_info;memset(&system_info,0,sizeof(system_info));stm32_flash_read(SYSTEM_INFO_START_ADDR,(uint8_t *)&system_info,sizeof(system_info));*flag = system_info.update_flag;return MI_TRUE;
}

升级标志位,是结构体形式写进0x08005000地址的,所以读的时候按一个字节从0x08005000以结构体形式再读出来即可。

/*** 系统信息结构体
*/
typedef struct system_info
{/* data */MI_CHAR model_name[64];MI_CHAR band_name[12];MI_CHAR soft_version[36];MI_CHAR settings_version[36];MI_CHAR app_version[36];MI_CHAR boot_version[36];MI_U32 build_date;MI_U32 build_time;MI_U8  update_flag;MI_GainMuteInfo gain_mute_info;}MI_SystemInfo;MI_BOOL stm32_flash_read(MI_U32 dest_addr, MI_U8* buff, MI_U32 Len)
{MI_U32 i;for(i = 0; i < Len; i++){buff[i] = *(__IO MI_U8*)(dest_addr + i);}/* Return a valid address to avoid HardFault */return 0;
}

main.c读取时代码如下:

 system_info_get_update_flag(&update_flag);//create_setting_data();if (update_flag == SYSTEM_UPDATE){// new Copy Application bin and updateHAL_TIM_Base_Start_IT(&htim2);printf("Now Need copy Application bin and Update\\r\\n");HAL_Delay(1000);printf("\\r\\n");led_freq = LED_TOGGLE_100_MS;copy_download_to_app();printf("\\r\\n");printf("update success,and go to Application\\r\\n");//升级成功后,将升级标志位清0system_info_set_update_flag(SYSTEM_NO_UPGRADE);led_freq = LED_TOGGLE_500_MS;HAL_Delay(4000);jumpApplication();}else if (update_flag == SYSTEM_NO_UPGRADE){printf("\\r\\n");printf("Now go to Application ,please wait! \\r\\n");printf("\\r\\n");HAL_Delay(1000);jumpApplication();}Copy数据代码MI_BOOL copy_download_to_app(void)
{MI_U8 buffer[1024] = {0};  //每次从download读1K字节,然后写入1KMI_U32 w_count = 0;MI_U32 w_len = 0;w_count = APP_SECTOR_SIZE / sizeof(buffer);w_len = sizeof(buffer);// 将App区域擦除stm32_erase_flash(APP_START_SECTOR_ADDR,APP_END_SECTOR_ADDR);for (int i = 0;i < w_count;i++){stm32_flash_read(DOWNLOAD_START_SECTOR_ADDR + (w_len * i),buffer,w_len);HAL_Delay(500);stm32_flash_write(APP_START_SECTOR_ADDR + (w_len * i),buffer,w_len);printf("update.............................%03d [100] \\r\\n",((i+1) * 100 /w_count));}return MI_TRUE;
}

4、App跳转

MI_VOID jumpApplication(MI_VOID)
{HAL_GPIO_DeInit(UserLed_GPIO_Port,UserLed_Pin);HAL_UART_MspDeInit(&huart1);HAL_TIM_Base_MspDeInit(&htim2); jump_app(APP_START_SECTOR_ADDR);
}uint8_t jump_app(uint32_t app_addr) 
{uint32_t jump_addr;jump_callback cb;if (((*(__IO uint32_t*)app_addr) & 0x2FFE0000 ) == 0x20000000) {  jump_addr = *(__IO uint32_t*) (app_addr + 4);  cb = (jump_callback)jump_addr;  __set_MSP(*(__IO uint32_t*)app_addr);  //__set_CONTROL(0);cb();return 1;} return 0;
}

5、修改STM32L412RBTxP_FLASH.ld

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 40K
RAM2 (xrw)      : ORIGIN = 0x10000000, LENGTH = 8K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 20K
}因为bootloader从0x08000000启动,大小为20K,故修改如上。

6、编译完成后,用stm32cubemxProgramer将Bootloader.bin烧录进板卡,地址填0x08000000.

整体代码在
https://download.csdn.net/download/weixin_43932857/87693349