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

📄 drvserflash.c

📁 mstar 776 开发的车载dvd
💻 C
📖 第 1 页 / 共 2 页
字号:
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006-2007 MStar Semiconductor, Inc.
// All rights reserved.
//
// Unless otherwise stipulated in writing, any and all information contained
// herein regardless in any format shall remain the sole proprietary of
// MStar Semiconductor Inc. and be kept in strict confidence
// (¨MStar Confidential Information〃) by the recipient.
// Any unauthorized act including without limitation unauthorized disclosure,
// copying, use, reproduction, sale, distribution, modification, disassembling,
// reverse engineering and compiling of the contents of MStar Confidential
// Information is unlawful and strictly prohibited. MStar hereby reserves the
// rights to any and all damages, losses, costs and expenses resulting therefrom.
//
///@file Drvflash.h
///@brief Driver interface for accessing the flash.
///
///@author MStarSemi Inc.
///
///- Providing Read/Write and Erase function for accessing the flash.
///- Support 2 types of flash: Serial flash and Parallel flash.
///- Selecting different flash type by flag, but the Driver interface for serial/parallel flash is the same.
///
///@image html flash.jpg
///
///@par Example
///@code
///  //Erase database in flash
///  //Input   StartAddr:Database base address in flash
///  //Input   databaseSize: database size
///  BOOL msAPI_EraseFlashDatabase(U32 StartAddr, U16 databaseSize)
///  {
///       // Erase flash from "Database Start Address" to "End address"
///       MDrv_Flash_Erase(StartAddr, StartAddr+databaseSize);
///  }
///@endcode
///
///@internal This file is for Serial flash ONLY
////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <intrins.h>
#include "hwreg.h"
#include "debug.h"
#include "datatype.h"
#include "sysinfo.h"
#include "mreg51.h"
#include "drvuart.h"
#include "drvserflash_db.h"

/******************************************************************************/
// Local functions
/******************************************************************************/

#define BUSY_BIT        7
#define USE_FAST_READ   0

#define SPI_INFO(x) // x

extern void MDrv_Timer_Delayms(U32 u32DelayTime) ;

//------------------------------------------------------------------------------
void SFSH_RIU_REG16(U8 AddrOffset, U16 Data)
{
     XBYTE[ISP_BASE+AddrOffset]  =LOWBYTE(Data);
     XBYTE[ISP_BASE+AddrOffset+1]=HIGHBYTE(Data);
}

//------------------------------------------------------------------------------
U8 SFSH_RIU_Read8(U8 AddrOffset)
{
     return( XBYTE[ISP_BASE+AddrOffset]);
}

#define RESET_SPI()     (XBYTE[0x3C4D] = (XBYTE[0x3C4D] = (XBYTE[0x3C4D] | 0x01)) & ~0x01)
#define ENABLE_ISP()    SFSH_RIU_REG16(REG_SFSH_ISP_PASSWORD, 0xAAAA)
#define DISABLE_ISP()   do { SFSH_RIU_REG16(REG_SFSH_ISP_PASSWORD, 0x5555); RESET_SPI(); } while (0)
/*
#define ENABLE_ISP()    SFSH_RIU_REG16(REG_SFSH_ISP_PASSWORD, 0xAAAA)
//#define DISABLE_ISP()   SFSH_RIU_REG16(REG_SFSH_ISP_PASSWORD, 0x5555)
#define DISABLE_ISP()   {\
    SFSH_RIU_REG16(REG_SFSH_ISP_PASSWORD, 0x5555);\
    XBYTE[0x3C4D] |= BIT0;\
    XBYTE[0x3C4D] &= ~BIT0;\
    }
*/

//------------------------------------------------------------------------------
#if 0
void SerialFlashDelayLoop( U8 DlyCnt )
{
    U8 i;

    // TODO: can this be loop delay? what happens if CPU freq changes
    for ( i = 0; i <DlyCnt; i++ );
}
#endif
//------------------------------------------------------------------------------
// Wait for SPI Write Cmd Ready
// @return TRUE : succeed
// @return FALSE : fail before timeout
//------------------------------------------------------------------------------
BOOLEAN _MDrv_SerFlash_WaitWriteCmdRdy(void)
{
    BOOLEAN bRet = FALSE;

    //U8 DlyCnt0 = 0xff;

    do
    {
        if ( (SFSH_RIU_Read8(REG_SFSH_SPI_WR_CMD_RDY) & 0x1) == 0x1 )
        {
            bRet = TRUE;
            break;
        }

        //DlyCnt0--;
        //SerialFlashDelayLoop(0xff);

    } while ( 1 );  //DlyCnt0 > 0);

    //if ( DlyCnt0 == 0 )
    //{
    //     SPI_INFO(printf("_MDrv_SerFlash_WaitWriteCmdRdy time out\n"));
    //}

    return bRet;
}

//------------------------------------------------------------------------------
// Wait for SPI Write Data Ready
// @return TRUE : succeed
// @return FALSE : fail before timeout
//------------------------------------------------------------------------------
BOOLEAN _MDrv_SerFlash_WaitWriteDataRdy(void)
{
    BOOLEAN bRet = FALSE;
    //U8 DlyCnt0=0xff;

    do
    {
        if ( (SFSH_RIU_Read8(REG_SFSH_SPI_WR_DATA_RDY) & 0x1) == 0x1 )
        {
            bRet = TRUE;
            break;
        }

        //DlyCnt0--;  SerialFlashDelayLoop(0xff);
    } while ( 1 );   //DlyCnt0 > 0 );

    if (bRet == FALSE)
    {
        SPI_INFO(printf("Wait for SPI Write Data Ready fails!\r\n"));
    }

    return bRet;
}

//------------------------------------------------------------------------------
// Wait for SPI Read Data Ready
// @return TRUE : succeed
// @return FALSE : fail before timeout
//------------------------------------------------------------------------------
BOOLEAN _MDrv_SerFlash_WaitReadDataRdy(void)
{
    BOOLEAN bRet = FALSE;
    //U8 DlyCnt0=0xff;

    do
    {
        if ( (SFSH_RIU_Read8(REG_SFSH_SPI_RD_DATA_RDY) & 0x1) == 0x1 )
        {
            bRet = TRUE;
            break;
        }

        //DlyCnt0--;  SerialFlashDelayLoop(0x20);
    } while ( 1 );   //( DlyCnt0 > 0 );

    if (bRet == FALSE)
    {
        SPI_INFO(printf("Wait for SPI Read Data Ready fails!\r\n"));
    }

    return bRet;
}

//------------------------------------------------------------------------------
// Wait for Write/Erase to be done
// @return TRUE : succeed
// @return FALSE : fail before timeout
//------------------------------------------------------------------------------
BOOLEAN _MDrv_SerFlash_WaitWriteDone(void)
{
    BOOLEAN bRet = FALSE;

    if ( _MDrv_SerFlash_WaitWriteCmdRdy() == FALSE )
    {
        return FALSE;
    }

    do
    {
        SFSH_RIU_REG16(REG_SFSH_SPI_COMMAND, 0x8005);   // RDSR

        SFSH_RIU_REG16(REG_SFSH_SPI_RD_REQ ,0x01);      // SPI read request

        if ( _MDrv_SerFlash_WaitReadDataRdy() == FALSE )
        {
            //printf("start check..2.\r\n");
            break;
        }

        if ( (SFSH_RIU_Read8(REG_SFSH_RDATA) & 0x1) == 0 ) //WIP =0 write done
        {
            bRet = TRUE;
            break;
        }
    } while (1); // (MsOS_GetSystemTime()-u32Timer) < 100 ); //max (chip erase = 100ms, sector erase = 25ms, byte program = 20 us)

    if (bRet == FALSE)
    {
        SPI_INFO(printf("Wait for Write to be done fails!\r\n"));
    }

    SFSH_RIU_REG16(REG_SFSH_SPI_CE_CLR, 1); //SPI CEB dis

    return bRet;
}

//------------------------------------------------------------------------------
// Check for Write/Erase to be done
// @return TRUE : Done
// @return FALSE : Write In Progress
//------------------------------------------------------------------------------
BOOLEAN _MDrv_SerFlash_CheckWriteDone(void)
{
    BOOLEAN bRet = FALSE;

    if ( _MDrv_SerFlash_WaitWriteCmdRdy() == FALSE )
    {
        return FALSE;
    }

    SFSH_RIU_REG16(REG_SFSH_SPI_COMMAND, 0x8005);   // RDSR

    SFSH_RIU_REG16(REG_SFSH_SPI_RD_REQ ,0x01);      // SPI read request

    if ( _MDrv_SerFlash_WaitReadDataRdy() == FALSE )
    {
        //printf("start check..2.\r\n");
        //break;
    }

    if ( (SFSH_RIU_Read8(REG_SFSH_RDATA) & 0x1) == 0 ) //WIP =0 write done
    {
        bRet = TRUE;
    }

    if (bRet == FALSE)
    {
        SPI_INFO(printf("Write In Progress!\r\n"));
    }

    SFSH_RIU_REG16(REG_SFSH_SPI_CE_CLR, 1); //SPI CEB dis

    return bRet;
}

//------------------------------------------------------------------------------
/// Initialize Serial Flash
/// @return None
//------------------------------------------------------------------------------
void MDrv_SerFlash_Init(void)
{
    // this could be changed depends on different flash type; should this depends on CPU freq?
    // div 4 is safe even MCU runs up to 200Mhz
    SFSH_RIU_REG16(REG_SFSH_SPI_CLK_DIV, 0x0004);   // Div 4;

    SFSH_RIU_REG16(REG_SFSH_DEV_SEL, BRAND_PMC);    // PMC flash

    SFSH_RIU_REG16(REG_SFSH_ENDIAN_SEL_SPI, 0);     // Little-Endian
}

/******************************************************************************/
/// Write data to flash
/// @param -u32addr \b IN: Starting address in flash to write
/// @param -u32size \b IN: Total size to write
/// @param -pdat \b IN: Pointer to the data buffer which is going to be written to flash
/// @par Function Actions:
/******************************************************************************/
BOOLEAN MDrv_Flash_Write(U32 u32Addr, U32 u32Size, U8 *pu8Data)
{
    BOOLEAN bRet = FALSE;
    U32 u32I;
    U32 u32Rem, u32WriteBytes;

#define SERFLASH_PAGE_SIZE  256

    ENABLE_ISP();

    u32Rem = u32Addr % SERFLASH_PAGE_SIZE;

    if ( u32Rem )
    {
        u32WriteBytes = SERFLASH_PAGE_SIZE - u32Rem;

        if ( u32Size < u32WriteBytes )
        {
            u32WriteBytes = u32Size;
        }

        if ( _MDrv_SerFlash_WaitWriteCmdRdy() == FALSE )
        {
            goto MDrv_SerFlash_Write_return;
        }

        //SFSH_RIU_REG16(REG_SFSH_SPI_COMMAND , 0x8006 ); //WREN
        SFSH_RIU_REG16(REG_SFSH_SPI_COMMAND , 0x0006 ); //WREN

        SFSH_RIU_REG16(REG_SFSH_ADDRESS21 , LOU16(u32Addr) );
        SFSH_RIU_REG16(REG_SFSH_ADDRESS3  , HIU16(u32Addr) );

        if ( _MDrv_SerFlash_WaitWriteCmdRdy() == FALSE )
        {
            goto MDrv_SerFlash_Write_return;
        }

        SFSH_RIU_REG16(REG_SFSH_SPI_COMMAND , 0x8002 ); //PAGE_PROG

        for ( u32I = 0; u32I < u32WriteBytes; u32I++ )
        {
            SFSH_RIU_REG16(REG_SFSH_WDATA ,  ( 0x8000 | pu8Data[u32I] ) );

            if ( _MDrv_SerFlash_WaitWriteDataRdy() == FALSE )
            {
                goto MDrv_SerFlash_Write_return;
            }
        }

        SFSH_RIU_REG16(REG_SFSH_SPI_CE_CLR , 1 ); //SPI CEB dis

        bRet = _MDrv_SerFlash_WaitWriteDone();

        if ( bRet == TRUE )
        {
            u32Addr += u32WriteBytes;
            pu8Data += u32WriteBytes;
            u32Size -= u32WriteBytes;
        }
        else
        {
            goto MDrv_SerFlash_Write_return;
        }
    }

    while ( u32Size )
    {
        if ( u32Size > SERFLASH_PAGE_SIZE )
        {
            u32WriteBytes = SERFLASH_PAGE_SIZE; //write EEPROM_WRITE_BYTES_MAX bytes one time
        }
        else
        {
            u32WriteBytes = u32Size;
        }

        if ( _MDrv_SerFlash_WaitWriteCmdRdy() == FALSE )
        {
            goto MDrv_SerFlash_Write_return;
        }

        SFSH_RIU_REG16(REG_SFSH_SPI_COMMAND , 0x8006 ); //WREN

        SFSH_RIU_REG16(REG_SFSH_ADDRESS21, LOU16(u32Addr) ) ;
        SFSH_RIU_REG16(REG_SFSH_ADDRESS3 , HIU16(u32Addr) );

        if ( _MDrv_SerFlash_WaitWriteCmdRdy() == FALSE )
        {
            goto MDrv_SerFlash_Write_return;
        }

        SFSH_RIU_REG16(REG_SFSH_SPI_COMMAND , 0x8002 ); //PAGE_PROG

        for ( u32I = 0; u32I < u32WriteBytes; u32I++ )
        {
            SFSH_RIU_REG16(REG_SFSH_WDATA , ( 0x8000 | pu8Data[u32I] ) );

            if ( _MDrv_SerFlash_WaitWriteDataRdy() == FALSE )
            {
                goto MDrv_SerFlash_Write_return;
            }
        }

        SFSH_RIU_REG16(REG_SFSH_SPI_CE_CLR , 1 ); //SPI CEB dis

        bRet = _MDrv_SerFlash_WaitWriteDone();

        if ( bRet == TRUE )
        {
            u32Addr += u32WriteBytes;
            pu8Data += u32WriteBytes;
            u32Size -= u32WriteBytes;
        }
        else
        {
            goto MDrv_SerFlash_Write_return;
        }
    }

MDrv_SerFlash_Write_return:

    SFSH_RIU_REG16(REG_SFSH_SPI_CE_CLR , 1 ); //SPI CEB dis

    DISABLE_ISP();
    //MDrv_Timer_Delayms(5);  // seven 20070808 for SPI

    SPI_INFO(printf("MDrv_SerFlash_Write %x\n", bRet));

    return bRet;

⌨️ 快捷键说明

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