快速应用RT-Thread IAP升级功能

参考官方文档

文档地址

步骤一准备bootload

进入网站选择升级的芯片配置好,下载bootloader
地址
填写分区配置
在这里插入图片描述
在这里插入图片描述

填写加密等配置

在这里插入图片描述
将 Bootloader 下载烧录到片内,烧录地址就是我们正常的启始地址0x08000000

APP项目设置及代码修改

下载RTT源码

下载地址

进入如下目录:rt-thread/bsp选择合适的平台,我这里选择rt-thread/bsp/stm32/stm32f103-atk-warshipv3
在这里插入图片描述
进入目录,右键在这打开env
在这里插入图片描述
键入命令:menuconfig回车
进入如下界面
在这里插入图片描述
SPACE选中ota
在这里插入图片描述
回车键进入二级菜单,选中如下
在这里插入图片描述
他会自动选择如下的FAL组件
在这里插入图片描述
选中如下,开启片内flash
在这里插入图片描述
通过键,选择Save,回车键,回车键,即可保存更改。
在这里插入图片描述
键入scons --target=mdk5+回车键,生成工程!
KEIL生成bin文件设置

fromelf --bin !L --output rtthread.bin

在这里插入图片描述

修改main.c

增加以下代码,设置中断向量表偏移

#define RT_APP_PART_ADDR	0x8040000/**< 目前APP*/

#define APP_VERSION		"V1.0.0"
/**
 * Function    ota_app_vtor_reconfig
 * Description Set Vector Table base location to the start addr of app(RT_APP_PART_ADDR).
*/
static int ota_app_vtor_reconfig(void)
{
    #define NVIC_VTOR_MASK   0x3FFFFF80
    /* Set the Vector Table base location by user application firmware definition */
    SCB->VTOR = RT_APP_PART_ADDR & NVIC_VTOR_MASK;

    return 0;
}
INIT_BOARD_EXPORT(ota_app_vtor_reconfig);

增加以下代码支持FAL,并初始化

#include "fal.h"//!<增加FAL组件
/*main.c中初始化FAL组件*/
fal_init();
/*打印版本号*/
rt_kprintf("The Current Vsersion is :%s\n",APP_VERSION);

增加分区表配置文件

此文件可有FAL源码中例程里找到,复制一份并修改即可

/*
 * File      : fal_cfg.h
 * This file is part of FAL (Flash Abstraction Layer) package
 * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-05-17     armink       the first version
 */

#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_

#include <rtconfig.h>
#include <board.h>

#define NOR_FLASH_DEV_NAME             "norflash0"/**< 未使用 */

/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev stm32f1_onchip_flash;
//extern struct fal_flash_dev nor_flash0;/**< 未使用 */

/* flash device table */
#define FAL_FLASH_DEV_TABLE                                          \
{                                                                    \
    &stm32f1_onchip_flash,                                           \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE                                                               \
{                                                                                    \
	{FAL_PART_MAGIC_WORD,   "bl",   	  "stm32_onchip",          0,  128*1024, 0}, \
    {FAL_PART_MAGIC_WORD,   "download",   "stm32_onchip",   128*1024,  128*1024, 0}, \
    {FAL_PART_MAGIC_WORD,   "app",     	  "stm32_onchip",   256*1024,  128*1024, 0}, \
	{FAL_PART_MAGIC_WORD,   "factory",    "stm32_onchip",   384*1024,  128*1024, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */

#endif /* _FAL_CFG_H_ */

依据分区表的配置修改flash驱动

/*
 * File      : fal_flash_stm32f1_port.c
 * This file is part of FAL (Flash Abstraction Layer) package
 * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-01-26     armink       the first version
 */

#include <fal.h>

#include <stm32f1xx.h>

/* base address of the flash sectors */

#define FLASH_PAGE_0_ADDR			 ((uint32_t)0x08000000)	/* 物理flash原始起始页地址 */
#define FLASH_START_PAGE_ADDR		 FLASH_PAGE_0_ADDR		/* 分区表起始地址 */
#define CURRENT_PART_START_PAGE	 	 ((FLASH_START_PAGE_ADDR-FLASH_PAGE_0_ADDR)/FLASH_PAGE_SIZE)	/* 当前分区实际物理起始页 */
#define FLASH_PAGE_NUM_MAX			 ((uint32_t)255+1)
/**
 * Get the sector of a given address
 *
 * @param address flash address
 *
 * @return The sector of a given address
 */
static uint32_t stm32_get_sector(uint32_t Startaddress ,size_t size ,uint32_t *get_pages)
{
		/*记录起始页与结束页*/
    	uint32_t Startpage = 0,Endpage = 0;
		/*搜索完成标记*/
		uint8_t start_page_flag = 0,end_page_flag = 0;
		/*计算起始地址所在页*/
		if(Startaddress >= stm32f1_onchip_flash.addr)
		{
				for(uint32_t i = 0; i < FLASH_PAGE_NUM_MAX;i++)
				{
						/*计算首地址所在页*/
						if(start_page_flag == 0)
						{
							if((i*FLASH_PAGE_SIZE+FLASH_PAGE_0_ADDR+FLASH_PAGE_SIZE-1) >= Startaddress)
							{
								log_i("first erase page:%d",i);
								Startpage = i;
								start_page_flag = 1;
							}
						}
						/*计算尾地址所在页*/
						if(end_page_flag == 0)
						{
							if((i*FLASH_PAGE_SIZE+FLASH_PAGE_0_ADDR+FLASH_PAGE_SIZE-1) >= (Startaddress+size-1))
							{
								log_i("end erase page:%d",i);
								Endpage = i;
								end_page_flag = 1;
								break;
							}
						}
				}
		}
		else
		{
				/*地址非法*/
				*get_pages = 0;
				return Startpage;
		}
		/*计算地址范围内的页数*/
		*get_pages = Endpage-Startpage+1;

    return Startpage*FLASH_PAGE_SIZE+FLASH_PAGE_0_ADDR;
}

/**
 * Get the sector size
 *
 * @param sector sector
 *
 * @return sector size
 */
static uint32_t stm32_get_sector_size(uint32_t pages) 
{
	return pages*FLASH_PAGE_SIZE;	//!< 2K一页			
}
static int init(void)
{
    /* do nothing now */
		return 0;
}

static int read(long offset, uint8_t *buf, size_t size)
{
    size_t i;
    uint32_t addr = stm32f1_onchip_flash.addr + offset;
    for (i = 0; i < size; i++, addr++, buf++)
    {
        *buf = *(uint8_t *) addr;
    }

    return size;
}

static int write(long offset, const uint8_t *buf, size_t size)
{
    size_t i;
    uint32_t read_data;
    uint32_t addr = stm32f1_onchip_flash.addr + offset;

    HAL_FLASH_Unlock();
    __HAL_FLASH_GET_FLAG(
    FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR
            | FLASH_FLAG_OPTVERR);
	uint16_t data = 0;
    for (i = 0; i < size; i++)
    {
        /* write data */
		log_i("write addr:0x%04X",addr);
		data = *(buf+i);
		if((i+1) < size)
		{
				i++;
				data |= ((uint16_t)*(buf+i)<<8);
		}
		else
		{
				data &= 0x00FF;
		}
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD ,addr, data);
		read_data = *(uint16_t *) addr;
		addr += 2;
        
        /* check data */
        if (read_data != data)
        {
			log_i("data unmatched read data:%d",read_data);
            return -1;
        }
    }
    HAL_FLASH_Lock();

    return size;
}

static int erase(long offset, size_t size)
{
    HAL_StatusTypeDef flash_status;
    size_t erased_size = 0;
    
    uint32_t addr = stm32f1_onchip_flash.addr + offset;
	FLASH_EraseInitTypeDef erase_config = {0};
	uint32_t erasepages = 0;
	uint32_t error;
    /* start erase */
    HAL_FLASH_Unlock();
    __HAL_FLASH_GET_FLAG(
    FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR
            | FLASH_FLAG_OPTVERR);
    /* it will stop when erased size is greater than setting size */
		
	/*擦除页地址*/
	erase_config.PageAddress = stm32_get_sector(addr ,size ,&erasepages);
	log_i("erase page addr:0x%08X,PAGES:%d",erase_config.PageAddress,erasepages);
	
	/*所属BANK*/
	erase_config.Banks = FLASH_BANK_1;
	/*按页擦除*/
	erase_config.TypeErase = FLASH_TYPEERASE_PAGES;
	/*擦除页数量*/
	erase_config.NbPages = erasepages;
	log_i("erase page number:%d",erasepages);
	flash_status = HAL_FLASHEx_Erase(&erase_config, &error);
	if (flash_status != HAL_OK)
	{
		log_i("erase error");
		return -1;
	}
	erased_size += stm32_get_sector_size(erasepages);
	log_i("erase size:%d",erased_size);
	
    HAL_FLASH_Lock();

    return size;
}

const struct fal_flash_dev stm32f1_onchip_flash =
{
    .name       = "stm32_onchip",
    .addr       = FLASH_START_PAGE_ADDR,
    .len        = 512*1024,
    .blk_size   = FLASH_PAGE_SIZE,
    .ops        = {init, read, write, erase},
    .write_gran = 32
};
  • 完成,读,写,擦除的调用接口即可!
  • 编写的依据自己的芯片,可能每个芯片以页区分,也有以扇区区分,块区分不尽相同,各自编写。
  • 以上编写以512KBflash总大小,2KB为一页,16bit单次写入,按页擦除,按字节读取,编写的驱动

第一次烧录进单片机

修改分散加载文件

在这里插入图片描述
编译下载烧录,运行可以看到串口打印的信息
在这里插入图片描述

无法烧录的情况

确认以下
在这里插入图片描述

升级包文件准备及升级

第二次使用打包器打包

  • 修改下main.c中的版本号,改为V1.0.1任意即可,方便看出程序已升级
  • 编译,打包
    在这里插入图片描述

串口连接Xshell

在 msh 命令行中输入 ymodem_ota 命令后,点击鼠标右键,然后在菜单栏找到用 YMODEM 发送选项发送文件
在这里插入图片描述

备份区烧录

  1. 与app程序一致无需单独设置
  2. 编译后的bin文件同样使用打包器打包成rpl文件,因为打包器会对其压缩加密操作,否则无法使用
  3. rpl文件更改后缀名为xx.bin使用烧写器烧录进flash的factory分区起始地址
  4. 保持按下恢复出厂设置按键情况下,启动芯片会由bootload将factory分区恢复到app分区中
  5. 完成!

下载注意大小端问题以及flash中存放地址

预期写入 1 2 3 4 5依次存放在8020008往后中
在这里插入图片描述
在这里插入图片描述
最后的结果可以看出,高地址高位数据
地址8020009数据1
为小端模式

所以应该这样
在这里插入图片描述
测试flash正常命令:
参考FAL说明

fal erase 0 4096
fal write 8 1 2 3 4 5
fal read 0 64

在这里插入图片描述

重启软件即可升级完成!

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aron566

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值