7 changed files with 222 additions and 24 deletions
-
2app/Core/Src/main.c
-
32app/MDK-ARM/app.uvguix.29643
-
20app/MDK-ARM/app.uvoptx
-
5app/MDK-ARM/app.uvprojx
-
7src/usermain.c
-
148src/zflash.c
-
32src/zflash.h
32
app/MDK-ARM/app.uvguix.29643
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,148 @@ |
|||||
|
#include "zflash.h" |
||||
|
|
||||
|
static bool stmflash_address_legal(uint32_t start_addr, uint32_t end_addr) { |
||||
|
if (start_addr < STM32_FLASH_BASE || start_addr % 4 || start_addr > (STM32_FLASH_BASE + STM32_FLASH_SIZE)) { |
||||
|
return false; |
||||
|
} |
||||
|
if (end_addr < STM32_FLASH_BASE || end_addr % 4 || end_addr > (STM32_FLASH_BASE + STM32_FLASH_SIZE)) { |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @brief 从指定地址读取一个字 (32位数据) |
||||
|
* @param faddr : 读取地址 (此地址必须为4倍数!!) |
||||
|
* @retval 读取到的数据 (32位) |
||||
|
*/ |
||||
|
uint32_t stmflash_read_word(uint32_t faddr) { return *(volatile uint32_t *)faddr; } |
||||
|
|
||||
|
/** |
||||
|
* @brief 获取某个地址所在的flash扇区 |
||||
|
* @param addr : lash地址 |
||||
|
* @retval 0~11,即addr所在的扇区 |
||||
|
*/ |
||||
|
uint8_t stmflash_get_flash_sector(uint32_t addr) { |
||||
|
if (addr < ADDR_FLASH_SECTOR_1) |
||||
|
return FLASH_SECTOR_0; |
||||
|
else if (addr < ADDR_FLASH_SECTOR_2) |
||||
|
return FLASH_SECTOR_1; |
||||
|
else if (addr < ADDR_FLASH_SECTOR_3) |
||||
|
return FLASH_SECTOR_2; |
||||
|
else if (addr < ADDR_FLASH_SECTOR_4) |
||||
|
return FLASH_SECTOR_3; |
||||
|
else if (addr < ADDR_FLASH_SECTOR_5) |
||||
|
return FLASH_SECTOR_4; |
||||
|
else if (addr < ADDR_FLASH_SECTOR_6) |
||||
|
return FLASH_SECTOR_5; |
||||
|
else if (addr < ADDR_FLASH_SECTOR_7) |
||||
|
return FLASH_SECTOR_6; |
||||
|
else if (addr < ADDR_FLASH_SECTOR_8) |
||||
|
return FLASH_SECTOR_7; |
||||
|
else if (addr < ADDR_FLASH_SECTOR_9) |
||||
|
return FLASH_SECTOR_8; |
||||
|
else if (addr < ADDR_FLASH_SECTOR_10) |
||||
|
return FLASH_SECTOR_9; |
||||
|
else if (addr < ADDR_FLASH_SECTOR_11) |
||||
|
return FLASH_SECTOR_10; |
||||
|
return FLASH_SECTOR_11; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @brief 在FLASH 指定位置, 写入指定长度的数据(自动擦除) |
||||
|
* @note 因为STM32F4的扇区实在太大,没办法本地保存扇区数据,所以本函数写地址如果非0XFF |
||||
|
* ,那么会先擦除整个扇区且不保存扇区数据.所以写非0XFF的地址,将导致整个扇区数据丢失. |
||||
|
* 建议写之前确保扇区里没有重要数据,最好是整个扇区先擦除了,然后慢慢往后写. |
||||
|
* 该函数对OTP区域也有效!可以用来写OTP区! |
||||
|
* OTP区域地址范围:0X1FFF7800~0X1FFF7A0F(注意:最后16字节,用于OTP数据块锁定,别乱写!!) |
||||
|
* @param start_address : 起始地址 (此地址必须为4的倍数!!,否则写入出错!) |
||||
|
* @param pbuf : 数据指针 |
||||
|
* @param length : 要写入的 字(32位)数(就是要写入的32位数据的个数) |
||||
|
* @retval 无 |
||||
|
*/ |
||||
|
void stmflash_write(uint32_t start_address, uint32_t *pbuf, uint32_t length) { |
||||
|
FLASH_EraseInitTypeDef flasheraseinit; |
||||
|
HAL_StatusTypeDef FlashStatus = HAL_OK; |
||||
|
|
||||
|
uint32_t flash_write_start_address = 0; |
||||
|
uint32_t flash_write_end_address = 0; |
||||
|
uint32_t sectorerror = 0; |
||||
|
|
||||
|
flash_write_start_address = start_address; /* 写入的起始地址 */ |
||||
|
flash_write_end_address = start_address + length * 4; /* 写入的结束地址 */ |
||||
|
|
||||
|
if (!stmflash_address_legal(flash_write_start_address, flash_write_end_address)) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
HAL_FLASH_Unlock(); /* 解锁 */ |
||||
|
FLASH->ACR &= ~(1 << 10); /* FLASH擦除期间,必须禁止数据缓存!!! */ |
||||
|
|
||||
|
if (flash_write_start_address < 0X1FFF0000) /* 只有主存储区,才需要执行擦除操作!! */ |
||||
|
{ |
||||
|
while (flash_write_start_address < flash_write_end_address) /* 扫清一切障碍.(对非FFFFFFFF的地方,先擦除) */ |
||||
|
{ |
||||
|
if (stmflash_read_word(flash_write_start_address) != 0XFFFFFFFF) /* 有非0XFFFFFFFF的地方,要擦除这个扇区 */ |
||||
|
{ |
||||
|
flasheraseinit.TypeErase = FLASH_TYPEERASE_SECTORS; /* 擦除类型,扇区擦除 */ |
||||
|
flasheraseinit.Sector = stmflash_get_flash_sector(flash_write_start_address); /* 要擦除的扇区 */ |
||||
|
flasheraseinit.NbSectors = 1; /* 一次只擦除一个扇区 */ |
||||
|
flasheraseinit.VoltageRange = FLASH_VOLTAGE_RANGE_3; /* 电压范围,VCC=2.7~3.6V之间!! */ |
||||
|
|
||||
|
if (HAL_FLASHEx_Erase(&flasheraseinit, §orerror) != HAL_OK) { |
||||
|
break; /* 发生错误了 */ |
||||
|
} |
||||
|
|
||||
|
} else { |
||||
|
flash_write_start_address += 4; |
||||
|
} |
||||
|
FLASH_WaitForLastOperation(FLASH_WAITETIME); /* 等待上次操作完成 */ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
FlashStatus = FLASH_WaitForLastOperation(FLASH_WAITETIME); /* 等待上次操作完成 */ |
||||
|
|
||||
|
if (FlashStatus == HAL_OK) { |
||||
|
while (start_address < flash_write_end_address) /* 写数据 */ |
||||
|
{ |
||||
|
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, start_address, *pbuf) != HAL_OK) /* 写入数据 */ |
||||
|
{ |
||||
|
break; /* 写入异常 */ |
||||
|
} |
||||
|
|
||||
|
start_address += 4; |
||||
|
pbuf++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
FLASH->ACR |= 1 << 10; /* FLASH擦除结束,开启数据fetch */ |
||||
|
|
||||
|
HAL_FLASH_Lock(); /* 上锁 */ |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @brief 从指定地址开始读出指定长度的数据 |
||||
|
* @param raddr : 起始地址 |
||||
|
* @param pbuf : 数据指针 |
||||
|
* @param length: 要读取的字(32)数,即4个字节的整数倍 |
||||
|
* @retval 无 |
||||
|
*/ |
||||
|
void stmflash_read(uint32_t raddr, uint32_t *pbuf, uint32_t length) { |
||||
|
uint32_t i; |
||||
|
|
||||
|
for (i = 0; i < length; i++) { |
||||
|
pbuf[i] = stmflash_read_word(raddr); /* 读取4个字节. */ |
||||
|
raddr += 4; /* 偏移4个字节. */ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/******************************************************************************************/ |
||||
|
/* 测试用代码 */ |
||||
|
|
||||
|
/** |
||||
|
* @brief 测试写数据(写1个字) |
||||
|
* @param waddr : 起始地址 |
||||
|
* @param wdata : 要写入的数据 |
||||
|
* @retval 读取到的数据 |
||||
|
*/ |
||||
|
void test_write(uint32_t waddr, uint32_t wdata) { stmflash_write(waddr, &wdata, 1); /* 写入一个字 */ } |
@ -0,0 +1,32 @@ |
|||||
|
#ifndef __STMFLASH_H |
||||
|
#define __STMFLASH_H |
||||
|
|
||||
|
#include <stdbool.h> |
||||
|
|
||||
|
#include "stm32f4xx_hal.h" |
||||
|
/* FLASH起始地址 */ |
||||
|
#define STM32_FLASH_SIZE 0x100000 /* STM32 FLASH 总大小 */ |
||||
|
#define STM32_FLASH_BASE 0x08000000 /* STM32 FLASH 起始地址 */ |
||||
|
#define FLASH_WAITETIME 50000 /* FLASH等待超时时间 */ |
||||
|
|
||||
|
/* FLASH 扇区的起始地址 */ |
||||
|
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* 扇区0起始地址, 16 Kbytes */ |
||||
|
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* 扇区1起始地址, 16 Kbytes */ |
||||
|
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* 扇区2起始地址, 16 Kbytes */ |
||||
|
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* 扇区3起始地址, 16 Kbytes */ |
||||
|
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* 扇区4起始地址, 64 Kbytes */ |
||||
|
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* 扇区5起始地址, 128 Kbytes */ |
||||
|
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* 扇区6起始地址, 128 Kbytes */ |
||||
|
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* 扇区7起始地址, 128 Kbytes */ |
||||
|
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* 扇区8起始地址, 128 Kbytes */ |
||||
|
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* 扇区9起始地址, 128 Kbytes */ |
||||
|
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* 扇区10起始地址,128 Kbytes */ |
||||
|
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* 扇区11起始地址,128 Kbytes */ |
||||
|
|
||||
|
uint32_t stmflash_read_word(uint32_t faddr); /* 读出字 */ |
||||
|
void stmflash_write(uint32_t waddr, uint32_t *pbuf, uint32_t length); /* 从指定地址开始写入指定长度的数据 */ |
||||
|
void stmflash_read(uint32_t raddr, uint32_t *pbuf, uint32_t length); /* 从指定地址开始读出指定长度的数据 */ |
||||
|
|
||||
|
void test_write(uint32_t waddr, uint32_t wdata); /* 测试写入 */ |
||||
|
|
||||
|
#endif |
Write
Preview
Loading…
Cancel
Save
Reference in new issue