You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
489 lines
16 KiB
489 lines
16 KiB
1 week ago
|
/*
|
||
|
* bsp_quadspi_W25Q128.c
|
||
|
*
|
||
|
* Created on: Apr 25, 2021
|
||
|
* Author: Administrator
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
#include <bsp_qspi_w25q128.h>
|
||
|
#include "quadspi.h"
|
||
|
|
||
|
/* 仅限本文件使用的函数 */
|
||
|
static void QSPI_W25Qx_Write_Enable(QSPI_HandleTypeDef *hqspi);
|
||
|
static uint8_t QSPI_W25Qx_AutoPollingMemRead(uint32_t Timeout);
|
||
|
static void QSPI_W25Qx_Enter(QSPI_HandleTypeDef *hqspi);
|
||
|
static void QSPI_W25Qx_Exit(QSPI_HandleTypeDef *hqspi);
|
||
|
|
||
|
/**
|
||
|
* 函数功能: 读取Flash状态并等待操作结束
|
||
|
* 输入参数: Timeout:等待时间
|
||
|
*
|
||
|
* 返回值: Flash的状态
|
||
|
* 说明:
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
static uint8_t QSPI_W25Qx_AutoPollingMemRead(uint32_t Timeout)
|
||
|
{
|
||
|
QSPI_CommandTypeDef s_command={0};
|
||
|
QSPI_AutoPollingTypeDef s_config={0};
|
||
|
|
||
|
/* 基本配置 */
|
||
|
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令
|
||
|
s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址
|
||
|
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节
|
||
|
s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式
|
||
|
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟
|
||
|
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令
|
||
|
|
||
|
/* 配置自动轮询模式 */
|
||
|
s_command.Instruction = READ_STATUS_REG1_CMD; //读取状态寄存器
|
||
|
s_command.AddressMode = QSPI_ADDRESS_NONE; //没有地址
|
||
|
s_command.DataMode = QSPI_DATA_1_LINE; //1线数据
|
||
|
s_command.DummyCycles = 0; //无空周期
|
||
|
|
||
|
/* 配置自动轮询寄存器(不断查询状态寄存器bit0,等待其为0) */
|
||
|
s_config.Match = 0x00; //等待其为0
|
||
|
s_config.Mask = W25Q128FV_FSR_BUSY; //状态寄存器bit0
|
||
|
s_config.MatchMode = QSPI_MATCH_MODE_AND; //逻辑与
|
||
|
s_config.StatusBytesSize = 1;
|
||
|
s_config.Interval = 0x10;
|
||
|
s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE;
|
||
|
|
||
|
/* 自动轮询模式等待编程结束 */
|
||
|
if(HAL_QSPI_AutoPolling(&hqspi,&s_command,&s_config,Timeout) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
return FLASH_OK;
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 函数功能: 读取外部FLASH的ID
|
||
|
* 输入参数: 无
|
||
|
*
|
||
|
* 返回值: uint32_t
|
||
|
* 说明:
|
||
|
* 1、使用SPI模式的指令
|
||
|
*
|
||
|
*/
|
||
|
uint32_t QSPI_W25Qx_ReadID(void)
|
||
|
{
|
||
|
uint32_t uiID;
|
||
|
|
||
|
QSPI_CommandTypeDef s_command = {0};
|
||
|
uint8_t buf[3];
|
||
|
|
||
|
/* 基本配置 */
|
||
|
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令
|
||
|
s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址
|
||
|
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节
|
||
|
s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式
|
||
|
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟
|
||
|
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令
|
||
|
|
||
|
/* 读取JEDEC ID */
|
||
|
s_command.Instruction = READ_JEDEC_ID_CMD; //读取ID命令: 0x9F
|
||
|
s_command.AddressMode = QSPI_ADDRESS_NONE; //没有地址
|
||
|
s_command.DataMode = QSPI_DATA_1_LINE; //1线数据
|
||
|
s_command.DummyCycles = 0; //无空周期
|
||
|
s_command.NbData = 3; //读取三个数据
|
||
|
|
||
|
/* 发送指令 */
|
||
|
if(HAL_QSPI_Command(&hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
/* 启动接收 */
|
||
|
if(HAL_QSPI_Receive(&hqspi,buf,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
uiID = (buf[0] << 16) | (buf[1] << 8) | buf[2];
|
||
|
|
||
|
return uiID;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 函数功能: 外部FLASH写使能
|
||
|
* 输入参数: hqspi QSPI_HandleTypeDef句柄
|
||
|
*
|
||
|
* 返回值: 无
|
||
|
* 说明:
|
||
|
* 1、使用SPI模式的指令
|
||
|
*
|
||
|
*/
|
||
|
static void QSPI_W25Qx_Write_Enable(QSPI_HandleTypeDef *hqspi)
|
||
|
{
|
||
|
QSPI_CommandTypeDef s_command = {0};
|
||
|
QSPI_AutoPollingTypeDef s_config={0};
|
||
|
|
||
|
/* 基本配置 */
|
||
|
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令
|
||
|
//s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址
|
||
|
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节
|
||
|
s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式
|
||
|
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟
|
||
|
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令
|
||
|
|
||
|
/* 写入使能配置 */
|
||
|
s_command.Instruction = WRITE_ENABLE_CMD; //写使能命令
|
||
|
s_command.AddressMode = QSPI_ADDRESS_NONE; //没有地址
|
||
|
s_command.DataMode = QSPI_DATA_NONE; //没有数据
|
||
|
s_command.DummyCycles = 0; //无空周期
|
||
|
s_command.NbData = 0; //空数据
|
||
|
|
||
|
/* 发送指令 */
|
||
|
if(HAL_QSPI_Command(hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
/* 配置自动轮询模式等待操作完成 */
|
||
|
s_config.Match = W25Q128FV_FSR_WREN;
|
||
|
s_config.Mask = W25Q128FV_FSR_WREN;
|
||
|
s_config.MatchMode = QSPI_MATCH_MODE_AND;
|
||
|
s_config.StatusBytesSize = 1;
|
||
|
s_config.Interval = 0x10;
|
||
|
s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE;
|
||
|
|
||
|
s_command.Instruction = READ_STATUS_REG1_CMD;
|
||
|
s_command.DataMode = QSPI_DATA_1_LINE;
|
||
|
s_command.NbData = 1;
|
||
|
|
||
|
if(HAL_QSPI_AutoPolling(hqspi,&s_command,&s_config,HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 函数功能: 擦除外部FLASH的扇区(大小:4KB)
|
||
|
* 输入参数: _uiSectorAddr: 扇区地址,以4KB为单位的地址,比如0,4096,8192等
|
||
|
*
|
||
|
* 返回值: 无
|
||
|
* 说明:
|
||
|
* 1、
|
||
|
*
|
||
|
*/
|
||
|
void QSPI_W25Qx_EraseSector(uint32_t _SectorAddr)
|
||
|
{
|
||
|
QSPI_CommandTypeDef s_command = {0};
|
||
|
|
||
|
/* 写使能 */
|
||
|
QSPI_W25Qx_Write_Enable(&hqspi);
|
||
|
|
||
|
/* 基本配置 */
|
||
|
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令
|
||
|
s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址
|
||
|
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节
|
||
|
s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式
|
||
|
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟
|
||
|
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令
|
||
|
|
||
|
/* 擦除扇区配置 */
|
||
|
s_command.Instruction = SECTOR_ERASE_CMD; //扇区擦除指令
|
||
|
s_command.AddressMode = QSPI_ADDRESS_1_LINE; //1线地址方式
|
||
|
s_command.DataMode = QSPI_DATA_NONE; //没有数据
|
||
|
s_command.Address = _SectorAddr; //扇区的首地址,保证是4KB整数倍
|
||
|
s_command.DummyCycles = 0; //无空周期
|
||
|
|
||
|
/* 发送指令 */
|
||
|
if(HAL_QSPI_Command(&hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
/* 自动轮询模式等待编程结束 */
|
||
|
if(QSPI_W25Qx_AutoPollingMemRead(W25Q128FV_SUBSECTOR_ERASE_MAX_TIME) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 函数功能: 页编程,通过QSPI将数据写入外部FALSH
|
||
|
* 输入参数: _pBuf: 需要存入数据的指针
|
||
|
* _write_Addr: 目标区域首地址,即页首地址,比如0,256,512等。
|
||
|
* _write_Size: 数据个数,不能超过页的大小,可以填入(1 ~ 256)
|
||
|
* 返回值: 无
|
||
|
* 说明:
|
||
|
* 1、华邦的W25Q128FV仅仅支持SPI模式写入
|
||
|
*/
|
||
|
uint8_t QSPI_W25Qx_Write_Buffer(uint8_t *_pBuf,uint32_t _write_Addr,uint16_t _write_Size)
|
||
|
{
|
||
|
QSPI_CommandTypeDef s_command = {0};
|
||
|
|
||
|
/* 防止写入的大小超过256字节 */
|
||
|
if(_write_Size > W25Q128FV_PAGE_SIZE)
|
||
|
{
|
||
|
/* 进入断言,提示错误 */
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
QSPI_W25Qx_Write_Enable(&hqspi); //写使能
|
||
|
|
||
|
/* 基本配置 */
|
||
|
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令
|
||
|
s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址
|
||
|
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节
|
||
|
s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式
|
||
|
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟
|
||
|
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令
|
||
|
|
||
|
/*写入序列配置 */
|
||
|
s_command.Instruction = QUAD_INPUT_PAGE_PROG_CMD; //24位四线快速写入指令
|
||
|
s_command.AddressMode = QSPI_ADDRESS_1_LINE; //1线地址方式
|
||
|
s_command.DataMode = QSPI_DATA_4_LINES; //4线数据方式
|
||
|
s_command.Address = _write_Addr; //写入数据的地址
|
||
|
s_command.NbData = _write_Size; //写入数据的大小
|
||
|
s_command.DummyCycles = 0; //无空周期
|
||
|
|
||
|
/* 发送指令 */
|
||
|
if(HAL_QSPI_Command(&hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
/* 启动传输 */
|
||
|
if(HAL_QSPI_Transmit(&hqspi,_pBuf,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
/* 自动轮询模式等待编程结束 */
|
||
|
if(QSPI_W25Qx_AutoPollingMemRead(W25Q128FV_SUBSECTOR_ERASE_MAX_TIME) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 函数功能: 外部FLASH芯片进入QSPI模式
|
||
|
* 输入参数: *hqspi: qspi句柄
|
||
|
*
|
||
|
* 返回值: 无
|
||
|
* 说明:
|
||
|
*
|
||
|
*/
|
||
|
static void QSPI_W25Qx_Enter(QSPI_HandleTypeDef *hqspi)
|
||
|
{
|
||
|
QSPI_CommandTypeDef s_command = {0};
|
||
|
/* 配置FLASH进入QPSI模式 */
|
||
|
/* 基本配置 */
|
||
|
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令
|
||
|
s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址
|
||
|
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节
|
||
|
s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式
|
||
|
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟
|
||
|
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令
|
||
|
|
||
|
/* 写入序列配置 */
|
||
|
s_command.Instruction = ENTER_QPI_MODE_CMD; //进入QSPI模式
|
||
|
s_command.AddressMode = QSPI_ADDRESS_NONE; //无地址方式
|
||
|
s_command.DataMode = QSPI_DATA_NONE; //无数据方式
|
||
|
s_command.DummyCycles = 0; //0空闲状态周期
|
||
|
|
||
|
/* 发送指令 */
|
||
|
if(HAL_QSPI_Command(hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 函数功能: 外部FLASH芯片退出QSPI模式
|
||
|
* 输入参数: *hqspi: qspi句柄
|
||
|
*
|
||
|
* 返回值: 无
|
||
|
* 说明:
|
||
|
*
|
||
|
*/
|
||
|
static void QSPI_W25Qx_Exit(QSPI_HandleTypeDef *hqspi)
|
||
|
{
|
||
|
QSPI_CommandTypeDef s_command = {0};
|
||
|
|
||
|
/* 基本配置 */
|
||
|
s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; //4线方式发送指令
|
||
|
s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址
|
||
|
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节
|
||
|
s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式
|
||
|
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟
|
||
|
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令
|
||
|
|
||
|
/* 写入序列配置 */
|
||
|
s_command.Instruction = EXIT_QPI_MODE_CMD; //进入QSPI模式
|
||
|
s_command.AddressMode = QSPI_ADDRESS_NONE; //无地址方式
|
||
|
s_command.DataMode = QSPI_DATA_NONE; //无数据方式
|
||
|
s_command.DummyCycles = 0; //0空闲状态周期
|
||
|
|
||
|
/* 发送指令 */
|
||
|
if(HAL_QSPI_Command(hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 函数功能: 连续读取若干字节,字节的个数不能超出芯片容量
|
||
|
* 输入参数: _pBuf: 读取数据的存放地址
|
||
|
* _read_Addr: 起始的地址
|
||
|
* _read_Size: 数据个数,可以大于W25Q128FV_PAGE_SIZE,但不能超出芯片总容量
|
||
|
* 返回值: 无
|
||
|
* 说明:
|
||
|
* 1、从SPI模式切换到QSPI模式,读取完毕后切换回SPI模式(其他函数仅仅支持SPI模式)。
|
||
|
*/
|
||
|
void QSPI_W25Qx_Read_Buffer(uint8_t *_pBuf,uint32_t _read_Addr,uint32_t _read_Size)
|
||
|
{
|
||
|
QSPI_CommandTypeDef s_command = {0};
|
||
|
|
||
|
/* 进入QSPI模式 */
|
||
|
QSPI_W25Qx_Enter(&hqspi);
|
||
|
|
||
|
/* 开始从FLASH读取数据 */
|
||
|
/* 基本配置 */
|
||
|
s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; //1线方式发送指令
|
||
|
s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址
|
||
|
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节
|
||
|
s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式
|
||
|
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟
|
||
|
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令
|
||
|
|
||
|
/*读取序列配置 */
|
||
|
s_command.Instruction = QUAD_INOUT_FAST_READ_CMD; //24位四线快速写入指令
|
||
|
s_command.AddressMode = QSPI_ADDRESS_4_LINES; //4线地址方式
|
||
|
s_command.DataMode = QSPI_DATA_4_LINES; //4线数据方式
|
||
|
s_command.Address = _read_Addr; //写入数据的地址
|
||
|
s_command.NbData = _read_Size; //写入数据的大小
|
||
|
s_command.DummyCycles = 2; //两个空闲状态周期(4个时钟周期),结合时序理解
|
||
|
|
||
|
/* 发送指令 */
|
||
|
if(HAL_QSPI_Command(&hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
/* 读取数据 */
|
||
|
if(HAL_QSPI_Receive(&hqspi,_pBuf,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
/* 退出QSPI模式 */
|
||
|
QSPI_W25Qx_Exit(&hqspi);
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 函数功能: 复位外部Flash
|
||
|
* 输入参数: 无
|
||
|
*
|
||
|
* 返回值: void
|
||
|
* 说明:
|
||
|
*
|
||
|
*/
|
||
|
void QSPI_W25Qx_Reset_Memory()
|
||
|
{
|
||
|
QSPI_CommandTypeDef s_command = {0};
|
||
|
|
||
|
/* 基本配置 */
|
||
|
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; //1线方式发送指令
|
||
|
s_command.AddressSize = QSPI_ADDRESS_24_BITS; //24位地址
|
||
|
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节
|
||
|
s_command.DdrMode = QSPI_DDR_MODE_DISABLE; //W25Q128FV不支持DDR模式
|
||
|
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR模式,数据输出延迟
|
||
|
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次传输都发指令
|
||
|
|
||
|
/* 复位使能W25x */
|
||
|
s_command.Instruction = RESET_ENABLE_CMD; //复位使能命令
|
||
|
s_command.AddressMode = QSPI_ADDRESS_NONE; //没有地址
|
||
|
s_command.DataMode = QSPI_DATA_NONE; //没有数据
|
||
|
s_command.DummyCycles = 0; //无空周期
|
||
|
|
||
|
/* 发送复位使能命令 */
|
||
|
if(HAL_QSPI_Command(&hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
/* 发送复位命令 */
|
||
|
s_command.Instruction = RESET_MEMORY_CMD; //复位命令
|
||
|
/* 发送复位使能命令 */
|
||
|
if(HAL_QSPI_Command(&hqspi,&s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
/* 自动轮询模式等待等待完成 */
|
||
|
if(QSPI_W25Qx_AutoPollingMemRead(HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
|
||
|
{
|
||
|
user_Assert(__FILE__,__LINE__);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* 函数功能: 检查代码异常,打印出异常的位置(文件名与行号)
|
||
|
* 输入参数: file: 源代码文件名称。关键字__FILE__表示源代码文件名。
|
||
|
* line: 代码行号,关键字__LINE__表示源代码行号
|
||
|
* 返回值: void
|
||
|
|
||
|
* 说明:
|
||
|
* 1、在需要断言的地方直接调用user_Assert(__FILE__,__LINE__);
|
||
|
*/
|
||
|
void user_Assert(char *file,uint32_t line)
|
||
|
{
|
||
|
printf("Wrong parameters value: file %s on line %d\r\n",file, (unsigned int)line);
|
||
|
|
||
|
/* 这是一个死循环,断言失败时程序会卡此处死机,以便于用户差错 */
|
||
|
if(line == 0)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
while(1)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* 函数功能: 读取Flash状态并等待操作结束
|
||
|
* 输入参数: Timeout:等待时间
|
||
|
*
|
||
|
* 返回值: Flash的状态
|
||
|
* 说明:
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
void QSPI_W25Qx_EraseDownLoadFlash()
|
||
|
{
|
||
|
int i =0;
|
||
|
int count=CODE_FLASH_STORAGE_SIZE/4/1024;
|
||
|
for(i=0;i<=count;i++)
|
||
|
{
|
||
|
QSPI_W25Qx_EraseSector(i*4*1024);
|
||
|
// HAL_Delay(10);
|
||
|
}
|
||
|
i=10;
|
||
|
}
|