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

📄 drv_28f128.c

📁 Flash型号: 28F128 功能说明:驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "vxWorks.h"            /* always first */
#include "config.h"             /* board support configuration header */
#include "typedef.h"
#include "../board/bsp.h"

/*#define BIT_0                           0x01
#define BIT_1                           0x02
#define BIT_2                           0x04
#define BIT_3                           0x08
#define BIT_4                           0x10
#define BIT_5                           0x20
#define BIT_6                           0x40*/      // for pc-lint
#define BIT_7                           0x80

/* Flash private command, only operate by 16 bit */
#define READ_FLASH_ARRAY                0xFFFF
#define READ_FLASH_ID_CODE              0x9090
#define CLEAR_FLASH_STATUS              0x5050
#define WRITE_FLASH_BUFFER              0xE8E8
#define ERASE_FLASH_BLOCK               0x2020
#define RESUME_FLASH_CMD                0xD0D0
#define READ_FLASH_STATUS               0x7070
#define SET_FLASH_LOCK_CMD1             0x6060
#define WRITE_FLASH_BYTE                0x4040
/*#define READ_FLASH_QUERY                0x9898
#define ERASE_FLASH_SUSPEND             0xB0B0
#define CONFIGURATION_FLASH             0xB8B8

#define SET_FLASH_LOCK_CMD2             0x0101
#define PROGRAM_FLASH_PROTECTION        0xC0C0*/    // for pc-lint

#define ESR_POLLING_TIMEOUT             0x00800000L

#define FLASH_BUFFER_SIZE               0x0F

/* Each block is 128K */
#define FLASH_BLOCK_MASK                0xFFFE0000

#define FLASH_NO_OPERATOR      0
#define FALSH_DIREC_WRITE      1
#define FALSH_ERASE_WRITE      2

#define DELAY_WRITE            0x01
#define DEFAULT_STATUS         0x00

_U8 Drv_FlashStatus = DEFAULT_STATUS;

_U32 WriteFlashSeg( _U16 *FlashAddr, _U32 ByteCount, _U8 *RamAddr );
_U16 ReadFlashStatus( _U16 *FlashAddr );
void WriteFlashStatus( _U16 *FlashAddr, _U16 value );
//static _U32 CheckFlashMem(_U32 pMem , _U32 pFlashBlock , _U32 Length , _U8 *retStatus, _U32 *StartOffset,_U32 *EndOffset);

_U32 FlashErase(_U16 *addr);
/* write flash buffer */
_U8 BlockMapMem[0x20000];

extern void BSP_PrintMemSimple(char *pData,_U32 Count);


/*****************************************************************************
function :     write flash
return   :     SUCCESS if write success
               FAILURE if write fail
******************************************************************************/
_U32 Drv_WriteFlash( _U32 FlashAddr, _U32 ByteCount, _U32 RamAddr )
{
    _U32 AddrTemp, LenTmp = 0;
    long WriteCount = 0;
    _U8 *pSrc, *pDst, *pTmp;

    /* Check input flash address */
    if ( (FlashAddr < FLASH_START_ADDR)
       ||(FlashAddr > FLASH_END_ADDR))
    {
        Drv_Print("\r\n Input flash address error, FlashAddr = 0x%lx", FlashAddr);
        return FAILURE;
    }

    /* Get flash address(in flash) */
    pTmp = (_U8 *)FlashAddr;

    /* Remained byte count that wait to write into flash */
    WriteCount = (long)ByteCount;

    /* Source address(in ram) */
    pSrc = (_U8 *)RamAddr;


    while (WriteCount > 0)
    {
        /* Get current writing flash block address */
        AddrTemp = (_U32)pTmp & FLASH_BLOCK_MASK;

        /* Read current block to  BlockMapMem */
        if (Drv_ReadFlash(AddrTemp, FLASH_BLOCK_SIZE, (_U32)(_U8*)BlockMapMem) != SUCCESS)
        {
            Drv_Print("\r\n ReadFlash error!");
            return FAILURE;
        }

        /* Get writing ram address(in ram), offset from 0 to ByteCount */
        pSrc = (_U8 *)(pSrc + LenTmp);

        /* Get writing block address(in BlockMapMem), because AddrTemp in block,
           so offset is (FlashAddr - AddrTemp), base is BlockMapMem. BlockMapMem
           is map of flash */
        pDst = (_U8 *)(FlashAddr - AddrTemp + BlockMapMem);

        /* Get write count */
        if ((_U32)WriteCount + FlashAddr - (FlashAddr & FLASH_BLOCK_MASK) >= FLASH_BLOCK_SIZE)
        {
            LenTmp = AddrTemp + FLASH_BLOCK_SIZE - FlashAddr;
        }
        else
        {
            /* If last block, only write remain content */
            LenTmp = (_U32)WriteCount;
        }

        /* If content is same in a block, no erase no write */
        if (memcmp(pDst, pSrc, LenTmp) != 0)
        {
		    if (DELAY_WRITE == Drv_FlashStatus)
		    {
//		    	Drv_Print("\r\n %d",__LINE__);
		        (void)taskDelay(1);
		    }
            memcpy((char *)pDst, (char *)pSrc, LenTmp);

            if (FlashErase((_U16 *)AddrTemp) == FAILURE)
            {
                Drv_Print("\r\n Erase error!");
                return FAILURE;
            }


            if (FAILURE == WriteFlashSeg((_U16 *)AddrTemp, FLASH_BLOCK_SIZE, BlockMapMem))
            {
            	Drv_Print("Write Flash Seg fail.");
                return FAILURE;
            }

        }
	    if (DELAY_WRITE == Drv_FlashStatus)
	    {
//	    	Drv_Print("\r\n %d",__LINE__);
	        (void)taskDelay(1);
	    }


        pTmp = (_U8 *)(AddrTemp + FLASH_BLOCK_SIZE);

        WriteCount -= (long)LenTmp;

        FlashAddr += LenTmp;
    }
    return SUCCESS;
}


/*****************************************************************************
function :     Read data from flash memory chip.
return   :     void
******************************************************************************/
_U32 Drv_ReadFlash( _U32 FlashAddr, _U32 ByteNum, _U32 RamAddr )
{
    _U32 loop ;
    _U8 *src ;
    _U8 *dest ;

    if ( (FlashAddr < FLASH_START_ADDR)
       ||(FlashAddr >= FLASH_END_ADDR) )
    {
        Drv_Print("\r\n Read flash address error, FlashAddr = 0x%lx", FlashAddr);
        return FAILURE;
    }


    if (RamAddr == 0)
    {
        return FAILURE;
    }

    src  = (_U8 *)FlashAddr ;
    dest = (_U8 *)RamAddr ;

    /* Write status word */
    WriteFlashStatus((_U16 * )FLASH_START_ADDR, CLEAR_FLASH_STATUS);
    WriteFlashStatus((_U16 * )FLASH_START_ADDR, READ_FLASH_ARRAY);

    /* Get data from flash */
    for (loop = 0; loop < ByteNum; loop++)
    {
        *dest++ = *src++;
    }
    return SUCCESS;
}

/****************************************************************************
 function    : Judge flash if on board by read manuf code and device code,
               in 28f640 is 0x89 and 0x17, in 28f128 is 0x89 and 0x18
 return      : FLASH_28F640 or FLASH_28F128 if on board
               FAILURE if no flash
****************************************************************************/
_U32 Drv_IsFlashOnboard(void)
{
    _U16 ucManufCode, ucDeviceCode;

    *((_U16 * )FLASH_START_ADDR) = READ_FLASH_ID_CODE;
    ucManufCode  =  *((_U16 *) FLASH_START_ADDR );
    /* 在读取identifier codes时,A0地址是无效的,最低位从A1开始。文档4.2 */
    ucDeviceCode =  *((_U16 *) (FLASH_START_ADDR + 2));

    if ( (ucManufCode != 0x89)
       ||((ucDeviceCode != 0x17)&&(ucDeviceCode != 0x18)) )
    {
        Drv_Print("\r\n Flash is not on board, Manuf Code is 0x%x, Device code is 0x%x",
            ucManufCode, ucDeviceCode);
        return FAILURE;
    }

    /* Switch status to read */
    WriteFlashStatus((_U16 * )FLASH_START_ADDR, CLEAR_FLASH_STATUS);
    WriteFlashStatus((_U16 * )FLASH_START_ADDR, READ_FLASH_ARRAY);

    return ucDeviceCode;
}

#if USE_FLASH_BUFFER
/*****************************************************************************
function :     write flash one block
return   :     SUCCESS if write success
               FAILURE if write fail
******************************************************************************/
_U32 WriteFlashSeg( _U16 *FlashAddr, _U32 ByteCount, _U8 *RamAddr )
{
    _U32 i,j,t = 0;
    _U16 *p1, *p2, status;
    _U32 BufCount, LastCount, Length = FLASH_BUFFER_SIZE;




    /* Switch to read array status */
    WriteFlashStatus( (_U16 *)FlashAddr, CLEAR_FLASH_STATUS ) ;
    WriteFlashStatus( (_U16 *)FlashAddr, READ_FLASH_ARRAY ) ;


    p1 = (_U16 *)FlashAddr;
    p2 = (_U16 *)RamAddr;

    /* Buffer count that wait for writing, one buffer length is 16 word(32 byte) */
    BufCount = ByteCount/((FLASH_BUFFER_SIZE + 1)*2) ;

    /* Last buffer data length */
    LastCount = (_U32)(ByteCount%((FLASH_BUFFER_SIZE + 1)*2));

    if (DELAY_WRITE == Drv_FlashStatus)
    {
//    	Drv_Print("\r\n %d",__LINE__);
        (void)taskDelay(1);
    }


    for(i = 0; i <= BufCount; i++)
    {
        Length = FLASH_BUFFER_SIZE;

        /* Deal with last buffer */
        if(i == BufCount)
        {
            if(LastCount != 0)
                Length = LastCount - 1;
            else
                break;
        }

        /* 1、Write status */
        WriteFlashStatus((_U16 *)p1, WRITE_FLASH_BUFFER);

        status = ReadFlashStatus(p1);

        while( ((status & BIT_7) != BIT_7)
            && (t++ <= ESR_POLLING_TIMEOUT) )
        {
            /*如果写入有些问题可以考虑在此加入写状态字命令 :
            WriteFlashStatus((_U16 *)p1, WRITE_FLASH_BUFFER);
            */
            status = ReadFlashStatus(p1);
        }
        if (t >= ESR_POLLING_TIMEOUT)
        {
//            Drv_Print("\r\n Read Flash Status Timeout!!!,%d",__LINE__);
            return FAILURE;
        }
//        Drv_Print("\r\n ReadFlash OK! %d",__LINE__);
        /* 2、Write length */
        WriteFlashStatus((_U16 *)p1, (_U16)Length);
//        Drv_Print("\r\n %d Write Status Addr: 0x%x, Write Value:0x%x",__LINE__,(_U32)p1,Length);

        /* 3、Write data */
        for (j = 0; j <= Length; j++)
        {
            WriteFlashStatus((_U16 *)p1++, *(_U16 *)p2++);
        }

        /* 减8是为了保证地址在FLASH的范围内,因为前面有P1++可能越界。 */
        p1 -= 8;

        /* 4、Confirm Command */
        WriteFlashStatus((_U16 *)p1, RESUME_FLASH_CMD);


        t = 0;
        /*按照INTEL手册上说,此时如果读到BIT7为1,
        应该判断其他位是否为1,各个有各自的错误描述。
        此时为0或者为1应该都可以结束。以后可以考虑删除以下代码。*/
        status = ReadFlashStatus(p1);

        while( ((status & BIT_7) != BIT_7)
            && (t++ <= ESR_POLLING_TIMEOUT) )
        {
            status = ReadFlashStatus(p1);
        }
        if (t >= ESR_POLLING_TIMEOUT)
        {
            Drv_Print("\r\n Read Flash Status Timeout!!!,%d",__LINE__);

            return FAILURE;
        }


        p1 += 8;


    }

    /* Switch to read array status */
    WriteFlashStatus( (_U16 *)FlashAddr, CLEAR_FLASH_STATUS ) ;
    WriteFlashStatus( (_U16 *)FlashAddr, READ_FLASH_ARRAY ) ;



    return(SUCCESS);
}
#else
/*****************************************************************************
function :     write flash one block
return   :     SUCCESS if write success
               FAILURE if write fail
******************************************************************************/
_U32 WriteFlashSeg( _U16 *FlashAddr, _U32 ByteCount, _U8 *RamAddr )
{
    _U16 ucByte = 0 ;
    _U32 loop = 0, cnt = 0 ;
	_U16 *pucValue = 0;

	pucValue = (_U16 *)RamAddr;

    if (DELAY_WRITE == Drv_FlashStatus)
    {
//    	Drv_Print("\r\n %d",__LINE__);
        (void)taskDelay(1);
    }
    for (cnt = 0; cnt < ByteCount; cnt += 2)
    {//因为采用16位操作.
        /* Byte write command */
        WriteFlashStatus( FlashAddr, WRITE_FLASH_BYTE ) ;

        /* Actual data write to flash address */
        WriteFlashStatus( FlashAddr, *pucValue ) ;

        ucByte = ReadFlashStatus( FlashAddr ) ;

        loop = 0 ;
        /* Poll CSR until CSR.7 = 1 (WSM) */
        while ((!(BIT_7 & ucByte)) && (loop ++ < ESR_POLLING_TIMEOUT))
        {
		    if ((DELAY_WRITE == Drv_FlashStatus)&&(loop % 2048 == 0))
			{
//			   	Drv_Print("\r\n %d",__LINE__);
			    (void)taskDelay(1);
			}
            ucByte = ReadFlashStatus( FlashAddr ) ;
        }

        if (loop >= ESR_POLLING_TIMEOUT)
        {
            return FAILURE;
        }

	    if ((DELAY_WRITE == Drv_FlashStatus)&&(cnt % (FLASH_BLOCK_SIZE/16) == 0))
		{
//		   	Drv_Print("\r\n %d",__LINE__);
		    (void)taskDelay(1);
		}

        FlashAddr++ ;
        pucValue++;


    }
    if (DELAY_WRITE == Drv_FlashStatus)
    {
//    	Drv_Print("\r\n %d",__LINE__);
        (void)taskDelay(1);
    }

	FlashAddr--;
    /* Switch to read array status */
    WriteFlashStatus( (_U16 *)FlashAddr, CLEAR_FLASH_STATUS ) ;
    WriteFlashStatus( (_U16 *)FlashAddr, READ_FLASH_ARRAY ) ;

    return SUCCESS;
}
#endif
//不用擦除直接写 单字符写入
_U32 Drv_FlashTestWrite( _U8 *FlashAddr, _U32 ByteCount, _U8 *RamAddr )
{
    _U16 ucByte = 0 ;
    _U32 loop = 0, cnt = 0 ;
	_U16 *pucValue = 0;

	pucValue = (_U16 *)RamAddr;

    if (DELAY_WRITE == Drv_FlashStatus)
    {
//    	Drv_Print("\r\n %d",__LINE__);
        (void)taskDelay(1);
    }
    for (cnt = 0; cnt < ByteCount; cnt += 2)
    {//因为采用16位操作.
        /* Byte write command */

⌨️ 快捷键说明

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