⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flashhelper.c

📁 基于STR711的PRCCU程序
💻 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 + -