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

📄 flash_test.c

📁 Redboot, boot-loader of Linux for Freescale ARM family.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************************
*
* Copyright (C) 2003, MOTOROLA INC.   All Rights Reserved
*
*  FILE NAME      :  flash_test.c
*  DATE CREATED   :  06-18-03
*  	
*  DESCRIPTION: Function and Test code for AMD Am29BDS128H Flash
*  This code will query the burst flash on the eval board for its manufacturer ID 
*  AND device ID.  If device ID is incorrect, the code will report this failure. 
*  If manufacturer ID not correct, the code will also report this.
*	
*  Next, this code will erase the contents of the burst flash device and program 
*  it with instructions (add "..." to R2).  Then the code will enable the EIM
*  to burst read these instructions.  Use an logic analyzer to verify burst 
*  operation.
*
*
*  NOTE: Jumper bank J6 must have pins 3-4 bridged. This sets the Am29BDS128H
*        flash to chip select 0. The other chip selects do not have sufficient
*        address space. There should be only one jumper per row, and no two
*        rows should have the same pins bridged.
*
*  ****************************
*  IMPORTANT NOTE ON FUNCTIONS:
*  ****************************
*
*  When passing an address to a function, the function assumes that the address
*  passed to it is the Flash address as a standard integer, not the System address.
*  E.g., regardless of where in the system memory the Flash resides, the functions
*  should be passed address values between 0x000000 and 0x7FFFFF. The functions will
*  automatically adjust to write or read to the correct system address based off of
*  the value of CS_BASE. Address values between 0x000000 and 0x7FFFFF represent the
*  entire FLASH (x16) address range. This test code assumes a system with a x32
*  FLASH configuration.  Thus the functions will convert the x16 FLASH address to the
*  appropriate and desired SYSTEM (x32) address.  
*
*  If a function needs to be passed a sector value, it will accept either the
*  NEGATIVE number of the sector or any Flash address within the sector.
*
*  Ex: Sector 2 starts at Flash address 0x002000 and ends at 0x002FFF
*        Passing -2, 0x002000, 0x002FFF or 0x0023F9 would all work correctly
*        Passing 2 would be interpreted as an address in sector 0
*
*  The sector value functions will actually also operate correctly when passed
*  a system address that points to the sector.
*
*  In general though, the intent is that as long as CS_BASE is defined, the function
*  user does not need to bother with where the Flash resides in system memory.
*
*	Revision history:
*	rev 0.0 - original release
*	rev 0.1 - updated for i.mx21
*
********************************************************************************
*  I N C L U D E   F I L E S
*******************************************************************************/

#include "common.h"
#include "tht_memory_map_defines.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Modify SysInit() for different system initialization settings */
extern int SysInit(void);
extern int MemInit(void);



/******************************************************************************
*  DEFINES
******************************************************************************/

/* i.MX21 specific defines */

/***** Critical *****/
// CS_BASE informs the program of the base system address of the Flash
#define CS_BASE	(volatile unsigned int *)CS0_BASE_ADDR	// Chip select 0, i.mx21


/***************************************************
********* AMD Burst Flash Constant Defines *********
***************************************************/

// Read adjusting for CS_BASE

#define read(x) *(CS_BASE+x)

//reset & unlock writes
#define reset() *CS_BASE=0x00F000F0
#define unlock() *(CS_BASE + 0x555)=0x00AA00AA; *(CS_BASE + 0x2AA)=0x00550055

//manufacturer and device ID values
#define MANU_ID 0x00010001
#define MANU_ID_AD (CS_BASE)
#define DEV_ID_1 0x227E227E
#define DEV_ID_AD_1 (CS_BASE + 0x1)
#define DEV_ID_2 0x22182218
#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
#define BANK_D	(CS_BASE)
#define BANK_C	(CS_BASE + 0x100000)
#define BANK_B	(CS_BASE + 0x400000)
#define BANK_A	(CS_BASE + 0x700000)

// 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:-269]
//						or	Flash address in desired sector [0:0x7FFFFF]
//						or	System address in desired sector (CS_BASE+[0:0x7FFFFF])
// Returns: Base address of the sector calculated, or 'null' if the input is invalid
//		as a "volatile unsigned int *"
// Examples:	assuming CS_BASE = 0x16000000
//		Correct:
//				sector_calc(-15) would return the base address of sector 15 (0x16040000)
//				sector_calc(0x04A820) would return the base address of sector 15 also
//				sector_calc(0x1604A820) 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(0x9FFFFF) would return null, as the address is outside of the flash

volatile unsigned int * sector_bcalc(int sector){	
	if(sector<1){
		sector*=-1;
		if (sector<8){
			return (CS_BASE + sector * 0x1000);
		} else if (sector<262){
			return (CS_BASE + (sector - 7) * 0x8000);
		} else if (sector<270){
			return (CS_BASE + (sector - 262) * 0x1000 + 0x7F8000);
		} else {
			return 0;
		}
	} else if(sector<0x800000){
		sector+=(int)CS_BASE;
	} else if((sector > (int)CS_BASE) && (sector < (int)CS_BASE+0x800000)){
		if((sector > (int)CS_BASE+0x7FFF) && (sector < (int)CS_BASE+0x7F8000)){
			return (volatile unsigned int *)(sector&0xFFFF8000);
		} else {
			return (volatile unsigned int *)(sector&0xFFFFF000);
		}
	}
	return 0;
}

/***************************************************
********* AMD Burst Flash Function Defines *********
***************************************************/

/*****/

/* Asynchronous Read */

// This is actually just a define that adjusts for CS_BASE

// 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;
	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
	while(((*(CS_BASE + address)^data)&DQ7) != 0){
		if((*(CS_BASE + address)&DQ5)==DQ5){
			if(((*(CS_BASE + address)^data)&DQ7)==0){
				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;
			}
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -