3. QSPI Memory Driver
Using a custom QSPI memory requires the creation of a driver for the custom device and subsequently making said driver visible to the firmware loader tools and to the firmware itself. For products of the DA1469x family, the process of the driver creation has been simplified into the making of a simple c header file. The driver header file consists of a configuration object of structure qspi_flash_config_t as well as a set of callback and helper functions. When creating a new driver it is advised to use qspi_XXX_template.h as a basis, which can be found along with the other QSPI Memory Drivers under {SDK_root}/sdk/bsp/memory/include folder.
3.1. Configuration Structure
The qspi_flash_config_t structure is defined in qspi_common.h header file which can be found under {SDK_root}/sdk/bsp/memory/include folder. Fill in the required fields after consulting the datasheet of the QSPI Memory device used.
The fields of the configuration structure could be divided into three different sections.
Common: These fields are mandatory for both QSPI Flash drivers AND QSPI PSRAM drivers.
QSPI Flash only: These fields should only be initialized when the device targetted by the driver, is a QSPI Flash.
QSPI PSRAM only: These fields should only be initialized when the device targetted by the driver, is a QSPI PSRAM.
3.1.1. Common Fields
Field  | 
Type  | 
Description  | 
|---|---|---|
.manufacturer_id  | 
uint8_t  | 
This corresponds to the first byte expected to be returned by the read_jedec_id command (9Fh).  | 
.device_type  | 
uint8_t  | 
This corresponds to the second byte expected to be returned by the read_jedec_id command (9Fh).  | 
.device_density  | 
uint8_t  | 
This corresponds to the third byte expected to be returned by the read_jedec_id command (9Fh).  | 
.memory_size  | 
uint32_t  | 
This represents the capacity of the storage device in bits.  | 
.address_size  | 
HW_QSPI_ADDR_SIZE  | 
Desired Addressing Mode. Either 24-bit or 32-bit addressing will be used when accessing the device.   | 
.is_ram  | 
bool  | 
Set to true if the device is a PSRAM device connected to QSPI Controller 2 or false if it is a Flash Memory.  | 
.initialize  | 
initialize_cb_t  | 
This is the QSPI Memory Device initialization function. It is called by the system to perform all the necessary steps that will set the QSPI Memory device operable.   | 
.sys_clk_cfg  | 
sys_clk_cfg_cb_t  | 
This callback function is called right before a system clock change is going to take place when switching to PLL96 or after the clock change when switching from PLL96 to account for any configurations that might require change when switching operating frequency.   | 
.is_suspended  | 
is_suspended_cb_t  | 
This callback function is called to check if the Flash is in suspended state.   | 
.get_dummy_bytes  | 
get_dummy_bytes_cb_t  | 
This function’s purpose is to return the number of dummy bytes that need to be sent after the extra byte, before the QSPI Storage device can switch SIO0 to SIO3 from input to output. The number might vary, depending on the vendor, model or even QSPIC clock frequency.   | 
.fast_read_opcode  | 
uint8_t  | 
This is the opcode that should be used to perform read operations.  | 
.extra_byte  | 
uint8_t  | 
This field represents the byte that needs to be sent right after the addressing phase which activates performance mode and could vary from vendor to vendor.   | 
.send_once  | 
uint8_t  | 
This field goes along with the extra byte.   | 
.break_seq_size  | 
HW_QSPI_BREAK_SEQ_SIZE  | 
When it is desired to exit performance mode, a new empty read command is issued only this time 0xFF is sent instead of the extra byte.   | 
Warning
if Device Autodetect is used, the firmware will first issue a READ_JEDEC_ID (9Fh) command to the device to retrieve three bytes that uniquely identify the QSPI Memory. These three bytes that were returned are then checked against every configuration object of every driver that is part of Device Autodetect. If they match with .manufacturer_id, .device_type and .device_density fields of any configuration object, the initialization of the QSPI Memory occurs according to that configuration object’s fields.
Tool uartboot loader which is responsible for downloading firmware to the Flash or RAM, uses dg_configFLASH_AUTODETECT by default.
3.1.2. QSPI Flash only Fields
Field  | 
Type  | 
Description  | 
|---|---|---|
(QSPI Flash only)   | 
qspi_ucode_t  | 
OBSOLETE - Currently not used in DA1469x products. The .ucode_wakeup field can be ommited in the driver. - OBSOLETE   | 
(QSPI Flash only)   | 
uint16_t  | 
Every QSPI Flash device needs some time from the moment that it is supplied with power for the first time, until it is able to accept all the SPI commands it supports. This delay in microseconds should be the value of this field.   | 
(QSPI Flash only)   | 
uint16_t  | 
Similar to power_up_delay, this field represents the delay in microseconds between sending Enter Deep Power Down Mode command (B9h) until it takes effect.   | 
(QSPI Flash only)   | 
uint16_t  | 
Exiting Deep Power Down mode has a short delay as well. This field’s value should reflect this delay in microseconds as well.    | 
(QSPI Flash only)   | 
uint8_t  | 
This byte value corresponds to the opcode of the Quad Page Program command.  | 
(QSPI Flash only)   | 
uint8_t  | 
Optional   | 
(QSPI Flash only)   | 
bool  | 
This field sets the QSPI bus to the proper mode during the addressing phase for Page Program.   | 
(QSPI Flash only)   | 
uint8_t  | 
This byte value corresponds to the opcode of sector(4KB) erase.  | 
(QSPI Flash only)   | 
uint8_t  | 
This byte value corresponds to the opcode of erase suspend.  | 
(QSPI Flash only)   | 
uint8_t  | 
This byte value corresponds to the opcode of erase resume.  | 
(QSPI Flash only)   | 
uint8_t  | 
This field usually takes the value of Read Status Register command so it can read the WIP bit.  | 
(QSPI Flash only)   | 
uint8_t  | 
This corresponds to the bit position [0-7] of the WIP bit in the Status Register. (usually position 0)  | 
(QSPI Flash only)   | 
bool  | 
This field’s value represents the value of WIP bit when the QSPI Flash is busy.   | 
3.1.3. QSPI PSRAM only Fields
Field  | 
Type  | 
Description  | 
|---|---|---|
(QSPI PSRAM only)    | 
HW_QSPI2_MEMBLEN  | 
The length of the wrapping burst that the external memory device is capable to implement is held in this field.  | 
(QSPI PSRAM only)    | 
bool  | 
Some QSPI Memory devices only allow up to a maximum amount of time that the Chip Select (CE#) can stay active-low during burst read operations.   | 
(QSPI PSRAM only)    | 
uint8_t  | 
The maximum allowed time that the Chip Select(CE#) can stay active, in microseconds.   | 
3.2. Extra Driver Components
Other than the configuration object, a driver should contain the definitions of the callback functions as well as functions that provide non-standard functionality and which could also be called by the callback functions.Such functions’ range of operations could vary from performing optional to essential tasks to the proper operation of the device.
One such example could be writing directly to the second byte of status register or driving the output signal. In most cases they are not mandatory for operating the device however they are helpful.
Another example could be reading or writing to a register which is non accessible through Write Status Register command (01h).