Open khill25 opened 1 year ago
A difference between W25Q128JV (at least IQ option as used by Pico boards) and APS6404L-3SQR is that Quad Mode is enabled by default for the former and disabled by default for APS6404L-3SQR. To enable Quad Mode for APS6404L-3SQR, need to send it command 'h35 while its in SPI mode. I don't see that in your code snippet. It's probably just elsewhere in your code but thought I would check.
The PSRAM has two modes, SPI and QPI. 0x0B Fast read
and 0xEB Fast read quad
are supported in both formats.
In SPI Column version (no need to issue the 0x35 command) 0x0B sends serial command, sends serial address (has 8 wait cycles) then gets serial data 0xEB sends serial command, sends quad address (has 6 wait cycles) then gets quad data.
The SSI_SPI_CTRLR0_TRANS_TYPE_LSB
states
0x0 -> Command and address both in standard SPI frame format
0x1 -> Command in standard SPI format, address in format specified by FRF
0x2 -> Command and address both in format specified by FRF (e.g. Dual-SPI)
So in my example config above where I am trying to use fast read quad in spi mode, wants a serial command, quad address and then quad data as SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A = 0x1
no need to enter QPI mode.
I have also tried entering QPI mode (sending 0x35) command before setting up the SSI hardware and setting trans type to 0x2 but had no change.
From my testing it seems that SSI_SPI_CTRLR0_WAIT_CYCLES_LSB only has an effect when not in SSI_CTRLR0_SPI_FRF_VALUE_STD mode. SSI_SPI_CTRLR0_ADDR_L_LSB also seems to behave the same way.
This configuration almost works.
ssi->ssienr = 0;
// Clear sticky errors (clear-on-read)
(void)ssi_hw->sr;
(void)ssi_hw->icr;
ssi_hw->baudr = 2;
ssi_hw->ctrlr0 = ((SSI_CTRLR0_SPI_FRF_VALUE_STD << SSI_CTRLR0_SPI_FRF_LSB) |
(31 << SSI_CTRLR0_DFS_32_LSB) |
(SSI_CTRLR0_TMOD_VALUE_EEPROM_READ << SSI_CTRLR0_TMOD_LSB)
);
ssi_hw->ctrlr1 = 0; // NDF=0 (single 32b read)
ssi_hw->spi_ctrlr0 = ((0x0B << SSI_SPI_CTRLR0_XIP_CMD_LSB) |
(8 << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) |
(SSI_SPI_CTRLR0_INST_L_VALUE_8B << SSI_SPI_CTRLR0_INST_L_LSB) | /* */
(8 << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */
(SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C1A << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) /* Send Address in Quad I/O mode (and Command but that is zero bits long) */
);
ssi_hw->ssienr = 1;
But the data seems to be dropping data. Lowering baud for this setup from 4 to 2, sees the data return which to me says it's not honoring the (8) wait cycles since the first 2 values of each 32bit value are gone. GOT:
12378000 00000000 04008000 14000000 8f45d700 b3455200
EXPECTED:
40123780 0f000000 00040080 44140000 648f45d7 5fb34552
Hello. It is by sheer coincidence that I came across this issue, as I'm also interested in using PSRAM as well as NOR flash on the XIP peripheral of the RP2040. Would you be able to link your schematic and source code for me to inspect please?
The PSRAM chips work with more or less the same commands as the flash chips but don't have a "continuation mode".
The PSRAM seems to have a continuation mode named "Linear Burst", which is its default mode of operation (Boundary Crossing is also default). This mode has a lower maximum frequency of 84MHz.
It's my understanding that the RP2040 and the PSRAM will only support "SPI" and "SPI Quad" communication with eachother, as the RP2040 does not support QPI, and the PSRAM does not support "DDR Mode" (RP2040 datasheet: 4.10.10.5. Dual Data-Rate (DDR) Support in SPI Operation). So make sure that the PSRAM is not placed in QPI mode.
I was able to get this working but several things had to be done. The PSRAM will only work in quad mode as the hardware doesn't respect serial address, quad data. When using quad mode, you must configure the hardware for standard mode (03h) and send the enter quad mode command, then you can configure the qspi hardware for quad mode.
It's sadly not as fast as flash memory though since psram doesn't support the magical continuation mode that saves addresses bits for sequential reads.
You can checkout this commit c0bb956c026dfd070aa7d3031aa75c773880ee09
from my repo https://github.com/khill25/PicoCart64. In qpi_helper.c
function void qspi_init_qspi(void)
is where I configure the qspi hardware for the psram. Also keep in mind you want to use the CS pin connected to the qspi hadware.
Originally I was toggling it manually but rewired my hardware to use the CS pin to toggle my demux. Then all I had to do was set the address and use the CS as enable with the demux output connected to the CS pins of the chips.
It's great that you got it working!
I misunderstood the "Linear Burst (continuous)" mode mentioned in the PSRAM datasheet, which is just reading sequential data. Whereas the "continuous read mode" in the W25Q NOR datasheet means that you don't need to issue the Fast Quad Read command even after the CS pin has toggled and can just enter a new address immediately. This removes the overhead of issuing the instruction (8 clock cycles), but instead send a mode byte after the address in quad mode (only 2 clock cyles).
It looks like you're using the SPI Fast Read command 0x0B
at https://github.com/khill25/PicoCart64/blob/c0bb956c026dfd070aa7d3031aa75c773880ee09/sw/picocart64_v2/qspi_helper.c#L372 . How come you aren't using the SPI Fast Quad Read 0xEB
command instead?
I have PSRAM (part
APS6404L-3SQR QSPI PSRAM
) chips connected to the QSPI pins on a custom board with two RP2040s. Aw25q128jv
flash chip is also present. With the binary set to copy to ram on startup, reading and writing to the PSRAM array works fine as long as I'm not trying to configure the SSI hardware for quad spi. The PSRAM chips work with more or less the same commands as the flash chips but don't have a "continuation mode". Chip select is handled manually with a few gpio acting as a mux.I wrote some code to try 288 permutations of frame format, wait cycle, trans type, and xip/read cmds.
There were a few permutations that had data that looked like it was reading actual data I loaded on the PSRAM chip but seemed to be bit shifted or out of phase. This is the output of one of the "close" attempts.
Configuration for ssi hardware of a "close" attempt:
cmd:eb, frf:02, trans_type:01, dfs:31, waitCycles: 4, baudDivider:2
"close" Output:
Expected output:
Below is the code that should work to setup quad spi reads in
Fast Read Quad
mode for the PSRAM chips. Not using a continuation bit so will just issue the XIP command everytime. I left in the note I wrote based on the bootloader assembly that setup the flash chips.I have spent weeks playing with this and simply cannot get it working. My code is open source and available on demand (albeit very messy due to all my hair tearing). The data loads are simply too slow with standard read commands for my project. Theoretically this should all just work, as it does if you make your reads from the flash chip.