/*
* 变更历史:
* 2015-02-13 whwei 创建该文件。
*/
/*
* @file mslS29GL512P.c
* @brief
* 功能:
* <li>本文件为Flash驱动程序,,完成Flash的读写功能。 </li>
*/
/* INCLUDE */
#include <arch.h>
#include <sysInterface.h>
#include <printk.h>
/* DEFINE */
#define FLASH_DEBUG 0
#define TRY_LOOPS 3
#define FLASH_BLOCK_NUM 1
#define FLASH_TIMEOUT 0x800000
/* DQx */
#define FLASH_DQ6 0x40
#define FLASH_DQ5 0x20
#define FALSH_DQ2 0x04
/* CODES */
#define FLASH_CODE1 0xAAAA
#define FLASH_CODE2 0x5555
#define ID_IN_CODE 0x9090
#define ID_OUT_CODE 0xF0F0
#define CMD_READ_ARRAY 0xF0F0
#define CMD_UNLOCK1 0xAAAA
#define CMD_UNLOCK2 0x5555
#define CMD_ERASE_SETUP 0x8080
#define CMD_ERASE_CONFIRM 0x3030
#define CMD_PROGRAM 0xA0A0
#define CMD_UNLOCK_BYPASS 0x2020
#define CMD_SECTOR_UNLOCK 0x7070
#define CMD_ERASE_CHIP 0x1010
#define MEM_FLASH_ADDR1 (0x555 << 1)
#define MEM_FLASH_ADDR2 (0x2AA << 1)
#define BIT_ERASE_DONE 0x8080
#define BIT_RDY_MASK 0x8080
#define BIT_PROGRAM_ERROR 0x2020
#define BIT_TIMEOUT 0x80000000 /* our flag */
/* IMPORT */
/*boot设备表*/
extern struct T_LBT_Devicedes *LBT_dev_tab ;
/*Flash配置表*/
static struct T_LBT_Flash_block flash_addr_tab[FLASH_BLOCK_NUM]=
{
{0x0, 0x20000, 0x7FFFFFF} // {开始, 最大扇区字节数,FLASH总空间大小}(start,size, end)
};
/* Flash驱动程序向前声明 */
static INT32 flash_init( UINT32 dev_num) __attribute__ ((section (".flash")));
static INT32 flash_sec_erase(UINT32 dev_num, UINT16 *sector_addr) __attribute__ ((section (".flash")));
static INT32 flash_program(UINT32 dev_num,UINT16 *start,UINT16 *src, UINT32 len) __attribute__ ((section (".flash")));
static INT32 flash_erase_check(UINT32 start_addr) __attribute__ ((section (".flash")));
static INT32 flash_program_check(UINT32 start_addr, UINT16 data) __attribute__ ((section (".flash")));
static volatile void Flash_Delay(int cnt) __attribute__ ((section (".flash")));
/*Flash 芯片配置表*/
struct T_LBT_Flash_chip S29GL512P =
{
"S29GL512P",
FLASH_BLOCK_NUM,
flash_addr_tab,
flash_init,
flash_sec_erase,
flash_program
};
/**
* @brief
* Flash延迟时间函数,通过循环进行延迟。
* @param[in] cnt:循环计数。
* @return
* 无
* @implements
*/
static volatile void Flash_Delay(int cnt)
{
cnt *= 50;
while (cnt){
cnt-- ;
}
}
/**
* @brief
* Flash芯片初始化。
* @param[in] dev_num:设备号。
* @return:
* LBT_SUCCESS:始终返回初始化成功。
* @implements
*/
static INT32 flash_init(UINT32 dev_num)
{
UINT32 f_start;
volatile UINT16 manuf_code, device_code_1, device_code_2, device_code_3;
f_start = ((T_LBT_Flash_bank*) ( LBT_dev_tab[dev_num].pri_info))->vir_start_addr ;
/* Reset (software reset of Flash state machine) */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR1, CMD_READ_ARRAY);
Flash_Delay(10);
/* Autoselect mode (getting manufacturer ID) */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR1, FLASH_CODE1); /* unlock cycle 1 */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR2, FLASH_CODE2); /* unlock cycle 2 */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR1, ID_IN_CODE); /* autoselect command */
/* multiple reads can be performed after entry */
manuf_code = *(volatile UINT16 *) f_start; /* read manuf. id */
device_code_1 = *(volatile UINT16 *) (f_start + (0x01 <<1));
device_code_2 = *(volatile UINT16 *) (f_start + (0x0E << 1));
device_code_3 = *(volatile UINT16 *) (f_start + (0x0F << 1));
#if FLASH_DEBUG
printk("ATMEL FLASH ID: manuf 0x%x, device_1 0x%x, device_2 0x%x, device_3 0x%x\n",
manuf_code, device_code_1, device_code_2, device_code_3);
#endif
FLASH_WriteWord(f_start+MEM_FLASH_ADDR1, FLASH_CODE1); /* unlock cycle 1 */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR2, FLASH_CODE2); /* unlock cycle 2 */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR1, ID_OUT_CODE); /* leave autoselect command */
return (LBT_SUCCESS );
}
static INT32 flash_erase_check(UINT32 start_addr)
{
UINT16 data1, data2;
UINT16 *addr = (UINT16*)(start_addr);
UINT32 timeout = FLASH_TIMEOUT;
#if FLASH_DEBUG
printk("begin check: %x\n", addr);
#endif
do{
data1 = *addr;
data2 = *addr;
if ((data1 ==0xffff) && (data2 ==0xffff))
{
return LBT_SUCCESS;
}
timeout--;
} while (timeout > 0);
#if FLASH_DEBUG
printk("flash_erase_check error!\n");
#endif
return LBT_FAILURE;
}
/**
* @brief
* Flash扇区擦除。
* @param[in] dev_num:设备号;
* @param[in] *sector_addr:擦除的扇区地址;
* @return:
* LBT_FAILURE:Flash扇区擦除失败;
* LBT_SUCCESS:Flash扇区擦除成功。
* @implements
*/
static INT32 flash_sec_erase( UINT32 dev_num, UINT16 *sector_addr)
{
UINT32 f_start;
INT32 result;
f_start = ((T_LBT_Flash_bank*) ( LBT_dev_tab[dev_num].pri_info))->vir_start_addr ;
#if FLASH_DEBUG
printk("dev_num = %x, flash_sec_erase %x!, f_start = %x\n",dev_num, sector_addr, f_start);
#endif
/* Reset (software reset of Flash state machine) */
FLASH_WriteWord(f_start,CMD_READ_ARRAY);
Flash_Delay(10);
/* Sector Erase Command */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR1, FLASH_CODE1); /* unlock cycle 1 */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR2, FLASH_CODE2); /* unlock cycle 2 */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR1, CMD_ERASE_SETUP); /* setup command */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR1, FLASH_CODE1); /* unlock cycle 1 */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR2, FLASH_CODE2); /* unlock cycle 2 */
FLASH_WriteWord(sector_addr, CMD_ERASE_CONFIRM); /* sector erase command */
result = flash_erase_check((UINT32)sector_addr);
return result;
}
static INT32 flash_program_check(UINT32 start_addr, UINT16 data)
{
UINT16 data1, data2;
UINT16 *addr = (UINT16*)(start_addr);
UINT32 timeout = 0x0FFFFFFF;
do{
data1 = *addr;
data2 = *addr;
if (data1 ==data2){
return LBT_SUCCESS;
}
timeout--;
} while (timeout > 0);
#if FLASH_DEBUG
printk("flash_program_check error!\n");
#endif
return LBT_FAILURE;
}
/**
* @brief
* Flash写程序。
* @param[in]
* UINT32 dev_num:设备号;
* UINT32 *fstart:写地址;
* UINT32 *src:源数据地址;
* UINT32 len:写数据长度,按字节计算;
* @return:
* LBT_FAILURE:Flash写失败;
* LBT_SUCCESS:Flash写成功。
* @implements
*/
static INT32 flash_program(UINT32 dev_num,UINT16 *start,UINT16 *src, UINT32 len)
{
UINT32 f_start;
UINT8 cnt;
UINT32 result;
UINT16 * src1 = src;
UINT16 * start1 = start;
UINT16 data0, data1;
f_start = ((T_LBT_Flash_bank*) ( LBT_dev_tab[dev_num].pri_info))->vir_start_addr ;
/* Reset (software reset of Flash state machine) */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR1, CMD_READ_ARRAY);
Flash_Delay(10);
#if FLASH_DEBUG
printk("begin flash_program!, start=%x, len=%x,src=%x\n",start, len, src);
#endif
while (len)
{
/* Check if Flash is (sufficiently) erased */
data0 = *start;
data1 = *src;
if ((data0 & data1) != data1)
{
printk("Flash not (sufficiently) erased\n");
return LBT_FAILURE;
}
/* Program Command */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR1, FLASH_CODE1); /* unlock cycle 1 */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR2, FLASH_CODE2); /* unlock cycle 2 */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR1, CMD_PROGRAM); /* program setup commandd */
FLASH_WriteWord(start1, *src1); /* write 16bit data to be programmed */
Flash_Delay(20);
result = flash_program_check(start1,*src1);
if(result == LBT_FAILURE)
return LBT_FAILURE;
len -= 2;
start1++;
src1++;
cnt = 0;
}
/* Reset Flash */
FLASH_WriteWord(f_start+MEM_FLASH_ADDR1, CMD_READ_ARRAY);
Flash_Delay(10);
return (LBT_SUCCESS);
}
评论1