MX25L1635D spi-flash芯片的读写记录

读取设备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时必须先擦除块或者扇区。擦除或者写时必须先使能写。

你可能感兴趣的:(单片机,spi-flash,tw8825)