7. QSPI Driver Example
This chapter contains the code of the GigaDevice GD25LQ128DSIG QSPI Flash Driver, the modifications to qspi_memory_config_table_internal.h as well as the modifications performed on the custom_config files and the XML configuration entry.
7.1. GigaDevice GD25LQ128DSIG Flash Driver header files
GigaDevice GD25LQ128DSIG Driver Header:
/**
* \addtogroup PLA_BSP_SYSTEM
* \{
* \addtogroup PLA_MEMORY
*
* \{
*/
/**
****************************************************************************************
*
* @file qspi_gigadevice_v2.h
*
* @brief The macros and functions of this header file are utilized by the memory drivers of the
* GigaDevice QSPI flash memories.
*
* Copyright (C) 2025 Renesas Electronics Corporation and/or its affiliates.
* All rights reserved. Confidential Information.
*
* This software ("Software") is supplied by Renesas Electronics Corporation and/or its
* affiliates ("Renesas"). Renesas grants you a personal, non-exclusive, non-transferable,
* revocable, non-sub-licensable right and license to use the Software, solely if used in
* or together with Renesas products. You may make copies of this Software, provided this
* copyright notice and disclaimer ("Notice") is included in all such copies. Renesas
* reserves the right to change or discontinue the Software at any time without notice.
*
* THE SOFTWARE IS PROVIDED "AS IS". RENESAS DISCLAIMS ALL WARRANTIES OF ANY KIND,
* WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. TO THE
* MAXIMUM EXTENT PERMITTED UNDER LAW, IN NO EVENT SHALL RENESAS BE LIABLE FOR ANY DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE, EVEN IF RENESAS HAS BEEN ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGES. USE OF THIS SOFTWARE MAY BE SUBJECT TO TERMS AND CONDITIONS CONTAINED IN
* AN ADDITIONAL AGREEMENT BETWEEN YOU AND RENESAS. IN CASE OF CONFLICT BETWEEN THE TERMS
* OF THIS NOTICE AND ANY SUCH ADDITIONAL LICENSE AGREEMENT, THE TERMS OF THE AGREEMENT
* SHALL TAKE PRECEDENCE. BY CONTINUING TO USE THIS SOFTWARE, YOU AGREE TO THE TERMS OF
* THIS NOTICE.IF YOU DO NOT AGREE TO THESE TERMS, YOU ARE NOT PERMITTED TO USE THIS
* SOFTWARE.
*
****************************************************************************************
*/
#ifndef _QSPI_GIGADEVICE_V2_H_
#define _QSPI_GIGADEVICE_V2_H_
#include "qspi_common.h"
#ifndef QSPI_GIGADEVICE_UNLOCK_PROTECTION
#define QSPI_GIGADEVICE_UNLOCK_PROTECTION (0)
#endif
#define QSPI_GIGADEVICE_MANUFACTURER_ID (0xC8)
#define QSPI_GIGADEVICE_GD25LQ128DSIG_TYPE (0x60)
#define QSPI_GIGADEVICE_READ_STATUS_REG2_OPCODE (0x35)
#define QSPI_GIGADEVICE_READ_STATUS_REG3_OPCODE (0x15)
#define QSPI_GIGADEVICE_SUSPEND_OPCODE (0x75)
#define QSPI_GIGADEVICE_RESUME_OPCODE (0x7A)
#define QSPI_GIGADEVICE_STATUS_REG_BP0_POS (2) // Block Protection Bit 0
#define QSPI_GIGADEVICE_STATUS_REG_BP1_POS (3) // Block Protection Bit 1
#define QSPI_GIGADEVICE_STATUS_REG_BP2_POS (4) // Block Protection Bit 2
#define QSPI_GIGADEVICE_STATUS_REG_BP3_POS (5) // Block Protection Bit 1
#define QSPI_GIGADEVICE_STATUS_REG_BP4_POS (6) // Block Protection Bit 2
#define QSPI_GIGADEVICE_STATUS_REG_SRP_POS (7) // Status Register Protection Bit 0
#define QSPI_GIGADEVICE_STATUS_REG_PROTECTION_MASK ((1 << QSPI_GIGADEVICE_STATUS_REG_BP0_POS) | \
(1 << QSPI_GIGADEVICE_STATUS_REG_BP1_POS) | \
(1 << QSPI_GIGADEVICE_STATUS_REG_BP2_POS) | \
(1 << QSPI_GIGADEVICE_STATUS_REG_BP3_POS) | \
(1 << QSPI_GIGADEVICE_STATUS_REG_BP4_POS) | \
(1 << QSPI_GIGADEVICE_STATUS_REG_SRP_POS))
#define QSPI_GIGADEVICE_STATUS_REG2_SRL_POS (0) // Status Register2 Protection Bit 1
#define QSPI_GIGADEVICE_STATUS_REG2_CMP_POS (6) // Complement Protect Bit 1
#define QSPI_GIGADEVICE_STATUS_REG2_PROTECTION_MASK ((1 << QSPI_GIGADEVICE_STATUS_REG2_SRL_POS) | \
(1 << QSPI_GIGADEVICE_STATUS_REG2_CMP_POS))
#define QSPI_GIGADEVICE_STATUS_REG2_SUSPEND1_POS (7)
#define QSPI_GIGADEVICE_STATUS_REG2_SUSPEND1_MASK (1 << QSPI_GIGADEVICE_STATUS_REG2_SUSPEND1_POS)
#define QSPI_GIGADEVICE_STATUS_REG2_SUSPEND2_POS (2)
#define QSPI_GIGADEVICE_STATUS_REG2_SUSPEND2_MASK (1 << QSPI_GIGADEVICE_STATUS_REG2_SUSPEND2_POS)
#define QSPI_GIGADEVICE_STATUS_REG2_QUAD_ENABLE_POS (1)
#define QSPI_GIGADEVICE_STATUS_REG2_QUAD_ENABLE_MASK (1 << QSPI_GIGADEVICE_STATUS_REG2_QUAD_ENABLE_POS)
__RETAINED_CODE static void qspi_gigadevice_enable_quad_mode(HW_QSPIC_ID id);
__RETAINED_CODE static uint8_t qspi_gigadevice_read_register(HW_QSPIC_ID id, uint8_t opcode, uint8_t mask)
{
__DBG_QSPI_VOLATILE__ uint8_t reg_val;
ASSERT_WARNING((opcode == QSPI_READ_STATUS_REG_OPCODE) ||
(opcode == QSPI_GIGADEVICE_READ_STATUS_REG2_OPCODE));
hw_qspi_cs_enable(id);
hw_qspi_write8(id, opcode);
reg_val = hw_qspi_read8(id);
hw_qspi_cs_disable(id);
return (reg_val & mask);
}
__RETAINED_CODE static void qspi_gigadevice_write_register(HW_QSPIC_ID id, uint8_t opcode, uint8_t value)
{
ASSERT_WARNING((opcode == QSPI_WRITE_STATUS_REG_OPCODE));
// Notice: GD25LQ128DSIG has three status registers. Please check the write-status operation date formation.
// for this demo the write-status register operation only write the QE bit, so this callback link to the QE enable.
qspi_gigadevice_enable_quad_mode(id);
}
__RETAINED_CODE static uint8_t qspi_gigadevice_read_status_reg(HW_QSPIC_ID id)
{
return qspi_gigadevice_read_register(id, QSPI_READ_STATUS_REG_OPCODE, 0xFF);
}
__RETAINED_CODE static void qspi_gigadevice_write_status_reg(HW_QSPIC_ID id, uint8_t status_reg)
{
qspi_gigadevice_write_register(id, QSPI_WRITE_STATUS_REG_OPCODE, status_reg);
}
__RETAINED_CODE static uint8_t qspi_gigadevice_get_dummy_bytes(HW_QSPIC_ID id, sys_clk_t sys_clk)
{
return 2;
}
__RETAINED_CODE static void qspi_gigadevice_sys_clock_cfg(HW_QSPIC_ID id, sys_clk_t sys_clk)
{
}
__RETAINED_CODE static bool qspi_gigadevice_is_suspended(HW_QSPIC_ID id)
{
__DBG_QSPI_VOLATILE__ uint8_t is_suspended;
// Notice: the GD25LQ128DSIG has two suspend flags, here we combine the flags.
is_suspended = qspi_gigadevice_read_register(id, QSPI_GIGADEVICE_READ_STATUS_REG2_OPCODE,
QSPI_GIGADEVICE_STATUS_REG2_SUSPEND1_MASK);
is_suspended |= qspi_gigadevice_read_register(id, QSPI_GIGADEVICE_READ_STATUS_REG2_OPCODE,
QSPI_GIGADEVICE_STATUS_REG2_SUSPEND2_MASK);
return (bool) is_suspended;
}
__RETAINED_CODE static bool qspi_gigadevice_is_busy(HW_QSPIC_ID id, HW_QSPI_BUSY_LEVEL busy_level)
{
__DBG_QSPI_VOLATILE__ HW_QSPI_BUSY_LEVEL is_busy;
is_busy = (HW_QSPI_BUSY_LEVEL ) (qspi_gigadevice_read_status_reg(id) & QSPI_STATUS_REG_BUSY_MASK);
return (bool) is_busy;
}
__RETAINED_CODE static void qspi_gigadevice_enable_quad_mode(HW_QSPIC_ID id)
{
__DBG_QSPI_VOLATILE__ uint8_t status_reg1;
__DBG_QSPI_VOLATILE__ uint8_t status_reg2;
__DBG_QSPI_VOLATILE__ uint16_t status_regs;
__DBG_QSPI_VOLATILE__ uint16_t verify;
status_reg1 = qspi_gigadevice_read_register(id, QSPI_READ_STATUS_REG_OPCODE, 0xFF); // read status reg 1
status_reg2 = qspi_gigadevice_read_register(id, QSPI_GIGADEVICE_READ_STATUS_REG2_OPCODE, 0xFF); // read status reg 2
if (!(status_reg2 & QSPI_GIGADEVICE_STATUS_REG2_QUAD_ENABLE_MASK)) {
status_reg2 |= QSPI_GIGADEVICE_STATUS_REG2_QUAD_ENABLE_MASK;
status_regs = ((((uint16_t)status_reg1)<<8)&0xff00) | status_reg2;
qspi_flash_write_enable(id);
hw_qspi_cs_enable(id);
hw_qspi_write8(id, QSPI_WRITE_STATUS_REG_OPCODE);
hw_qspi_write16(id, status_regs);
hw_qspi_cs_disable(id);
while (qspi_gigadevice_is_busy(id, HW_QSPI_BUSY_LEVEL_HIGH));
verify = qspi_gigadevice_read_register(id, QSPI_GIGADEVICE_READ_STATUS_REG2_OPCODE, 0xFF);
ASSERT_WARNING(status_reg2 == verify);
}
}
__UNUSED __RETAINED_CODE static void qspi_gigadevice_unlock_protection(HW_QSPIC_ID id)
{
__DBG_QSPI_VOLATILE__ uint8_t status_reg;
__DBG_QSPI_VOLATILE__ uint8_t status_reg2;
__DBG_QSPI_VOLATILE__ uint16_t status_regs;
__DBG_QSPI_VOLATILE__ uint8_t verify;
status_reg = qspi_gigadevice_read_status_reg(id);
status_reg2 = 0x02 & qspi_gigadevice_read_register(id, QSPI_GIGADEVICE_READ_STATUS_REG2_OPCODE, 0xFF);
// Clear Protection Bits [SRP BP4 BP3 BP2 BP1 BP0]
if (status_reg & QSPI_GIGADEVICE_STATUS_REG_PROTECTION_MASK) {
status_reg &= ~QSPI_GIGADEVICE_STATUS_REG_PROTECTION_MASK;
qspi_flash_write_enable(id);
status_regs = (uint16_t)(status_regs | (status_reg<<8)) | status_reg2;
qspi_gigadevice_write_status_reg(id, status_reg);
while (qspi_gigadevice_is_busy(id, HW_QSPI_BUSY_LEVEL_HIGH));
verify = qspi_gigadevice_read_status_reg(id);
ASSERT_WARNING(status_reg == verify);
}
}
#endif /* _QSPI_GIGADEVICE_V2_H_ */
/**
* \}
* \}
*/
7.2. Modifications to qspi_memory_config_table_internal.h
Under folder {SDK_root}/sdk/bsp/memory/src, resides source file qspi_memory_config_table_internal.h. Find the following section…
#include "qspi_mx25u3235_v2.h"
#include "qspi_w25q32jwiq_v2.h"
#include "qspi_w25q32jwim_v2.h"
const qspi_flash_config_t* qspi_memory_config_table[] = {
&qspi_mx25u3235_cfg,
&qspi_w25q32jwiq_cfg,
&qspi_w25q32jwim_cfg,
};
… and replace it with …
#include "qspi_mx25u3235_v2.h"
#include "qspi_w25q32jwiq_v2.h"
#include "qspi_w25q32jwim_v2.h"
#include "qspi_gd25lq128dsig_v2.h"
const qspi_flash_config_t* qspi_memory_config_table[] = {
&qspi_gd25lq128dsig_cfg,
&qspi_mx25u3235_cfg,
&qspi_w25q32jwiq_cfg,
&qspi_w25q32jwim_cfg,
};
… to make GigaDevice GD25LQ128DSIG QSPI Flash discoverable through FLASH_AUTODETECT.
7.3. The custom_config_ files
In custom_config_ variant files of any custom Firmware add the following lines:
#define dg_configFLASH_AUTODETECT (0)
#define dg_configFLASH_HEADER_FILE "qspi_gd25lq128dsig_v2.h"
#define dg_configFLASH_CONFIG qspi_gd25lq128dsig_cfg
The above snippet disables device autodetect, defines which driver should be used and defines the name of the configuration object to be used as it is defined in the driver file.
7.4. XML Configuration Entry
Under folder {SDK_root}/utilities/python_scripts/qspi find and edit file flash_configurations.xml. Add the following entry:
<configuration name="GD25LQ128DSIG">
<flash_size>0x1000000</flash_size>
<flash_burstcmda_reg_value>0xA8FF00EB</flash_burstcmda_reg_value>
<flash_burstcmdb_reg_value>0x00001026</flash_burstcmdb_reg_value>
<flash_write_config_command>0x01 0x02 0x07</flash_write_config_command>
</configuration>
Now, if program_qspi_config is chosen from External Tools drop-down menu, there should be a QSPI Flash Option called GigaDevice GD25LQ128DSIG which will set the correct values to the Product Header of any custom Firmware targeting this particular QSPI Flash Device.