You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
500 lines
14 KiB
500 lines
14 KiB
2 days ago
|
/*
|
||
|
*********************************************************************************************************
|
||
|
*
|
||
|
* 模块名称 : cpu内部falsh操作模块(for STM32H743 H750)
|
||
|
* 文件名称 : bsp_cpu_flash.c
|
||
|
* 版 本 : V1.1
|
||
|
* 说 明 : 提供读写CPU内部Flash的函数
|
||
|
* 修改记录 :
|
||
|
* 版本号 日期 作者 说明
|
||
|
* V1.0 2019-09-20 armfly 正式发布
|
||
|
* V1.1 2019-10-03 armfly 写flash函数,修正长度不是32字节整数倍的bug,末尾补0写入。
|
||
|
* 解决HAL库函数的 HAL_FLASH_Program()的bug,
|
||
|
* 问题现象是大批量连续编程失败(报编程指令顺序错, PGSERR1、 PGSERR2)
|
||
|
* Copyright (C), 2019-2030, 安富莱电子 www.armfly.com
|
||
|
*
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
|
||
|
#include "bsp_cpu_flash.h"
|
||
|
#include <string.h>
|
||
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* 函数
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
|
||
|
|
||
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* 宏定义
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
//0x08020000 - 0x08000000 = 128k;//bootload 128k // every sector 448k
|
||
|
|
||
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* 变量
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
__IO uint32_t uwCRCValue;
|
||
|
__IO uint32_t uwExpectedCRCValue;
|
||
|
__IO uint32_t uwAppSize;
|
||
|
|
||
|
uint8_t buf[1024];
|
||
|
uint32_t RecCount = 0;
|
||
|
uint32_t RecCount0 = 0;
|
||
|
uint32_t RecSize = 0;
|
||
|
uint8_t RecCplt = 0;
|
||
|
uint32_t filesize = 0;
|
||
|
|
||
|
uint32_t Bus_Error=0;
|
||
|
uint32_t update_index = 0;
|
||
|
uint32_t update_index_true = 0;
|
||
|
uint32_t update_sum = 0;
|
||
|
uint32_t update_sum_true = 0;
|
||
|
|
||
|
|
||
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* 函 数 名: bsp_GetSector
|
||
|
* 功能说明: 根据地址计算扇区首地址
|
||
|
* 形 参: 无
|
||
|
* 返 回 值: 扇区号(0-7)
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
uint32_t bsp_GetSector(uint32_t Address)
|
||
|
{
|
||
|
uint32_t sector = 0;
|
||
|
|
||
|
if (((Address < ADDR_FLASH_SECTOR_1_BANK1) && (Address >= ADDR_FLASH_SECTOR_0_BANK1)) || \
|
||
|
((Address < ADDR_FLASH_SECTOR_1_BANK2) && (Address >= ADDR_FLASH_SECTOR_0_BANK2)))
|
||
|
{
|
||
|
sector = FLASH_SECTOR_0;
|
||
|
}
|
||
|
else if (((Address < ADDR_FLASH_SECTOR_2_BANK1) && (Address >= ADDR_FLASH_SECTOR_1_BANK1)) || \
|
||
|
((Address < ADDR_FLASH_SECTOR_2_BANK2) && (Address >= ADDR_FLASH_SECTOR_1_BANK2)))
|
||
|
{
|
||
|
sector = FLASH_SECTOR_1;
|
||
|
}
|
||
|
else if (((Address < ADDR_FLASH_SECTOR_3_BANK1) && (Address >= ADDR_FLASH_SECTOR_2_BANK1)) || \
|
||
|
((Address < ADDR_FLASH_SECTOR_3_BANK2) && (Address >= ADDR_FLASH_SECTOR_2_BANK2)))
|
||
|
{
|
||
|
sector = FLASH_SECTOR_2;
|
||
|
}
|
||
|
else if (((Address < ADDR_FLASH_SECTOR_4_BANK1) && (Address >= ADDR_FLASH_SECTOR_3_BANK1)) || \
|
||
|
((Address < ADDR_FLASH_SECTOR_4_BANK2) && (Address >= ADDR_FLASH_SECTOR_3_BANK2)))
|
||
|
{
|
||
|
sector = FLASH_SECTOR_3;
|
||
|
}
|
||
|
else if (((Address < ADDR_FLASH_SECTOR_5_BANK1) && (Address >= ADDR_FLASH_SECTOR_4_BANK1)) || \
|
||
|
((Address < ADDR_FLASH_SECTOR_5_BANK2) && (Address >= ADDR_FLASH_SECTOR_4_BANK2)))
|
||
|
{
|
||
|
sector = FLASH_SECTOR_4;
|
||
|
}
|
||
|
else if (((Address < ADDR_FLASH_SECTOR_6_BANK1) && (Address >= ADDR_FLASH_SECTOR_5_BANK1)) || \
|
||
|
((Address < ADDR_FLASH_SECTOR_6_BANK2) && (Address >= ADDR_FLASH_SECTOR_5_BANK2)))
|
||
|
{
|
||
|
sector = FLASH_SECTOR_5;
|
||
|
}
|
||
|
else if (((Address < ADDR_FLASH_SECTOR_7_BANK1) && (Address >= ADDR_FLASH_SECTOR_6_BANK1)) || \
|
||
|
((Address < ADDR_FLASH_SECTOR_7_BANK2) && (Address >= ADDR_FLASH_SECTOR_6_BANK2)))
|
||
|
{
|
||
|
sector = FLASH_SECTOR_6;
|
||
|
}
|
||
|
else if (((Address < ADDR_FLASH_SECTOR_0_BANK2) && (Address >= ADDR_FLASH_SECTOR_7_BANK1)) || \
|
||
|
((Address < CPU_FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_7_BANK2)))
|
||
|
{
|
||
|
sector = FLASH_SECTOR_7;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sector = FLASH_SECTOR_7;
|
||
|
}
|
||
|
|
||
|
return sector;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* 函 数 名: bsp_ReadCpuFlash
|
||
|
* 功能说明: 读取CPU Flash的内容
|
||
|
* 形 参: _ucpDst : 目标缓冲区
|
||
|
* _ulFlashAddr : 起始地址
|
||
|
* _ulSize : 数据大小(单位是字节)
|
||
|
* 返 回 值: 0=成功,1=失败
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
uint8_t bsp_ReadCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpDst, uint32_t _ulSize)
|
||
|
{
|
||
|
uint32_t i;
|
||
|
|
||
|
if (_ulFlashAddr + _ulSize > CPU_FLASH_BASE_ADDR + CPU_FLASH_SIZE)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/* 长度为0时不继续操作,否则起始地址为奇地址会出错 */
|
||
|
if (_ulSize == 0)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < _ulSize; i++)
|
||
|
{
|
||
|
*_ucpDst++ = *(uint8_t *)_ulFlashAddr++;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* 函 数 名: bsp_CmpCpuFlash
|
||
|
* 功能说明: 比较Flash指定地址的数据.
|
||
|
* 形 参: _ulFlashAddr : Flash地址
|
||
|
* _ucpBuf : 数据缓冲区
|
||
|
* _ulSize : 数据大小(单位是字节)
|
||
|
* 返 回 值:
|
||
|
* FLASH_IS_EQU 0 Flash内容和待写入的数据相等,不需要擦除和写操作
|
||
|
* FLASH_REQ_WRITE 1 Flash不需要擦除,直接写
|
||
|
* FLASH_REQ_ERASE 2 Flash需要先擦除,再写
|
||
|
* FLASH_PARAM_ERR 3 函数参数错误
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
uint8_t bsp_CmpCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpBuf, uint32_t _ulSize)
|
||
|
{
|
||
|
uint32_t i;
|
||
|
uint8_t ucIsEqu; /* 相等标志 */
|
||
|
uint8_t ucByte;
|
||
|
|
||
|
/* 如果偏移地址超过芯片容量,则不改写输出缓冲区 */
|
||
|
if (_ulFlashAddr + _ulSize > CPU_FLASH_BASE_ADDR + CPU_FLASH_SIZE)
|
||
|
{
|
||
|
return FLASH_PARAM_ERR; /* 函数参数错误 */
|
||
|
}
|
||
|
|
||
|
/* 长度为0时返回正确 */
|
||
|
if (_ulSize == 0)
|
||
|
{
|
||
|
return FLASH_IS_EQU; /* Flash内容和待写入的数据相等 */
|
||
|
}
|
||
|
|
||
|
ucIsEqu = 1; /* 先假设所有字节和待写入的数据相等,如果遇到任何一个不相等,则设置为 0 */
|
||
|
for (i = 0; i < _ulSize; i++)
|
||
|
{
|
||
|
ucByte = *(uint8_t *)_ulFlashAddr;
|
||
|
|
||
|
if (ucByte != *_ucpBuf)
|
||
|
{
|
||
|
if (ucByte != 0xFF)
|
||
|
{
|
||
|
return FLASH_REQ_ERASE; /* 需要擦除后再写 */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ucIsEqu = 0; /* 不相等,需要写 */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_ulFlashAddr++;
|
||
|
_ucpBuf++;
|
||
|
}
|
||
|
|
||
|
if (ucIsEqu == 1)
|
||
|
{
|
||
|
return FLASH_IS_EQU; /* Flash内容和待写入的数据相等,不需要擦除和写操作 */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return FLASH_REQ_WRITE; /* Flash不需要擦除,直接写 */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* 函 数 名: bsp_EraseCpuFlash
|
||
|
* 功能说明: 擦除CPU FLASH一个扇区 (128KB)
|
||
|
* 形 参: _ulFlashAddr : Flash地址
|
||
|
* 返 回 值: 0 成功, 1 失败
|
||
|
* HAL_OK = 0x00,
|
||
|
* HAL_ERROR = 0x01,
|
||
|
* HAL_BUSY = 0x02,
|
||
|
* HAL_TIMEOUT = 0x03
|
||
|
*
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
uint8_t bsp_EraseCpuFlash(uint32_t _ulFlashAddr)
|
||
|
{
|
||
|
uint32_t FirstSector = 0, NbOfSectors = 0;
|
||
|
FLASH_EraseInitTypeDef EraseInitStruct;
|
||
|
uint32_t SECTORError = 0;
|
||
|
uint8_t re;
|
||
|
|
||
|
/* 解锁 */
|
||
|
HAL_FLASH_Unlock();
|
||
|
|
||
|
/* 获取此地址所在的扇区 */
|
||
|
FirstSector = bsp_GetSector(_ulFlashAddr);
|
||
|
|
||
|
/* 固定1个扇区 */
|
||
|
NbOfSectors = 1;
|
||
|
|
||
|
/* 擦除扇区配置 */
|
||
|
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
|
||
|
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
|
||
|
|
||
|
if (_ulFlashAddr >= ADDR_FLASH_SECTOR_0_BANK2)
|
||
|
{
|
||
|
EraseInitStruct.Banks = FLASH_BANK_2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
EraseInitStruct.Banks = FLASH_BANK_1;
|
||
|
}
|
||
|
|
||
|
EraseInitStruct.Sector = FirstSector;
|
||
|
EraseInitStruct.NbSectors = NbOfSectors;
|
||
|
|
||
|
/* 扇区擦除 */
|
||
|
re = HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError);
|
||
|
|
||
|
/* 擦除完毕后,上锁 */
|
||
|
HAL_FLASH_Lock();
|
||
|
|
||
|
return re;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* 函 数 名: bsp_WriteCpuFlash
|
||
|
* 功能说明: 写数据到CPU 内部Flash。 必须按32字节整数倍写。不支持跨扇区。扇区大小128KB. \
|
||
|
* 写之前需要擦除扇区. 长度不是32字节整数倍时,最后几个字节末尾补0写入.
|
||
|
* 形 参: _ulFlashAddr : Flash地址
|
||
|
* _ucpSrc : 数据缓冲区
|
||
|
* _ulSize : 数据大小(单位是字节, 必须是32字节整数倍)
|
||
|
* 返 回 值: 0-成功,1-数据长度或地址溢出,2-写Flash出错(估计Flash寿命到)
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
uint8_t bsp_WriteCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpSrc, uint32_t _ulSize)
|
||
|
{
|
||
|
uint32_t i;
|
||
|
uint8_t ucRet;
|
||
|
|
||
|
/* 如果偏移地址超过芯片容量,则不改写输出缓冲区 */
|
||
|
if (_ulFlashAddr + _ulSize > CPU_FLASH_BASE_ADDR + CPU_FLASH_SIZE)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/* 长度为0时不继续操作 */
|
||
|
if (_ulSize == 0)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
ucRet = bsp_CmpCpuFlash(_ulFlashAddr, _ucpSrc, _ulSize);
|
||
|
|
||
|
if (ucRet == FLASH_IS_EQU)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
__set_PRIMASK(1); /* 关中断 */
|
||
|
|
||
|
/* FLASH 解锁 */
|
||
|
HAL_FLASH_Unlock();
|
||
|
|
||
|
for (i = 0; i < _ulSize / 32; i++)
|
||
|
{
|
||
|
uint64_t FlashWord[4];
|
||
|
|
||
|
memcpy((char *)FlashWord, _ucpSrc, 32);
|
||
|
_ucpSrc += 32;
|
||
|
|
||
|
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, _ulFlashAddr, (uint64_t)((uint32_t)FlashWord)) == HAL_OK)
|
||
|
{
|
||
|
_ulFlashAddr = _ulFlashAddr + 32; /* 递增,操作下一个256bit */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
goto err;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* 长度不是32字节整数倍 */
|
||
|
if (_ulSize % 32)
|
||
|
{
|
||
|
uint64_t FlashWord[4];
|
||
|
|
||
|
FlashWord[0] = 0;
|
||
|
FlashWord[1] = 0;
|
||
|
FlashWord[2] = 0;
|
||
|
FlashWord[3] = 0;
|
||
|
memcpy((char *)FlashWord, _ucpSrc, _ulSize % 32);
|
||
|
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, _ulFlashAddr, (uint64_t)((uint32_t)FlashWord)) == HAL_OK)
|
||
|
{
|
||
|
; // _ulFlashAddr = _ulFlashAddr + 32;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
goto err;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Flash 加锁,禁止写Flash控制寄存器 */
|
||
|
HAL_FLASH_Lock();
|
||
|
|
||
|
__set_PRIMASK(0); /* 开中断 */
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
err:
|
||
|
/* Flash 加锁,禁止写Flash控制寄存器 */
|
||
|
HAL_FLASH_Lock();
|
||
|
|
||
|
__set_PRIMASK(0); /* 开中断 */
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* 函 数 名: JumpToApp
|
||
|
* 功能说明: 跳转到应用JumpToApp
|
||
|
* 形 参: 无
|
||
|
* 返 回 值: 无
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
void JumpToApp(void)
|
||
|
{
|
||
|
uint32_t i=0;
|
||
|
void (*AppJump)(void); /* 声明一个函数指针 */
|
||
|
|
||
|
/* 关闭全局中断 */
|
||
|
DISABLE_INT();
|
||
|
|
||
|
/* 设置所有时钟到默认状态,使用HSI时钟 */
|
||
|
|
||
|
__HAL_RCC_GPIOH_CLK_DISABLE();
|
||
|
__HAL_RCC_GPIOB_CLK_DISABLE();
|
||
|
HAL_RCC_DeInit();
|
||
|
|
||
|
/* 关闭滴答定时器,复位到默认值 */
|
||
|
SysTick->CTRL = 0;
|
||
|
SysTick->LOAD = 0;
|
||
|
SysTick->VAL = 0;
|
||
|
|
||
|
/* 关闭所有中断,清除所有中断挂起标志 */
|
||
|
for (i = 0; i < 8; i++)
|
||
|
{
|
||
|
NVIC->ICER[i]=0xFFFFFFFF;
|
||
|
NVIC->ICPR[i]=0xFFFFFFFF;
|
||
|
}
|
||
|
|
||
|
/* 使能全局中断 */
|
||
|
ENABLE_INT();
|
||
|
|
||
|
/* 跳转到应用程序,首地址是MSP,地址+4是复位中断服务程序地址 */
|
||
|
AppJump = (void (*)(void)) (*((uint32_t *) (App_Run_Addr + 4)));
|
||
|
|
||
|
/* 设置主堆栈指针 */
|
||
|
__set_MSP(*(uint32_t *)App_Run_Addr);
|
||
|
|
||
|
/* 在RTOS工程,这条语句很重要,设置为特权级模式,使用MSP指针 */
|
||
|
__set_CONTROL(0);
|
||
|
|
||
|
/* 跳转到系统BootLoader */
|
||
|
AppJump();
|
||
|
|
||
|
/* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */
|
||
|
while (1)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* 函 数 名: JumpToApp
|
||
|
* 功能说明: 跳转到应用JumpToApp
|
||
|
* 形 参: 无
|
||
|
* 返 回 值: 无
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
void Copy_Download_Flash_to_Start()
|
||
|
{
|
||
|
|
||
|
uint32_t startIndex=0;
|
||
|
|
||
|
for(startIndex = 0; startIndex < 3; startIndex++)
|
||
|
{
|
||
|
bsp_EraseCpuFlash((uint32_t)(App_Run_Addr + startIndex*128*1024));//Erase this function
|
||
|
}
|
||
|
|
||
|
|
||
|
uint8_t readData[32];
|
||
|
uint32_t total=3*128*1024/sizeof(readData);
|
||
|
uint8_t retult=0;
|
||
|
for(startIndex=0;startIndex<total;startIndex++)
|
||
|
{
|
||
|
//App_Download_Addr
|
||
|
//Read 32 bytes
|
||
|
bsp_ReadCpuFlash(App_Download_Addr+startIndex*sizeof(readData),readData,sizeof(readData));
|
||
|
//ucState = bsp_WriteCpuFlash((uint32_t)(AppAddr + TotalSize), (uint8_t *)&g_Can2RxData[8], RecSize);
|
||
|
retult=bsp_WriteCpuFlash(App_Run_Addr+startIndex*sizeof(readData),readData,sizeof(readData));
|
||
|
//Read
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void Copy_Peripheral_Download_Flash_to_App_Start(uint32_t totalBytes)
|
||
|
{
|
||
|
|
||
|
uint32_t startIndex=0;
|
||
|
// erase the all the flash from the App_Run_Addr
|
||
|
for(startIndex = 0; startIndex < 7; startIndex++)
|
||
|
{
|
||
|
bsp_EraseCpuFlash((uint32_t)(App_Run_Addr + startIndex*128*1024));//Erase this function
|
||
|
}
|
||
|
|
||
|
|
||
|
uint8_t readData[256];
|
||
|
uint32_t total=totalBytes/sizeof(readData)+1;
|
||
|
uint8_t retult=0;
|
||
|
for(startIndex=0;startIndex<total;startIndex++)
|
||
|
{
|
||
|
//App_Download_Addr
|
||
|
//Read 32 bytes
|
||
|
|
||
|
QSPI_W25Qx_Read_Buffer(&readData,CODE_DOWNLOAD_FLASH_BEGIN_ADDRESS+startIndex*sizeof(readData),256);
|
||
|
HAL_Delay(10);
|
||
|
//retult= bsp_ReadCpuFlash(App_Download_Addr+startIndex*sizeof(readData),readData,sizeof(readData));
|
||
|
//ucState = bsp_WriteCpuFlash((uint32_t)(AppAddr + TotalSize), (uint8_t *)&g_Can2RxData[8], RecSize);
|
||
|
retult=bsp_WriteCpuFlash(App_Run_Addr+startIndex*sizeof(readData),readData,sizeof(readData));
|
||
|
//Read
|
||
|
HAL_Delay(10);
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
void Erase_App_Download_Flash_Addr()
|
||
|
{
|
||
|
uint32_t startIndex=0;
|
||
|
//清空bank0 的1-7 区域
|
||
|
//there are 8 sectors in total, and
|
||
|
for(startIndex = 0; startIndex < 4; startIndex++)
|
||
|
{
|
||
|
bsp_EraseCpuFlash((uint32_t)(App_Download_Addr + startIndex*128*1024));//Erase this function
|
||
|
}
|
||
|
//char data[1];
|
||
|
//data[0]=20;
|
||
|
// bsp_WriteCpuFlash(App_Download_Addr,
|
||
|
// data, 1);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|