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

📄 extflash.c

📁 基于TI公司Cortex-M3的uart超级通信开发
💻 C
📖 第 1 页 / 共 2 页
字号:
//*****************************************************************************
//
// 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 + -