Forum Discussion

miscellaneous-mice's avatar
miscellaneous-mice
Icon for New Contributor rankNew Contributor
14 hours ago

Reading S25FL256S OTP region via QSPI Indirect Transfer on Cyclone V HPS — data comes back incorrect

What I'm trying to do

I need to read OTP memory region of the S25FL256S flash using command 0x4B. The system normally runs in quad-SPI mode (0xEC, 4-byte address). Since the data I need is more than 8 bytes (STIG limit), I'm trying to use the indirect transfer path.

The 0x4B command requires:

  • Single-SPI (1-wire address and data)
  • 3-byte address
  • 1 fixed dummy byte (8 clocks) after address

Setup

The QSPI controller is initialized at startup using the standard Altera HAL:

alt_qspi_init(); // detects flash JEDEC ID, configures timing, sets up qspi_config struct
alt_qspi_enable(); // enables controller, sets quad mode (0xEC, 4-byte addr, LC=10b)

After this, normal quad-SPI reads via alt_qspi_read() works correctly.

What I'm doing

Reconfigure controller for 0x4B (OTP Read)

ALT_QSPI_DEV_INST_CONFIG_t read_cfg = {
        .op_code = 0x4B,
       .inst_type = ALT_QSPI_MODE_SINGLE,
       .addr_xfer_type = ALT_QSPI_MODE_SINGLE,
       .data_xfer_type = ALT_QSPI_MODE_SINGLE,
       .dummy_cycles = 8
};

alt_qspi_device_read_config_set(&read_cfg);

ALT_QSPI_DEV_SIZE_CONFIG_t size_cfg = {
       ...
       .addr_size = 2, // N+1 encoding → 3 bytes on wire
       .page_size = 256,
       ...
};

alt_qspi_device_size_config_set(&size_cfg);

Disable QUAD on the flash device itself via STIG

alt_qspi_read_register(0x35, &regs[1]); // read CR1
alt_qspi_read_register(0x05, &regs[0]); // read SR1
alt_qspi_device_wren();
regs[1] = (regs[1] & 0x3D) | 0x00 | 0x80; // QUAD=0, LC=10b
alt_qspi_stig_wr_cmd(0x01, 0, 2, (uint32_t*)regs, timeout);
alt_qspi_sr_wait_write(timeout);

Execute indirect read

// Internally: sets INDRDSTADDR, INDRDCNT, starts transfer,
// then CPU drains SRAM FIFO via ALT_QSPIDATA_ADDR
alt_qspi_read(dst, src, size);

Problem

The data returned by the indirect read is incorrect. A STIG-based read of the same region (using the same 0x4B command, 8 bytes at a time) returns the correct data. The indirect read returns wrong/shifted bytes. Hence do I need to configure anything else?

Result

correct value : 97C5995C5C1E9D5D7A00D4E6BD4ED53E
read value : FF97C5995C5C1E9D5D7A00D4E6BD4ED5

No RepliesBe the first to reply