stm32cubemx IAP升级(一)

news2024/10/5 1:13:27

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");
    #endif
    printf("\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共用的代码。
在这里插入图片描述
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 update

    HAL_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");

    //升级成功后,将升级标志位清0
    system_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字节,然后写入1K
    MI_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

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

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

相关文章

crypto-js AES-CTR 实现密文前缀式局部解密细节 踩坑点

项目有需求&#xff0c;长明文经过AES-CTR模式加密后&#xff0c;在解密的时候&#xff0c;密文不能直接得到&#xff0c;每次通过某些方法尝试后&#xff0c;只能得到一块密文&#xff08;按顺序&#xff09;&#xff0c;所以只能一块一块的拼接解密。在使用crypto-js这个库的…

WooCommerce可扩展性:如何扩大您的WooCommerce商店

有了合适的人和技术&#xff0c;WooCommerce可扩展性绝对是很大的&#xff01; 事实上&#xff0c;使用WooCommerce作为您的电子商务平台&#xff0c;您的在线商店的规模可以与您的目标和愿望一样大&#xff01; 根据自定义模板开发高性能品牌电子商务网站 全球超500万个电商…

高效办公——Excel表格-02篇(if函数常见用法 + 条件格式的使用)

高效办公——Excel表格-02篇&#xff08;if函数常见用法 条件格式的使用&#xff09;1. if单条件简单用法1.1 简单需求1.2 实现方法2. if多条件使用(if-else的情况)3. if多条件使用(if(A && B)的情况)3.1 简单需求3.2 实现需求4. if多条件使用(if(A || B)的情况)5. 条…

亚马逊云科技“三步走”,实现区块链应用的快速开发

作为数字技术的代表之一&#xff0c;区块链技术正在被越来越多的企业所重视&#xff0c;并被引入到各行业的数字化转型中。根据中国通信院数据显示&#xff0c;目前中国区块链应用场景主要以金融和互联网为主&#xff0c;但应用范围呈现不断拓展的态势&#xff0c;政务数据共享…

day10_oop

今日内容 零、 复习昨日 一、面向对象的概念 二、面向对象编程 三、内存图 零、 复习昨日 晨考复习… 一、作业 package com.qf.homework;import java.util.Arrays;/*** --- 天道酬勤 ---** author QiuShiju* desc* ----------------* 引用数据类型的默认初始值null*/ public …

Nginx 正向代理、方向代理、端口转发

正向代理就是客户端代理&#xff0c;代理客户端&#xff0c;服务端不知道实际发起请求的客户端 正向代理中&#xff0c;proxy和client一般同一个lan或者网络可达&#xff0c;server与client一般不可达&#xff08;缓存场景除外&#xff09; 正向代理类似一个跳板机&#xff0c…

下一个“AI王炸”,别只盯着OpenAI,DeepMind也在憋大招

过去几个月&#xff0c;OpenAI风头无两&#xff0c;各大科技公司争先恐后地跟进大语言模型&#xff08;LLM&#xff09;这一技术路线。 对比之下&#xff0c;OpenAI的老对手DeepMind&#xff0c;显得有些低调和沉默。微软靠OpenAI打了一场胜仗&#xff0c;而谷歌推出的Bard翻了…

【c++初阶】命名空间的定义

命名空间的定义一.缺陷二.namespace和::三.访问namespace四.一些注意1.工程里标准库的展开2.命名域的小技巧一.缺陷 在c语言中&#xff0c;如果我们同时定义一个全局变量和一个局部变量并且使用同一个名称的话&#xff0c;是可以编过的&#xff08;因为全局和局部是属于两个不同…

云原生_kubernetes(k8s)_pod介绍以及配置信息说明

目录 一、Pod介绍 1、Pod结构 2、Pod定义 二、Pod配置 1、基本配置 2、镜像拉取 3、启动命令 4、环境变量 5、端口设置 6、资源配额 一、Pod介绍 1、Pod结构 每个Pod中都可以包含一个或者多个容器&#xff0c;这些容器可以分为两类&#xff1a; 用户程序所在的容器&…

网络编程(第二章: TCPUDP基础模型)

TCP/UDP&#xff08;服务器、客户端源码&#xff09; [(12条消息) 网络编程(4.7作业)(TCP/UDP源代码)_m0_37565374的博客-CSDN博客]: 一. 套接字 socket 1.概念 最早的socket和消息队列、共享内存&#xff0c;管道一致只能实现一台主机中的多个进程间通信。后期加入了TCP/I…

云日记个人中心项目思路

验证昵称的唯一性 前台&#xff1a; 昵称文本框的失焦事件 blur 1. 获取昵称文本框的值 2. 判断值是否为空 如果为空&#xff0c;提示用户&#xff0c;禁用按钮&#xff0c;并return 3. 判断昵称是否做了修改…

一文详解:linux部署jenkins,一键构建并部署springboot至第三方服务器

目录 1、下载jenkins 2、 启动jenkins 3、访问jenkins 4、在当前Linux上安装maven 4.1、更新wget命令&#xff0c;支持https请求 4.2、下载maven 4.3、解压安装maven 4.4、配置maven环境变量 4.5、maven配置阿里云镜像 4.6、配置maven依赖下载的位置 5、Linux安装Gi…

Redis的使用【Redis】

一、缓存简介 缓存简介 二、缓存分类 缓存分类 三、常见缓存 常见缓存 四、Redis使用 Redis 有 5 ⼤基础数据类型&#xff1a; String——字符串类型Hash——字典类型List——列表类型Set——集合类型ZSet——有序集合类型 其中最常⽤的是字符串和字典类型。 1.字符…

Vulnhub靶场DC-1练习

目录0x00 准备0x01 主机信息收集0x02 站点信息收集0x03 漏洞查找与利用0x00 准备 下载链接&#xff1a;https://download.vulnhub.com/dc/DC-1.zip 介绍&#xff1a;There are five flags in total, but the ultimate goal is to find and read the flag in root’s home dir…

常见的DNS攻击与防御

DNS查询通常都是基于UDP的&#xff0c;这就导致了在查询过程中验证机制的缺失&#xff0c;黑客很容易利用该漏洞进行分析。DNS服务可能面临如下DNS攻击风险&#xff1a; 黑客伪造客户端源IP地址发送大量的DNS请求报文&#xff0c;造成DNS request flood攻击。黑客伪造成授权服…

Node.js安装与配置步骤

前言一、安装Node.js1.下载2.安装3.添加环境变量二、验证是否安装成功三、修改模块下载位置1.查看npm默认存放位置2.在 nodejs 安装目录下&#xff0c;创建 “node_global” 和 “node_cache” 两个文件夹3.修改默认文件夹4.测试默认位置是否更改成功四、设置淘宝镜像1.将npm默…

ARM Linux 内核启动2 ——C语言阶段

一、内核启动的C语言阶段 1 1、这一块的学习思路 (1) 抓大放小&#xff0c;不深究。 (2) 感兴趣可以就某个话题去网上搜索资料学习。 (3) 重点局部深入分析。 2、具体学习方法 (1) 顺着代码执行路径抓全。这是我们的学习主线。 (2) 对照内核启动的打印信息进行分析。 3、…

Ansible批量部署采集器

千台服务器部署采集器的时候用到了 Ansible&#xff0c;简单记录一下。 安装 Ansible pip install ansible yum install ansible –y在 /etc/ansible/hosts 中添加被管理组 &#xff0c;比如图中[web] 是组的名字。 执行ansible命令测试&#xff0c;通过hosts中定义的web组执…

君子签「数据签」正式上线,推动企业电子合同实现高效安全签署

近年来&#xff0c;从政府机关到企事业单位&#xff0c;数字化转型步伐明显加快。 在数字化的驱动下&#xff0c;在各行业的服务过程中&#xff0c;君子签对产品部署有了更深的沉淀和经验&#xff0c;通过不断打磨、升级产品&#xff0c;「数据签」产品于近日正式上线&#xf…

Word这样用,提高效率不加班

Word这样用&#xff0c;提高效率不加班 今天给大家分享23条Word文档的应用小技巧。对于大家来说&#xff0c;掌握些技巧能够效率百倍&#xff0c;何乐不为&#xff1f; 这些技巧是本人通过整理一直在用并且使用频率较高的&#xff0c;也希望能帮到大家。有兴趣的小伙伴可以自己…