测试板卡上GD25x512ME芯片 SPI方式读写测试。
一、电路部分
1.1、GD25x512ME芯片部分电路图
使用SPI方式,需要将JP64选择QSPI0功能。
1.2、GD25x512手册部分
GD25x512是一颗512M-bit FLASH芯片,支持SPI模式和OPI模式。
芯片内部框图
存储结构
1.3、OSPI接口
1.3.1、GD32H759的OSPI简介
OSPI是一种专用于和外部存储器通信的接口,支持单线,双线,四线和八线SPI模式。
1.3.2、主要特征
-三种模式:
- 间接模式:使用OSPI的寄存器执行所有操作。
- 状态轮询模式:周期性读取并检测外部存储器的状态寄存器值。
- 内存映射模式:外部存储器映射到MCU地址空间(OSPI0: 0x9000 0000 - 0x9FFFFFFF, OSPI1: 0x7000 0000- 0x 7FFF FFFF),和访问内部存储空间一样访问存储器。
支持内存映射模式下读;
支持单线、双线、四线和八线通信;
可用于间接模式和内存映射模式的完全可编程命令格式;
支持SDR(单倍数据速率)和DTR(双倍传输速率,仅支持读GD25LX512ME);
接收和发送的FIFO功能;
允许8位、 16位或32位数据访问;
间接模式支持DMA操作;
中断: FIFO达到阈值,状态匹配、传输完成、访问错误中断。
1.3.3、8线通信模式结构框图
1.3.4、4线通信模式结构框图
二、程序部分
2.1、gd25x512me.c
/*!
\file gd25x512me.c
\brief OSPI flash gd25x512 driver
\version 2024-01-05, V1.2.0, demo for GD32H7xx
*/
/*
Copyright (c) 2024, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd25x512me.h"
#include "gd32h7xx.h"
/*!
\brief initialize OSPI/OSPIM and GPIO
\param[in] ospi_periph: OSPIx(x=0,1)
\param[out] ospi_struct: OSPI parameter initialization stuct members of the structure
and the member values are shown as below:
prescaler: between 0 and 255
fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
OSPI_MACRONIX_RAM_MODE,
wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
\retval none
*/
void ospi_flash_init(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct)
{
/* reset the OSPI and OSPIM peripheral */
ospi_deinit(ospi_periph);
ospim_deinit();
/* enable OSPIM and GPIO clock */
rcu_periph_clock_enable(RCU_OSPIM);
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_GPIOE);
/* configure OSPIM GPIO pin:
OSPIM_P0_IO0(PD11)
OSPIM_P0_IO1(PC10)
OSPIM_P0_IO2(PE2)
OSPIM_P0_IO3(PD13)
OSPIM_P0_IO4(PD4)
OSPIM_P0_IO5(PD5)
OSPIM_P0_IO6(PD6)
OSPIM_P0_IO7(PD7)
OSPIM_P0_CLK(PA3)
OSPIM_P0_NCS(PB10) */
gpio_af_set(GPIOA, GPIO_AF_12, GPIO_PIN_3);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_3);
gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_10);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_10);
gpio_af_set(GPIOC, GPIO_AF_9, GPIO_PIN_10);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_10);
gpio_af_set(GPIOD, GPIO_AF_10, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
gpio_af_set(GPIOD, GPIO_AF_9, GPIO_PIN_11 | GPIO_PIN_13);
gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11 | GPIO_PIN_13);
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_11 | GPIO_PIN_13);
gpio_af_set(GPIOE, GPIO_AF_9, GPIO_PIN_2);
gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_2);
/* enable SCK, CSN, IO[3:0] and IO[7:4] for OSPIM port0 */
ospim_port_sck_config(OSPIM_PORT0, OSPIM_PORT_SCK_ENABLE);
ospim_port_csn_config(OSPIM_PORT0, OSPIM_PORT_CSN_ENABLE);
ospim_port_io3_0_config(OSPIM_PORT0, OSPIM_IO_LOW_ENABLE);
ospim_port_io7_4_config(OSPIM_PORT0, OSPIM_IO_HIGH_ENABLE);
switch(ospi_periph) {
case OSPI0:
rcu_periph_clock_enable(RCU_OSPI0);
/* configure OSPIM port0 */
ospim_port_sck_source_select(OSPIM_PORT0, OSPIM_SCK_SOURCE_OSPI0_SCK);
ospim_port_csn_source_select(OSPIM_PORT0, OSPIM_CSN_SOURCE_OSPI0_CSN);
ospim_port_io3_0_source_select(OSPIM_PORT0, OSPIM_SRCPLIO_OSPI0_IO_LOW);
ospim_port_io7_4_source_select(OSPIM_PORT0, OSPIM_SRCPHIO_OSPI0_IO_HIGH);
break;
case OSPI1:
rcu_periph_clock_enable(RCU_OSPI1);
/* configure OSPIM port0 */
ospim_port_sck_source_select(OSPIM_PORT0, OSPIM_SCK_SOURCE_OSPI1_SCK);
ospim_port_csn_source_select(OSPIM_PORT0, OSPIM_CSN_SOURCE_OSPI1_CSN);
ospim_port_io3_0_source_select(OSPIM_PORT0, OSPIM_SRCPLIO_OSPI1_IO_LOW);
ospim_port_io7_4_source_select(OSPIM_PORT0, OSPIM_SRCPHIO_OSPI1_IO_HIGH);
break;
default:
break;
}
/* initialize the parameters of OSPI struct */
ospi_struct_init(ospi_struct);
ospi_struct->prescaler = 9U;
ospi_struct->sample_shift = OSPI_SAMPLE_SHIFTING_NONE;
ospi_struct->fifo_threshold = OSPI_FIFO_THRESHOLD_5;
ospi_struct->device_size = OSPI_MESZ_512_MBS;
ospi_struct->wrap_size = OSPI_DIRECT;
ospi_struct->cs_hightime = OSPI_CS_HIGH_TIME_3_CYCLE;
ospi_struct->memory_type = OSPI_MICRON_MODE;
ospi_struct->delay_hold_cycle = OSPI_DELAY_HOLD_NONE;
/* initialize OSPI parameter */
ospi_init(ospi_periph, ospi_struct);
/* enable OSPI */
ospi_enable(ospi_periph);
}
/*!
\brief read the flah id
\param[in] ospi_periph: OSPIx(x=0,1)
\param[in] ospi_struct: OSPI parameter initialization stuct members of the structure
and the member values are shown as below:
prescaler: between 0 and 255
fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
OSPI_MACRONIX_RAM_MODE,
wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
\param[in] mode: flash interface mode
only one parameter can be selected which is shown as below:
\arg SPI_MODE: SPI mode
\arg OSPI_MODE: OSPI mode
\retval none
*/
uint32_t ospi_flash_read_id(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode)
{
uint8_t temp_id[4];
ospi_regular_cmd_struct cmd_struct = {0};
/* initialize read ID command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
cmd_struct.addr_mode = OSPI_ADDRESS_NONE;
cmd_struct.data_mode = OSPI_DATA_1_LINE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
cmd_struct.addr_mode = OSPI_ADDRESS_NONE;
cmd_struct.data_mode = OSPI_DATA_8_LINES;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_8;
}
cmd_struct.operation_type = OSPI_OPTYPE_COMMON_CFG;
cmd_struct.instruction = GD25X512ME_READ_ID_CMD;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.addr_size = OSPI_ADDRESS_24_BITS;
cmd_struct.addr_dtr_mode = OSPI_ADDRDTR_MODE_DISABLE;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.alter_bytes_size = OSPI_ALTERNATE_BYTES_24_BITS;
cmd_struct.alter_bytes_dtr_mode = OSPI_ABDTR_MODE_DISABLE;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.nbdata = 4;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
/* receive data */
ospi_receive(ospi_periph, temp_id);
return (temp_id[0] << 24) | (temp_id[1] << 16) | (temp_id[2] << 8) | temp_id[3];
}
/*!
\brief enable flash reset
\param[in] ospi_periph: OSPIx(x=0,1)
\param[in] ospi_struct: OSPI parameter initialization stuct members of the structure
and the member values are shown as below:
prescaler: between 0 and 255
fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
OSPI_MACRONIX_RAM_MODE,
wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
\param[in] mode: flash interface mode
only one parameter can be selected which is shown as below:
\arg SPI_MODE: SPI mode
\arg OSPI_MODE: OSPI mode
\retval none
*/
void ospi_flash_reset_enable(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode)
{
ospi_regular_cmd_struct cmd_struct = {0};
/* initialize enable flash reset command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
}
cmd_struct.operation_type = OSPI_OPTYPE_COMMON_CFG;
cmd_struct.instruction = GD25X512ME_RESET_ENABLE_CMD;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.addr_mode = OSPI_ADDRESS_NONE;
cmd_struct.addr_size = OSPI_ADDRESS_24_BITS;
cmd_struct.addr_dtr_mode = OSPI_ADDRDTR_MODE_DISABLE;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.alter_bytes_size = OSPI_ALTERNATE_BYTES_24_BITS;
cmd_struct.alter_bytes_dtr_mode = OSPI_ABDTR_MODE_DISABLE;
cmd_struct.data_mode = OSPI_DATA_NONE;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
cmd_struct.nbdata = 0;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
}
/*!
\brief reset the flash
\param[in] ospi_periph: OSPIx(x=0,1)
\param[in] ospi_struct: OSPI parameter initialization stuct members of the structure
and the member values are shown as below:
prescaler: between 0 and 255
fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
OSPI_MACRONIX_RAM_MODE,
wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
\param[in] mode: flash interface mode
only one parameter can be selected which is shown as below:
\arg SPI_MODE: SPI mode
\arg OSPI_MODE: OSPI mode
\retval none
*/
void ospi_flash_reset_memory(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode)
{
ospi_regular_cmd_struct cmd_struct = {0};
/* initialize flash reset command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
}
cmd_struct.operation_type = OSPI_OPTYPE_COMMON_CFG;
cmd_struct.instruction = GD25X512ME_RESET_MEMORY_CMD;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.addr_mode = OSPI_ADDRESS_NONE;
cmd_struct.addr_size = OSPI_ADDRESS_24_BITS;
cmd_struct.addr_dtr_mode = OSPI_ADDRDTR_MODE_DISABLE;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.alter_bytes_size = OSPI_ALTERNATE_BYTES_24_BITS;
cmd_struct.alter_bytes_dtr_mode = OSPI_ABDTR_MODE_DISABLE;
cmd_struct.data_mode = OSPI_DATA_NONE;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
cmd_struct.nbdata = 0;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
}
/*!
\brief enable flash write
\param[in] ospi_periph: OSPIx(x=0,1)
\param[in] ospi_struct: OSPI parameter initialization stuct members of the structure
and the member values are shown as below:
prescaler: between 0 and 255
fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
OSPI_MACRONIX_RAM_MODE,
wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
\param[in] mode: flash interface mode
only one parameter can be selected which is shown as below:
\arg SPI_MODE: SPI mode
\arg OSPI_MODE: OSPI mode
\retval none
*/
void ospi_flash_write_enbale(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode)
{
ospi_autopolling_struct autopl_cfg_struct = {0};
ospi_regular_cmd_struct cmd_struct = {0};
/* initialize write enable command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
}
cmd_struct.operation_type = OSPI_OPTYPE_COMMON_CFG;
cmd_struct.instruction = GD25X512ME_WRITE_ENABLE_CMD;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.addr_mode = OSPI_ADDRESS_NONE;
cmd_struct.addr_size = OSPI_ADDRESS_24_BITS;
cmd_struct.addr_dtr_mode = OSPI_ADDRDTR_MODE_DISABLE;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.alter_bytes_size = OSPI_ALTERNATE_BYTES_24_BITS;
cmd_struct.alter_bytes_dtr_mode = OSPI_ABDTR_MODE_DISABLE;
cmd_struct.data_mode = OSPI_DATA_NONE;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
cmd_struct.nbdata = 0;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
/* configure automatic polling mode to wait for write enabling */
if(SPI_MODE == mode) {
cmd_struct.data_mode = OSPI_DATA_1_LINE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
} else {
cmd_struct.data_mode = OSPI_DATA_8_LINES;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_8;
}
cmd_struct.instruction = GD25X512ME_READ_STATUS_REG_CMD;
cmd_struct.addr_dtr_mode = OSPI_ADDRDTR_MODE_DISABLE;
cmd_struct.nbdata = 1;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
autopl_cfg_struct.match = 2U;
autopl_cfg_struct.mask = 2U;
autopl_cfg_struct.match_mode = OSPI_MATCH_MODE_AND;
autopl_cfg_struct.interval = GD25X512ME_AUTOPOLLING_INTERVAL_TIME;
autopl_cfg_struct.automatic_stop = OSPI_AUTOMATIC_STOP_MATCH;
ospi_autopolling_mode(ospi_periph, ospi_struct, &autopl_cfg_struct);
}
/*!
\brief write flash volatile configuration register
\param[in] ospi_periph: OSPIx(x=0,1)
\param[in] ospi_struct: OSPI parameter initialization stuct members of the structure
and the member values are shown as below:
prescaler: between 0 and 255
fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
OSPI_MACRONIX_RAM_MODE,
wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
\param[in] mode: flash interface mode
only one parameter can be selected which is shown as below:
\arg SPI_MODE: SPI mode
\arg OSPI_MODE: OSPI mode
\param[in] addr_size: the size of address
\param[in] value: the value of transmit
\retval none
*/
void ospi_flash_write_volatilecfg_register(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size,
uint32_t addr, uint8_t value)
{
ospi_regular_cmd_struct cmd_struct = {0};
/* initialize write enable for volatile status register command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
}
cmd_struct.operation_type = OSPI_OPTYPE_COMMON_CFG;
cmd_struct.instruction = GD25X512ME_WRITE_ENABLE_VOLATILE_STATUS_CFG_CMD;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.addr_mode = OSPI_ADDRESS_NONE;
cmd_struct.addr_size = OSPI_ADDRESS_24_BITS;
cmd_struct.addr_dtr_mode = OSPI_ADDRDTR_MODE_DISABLE;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.alter_bytes_size = OSPI_ALTERNATE_BYTES_24_BITS;
cmd_struct.alter_bytes_dtr_mode = OSPI_ABDTR_MODE_DISABLE;
cmd_struct.data_mode = OSPI_DATA_NONE;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
cmd_struct.nbdata = 0;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
/* initialize write volatile configuration register command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
cmd_struct.addr_mode = OSPI_ADDRESS_1_LINE;
cmd_struct.data_mode = OSPI_DATA_1_LINE;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
cmd_struct.addr_mode = OSPI_ADDRESS_8_LINES;
cmd_struct.data_mode = OSPI_DATA_8_LINES;
}
if(GD25X512ME_3BYTES_SIZE == addr_size) {
cmd_struct.addr_size = OSPI_ADDRESS_24_BITS;
} else {
cmd_struct.addr_size = OSPI_ADDRESS_32_BITS;
}
cmd_struct.operation_type = OSPI_OPTYPE_COMMON_CFG;
cmd_struct.instruction = GD25X512ME_WRITE_VOLATILE_CFG_REG_CMD;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.address = addr;
cmd_struct.addr_dtr_mode = OSPI_ADDRDTR_MODE_DISABLE;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.alter_bytes_size = OSPI_ALTERNATE_BYTES_24_BITS;
cmd_struct.alter_bytes_dtr_mode = OSPI_ABDTR_MODE_DISABLE;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
cmd_struct.nbdata = 1;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
ospi_transmit(ospi_periph, &value);
}
/*!
\brief polling WIP(Write In Progress) bit become to 0
\param[in] ospi_periph: OSPIx(x=0,1)
\param[in] ospi_struct: OSPI parameter initialization stuct members of the structure
and the member values are shown as below:
prescaler: between 0 and 255
fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
OSPI_MACRONIX_RAM_MODE,
wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
\param[in] mode: flash interface mode
only one parameter can be selected which is shown as below:
\arg SPI_MODE: SPI mode
\arg OSPI_MODE: OSPI mode
\retval none
*/
void ospi_flash_autopolling_mem_ready(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode)
{
ospi_autopolling_struct autopl_cfg_struct = {0};
ospi_regular_cmd_struct cmd_struct = {0};
/* initialize read status register command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
cmd_struct.addr_mode = OSPI_ADDRESS_NONE;
cmd_struct.data_mode = OSPI_DATA_1_LINE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
cmd_struct.addr_mode = OSPI_ADDRESS_NONE;
cmd_struct.data_mode = OSPI_DATA_8_LINES;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_8;
}
cmd_struct.operation_type = OSPI_OPTYPE_COMMON_CFG;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.instruction = GD25X512ME_READ_STATUS_REG_CMD;
cmd_struct.addr_dtr_mode = OSPI_ADDRDTR_MODE_DISABLE;
cmd_struct.addr_size = OSPI_ADDRESS_24_BITS;
cmd_struct.address = 0U;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.alter_bytes_size = OSPI_ALTERNATE_BYTES_24_BITS;
cmd_struct.alter_bytes_dtr_mode = OSPI_ABDTR_MODE_DISABLE;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.nbdata = 1;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
/* configure the OSPI automatic polling mode */
autopl_cfg_struct.match = 0U;
autopl_cfg_struct.mask = GD25X512ME_SR_WIP;
autopl_cfg_struct.match_mode = OSPI_MATCH_MODE_AND;
autopl_cfg_struct.interval = GD25X512ME_AUTOPOLLING_INTERVAL_TIME;
autopl_cfg_struct.automatic_stop = OSPI_AUTOMATIC_STOP_MATCH;
ospi_autopolling_mode(ospi_periph, ospi_struct, &autopl_cfg_struct);
}
/*!
\brief erase the specified block of the flash
\param[in] ospi_periph: OSPIx(x=0,1)
\param[in] ospi_struct: OSPI parameter initialization stuct members of the structure
and the member values are shown as below:
prescaler: between 0 and 255
fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
OSPI_MACRONIX_RAM_MODE,
wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
\param[in] mode: flash interface mode
only one parameter can be selected which is shown as below:
\arg SPI_MODE: SPI mode
\arg OSPI_MODE: OSPI mode
\param[in] addr_size: the size of address
\param[in] address: address of erase
\param[in] block_size: block size to erase
\retval none
*/
void ospi_flash_block_erase(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size, uint32_t addr,
erase_size block_size)
{
ospi_regular_cmd_struct cmd_struct = {0};
/* initialize block erase command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
cmd_struct.addr_mode = OSPI_ADDRESS_1_LINE;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
cmd_struct.addr_mode = OSPI_ADDRESS_8_LINES;
}
if(GD25X512ME_ERASE_64K == block_size) {
if(GD25X512ME_3BYTES_SIZE == addr_size) {
cmd_struct.instruction = GD25X512ME_BLOCK_ERASE_64K_CMD;
} else {
cmd_struct.instruction = GD25X512ME_4_BYTE_BLOCK_ERASE_64K_CMD;
}
} else {
if(GD25X512ME_3BYTES_SIZE == addr_size) {
cmd_struct.instruction = GD25X512ME_SECTOR_ERASE_4K_CMD;
} else {
cmd_struct.instruction = GD25X512ME_4_BYTE_SECTOR_ERASE_4K_CMD;
}
}
cmd_struct.operation_type = OSPI_OPTYPE_COMMON_CFG;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.addr_size = OSPI_ADDRESS_24_BITS;
cmd_struct.address = addr;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.alter_bytes_size = OSPI_ALTERNATE_BYTES_24_BITS;
cmd_struct.alter_bytes_dtr_mode = OSPI_ABDTR_MODE_DISABLE;
cmd_struct.data_mode = OSPI_DATA_NONE;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
cmd_struct.nbdata = 0;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
}
/*!
\brief erase the the entire flash
\param[in] ospi_periph: OSPIx(x=0,1)
\param[in] ospi_struct: OSPI parameter initialization stuct members of the structure
and the member values are shown as below:
prescaler: between 0 and 255
fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
OSPI_MACRONIX_RAM_MODE,
wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
\param[in] mode: flash interface mode
only one parameter can be selected which is shown as below:
\arg SPI_MODE: SPI mode
\arg OSPI_MODE: OSPI mode
\retval none
*/
void ospi_flash_chip_erase(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode)
{
ospi_regular_cmd_struct cmd_struct = {0};
/* initialize block erase command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
}
cmd_struct.operation_type = OSPI_OPTYPE_COMMON_CFG;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.instruction = GD25X512ME_CHIP_ERASE_CMD;
cmd_struct.addr_mode = OSPI_ADDRESS_NONE;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.alter_bytes_size = OSPI_ALTERNATE_BYTES_24_BITS;
cmd_struct.alter_bytes_dtr_mode = OSPI_ABDTR_MODE_DISABLE;
cmd_struct.data_mode = OSPI_DATA_NONE;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
cmd_struct.nbdata = 0;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
}
/*!
\brief write data to the flash
\param[in] ospi_periph: OSPIx(x=0,1)
\param[in] ospi_struct: OSPI parameter initialization stuct members of the structure
and the member values are shown as below:
prescaler: between 0 and 255
fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
OSPI_MACRONIX_RAM_MODE,
wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
\param[in] mode: flash interface mode
only one parameter can be selected which is shown as below:
\arg SPI_MODE: SPI mode
\arg OSPI_MODE: OSPI mode
\param[in] addr_size: the size of address
\param[in] pdata: pointer to data to be written
\param[in] addr: write start address
\param[in] data_size: size of data to write
\retval none
*/
void ospi_flash_page_program(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size, uint8_t *pdata,
uint32_t addr, uint32_t data_size)
{
ospi_regular_cmd_struct cmd_struct = {0};
/* initialize program command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
cmd_struct.addr_mode = OSPI_ADDRESS_1_LINE;
cmd_struct.data_mode = OSPI_DATA_1_LINE;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
cmd_struct.addr_mode = OSPI_ADDRESS_8_LINES;
cmd_struct.data_mode = OSPI_DATA_8_LINES;
}
if(GD25X512ME_3BYTES_SIZE == addr_size) {
cmd_struct.instruction = GD25X512ME_PAGE_PROG_CMD;
cmd_struct.addr_size = OSPI_ADDRESS_24_BITS;
} else {
cmd_struct.instruction = GD25X512ME_4_BYTE_PAGE_PROG_CMD;
cmd_struct.addr_size = OSPI_ADDRESS_32_BITS;
}
cmd_struct.operation_type = OSPI_OPTYPE_COMMON_CFG;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.addr_dtr_mode = OSPI_ADDRDTR_MODE_DISABLE;
cmd_struct.address = addr;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.alter_bytes_size = OSPI_ALTERNATE_BYTES_24_BITS;
cmd_struct.alter_bytes_dtr_mode = OSPI_ABDTR_MODE_DISABLE;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.nbdata = data_size;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
/* transmission of the data */
ospi_transmit(ospi_periph, pdata);
}
/*!
\brief read data from the flash
\param[in] ospi_periph: OSPIx(x=0,1)
\param[in] ospi_struct: OSPI parameter initialization stuct members of the structure
and the member values are shown as below:
prescaler: between 0 and 255
fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
OSPI_MACRONIX_RAM_MODE,
wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
\param[in] mode: flash interface mode
only one parameter can be selected which is shown as below:
\arg SPI_MODE: SPI mode
\arg OSPI_MODE: OSPI mode
\param[in] addr_size: the size of address
\param[in] pdata: pointer to data to be read
\param[in] addr: read start address
\param[in] data_size: size of data to read
\retval none
*/
void ospi_flash_read(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size, uint8_t *pdata,
uint32_t addr, uint32_t data_size)
{
ospi_regular_cmd_struct cmd_struct = {0};
/* initialize read command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
cmd_struct.addr_mode = OSPI_ADDRESS_1_LINE;
cmd_struct.data_mode = OSPI_DATA_1_LINE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_8;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
cmd_struct.addr_mode = OSPI_ADDRESS_8_LINES;
cmd_struct.data_mode = OSPI_DATA_8_LINES;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_16;
}
if(GD25X512ME_3BYTES_SIZE == addr_size) {
cmd_struct.instruction = GD25X512ME_FAST_READ_CMD;
cmd_struct.addr_size = OSPI_ADDRESS_24_BITS;
} else {
cmd_struct.instruction = GD25X512ME_4_BYTE_ADDR_FAST_READ_CMD;
cmd_struct.addr_size = OSPI_ADDRESS_32_BITS;
}
cmd_struct.operation_type = OSPI_OPTYPE_COMMON_CFG;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.addr_dtr_mode = OSPI_ADDRDTR_MODE_DISABLE;
cmd_struct.address = addr;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.alter_bytes_size = OSPI_ALTERNATE_BYTES_24_BITS;
cmd_struct.alter_bytes_dtr_mode = OSPI_ABDTR_MODE_DISABLE;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.nbdata = data_size;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
/* reception of the data */
ospi_receive(ospi_periph, pdata);
}
int32_t ospi_read_status_register(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode)
{
uint8_t status;
ospi_regular_cmd_struct cmd_struct = {0};
/* initialize read command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
cmd_struct.data_mode = OSPI_DATA_1_LINE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
cmd_struct.data_mode = OSPI_DATA_8_LINES;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_8;
}
cmd_struct.operation_type = OSPI_OPTYPE_COMMON_CFG;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.instruction = GD25X512ME_READ_STATUS_REG_CMD;
cmd_struct.addr_mode = OSPI_ADDRESS_NONE;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.nbdata = 1;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
/* reception of the data */
ospi_receive(ospi_periph, &status);
return status;
}
/*!
\brief enable memory mapped mode
\param[in] ospi_periph: OSPIx(x=0,1)
\param[in] ospi_struct: OSPI parameter initialization stuct members of the structure
and the member values are shown as below:
prescaler: between 0 and 255
fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
OSPI_MACRONIX_RAM_MODE,
wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
\param[in] mode: flash interface mode
only one parameter can be selected which is shown as below:
\arg SPI_MODE: SPI mode
\arg OSPI_MODE: OSPI mode
\param[in] addr_size: the size of address
\retval none
*/
void ospi_flash_memory_map_mode_enable(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size)
{
ospi_regular_cmd_struct cmd_struct = {0};
/* initialize read command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
}
if(GD25X512ME_3BYTES_SIZE == addr_size) {
cmd_struct.instruction = GD25X512ME_OCTAL_IO_FAST_READ_CMD;
cmd_struct.addr_size = OSPI_ADDRESS_24_BITS;
} else {
cmd_struct.instruction = GD25X512ME_4_BYTE_ADDR_OCTAL_IO_FAST_READ_CMD;
cmd_struct.addr_size = OSPI_ADDRESS_32_BITS;
}
cmd_struct.operation_type = OSPI_OPTYPE_READ_CFG;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.addr_mode = OSPI_ADDRESS_8_LINES;
cmd_struct.addr_dtr_mode = OSPI_ADDRDTR_MODE_DISABLE;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.alter_bytes_size = OSPI_ALTERNATE_BYTES_24_BITS;
cmd_struct.alter_bytes_dtr_mode = OSPI_ABDTR_MODE_DISABLE;
cmd_struct.data_mode = OSPI_DATA_8_LINES;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_16;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
/* initialize program command */
cmd_struct.operation_type = OSPI_OPTYPE_WRITE_CFG;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
if(GD25X512ME_3BYTES_SIZE == addr_size) {
cmd_struct.instruction = GD25X512ME_EXT_OCTAL_PAGE_PROG_CMD;
} else {
cmd_struct.instruction = GD25X512ME_4_BYTE_EXT_OCTAL_PAGE_PROG_CMD;
}
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
/* wait BUSY bit to 0 */
while(RESET != ospi_flag_get(ospi_periph, OSPI_FLAG_BUSY)) {
}
/* configure OSPI memory mapped mode */
ospi_functional_mode_config(ospi_periph, OSPI_MEMORY_MAPPED);
}
/*!
\brief enable memory mapped mode with wrap
\param[in] ospi_periph: OSPIx(x=0,1)
\param[in] ospi_struct: OSPI parameter initialization stuct members of the structure
and the member values are shown as below:
prescaler: between 0 and 255
fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
OSPI_MACRONIX_RAM_MODE,
wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
\param[in] mode: flash interface mode
only one parameter can be selected which is shown as below:
\arg SPI_MODE: SPI mode
\arg OSPI_MODE: OSPI mode
\param[in] addr_size: the size of address
\retval none
*/
void ospi_flash_memory_map_mode_wrap_enable(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size)
{
ospi_regular_cmd_struct cmd_struct = {0};
/* initialize read command */
if(SPI_MODE == mode) {
cmd_struct.ins_mode = OSPI_INSTRUCTION_1_LINE;
} else {
cmd_struct.ins_mode = OSPI_INSTRUCTION_8_LINES;
}
if(GD25X512ME_3BYTES_SIZE == addr_size) {
cmd_struct.instruction = GD25X512ME_OCTAL_IO_FAST_READ_CMD;
cmd_struct.addr_size = OSPI_ADDRESS_24_BITS;
} else {
cmd_struct.instruction = GD25X512ME_4_BYTE_ADDR_OCTAL_IO_FAST_READ_CMD;
cmd_struct.addr_size = OSPI_ADDRESS_32_BITS;
}
cmd_struct.operation_type = OSPI_OPTYPE_WRAP_CFG;
cmd_struct.ins_size = OSPI_INSTRUCTION_8_BITS;
cmd_struct.addr_mode = OSPI_ADDRESS_8_LINES;
cmd_struct.addr_dtr_mode = OSPI_ADDRDTR_MODE_DISABLE;
cmd_struct.alter_bytes_mode = OSPI_ALTERNATE_BYTES_NONE;
cmd_struct.alter_bytes_size = OSPI_ALTERNATE_BYTES_24_BITS;
cmd_struct.alter_bytes_dtr_mode = OSPI_ABDTR_MODE_DISABLE;
cmd_struct.data_mode = OSPI_DATA_8_LINES;
cmd_struct.data_dtr_mode = OSPI_DADTR_MODE_DISABLE;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_16;
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
/* initialize program command */
cmd_struct.operation_type = OSPI_OPTYPE_WRITE_CFG;
cmd_struct.dummy_cycles = OSPI_DUMYC_CYCLES_0;
if(GD25X512ME_3BYTES_SIZE == addr_size) {
cmd_struct.instruction = GD25X512ME_EXT_OCTAL_PAGE_PROG_CMD;
} else {
cmd_struct.instruction = GD25X512ME_4_BYTE_EXT_OCTAL_PAGE_PROG_CMD;
}
/* send the command */
ospi_command_config(ospi_periph, ospi_struct, &cmd_struct);
/* wait BUSY bit to 0 */
while(RESET != ospi_flag_get(ospi_periph, OSPI_FLAG_BUSY)) {
}
/* configure OSPI memory mapped mode */
ospi_functional_mode_config(ospi_periph, OSPI_MEMORY_MAPPED);
}
2.2、gd25x512me.h
/*!
\file gd25x512me.h
\brief the header file of OSPI flash gd25x512me driver
\version 2024-01-05, V1.2.0, demo for GD32H7xx
*/
/*
Copyright (c) 2024, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef GD25X512ME_H
#define GD25X512ME_H
#include "gd32h7xx_ospi.h"
/* GD25X512ME size configuration */
#define GD25X512ME_BLOCK_64K (uint32_t)(16*4*1024) /* 16 sectors of 64KBytes */
#define GD25X512ME_SECTOR_4K (uint32_t)(4 * 1024) /* 1 sectors of 4KBytes */
#define GD25X512ME_FLASH_SIZE (uint32_t)(512*1024*1024/8) /* 512 Mbits => 64MBytes */
#define GD25X512ME_PAGE_SIZE (uint32_t)256 /* 262144 pages of 256 Bytes */
/* GD25X512ME timing configuration */
#define GD25X512ME_BULK_ERASE_MAX_TIME 460000U
#define GD25X512ME_SECTOR_ERASE_MAX_TIME 1000U
#define GD25X512ME_SUBSECTOR_4K_ERASE_MAX_TIME 400U
#define GD25X512ME_WRITE_REG_MAX_TIME 40U
#define GD25X512ME_RESET_MAX_TIME 100U /* when SWreset during erase operation */
#define GD25X512ME_AUTOPOLLING_INTERVAL_TIME 0x10U
/* GD25X512ME Error codes */
#define GD25X512ME_OK (0)
#define GD25X512ME_ERROR (-1)
/* GD25X512ME commands */
/* READ/WRITE MEMORY operations with 3-bytes address */
#define GD25X512ME_READ_CMD 0x03U /* normal read 3 bytes address */
#define GD25X512ME_FAST_READ_CMD 0x0BU /* fast read 3 bytes address */
#define GD25X512ME_OCTAL_OUTPUT_FAST_READ_CMD 0x8BU /* octal output fast read 3 bytes address */
#define GD25X512ME_OCTAL_IO_FAST_READ_CMD 0xCBU /* octal I/O fast read 3 bytes address */
#define GD25X512ME_PAGE_PROG_CMD 0x02U /* page program 3 bytes address */
#define GD25X512ME_OCTAL_PAGE_PROG_CMD 0x82U /* octal page program 3 bytes address */
#define GD25X512ME_EXT_OCTAL_PAGE_PROG_CMD 0xC2U /* extended octal page program 3 bytes address */
#define GD25X512ME_SECTOR_ERASE_4K_CMD 0x20U /* sector erase 4KB 3 bytes address */
#define GD25X512ME_BLOCK_ERASE_32K_CMD 0x52U /* block erase 32KB 3 bytes address */
#define GD25X512ME_BLOCK_ERASE_64K_CMD 0xD8U /* block erase 64KB 3 bytes address */
#define GD25X512ME_CHIP_ERASE_CMD 0x60U /* chip erase */
/* READ/WRITE MEMORY operations with 4-bytes address */
#define GD25X512ME_4_BYTE_ADDR_READ_CMD 0x13U /* normal read 4 bytes address */
#define GD25X512ME_4_BYTE_ADDR_FAST_READ_CMD 0x0CU /* fast read 4 bytes address */
#define GD25X512ME_4_BYTE_ADDR_OCTAL_OUTPUT_FAST_READ_CMD 0x7CU /* octal output fast read 4 bytes address */
#define GD25X512ME_4_BYTE_ADDR_OCTAL_IO_FAST_READ_CMD 0xCCU /* octal I/O fast read 4 bytes address */
#define GD25X512ME_4_BYTE_ADDR_OCTAL_IO_DTR_FAST_READ_CMD 0xFDU /* octal I/O DTR fast read 4 bytes address */
#define GD25X512ME_4_BYTE_PAGE_PROG_CMD 0x12U /* page program 4 bytes address */
#define GD25X512ME_4_BYTE_OCTAL_PAGE_PROG_CMD 0x84U /* octal page program 4 bytes address */
#define GD25X512ME_4_BYTE_EXT_OCTAL_PAGE_PROG_CMD 0x8EU /* extended octal page program 4 byte address */
#define GD25X512ME_4_BYTE_SECTOR_ERASE_4K_CMD 0x21U /* sector erase 4KB 4 bytes address */
#define GD25X512ME_4_BYTE_BLOCK_ERASE_32K_CMD 0x5CU /* block erase 32KB 4 byte address */
#define GD25X512ME_4_BYTE_BLOCK_ERASE_64K_CMD 0xDCU /* block erase 64KB 4 byte address */
/* setting commands */
#define GD25X512ME_WRITE_ENABLE_CMD 0x06U /* write enable */
#define GD25X512ME_WRITE_DISABLE_CMD 0x04U /* write disable */
#define GD25X512ME_PROG_ERASE_SUSPEND_CMD 0x75U /* program/erase suspend */
#define GD25X512ME_PROG_ERASE_RESUME_CMD 0x7AU /* program/erase resume */
#define GD25X512ME_ENTER_DEEP_POWER_DOWN_CMD 0xB9U /* enter deep power down */
#define GD25X512ME_RELEASE_FROM_DEEP_POWER_DOWN_CMD 0xABU /* release form deep power down */
#define GD25X512ME_ENABLE_4_BYTE_ADDR_CMD 0xB7U /* enable 4 byte address mode */
#define GD25X512ME_DISABLE_4_BYTE_ADDR_CMD 0xE9U /* disable 4 byte address mode */
/* advanced sector protection commands */
#define GD25X512ME_INDIVIDUAL_BLOCK_SECTOR_LOCK_CMD 0x36U /* individual block/sector lock */
#define GD25X512ME_INDIVIDUAL_BLOCK_SECTOR_UNLOCK_CMD 0x39U /* individual block/sector unlock */
#define GD25X512ME_READ_INDIVIDUAL_BLOCK_SECTOR_LOCK_CMD 0x3DU /* read individual block/sector lock */
#define GD25X512ME_GLOBAL_BLOCK_SECTOR_LOCK_CMD 0x7EU /* global block/sector lock */
#define GD25X512ME_GLOBAL_BLOCK_SECTOR_UNLOCK_CMD 0x98U /* global block/sector unlock */
/* RESET commands */
#define GD25X512ME_RESET_ENABLE_CMD 0x66U /*!< reset enable */
#define GD25X512ME_RESET_MEMORY_CMD 0x99U /*!< reset memory */
/* register commands (SPI) */
#define GD25X512ME_READ_ID_CMD 0x9FU /* read identification */
#define GD25X512ME_READ_SERIAL_FLASH_DISCO_PARAM_CMD 0x5AU /* read serial flash discoverable parameter */
#define GD25X512ME_READ_UNIQUE_ID_CMD 0x4BU /* read unique identification */
#define GD25X512ME_READ_STATUS_REG_CMD 0x05U /* read status register */
#define GD25X512ME_READ_FLAG_STATUS_REG_CMD 0x70U /* read flag status register */
#define GD25X512ME_READ_EXT_ADDR_REG_CMD 0xC8U /* read extended address register */
#define GD25X512ME_READ_NONVOLATILE_CFG_REG_CMD 0xB5U /* read nonvolatile configuration register */
#define GD25X512ME_READ_VOLATILE_CFG_REG_CMD 0x85U /* read volatile configuration register */
#define GD25X512ME_WRITE_STATUS_REG_CMD 0x01U /* write status register */
#define GD25X512ME_WRITE_EXT_ADDR_REG_CMD 0xC5U /* write extended address register */
#define GD25X512ME_WRITE_ENABLE_VOLATILE_STATUS_CFG_CMD 0x50U /* write enable for volatile status register */
#define GD25X512ME_WRITE_NONVOLATILE_CFG_REG_CMD 0xB1U /* write nonvolatile configuration register */
#define GD25X512ME_WRITE_VOLATILE_CFG_REG_CMD 0x81U /* write volatile configuration register */
#define GD25X512ME_READ_SECURITY_REG_CMD 0x48U /* read security register */
#define GD25X512ME_PROG_SECURITY_REG_CMD 0x42U /* program security register */
#define GD25X512ME_ERASE_SECURITY_REG_CMD 0x44U /* erase Security register */
/* GD25X512ME registers */
/* status register */
#define GD25X512ME_SR_WIP 0x01U /* write in progress */
#define GD25X512ME_SR_WEL 0x02U /* write enable latch */
#define GD25X512ME_SR_PB 0x3CU /* block protected against program and erase operations */
/* flag status register */
#define GD25X512ME_FSR_ADS 0x01U /* current address mode */
#define GD25X512ME_FSR_PTE 0x02U /* protection error bit */
#define GD25X512ME_FSR_SUS2 0x04U /* program suspend */
#define GD25X512ME_FSR_PE 0x10U /* program error bit */
#define GD25X512ME_FSR_EE 0x20U /* erase error bit */
#define GD25X512ME_FSR_SUS1 0x40U /* erase suspend */
#define GD25X512ME_FSR_RY_BY 0x80U /* ready/busy */
/* extended address register */
#define GD25X512ME_EAR_A24 0x01U /* address bit 24 */
#define GD25X512ME_EAR_A25 0x02U /* address bit 25 */
#define GD25X512ME_EAR_SEC 0x80U /* single error correction bit */
/* configuration register */
/* address : 0x00000000 */
#define GD25X512ME_CFG_REG0_ADDR 0x00000000U /* CFG register address 0x00000000 */
#define GD25X512ME_CFG_SPI 0xFFU /* SPI */
#define GD25X512ME_CFG_SPI_WO 0xDFU /* SPI W/O */
#define GD25X512ME_CFG_OCTAL_DTR 0xE7U /* Octal DTR with */
#define GD25X512ME_CFG_OCTAL_DTR_WO 0xC7U /* Octal DTR W/O */
#define GD25X512ME_CFG_OCTAL_STR 0xB7U /* Octal STR with */
#define GD25X512ME_CFG_OCTAL_STR_WO 0x97U /* Octal STR W/O */
/* address : 0x00000001 */
#define GD25X512ME_CFG_REG1_ADDR 0x00000001U /* CFG register address 0x00000001 */
#define GD25X512ME_CFG_DUMMY_CYCLE(regval) (BITS(0,5) & (uint32_t)(regval)) /* 5~30 dummy cycle */
#define GD25X512ME_CFG_6_DUMMY_CYCLES 0x06U /* 6 dummy cycles */
#define GD25X512ME_CFG_8_DUMMY_CYCLES 0x08U /* 8 dummy cycles */
#define GD25X512ME_CFG_10_DUMMY_CYCLES 0x0AU /* 10 dummy cycles */
#define GD25X512ME_CFG_12_DUMMY_CYCLES 0x0CU /* 12 dummy cycles */
#define GD25X512ME_CFG_14_DUMMY_CYCLES 0x0EU /* 14 dummy cycles */
#define GD25X512ME_CFG_16_DUMMY_CYCLES 0x10U /* 16 dummy cycles(default) */
#define GD25X512ME_CFG_18_DUMMY_CYCLES 0x12U /* 18 dummy cycles */
#define GD25X512ME_CFG_20_DUMMY_CYCLES 0x14U /* 20 dummy cycles */
/* address : 0x00000002 */
#define GD25X512ME_CFG_REG2_ADDR 0x00000002U /* CFG register address 0x00000002 */
#define GD25X512ME_CFG_SECURITY_REG_UNLOCKED 0xF0U /* security register unlocked(default) */
#define GD25X512ME_CFG_SECURITY_REG_LOCKED 0xF1U /* security register locked */
#define GD25X512ME_CFG_SRP1_UNLOCKED 0x0FU /* SRP1 unlocked(default) */
#define GD25X512ME_CFG_SRP1_LOCKED 0x1FU /* SRP1 locked */
/* Address : 0x00000003 */
#define GD25X512ME_CFG_REG3_ADDR 0x00000003U /* CFG register address 0x00000003 */
#define GD25X512ME_CFG_50_OHM 0xFFU /* driver strength configuration 50 Ohm(default) */
#define GD25X512ME_CFG_35_OHM 0xFEU /* driver strength configuration 35 Ohm */
#define GD25X512ME_CFG_25_OHM 0xFDU /* driver strength configuration 25 Ohm */
#define GD25X512ME_CFG_18_OHM 0xFCU /* driver strength configuration 18 Ohm */
/* Address : 0x00000004 */
#define GD25X512ME_CFG_REG4_ADDR 0x00000004U /* CFG register address 0x00000004 */
#define GD25X512ME_CFG_REG4(regval) (BITS(0,1) & (uint32_t)(regval)) /* follow below table */
/* address : 0x00000005 */
#define GD25X512ME_CFG_REG5_ADDR 0x00000005U /* CFG register address 0x00000005 */
#define GD25X512ME_CFG_3_BYTE_ADDR 0xFFU /* 3-bytes address(default) */
#define GD25X512ME_CFG_4_BYTE_ADDR 0xFEU /* 4-bytes address */
/* Address : 0x00000006 */
#define GD25X512ME_CFG_REG6_ADDR 0x00000006U /* CFG register address 0x00000006 */
#define GD25X512ME_CFG_XIP_DISABLE 0xFFU /* XIP disable(default) */
#define GD25X512ME_CFG_XIP_ENABLE 0xFEU /*!< XIP enable */
/* Address : 0x00000007 */
#define GD25X512ME_CFG_REG7_ADDR 0x00000007U /*!< CFG register address 0x00000007 */
#define GD25X512ME_CFG_WRAP_DISABLE 0xFFU /*!< Wrap disable(default) */
#define GD25X512ME_CFG_WRAP_64_BYTE 0xFEU /*!< 64-Byte wrap */
#define GD25X512ME_CFG_WRAP_32_BYTE 0xFDU /*!< 32-Byte wrap */
#define GD25X512ME_CFG_WRAP_16_BYTE 0xFCU /*!< 16-Byte wrap */
#define DUMMY_CYCLES_READ_FAST 8U
#define DUMMY_CYCLES_READ_FAST_OCTAL 16U
#define DUMMY_CYCLES_READ_OCTAL_OUTPUT 8U
#define DUMMY_CYCLES_READ_OCTAL_IO 16U
#define DUMMY_CYCLES_READ_SR_OCTAL 8U
#define DUMMY_CYCLES_READ_FSR_OCTAL 8U
#define DUMMY_CYCLES_READ_EAR_OCTAL 8U
#define DUMMY_CYCLES_READ_NONVOLATILE_CFG 8U
#define DUMMY_CYCLES_READ_VOLATILE_CFG 8U
typedef enum {
SPI_MODE = 0, /* 1-1-1 commands, power on H/W default setting */
OSPI_MODE /* 8-8-8 commands */
} interface_mode;
typedef enum {
GD25X512ME_3BYTES_SIZE = 0, /* 3 Bytes address mode */
GD25X512ME_4BYTES_SIZE /* 4 Bytes address mode */
} addr_size;
typedef enum {
GD25X512ME_ERASE_4K = 0, /* 4K size sector erase */
GD25X512ME_ERASE_64K, /* 64K size block erase */
GD25X512ME_ERASE_CHIP /* whole bulk erase */
} erase_size;
/* initialize OSPI/OSPIM and GPIO */
void ospi_flash_init(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct);
/* read the flah id */
uint32_t ospi_flash_read_id(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode);
/* enable flash reset */
void ospi_flash_reset_enable(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode);
/* reset the flash */
void ospi_flash_reset_memory(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode);
/* enable flash write */
void ospi_flash_write_enbale(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode);
/* write flash volatile configuration register */
void ospi_flash_write_volatilecfg_register(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size,
uint32_t addr, uint8_t value);
/* polling WIP(Write In Progress) bit become to 0 */
void ospi_flash_autopolling_mem_ready(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode);
/* erase the specified block of the flash */
void ospi_flash_block_erase(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size, uint32_t addr,
erase_size block_size);
/* erase the the entire flash */
void ospi_flash_chip_erase(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode);
/* write data to the flash */
void ospi_flash_page_program(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size, uint8_t *pdata,
uint32_t addr, uint32_t data_size);
/* read data from the flash */
void ospi_flash_read(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size, uint8_t *pdata,
uint32_t addr, uint32_t data_size);
/* enable memory mapped mode */
void ospi_flash_memory_map_mode_enable(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size);
/* enable memory mapped mode with wrap */
void ospi_flash_memory_map_mode_wrap_enable(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct, interface_mode mode, addr_size addr_size);
#endif /* #define GD25X512ME_H */
2.3、main.c
#include "main.h"
#define GD25X512ME_ID 0xC8481AFF
#define OSPI_INTERFACE OSPI0
uint8_t txbuf[512];
uint8_t rxbuf[512];
ospi_parameter_struct ospi_struct = {0};
uint32_t flashid = 0;
void cache_enable(void);
int main(void)
{
cache_enable();
systick_config();
init_usart(115200);
printf("\n\rGD25X512ME read/write test!\n\r");
ospi_flash_init(OSPI_INTERFACE, &ospi_struct);
/* reset ospi flash */
ospi_flash_reset_enable(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
ospi_flash_reset_memory(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
/* read flash ID */
flashid = ospi_flash_read_id(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
if(GD25X512ME_ID == flashid)
{
printf("\n\rThe device ID is 0x%X\n\r", flashid);
printf("\r\nwrite data buf:\r\n");
for(uint16_t i=0;i<256;i++)
{
txbuf[i]=i;
printf("%02x ",txbuf[i]);
}
/* erase specified address */
ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
ospi_flash_write_enbale(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
//ospi_flash_block_erase(OSPI_INTERFACE, &ospi_struct, SPI_MODE, GD25X512ME_3BYTES_SIZE, FLASH_WRITE_ADDRESS_1, GD25X512ME_ERASE_4K);
ospi_flash_block_erase(OSPI_INTERFACE, &ospi_struct, SPI_MODE, GD25X512ME_3BYTES_SIZE, 0x000000, GD25X512ME_ERASE_4K);
ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
/* write data of tx_buffer1 to flash */
ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
ospi_flash_write_enbale(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
//ospi_flash_page_program(OSPI_INTERFACE, &ospi_struct, SPI_MODE, GD25X512ME_3BYTES_SIZE, tx_buffer1, FLASH_WRITE_ADDRESS_1, buffersize1);
ospi_flash_page_program(OSPI_INTERFACE, &ospi_struct, SPI_MODE, GD25X512ME_3BYTES_SIZE, txbuf, 0x000000, 256);
ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
/* read data from flash */
//ospi_flash_read(OSPI_INTERFACE, &ospi_struct, SPI_MODE, GD25X512ME_3BYTES_SIZE, rx_buffer1, FLASH_WRITE_ADDRESS_1, buffersize1);
ospi_flash_read(OSPI_INTERFACE, &ospi_struct, SPI_MODE, GD25X512ME_3BYTES_SIZE, rxbuf, 0x000000, 256);
printf("\r\nread data buf:\r\n");
for(uint16_t x=0; x<256;x++)
{
printf("%02x ",rxbuf[x]);
}
}
while(1)
{
}
}
void cache_enable(void)
{
/* enable i-cache */
SCB_EnableICache();
/* enable d-cache */
SCB_EnableDCache();
}
三、测试结果
下载程序后,串口输出内容
四、附件
本帖最后由 TL-LED 于 2024-6-12 21:52 编辑