📄 norflash_rw.txt
字号:
#define DEV_ID_1 0x227E227E
#define DEV_ID_AD_1 (CS_BASE + 0x1)
#define DEV_ID_2 0x22302230
#define DEV_ID_AD_2 (CS_BASE + 0xE)
#define DEV_ID_3 0x22002200
#define DEV_ID_AD_3 (CS_BASE + 0xF)
// base addresses of FLASH banks (based on 16-bit address given in flash data sheet)
#define BANK_0 (CS_BASE)
#define BANK_1 (CS_BASE + 0x100000)
#define BANK_2 (CS_BASE + 0x200000)
#define BANK_3 (CS_BASE + 0x300000)
#define BANK_4 (CS_BASE + 0x400000)
#define BANK_5 (CS_BASE + 0x500000)
#define BANK_6 (CS_BASE + 0x600000)
#define BANK_7 (CS_BASE + 0x700000)
#define BANK_8 (CS_BASE + 0x800000)
#define BANK_9 (CS_BASE + 0x900000)
#define BANK_10 (CS_BASE + 0xA00000)
#define BANK_11 (CS_BASE + 0xB00000)
#define BANK_12 (CS_BASE + 0xC00000)
#define BANK_13 (CS_BASE + 0xD00000)
#define BANK_14 (CS_BASE + 0xE00000)
#define BANK_15 (CS_BASE + 0xF00000)
// used for convenience during polling
#define DQ7 ((1<<23)|(1<<7))
#define DQ6 ((1<<22)|(1<<6))
#define DQ5 ((1<<21)|(1<<5))
#define DQ4 ((1<<20)|(1<<4))
#define DQ3 ((1<<19)|(1<<3))
#define DQ2 ((1<<18)|(1<<2))
#define DQ1 ((1<<17)|(1<<1))
#define DQ0 ((1<<16)|(1<<0))
/******************************
****** Globals Variables ******
******************************/
unsigned char UBM = 0; //Unlock Bypass Mode flag
volatile unsigned int gFailCount;
/*****************************
****** Function Defines ******
*****************************/
/* Sector Base Address Convertor */
// Takes in flexible input to return base address of desired sector
// Parameter: int sector = negative of Sector # [0:-261]
// or Flash address in desired sector [0:0xFFFFFF]
// or System address in desired sector (CS_BASE+[0:0xFFFFFF])
// Returns: Base address of the sector calculated, or 'null' if the input is invalid
// as a "volatile unsigned int *"
// Examples: assuming CS_BASE = 0xC0000000
// Correct:
// sector_calc(-15) would return the base address of sector 15 (0xC0300000) (flash addr is 0x0C0000)
// sector_calc(0x0CA820) would return the base address of sector 15 also
// sector_calc(0x1634A820) would return the base address of sector 15 as well
// sector_calc(0) returns CS_BASE
// Incorrect:
// sector_calc(-273) would return null, as there is not a sector 273
// sector_calc(0x1FFFFFF) would return null, as the address is outside of the flash
volatile unsigned int * sector_bcalc(int sector){
// sector number (negative number)
if(sector<1){
sector*=-1;
// sectors 0 to 3
if (sector<4){
return (CS_BASE + sector * 0x4000); // 16 K-words (64K-bytes)
// sectors 4 to 257
} else if (sector<258){
return (CS_BASE + (sector - 3) * 0x10000); // 64 Kwords (256K-bytes)
// sectors 258 to 261
} else if (sector<262){
return (CS_BASE + (sector - 258) * 0x4000 + 0xFF0000); // 16 K-words (64K-bytes)
// undefined sectors, return null
} else {
return 0;
}
// sector address (address within sector)
} else if(sector<0x1000000){
sector+=(int)CS_BASE;
return ((volatile unsigned int *)(sector));
// flash based system address within sector
} else if((sector > (int)CS_BASE) && (sector < (int)CS_BASE+0x1000000)){
if((sector > (int)CS_BASE+0xFFFF) && (sector < (int)CS_BASE+0xFF0000)){
return (volatile unsigned int *)(sector&0xFFFC0000); // within the 64 Kword sector blocks
} else {
return (volatile unsigned int *)(sector&0xFFFF0000); // within the 16 Kword sector blocks
}
}
return 0;
}
/***************************************************
********* Spansion Flash Function Defines *********
***************************************************/
/*****/
/* Asynchronous Read */
// This is actually just a define that adjusts for CS_BASE (refer to #defines above).
// Syntax:
// int store_data=read(x); where x is the desired Flash address to be read
/*****/
/* Asynchronous Read Multiple */
// Read out a chunk of data to dynamically allocated memory
// Parameters: volatile unsigned int* address = pointer to "lowest" address to be read
// int words = number of words to be read
// Returns: pointer to an array containing the read data.
// This pointer has been acquired using malloc, therefore:
// **** NOTE: ****
// returned pointer should be released before program ends using
// free(<pointer>);
// Do not lose, overwrite, alter, etc...this pointer!
// after free() you will no longer have address to the data in it
int* read_m(int address, int words){
int *data = malloc(words * sizeof(int));
address = ((int)CS_BASE + 4*address);
reset();
memcpy(data,(int*)address,words*4);
return data;
}
/*****/
/*** Autoselect Commands ***/
/* Manufacturer ID */
// Returns: 1 if manufacturer id matches expected value (MANU_ID)
int auto_manu_id(void){
int temp;
*CS_BASE=0x00F000F0;
unlock();
*(CS_BASE + 0x555)=0x00900090;
temp=*MANU_ID_AD;
// printf("MANU_ID = 0x%x\n", temp); // uncomment for debug purposes
reset();
return (temp==MANU_ID);
}
/*****/
/* Device ID */
// Returns: 1 if device id matches expected values (DEV_ID_x, x=(1..3))
int auto_dev_id(void){
int temp[3];
*CS_BASE=0x00F000F0;
unlock();
*(CS_BASE + 0x555)=0x00900090;
temp[0]=*DEV_ID_AD_1;
temp[1]=*DEV_ID_AD_2;
temp[2]=*DEV_ID_AD_3;
reset();
return (temp[0]==DEV_ID_1&&temp[1]==DEV_ID_2&&temp[2]==DEV_ID_3); // relational operator, compares and returns true (1) or false (0)
}
/*****/
/* Sector Lock Verify */
// Parameter: int sector = negative sector # or a flash/system address within the sector to be erased
// Returns: 1 if sector is locked
// WARNING: function is fairly flexible for input, but does not error check,
int auto_sect_lock_ver(int sector){
volatile unsigned int * sector_p=sector_bcalc(sector);
sector_p+=0x555;
reset();
unlock();
*sector_p=0x00900090;
sector = *sector_p;
reset();
return (sector==0x00010001); // relational operator, compares and returns true (1) or false (0)
}
/*****/
/* Indicator Bits */
// Returns: indicator bits - DQ15-DQ8 = 0, DQ7: factory lock bit,
// DQ6: customer lock bit, DQ5: Handshake bit (1 = reduced wait, 0 = standard),
// DQ4-DQ0 = 0
int auto_indicator(void){
int temp;
reset();
unlock();
*(CS_BASE + 0x555)=0x00900090;
temp = *(CS_BASE + 0x3);
reset();
return temp;
}
/*** End of Autoselect Commands ***/
/*****/
/*** Unlock Bypass Mode ***/
// while in UBM mode data cannot be read
// Commands that benefit from UBM mode:
// Program, Sector Erase, Erase
// Highly recommended for write multiple
/* Unlock Bypass Entry */
// Enables Unlock Bypass Mode, sets the UBM flag to 1
void ub_entry(void){
reset();
unlock();
*(CS_BASE + 0x555)=0x00200020;
UBM = 1;
}
/*****/
/* Unlock Bypass Reset */
// Exits Unlock Bypass Mode, sets the UBM flag to 0
void ub_reset(void){
reset();
*CS_BASE = 0x00900090;
*CS_BASE = 0x00000000;
UBM = 0;
}
/*** End of UBM commands ***/
/*****/
/* Program */
// Parameters: int address = flash address to be written to
// int data = data to be written
// Returns: 1 on succesful write, null on failure
int write(int address,int data){
if(!UBM){
unlock();
}
*(CS_BASE + 0x555)=0x00A000A0;
*(CS_BASE + address)=data;
// Polling for completion
// Note: "^" is an XOR, comparing data bit 7 (and bit 22)
// So, if "(*(CS_BASE + address)^data)" equals the data bit (on a bit per bit basis),
// this will return a "0", else if not equal, will return a "1"
// Then AND with DQ7 (0x00800080), and if data bit 7 and 22 are 0, programming is done, if 1, programming
// still continues.
while(((*(CS_BASE + address)^data)&DQ7) != 0){
if((*(CS_BASE + address)&DQ5)==DQ5){ // polling DQ5 checks for any time out conditions
if(((*(CS_BASE + address)^data)&DQ7)==0){ // if time out occurs, check back to see if program complete
return 1;
} else {
return 0;
}
}
}
return 1;
}
/*****/
/* Program multiple */
// Writes a chunk of data sequentially starting at a pointer
// Parameters: int address = starting flash address to be written to
// int words = number of words of data to be written
// int * data = pointer to start of data
// Returns: 1 on success, 0 if an attempt to write a word of data fails
// twice in a row.
int write_m(int address,int words, int * data){
int z=0,error=0;
reset();
ub_entry();
while(z<words){
if(write(address + z,data[z])){
z+=1;
error=0;
} else {
error+=1;
if(error>1){
ub_reset();
return 0;
}
}
}
ub_reset();
return 1;
}
/*****/
/*** Erasure Commands ***/
/* Chip Erase */
// The Fifth Horseman of the Apocalypse. Nothing will survive.
// Note that this takes some time to occur, 2-3 minutes
// Returns: 1 on succesful erase, null on failure
int erase_chip(void){
// volatile unsigned int intermediate;
reset();
if(!UBM){
unlock();
}
*(CS_BASE + 0x555)=0x00800080;
if(!UBM){
unlock();
}
*(CS_BASE + 0x555)=0x00100010;
// Polling for completion
while(((*CS_BASE^0x00800080)&DQ7)!=0){
if((*CS_BASE&DQ5)==DQ5){
if(((*CS_BASE^0x00800080)&DQ7)==0){
return 1;
} else {
return 0;
}
}
}
return 1;
}
/*****/
/* Sector Erase */
// Practices a less wanton destruction, erasing only a specific sector.
// Parameters: int sector = either the negative # of the sector to be erased,
// or a flash or system address within the sector to be erased
// valid range: [0:-269], [0:0x7FFFFF] or [(CS_BASE) + 4 * (0:0x7FFFFF)]
// Returns: 1 on succesful erase, null on failure
int erase_sector(int sector){
volatile unsigned int * sector_p=sector_bcalc(sector);
sector_p+=0x555;
reset();
if(!UBM){
unlock();
}
*(CS_BASE + 0x555)=0x00800080;
if(!UBM){
unlock();
}
*sector_p=0x00300030;
// Polling for completion
while(((*sector_p^0x00800080)&DQ7)!=0){
if((*sector_p&DQ5)==DQ5){
if(((*sector_p^0x00800080)&DQ7)==0){
return 1;
} else {
return 0;
}
}
}
return 1;
}
/*****/
/* Erase Suspend */
// Valid only during a sector erase.
// Allows erase to be temporarily suspended so data can be read from a different sector.
// Parameter: int sector = preferably the same input used to initialize the erase.
// technically, it only needs to be a sector # (negative) or address in the same bank
// as the sector being currently erased. constants BANK_A to BANK_D will
// also function correctly as inputs
void erase_suspend(int sector){
*sector_bcalc(sector)=0x00B000B0;
reset();
}
/*****/
/* Erase Resume */
// Valid only during erase suspend mode, resumes suspended erase.
// Parameter: identical to erase suspend
void erase_resume(int sector){
reset();
*sector_bcalc(sector)=0x00300030;
}
/*** End of Erasure Commands ***/
/*****/
/* Set Configuration Register */
//** NEEDS TO BE UPDATED FOR S29WS256N FLASH DEVICE **
// Command not valid during program/write, erase, or sector lock
// Parameter: unsigned char config = detailed bit-wise:
// [7] Set Device Read Mode (1 = Async, 0 = Synchronous)
// [6] RDY signal (1 = active with data, 0 = active one clock cycle before data)
// [5] Clock (1 = output triggers on rising edge, 0 = output triggers on falling edge)
// [4:3] Read Mode:
// 00 = Continous
// 01 = 8-word linear with wrap around
// 10 = 16-word linear with wrap around
// 11 = 32-word linear with wrap around
// [2:0] Programmable Wait State:
// Data is valid on the [...] active CLK edge after AVD# transition to Vih
// 000 = 2nd
// 001 = 3rd
// 010 = 4th
// 011 = 5th
// 100 = 6th
// 101 = 7th
// 110 = <reserved>
// 111 = <reserved>
/*
void set_config(unsigned int build_address){
build_address = build_address << 12;
build_address += 0x555;
unlock();
(*(volatile unsigned int *)(CS_BASE + build_address))=0x00C000C0;
}
*/
void Enable_I_cache (void)
{
__asm
{
mrc p15,0,r0,c1,c0,0
mov r0, #0x00001000
mcr p15,0,r0,c1,c0,0
}
}
/*****/
/****************************
****** The Program ******
****************************/
int main(void){
/***********************
** Setting up the MX21 **
***********************/
//counter
volatile unsigned int q;
int * data, * data1;
*(p_uint32_t)CRM_CCSR = 0x00000308; //output HCLK
#ifdef HCLK133MHZ // set up for HCLK = 133MHz
// set for 133MHz HCLK, assuming 266MHz FCLK
*(p_uint32_t)CRM_CSCR |= 0x00000400; // set BCLKDIV to div-by-2, or '01'
*(p_uint32_t)CRM_CSCR &= 0xFFFFC7FF; // clear other BCLKDIV bits
// now program the EIM wait states under the HCLK 133MHz condition
// flash async access time: 70ns
// WSC = (70ns*133MHz)-1= ~9
*(p_uint32_t)WEIM_CS0U = 0x00000901; //chip select 0 upper register
#else //set up for HCLK = 88.08MHz
// set for 88.08MHz MHz HCLK, assuming 266MHz FCLK
*(p_uint32_t)CRM_CSCR |= 0x00000800; // set BCLKDIV to div-by-3, or '10'
*(p_uint32_t)CRM_CSCR &= 0xFFFFCBFF; // clear other BCLKDIV bits
//set to async mode, random access time 70ns, assuming HCLK = 88.08MHz
// 70ns * 88.08MHz = 6.2 clocks, or 7 clocks. This provides 6 wait states
// *(p_uint32_t)WEIM_CS0U = 0x00000601; //chip select 0 upper register
*(p_uint32_t)WEIM_CS0U = 0x00000A01; //chip select 0 upper register
*(p_uint32_t)WEIM_CS0L = 0x00000E01; //chip select 0 lower register
#endif
Enable_I_cache();
/********************************************************************
** Test 1: Verify manufacturer and device code for AMD Am29BDS128H **
********************************************************************/
if(auto_manu_id()){
printf("Manufacturer ID is correct!\n");
} else {
printf("**Manufacturer ID is incorrect**\n");
}
if(auto_dev_id()){
printf("Device ID is correct!\n");
} else {
printf("**Device ID is incorrect**\n");
}
/**********************************
** Test 2: Flash Erase and Write **
**********************************/
/*
// Clear Sector 0 for writing
if(erase_sector(0)){
printf("Sector 0 Erased\n");
} else {
printf("Sector 0 Erase failed.\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -