STM32F103 USB OTA升级APP (二)

2023-11-05

接上一篇STM32F103 USB OTA升级BootLoader (一):跳转链接

修改程序启动地址和Flash大小

 修改main.c代码

#include "main.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"
#include "Update.h"

void SystemClock_Config(void);

int main(void)
{
    SCB->VTOR = FLASH_APP_ADDR;
	HAL_Init();
	SystemClock_Config();

	MX_GPIO_Init();
	MX_USART1_UART_Init();
	MX_USB_DEVICE_Init();
	printf("IAP Code V1.1\r\n");
	while (1)
	{
		

		Usart_Data_Handler();

	}
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
  PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Update.c

#include "Update.h"

uint32_t PageError = 0;

void Write_Flash(uint8_t *data, uint16_t DataLen, uint32_t Addr)
{
	uint16_t i = 0;
	uint64_t Data = 0;
    uint64_t temp = 0;
    
	HAL_FLASH_Unlock();
	for(i = 0; i < DataLen; i += 8)
	{
        Data = 0;        
        for(uint8_t j = 0; j < 8; j++)
        {
            temp = data[i + j];
            Data |= temp << 8 * j;
        }
        
		if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, FLASH_APP_ADDR + Addr + i, Data) == HAL_OK)
		{
             
		}
        
       /* printf("0x%16llx   |", Data);
        if(i % 16 == 0 && i != 0)
        printf("\r\n");*/
	}
	HAL_FLASH_Lock();
}


void Write_Updata_Flag_Flash(void)
{
    HAL_FLASH_Unlock();
    HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, FLASH_Updata_Flag_ADDR, 0x55555555);
    HAL_FLASH_Lock();
}

void Erase_Updata_Flag_Flash(void)
{
	FLASH_EraseInitTypeDef EraseInitStruct;
	HAL_FLASH_Unlock();
	EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
	EraseInitStruct.PageAddress        = FLASH_Updata_Flag_ADDR;
	EraseInitStruct.NbPages     = 1;
	if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
	{

    }
    HAL_FLASH_Lock();
}

void Erase_APP_Flash(void)
{
	FLASH_EraseInitTypeDef EraseInitStruct;
	HAL_FLASH_Unlock();
	EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
	EraseInitStruct.PageAddress        = FLASH_APP_ADDR;
	EraseInitStruct.NbPages     = 20;
	if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
	{

    }
    HAL_FLASH_Lock();
}


void Read_Flash_Data(uint8_t* pBuffer, uint32_t NumToRead, uint32_t ReadAddr)
{
    uint32_t i;
    for (i = 0; i < NumToRead; i++)
    {
        *((uint8_t*)pBuffer + i) = *((uint8_t*)ReadAddr + i);
    }
}


#define RX_QUEUE_LENGTH 	2048		
static uint8_t RxQueue[RX_QUEUE_LENGTH];
uint8_t Update_Data[1024 + 10];
static uint16_t RxQueueHead = 0;
static uint16_t RxQueueTail = 0;

typedef enum
{
	RECEIVER_IDLE	= 0,
    RECEIVER_HEAD_H,
    RECEIVER_HEAD_L,
    RECEIVER_CMD,
    RECEIVER_LEN_H,
    RECEIVER_LEN_L,
    RECEIVER_DATA,
    RECEIVER_CHECK,
}RECEIVER_STATE;

typedef enum
{
    UPDATE_IDLE = 0,
	UPDATE_START,	
    UPDATE_STARTING,
    UPDATE_END,
}UPDATE_STATE;

RECEIVER_STATE Receiver_State = RECEIVER_HEAD_H;
UPDATE_STATE Update_State = UPDATE_IDLE;

void OnDataReceived(uint8_t val)
{
	if(((RxQueueTail + 1) % RX_QUEUE_LENGTH) != RxQueueHead)		//queue is not full
	{		
		RxQueue[RxQueueTail++] = val;			                        //save data into queue
		RxQueueTail %= RX_QUEUE_LENGTH;		                    //queue tail++
	}
}

void ClearRxQueue(void)
{
	RxQueueHead = 0;
	RxQueueTail = 0;
	memset(RxQueue, 0, sizeof(RxQueue));
}

static uint16_t GetRxQueueLen(void)
{
	return ((RxQueueTail + RX_QUEUE_LENGTH - RxQueueHead) % RX_QUEUE_LENGTH);
}

uint8_t GetRxQueueData(void)
{
	uint8_t val;
	val = RxQueue[RxQueueHead];
	RxQueueHead = ((RxQueueHead + 1) % RX_QUEUE_LENGTH);
	return val;
}

uint8_t Check_Sum(uint8_t *str, uint16_t len)
{
    uint8_t sum = 0;
    for(;len > 0; len--)
    {
        sum += *str++;
    }
    return sum;
}

bool Usart_Data_Handler(void)
{
	static uint8_t Data;
	static uint8_t Cmd;
	static uint16_t Receive_Data_Len;
	static uint16_t Receive_Data_Count;

    while(GetRxQueueLen() > 0)
    {	
        Data = GetRxQueueData();
        
        if(Receiver_State == RECEIVER_HEAD_H)
        {
            if(Data == 0x55)
            {
                Receiver_State++;
            }
        }
        else if(Receiver_State == RECEIVER_HEAD_L)
        {
            if(Data == 0x55)
            {
                Receiver_State++;
            }
        }
        else if(Receiver_State == RECEIVER_CMD)
        {
            Receiver_State++;
            Cmd = Data;
            if(Cmd == 0x00)
            {
                Erase_Updata_Flag_Flash();
                printf("Erase_Updata_Flag_Flash \r\n");
                NVIC_SystemReset();
            }    
        }
        else if(Receiver_State == RECEIVER_LEN_H)
        {
            Receiver_State++;

        }
        else if(Receiver_State == RECEIVER_LEN_L)
        {
            Receiver_State++;
        }
        else if(Receiver_State == RECEIVER_DATA)
        {
            if(Receive_Data_Count == Receive_Data_Len)
            {
                Receiver_State++;
            }
        }
        else if(Receiver_State == RECEIVER_CHECK)
        {
            Receiver_State = RECEIVER_HEAD_H;
        }
    }
}

void Usart_Get_Data_Handler(void)
{
	if(!Usart_Data_Handler())
	{
		return;
	}
}

Update.h

#ifndef __UPDATE_H
#define __UPDATE_H

#include "main.h"
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include "usbd_cdc_if.h"

#define FLASH_Page_Size		(2048)
#define FLASH_Updata_Flag_ADDR	(0x08000000 + 9 * FLASH_Page_Size)
#define FLASH_APP_ADDR	(0x08000000 + 10 * FLASH_Page_Size)


void Erase_APP_Flash(void);
void Erase_Updata_Flag_Flash(void);
void Write_Flash(uint8_t *data, uint16_t DataLen, uint32_t Addr);
void Read_Flash_Data(uint8_t* pBuffer, uint32_t NumToRead, uint32_t ReadAddr);


void ClearRxQueue(void);
void OnDataReceived(uint8_t val);
bool Usart_Data_Handler(void);

#endif

源码链接:跳转链接

上位机升级工具:升级工具

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32F103 USB OTA升级APP (二) 的相关文章

  • 大数据技术与实践学习笔记(1 of 3,from hitwh)

    大数据技术与实践 注意 由于文章图片是通过typora一键上传图片实现 该功能还存在bug 容易导致图片顺序混乱 文章开头提供了原版文章的 pdf 资源下载 推荐下载 pdf 后观看 文章目录 大数据技术与实践 1 1 大数据技术概述 一
  • CSDN文章复制没有图片只有文字

    有朋友反映 复制CSDN页面内容 然后粘贴 结果发现图片没拷过来 只有文字部分 是这样吗 做一个测试 确认这个问题存在 随便找了一个页面 53 岁的我都退休了 但好想跨行当一名程序员 结果收到了 3 份 Offer 相当的励志 人家53岁老
  • 搭建Docker+SRS服务器实现推流拉流的效果

    最初的一个想法 是针对当前的网络电视去的 很多网络电视买回家 还要充很多会员 甚至跌入连环坑 我想给妈妈买一台电视 想把我自己收集的电影电视剧做成一个影视库 通过搭建家庭影院服务器 然后在安卓终端上面点播 最初想得很简单 就是做一个文件服务
  • web中css怎么去除链接的,css中怎么为导航添加超链接

    css中怎么为导航添加超链接 发布时间 2021 07 09 16 43 47 来源 亿速云 阅读 55 作者 Leah 这篇文章将为大家详细讲解有关css中怎么为导航添加超链接 文章内容质量较高 因此小编分享给大家做个参考 希望大家阅读完

随机推荐

  • 自动驾驶通信中间件ecal源码分析—2. Broker vs Brokerless

    前面我们提到ecal是没有中间代理商的 brokerless 那么什么是Broker和Brokerless 1 Message Broker A message broker is software that enables applica
  • java.lang.ArrayIndexOutBoundException数组越界异常解决

    ArrayIndexOutBoundException是数组越界异常 非常常见的一个异常 从字面意思理解是数组下标访问错误 通常是在使用的时候访问了错误的数组下标 个人觉得这个问题的出现一般是搞混了数组长度和下标的问题 数组的长度 是指数组
  • C/C++语言ACM格式输入输出练习

    文章目录 1 输入字符串个数 一行字符串 空格隔开 2 输入多组字符串 空格隔开 3 数多组字符串 逗号隔开 1 输入字符串个数 一行字符串 空格隔开 题目描述 对输入的字符串进行排序后输出 打开以下链接可以查看正确的代码 https ac
  • 当在浏览器输入一个URL后会发生什么

    上网这件事对于现时代年轻人来说已经是家常便饭了 那么当输入一个URL 网址 之后会发生什么呢 这里面涉及到计算机图形学 操作系统 编译原理 计算机网络 通信原理 分布式系统 浏览器原理等多个不同的学科 领域 在这里由于我的能力和知识都有限
  • windows下编译、配置ceres库(保姆级教程)

    文章目录 前言 一 cmake安装 二 ceres 依赖库的下载 2 1 依赖库的下载 2 2 编译前准备工作 2 2 1 创建vs工程的输出文件夹 2 2 2 创建编译库的输出文件夹 2 3 编译Eigen库 2 3 1 编译Eigen3
  • hexo置顶文章及样式美化

    问题描述 文章置顶功能实现 top值越高越在前 由于官方并未给出置顶功能 所以要手动修改 sticky 显示图钉样式 top 置顶功能实现 原理 在Hexo生成首页HTML时 top值越高越在前 达到文章置顶功能 效果 置顶效果 修改 找到
  • 牛客周赛 Round 4---游游的因子计算

    输入 6 2 输出 6 1 2 3 4 6 12 解析 如果一个数 x 是 a 的因子 y是b的因子 那么x y一定是a b的因子 试除法分别获取a和b的因子 然后两层遍历的所有 a i b j 的所有情况即为答案 include
  • 安全防御——APT

    安全防御 APT APT介绍 APT攻击技术 APT攻击方式 APT攻击诱饵种类 APT特征 APT攻击过程 生命周期 第一阶段 扫描探测 第二阶段 工具投送 第三阶段 漏洞利用 第四阶段 木马植入 第五阶段 远程控制 第六阶段 横向渗透
  • Linux内核空间映射到用户空间

    作者 EasyWave 时间 2012 12 26 类别 Linux内核 内核空间映射 声明 转载 请保留链接 注意 如有错误 欢迎指正 这些是我学习的日志文章
  • 基数排序(C语言)

    基数排序 基数排序 Radix sort 是一种非比较型的排序算法 最早用于解决卡片排序的问题 它的工作原理是将待排序的元素拆分为k个关键字 其中k为最大值的位数 从低位开始进行稳定排序 注意 数列中的元素都是非负整数 基数排序是一种稳定的
  • Python爬虫批量下载文献

    最近在看NeurIPS的文章 但是一篇篇下载太繁琐 希望能快速批量下载下来 于是想到了之前一直听说的python爬虫 初次学着弄一下 用到了requests BeautifulSoup urllib request包 先放最终运行的程序 结
  • Proteus8仿真:51单片机IrLink红外发送加接受模块的使用

    51单片机IrLink红外的使用 元器件 原理图部分 代码 单片机1发送main c 单片机2接受main c 工程文件 注意 本篇的密码接受有问题 不够仍然可以使用 想优化可以看我最新文章 最新优化 这个是没有bug的版本 元器件 元器件
  • 缓存篇

    1 springboot自带缓存 step1 开启注解 在application类上加上 EnableCaching注解 step2 在需要加缓存的方法上加上注解 Cacheable 该注解的属性 cacheManager管理多个cache
  • HJ24 合唱队——动态规划

    HJ24 合唱队 解析 这道题可以参考该视频的思路 使用left和right数组记录元素i左边递增的元素个数和右边递减元素的个数 left和right数组的值由前面的状态推出 如果i比前面的某一元素ii大 则left i max left
  • 微信小程序真机调试接口错误怎么解决

    今天项目写完做真机测试的时候遇到了一个问题 就是二级路由在真机测试的时候不能跳转 错误如下 于是去上网找了一下解决方法 大致如下 第一步 找到小程序里面的开发选项 找到服务器域名 获取域名 保存域名 第二步 打开小程序 刷新页面 打开详情
  • Pandas-object字符类型转时间类型to_datetime()函数

    一 pandas中to datetime 函数 可以将指定数据转换为相应格式的时间类型数据 pandas to datetime arg format None unit None 参数 含义 arg 需要转换类型的数据 format 所输
  • AI时代到来,免费ChatGPT在这里

    AI大模型是什么 它指的是参数量巨大的深度学习模型 其参数数量通常达到数十亿乃至数万亿 通过学习海量数据 这些模型不断提升预测能力 在自然语言处理 计算机视觉 自主驾驶等领域取得了重要的突破 AI大模型的定义可根据参数规模进行分类 按照Op
  • python解析含有重复key的json

    python自带的json包能够方便的解析json文本 但是如果json文本中包含重复key的时候 解析的结果就是错误的 如下为例 key 1 key 2 key 3 key2 4 经过解析 结果却如下所示 key 3 key2 4 原因是
  • J-Tech & 开源之夏|什么是比快更快的向量搜索

    J Tech Talk 由 Jina AI 社区为大家带来的技术分享工程师们将深入细节地讲解具体的问题 分享 Jina AI 在开发过程中所积累的经验 本期 J Tech Talk 邀请到了在开源之夏项目中脱颖而出的杨小燕 分享她负责的项目
  • STM32F103 USB OTA升级APP (二)

    接上一篇STM32F103 USB OTA升级BootLoader 一 跳转链接 修改程序启动地址和Flash大小 修改main c代码 include main h include usart h include usb device h