flash_sst_39vfxxx.inl
来自「eCos操作系统源码」· INL 代码 · 共 337 行
INL
337 行
#ifndef CYGONCE_DEVS_FLASH_SST_39VFXXX_INL#define CYGONCE_DEVS_FLASH_SST_39VFXXX_INL//==========================================================================//// flash_sst_39vfxxx.inl//// SST 39VFxxx series flash driver////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): gthomas// Contributors: gthomas, jskov, rcassebohm// Date: 2001-02-21// Purpose: // Description: // // Notes: FLASH_P2V is not properly used.// Needs locking.//####DESCRIPTIONEND####////==========================================================================#include <pkgconf/hal.h>#include <cyg/hal/hal_arch.h>#include <cyg/hal/hal_cache.h>#include CYGHWR_MEMORY_LAYOUT_H#define _FLASH_PRIVATE_#include <cyg/io/flash.h>//----------------------------------------------------------------------------// Common device details.#define FLASH_Read_ID FLASHWORD( 0x90 )#define FLASH_Read_ID_Exit FLASHWORD( 0xF0 )#define FLASH_Reset FLASHWORD( 0xFF )#define FLASH_Program FLASHWORD( 0xA0 )#define FLASH_Block_Erase FLASHWORD( 0x30 )#define FLASH_Data FLASHWORD( 0x80 ) // Data complement#define FLASH_Busy FLASHWORD( 0x40 ) // "Toggle" bit#define FLASH_Err FLASHWORD( 0x20 )#define FLASH_Sector_Erase_Timer FLASHWORD( 0x08 )#define FLASH_Setup_Addr1 (0x5555)#define FLASH_Setup_Addr2 (0x2AAA)#define FLASH_Setup_Code1 FLASHWORD( 0xAA )#define FLASH_Setup_Code2 FLASHWORD( 0x55 )#define FLASH_Setup_Erase FLASHWORD( 0x80 )// Platform code must define the below// #define CYGNUM_FLASH_INTERLEAVE : Number of interleaved devices (in parallel)// #define CYGNUM_FLASH_SERIES : Number of devices in series// #define CYGNUM_FLASH_BASE : Address of first device// And select one of the below device variants#ifdef CYGPKG_DEVS_FLASH_SST_39VF080# define FLASH_BLOCK_SIZE (0x1000*CYGNUM_FLASH_INTERLEAVE)# define FLASH_NUM_REGIONS (256)# define CYGNUM_FLASH_BASE_MASK (0xFFF00000u) // 1024kB devices# define CYGNUM_FLASH_WIDTH (8)# define CYGNUM_FLASH_BLANK (1)# define CYGNUM_FLASH_ID_MANUFACTURER FLASHWORD(0xBF)# define CYGNUM_FLASH_ID_DEVICE FLASHWORD(0xD8)#endif#ifdef CYGPKG_DEVS_FLASH_SST_39VF016# define FLASH_BLOCK_SIZE (0x1000*CYGNUM_FLASH_INTERLEAVE)# define FLASH_NUM_REGIONS (512)# define CYGNUM_FLASH_BASE_MASK (0xFFE00000u) // 2048kB devices# define CYGNUM_FLASH_WIDTH (8)# define CYGNUM_FLASH_BLANK (1)# define CYGNUM_FLASH_ID_MANUFACTURER FLASHWORD(0xBF)# define CYGNUM_FLASH_ID_DEVICE FLASHWORD(0xD9)#endif#ifdef CYGPKG_DEVS_FLASH_SST_39VF400# define FLASH_BLOCK_SIZE (0x1000*CYGNUM_FLASH_INTERLEAVE)# define FLASH_NUM_REGIONS (0x80000/FLASH_BLOCK_SIZE)# define CYGNUM_FLASH_BASE_MASK (0xFFF80000u) // 512kB devices# define CYGNUM_FLASH_WIDTH (16)# define CYGNUM_FLASH_BLANK (1)# define CYGNUM_FLASH_ID_MANUFACTURER FLASHWORD(0x00BF)# define CYGNUM_FLASH_ID_DEVICE FLASHWORD(0x2780)#endif#define FLASH_DEVICE_SIZE (FLASH_BLOCK_SIZE*FLASH_NUM_REGIONS)#define CYGNUM_FLASH_DEVICES (CYGNUM_FLASH_INTERLEAVE*CYGNUM_FLASH_SERIES)//----------------------------------------------------------------------------// Now that device properties are defined, include magic for defining// accessor type and constants.#include <cyg/io/flash_dev.h>//----------------------------------------------------------------------------// Functions that put the flash device into non-read mode must reside// in RAM.void flash_query(void* data) __attribute__ ((section (".2ram.flash_query")));int flash_erase_block(void* block, unsigned int size) __attribute__ ((section (".2ram.flash_erase_block")));int flash_program_buf(void* addr, void* data, int len) __attribute__ ((section (".2ram.flash_program_buf")));//----------------------------------------------------------------------------// Initialize driver detailsintflash_hwr_init(void){ flash_data_t id[2]; flash_dev_query(id); // Check that flash_id data is matching the one the driver was // configured for. if (id[0] != CYGNUM_FLASH_ID_MANUFACTURER || id[1] != CYGNUM_FLASH_ID_DEVICE) return FLASH_ERR_DRV_WRONG_PART; // Hard wired for now flash_info.block_size = FLASH_BLOCK_SIZE; flash_info.blocks = FLASH_NUM_REGIONS; flash_info.start = (void *)CYGNUM_FLASH_BASE; flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (FLASH_NUM_REGIONS * FLASH_BLOCK_SIZE * CYGNUM_FLASH_SERIES)); return FLASH_ERR_OK;}//----------------------------------------------------------------------------// Map a hardware status to a package errorintflash_hwr_map_error(int e){ return e;}//----------------------------------------------------------------------------// See if a range of FLASH addresses overlaps currently running codeboolflash_code_overlaps(void *start, void *end){ extern unsigned char _stext[], _etext[]; return ((((unsigned long)&_stext >= (unsigned long)start) && ((unsigned long)&_stext < (unsigned long)end)) || (((unsigned long)&_etext >= (unsigned long)start) && ((unsigned long)&_etext < (unsigned long)end)));}//----------------------------------------------------------------------------// Flash Query//// Only reads the manufacturer and part number codes for the first// device(s) in series. It is assumed that any devices in series// will be of the same type.voidflash_query(void* data){ volatile flash_data_t *ROM; flash_data_t* id = (flash_data_t*) data; int i; ROM = (volatile flash_data_t*) CYGNUM_FLASH_BASE; ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1; ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2; ROM[FLASH_Setup_Addr1] = FLASH_Read_ID; // FIXME: 10ms delay for (i = 10000; i > 0; i--); // Manufacturers' code id[0] = ROM[0]; // Part number id[1] = ROM[1]; ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1; ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2; ROM[FLASH_Setup_Addr1] = FLASH_Read_ID_Exit; // FIXME: 10ms delay for (i = 10000; i > 0; i--);}//----------------------------------------------------------------------------// Erase Blockintflash_erase_block(void* block, unsigned int len){ volatile flash_data_t* ROM; volatile flash_data_t* addr_ptr = (volatile flash_data_t*) block; int res = FLASH_ERR_OK; while ((FLASH_ERR_OK == res) && (len > 0)) { int timeout; flash_data_t state, prev_state; // Base address of device(s) being programmed. ROM = (volatile flash_data_t*)((unsigned long)block & ~(FLASH_DEVICE_SIZE-1)); // Program data [byte] - 6 step sequence ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1; ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2; ROM[FLASH_Setup_Addr1] = FLASH_Setup_Erase; ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1; ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2; *addr_ptr = FLASH_Block_Erase; // Wait for completion (bit 6 stops toggling) timeout = 5000000; prev_state = *addr_ptr & FLASH_Busy; while (true) { state = *addr_ptr & FLASH_Busy; if (prev_state == state) { break; } if (--timeout == 0) { res = FLASH_ERR_DRV_TIMEOUT; break; } prev_state = state; } // Verify loaded data bytes while (len > 0) { if (*addr_ptr != FLASH_BlankValue) { // Only update return value if erase operation was OK if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY; break; } addr_ptr++; len -= sizeof(*addr_ptr); } } return FLASH_ERR_OK;}//----------------------------------------------------------------------------// Program Bufferintflash_program_buf(void* addr, void* data, int len){ volatile flash_data_t* ROM; volatile flash_data_t* addr_ptr = (volatile flash_data_t*) addr; volatile flash_data_t* data_ptr = (volatile flash_data_t*) data; int res = FLASH_ERR_OK;#if 0 CYG_ASSERT((unsigned long)data_ptr & (sizeof(flash_data_t)-1) == 0, "Data not properly aligned"); CYG_ASSERT((unsigned long)addr_ptr & (CYGNUM_FLASH_INTERLEAVE*sizeof(flash_data_t)-1) == 0, "Addr not properly aligned (to first interleaved device)");#endif while ((FLASH_ERR_OK == res) && (len > 0)) { int timeout; flash_data_t state, prev_state; // Base address of device(s) being programmed. ROM = (volatile flash_data_t*)((unsigned long)addr & ~(FLASH_DEVICE_SIZE-1)); // Program data [byte] - 4 step sequence ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1; ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2; ROM[FLASH_Setup_Addr1] = FLASH_Program; *addr_ptr = *data_ptr; // Wait for completion (bit 6 stops toggling) timeout = 5000000; prev_state = *addr_ptr & FLASH_Busy; while (true) { state = *addr_ptr & FLASH_Busy; if (prev_state == state) { break; } if (--timeout == 0) { res = FLASH_ERR_DRV_TIMEOUT; break; } prev_state = state; } // Verify loaded data bytes if (*addr_ptr != *data_ptr) { // Only update return value if program operation was OK if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY; break; } addr_ptr++; data_ptr++; len -= sizeof(*data_ptr); } // Ideally, we'd want to return not only the failure code, but also // the address/device that reported the error. return res;}#endif // CYGONCE_DEVS_FLASH_SST_39VFXXX_INL
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?