读取设备ID 厂家ID和读写状态寄存器代码段
TW8825_WritePage(TW8825_PAGE4_SPI); SpiFlashDmaDestType(DMA_DEST_CHIPREG, 0);
SpiFlashDmaBuffAddr(DMA_BUFF_REG_ADDR);
SpiFlashDmaReadLen(0); /*Clear high & middle bytes*/
SpiFlashCmd(FLASH_CMD_RDID, 1); SpiFlashDmaReadLenByte(3);
SpiFlashDmaStart(SPIDMA_READ, 0, __LINE__);
ManufacturerID = TW8825_Read(REG4D0);
MemoryType = TW8825_Read(REG4D1);
MemoryDensity = TW8825_Read(REG4D2);
printf("\r\nSPI Flash JEDEC ID : 0x%bx, 0x%bx, 0x%bx", ManufacturerID, MemoryType, MemoryDensity);
/*Read Status Register*/
if(
ManufacturerID == 0x1C || /*EON*/
ManufacturerID == 0x9D || /*ISSI*/
ManufacturerID == 0xC2 /*MX*/
)
{
SpiFlashCmd(FLASH_CMD_RDSR, 1);
SpiFlashDmaReadLenByte(1);
SpiFlashDmaStart(SPIDMA_READ, 0, __LINE__);
value = TW8825_Read(REG4D0) & 0x40;
}
写状态寄存器值
/* Enable Quad IO Mode */
if(
ManufacturerID == 0x1C || /*EON*/
ManufacturerID == 0x9D || /*ISSI*/
ManufacturerID == 0xC2 /*MX*/
)
{
SpiFlashCmd(FLASH_CMD_WREN, 1);
SpiFlashDmaReadLenByte(0);
SpiFlashDmaStart(SPIDMA_WRITE, 0, __LINE__);
SpiFlashCmd2(FLASH_CMD_WRSR, 0x40); /*Enable QAUD Mode*/
SpiFlashDmaReadLenByte(0);
SpiFlashDmaStart(SPIDMA_WRITE, 1, __LINE__);
SpiFlashCmd(FLASH_CMD_WRDI, 1);
SpiFlashDmaReadLenByte(0);
SpiFlashDmaStart(SPIDMA_WRITE, 0, __LINE__);
}
else if(ManufacturerID == 0xEF) /*WB*/
{
SpiFlashCmd(FLASH_CMD_WREN, 1);
SpiFlashDmaReadLenByte(0);
SpiFlashDmaStart(SPIDMA_WRITE, 0, __LINE__);
SpiFlashCmd3(FLASH_CMD_WRSR, 0x00, 0x02); /*Enable QAUD Mode*/
SpiFlashDmaReadLenByte(0);
SpiFlashDmaStart(SPIDMA_WRITE, 1, __LINE__);
SpiFlashCmd(FLASH_CMD_WRDI, 1);
SpiFlashDmaReadLenByte(0);
SpiFlashDmaStart(SPIDMA_WRITE, 0, __LINE__);
}
此上代码段位于spi-flash初始化部分。
下面设置读模式,实验证明需设置为读或者快读时方可读出数据。
PI_SetReadMode(SPI_RD_MODE_SLOW);
read flash操作代码如下:
BYTE SpiFlashDmaStart1(BYTE dma_option)
{
BYTE i;
volatile BYTE vdata;
// DMA-start
TW8825_Write(REG4C4, 0x01 | dma_option);
//wait done flag
//REG4C4[0] is a self clear flag register.
for(i=0; i < 100; i++) {
vdata = TW8825_Read(REG4C4);
if((vdata & 0x01)==0)
break;
delay(2*10);
}
if(i==100) {
printf("\nSpiFlashDmaWait DMA Busy.");
return 2; //fail:busy
}
return 0;
}
void SpiFlashSetAddress2Hw(DWORD addr)
{
TW8825_Write(REG4CB, (BYTE)(addr >> 16));
TW8825_Write(REG4CC, (BYTE)(addr >> 8));
TW8825_Write(REG4CD, (BYTE)(addr));
}
void SpiFlashDmaRead2XMem(BYTE * dest_loc, DWORD src_loc, WORD size)
{
WORD dest_w_loc = (WORD)dest_loc;
BYTE dma_option;
TW8825_WritePage(TW8825_PAGE4_SPI);
TW8825_Write(REG4C3, (DMA_DEST_MCU_XMEM << 6) | 0x05);
TW8825_Write(REG4C6, (BYTE)(dest_w_loc>>8)); //page
TW8825_Write(REG4C7, (BYTE)(dest_w_loc)); //index
TW8825_Write(REG4C8, (BYTE)(size >> 8) ); // data Buff count middle
TW8825_Write(REG4C9, (BYTE)size ); // data Buff count Lo
TW8825_Write(REG4CA, 0x03 );
SpiFlashSetAddress2Hw(src_loc);
TW8825_Write(REG4DA, (BYTE)(size >> 16) ); // data Buff count high
//vblank wait
//if(vblank)
// WaitVBlank(vblank);
//dma option
dma_option = 0x04; //SPIDMA_BUSYCHECK
// DMA-start
SpiFlashDmaStart1(dma_option);
}
主函数里面对SpiFlashDmaRead2XMem()这个函数进行调用即可读出数据。
void SpiFlashDmaStart(BYTE fWrite, BYTE fBusy, WORD call_line)
{
BYTE dat = 0x01; /*Start*/
if(fWrite) dat |= 0x02; /*Write*/
if(fBusy) dat |= 0x04; /*Busy*/
TW8825_WritePage(TW8825_PAGE4_SPI);
TW8825_Write(REG4C4, dat);
SpiFlashDmaWait(200, 1, call_line);
}
BYTE SpiFlashChipRegCmd(BYTE cmd, BYTE w_len, BYTE r_len, BYTE vblank)
{
BYTE dma_option;
BYTE i;
volatile BYTE vdata;
TW8825_WritePage(TW8825_PAGE4_SPI);
TW8825_Write(REG4C3,(DMA_DEST_CHIPREG << 6) | (1+w_len));
TW8825_Write(REG4C6, DMA_BUFF_REG_ADDR_PAGE);
TW8825_Write(REG4C7, DMA_BUFF_REG_ADDR_INDEX);
TW8825_Write(REG4C8, 0x00 ); // data Buff count middle
TW8825_Write(REG4C9, r_len ); // data Buff count Lo
TW8825_Write(REG4CA, cmd );
for(i=0; i < w_len; i++)
TW8825_Write(REG4CB+i, SPI_CmdBuffer[i]);
TW8825_Write(REG4DA, 0x00 ); // data Buff count high
//vblank wait
if(vblank)
TW8825_WaitVBlank(vblank);
//dma option
dma_option = 0x00;
if(cmd==FLASH_CMD_PP
|| cmd==FLASH_CMD_SE
|| cmd==FLASH_CMD_BE
|| cmd==FLASH_CMD_BE_32K
|| cmd==FLASH_CMD_CE
)
dma_option |= 0x02; //DMA Buff Write Mode
if(cmd==FLASH_CMD_READ
|| cmd==FLASH_CMD_FAST_READ
|| cmd==FLASH_CMD_4READ
|| cmd==FLASH_CMD_WRSR
|| cmd==FLASH_CMD_SE
|| cmd==FLASH_CMD_BE
|| cmd==FLASH_CMD_BE_32K
|| cmd==FLASH_CMD_CE
)
dma_option |= 0x04; //BUSY CHECK
// DMA-start
TW8825_Write(REG4C4, 0x01 | dma_option);
//wait done
for(i=0; i < 200; i++) {
vdata = TW8825_Read(REG4C4);
if((vdata & 0x01)==0)
break;
delay(10 * 10);
}
if(i==200) {
printf("\nSpiFlashChipRegCmd Busy cmd:%bx",cmd);
return 2; //fail:busy
}
//read
for(i=0; i < r_len; i++)
SPI_CmdBuffer[i] = TW8825_Read(REG4D0+i);
printf("SPI_CmdBuffer\n");
return 0; //success
}
void SPI_PageProgram(WORD xaddr ,DWORD spiaddr, WORD cnt)
{
BYTE dma_option;
printf("tuning debug1********* %06lx\n",spiaddr);
SpiFlashChipRegCmd(FLASH_CMD_WREN,0,0,0);
TW8825_WritePage(TW8825_PAGE4_SPI);
TW8825_Write(REG4C3, (DMA_DEST_MCU_XMEM << 6) | 4);
TW8825_Write(REG4C6, (BYTE)(xaddr>>8)); //page
TW8825_Write(REG4C7, (BYTE)(xaddr)); //index
TW8825_Write(REG4C8, (BYTE)(cnt >> 8) ); // data Buff count middle
TW8825_Write(REG4C9, (BYTE)cnt ); // data Buff count Lo
TW8825_Write(REG4CA, FLASH_CMD_PP );
SpiFlashSetAddress2Hw(spiaddr);
TW8825_Write(REG4DA, (BYTE)(cnt >> 16) ); // data Buff count high
//vblank wait
//if(vblank)
// WaitVBlank(vblank);
//dma option
dma_option = 0x04; //SPIDMA_BUSYCHECK
dma_option |= 0x02; //SPIDMA_WRITE. BK121011. I think, we don't need it.
// DMA-start
SpiFlashDmaStart(dma_option);
printf("dma down\n");
}
void SPI_SectorErase( DWORD spiaddr )
{
SpiFlashChipRegCmd(FLASH_CMD_WREN,0,0,0);
SpiFlashSetAddress2CmdBuffer(spiaddr);
SpiFlashChipRegCmd(FLASH_CMD_SE,3,0,0);
}
void SpiFlashDmaWrite4XMem(BYTE * src_loc, DWORD dest_loc, WORD size)
{
SPI_SectorErase(dest_loc);
SPI_PageProgram(src_loc, dest_loc, size);
}
主函数里面对SpiFlashDmaWrite4XMem()这个函数进行调用即可向flash里面写数据了。
注意事项:写flash时必须先擦除块或者扇区。擦除或者写时必须先使能写。