Hi,
I am currently working on interfacing the QSPI Flash AT25FF321A with the R7FA4M3AF3CFP MCU. While everything functions correctly in extended SPI mode, I am encountering issues in QPI mode.
I have attached the schematic snapshots and relevant code sections to assist in debugging this issue. Please note that I have utilized a mixed pin group for the QSPI configuration. Despite my efforts, I am unable to read even Manufacturer/Device ID in QPI mode. I am including the firmware section related to this issue.
I would greatly appreciate your assistance in resolving this matter.
Code :
void qspi_test(){ // Initialize QSPI configuration and open the QSPI interface spi_flash_cfg_t l_qspi_cfg; memcpy((spi_flash_cfg_t *)&l_qspi_cfg, (spi_flash_cfg_t *)&g_qspi0_cfg, sizeof(spi_flash_cfg_t)); l_qspi_cfg.spi_protocol = SPI_FLASH_PROTOCOL_QPI; l_qspi_cfg.page_program_address_lines = SPI_FLASH_DATA_LINES_4; l_qspi_cfg.page_program_command = 0x32; R_QSPI_Open(&g_qspi0_ctrl, &l_qspi_cfg);
fsp_err_t err; uint8_t command[8]; uint8_t read_data[2]; uint8_t status[2]; uint8_t manufacturer_id = 0; uint8_t device_id = 0; uint8_t data[3]; // Adjusted size to fit commands and data
// Step 1: Enable Quad Mode (Set QE bit in Status Register 2) // Write Enable before writing to the status register data[0] = 0x06; // Write Enable command err = R_QSPI_DirectWrite(&g_qspi0_ctrl, data, 1, false); if (err != FSP_SUCCESS) { return; } R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS); // Short delay after Write Enable
// Read the current Status Register 2 data[0] = 0x35; // Read Status Register 2 command err = R_QSPI_DirectWrite(&g_qspi0_ctrl, data, 1, true); if (err != FSP_SUCCESS) { return; } err = R_QSPI_DirectRead(&g_qspi0_ctrl, status, 2); if (err != FSP_SUCCESS) { return; }
// Set the QE bit in Status Register 2 status[1] |= 0x02; // Set QE bit
// Write Enable again before writing the updated status register data[0] = 0x06; // Write Enable command err = R_QSPI_DirectWrite(&g_qspi0_ctrl, data, 1, false); if (err != FSP_SUCCESS) { return; } R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS); // Short delay after Write Enable
// Write the updated status register (SR1 and SR2) data[0] = 0x01; // Write Status Register command data[1] = status[0]; // Status Register 1 (unchanged) data[2] = status[1]; // Status Register 2 (QE bit set) err = R_QSPI_DirectWrite(&g_qspi0_ctrl, data, 3, true); if (err != FSP_SUCCESS) { return; } R_BSP_SoftwareDelay(1000, BSP_DELAY_UNITS_MILLISECONDS); // Increased delay for status register write
// Poll the status register to wait for write completion do { data[0] = 0x05; // Read Status Register command err = R_QSPI_DirectWrite(&g_qspi0_ctrl, data, 1, true); if (err != FSP_SUCCESS) { return; } err = R_QSPI_DirectRead(&g_qspi0_ctrl, status, 1); if (err != FSP_SUCCESS) { return; } } while (status[0] & 0x01); // Wait while the device is busy
// Step 3: Prepare the command sequence for Quad I/O Read Manufacturer/Device ID command[0] = 0x94; // Command for Quad I/O Read Manufacturer/Device ID command[1] = 0x00; // Dummy address byte 1 command[2] = 0x00; // Dummy address byte 2 command[3] = 0x00; // Dummy address byte 3 command[4] = 0x00; // Mode byte (ignored, 2 clocks) command[5] = 0x00; // Dummy byte (4 clocks)
// Step 4: Send the command sequence using 1-bit for command and 4-bit for address/data err = R_QSPI_DirectWrite(&g_qspi0_ctrl, command, 6, true); if (err != FSP_SUCCESS) { return; }
// Short delay to ensure command is processed R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS);
// Step 5: Read Manufacturer ID and Device ID (2 bytes) in Quad I/O mode err = R_QSPI_DirectRead(&g_qspi0_ctrl, read_data, 2); if (err != FSP_SUCCESS) { return; }
// Step 6: Retrieve Manufacturer and Device ID from read data manufacturer_id = read_data[0]; device_id = read_data[1]; R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS);
}
Schematic Snap:
FSP Configurator Snaps:
Thanks,
Parth
Can you pullup all lines. Here EK-RA6M3 schematics.
Thanks for going through my query.
Tried with pull-ups, still facing same issue.
Regards,
The AT25FF321A only supports receiving commands on a single pin :-
The SI (or IO0) pin.
You can't use Quad SPI protocol to communicate with the AT25FF321A, as in Quad SPI protocol the commands are sent on all 4 QIO pins.
You will have to use Extended SPI mode :-
Could you please help me to modify the below code to write and read back few bytes using the quad write (32h) command? I've tried everything, but I haven't had any success so far.
Code -
void qspi_test(){ uint8_t data[10]; uint8_t id_data[2]; uint8_t status[2]; // Buffer for status registers uint32_t timeout_ms; uint32_t elapsed_time; uint32_t polling_interval; uint8_t command[10]; spi_flash_cfg_t qspi_cfg; uint32_t device_size_bytes;
// Copy and modify QSPI configuration memcpy((spi_flash_cfg_t *)&qspi_cfg, (spi_flash_cfg_t *)&g_qspi0_cfg, sizeof(spi_flash_cfg_t)); qspi_cfg.spi_protocol = SPI_FLASH_PROTOCOL_EXTENDED_SPI; qspi_cfg.page_program_command = 0x32; R_QSPI_Open(&g_qspi0_ctrl, &qspi_cfg);
// Step 1: Check and set Quad Enable (QE) bit if not set uint8_t cmd_read_status[1] = {0x35}; // Read Status Register 2 command R_QSPI_DirectWrite(&g_qspi0_ctrl, cmd_read_status, 1, true); R_QSPI_DirectRead(&g_qspi0_ctrl, status, 1);
if (!(status[0] & 0x02)) // Check if QE bit is set { // QE bit not set, set it explicitly uint8_t cmd_write_enable[1] = {0x06}; // Write Enable command uint8_t cmd_write_status[2] = {0x31, 0x02}; // Write Status Register 2 command, setting QE bit
R_QSPI_DirectWrite(&g_qspi0_ctrl, cmd_write_enable, 1, false); R_BSP_SoftwareDelay(2, BSP_DELAY_UNITS_MILLISECONDS);
R_QSPI_DirectWrite(&g_qspi0_ctrl, cmd_write_status, 2, false); R_BSP_SoftwareDelay(2, BSP_DELAY_UNITS_MILLISECONDS);
// Poll the status register to wait for write completion do { data[0] = 0x35; // Read Status Register command R_QSPI_DirectWrite(&g_qspi0_ctrl, data, 1, true); R_QSPI_DirectRead(&g_qspi0_ctrl, status, 1); } while (status[0] & 0x02); // Wait while the device is busy }
// enter into extended SPI mode R_QSPI_SpiProtocolSet(&g_qspi0_ctrl, SPI_FLASH_PROTOCOL_EXTENDED_SPI); R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS);
// Step 2 : Erase the sector/block err2 = R_QSPI_Erase(&g_qspi0_ctrl, 0, 4096); R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS);
// Step 3 : write bytes address = 0; data[0] = 0x67; data[1] = 0x85; R_QSPI_Write(&g_qspi0_ctrl, data, (uint8_t *)QSPI_FLASH_ADDRESS(PAGE_FIRST), 1);
// Poll the status register to wait for write completion do { data[0] = 0x05; // Read Status Register command R_QSPI_DirectWrite(&g_qspi0_ctrl, data, 1, true); R_QSPI_DirectRead(&g_qspi0_ctrl, status, 1); } while (status[0] & 0x01); // Wait while the device is busy
// Step 4 : Read-back memcpy(read_data, (uint8_t *)QSPI_FLASH_ADDRESS(PAGE_FIRST), 25); R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS);
Thanks,Parth