赞
踩
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。