?? flash.c
字號:
/****************************************Copyright (c)****************************************************
** ZhangZhou KENENG electronics Co.,LTD.
**
**
**
**--------------File Info---------------------------------------------------------------------------------
** File name: flash.c
** Last modified Date: 2009-03-11
** Last Version: 1.0
** Descriptions: 提供操作片外NOR FLASH的接口,當(dāng)前主要用到初始化函數(shù)
同時提供其他操作,以備將來BOOTLOADER功能擴展需要。
** 此驅(qū)動專針對SST39VF1601芯片,它是1Mx16寬的芯片。
** (此驅(qū)動在之前的bootloader代碼中完成,但是沒考慮軟件環(huán)境,
** 現(xiàn)在將其移植到uc/os-II的操作系統(tǒng)中,需要考慮uc/os-II操作系統(tǒng)
** 運行環(huán)境的一些因素,因此做了一些調(diào)整。大體框架不變)
**--------------------------------------------------------------------------------------------------------
** Created by: heshusheng
** Created date: 2009-03-11
** Version: 1.0
** Descriptions: The original version
**
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
**
*********************************************************************************************************/
//#include "flash.h"
#include "config.h"
#include "flash.h"
/********************************************************************************************************
**存儲flash信息;
*********************************************************************************************************/
static flash_info_type flash_info;
/********************************************************************************************************
* 轉(zhuǎn)換地址。將要發(fā)送給SST39VF1601的地址值進行轉(zhuǎn)換,以便于LPC2210輸出。
* 由于SST39VF1601的A0是與LPC2470的A1相連,所以addr要左移1位。
*********************************************************************************************************/
#define GetAddr(addr) (volatile uint16 *)(flash_info.base_addr|(addr<<1))
/********************************************************************************************************
*將16位的前后兩個字節(jié)進行顛倒處理
*
*********************************************************************************************************/
#define SWAP_16(x) ((uint16)( \
(((uint16)(x) & (uint16)0x00ffU) << 8) | \
(((uint16)(x) & (uint16)0xff00U) >> 8) ))
/********************************************************************************************************
*定義最大地址
*
*********************************************************************************************************/
#define MAX_ADDR() (flash_info.base_addr + flash_info.size)
/*********************************************************************************************************
* 名 稱:WordProgram()
* 功 能:半字(16位)數(shù)據(jù)編程。
* 入口參數(shù):Addr 編程地址(SST39VF1601內(nèi)部地址)
* Data 編程數(shù)據(jù)
* 出口參數(shù):返回TRUE表示操作成功,返回FALSE表示操作失敗
**********************************************************************************************************/
uint8 WordProgram(uint32 iAddr, uint16 iData)
{
volatile uint16 *ipTmp;
uint16 itemp1,itemp2;
OS_ENTER_CRITICAL( );
ipTmp = GetAddr(0x5555); /* 轉(zhuǎn)換地址0x5555 */
ipTmp[0] = 0xaaaa; /* 第一個周期,地址0x5555,數(shù)據(jù)0xAA*/
ipTmp = GetAddr(0x2aaa);
ipTmp[0] = 0x5555; /* 第二個周期,地址0x2aaa,數(shù)據(jù)0x55*/
ipTmp = GetAddr(0x5555);
ipTmp[0] = 0xa0a0; /* 第三個周期,地址0x5555,數(shù)據(jù)0xA0*/
ipTmp = (volatile uint16 *)iAddr;
*ipTmp = iData; /* 第四個周期,地址Addr,數(shù)據(jù)Data */
OS_EXIT_CRITICAL( );
/*
* 等待操作完成 (若編程操作沒有完成,每次讀操作DQ6會跳變)
*/
while (1)
{
itemp1 = *ipTmp;
itemp2 = *ipTmp;
if (itemp1 == itemp2)
{
itemp1 = *ipTmp;
itemp2 = *ipTmp;
if (itemp1 != iData)
return(FALSE);
return(TRUE);
}
}
}
/*********************************************************************************************************
* 名 稱:flash_erase_sector
* 功 能:擦除指定的扇區(qū) 4Kbyte
* 入口參數(shù):Addr 編程地址
* no 扇區(qū)數(shù)目
* 出口參數(shù):返回TRUE表示操作成功,返回FALSE表示操作失敗
**********************************************************************************************************/
int flash_erase_sector(long addr, int no)
{
volatile uint16 *ipTmp;
uint16 itemp1,itemp2;
int i;
for (i = 0; i < no; i++)
{
if (addr <= MAX_ADDR())
{
OS_ENTER_CRITICAL( );
ipTmp = GetAddr(0x5555);
ipTmp[0] = 0xaaaa;
ipTmp = GetAddr(0x2aaa);
ipTmp[0] = 0x5555;
ipTmp = GetAddr(0x5555);
ipTmp[0] = 0x8080;
ipTmp = GetAddr(0x5555);
ipTmp[0] = 0xaaaa;
ipTmp = GetAddr(0x2aaa);
ipTmp[0] = 0x5555;
ipTmp = (volatile uint16 *)addr;
*ipTmp = 0x3030;
OS_EXIT_CRITICAL( );
/*
* 等待操作完成 (若編程操作沒有完成,每次讀操作DQ6會跳變)
*/
while (1)
{
itemp1 = *ipTmp;
itemp2 = *ipTmp;
if (itemp1 == itemp2)
if (itemp1 != 0xffff)
return 0;
else
break;
}
addr += flash_info.sector_size;
}
else
return 1;
}
return 1;
}
/*********************************************************************************************************
* 名 稱:flash_erase_block
* 功 能:擦除指定的塊64Kbyte
* 入口參數(shù):Addr 編程地址
* no 塊數(shù)目
* 出口參數(shù):返回TRUE表示操作成功,返回FALSE表示操作失敗
**********************************************************************************************************/
int flash_erase_block(long addr, int no)
{
volatile uint16 *ipTmp;
uint16 itemp1,itemp2;
int i;
for (i = 0; i < no; i++)
{
if (addr <= MAX_ADDR())
{
OS_ENTER_CRITICAL( );
ipTmp = GetAddr(0x5555);
ipTmp[0] = 0xaaaa;
ipTmp = GetAddr(0x2aaa);
ipTmp[0] = 0x5555;
ipTmp = GetAddr(0x5555);
ipTmp[0] = 0x8080;
ipTmp = GetAddr(0x5555);
ipTmp[0] = 0xaaaa;
ipTmp = GetAddr(0x2aaa);
ipTmp[0] = 0x5555;
ipTmp = (volatile uint16 *)addr;
*ipTmp = 0x5050;
OS_EXIT_CRITICAL( );
/*
* 等待操作完成 (若編程操作沒有完成,每次讀操作DQ6會跳變)
*/
while (1)
{
itemp1 = *ipTmp;
itemp2 = *ipTmp;
if (itemp1 == itemp2)
if (itemp1 != 0xffff)
return 0;
else
break;
}
addr += flash_info.block_size;
}
else
return 1;
}
return 1;
}
/*********************************************************************************************************
* 名 稱:flash_erase_chip()
* 功 能:提供接口供給外部調(diào)用,擦除全片數(shù)據(jù)
* 入口參數(shù):
* 出口參數(shù):返回TRUE表示操作成功,返回FALSE表示操作失敗
**********************************************************************************************************/
int flash_erase_chip( void )
{
volatile uint16 *ipTmp;
uint16 itemp1,itemp2;
OS_ENTER_CRITICAL( );
ipTmp = GetAddr(0x5555);
ipTmp[0] = 0xaaaa; /* 第一個周期,地址0x5555,數(shù)據(jù)0xAA*/
ipTmp = GetAddr(0x2aaa);
ipTmp[0] = 0x5555; /* 第二個周期,地址0x2aaa,數(shù)據(jù)0x55*/
ipTmp = GetAddr(0x5555);
ipTmp[0] = 0x8080; /* 第三個周期,地址0x5555,數(shù)據(jù)0x80*/
ipTmp = GetAddr(0x5555);
ipTmp[0] = 0xaaaa; /* 第四個周期,地址0x5555,數(shù)據(jù)0xAA*/
ipTmp = GetAddr(0x2aaa);
ipTmp[0] = 0x5555; /* 第五個周期,地址0x2aaa,數(shù)據(jù)0x55*/
ipTmp = GetAddr(0x5555);
ipTmp[0] = 0x1010; /* 第六個周期,地址0x5555,數(shù)據(jù)0x10*/
OS_EXIT_CRITICAL( );
/*
* 等待操作完成 (若擦除操作沒有完成,每次讀操作DQ6會跳變)
*/
while (1)
{
itemp1 = *ipTmp;
itemp2 = *ipTmp;
if (itemp1 == itemp2)
{
if (itemp1 != 0xffff)
return(FALSE);
return(TRUE);
}
}
}
/*********************************************************************************************************
* 名 稱:flash_write()
* 功 能:提供接口供給外部調(diào)用,按字節(jié)進行編程。
* 入口參數(shù):src 寫入的數(shù)據(jù)緩存
* addr : 寫入的地址,使用0x81******開頭的地址
* cnt :寫入的數(shù)據(jù)長度
* 出口參數(shù):返回TRUE表示操作成功,返回FALSE表示操作失敗
**********************************************************************************************************/
int flash_write(char *src,long addr,long cnt)
{
long cp, wp;
uint16 data;
int count, i, l, rc, port_width;
if ( (addr + cnt) > MAX_ADDR())
return FALSE;
wp = (addr & ~1);
port_width = 2;
/*處理非16位對齊的起始地址*/
if ((l = addr - wp) != 0) {
data = 0;
for (i = 0, cp = wp; i < l; ++i, ++cp) {
data = (data << 8) | (*(char *) cp);
}
for (; i < port_width && cnt > 0; ++i) {
data = (data << 8) | *src++;
--cnt;
++cp;
}
for (; cnt == 0 && i < port_width; ++i, ++cp) {
data = (data << 8) | (*(char *) cp);
}
if ((rc = WordProgram( wp, SWAP_16 (data))) == 0) {
return (rc);
}
wp += port_width;
}
/*處理對齊后的數(shù)據(jù)部分*/
count = 0;
while (cnt >= port_width) {
data = 0;
for (i = 0; i < port_width; ++i) {
data = (data << 8) | *src++;
}
if ((rc = WordProgram( wp, SWAP_16 (data))) == 0) {
return (rc);
}
wp += port_width;
cnt -= port_width;
if (count++ > 0x800) {
count = 0;
}
}
if (cnt == 0) {
return (1);
}
/*處理非16位對齊的結(jié)尾地址*/
data = 0;
for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) {
data = (data << 8) | *src++;
--cnt;
}
for (; i < port_width; ++i, ++cp) {
data = (data << 8) | (*(char *) cp);
}
return (WordProgram ( wp, SWAP_16 (data)));
}
/*********************************************************************************************************
* 名 稱:flash_get_id()
* 功 能:獲取flash id.用于判斷當(dāng)前EMC外接的NOR FLASH的類型
* 入口參數(shù):無
* 出口參數(shù):16位flash id.
**********************************************************************************************************/
static uint16 flash_get_id( void )
{
volatile uint16 *ipTmp;
uint16 itemp;
//enter cfi read mode.
OS_ENTER_CRITICAL( );
ipTmp = GetAddr(0x5555); /* 轉(zhuǎn)換地址0x5555 */
ipTmp[0] = 0xaaaa; /* 第一個周期,地址0x5555,數(shù)據(jù)0xAA*/
ipTmp = GetAddr(0x2aaa);
ipTmp[0] = 0x5555; /* 第二個周期,地址0x2aaa,數(shù)據(jù)0x55*/
ipTmp = GetAddr(0x5555);
ipTmp[0] = 0x9898; /* 第三個周期,地址0x5555,數(shù)據(jù)0x98*/
OS_EXIT_CRITICAL( );
//SST flash
ipTmp = GetAddr(0x0000);
itemp = *ipTmp;
if ( itemp != 0xbf)
return FALSE;
//read id.
ipTmp = GetAddr(0x0001);
itemp = *ipTmp;
//exit cfi read mode.
OS_ENTER_CRITICAL( );
ipTmp = GetAddr(0x5555); /* 轉(zhuǎn)換地址0x5555 */
ipTmp[0] = 0xaaaa; /* 第一個周期,地址0x5555,數(shù)據(jù)0xAA*/
ipTmp = GetAddr(0x2aaa);
ipTmp[0] = 0x5555; /* 第二個周期,地址0x2aaa,數(shù)據(jù)0x55*/
ipTmp = GetAddr(0x5555);
ipTmp[0] = 0xf0f0; /* 第三個周期,地址0x5555,數(shù)據(jù)0xf0*/
OS_EXIT_CRITICAL( );
return itemp;
}
/*********************************************************************************************************
* 名 稱:flash_init()
* 功 能:提供接口供給外部調(diào)用,NORFLASH 初始化函數(shù)
* 入口參數(shù):無
* 出口參數(shù):無
**********************************************************************************************************/
void flash_init( void )
{
uint16 id;
//硬件初始化
PINSEL6 = 0x55555555;
PINSEL8 = 0x55555555;
PINSEL9 |= 0x40050155;
EMCControl = 0x01;
EMCStaticConfig1 = 0x00000081;
EMCStaticWaitRd1 = 0x04;
EMCStaticWaitOen1 = 0x01;
EMCStaticWaitWen1 = 0x00;
EMCStaticWaitWr1 = 0x02;
//讀取flash物理設(shè)備的ID。
flash_info.base_addr = 0x81000000;
id = flash_get_id( );
switch(id)
{
//39vf1601
case 0x234b:
flash_info.size = 0x200000;
flash_info.sector_size = 0x1000;
flash_info.block_size = 0x10000;
break;
//add other types of flash.
default:
break;
}
}
/*--------------------------------------------------------------------------------------------------------------------------------
** END OF FILE
----------------------------------------------------------------------------------------------------------------------------------*/
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -