📄 fl_sst.c
字号:
/* * $Revision: 1.2 $ * $Author: mechavar $ * $Date: 2000/06/20 18:23:46 $ * * Copyright (c) 1999 ARM, INC. * All rights reserved * * * This file currently will recognise and program the FLASH EPROMS from * SST :- * SST39VF400 4 Mbit device * The code will use 4K sectors *//* Include Standard c Libraries */#include <stdio.h>/* Include the specific files for the flash memory system */#include "fl_sst.h"/********************************************************************** * P R E P R O C E S S O R D E F I N E S **********************************************************************//* Local routine defines for the fl_sst.c module */#define WORD_TRUE 1typedef int bool;#ifndef TRUE#define TRUE (bool)1#endif#ifndef FALSE#define FALSE (bool)0#endif#define ASSERT(cond) if (!cond) fprintf(stderr, "Assertion failed in file %s line %d\n", __MODULE__, __LINE__);#define divroundup(x, y) ((unsigned long)((x) + ((y)-1)) / (unsigned long)(y))/********************************************************************** * P R O G R A M D A T A **********************************************************************/extern FILE *image;extern bool file_defined;extern unsigned long filesize;extern bool filesize_defined;extern unsigned long sector_size;extern unsigned long no_of_sectors;extern unsigned long start_offset;extern bool verbose;extern bool quiet;extern int manuf_code, device_code;extern bool base_defined;extern bool rom_identified;extern unsigned long romsize;unsigned long base_address = EPROM_BASE;unsigned int sector[MAX_SECTOR_SIZE/4];static short *flashptr = (short *)EPROM_BASE; /* flash window *//********************************************************************** * P R O T O T Y P E D E C L A R A T I O N S **********************************************************************/extern void needBaseAddress(void);extern void openFile(void);extern void RomInfo(char *msg);extern void needStartOffset(void);extern void needFilename(void);extern void FileInfo(void);extern void ShowProgress(int sectors_done);extern bool getYesOrNo(char *msg, bool def);bool checkFileSize(char *action);/********************************************************************** * L O C A L F U N C T I O N S **********************************************************************//* Flash_status utilizes the DQ6 polling algorithm described in the flash data book.*/ static int flash_status(volatile short *fp){ unsigned char d, t; d = *(volatile char *)fp; /* read data */ t = d ^ *(volatile char *)fp; /* read it again and see what toggled */ if (t == 0) { /* no toggles, nothing's happening */ return STATUS_READY; } else { return STATUS_BUSY; }}/* Flash_command() is the main driver function.*/static void flash_command(int command, int sector, int offset, unsigned int data){ int retry; /* Some commands may not work the first time, but will work on successive attempts. */ static int retrycount[] = {0,0,0,0,15,15,15,0}; if ( command > FLASH_LASTCMD ) { /* assume reset device to read mode */ command = FLASH_RESET; } retry = retrycount[command]; again: if (command == FLASH_SELECT) { return; } else if (command == FLASH_RESET ) { flashptr[0] = FL_RESET; } else { flashptr[FL_SEQ_ADD_1] = FL_WORD_COM_1; /* unlock 1 */ flashptr[FL_SEQ_ADD_2] = FL_WORD_COM_2; /* unlock 2 */ switch (command) { case FLASH_AUTOSEL: flashptr[FL_SEQ_ADD_3] = FL_AUTO_SELECT; break; case FLASH_PROG: flashptr[FL_SEQ_ADD_3] = FL_PROGRAM; flashptr[(sector+offset)/2] = data; break; case FLASH_CERASE: flashptr[FL_SEQ_ADD_3] = FL_ERASE_3; flashptr[FL_ERASE_ADD_4] = FL_ERASE_4; flashptr[FL_ERASE_ADD_5] = FL_ERASE_5; flashptr[FL_CHIP_ERASE_ADD_6] = FL_CHIP_ERASE_6; break; case FLASH_BERASE: flashptr[FL_SEQ_ADD_3] = FL_ERASE_3; flashptr[FL_ERASE_ADD_4] = FL_ERASE_4; flashptr[FL_ERASE_ADD_5] = FL_ERASE_5; flashptr[(sector)/2] = FL_BLOCK_ERASE_6; break; case FLASH_SERASE: flashptr[FL_SEQ_ADD_3] = FL_ERASE_3; flashptr[FL_ERASE_ADD_4] = FL_ERASE_4; flashptr[FL_ERASE_ADD_5] = FL_ERASE_5; flashptr[(sector)/2] = FL_SECTOR_ERASE_6; break; } } if (retry-- > 0 && flash_status(flashptr) == STATUS_READY) { goto again; }}/* flash_get_device_id() will perform an autoselect sequence on the flash device, and return the device id of the component. This function automatically resets to read mode. */static int flash_get_device_id(){ short *fwp; /* flash window */ short answer; fwp = flashptr; flash_command(FLASH_AUTOSEL,0,0,0); answer = *(fwp+1); flash_command(FLASH_RESET,0,0,0); /* just to be safe */ return( answer );}/* flash_get_manuf_code() will perform an autoselect sequence on the flash device, and return the manufacturer code of the component. This function automatically resets to read mode. */static int flash_get_manuf_code(){ short *fwp; /* flash window */ short answer; fwp = flashptr; flash_command(FLASH_AUTOSEL,0,0,0); answer = *fwp; flash_command(FLASH_RESET,0,0,0); /* just to be safe */ return( (answer & 0x00FF) );}/* 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.*/static int flash_write(char *flash_data, char *buf, int nbytes ){ short *src, *dst; int stat; int retry = 3, retried = 0; if( (nbytes | ((int) (flash_data)) ) & 1) { return -1; } dst = (short *)flash_data; src = (short *)buf; again: flash_command(FLASH_RESET,0,0,0); while ((stat = flash_status(flashptr)) == STATUS_BUSY) {} if (stat != STATUS_READY) { return (char *)src - buf; } while (nbytes > 0) { flashptr[FL_SEQ_ADD_1] = FL_WORD_COM_1; /* unlock 1 */ flashptr[FL_SEQ_ADD_2] = FL_WORD_COM_2; /* unlock 2 */ flashptr[FL_SEQ_ADD_3] = FL_PROGRAM; *dst = *src; while ((stat = flash_status(dst)) == STATUS_BUSY) {} if (stat != STATUS_READY) break; ++dst, ++src; nbytes -= 2; } if (stat != STATUS_READY || nbytes != 0) { if (retry-- > 0) { ++retried; goto again; /* and retry the last word */ } flash_command(FLASH_RESET,0,0,0); } return (char *)src - buf;}int flashAccessDenied( unsigned start_addr, unsigned end_addr ){ if ( start_addr < base_address ) { return( ADDR_TOO_LOW ); } if ( base_address + (no_of_sectors * sector_size) < end_addr ) { return( ADDR_TOO_HI ); } if ( start_addr < ROM_PROTECT_LIMIT ) { return( ADDR_PROTECTED ); } return( 0 );}void Erase_Sector( unsigned sect ){ flash_command( FLASH_SERASE, sect - base_address, 0, 0 ); while ( STATUS_BUSY == flash_status( (short *)sect ) ) { ; }}void FlashErase(unsigned base, unsigned limit){ unsigned nbytes, nsectors, sector; nbytes = limit - GET_SECTOR_START(base); nsectors = nbytes / SST39_SECTOR_SIZE; nsectors += (limit % SST39_SECTOR_SIZE > 0 ? 1 : 0); for ( sector = GET_SECTOR_START(base); nsectors > 0; nsectors--, sector+= SST39_SECTOR_SIZE ) { Erase_Sector( sector ); }}int checkEraseReq( char *pSrc, unsigned extent ){ while ( extent > 0 ) { if ( 0xFF == *pSrc ) { pSrc++; extent--; continue; } return( extent ); } return( 0 );}/********************************************************************** * P U B L I C F U N C T I O N S **********************************************************************//* SetDeviceParams() will set parameters for simple contiguous writing of the flash. sector_size is an arbitrarily chosen buffer size for file writes. sector_size must divide into 8K with no remainder. no_of_sectors is the number of sector-sized sectors in the device. These parameters are independent of the actual Flash block organization. For that, see memdesc[]. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -