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

📄 norflash_rw.txt

📁 flash read and write
💻 TXT
📖 第 1 页 / 共 4 页
字号:
#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 + -