OTA工程的思考:
V1.0wo 想到设置一个U8的flag 读一读判断是不是要MV在JUMP
V2.0我想到flag还不够 我希望你告诉我BIN文件的大小 这样我好知道我MV多少次
V3.0我终于明白了 我最想要的就是flag 它标识MV多少次就好了 我是无脑搬运!
再看OTA主要流程:
上电--读标识--没有比较就直接JUMP--有必要就MV在JUMP
1--JUMP--地址就是APP工程的偏移量【设计KEIL+代码宏定义】
2--MV【就是flash操作】
代码:
保存的时候:以前
void goto_reset(void)
{
char flag = 1;
config.write(CFG_BOOT_FLAG, &flag,1);
printf("准备操作BOOT 复位啦\r\n");
GSysdelay(500);
soft_system_resert(__FUNCTION__);
}
现在:
void goto_reset(uint8_t mvcnt)
{
config.write(CFG_BOOT_FLAG, &mvcnt,1);
printf("准备操作BOOT 复位啦\r\n");
GSysdelay(500);
soft_system_resert(__FUNCTION__);
}
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "rng.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "gunit.h"
#include "GW24Q64.h"
#include "ChipFlash.h"
G_SPIFlash_Type *flash=NULL;
#define W24Q64_CFG_ADD (4096*5)
#define W24Q64_BACKUP_ADD (4096*6)
#define STM32_APP_ADD 0x0800A000 //这个地址就是BOOT工程中的IDE设置的地址 main开头的地址!!务必
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* 跳转函数*/
#if defined ( __CC_ARM ) // 使用Keil编译环境
__asm void MSR_MSP ( uint32_t ulAddr )
{
MSR MSP, r0 //set Main Stack value
BX r14
}
#elif defined ( __ICCARM__ ) // 使用IAR编译环境
void MSR_MSP ( uint32_t ulAddr )
{
asm("MSR MSP, r0"); //set Main Stack value
asm("BX r14");
}
#endif
typedef void (*iapfun)(void); //定义一个函数类型的参数.
iapfun jump2app;
void iap_load_app(uint32_t appxaddr)
{
printf("马上跳转到0X%08X\r\n",appxaddr);
__set_PRIMASK(1);
if(((*(uint32_t*)appxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法.
{
jump2app=(iapfun)*(uint32_t*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址)
MSR_MSP(*(uint32_t*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
jump2app(); //跳转到APP.
}
}
/* 跳转函数*/
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_NVIC_Init(void);
/* USER CODE BEGIN PFP */
void mv_binfile(uint8_t mvcount);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI1_Init();
MX_USART1_UART_Init();
MX_RNG_Init();
/* Initialize interrupts */
MX_NVIC_Init();
/* USER CODE BEGIN 2 */
G_lovexin();
//test_st_chipflash();//测试OK
uint8_t bootflag_carrycount=0;
flash = &spiflash;
flash->init();
flash->read( W24Q64_CFG_ADD , &bootflag_carrycount , 1 );
printf("READED bootflag=%d\r\n",bootflag_carrycount);//255
if(bootflag_carrycount ==0 ||bootflag_carrycount ==0XFF)
{
printf("DO NOTHING --> GO TO APP\r\n");
}
else
{
printf("DO WORK 1--MV BACKUP(W24Q64)->BOOT(STM32) 2--GO TO APP\r\n");
mv_binfile(bootflag_carrycount);//其实没有mv这是cp flag需要清除做MV避免下次还MV
bootflag_carrycount=0;
flash->write( W24Q64_CFG_ADD , &bootflag_carrycount , 1 );
}
iap_load_app(STM32_APP_ADD);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* 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 CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 20;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses 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_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_RNG;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
PeriphClkInit.RngClockSelection = RCC_RNGCLKSOURCE_PLLSAI1;
PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE;
PeriphClkInit.PLLSAI1.PLLSAI1M = 1;
PeriphClkInit.PLLSAI1.PLLSAI1N = 12;
PeriphClkInit.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7;
PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_48M2CLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/** Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief NVIC Configuration.
* @retval None
*/
static void MX_NVIC_Init(void)
{
/* USART1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief Period elapsed callback in non blocking mode
* @note This function is called when TIM6 interrupt took place, inside
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
* a global variable "uwTick" used as application time base.
* @param htim : TIM handle
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM6) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
/* USER CODE END Callback 1 */
}
/**
* @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(char *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****/
/*拷贝W24Q64的文件到STM32
需要知道文件大小 然后计算我需要搬运多少次
我没有搞参数
默认BIN文件一共220K
W24Q64使用了 4K*55PAGE=220K
也就是从 W24Q64_BACKUP_ADD 开始连续55页
我需要搬运110次 因为STM32是2K一个PAGE
也就是从 STM32_APP_ADD 开始连续110页
*/
void mv_binfile(uint8_t mvcount)
{
ChipFlash_T *c = &ChipFlash;
G_SPIFlash_Type *s = &spiflash;
static uint8_t buf[4096];
uint8_t totalpage=0,i=0,page=0,j=0;
uint32_t addrpagefrom=0,addrpageto=0,x=0;
printf("我们不考虑BIN文件-因为前人已经算好-我们直接暴力搬运%d次\r\n",mvcount);
for (i=0;i<mvcount;i++)
{
addrpagefrom = W24Q64_BACKUP_ADD+i*4096;
addrpageto = STM32_APP_ADD+i*4096;//一次翻了2页
memset(buf,0,4096);
s->read (addrpagefrom,buf,4096);
c->write(addrpageto ,buf,2048 );//写第1页[已经在写函数内部做了先擦除在写入]
c->write(addrpageto+2048 ,&buf[2048],2048 );//写第2页
printf("第%03d次addrpagefrom = 0X%08X ,addrpageto = 0X%08X \r\n",i,addrpagefrom,addrpageto);
}
}