Writing to flash memory QSPI from Xilinx FPGA

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Aida
Level 1
Level 1
First solution authored First reply posted First question asked

Hi!

I am using an example program from Xilinx to access the S25FL256SAGBHI20 flash memory and write some data at location 0xEA6000. For this, I have created an FPGA design with a Microblaze and the AXI SPI IP core. I am attaching the C code for the Microblaze that controls the flash memory access but here is the short version:

The XSpi_Transfer function accesses the flash registers over the AXI QSPI IP core.

#define INTEL_COMMAND_RANDOM_READ 0x03 /* Random read command */
#define INTEL_COMMAND_PAGEPROGRAM_WRITE 0x02 /* Page Program command */
#define INTEL_COMMAND_WRITE_ENABLE 0x06 /* Write Enable command */
#define INTEL_COMMAND_SECTOR_ERASE 0xD8 /* Sector Erase command */
#define INTEL_COMMAND_BULK_ERASE 0xC7 /* Bulk Erase command */
#define INTEL_COMMAND_STATUSREG_READ 0x05 /* Status read command */
#define INTEL_COMMAND_STATUSREG_WRITE 0x01 /* Status write command */

#define INTEL_READ_WRITE_EXTRA_BYTES 4 /* Read/Write extra bytes */
#define INTEL_WRITE_ENABLE_BYTES 1 /* Write Enable bytes */
#define INTEL_SECTOR_ERASE_BYTES 4 /* Sector erase extra bytes */
#define INTEL_BULK_ERASE_BYTES 1 /* Bulk erase extra bytes */
#define INTEL_STATUS_READ_BYTES 2 /* Status read bytes count */
#define INTEL_STATUS_WRITE_BYTES 2 /* Status write bytes count */

#define INTEL_FLASH_SR_IS_READY_MASK 0x01 /* Ready mask */
#define INTEL_DISABLE_PROTECTION_ALL 0x00
#define INTEL_FLASH_PAGE_SIZE 256

// Write enable
XSpi_Transfer(SpiPtr, INTEL_COMMAND_WRITE_ENABLE, NULL,
INTEL_WRITE_ENABLE_BYTES);

//Check if flash busy
XSpi_Transfer(SpiPtr, INTEL_COMMAND_STATUSREG_READ, ReadBuffer,
INTEL_STATUS_READ_BYTES);
StatusReg = ReadBuffer[1];
if((StatusReg & INTEL_FLASH_SR_IS_READY_MASK) == 0) {
break;
}

// Disable protection
WriteBuffer[BYTE1] = INTEL_COMMAND_STATUSREG_WRITE;
WriteBuffer[BYTE2] = INTEL_DISABLE_PROTECTION_ALL;

XSpi_Transfer(SpiPtr, WriteBuffer, NULL,
INTEL_STATUS_WRITE_BYTES);

// Write data to flash memory define in "Address"
WriteBuffer[BYTE1] = INTEL_COMMAND_PAGEPROGRAM_WRITE;
WriteBuffer[BYTE2] = (u8) ((Address+INTEL_FLASH_PAGE_SIZE) >> 16);
WriteBuffer[BYTE3] = (u8) ((Address+INTEL_FLASH_PAGE_SIZE) >> 8);
WriteBuffer[BYTE4] = (u8) (Address+INTEL_FLASH_PAGE_SIZE);

XSpi_Transfer(SpiPtr, WriteBuffer, NULL,
(INTEL_FLASH_PAGE_SIZE + INTEL_READ_WRITE_EXTRA_BYTES));

 

The writing of data works, because I can also read it back after power cycling the FPGA, the problem is just, that my FPGA design doesn’t boot any more. I have to program it new, every single time I power cycle it. I flash the FPGA file starting from memory 0x0 so the two memory regions should not overlap.

Any suggestion as why this doesnt work will be very welcome!

KR,

Aida

 

0 Likes
1 Solution
Aida
Level 1
Level 1
First solution authored First reply posted First question asked

Hi Ronak!

 

So I tried leaving the protection in and noticed that the FPGA was booting properly, however, even though I could read data from the flash, it wasn’t the data I have written (so the write operation probably failed with the protection enabled)

 

So I tried the following which actually worked!

 

  1. Enabling extended address range:

Since the example program has a 3-byte addressing but my flash memory goes to 256 MB I can use the upper memory region by writing my address to the Bank Register Write (BRWR). So even if my address is 0x0, as far as I understood, the program will take it as memory location 0x100 0000.

 

  1. Protect the lower memory region, where I suspected the FPGA boot image would be programmed:
  • Writing Status Register (SR1) bits BP2 – BP0 for block protection of half the memory range (1,1,0)
  • Setting Configuration Register (CR1) bit TBPROT to 1, so that the block protection refers to the lower memory region

 

So thanks a lot for your reply!

View solution in original post

0 Likes
2 Replies
Ronak
Moderator
Moderator
Moderator
50 solutions authored 250 sign-ins 50 replies posted

Hi Aida,

Can you please check the following point:

1) Can you test the system without the protection part of the code? Does the problem remain after removing the disable protection part of the code?

2) Can you please let me know which SPI mode are you using in your application for the program and reading the data, Is it QSPI or SPI?

3) In which mode does the FPGS read and boot from the Flash?

4) When you are using the QSPI mode. The QUAD bit CR[1] is set to 1. When performing the Write Register (WRR 01h) the QUAD bit gets reset. Thus when you are disabling the protection you must then set the bits again. Otherwise, the QSPI won't work.

Also, please share the value of both Status registers and configuration register values before and after you perform point 1.

Thanks & Regards,

Ronak

Aida
Level 1
Level 1
First solution authored First reply posted First question asked

Hi Ronak!

 

So I tried leaving the protection in and noticed that the FPGA was booting properly, however, even though I could read data from the flash, it wasn’t the data I have written (so the write operation probably failed with the protection enabled)

 

So I tried the following which actually worked!

 

  1. Enabling extended address range:

Since the example program has a 3-byte addressing but my flash memory goes to 256 MB I can use the upper memory region by writing my address to the Bank Register Write (BRWR). So even if my address is 0x0, as far as I understood, the program will take it as memory location 0x100 0000.

 

  1. Protect the lower memory region, where I suspected the FPGA boot image would be programmed:
  • Writing Status Register (SR1) bits BP2 – BP0 for block protection of half the memory range (1,1,0)
  • Setting Configuration Register (CR1) bit TBPROT to 1, so that the block protection refers to the lower memory region

 

So thanks a lot for your reply!

0 Likes