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, ®s[1]); // read CR1
alt_qspi_read_register(0x05, ®s[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