📄 flash.c
字号:
/*********************************************************************************************
* File: flash.c
* Author: embest
* Desc: AT49BV1614A & AM29LV160DB Flash program code
* History:
*********************************************************************************************/
#include "flash.h"
#define OS_CRITICAL_METHOD 0
#define OS_CPU_SR unsigned int
#define OS_ENTER_CRITICAL()
#define OS_EXIT_CRITICAL()
/*
* Flash ID
*/
static unsigned short id_man, id_dev, id_ade;
/*
* delay function
*/
static void Flash_Delay(void)
{
volatile unsigned int i;
/* delay about 70 us */
for(i=0; i<231; i++);
}
/*
* AT49BV1614A
*/
static void FlashID_AT49BV1614A(unsigned int base_addr)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
base_addr &= ~AT49BV1614A_FLASH_MASK;
OS_ENTER_CRITICAL();
/* enter read ID mode */
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
*(volatile unsigned short *)(base_addr + (0xAAA<<1)) = 0x55;
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0x90;
/* read ID */
id_man = *(volatile unsigned short *)(base_addr + (0x00<<1));
id_dev = *(volatile unsigned short *)(base_addr + (0x01<<1));
id_ade = *(volatile unsigned short *)(base_addr + (0x03<<1));
/* exit read ID mode */
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
*(volatile unsigned short *)(base_addr + (0xAAA<<1)) = 0x55;
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xF0;
OS_EXIT_CRITICAL();
}
/*
* AT49BV1614A
*/
static void FlashEraseSector_AT49BV1614A(unsigned int base_addr)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
unsigned int i, sector_addr;
sector_addr = (base_addr & AT49BV1614A_FLASH_MASK);
sector_addr >>= 1;
sector_addr <<= 1;
base_addr &= ~AT49BV1614A_FLASH_MASK;
OS_ENTER_CRITICAL();
/* enter erase sector mode */
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
*(volatile unsigned short *)(base_addr + (0xAAA<<1)) = 0x55;
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0x80;
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
*(volatile unsigned short *)(base_addr + (0xAAA<<1)) = 0x55;
*(volatile unsigned short *)(base_addr + (sector_addr)) = 0x30;
/* delay about 420 ms */
for(i=0; i<6000; i++)
Flash_Delay();
OS_EXIT_CRITICAL();
}
/*
* AT49BV1614A
*/
static void FlashProgram_AT49BV1614A(unsigned int base_addr, unsigned short *data_addr, unsigned int bytes)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
unsigned int i, word_addr;
word_addr = (base_addr & AT49BV1614A_FLASH_MASK);
base_addr &= ~AT49BV1614A_FLASH_MASK;
if(bytes % 2)
bytes += 1;
bytes >>= 1;
/* enter program mode */
for(i=0; i<bytes; i++)
{
OS_ENTER_CRITICAL();
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
*(volatile unsigned short *)(base_addr + (0xAAA<<1)) = 0x55;
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xA0;
*(volatile unsigned short *)(base_addr + (word_addr)) = data_addr[i];
/* delay 50 us */
Flash_Delay();
word_addr += sizeof(unsigned short);
OS_EXIT_CRITICAL();
}
}
static unsigned int FlashSectorSize_AT49BV1614A(unsigned int base_addr)
{
unsigned int sector_addr = (base_addr & AT49BV1614A_FLASH_MASK);
if(sector_addr >= 0x00 && sector_addr < 0x10000)
return (8*1024);
else if(sector_addr >= 0x10000 && sector_addr < 0x200000)
return (64*1024);
else
return 0;
}
/*
* AM29LV160B/DB
*/
static void FlashID_AM29LV160DB(unsigned int base_addr)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
base_addr &= ~AM29LV160DB_FLASH_MASK;
OS_ENTER_CRITICAL();
/* enter read man_ID mode */
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
*(volatile unsigned short *)(base_addr + (0x2AA<<1)) = 0x55;
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0x90;
/* read man_ID */
id_man = *(volatile unsigned short *)(base_addr + (0x00<<1));
/* enter read dev_ID mode */
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
*(volatile unsigned short *)(base_addr + (0x2AA<<1)) = 0x55;
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0x90;
/* read dev_ID */
id_dev = *(volatile unsigned short *)(base_addr + (0x01<<1));
id_ade = AM29LV160DB_ADE_ID;
OS_EXIT_CRITICAL();
}
/*
* AM29LV160B/DB
*/
static void FlashEraseSector_AM29LV160DB(unsigned int base_addr)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
unsigned int i, sector_addr;
sector_addr = (base_addr & AM29LV160DB_FLASH_MASK);
sector_addr >>= 1;
sector_addr <<= 1;
base_addr &= ~AM29LV160DB_FLASH_MASK;
OS_ENTER_CRITICAL();
/* enter erase sector mode */
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
*(volatile unsigned short *)(base_addr + (0x2AA<<1)) = 0x55;
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0x80;
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
*(volatile unsigned short *)(base_addr + (0x2AA<<1)) = 0x55;
*(volatile unsigned short *)(base_addr + (sector_addr)) = 0x30;
/* delay about 700 ms */
for(i=0; i<10000; i++)
Flash_Delay();
OS_EXIT_CRITICAL();
}
/*
* AM29LV160B/DB
*/
static void FlashProgram_AM29LV160DB(unsigned int base_addr, unsigned short *data_addr, unsigned int bytes)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
unsigned int i, word_addr;
word_addr = (base_addr & AM29LV160DB_FLASH_MASK);
base_addr &= ~AM29LV160DB_FLASH_MASK;
if(bytes % 2)
bytes += 1;
bytes >>= 1;
/* enter programe mode */
for(i=0; i<bytes; i++)
{
OS_ENTER_CRITICAL();
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
*(volatile unsigned short *)(base_addr + (0x2AA<<1)) = 0x55;
*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xA0;
*(volatile unsigned short *)(base_addr + (word_addr)) = data_addr[i];
/* delay 50 us */
Flash_Delay();
word_addr += sizeof(unsigned short);
OS_EXIT_CRITICAL();
}
}
static unsigned int FlashSectorSize_AM29LV160DB(unsigned int base_addr)
{
unsigned int sector_addr = (base_addr & AM29LV160DB_FLASH_MASK);
if(sector_addr >= 0x00 && sector_addr < 0x4000)
return (16*1024);
else if(sector_addr >= 0x4000 && sector_addr < 0x6000)
return (8*1024);
else if(sector_addr >= 0x6000 && sector_addr < 0x8000)
return (8*1024);
else if(sector_addr >= 0x8000 && sector_addr < 0x10000)
return (32*1024);
else if(sector_addr >= 0x10000 && sector_addr < 0x200000)
return (64*1024);
else
return 0;
}
/*
* Flash ID
*/
int FlashID(unsigned int base_addr)
{
/* read AT49BV1614A flash ID */
FlashID_AT49BV1614A(base_addr);
if( id_man == AT49BV1614A_MAN_ID &&
id_dev == AT49BV1614A_DEV_ID &&
id_ade == AT49BV1614A_ADE_ID )
{
return 1;
}
/* read AM29LV160B/DB flash ID */
FlashID_AM29LV160DB(base_addr);
if( id_man == AM29LV160DB_MAN_ID &&
id_dev == AM29LV160DB_DEV_ID &&
id_ade == AM29LV160DB_ADE_ID )
{
return 1;
}
return 0;
}
/*
* Erase Sector
*/
void FlashEraseSector(unsigned int base_addr)
{
/* AT49BV1614A */
if( id_man == AT49BV1614A_MAN_ID &&
id_dev == AT49BV1614A_DEV_ID &&
id_ade == AT49BV1614A_ADE_ID )
{
FlashEraseSector_AT49BV1614A(base_addr);
}
/* AM29LV160B/DB */
else if(id_man == AM29LV160DB_MAN_ID &&
id_dev == AM29LV160DB_DEV_ID &&
id_ade == AM29LV160DB_ADE_ID )
{
FlashEraseSector_AM29LV160DB(base_addr);
}
}
/*
* Program Flash
*/
void FlashProgram(unsigned int base_addr, unsigned short *data_addr, unsigned int bytes)
{
/* AT49BV1614A */
if( id_man == AT49BV1614A_MAN_ID &&
id_dev == AT49BV1614A_DEV_ID &&
id_ade == AT49BV1614A_ADE_ID )
{
FlashProgram_AT49BV1614A(base_addr, data_addr, bytes);
}
/* AM29LV160B/DB */
else if(id_man == AM29LV160DB_MAN_ID &&
id_dev == AM29LV160DB_DEV_ID &&
id_ade == AM29LV160DB_ADE_ID )
{
FlashProgram_AM29LV160DB(base_addr, data_addr, bytes);
}
}
/*
* Flash sector's size
*/
unsigned int FlashSectorSize(unsigned int base_addr)
{
unsigned int size = 0;
/* AT49BV1614A */
if( id_man == AT49BV1614A_MAN_ID &&
id_dev == AT49BV1614A_DEV_ID &&
id_ade == AT49BV1614A_ADE_ID )
{
size = FlashSectorSize_AT49BV1614A(base_addr);
}
/* AM29LV160B/DB */
else if(id_man == AM29LV160DB_MAN_ID &&
id_dev == AM29LV160DB_DEV_ID &&
id_ade == AM29LV160DB_ADE_ID )
{
size = FlashSectorSize_AM29LV160DB(base_addr);
}
return size;
}
/*
* Flash sector's backup
*/
unsigned int FlashSectorBackup(unsigned int base_addr, unsigned char *buf)
{
unsigned int size;
size = FlashSectorSize(base_addr);
if(size > 0)
{
unsigned int i;
unsigned char *ptr;
ptr = (unsigned char *)(base_addr & (0 - size));
for(i=0; i<size; i++)
buf[i] = *ptr++;
}
return size;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -