|
本帖最后由 让我看看各位 于 2024-11-22 10:54 编辑
读大文件(400K)90%会进硬件错误 , 小文件1K,基本不会死机 ,用H7Tool查进入硬件错误的原因是总线错误 ,一顿瞎折腾也不知道啥原因,大佬们求助
这是读函数:
/*
*********************************************************************************************************
* 函 数 名: STMFLASH_Write
* 功能说明: 从指定地址开始写入指定长度的数据
* 形 参:
* waddr - 起始地址(此地址必须为4的倍数)
* pbuf - 数据指针
* length - 字(32位)数(就是要写入的32位数据的个数)
* 输 出: 无
* 返 回 值: 无
* 特 别:
* - 因为STM32H7的扇区较大,如果写地址非0xFF,会先擦除整个扇区且不保存扇区数据,导致整个扇区数据丢失。
* - 写非0xFF的地址前,确保扇区中没有重要数据,最好先擦除整个扇区再写入。
* - 该函数对OTP区域也有效,可以用来写OTP区。
* - OTP区域地址范围:0X1FFF7800 ~ 0X1FFF7A0F(注意:最后16字节用于OTP数据块锁定,不要随意写入)
*********************************************************************************************************
*/
void STMFLASH_Write(uint32_t waddr, uint32_t *pbuf, uint32_t length)
{
FLASH_EraseInitTypeDef FlashEraseInit;
HAL_StatusTypeDef FlashStatus = HAL_OK;
uint32_t SectorError = 0;
uint32_t addrx = 0;
uint32_t endaddr = 0;
if (waddr < STM32_FLASH_BASE || waddr % 32 || /* 写入地址小于 STM32_FLASH_BASE, 或不是32的整数倍, 非法. */
waddr > (STM32_FLASH_BASE + STM32_FLASH_SIZE)) /* 写入地址大于 STM32_FLASH_BASE + STM32_FLASH_SIZE, 非法. */
{
return;
}
HAL_FLASH_Unlock(); /* 解锁 */
addrx = waddr; /* 写入的起始地址 */
endaddr = waddr + length * 4; /* 写入的结束地址 */
if (addrx < 0X1FF00000)
{
while (addrx < endaddr) /* 扫清一切障碍.(对非FFFFFFFF的地方,先擦除) */
{
if (STMFLASH_ReadWord(addrx) != 0XFFFFFFFF) /* 有非0XFFFFFFFF的地方,要擦除这个扇区 */
{
FlashEraseInit.Banks = FLASH_BANK_1;
FlashEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS; /* 擦除类型,扇区擦除 */
FlashEraseInit.Sector = STMFLASH_GetFlashSector(addrx); /* 要擦除的扇区 */
FlashEraseInit.NbSectors = 1; /* 一次只擦除一个扇区 */
FlashEraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3; /* 电压范围,VCC=2.7~3.6V之间!! */
if (HAL_FLASHEx_Erase(&FlashEraseInit, &SectorError) != HAL_OK)
{
break; /* 发生错误了 */
}
SCB_CleanInvalidateDCache(); /* 清除无效的D-Cache */
}
else
{
addrx += 128 * 1024;
}
FLASH_WaitForLastOperation(FLASH_WAITETIME, FLASH_BANK_1); /* 等待上次操作完成 */
}
}
FlashStatus = FLASH_WaitForLastOperation(FLASH_WAITETIME, FLASH_BANK_1); /* 等待上次操作完成 */
if (FlashStatus == HAL_OK)
{
while (waddr < endaddr) /* 写数据 */
{
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, waddr, (uint64_t)pbuf) != HAL_OK) /* 写入数据 */
{
break; /* 写入异常 */
}
waddr += 32;
pbuf += 8;
}
}
HAL_FLASH_Lock(); /* 上锁 */
}
/*
*********************************************************************************************************
* 函 数 名: STMFLASH_ReadWord
* 功能说明: 从指定地址读取一个字 (32位数据)
* 形 参:
* faddr - 读取地址 (此地址必须为4的倍数)
* 输 出: 无
* 返 回 值:
* 读取到的数据 (32位)
*********************************************************************************************************
*/
uint32_t STMFLASH_ReadWord(uint32_t faddr)
{
return *(volatile uint32_t *)faddr;
}
/*
*********************************************************************************************************
* 函 数 名: STMFLASH_Read
* 功能说明: 从指定地址开始读出指定长度的数据
* 形 参:
* raddr - 起始地址
* pbuf - 存储读取数据的缓冲区指针
* length- 要读取的字(32位)数,即4个字节的整数倍
* 输 出: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void STMFLASH_Read(uint32_t raddr, uint32_t *pbuf, uint32_t length)
{
uint32_t i;
for (i = 0; i < length; i++)
{
pbuf[i = STMFLASH_ReadWord(raddr); /* 读取4个字节 */
raddr += 4; /* 偏移4个字节 */
}
}
/*
*********************************************************************************************************
* 函 数 名: STMFLASH_GetFlashSector
* 功能说明: 获取某个地址所在的flash扇区
* 形 参:
* faddr - flash地址
* 输 出: 无
* 返 回 值:
* 0~7 - addr所在的Bank1扇区编号
* 8~15 - addr所在的Bank2扇区编号(需要减去8,才得到Bank2的实际扇区编号)
*********************************************************************************************************
*/
uint8_t STMFLASH_GetFlashSector(uint32_t addr)
{
if (addr < BANK1_FLASH_SECTOR_1)
return 0;
else if (addr < BANK1_FLASH_SECTOR_2)
return 1;
else if (addr < BANK1_FLASH_SECTOR_3)
return 2;
else if (addr < BANK1_FLASH_SECTOR_4)
return 3;
else if (addr < BANK1_FLASH_SECTOR_5)
return 4;
else if (addr < BANK1_FLASH_SECTOR_6)
return 5;
else if (addr < BANK1_FLASH_SECTOR_7)
return 6;
else if (addr < BANK2_FLASH_SECTOR_0)
return 7;
else if (addr < BANK2_FLASH_SECTOR_1)
return 8;
else if (addr < BANK2_FLASH_SECTOR_2)
return 9;
else if (addr < BANK2_FLASH_SECTOR_3)
return 10;
else if (addr < BANK2_FLASH_SECTOR_4)
return 11;
else if (addr < BANK2_FLASH_SECTOR_5)
return 12;
else if (addr < BANK2_FLASH_SECTOR_6)
return 13;
else if (addr < BANK2_FLASH_SECTOR_7)
return 14;
return 15;
}
下面是.H文件内容
#ifndef __STMFLASH_H
#define __STMFLASH_H
#include <stdint.h>
/* FLASH起始地址 */
#define STM32_FLASH_SIZE 0X200000 /* STM32 FLASH 总大小 */
#define STM32_FLASH_BASE 0x08000000 /* STM32 FLASH 起始地址 */
#define FLASH_WAITETIME 50000 /* FLASH等待超时时间 */
/* FLASH 扇区的起始地址,分2个bank,每个bank 1MB */
/* BANK1 */
#define BANK1_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Bank1扇区0起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_1 ((uint32_t)0x08020000) /* Bank1扇区1起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_2 ((uint32_t)0x08040000) /* Bank1扇区2起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_3 ((uint32_t)0x08060000) /* Bank1扇区3起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_4 ((uint32_t)0x08080000) /* Bank1扇区4起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_5 ((uint32_t)0x080A0000) /* Bank1扇区5起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_6 ((uint32_t)0x080C0000) /* Bank1扇区6起始地址, 128 Kbytes */
#define BANK1_FLASH_SECTOR_7 ((uint32_t)0x080E0000) /* Bank1扇区7起始地址, 128 Kbytes */
/* BNAK2 */
#define BANK2_FLASH_SECTOR_0 ((uint32_t)0x08100000) /* Bank2扇区0起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_1 ((uint32_t)0x08120000) /* Bank2扇区1起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_2 ((uint32_t)0x08140000) /* Bank2扇区2起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_3 ((uint32_t)0x08160000) /* Bank2扇区3起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_4 ((uint32_t)0x08180000) /* Bank2扇区4起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_5 ((uint32_t)0x081A0000) /* Bank2扇区5起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_6 ((uint32_t)0x081C0000) /* Bank2扇区6起始地址, 128 Kbytes */
#define BANK2_FLASH_SECTOR_7 ((uint32_t)0x081E0000) /* Bank2扇区7起始地址, 128 Kbytes */
不知道和内部的时钟主频配置有关系没
这是时钟树配置
|
-
时钟配置
|