IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32 HAL OTA 小白教程 -> 正文阅读

[嵌入式]STM32 HAL OTA 小白教程

作者:recommend-item-box type_blog clearfix

STM32 HAL OTA 小白教程

1. OTA基础知识
2. 手把手教你写Boot Loader(引导程序)
3. OTA理论基础


提示:这一系列文章还没有更新完... ...


前言

感谢这些前辈分享的资料,
在此我只是整理了前辈们的资料,然后使用通俗易懂的方法再介绍给大家,方便大家学习


一、OTA基础知识

我是懒得再写了,这里有个很完整的
OTA基础知识链接

二、创建Boot Loader(引导程序)

1.ota_bootloader.h

代码如下(示例):

#ifndef __OTA_BOOTLOADER_H
#define __OTA_BOOTLOADER_H
#include "main.h"
#include <stdbool.h>

// Bootloader代码区域
#define BLOCK_BOOTLOADER_START  ((uint32_t)0x08000000)//16k
// 系统参数区域
#define BLCOK_SYS_PARAM_START   ((uint32_t)0x08004000)//16k
#define UPDATE_FLASH_FLAG 0x08004000    //更新标志位
// APP1代码区域
#define BLOCK_APP1_START        ((uint32_t)0x08008000)//224k
// APP2代码区域
#define BLOCK_APP2_START        ((uint32_t)0x08040000)//256k
#define BLCOK_APP2_SPACE        ((uint32_t)224*1024)//256k


typedef  void (*pFunction)(void);

void FlashErase(uint32_t StartAddress);
void FlashWrite(uint32_t StartAddress,uint32_t data);
uint32_t FlashRead(uint32_t StartAddress);
void jump_to_app(uint32_t app_addr);
bool check_update_flag(void);
void FlashErases(uint32_t StartAddress,uint8_t num);
void updateInterface_CopyCode_FromApp2ToApp1(void);

#endif

2.ota_bootloader.c

代码如下(示例):

#include "ota_bootloader.h"

//F411CEU6 512k 8个扇区
uint32_t sectStartAddr[8]=
{
    0x08000000,//0
    0x08004000,//1
    0x08008000,//2
    0x0800c000,//3
    0x08010000,//4
    0x08020000,//5
    0x08040000,//6
    0x08060000 //7
};
//获取Sector的编号
int GetSectorFromAddress(uint32_t address)
{
    int sect;
    if( address < 0x08000000 || address > 0x0807FFFF )
        return -1;

    for( int i=0; i<8; i++ )
    {
        if( address >= sectStartAddr[i] && address < sectStartAddr[i+1] )
        {
            sect = i;
            break;
        }
    }
    return sect;
}

//清除扇区
void FlashErase(uint32_t StartAddress)
{
    int sect = 0;

    HAL_FLASH_Unlock();//解锁
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | 
                          FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);//清除一些错误标志

    sect = GetSectorFromAddress(StartAddress);//获取地址所在的扇区
    FLASH_Erase_Sector(sect,FLASH_VOLTAGE_RANGE_3);//擦除指定的闪存扇区(0~7)    
    HAL_FLASH_Lock();//上锁
}

//清除多个扇区
void FlashErases(uint32_t StartAddress,uint8_t num)
{
    int sect = 0;

    HAL_FLASH_Unlock();//解锁
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | 
                          FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);//清除一些错误标志

    sect = GetSectorFromAddress(StartAddress);//获取地址所在的扇区
    for(uint8_t i = 0;i<num;i++)
    {
        FLASH_Erase_Sector(sect+i,FLASH_VOLTAGE_RANGE_3);//擦除指定的闪存扇区(0~7)   
        FLASH_WaitForLastOperation(1000);
    }        
    HAL_FLASH_Lock();//上锁
}

//写数据
void FlashWrite(uint32_t StartAddress,uint32_t data)
{
    HAL_FLASH_Unlock();//解锁
    HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,StartAddress,data);
    HAL_FLASH_Lock();//上锁
}

//读数据
uint32_t FlashRead(uint32_t StartAddress)
{
    return *(uint32_t *)StartAddress;
}

//更新标志位
bool check_update_flag(void)
{
    bool status = false;
    if (FlashRead(UPDATE_FLASH_FLAG) == 0x55555555)
    {
        status = true;
    }
    return status; 
}

//将APP2代码复制到APP1中
void updateInterface_CopyCode_FromApp2ToApp1(void)
{
    uint32_t i = 0;

    for (i = 0; i < BLCOK_APP2_SPACE; i += 4)
    {
        FlashWrite(BLOCK_APP1_START + i, *(uint32_t *)(BLOCK_APP2_START + i));
    }
}

//跳转到应用程序
//appxaddr:用户代码起始地址.
void jump_to_app(uint32_t app_addr)
{ 
    pFunction jump_to_application;    
    if (((*(__IO uint32_t*)app_addr) & 0x2FFE0000 ) == 0x20000000)//检查栈顶地址是否合法.
    {
      jump_to_application = (pFunction)*(__IO uint32_t*) (app_addr + 4);/* 跳转到用户应用程序 */
      __set_MSP(*(__IO uint32_t*) app_addr);/* 初始化用户应用程序的堆栈指针 */
      jump_to_application();
    }    
}

3. 查看引导程序的大小

生成 bin 文件


总结

结合视频看更加详细
下一篇介绍怎么写APP程序

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-17 12:06:30  更:2021-07-17 12:07:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/7 14:01:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码