spi读写MT25QL01Gbflash

flash擦除是以页扇区为单位擦除,16位的falsh是三字节模式读写,超过16位使用四字节模式读写。

#include "flashspi.h"
#include "hw_types.h"
#include "hw_cm_cefuse.h"
#include "hw_cm_device.h"
#include "hw_cm_dpll.h"
#include "hw_cm_gfx.h"
#include "hw_cm_mpu.h"
#include "hw_cm_per.h"
#include "hw_cm_rtc.h"
#include "hw_cm_wkup.h"
#include "hw_control_AM335x.h"
#include "hw_emif4d.h"
#include "soc_AM335x.h"
#include "mcspi.h"
#include "gpio_v2.h"
#include "plat_gpio.h"
#include "stdlib.h"
#include "plat_mcspi.h"

#ifdef AM335X_DRIVER
    #define printf(...)   ;
#endif

static UINT8 spiFlashTxBuf[SPIFLASH_PAGESIZE + 5];
static UINT8 spiFlashRxBuf[SPIFLASH_PAGESIZE + 5];

static UINT8 statusbuf[8];


UINT32 SPIInit(INT32 spiId, UINT8 spiClockDiv, UINT8 spiDir)
{
	INT32 spiAddr;
	switch(spiId)
	{
	    case SPI_0:
	            spiAddr = MCSPI0_BASE_ADDR;
	                break;
	    case SPI_1:
	            spiAddr = MCSPI1_BASE_ADDR;
	                break;
	}

	HWREG(spiAddr + MCSPI_SYSCONFIG) |= (MCSPI_SYSCONFIG_SOFTRESET_INITIATE <<
			 MCSPI_SYSCONFIG_SOFTRESET_SHIFT);

	    /* Wait for reset to complete */
	    while(HWREG(spiAddr + MCSPI_SYSSTATUS) &
	        MCSPI_SYSSTATUS_RESETDONE_COMPLETED == 0);

	    /* Reset SPI - Bit is automatically reset by hardware*/
    HWREG(spiAddr + MCSPI_SYSCONFIG) = ((MCSPI_SYSCONFIG_AUTOIDLE_ENABLE <<
    		MCSPI_SYSCONFIG_AUTOIDLE_SHIFT) | (MCSPI_SYSCONFIG_CLOCKACTIVITY_BOTH <<
    				MCSPI_SYSCONFIG_CLOCKACTIVITY_SHIFT) |
    				(MCSPI_SYSCONFIG_SIDLEMODE_WAKEUP << MCSPI_SYSCONFIG_SIDLEMODE_SHIFT));

    /* gBoardID = 1; */		//For ICE board SPI Flash

    /* SPI System Register Configuration*/

    if (spiDir== 0)
    {
        HWREG(spiAddr + MCSPI_SYST) =
            (1 << MCSPI_SYST_SPIDATDIR0_SHIFT);
    }
    else
    {
        HWREG(spiAddr + MCSPI_SYST) =
            (1 << MCSPI_SYST_SPIDATDIR1_SHIFT);
    }

    /* Configure MCSPI Module */
    HWREG(spiAddr + MCSPI_MODULCTRL) =
    	((HWREG(spiAddr + MCSPI_MODULCTRL) &
    	~(MCSPI_MODULCTRL_SYSTEM_TEST | MCSPI_MODULCTRL_MS))
    	| ( MCSPI_MODULCTRL_SINGLE_SINGLE << MCSPI_MODULCTRL_SINGLE_SHIFT ));

    if (spiDir== 0)
    {
		HWREG ( spiAddr + MCSPI_CHCONF(0)) =
				(( MCSPI_CH0CONF_DPE0_DISABLED << MCSPI_CH0CONF_DPE0_SHIFT )
			| ( MCSPI_CH0CONF_WL_8BITS << MCSPI_CH0CONF_WL_SHIFT )
			| ( spiClockDiv << MCSPI_CH0CONF_CLKD_SHIFT )
			| ( MCSPI_CH0CONF_EPOL_ACTIVELOW << MCSPI_CH0CONF_EPOL_SHIFT )
			| ( MCSPI_CH0CONF_PHA_EVEN << MCSPI_CH0CONF_PHA_SHIFT )
			| ( MCSPI_CH0CONF_POL_ACTIVELOW << MCSPI_CH0CONF_POL_SHIFT ));
    }
    else
    {
		HWREG ( spiAddr + MCSPI_CHCONF(0)) =
				(( MCSPI_CH0CONF_DPE1_DISABLED << MCSPI_CH0CONF_DPE1_SHIFT )
			| ( MCSPI_CH0CONF_WL_8BITS << MCSPI_CH0CONF_WL_SHIFT )
			| ( MCSPI_CH0CONF_IS_LINE1 << MCSPI_CH0CONF_IS_SHIFT )
			| ( spiClockDiv << MCSPI_CH0CONF_CLKD_SHIFT )
			| ( MCSPI_CH0CONF_EPOL_ACTIVELOW << MCSPI_CH0CONF_EPOL_SHIFT )
			| ( MCSPI_CH0CONF_PHA_EVEN << MCSPI_CH0CONF_PHA_SHIFT )
			| ( MCSPI_CH0CONF_POL_ACTIVELOW << MCSPI_CH0CONF_POL_SHIFT ));
    }

    /* gBoardID = 2; */	//For ICE Board SPI Flash

    /* Configure MCSPI Channel 1 */
    HWREG ( spiAddr + MCSPI_CHCONF(1)) =
    		(( MCSPI_CH1CONF_DPE1_DISABLED << MCSPI_CH1CONF_DPE1_SHIFT )
        | ( MCSPI_CH1CONF_WL_8BITS << MCSPI_CH1CONF_WL_SHIFT )
        | ( MCSPI_CH1CONF_IS_LINE1 << MCSPI_CH1CONF_IS_SHIFT )
        | ( spiClockDiv << MCSPI_CH1CONF_CLKD_SHIFT )
        | ( MCSPI_CH1CONF_EPOL_ACTIVELOW << MCSPI_CH1CONF_EPOL_SHIFT )
        | ( MCSPI_CH1CONF_PHA_EVEN << MCSPI_CH1CONF_PHA_SHIFT )
        | ( MCSPI_CH1CONF_POL_ACTIVELOW << MCSPI_CH1CONF_POL_SHIFT ));

    /* Configure MCSPI Channel 2 */
    HWREG ( spiAddr + MCSPI_CHCONF(2)) =
    		(( MCSPI_CH2CONF_DPE1_DISABLED << MCSPI_CH2CONF_DPE1_SHIFT )
        | ( MCSPI_CH2CONF_WL_8BITS << MCSPI_CH2CONF_WL_SHIFT )
        | ( MCSPI_CH2CONF_IS_LINE1 << MCSPI_CH2CONF_IS_SHIFT )
        | ( MCSPI_CH2CONF_CLKD_DIVBY256 << MCSPI_CH2CONF_CLKD_SHIFT )
        | ( MCSPI_CH2CONF_EPOL_ACTIVELOW << MCSPI_CH2CONF_EPOL_SHIFT )
        | ( MCSPI_CH2CONF_PHA_EVEN << MCSPI_CH2CONF_PHA_SHIFT )
        | ( MCSPI_CH2CONF_POL_ACTIVELOW << MCSPI_CH2CONF_POL_SHIFT ));


    /* Configure MCSPI Channel 3 */
    HWREG ( spiAddr + MCSPI_CHCONF(3)) =
    		(( MCSPI_CH3CONF_DPE1_DISABLED << MCSPI_CH3CONF_DPE1_SHIFT )
        | ( MCSPI_CH3CONF_WL_8BITS << MCSPI_CH3CONF_WL_SHIFT )
        | ( MCSPI_CH3CONF_IS_LINE1 << MCSPI_CH3CONF_IS_SHIFT )
        | ( MCSPI_CH3CONF_CLKD_DIVBY256 << MCSPI_CH3CONF_CLKD_SHIFT )
        | ( MCSPI_CH3CONF_EPOL_ACTIVELOW << MCSPI_CH3CONF_EPOL_SHIFT )
        | ( MCSPI_CH3CONF_PHA_EVEN << MCSPI_CH3CONF_PHA_SHIFT )
        | ( MCSPI_CH3CONF_POL_ACTIVELOW << MCSPI_CH3CONF_POL_SHIFT ));

    return spiAddr;
}


void SPICycle( UINT32 spiAddr, UINT8 *buf, UINT16 len, UINT16 chNum )
{
	UINT32 i;
	/* Enable Channel */
    if (chNum > 0)
    	chNum = 1;   /*In SUBARTIC only two channels are used*/

    HWREG ( spiAddr + MCSPI_CHCTRL(chNum)) = MCSPI_CH0CTRL_EN_ACTIVE;
    GPIOCs_Write(6,0);
    forLoop();

    /* SPI access cycle */
    HWREG ( spiAddr + MCSPI_CHCONF(chNum)) |=
	    ( MCSPI_CH0CONF_FORCE_ASSERT << MCSPI_CH0CONF_FORCE_SHIFT ) ;

    /* SPI System Register Configuration*/
	HWREG(spiAddr + MCSPI_SYST) = (HWREG(spiAddr + MCSPI_SYST) &
		   ~MCSPI_SYST_SPIEN_0);

    for ( i = 0 ; i < len ; i++ )
    {

    	/* Wait for transmit empty */
        while ( ( HWREG(spiAddr + MCSPI_CHSTAT(chNum))
				& TX_EMPTY_FLAG) == 0 );

        HWREG (spiAddr + MCSPI_TX(chNum)) = buf[i]; // Write to TX buf

        /* Wait for receive data full */
        while ( (HWREG(spiAddr + MCSPI_CHSTAT(chNum))&
				RX_FULL_FLAG) == 0 );
        buf[i] = HWREG ( spiAddr + MCSPI_RX(chNum));// Read from RX buf
    }

#if 0
    for ( i = 0 ; i < len ; i++ )
    	UARTPrint1("SPI Data", buf[i]);
#endif

    HWREG ( spiAddr + MCSPI_CHCONF(chNum)) =
    		(HWREG ( spiAddr + MCSPI_CHCONF(chNum)) &
          ~( MCSPI_CH0CONF_FORCE)) ;

	HWREG(spiAddr + MCSPI_SYST) |= (1 << MCSPI_SYST_SPIEN_0_SHIFT);
	GPIOCs_Write(6,1);
	/* Disable Channel */
	HWREG ( spiAddr + MCSPI_CHCTRL(chNum)) = MCSPI_CH0CTRL_EN_INACTIVE;
	forLoop();
}


void SPIRead( UINT32 spiAddr, UINT8 *buf, UINT16 len, UINT16 chNum)
{
    SPICycle( spiAddr, buf, len, chNum);
}


void SPIWrite( UINT32 spiAddr, UINT8 *buf, UINT16 len, UINT16 chNum)
{
    SPICycle( spiAddr, buf, len, chNum);
}


void forLoop()
{
	volatile int loop;
	for(loop = 0; loop < 1000; loop++);
}


UINT8 spiFlashStatus( UINT32 spiAddr)
{
    /* Issue read status command */
    statusbuf[0] = SPIFLASH_CMD_RDSR;
    statusbuf[1] = 0;
    SPIRead(spiAddr, statusbuf, SPI_STATUS_LEN, SPI_FLASH_CH);
    return statusbuf[1];
}


void setFlash4Byte(UINT32 spiAddr)
{
	spiFlashTxBuf[0] = CMD_ENTER_4_BYTE;
	SPIWrite(spiAddr, spiFlashTxBuf, SPI_WPEN_LEN, SPI_FLASH_CH);
}


INT32 SPI_FlashReadID (UINT32 spiAddr)
{
    statusbuf[0] = SPIFLASH_CMD_READID;
    statusbuf[1] = 0x00;
    statusbuf[2] = 0x00;
    statusbuf[3] = 0x00;

    SPIRead(spiAddr, statusbuf, MFID_DEVID_LEN, SPI_FLASH_CH);

    printf ("ID read is 0x%x.\r\n", statusbuf[1]);
    printf ("ID read is 0x%x.\r\n", statusbuf[2]);
    printf ("ID read is 0x%x.\r\n", statusbuf[3]);

    return (0);
}


void SPI_FlashRead( UINT32 src, UINT32 *dst, UINT32 length, UINT32 spiAddr )
{
    INT32 i, j = 0;
    unsigned int allLen = 0, readLen = 0;
    // Setup command

    for (allLen = 0; allLen < length; allLen += SPIFLASH_PAGESIZE)
    {
    	readLen = (length -  allLen) >  SPIFLASH_PAGESIZE ? SPIFLASH_PAGESIZE:(length -  allLen);

    	spiFlashRxBuf[0] = SPIFLASH_CMD_READPAGE;
		spiFlashTxBuf[1] = ( src >> SHIFT_24BIT);
		spiFlashRxBuf[2] = ( src >> SHIFT_WORD );
		spiFlashRxBuf[3] = ( src >> SHIFT_BYTE );
		spiFlashRxBuf[4] = ( src >> 0 );

		// Execute SPIFLASH read cycle
		SPIRead(spiAddr, spiFlashRxBuf, readLen + 5, SPI_FLASH_CH);

		for ( i = 0 ; i < length ; i++ )
		{
			dst[j] = spiFlashRxBuf[5+i];
			j++;
		}
		src += readLen;
    }

    return;
}


UINT8 SPI_FlashErase(UINT32 offset, UINT32 length, UINT32 spiAddr )
{
	UINT16 quitLoop = 0;
	UINT32 itr;

	printf("Flash erase offset = %d , length = %d \n",offset, length);
	if (offset % SPIFLASH_SECTORSIZE || length % SPIFLASH_SECTORSIZE) {
		printf("SF: Erase offset/length not multiple of sector size\n");
		return 0xFF;
	}
	length /= SPIFLASH_SECTORSIZE;
    /* Issue WPEN */
	for (itr = 0; itr < length; itr++)
	{
		//printf("Erasing sector @ %d \n",offset);
		if((spiFlashStatus( spiAddr )& FLASH_WEL_STATUS) != FLASH_WEL_STATUS)
		{
			spiFlashTxBuf[0] = SPIFLASH_CMD_WREN;
			SPIWrite(spiAddr, spiFlashTxBuf, SPI_WPEN_LEN, SPI_FLASH_CH);
			while(( spiFlashStatus( spiAddr ) & FLASH_WEL_STATUS ) != FLASH_WEL_STATUS )
			{
				quitLoop = quitLoop + 1;
				if(quitLoop > 200)
					break;
			}
		}

		/* Issue Erase */
		spiFlashTxBuf[0] = SPIFLASH_CMD_SCTR_ERASE;//SPIFLASH_CMD_ERASE;
		spiFlashTxBuf[1] = ( UINT8 )( offset >> SHIFT_24BIT);
		spiFlashTxBuf[2] = ( UINT8 )( offset >> SHIFT_WORD );
		spiFlashTxBuf[3] = ( UINT8 )( offset >> SHIFT_BYTE );
		spiFlashTxBuf[4] = ( UINT8 )( offset );
		SPIWrite(spiAddr, spiFlashTxBuf, SPI_ERASE_LEN, SPI_FLASH_CH);

		while( ( spiFlashStatus( spiAddr) & FLASH_STATUS ) );

	#ifdef VERIFY_SECTOR_ERASE
		verifyErasedSector(offset,spiAddr);
	#endif

		offset += SPIFLASH_SECTORSIZE;
	}
	return 0;
}


void SPI_FlashWrite( UINT32 src, UINT32 dst, UINT32 length, UINT32 spiAddr )
{
    INT32 i;
    INT32 bytesLeft;
    INT32 bytesToProgram;
    UINT8 *psrc;
    UINT16 quitLoop;
    volatile int loop;

    /* Establish source */
    psrc = ( UINT8 * )src;
    bytesLeft = length;

    while ( bytesLeft > 0 )
    {
    	bytesToProgram = bytesLeft;

        /* Most to program is SPIFLASH_CMD_BLOCKSIZE */
        if ( bytesToProgram > SPIFLASH_PAGESIZE )
             bytesToProgram = SPIFLASH_PAGESIZE;

        /* Make sure you don't run off the end of a block */
        if ( ( dst & SPIFLASH_PAGEMASK ) != ( ( dst + bytesToProgram )
            & SPIFLASH_PAGEMASK ) )

            bytesToProgram -= ( dst + bytesToProgram ) -
                ( ( dst + bytesToProgram ) & SPIFLASH_PAGEMASK );

        /* Issue WPEN */
        quitLoop = 0;
        if((spiFlashStatus( spiAddr)& FLASH_WEL_STATUS) != FLASH_WEL_STATUS)
        {
            spiFlashTxBuf[0] = SPIFLASH_CMD_WREN;
            SPIWrite(spiAddr, spiFlashTxBuf, SPI_WPEN_LEN, SPI_FLASH_CH);

            while( ( spiFlashStatus( spiAddr) & FLASH_WEL_STATUS ) != FLASH_WEL_STATUS)
            {
				 quitLoop = quitLoop + 1;
				 if(quitLoop > 200)
					 break;
            }
        }

        /* Create command block for program operation */
        spiFlashTxBuf[0] = SPIFLASH_CMD_WRITE;
        spiFlashTxBuf[1] = ( UINT8 )( dst >> SHIFT_24BIT);
        spiFlashTxBuf[2] = ( UINT8 )( dst >> SHIFT_WORD );
        spiFlashTxBuf[3] = ( UINT8 )( dst >> SHIFT_BYTE );
        spiFlashTxBuf[4] = ( UINT8 )( dst );
        forLoop();

        for ( i = 0 ; i < bytesToProgram ; i++ )
            spiFlashTxBuf[5+i] = *psrc++;


        /* Execute write command */
	    SPIWrite(spiAddr, spiFlashTxBuf, bytesToProgram + 5, SPI_FLASH_CH);
        /* Wait while busy */
        //while( ( spiFlashStatus( spiAddr) & FLASH_STATUS ) );

        /* Get ready for next iteration */
        bytesLeft -= bytesToProgram;
        dst += bytesToProgram;
    }
}


#ifndef _FLASHSPI_H_
#define _FLASHSPI_H_
#include "userType.h"

#define SPIFLASH_PAGESIZE         256    //  一个页大小
#define SPIFLASH_SECTORSIZE       4096   //  扇区大小
#define FPGA_SIZE   64*1024*1024

#define SPI_0  0
#define SPI_1  1
#define MCSPI0_BASE_ADDR  SOC_SPI_0_REGS
#define MCSPI1_BASE_ADDR  SOC_SPI_1_REGS
#define TX_EMPTY_FLAG	  0x02
#define RX_FULL_FLAG	  0x01

//  READLEN
#define SPI_WPEN_LEN	  1
#define SPI_STATUS_LEN	  2
#define SPI_ERASE_LEN	  5
#define MFID_DEVID_LEN	  8
#define	SHIFT_BYTE		  8
#define	SHIFT_WORD		  16
#define SHIFT_24BIT       24

#define SPIFLASH_MANUF_ID	  0xEF

#define SPI_FLASH_CH 0

#define SPIFLASH_PAGEMASK         0xffffffc0

//  CMD

#define SPIFLASH_CMD_WREN         0x06
#define SPIFLASH_CMD_READ         0x03
#define SPIFLASH_CMD_WRDI         0x04
#define SPIFLASH_CMD_RDSR         0x05
#define SPIFLASH_CMD_WRITE        0x12
#define SPIFLASH_CMD_READPAGE     0x13
#define SPIFLASH_CMD_READID		  0x9E
#define SPIFLASH_CMD_ERASE		  0xD8
#define SPIFLASH_CMD_SCTR_ERASE	  0x20
#define CMD_ENTER_4_BYTE          0xb7

#define FLASH_STATUS		    0x01
#define FLASH_WEL_STATUS		0x02

UINT32 SPIInit(INT32 spiId, UINT8 spiClockDiv, UINT8 spiDir);

void SPICycle( UINT32 spiAddr, UINT8 *buf, UINT16 len, UINT16 chNum);

void SPIRead( UINT32 spiAddr, UINT8 *buf, UINT16 len, UINT16 chNum);

void SPIWrite( UINT32 spiAddr, UINT8 *buf, UINT16 len, UINT16 chNum);

INT32 SPI_FlashReadID (UINT32 spiAddr);

UINT8 SPI_FlashErase(UINT32 offset, UINT32 length, UINT32 spiAddr );

void SPI_FlashRead( UINT32 src, UINT32 *dst, UINT32 length, UINT32 spiAddr );

void SPI_FlashWrite( UINT32 src, UINT32 dst, UINT32 length, UINT32 spiAddr );

void forLoop();

void setFlash4Byte(UINT32 spiAddr);

UINT8 spiFlashStatus( UINT32 spiAddr);
#endif
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值