📄 extflash.c
字号:
//*****************************************************************************
//
// extflash.c - Functions accessing the external flash on the lm3s9b96
// SRAM/Flash daughter board.
//
// Copyright (c) 2009 Luminary Micro, Inc. All rights reserved.
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. You may not combine
// this software with "viral" open-source software in order to form a larger
// program. Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 5228 of the DK-LM3S9B96 Firmware Package.
//
//*****************************************************************************
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/epi.h"
#include "extflash.h"
//*****************************************************************************
//
//! \addtogroup extflash_api
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
// Definitions of important bits in the flash status register.
//
//*****************************************************************************
#define FLASH_STATUS_DATA_POLL 0x80
#define FLASH_STATUS_ERROR 0x20
//*****************************************************************************
//
// Check to determine whether or not the flash appears to be present. We do
// this by attempting to read the first 3 bytes of the CFI Query Identification
// String which should contain "QRY". If we get this, we assume all is well,
// otherwise we assume the flash is not accessible.
//
//*****************************************************************************
static tBoolean
CheckFlashPresent(void)
{
tBoolean bRetcode;
//
// Set autoselect mode
//
HWREGB(EXT_FLASH_BASE + 0xAAA) = 0xAA;
HWREGB(EXT_FLASH_BASE + 0x555) = 0x55;
HWREGB(EXT_FLASH_BASE + 0xAAA) = 0x90;
//
// Set CFI query
//
HWREGB(EXT_FLASH_BASE + 0xAA) = 0x98;
//
// Check that the query string is returned correctly.
//
if((HWREGB(EXT_FLASH_BASE + 0x20) != 'Q') ||
(HWREGB(EXT_FLASH_BASE + 0x22) != 'R') ||
(HWREGB(EXT_FLASH_BASE + 0x24) != 'Y'))
{
//
// We can't access the flash correctly - the query string was not
// read as expected.
//
bRetcode = false;
}
else
{
//
// We read the query string so tell the caller all is well.
//
bRetcode = true;
}
//
// Return to read array mode. We need to do this twice. The first write
// gets us back to autoselect mode and the second returns us to array
// read.
//
HWREGB(EXT_FLASH_BASE) = 0xF0;
HWREGB(EXT_FLASH_BASE) = 0xF0;
//
// Tell the caller whether or not the flash is accessible.
//
return(bRetcode);
}
//*****************************************************************************
//
//! Determines whether the external flash on the Flash/SRAM/LCD daughter board
//! is accessible.
//!
//! This function checks to ensure that the external flash is accessible by
//! reading back the "QRY" tag at the beginning of the CFI query block. If
//! this is read correctly, \b true is returned indicating that the flash is
//! now accessible, otherwise \b false is returned. It is assumed that the EPI
//! configuration has previously been set correctly using a call to
//! PinoutSet().
//!
//! On return, the flash device is in read array mode.
//!
//! \return Returns \b true if the flash is found and accessible or \b false
//! if the flash device is not found.
//
//*****************************************************************************
tBoolean
ExtFlashPresent(void)
{
//
// Make sure we can access the flash.
//
return(CheckFlashPresent());
}
//*****************************************************************************
//
//! Queries the total size of the attached flash device.
//!
//! This function read the flash CFI query block to determine the total size of
//! the device in bytes and returns this value to the caller. It is assumed
//! that the EPI configuration has previously been set correctly using a call
//! to PinoutSet().
//!
//! \return Returns the total size of the attached flash device in bytes.
//
//*****************************************************************************
unsigned long
ExtFlashChipSizeGet(void)
{
unsigned char ucSize;
//
// Set autoselect mode
//
HWREGB(EXT_FLASH_BASE + 0xAAA) = 0xAA;
HWREGB(EXT_FLASH_BASE + 0x555) = 0x55;
HWREGB(EXT_FLASH_BASE + 0xAAA) = 0x90;
//
// Set CFI query
//
HWREGB(EXT_FLASH_BASE + 0xAA) = 0x98;
//
// Read the device size from the CFI block. This is returned as a power
// of two.
//
ucSize = HWREGB(EXT_FLASH_BASE + 0x4E);
//
// Switch back to read mode. We need to do this twice. The first write
// gets us back to autoselect mode and the second returns to read array
// mode.
//
HWREGB(EXT_FLASH_BASE) = 0xF0;
HWREGB(EXT_FLASH_BASE) = 0xF0;
//
// Return the size of the device in bytes.
//
return(1 << ucSize);
}
//*****************************************************************************
//
//! Returns the size of a given flash block.
//!
//! \param ulAddress is the flash address whose block information is being
//! queried.
//! \param pulBlockAddr is storage for the returned block start address.
//!
//! This function determines the start address and size of the flash block
//! which contains the supplied address. The block information is determined
//! by parsing the flash CFI query data. If an invalid address is passed, the
//! block address and size are both returned as 0.
//!
//! It is assumed that the EPI configuration has previously been set correctly
//! using a call to PinoutSet().
//!
//! \return Returns the size of the flash block which contains \e ulAddress or
//! 0 if \e ulAddress is invalid.
//
//*****************************************************************************
unsigned long
ExtFlashBlockSizeGet(unsigned long ulAddress, unsigned long *pulBlockAddr)
{
unsigned char *pcCFIQuery;
unsigned char ucSize;
unsigned short usNumBlocks;
unsigned long ulBlockStart, ulBlockEnd, ulSizeBlock;
unsigned long ulRetcode, ulBlockAddr;
//
// Modify the address to be relative to the start of the flash device.
//
ulAddress -= EXT_FLASH_BASE;
//
// Set return values to indicate an error for now.
//
ulRetcode = 0;
ulBlockAddr = 0;
//
// Set autoselect mode
//
HWREGB(EXT_FLASH_BASE + 0xAAA) = 0xAA;
HWREGB(EXT_FLASH_BASE + 0x555) = 0x55;
HWREGB(EXT_FLASH_BASE + 0xAAA) = 0x90;
//
// Set CFI query
//
HWREGB(EXT_FLASH_BASE + 0xAA) = 0x98;
//
// Get a pointer to the CFI query information.
//
pcCFIQuery = (unsigned char *)EXT_FLASH_BASE;
//
//
// Read the device size from the CFI block. This is returned as a power
// of two.
//
ucSize = pcCFIQuery[0x4E];
//
// Is the address passed within the device?
//
if(ulAddress < (1 << ucSize))
{
//
// The address appears to be valid. Now walk the CFI regions to
// determine which one it is within.
//
ulBlockStart = 0;
for(ucSize = 0; ucSize < pcCFIQuery[0x58]; ucSize++)
{
//
// How many erase blocks exist in this region?
//
usNumBlocks = (pcCFIQuery[0x5A + (8 * ucSize)] +
(pcCFIQuery[0x5C + (8 * ucSize)] << 8) + 1);
//
// How big is each block?
//
ulSizeBlock = (pcCFIQuery[0x5E + (8 * ucSize)] +
(pcCFIQuery[0x60 + (8 * ucSize)] << 8)) * 256;
// Where does this region end?
//
ulBlockEnd = ulBlockStart + ((unsigned long)usNumBlocks *
ulSizeBlock);
//
// Does the passed address fall within this region?
//
if(ulAddress < ulBlockEnd)
{
//
// Yes - determine where the block starts.
//
ulBlockAddr = EXT_FLASH_BASE + (ulBlockStart +
(((ulAddress - ulBlockStart) / ulSizeBlock) *
ulSizeBlock));
//
// Set up to return the block size.
//
ulRetcode = ulSizeBlock;
//
// Drop out of the loop now that we have found the required
// block.
//
break;
}
//
// Move on to the next region.
//
ulBlockStart = ulBlockEnd;
}
}
//
// Return to read array mode. We need to do this twice. The first write
// gets us back to autoselect mode and the second returns us to array
// read.
//
HWREGB(EXT_FLASH_BASE) = 0xF0;
HWREGB(EXT_FLASH_BASE) = 0xF0;
//
// Return the block start address and size to the caller.
//
*pulBlockAddr = ulBlockAddr;
return(ulRetcode);
}
//*****************************************************************************
//
//! Determines whether the last erase operation has completed.
//!
//! \param ulAddress is an address within the area of flash which was last
//! erased using a call to ExtFlashBlockErase() or any valid flash address if
//! ExtFlashChipErase() was last issued.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -