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

📄 am29lv160db.c

📁 非tffs格式的flash读写程序。其实大体格式都一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/************************************************************************/
/*                                                                      */
/*  AMD CFI Enabled Flash Memory Drivers                                */
/*  File name: CFIFLASH.C                                               */
/*  Revision:  1.0  5/07/98                                             */
/*                                                                      */
/* Copyright (c) 1998 ADVANCED MICRO DEVICES, INC. All Rights Reserved. */
/* This software is unpublished and contains the trade secrets and      */
/* confidential proprietary information of AMD. Unless otherwise        */
/* provided in the Software Agreement associated herewith, it is        */
/* licensed in confidence "AS IS" and is not to be reproduced in whole  */
/* or part by any means except for backup. Use, duplication, or         */
/* disclosure by the Government is subject to the restrictions in       */
/* paragraph (b) (3) (B) of the Rights in Technical Data and Computer   */
/* Software clause in DFAR 52.227-7013 (a) (Oct 1988).                  */
/* Software owned by                                                    */
/* Advanced Micro Devices, Inc.,                                        */
/* One AMD Place,                                                       */
/* P.O. Box 3453                                                        */
/* Sunnyvale, CA 94088-3453.                                            */
/************************************************************************/
/*  This software constitutes a basic shell of source code for          */
/*  programming all AMD Flash components. AMD                           */
/*  will not be responsible for misuse or illegal use of this           */
/*  software for devices not supported herein. AMD is providing         */
/*  this source code "AS IS" and will not be responsible for            */
/*  issues arising from incorrect user implementation of the            */
/*  source code herein. It is the user's responsibility to              */
/*  properly design-in this source code.                                */
/*                                                                      */ 
/************************************************************************/                                                                        
#include "vxWorks.h"
#include "ioLib.h"
#include "errno.h"
#include "stdio.h"
#include "string.h"
#include "time.h"
/*#include "dosFsLib.h"*/
#include "am29lv160db.h"


/*********************************************************************/
/* The purpose of get_flash_memptr() is to return a memory pointer   */
/* which points to the beginning of memory space allocated for the   */
/* flash.  All function pointers are then referenced from this       */
/* pointer. 							     */
/*                                                                   */
/* Different systems will implement this in different ways:          */
/* possibilities include:                                            */
/*  - A direct memory pointer                                        */
/*  - A pointer to a memory map                                      */
/*  - A pointer to a hardware port from which the linear             */
/*    address is translated                                          */
/*  - Output of an MMU function / service                            */
/*                                                                   */
/* Also note that this function expects the pointer to a specific    */
/* sector of the device.  This can be provided by dereferencing      */
/* the pointer from a translated offset of the sector from a         */
/* global base pointer (e.g. flashptr = base_pointer + sector_offset)*/
/*                                                                   */
/* Important: Many AMD flash devices need both bank and or sector    */
/* address bits to be correctly set (bank address bits are A18-A16,  */
/* and sector address bits are A18-A12, or A12-A15).  Flash parts    */
/* which do not need these bits will ignore them, so it is safe to   */
/* assume that every part will require these bits to be set.         */
/*********************************************************************/

/*extern unsigned char FAR *get_flash_memptr(int sector);*/
/*extern unsigned char  *get_flash_memptr(int sector);*/

/*********************************************************************/
/* 'meminfo' should be a pointer, but most C compilers will not      */
/* allocate static storage for a pointer without calling             */
/* non-portable functions such as 'new'.  We also want to avoid      */
/* the overhead of passing this pointer for every driver call.       */
/* Systems with limited heap space will need to do this.             */
/*********************************************************************/

struct flashinfo meminfo; /* Flash information structure */

/*********************************************************************/
/* Init_flash is used to build a sector table from the information   */
/* provided through the CFI query.  This information is translated   */
/* from erase_block information to base:offset information for each  */
/* individual sector. This information is then stored in the meminfo */
/* structure, and used throughout the driver to access sector        */
/* information.                                                      */
/*                                                                   */
/* This is more efficient than deriving the sector base:offset       */
/* information every time the memory map switches (since on the      */
/* development platform can only map 64k at a time).  If the entire  */
/* flash memory array can be mapped in, then the addition static     */
/* allocation for the meminfo structure can be eliminated, but the   */
/* drivers will have to be re-written.                               */
/*                                                                   */
/* The meminfo struct occupies 653 bytes of heap space, depending    */
/* on the value of the define MAXSECTORS.  Adjust to suit            */
/* application                                                       */ 
/*********************************************************************/



/*********************************************************************/
/* config BR2 and OR2 */
/*********************************************************************/
void init_flash_memory()
{
  *(unsigned long*)(IMMR_CONFIG+IMMR_OR2) = (unsigned long)OR2_CONFIG;
  *(unsigned long*)(IMMR_CONFIG+IMMR_BR2) = (unsigned long)BR2_CONFIG;
}

byte init_flash(struct cfi_query *q)
{
  unsigned int i=0, j=0, count=0;
  long basecount=0L;

  /* If q == NULL, then we havent performed a CFI query
   * to retrieve the sector organization.  First, assume
   * a single 8k sector for sector 0.  This is to allow
   * the system to perform memory mapping to the device,
   * even though the actual physical layout is unknown.
   * Once mapped in, the CFI query will produce all
   * relevant information.
   */

  if(q == NULL) {
    meminfo.addr = 0L;
    meminfo.areg = 0;
    meminfo.nsect = 1;
    meminfo.bank1start = 0;
    meminfo.bank2start = 0;

    meminfo.sec[0].size = 8192;
    meminfo.sec[0].base = 0x00000;
    meminfo.sec[0].bank = 1;

    return(1);
  } else {
    count=0;basecount=0L;
    for (i=0; i<q->num_erase_blocks; i++) {
      count += q->erase_block[i].num_sectors;
    }
   
    meminfo.nsect = count;
    count=0;
    for (i=0; i<q->num_erase_blocks; i++) {
      for(j=0; j<q->erase_block[i].num_sectors; j++) {
	meminfo.sec[count].size = (long) q->erase_block[i].sector_size;
	meminfo.sec[count].base = (long) basecount;
	basecount += (long) q->erase_block[i].sector_size;
	count++;
      }
    }
  }
}

/*********************************************************************/
/* Flash_command() is the main driver function.  It performs         */
/* every possible command available to AMD B revision                */
/* flash parts. Note that this command is not used directly, but     */
/* rather called through the API wrapper functions provided below.   */
/*********************************************************************/

void flash_command(int command, int sector, int offset,
						 unsigned int data)
{
	 static dword base;    /* base offset for our sector */
	 static word *selp;
	 static dword sechigh;
/*	 static word far *flashptr; */ /* flash window (64K bytes) */
	 static word  *flashptr;
	 static int oldsector = -1;
	 int retry;
       
         /**************************************************************/
	 /* IMPORTANT: Note that flashptr is defined as a WORD pointer */
         /* If BYTE pointers are used, the command tables will have to */
         /* be remapped						       */
         /* Note 1: flashptr is declared far - if system does not      */
         /*         support far pointers, this will have to be changed */
         /* Note 2: flashptr is declared static to avoid calling       */
         /*         get_flash_memptr() on successive sector accesses   */
         /**************************************************************/

	 /* Some commands may not work the first time, but will work   */
         /* on successive attempts.  Vary the number of retries to suit*/
         /* requirements.                                              */
         
         static int retrycount[] = {0,0,0,0,15,15,0,15,0,0};

	 retry = retrycount[command];

	 if(sector != oldsector) {
	/*	flashptr = (word far *) get_flash_memptr(sector);*/
		flashptr = (word  *) get_flash_memptr(sector);
	 }

again1:

	 if (command == FLASH_SELECT) {
		return;
	 } else if (command == FLASH_RESET || command > FLASH_LASTCMD) {
		  flashptr[0] = 0xF0;   /* assume reset device to read mode */
	 } else if (command == FLASH_ESUSPEND) {
		  flashptr[0] = 0xB0;   /* suspend sector erase */
	 } else if (command == FLASH_ERESUME) {
		  flashptr[0] = 0x30;   /* resume suspended sector erase */
	 } else if (command == FLASH_UBPROG) {
		  flashptr[0] = 0xA0;
/*		  flashptr[((meminfo->sec[sector].base)+offset)/2] = data;*/
		  flashptr[((meminfo.sec[sector].base)+offset)/2] = data;
	 } else if (command == FLASH_UBRESET) {
		  flashptr[0] = 0x90;
		  flashptr[0] = 0x00;
	 }
	 else {
		  flashptr[0x555] = 0xAA;       /* unlock 1 */
		  flashptr[0x2AA] = 0x55;       /* unlock 2 */
		  switch (command) {
			 case FLASH_AUTOSEL:
				flashptr[0x555] = 0x90;
				break;
			 case FLASH_PROG:
				flashptr[0x555] = 0xA0;
/*				flashptr[((meminfo->sec[sector].base)+offset)/2] = data;*/
				flashptr[((meminfo.sec[sector].base)+offset)/2] = data;
				break;
			 case FLASH_CERASE:
				flashptr[0x555] = 0x80;
				flashptr[0x555] = 0xAA;
				flashptr[0x2AA] = 0x55;
				flashptr[0x555] = 0x10;
				break;
			 case FLASH_SERASE:
				flashptr[0x555]  = 0x80;
				flashptr[0x555]  = 0xAA;
				flashptr[0x2AA]  = 0x55;
/*				flashptr[(meminfo->sec[sector].base)/2] = 0x30;*/
				/*flashptr[(meminfo.sec[sector].base)/2] = 0x30;*/
				flashptr[0x0] = 0x30;
				break;
			 case FLASH_UB:
				flashptr[0x555] = 0x20;
				break;
			 case FLASH_CFIQUERY:
				flashptr[0x55] = 0x98;
				break;
		  }
	 }

	 if (retry-- > 0 && flash_status(flashptr) == STATUS_READY) {
		goto again1;
	 }
}
/*********************************************************************/
/* Flash_write extends the functionality of flash_program() by       */
/* providing an faster way to program multiple data words, without   */
/* needing the function overhead of looping algorithms which         */
/* program word by word.  This function utilizes fast pointers       */
/* to quickly loop through bulk data.                                */
/*********************************************************************/
int flash_write(int sector, unsigned offset, byte *buf, 
                int nbytes, int ub)
{
/*	 word far *flashptr; *//* flash window */
/*	 word far *src, *dst;*/
	 word  *flashptr; /* flash window */
	 word  *src, *dst;
	 int stat;
	 int retry = 0, retried = 0;

	 flashptr = (word *)get_flash_memptr(sector);
	 dst = flashptr + offset/2;   /* (byte offset) */
	 src = (word *)buf;

	 if ((nbytes | offset) & 1) {
		return -1;
	 }
again2:

	 /* Check to see if we're in unlock bypass mode */
         if (ub == FALSE)
		flashptr[0] = 0xF0;  /* reset device to read mode */

	 while ((stat = flash_status(flashptr)) == STATUS_BUSY) {}
	 if (stat != STATUS_READY) {
		return (byte *)src - buf;
	 }

	 while (nbytes > 0) {
		if (ub == FALSE){
		  flashptr[0x555] = 0xAA;      /* unlock 1 */
		  flashptr[0x2AA] = 0x55;      /* unlock 2 */
		}
		flashptr[0x555] = 0xA0;
		*dst++ = *src++;
		while ((stat = flash_status(flashptr)) == STATUS_BUSY) {}
		if (stat != STATUS_READY) break;
		nbytes -= 2;
	 }

	 if (stat != STATUS_READY || nbytes != 0) {
		if (retry-- > 0) {
		  ++retried;
		  --dst, --src;   /* back up */
		  goto again2;     /* and retry the last word */
		}
		if (ub == FALSE)
                  flash_command(FLASH_RESET,sector,0,0);
	 }

	 return (byte *)src - buf;
}

/*********************************************************************/
/* Flash_status utilizes the DQ6, DQ5, and DQ3 polling algorithms    */
/* described in the flash data book.  It can quickly ascertain the   */
/* operational status of the flash device, and return an             */
/* appropriate status code (defined in flash.h)                      */
/*********************************************************************/
 
/*int flash_status(word far *fp)*/
int flash_status(word  *fp)
{

⌨️ 快捷键说明

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