Skip to content

QSPI on SSI hardware doesn't work for any frame format except standard #1100

Open
@khill25

Description

@khill25

I have PSRAM (part APS6404L-3SQR QSPI PSRAM) chips connected to the QSPI pins on a custom board with two RP2040s. A w25q128jv 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:

0400800f 20343674 58804000 00b4af00 
a40c3cf0 000000fd ff2016ff 0089ad0f 
70000025 90000000 00111601 002eae00 
0089ad00 b0083c00 b0c80220 20082420 

Expected output:

40123780 0f000000 00040080 44140000 
648f45d7 5fb34552 00000000 00000000 
6f636950 74726143 54203436 20747365
004d4f52 00000000 00000000 00000000

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.

ssi_hw->ssienr = 0;
// Clear sticky errors (clear-on-read)
(void)ssi_hw->sr;
(void)ssi_hw->icr;

// ssi->baudr = 2;
// ssi->baudr = 6;
ssi->baudr = 4;

ssi_hw->ctrlr0 = ((SSI_CTRLR0_SPI_FRF_VALUE_QUAD << 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)

/*
FROM THE BOOT LOADER ASSEMBLY
// Note that the INST_L field is used to select what XIP data gets pushed into
// the TX FIFO:
//      INST_L_0_BITS   {ADDR[23:0],XIP_CMD[7:0]}       Load "mode bits" into XIP_CMD
//      Anything else   {XIP_CMD[7:0],ADDR[23:0]}       Load SPI command into XIP_CMD
// So in this case SSI_SPI_CTRLR0_ADDR_L_LSB should be 8 = (8 bit command + 24 bit address)/4
*/

// 4 wait cycles for "fast read" 0x0B when in quad mode
// 8 wait cycles for "fast read" 0x0B when in spi mode / quad read
// 6 wait cycles for "fast read quad" 0xEB when in quad mode
ssi_hw->spi_ctrlr0 = ((0xEB << SSI_SPI_CTRLR0_XIP_CMD_LSB) |	//
					 (6 << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) |	/* Hi-Z dummy clocks following address + mode */
					 (8 << SSI_SPI_CTRLR0_ADDR_L_LSB) |	/* Total number of address + mode bits, not using mode
					 (SSI_SPI_CTRLR0_INST_L_VALUE_8B << SSI_SPI_CTRLR0_INST_L_LSB) |	/* Instruction is 8 bits  */
					 (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A << SSI_SPI_CTRLR0_TRANS_TYPE_LSB)	/* Command in standard spi and address both in FRF specified format */
);

// Slave selected when transfers in progress
ssi_hw->ser = 1;
// Re-enable
ssi_hw->ssienr = 1;

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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions