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

📄 ssiflash.c

📁 基于TI公司Cortex-M3的uart超级通信开发
💻 C
📖 第 1 页 / 共 3 页
字号:
}

//*****************************************************************************
//
// Sends a command to the flash to enable program and erase operations.
//
// This function sends a write enable instruction to the serial flash device
// in preparation for an erase or program operation.
//
// \return Returns \b true if the instruction was accepted or \b false if
// write operations could not be enabled.
//
//*****************************************************************************
static tBoolean
SSIFlashWriteEnable(void)
{
    tBoolean bRetcode;
    unsigned char ucStatus;

    //
    // Issue the instruction we need to write-enable the chip.
    //
    SSIFlashInstructionWrite(INSTR_WRITE_ENABLE, (unsigned char *)0, 0);
    SSIFlashInstructionEnd();

    //
    // Wait for the instruction to complete.
    //
    bRetcode = SSIFlashIdleWait(MAX_BUSY_POLL_IDLE);

    //
    // Is the flash idle?
    //
    if(bRetcode)
    {
        //
        // Read the status and make sure that the Write Enable Latch bit is
        // set (indicating that a write may proceed).
        //
        ucStatus = SSIFlashStatusGet();

        bRetcode = (ucStatus & STATUS_WRITE_ENABLE_LATCH) ? true : false;
    }

    //
    // Tell the caller how we got on.
    //
    return(bRetcode);
}

//*****************************************************************************
//
//! Initializes the SSI port and determines if the serial flash is available.
//!
//! This function must be called prior to any other function offered by the
//! serial flash driver.  It configures the SSI port to run in mode 0 at 10MHz
//! and queries the ID of the serial flash device to ensure that it is
//! available.
//!
//! \note SSI0 is shared between the serial flash and the SDCard on the
//! dk-lm3s9b96 boards.  Two independent GPIOs are used to provide chip selects
//! for these two devices but care must be taken when using both in a single
//! application, especially during initialization of the SDCard when the SSI
//! clock rate must initially be set to 400KHz and later increased.  Since both
//! the SSI flash and SDCard drivers initialize the SSI peripheral, application
//! writers must be aware of the possible contention and ensure that they do
//! not allow the possibility of two different interrupt handlers or execution
//! threads from attempting to access both peripherals simultaneously.
//!
//! This driver assumes that the application is aware of the possibility of
//! contention and has been designed with this in mind.  Other than disabling
//! the SDCard when an attempt is made to access the serial flash, no code is
//! included here to arbitrate for ownership of the SSI peripheral.
//!
//! \return Returns \b true on success or \b false if an error is reported or
//! the expected serial flash device is not present.
//!
//*****************************************************************************
tBoolean
SSIFlashInit(void)
{
    tBoolean bRetcode;
    unsigned char ucManufacturer, ucDevice;

    //
    // Enable the peripherals used to drive the SDC on SSI.
    //
    SysCtlPeripheralEnable(SFLASH_SSI_PERIPH);
    SysCtlPeripheralEnable(SFLASH_SSI_GPIO_PERIPH);

    //
    // Configure the appropriate pins to be SSI instead of GPIO. The CS
    // is configured as GPIO since this board has 2 devices connected to
    // SSI0 and each uses a separate CS.
    //
    GPIOPinTypeSSI(SFLASH_SSI_GPIO_BASE, SFLASH_SSI_PINS);
    GPIOPinTypeGPIOOutput(SFLASH_CS_BASE, SFLASH_CS_PIN);
    GPIOPinTypeGPIOOutput(SDCARD_CS_BASE, SDCARD_CS_PIN);
    GPIOPadConfigSet(SFLASH_SSI_GPIO_BASE, SFLASH_SSI_PINS, GPIO_STRENGTH_4MA,
                     GPIO_PIN_TYPE_STD_WPU);

    //
    // Deassert the SSI0 chip selects for both the SD card and serial flash
    //
    GPIOPinWrite(SDCARD_CS_BASE, SDCARD_CS_PIN, SDCARD_CS_PIN);
    GPIOPinWrite(SFLASH_CS_BASE, SFLASH_CS_PIN, SFLASH_CS_PIN);

    //
    // Configure the SSI0 port for 10MHz operation
    //
    SSIConfigSetExpClk(SFLASH_SSI_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
                       SSI_MODE_MASTER, 10000000, 8);
    SSIEnable(SFLASH_SSI_BASE);

    //
    // Wait for the device to be ready to receive an instruction.
    //
    bRetcode = SSIFlashIdleWait(MAX_BUSY_POLL_IDLE);

    //
    // If the device didn't report that it was idle, assume it isn't there
    // and return an error.
    //
    if(!bRetcode)
    {
        return(bRetcode);
    }

    //
    // Read the device ID and check to see that it is one we recognize.
    //
    bRetcode = SSIFlashIDGet(&ucManufacturer, &ucDevice);
    if(!bRetcode || (ucManufacturer != MANUFACTURER_WINBOND) ||
       (ucDevice != DEVICE_ID_W25X80A))
    {
        //
        // This is not a device we recognize so return an error.
        //
        return(false);
    }
    else
    {
        //
        // All is well.
        //
        return(true);
    }
}

//*****************************************************************************
//
//! Determines if the serial flash is able to accept a new instruction.
//!
//! This function reads the serial flash status register and determines whether
//! or not the device is currently busy.  No new instruction may be issued to
//! the device if it is busy.
//!
//! \return Returns \b true if the device is busy and unable to receive a new
//! instruction or \b false if it is idle.
//
//*****************************************************************************
tBoolean
SSIFlashIsBusy(void)
{
    unsigned char ucStatus;

    //
    // Get the flash status.
    //
    ucStatus = SSIFlashStatusGet();

    //
    // Is the busy bit set?
    //
    return((ucStatus & STATUS_BUSY) ? true : false);
}

//*****************************************************************************
//
//! Returns the manufacturer and device IDs for the attached serial flash.
//!
//! \param pucManufacturer points to storage which will be written with the
//! manufacturer ID of the attached serial flash device.
//! \param pucDevice points to storage which will be written with the device
//! ID of the attached serial flash device.
//!
//! This function may be used to determine the manufacturer and device IDs
//! of the attached serial flash device.
//!
//! \return Returns \b true on success or \b false on failure.
//
//*****************************************************************************
tBoolean
SSIFlashIDGet(unsigned char *pucManufacturer, unsigned char *pucDevice)
{
    tBoolean bRetcode;
    unsigned char pucBuffer[3];

    //
    // Wait for the flash to be idle.
    //
    bRetcode = SSIFlashIdleWait(MAX_BUSY_POLL_IDLE);

    //
    // If the device is not idle, return an error.
    //
    if(!bRetcode)
    {
        return(bRetcode);
    }

    //
    // Now perform the instruction we need to read the IDs.
    //
    pucBuffer[0] = 0;
    pucBuffer[1] = 0;
    pucBuffer[2] = 0;
    SSIFlashInstructionWrite(INSTR_MAN_DEV_ID, pucBuffer, 3);
    SSIFlashInstructionRead(pucBuffer, 2);
    SSIFlashInstructionEnd();

    //
    // Copy the returned IDs into the caller's storage.
    //
    *pucManufacturer = pucBuffer[0];
    *pucDevice = pucBuffer[1];

    //
    // Tell the caller everything went well.
    //
    return(true);
}

//*****************************************************************************
//
//! Returns the size of a sector for this device.
//!
//! This function returns the size of an erasable sector for the serial flash
//! device.  All addresses passed to SSIFlashSectorErase() must be aligned on
//! a sector boundary.
//!
//! \return Returns the number of bytes in a sector.
//
//*****************************************************************************
unsigned long
SSIFlashSectorSizeGet(void)
{
    //
    // This device supports 4KB sectors.
    //
    return(W25X80A_SECTOR_SIZE);
}

//*****************************************************************************
//
//! Returns the size of a block for this device.
//!
//! This function returns the size of an erasable block for the serial flash
//! device.  All addresses passed to SSIFlashBlockErase() must be aligned on
//! a block boundary.
//!
//! \return Returns the number of bytes in a block.
//
//*****************************************************************************
unsigned long
SSIFlashBlockSizeGet(void)
{
    //
    // This device support 64KB blocks.
    //
    return(W25X80A_BLOCK_SIZE);
}

//*****************************************************************************
//
//! Returns the total amount of storage offered by this device.
//!
//! This function returns the size of the programmable area provided by the
//! attached SSI flash device.
//!
//! \return Returns the number of bytes in the device.
//
//*****************************************************************************
unsigned long
SSIFlashChipSizeGet(void)
{
    //
    // This device is 1MB in size.
    //
    return(W25X80A_CHIP_SIZE);
}

//*****************************************************************************
//
//! Erases the contents of a single serial flash sector.
//!
//! \param ulAddress is the start address of the sector which is to be erased.
//! This value must be an integer multiple of the sector size returned
//! by SSIFlashSectorSizeGet().
//! \param bSync should be set to \b true if the function is to block until
//! the erase operation is complete or \b false to return immediately after
//! the operation is started.
//!
//! This function erases a single sector of the serial flash, returning all
//! bytes in that sector to their erased value of 0xFF.  The sector size and,
//! hence, start address granularity can be determined by calling
//! SSIFlashSectorSizeGet().
//!
//! The function may be synchronous (\e bSync set to \b true) or asynchronous
//! (\e bSync set to \b false).  If asynchronous, the caller is responsible for
//! ensuring that no further serial flash operations are requested until the
//! erase operation has completed.  The state of the device may be queried by
//! calling SSIFlashIsBusy().
//!
//! Three options for erasing are provided. Sectors provide the smallest
//! erase granularity, blocks provide the option of erasing a larger section of
//! the device in one operation and, finally, the whole device may be erased
//! in a single operation via SSIFlashChipErase().
//!
//! \note This operation will take between 120mS and 250mS to complete. If the
//! \e bSync parameter is set to \b true, this function will, therefore, not
//! not return for a significant period of time.
//!
//! \return Returns \b true on success or \b false on failure.
//
//*****************************************************************************
tBoolean
SSIFlashSectorErase(unsigned long ulAddress, tBoolean bSync)
{
    tBoolean bRetcode;
    unsigned char pucBuffer[3];

    //
    // Make sure the address passed is aligned correctly.
    //
    if(ulAddress & (W25X80A_SECTOR_SIZE - 1))
    {
        //
        // Oops - it's not on a sector boundary so fail the call.
        //
        return(false);
    }

    //
    // Wait for the flash to be idle.
    //
    bRetcode = SSIFlashIdleWait(0);

    //
    // If the device is not idle, return an error.
    //
    if(!bRetcode)
    {
        return(bRetcode);
    }

    //
    // Enable write operations.
    //
    bRetcode = SSIFlashWriteEnable();

    //
    // If write operations could not be enabled, return the error.
    //
    if(!bRetcode)
    {
        return(bRetcode);
    }

    //
    // Now perform the instruction we need to erase the sector.
    //

⌨️ 快捷键说明

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