📄 flashhelper.c
字号:
#include "FlashHelper.h"
/* address offset of each sector in internal flash memory */
static const struct flash_sector_info {
u32 base, mask;
} FlashSectorInfo[] = {
{0x000000, FLASH_B0F0},
{0x002000, FLASH_B0F1},
{0x004000, FLASH_B0F2},
{0x006000, FLASH_B0F3},
{0x008000, FLASH_B0F4},
{0x010000, FLASH_B0F5},
{0x020000, FLASH_B0F6},
{0x030000, FLASH_B0F7},
{0x040000, ~0},
{0x0C0000, FLASH_B1F0},
{0x0C2000, FLASH_B1F1},
{0x0C4000, ~0},
{~0, ~0},
};
void Flash_Init(void)
{
FLASH_Init();
}
static void IntFlash_Wait(void)
{
while(FLASHR->CR0 & 0x16);
}
int IntFlash_Program(u32 addr, const void *buf, u32 size)
{
const struct flash_sector_info *p;
u32 limit, mask;
addr -= INT_FLASH_BASE;
limit = addr + size;
p = FlashSectorInfo;
while(addr >= p[1].base)
p++;
mask = p->mask;
while(limit > p[1].base)
mask |= (++p)->mask;
if(mask == ~0)
return -1;
IntFlash_Wait();
FLASH_WritePrConfig(mask, DISABLE);
IntFlash_Wait();
FLASH_SectorErase(mask);
IntFlash_Wait();
FLASH_BlockWrite((u32)buf, addr, size + 3 >> 2);
IntFlash_Wait();
return 0;
}
#define FLASH_DATA(n) ( (n) >> 0 & 0x8000 /* D15 -> D15 */ \
| (n) >> 1 & 0x2000 /* D14 -> D13 */ \
| (n) >> 2 & 0x0800 /* D13 -> D11 */ \
| (n) >> 3 & 0x0200 /* D12 -> D9 */ \
| (n) >> 4 & 0x0080 /* D11 -> D7 */ \
| (n) >> 5 & 0x0020 /* D10 -> D5 */ \
| (n) >> 6 & 0x0008 /* D9 -> D3 */ \
| (n) >> 7 & 0x0002 /* D8 -> D1 */ \
| (n) << 7 & 0x4000 /* D7 -> D14 */ \
| (n) << 6 & 0x1000 /* D6 -> D12 */ \
| (n) << 5 & 0x0400 /* D5 -> D10 */ \
| (n) << 4 & 0x0100 /* D4 -> D8 */ \
| (n) << 3 & 0x0040 /* D3 -> D6 */ \
| (n) << 2 & 0x0010 /* D2 -> D4 */ \
| (n) << 1 & 0x0004 /* D1 -> D2 */ \
| (n) << 0 & 0x0001 /* D0 -> D0 */ )
#define FLASH_ADDR(a) ((vu16 *)(EXT_FLASH_BASE + ((a) << 1)))
#define FLASH_WRITE(addr, word) (*FLASH_ADDR(addr) = FLASH_DATA(word))
static void Check_Toggle_Ready(u32 addr)
{
int TimeOut;
int PreData = *FLASH_ADDR(addr) & FLASH_DATA(0x0040);
for(TimeOut = 0; TimeOut < 0x07FFFFFF; TimeOut++)
{
int CurData = *FLASH_ADDR(addr) & FLASH_DATA(0x0040);
if(PreData == CurData)
break;
PreData = CurData;
}
}
void ExtFlash_ChipErase(void)
{
FLASH_WRITE(0x5555, 0xaaaa);
FLASH_WRITE(0x2aaa, 0x5555);
FLASH_WRITE(0x5555, 0x8080);
FLASH_WRITE(0x5555, 0xaaaa);
FLASH_WRITE(0x2aaa, 0x5555);
FLASH_WRITE(0x5555, 0x1010);
Check_Toggle_Ready(0);
}
int ExtFlash_SectorErase(u32 addr)
{
addr = addr - EXT_FLASH_BASE >> 1;
if(addr >= EXT_FLASH_SIZE)
return -1;
FLASH_WRITE(0x5555, 0xaaaa);
FLASH_WRITE(0x2aaa, 0x5555);
FLASH_WRITE(0x5555, 0x8080);
FLASH_WRITE(0x5555, 0xaaaa);
FLASH_WRITE(0x2aaa, 0x5555);
FLASH_WRITE(addr, 0x3030);
Check_Toggle_Ready(addr);
return 0;
}
int ExtFlash_BlockErase(u32 addr)
{
addr = addr - EXT_FLASH_BASE >> 1;
if(addr >= EXT_FLASH_SIZE)
return -1;
FLASH_WRITE(0x5555, 0xaaaa);
FLASH_WRITE(0x2aaa, 0x5555);
FLASH_WRITE(0x5555, 0x8080);
FLASH_WRITE(0x5555, 0xaaaa);
FLASH_WRITE(0x2aaa, 0x5555);
FLASH_WRITE(addr, 0x5050);
Check_Toggle_Ready(addr);
return 0;
}
int ExtFlash_WordWrite(u32 addr, u16 data)
{
vu16 *ptr = (vu16 *)addr;
addr = addr - EXT_FLASH_BASE >> 1;
if(addr >= EXT_FLASH_SIZE)
return -1;
FLASH_WRITE(0x5555, 0xaaaa);
FLASH_WRITE(0x2aaa, 0x5555);
FLASH_WRITE(0x5555, 0xa0a0);
*ptr = data;
Check_Toggle_Ready(addr);
return *ptr;
}
int ExtFlash_Program(u32 addr, const void *buf, u32 size)
{
u32 i, limit = addr + size;
if(addr < EXT_FLASH_BASE || limit >= EXT_FLASH_LIMIT)
return -1;
for(i = addr & ~(SECTOR_SIZE - 1); i < limit; i += SECTOR_SIZE)
ExtFlash_SectorErase(i);
for(i = addr; i < limit; i += 2)
{
int PreData, TimeOut;
FLASH_WRITE(0x5555, 0xaaaa);
FLASH_WRITE(0x2aaa, 0x5555);
FLASH_WRITE(0x5555, 0xa0a0);
*(vu16 *)i = *(u16 *)buf;
PreData = *(vu16 *)i & FLASH_DATA(0x0040);
for(TimeOut = 0; TimeOut < 0x07FFFFFF; TimeOut++)
{
int CurData = *(vu16 *)i & FLASH_DATA(0x0040);
if(PreData == CurData)
break;
PreData = CurData;
}
buf = (u16 *)buf + 1;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -