STM32 QSPI接口驱动GD/W25Qxx配置简要
STM32 QSPI接口GD/W25Qxx配置简要
- 📝本篇会具体涉及介绍Winbond(华邦)和GD(兆易创新) NOR flash相关型号指令差异。由于网络上可以搜索到很多相关QSPI相关知识内容,不对QSPI通讯协议做深度解析。
- 🔖首先确保所使用的STM32型号,硬件上是否支持QSPI功能。
- 由于GD25QXX和对应的W25Qxx 芯片型号较多,芯片出厂,默认状态寄存器关键位存在差异,在没有进行状态寄存器关键位做配置的情况下。两者的驱动代码不能互为通用,代码上可以通过型号辨别,以及对状态寄存器关键位的使能配置,可以整合为一套通用的驱动代码。
- 🌿QSPI支持三种工作模式:间接模式、状态轮询模式和内存映射模式:
- 间接模式:使用QSPI寄存器执行全部操作。
- 状态轮询模式:周期性读取外部FLASH状态寄存器,当标志位置1时会产生中断(如擦除或烧写完成,产生中断)。
- 内存映射模式:外部FLASH映射到微控制器地址空间,从而系统将其视作内部存储器进行访问。
在间接模式下也可以切换为内存映射模式进行访问,切换过程需要重新对QSPI外设进行复位和重新初始化QSPI操作,代码操作比较麻烦,好处就是提升了读取访问速度。如果需要进行擦除或编程操作,还需要切换为间接模式下进行。
- QUADSPI 功能框图(见STM32H750参考手册)
图中BK2只有在双闪存模式下才需要。
-
4线SPI结构框图
-
🧲QSPI通讯序列
QUADSPI 通过命令与 FLASH 通信 每条命令包括指令、地址、交替字节、空指令和数据这 五个阶段 任一阶段均可跳过,但至少要包含指令、地址、交替字节或数据阶段之一。
nCS 在每条指令开始前下降,在每条指令完成后再次上升
对于通讯的整个过程,只需要留意3个状态:WIP(BUSY)用于查看擦除/编程操作是否正在进行、QE用于使能4线模式(Quad)和WREN写使能位其实和WIP位对应,该位决定接下来是否可以进行编程、擦写操作。
- 📜GD25Q64读写测试:
- 📜W25Q64读写测试:
- 基于QSPI片外flash下载算法实现的片外启动APP程序:
📗 NOR FLASH 存储器介绍
- 🍁Winbond(华邦)W25Q64存储器功能控制结构图
- GD(兆易创新)GD25Q64
- 内存空间结构: 一页(Page)256字节,4K(4096 字节)为一个扇区(Sector),16个扇区为1块(Block),容量为8M字节,共有128个块,2048 个扇区。
- 支持页编程。每页大小由256字节组成,每页的256字节用一次页编程指令即可完成。
- 擦除指令通用: 16页(1个扇区4K)、32K、64K、全片擦除操作。
两者常规操作指令互为通用。在QE位都配置为使能状态情况下,除了在读取厂商ID有差异外,读取数据功能函数通用。测试了基于W25QXX制作的片外QSPI下载算法文件都可以兼容GD25XX使用。(前提是下载算法中没有对应闪存厂商ID校验,芯片相关状态寄存器位没有写保护)
🌼Nor Flash操作流程
- 写入操作时:
写入操作前,必须先进行写使能位.
每个数据位只能由1改写为0,不能由0改写为1
写入数据前必须先擦除,擦除后,所有数据位变为1。.(删除目录实际上是填充0xff)
擦除必须按最小擦除单元进行(一个扇区:4kb)
连续写入多字节时,最多写入一页(256字节)的数据,超过页尾位置的数据,会回到页首覆盖写入
写入操作结束后,芯片进入忙状态,不响应新的读写操作
- 读取操作时:
直接调用读取时序,快速读取(Fast Read Quad I/O (EBh)),需要QE=1,可以不需要使能
Write Enable (WREN) (06H)
,没有页的限制,读取操作结束后不会进入忙状态,但不能在忙状态时读取.
📘Nor flash状态寄存器介绍
- 🌿winbond(华邦)W25QXX状态寄存器访问指令
- 📄具体状态寄存器位说明
📘 GD25QXX状态寄存器
- 🌿GD(兆易创新)GD25QXX状态寄存器总表:
🔰状态寄存器差异化说明
- 🌿QE位:该位属于非易失性(non-volatile),数据在断电后仍然能够保持的特性。一旦该位配置位1,将一直保持其状态,不会断电丢失。
- 🔖winbond(华邦)W25QXX,该位出厂默认状态是根据芯片具体型号决定该位默认状态是否为
1
- When the QE bit is set to a 0 state (factory default for part numbers with ordering options “
IM
”&“JM
”).- When the QE bit is set to a 1 (factory fixed default for part numbers with ordering options “
IQ
” & “JQ
”),
- 🔖GD(兆易创新)GD25Qxx,该位出厂默认状态是
0
,如需要使用QSPI 模式,必须先将该位配置为1才行。
- ✨QE位的使能,对于QSPI 4线Quad访问方式尤为重要。
📘指令介绍
-
🌿winbond(华邦)W25Q64指令:
-
🌿GD(兆易创新)GD25Q64指令集
🛠状态寄存器配置
- 🌿状态寄存器1,QE位配置流程说明
👉针对GD(兆易创新)GD25Q64,经测试,如需修改QE位,可以通过使用写状态寄存器1(0x01)命令,读取2个字节数据(S0-S7、S8-S16),再进行修改。
- 🔖个人测试时,如果单独写状态寄存器2的QE位,会写入不成功。
- QE位是否配置成功,可以通过读状态寄存器(0x35),进行查询。
-
Write Status Register (WRSR) (01H or 31H or 11H)
The Write Status Register (WRSR) command allows new values to be written to the Status Register. Before it can be accepted, a Write Enable (WREN) command must previously have been executed. After the Write Enable (WREN)
command has been decoded and executed, the device sets the Write Enable Latch (WEL).
The Write Status Register (WRSR) command has no effect on S15, S10, S1 and S0 of the Status Register. For command code of “01H” / “31H” / “11H”, the Status Register bits S7~S0 / S15~S8 / S23~S16 would be written. CS# must be driven high after the eighth bit of the data byte has been latched in. Otherwise, the Write Status Register (WRSR) command is not executed. As soon as CS# is driven high, the self-timed Write Status Register cycle (whose duration is tW) is initiated. While the Write Status Register cycle is in progress, the Status Register may still be read to check the value of the Write In Progress (WIP) bit. The Write In Progress (WIP) bit is 1 during the self-timed Write Status Register cycle, and is 0 when it is completed. When the cycle is completed, the Write Enable Latch (WEL) is reset.
The Write Status Register (WRSR) command allows the user to change the values of the Block Protect (BP4, BP3, BP2, BP1, and BP0) bits, to define the size of the area that is to be treated as read-only. The Write Status Register (WRSR) command also allows the user to set or reset the Status Register Protect (SRP1 and SRP0) bits in accordance with the Write Protect (WP#) signal. The Status Register Protect (SRP1 and SRP0) bits and Write Protect (WP#) signal allow the device to be put in the Hardware Protected Mode. The Write Status Register (WRSR) command is not executed once the Hardware Protected Mode is entered -
🧬 时序图:
-
🌿读状态寄存器代码实现:
int qspi_flash_read_status1(uint8_t *status) {//读状态寄存器1QSPI_CommandTypeDef command;command.InstructionMode = QSPI_INSTRUCTION_1_LINE;command.AddressSize = QSPI_ADDRESS_24_BITS;command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;command.DdrMode = QSPI_DDR_MODE_DISABLE;command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;command.Instruction = READ_STATUS_REG_CMD; //0x05,读取:S7-S0command.AddressMode = QSPI_ADDRESS_NONE;command.DataMode = QSPI_DATA_1_LINE;command.DummyCycles = 0;command.NbData = 1;//1个字节if (HAL_QSPI_Command(&hqspi, &command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) !=HAL_OK) {return HAL_ERROR;}if (HAL_QSPI_Receive(&hqspi, status, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) !=HAL_OK) {return HAL_ERROR;}return HAL_OK;
}int qspi_flash_read_status2(uint8_t *status) {读状态寄存器2QSPI_CommandTypeDef command= {0};command.InstructionMode = QSPI_INSTRUCTION_1_LINE;command.AddressSize = QSPI_ADDRESS_24_BITS;command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;command.DdrMode = QSPI_DDR_MODE_DISABLE;command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;command.Instruction = READ_STATUS2_REG_CMD;//0x35读取:S15-S8command.AddressMode = QSPI_ADDRESS_NONE;command.DataMode = QSPI_DATA_1_LINE;command.DummyCycles = 0;command.NbData = 1;if (HAL_QSPI_Command(&hqspi, &command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) !=HAL_OK) {return HAL_ERROR;}if (HAL_QSPI_Receive(&hqspi, status, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) !=HAL_OK) {return HAL_ERROR;}return HAL_OK;
}
- 🌿写状态寄存器代码实现:
int qspi_flash_write_status(uint8_t status1_val, uint8_t status2_val) {写状态寄存器1-2QSPI_CommandTypeDef command = {0};uint8_t buf[2];TxCplt = 0;qspi_flash_write_enable();command.InstructionMode = QSPI_INSTRUCTION_1_LINE;command.AddressSize = QSPI_ADDRESS_24_BITS;command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;command.DdrMode = QSPI_DDR_MODE_DISABLE;command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;command.SIOOMode = QSPI_SIOO_INST_ONLY_FIRST_CMD;command.Instruction = WRITE_STATUS_REG_CMD;command.DummyCycles = 0;command.AddressMode = QSPI_ADDRESS_NONE;command.DataMode = QSPI_DATA_1_LINE;command.NbData = 2;//2个字节(S0-S7,S7-S16)buf[0] = status1_val;buf[1] = status2_val;if (HAL_QSPI_Command(&hqspi, &command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) !=HAL_OK) {return HAL_ERROR;}if (HAL_QSPI_Transmit(&hqspi, buf, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) !=HAL_OK) {return HAL_ERROR;}if (qspi_flash_atuo_polling_mem_ready() != HAL_OK) {return HAL_ERROR;}return HAL_OK;
}
📘读数据操作
- 主要介绍4线QUAD操作指令。
- 🌿Quad I/O Fast Read (EBH)
Quad I/O快速读取命令可以通过在输入3字节地址(A23-A0)之后设置“连续读取模式”位(M7-0),从而进一步降低命令开销。如果“连续读模式”位(M5-4)=(1,0),则下一个四I/O快速读命令(在CS#升降之后)不需要EBH命令代码。如果“连续读模式”位(M5-4)=(1,0),下一个命令需要该命令代码,从而恢复正常操作。重置命令之前也可以用来在发出正常命令前重置(M7-0)。
⏰Dummy Cycle空指令周期
- 🌿在STM32H7参考手册上,QUADSPI 通信配置寄存器 (QUADSPI_CCR),指定 CLK 周期数范围一般: 0 - 31。
对于stm32H7一般在快速读取数据时,默认设定的是6个Dummy Cycle,适用的最大工作频率是104MHz.验证这个参数是否设定合理,验证方法,读写数据页内容多次进行查看,验证数据是否正确即可。如果该参数设置不对,读取的数据和写入的数据对应不上,或者会出全部是0、或者是一个其他的uint8_t
类型任意的固定或不固定的数值,也可能出现读取出来的数据和写入的数据和对应的地址错位的情况。
- Winbond(华邦)W25Q64:没有找到相关描述
- GD(兆易创新)GD25Q64
- 🌿读数据实现
/*** @brief 读NOR Flash* @note 从指定地址开始读取指定长度的数据* @param pbuf : 读取到数据保存的地址* @param pbuf : 指定开始读取的地址* @param datalen: 指定读取数据的字节数* @retval 无*/
void norflash_read(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
{QSPI_CommandTypeDef qspi_command_struct = {0};qspi_flash_write_enable();//使能QE位qspi_command_struct.InstructionMode = QSPI_INSTRUCTION_1_LINE;qspi_command_struct.Instruction = QUAD_INOUT_FAST_READ_4_BYTE_ADDR_CMD;//Quad I/O Fast Read EBHqspi_command_struct.AddressMode = QSPI_ADDRESS_4_LINES;qspi_command_struct.AddressSize = QSPI_ADDRESS_24_BITS;qspi_command_struct.Address = addr;qspi_command_struct.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;qspi_command_struct.DummyCycles = 6; //此处必须要有空闲等待时间,否则数据和地址会出现错位qspi_command_struct.DataMode = QSPI_DATA_4_LINES;qspi_command_struct.NbData = datalen;qspi_command_struct.DdrMode = QSPI_DDR_MODE_DISABLE;qspi_command_struct.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;qspi_command_struct.SIOOMode = QSPI_SIOO_INST_ONLY_FIRST_CMD;HAL_QSPI_Command(&hqspi, &qspi_command_struct, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);HAL_QSPI_Receive(&hqspi, pbuf, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);
}
📗擦除和写入操作
之所以将擦除和写入放在一起说明,是因为nor flash写操作前,需要先对当前要写入数据的地址扇区进行擦除操作,目的是为了将要写入的区域,保证为空(0xff),才能保证写入的数据的准确性。需要注意的是,最小擦除大小为扇区单位(4K)。
- 📝扇区擦除操作:
int qspi_flash_erase_sector(uint32_t address) {uint32_t EraseStartAddress = address;EraseStartAddress &=0x0FFFFFFF; //最大可寻址范围EraseStartAddress = EraseStartAddress - EraseStartAddress % 0x1000;//起始地址-扇区地址QSPI_CommandTypeDef command = {0};qspi_flash_write_enable();//写使能QE=1command.InstructionMode = QSPI_INSTRUCTION_1_LINE;command.AddressSize = QSPI_ADDRESS_24_BITS;//24位地址,可寻址范围小于或等于16MBcommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;command.DdrMode = QSPI_DDR_MODE_DISABLE;command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;command.Instruction = SUBSECTOR_ERASE_4_BYTE_ADDR_CMD;//擦除指令0x20command.AddressMode = QSPI_ADDRESS_1_LINE;command.Address = EraseStartAddress;command.DataMode = QSPI_DATA_NONE;command.DummyCycles = 0;if (HAL_QSPI_Command(&hqspi, &command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) !=HAL_OK) {return HAL_ERROR;}if (qspi_flash_atuo_polling_mem_ready() != HAL_OK) {return HAL_ERROR;}return HAL_OK;
}
- 📑写操作
/* 扇区缓存 */
static uint8_t g_norflash_buf[4096];/*** @brief 写NOR Flash* @note 在指定地址开始写入指定长度的数据,该函数带擦除操作* NOR Flash一般是:256个字节为一个Page,4096个字节为一个Sector,16个Sector为1个Block* 擦除的最小单位为Sector* @param pbuf : 待写入数据的起始地址* @param addr : 指定开始写入数据的地址* @param datalen: 指定写入数据的字节数* @retval 无*/
void norflash_write(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
{uint32_t secpos;uint16_t secoff;uint16_t secremain;uint16_t i;uint8_t *norflash_buf;norflash_buf = g_norflash_buf; /* 扇区缓存 */secpos = addr / 4096; /* 扇区索引 */secoff = addr % 4096; /* 写入起始地址在当前扇区的偏移量 */secremain = 4096 - secoff; /* 计算当扇区剩余的字节数 */if (datalen <= secremain) /* 不大于4096个字节 */{secremain = datalen;}while (1){norflash_read(norflash_buf, secpos * 4096, 4096); /* 读出当前整个扇区的内容,用于擦除扇区后恢复非写入区域的数据 */for (i=0; i<secremain; i++) /* 校验数据 */{if (norflash_buf[secoff + i] != 0xFF) /* 写入区域中有非0xFF的数据,就需要擦除 */{break;}}if (i < secremain) /* 需要擦除 */{
// /* 擦除整个扇区 */qspi_flash_erase_sector(secpos) ;for (i=0; i<secremain; i++) /* 将待写入的数据,先写入扇区缓存 */{norflash_buf[i + secoff] = pbuf[i];}norflash_write_nocheck(norflash_buf, secpos * 4096, 4096); /* 写入整个扇区 */}else /* 不需要擦除,可以直接写入 */{norflash_write_nocheck(pbuf, addr, secremain); /* 直接写扇区剩余的空间 */}if (datalen == secremain) /* 写入结束 */{break;}else /* 写入未结束 */{secpos++; /* 扇区索引增1 */secoff = 0; /* 扇区偏移位置为0 */pbuf += secremain; /* 偏移pbuf指针地址secremain个已写入的字节数 */addr += secremain; /* 偏移写入地址secremain个已写入的字节数 */datalen -= secremain; /* 计算剩余写入的字节数 */if (datalen > 4096) /* 剩余数据量超过4096,只能先写入一个扇区数据 */{secremain = 4096;}else /* 剩余数据量不超过4096,可一次性写入 */{secremain = datalen;}}}
}
📓复位nor flash操作
- GD25Q64复位使能和复位指令:Enable Reset (66H) and Reset (99H)
- 复位内容:Volatile settings:易失性设置,包括易失性状态寄存器位、写使能锁存状态(WEL)、编程/擦除暂停状态、读取参数设置(P7-P0)、连续读取模式位设置(M7-M0)和环绕位设置(W6-W4).
- 复位流程:执行复位命令序列包括:先发送使能复位命令(66H),然后将CS#拉高,再发送复位命令(99H),最后将CS#拉高。设备在接受复位命令后会花费大约tRST / tRST_E的时间来完成复位,在此期间不会接受任何其他命令。
- 🌿High-Z时间:
- STM32H750 ,时钟配置为400MHz,执行一个
__NOP( )
控制指令时间:1/400MHz=2.5ns,
-
🌿复位命令发出之后,到nor flash 执行完内部复位所需的时间:12ms
-
来自:
https://doc.embedfire.com/mcu/stm32/h743prov/hal/zh/latest/book/QSPI.html#qspi-7
**
* @brief 复位QSPI存储器。
* @param QSPIHandle: QSPI句柄
* @retval 无
*/
static uint8_t QSPI_ResetMemory()
{QSPI_CommandTypeDef s_command;/* 初始化复位使能命令 */s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;s_command.Instruction = RESET_ENABLE_CMD;//0x66s_command.AddressMode = QSPI_ADDRESS_NONE;s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;s_command.DataMode = QSPI_DATA_NONE;s_command.DummyCycles = 0;s_command.DdrMode = QSPI_DDR_MODE_DISABLE;s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;/* 发送命令 */if (HAL_QSPI_Command(&QSPIHandle, &s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {return QSPI_ERROR;}/* 发送复位存储器命令 0x99*/s_command.Instruction = RESET_MEMORY_CMD;if (HAL_QSPI_Command(&QSPIHandle, &s_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {return QSPI_ERROR;}/* 配置自动轮询模式等待存储器就绪 */if (QSPI_AutoPollingMemReady(HAL_QPSI_TIMEOUT_DEFAULT_VALUE) !=QSPI_OK) {return QSPI_ERROR;}return QSPI_OK;
}
📗QSPI外设引脚配置
- 🔖QSPI外设引脚配置不是固定的,可以根据实际使用情况,可以映射到任意支持的引脚上。
- 🔨QSPI引脚配置:需要将外设引脚的速度设置为非常高(Very HIGH)。
- 🔖需要注意CS引脚配置,不能使能
Fast Mode
.
void MX_QUADSPI_Init(void)
{/* USER CODE BEGIN QUADSPI_Init 0 *//* USER CODE END QUADSPI_Init 0 *//* USER CODE BEGIN QUADSPI_Init 1 *//* USER CODE END QUADSPI_Init 1 */hqspi.Instance = QUADSPI;hqspi.Init.ClockPrescaler = 1; //200MHz/(1+1)=100MHzhqspi.Init.FifoThreshold = 32; //最大支持32hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;hqspi.Init.FlashSize = 22;//8MB= 2^[FSIZE+1] =1<<23hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_6_CYCLE;//信号(CS)的高电平持续时间hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;/*时钟模式选择模式0,nCS为高电平(片选释放),传输数据CLK保持低电平*/hqspi.Init.FlashID = QSPI_FLASH_ID_1;hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;if (HAL_QSPI_Init(&hqspi) != HAL_OK){Error_Handler();}/* USER CODE BEGIN QUADSPI_Init 2 *//* USER CODE END QUADSPI_Init 2 */}
-
有关信号时间参数信息:
-
📝QSPI初始化配置:(参考野火内容介绍:
https://doc.embedfire.com/mcu/stm32/h743prov/hal/zh/latest/book/QSPI.html#qspi-7
)
/**
* @brief 初始化QSPI存储器
* @retval QSPI存储器状态
*/
uint8_t BSP_QSPI_Init(void)
{QSPI_CommandTypeDef s_command;uint8_t value = W25Q256JV_FSR_QE;//0X02/* QSPI存储器复位 */if (QSPI_ResetMemory() != QSPI_OK) {return QSPI_NOT_SUPPORTED;}/* 使能写操作 */if (QSPI_WriteEnable() != QSPI_OK) {return QSPI_ERROR;}/* 设置四路使能的状态寄存器,使能四通道IO2和IO3引脚 */s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;s_command.Instruction = WRITE_STATUS_REG2_CMD;s_command.AddressMode = QSPI_ADDRESS_NONE;s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;s_command.DataMode = QSPI_DATA_1_LINE;s_command.DummyCycles = 0;s_command.NbData = 1;s_command.DdrMode = QSPI_DDR_MODE_DISABLE;s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;/* 配置命令 */if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {return QSPI_ERROR;}/* 传输数据 */if (HAL_QSPI_Transmit(&QSPIHandle, &value, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {return QSPI_ERROR;}/* 自动轮询模式等待存储器就绪 */if (QSPI_AutoPollingMemReady(W25Q256JV_SUBSECTOR_ERASE_MAX_TIME) != QSPI_OK) {return QSPI_ERROR;}/* 配置地址模式为 4 字节 */if (QSPI_Addr_Mode_Init() != QSPI_OK) {return QSPI_ERROR;}return QSPI_OK;
}
- 🍕相关参考和资料推荐
- 📌安富莱_STM32-V7:
https://www.armbbs.cn/forum.php?mod=viewthread&tid=91590&highlight=STM32-V7
- 📍QSPI驱动例程可以参考:正点原子STM32H750中的相关例程:
http://47.111.11.73/docs/boards/stm32/zdyz_stm32h750_polaris.html
- 🎈或者参考野火版的开发板资料:
https://gitee.com/Embedfire-stm32h7-pro/ebf_stm32h743_pro_code_v
- 🥕间接模式切换内存映射模式项目参考:
https://github.com/ziancube/GD25Qxx-Stm32h747
相关文章:

STM32 QSPI接口驱动GD/W25Qxx配置简要
STM32 QSPI接口GD/W25Qxx配置简要 📝本篇会具体涉及介绍Winbond(华邦)和GD(兆易创新) NOR flash相关型号指令差异。由于网络上可以搜索到很多相关QSPI相关知识内容,不对QSPI通讯协议做深度解析。 🔖首先确保所使用的ST…...

UCI-HAR数据集深度剖析:训练仿真与可视化解读
在本篇文章中,我们将深入探讨如何使用Python对UCI人类活动识别(HAR)数据集进行分割和预处理,以及运用模型网络CNN对数据集进行训练仿真和可视化解读。 一、UCI-HAR数据集分析及介绍 UCI-HAR数据集是一个公开的数据集,…...

牛客SQL练习详解 06:综合练习
牛客SQL练习详解 06:综合练习 SQL34 统计复旦用户8月练题情况SQL35 浙大不同难度题目的正确率SQL39 21年8月份练题总数 叮嘟!这里是小啊呜的学习课程资料整理。好记性不如烂笔头,今天也是努力进步的一天。一起加油进阶吧! SQL34 统…...

k8s apiserver高可用方案
目前官方推荐有 2 种方式部署k8s apiserver 高可用 keepalived and haproxy 部署有2种方式,一种是systemd管理的,另一种是pod形式,使用那种可以根据实际情况选择 服务部署 systemd方式 可以通过包管理工具安装,正常启动之后&…...

服务器数据恢复—硬盘坏扇区导致Linux系统服务器数据丢失的数据恢复案例
服务器数据恢复环境: 一台linux操作系统网站服务器,该服务器上部署了几十个网站,使用一块SATA硬盘。 服务器故障&原因: 服务器在工作过程中突然宕机。管理员尝试重新启动服务器失败,于是将服务器上的硬盘拆下检测…...

【多线程】多线程(12):多线程环境下使用哈希表
【多线程环境下使用哈希表(重点掌握)】 可以使用类:“ConcurrentHashMap” ★ConcurrentHashMap对比HashMap和Hashtable的优化点 1.优化了锁的粒度【最核心】 //Hashtable的加锁,就是直接给put,get等方法加上synch…...

轻量服务器和云服务器ecs哪个好用一些?
轻量服务器和云服务器ecs哪个好用一些?轻量服务器与云服务器ECS在多方面存在显著差异,对于需要高性能计算和大规模数据处理的用户来说,ECS可能是更好的选择;而对于预算有限且需求较为简单的用户来说,轻量服务器可能更为…...

【交通标志识别系统】Python+卷积神经网络算法+人工智能+深度学习+机器学习+算法模型
一、介绍 交通标志识别系统。本系统使用Python作为主要编程语言,在交通标志图像识别功能实现中,基于TensorFlow搭建卷积神经网络算法模型,通过对收集到的58种常见的交通标志图像作为数据集,进行迭代训练最后得到一个识别精度较高…...

特种设备作业叉车司机试题附答案
1.发生事故要本着"( )不放过"的原则,查明原因、分清责任、严肃处理。 A.三 B.四 C.五 答案:B 2.柴油发动机在压缩行程终了时气体的温度和压力都比汽油机( )。 A.低 B.高 C.相同 答案:B 3.柴油发动机的压缩比比汽…...

【Nginx系列】Nginx启动失败
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

2024/10/12 计组大题专训
2018: 2019: 2020: 2021:...

2024年腾讯外包面试题(微创公司)
笔试: 1、判断异步执行顺序 console.log(1);setTimeout(()>{Promise.resolve().then(()>{console.log(2);})console.log(3);},0);new Promise ((resolve)>{for(let i0; i<1000;i ){if(i1000){resolve();}}console.log(4);}).then(()>{console.log(5…...

nginx运行时报:No rule to make target ‘build‘, needed by ‘deault‘.Stop
项目场景: 部署前端项目,将打好的前端包,放到服务器上,运行nginx执行,结果nginx运行报错。 问题描述 nginx运行报以下错误: No rule to make target ‘build‘, needed by ‘deault‘.Stop原因分析&…...

dvwa:暴力破解、命令注入、csrf全难度详解
暴力破解 easy模式 hydra -L /usr/share/wordlists/SecLists-master/Usernames/top-usernames-shortlist.txt -P /usr/share/wordlists/SecLists-master/Passwords/500-worst-passwords.txt 192.168.72.1 http-get-form "/dvwa/vulnerabilities/brute/:username^USER^&…...

Java-学生管理系统[初阶]
这次我们来尝试使用Java实现一下"学生管理系统",顾名思义,就是实现一个能用来管理学生各种数据的系统。在后续学习中我们将对"学生管理系统"进行两种实现: 📚 学生管理系统[初阶](不带模拟登录系统) &#…...

微信小程序 详情图片预览功能实现详解
详情图片预览功能实现详解 在开发微信小程序时,我们经常需要实现点击商品图片进行全屏预览的功能。这不仅提升了用户体验,还允许用户进行保存图片、发送给朋友等操作。本文将详细介绍如何实现这一功能。 思路分析 当用户在商品详情页点击图片时&#…...

LeetCode 48 Rotate Image 解题思路和python代码
题目: You are given an n x n 2D matrix representing an image, rotate the image by 90 degrees (clockwise). You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and …...

余承东直播论道智能驾驶:激光雷达不可或缺,华为ADS 3.0引领安全创新
华为余承东:激光雷达,智能驾驶安全性的关键 9月29日,华为消费者业务集团CEO余承东在一场引人注目的直播中,与知名主持人马东就智能驾驶技术的最新进展进行了深入交流。在这场直播中,余承东针对激光雷达在智能驾驶中的必要性问题,发表了明确且深刻的观点,引发了业界和公众…...

51WORLD携手浙江科技大学,打造智慧校园新标杆
当前,国家教育数字化战略行动扎实推进,高等教育数字化转型步伐加快。 紧抓数字教育发展战略机遇,浙江科技大学联合51WORLD、正方软件股份有限公司(简称:正方软件),共同研发打造浙科大孪生数智校…...

SAP SD学习笔记09 - 受注传票中的不完全Log 和 Business Partner(取引先机能)
好久没写SD了,今天继续写。 上一章讲了SD的如下知识 - SD的售前的流程(引合和見積(询价和报价)) - 数据流的概念,主要就是后传票可以参照前传票,以实现数据的流动,减少输入 - Co…...

【ROS2】里程计(odometry)数据计算、发布
1、里程计消息 1.1 Odometry消息 消息描述:nav_msgs::msg::Odometry 是ROS2中用发布里程计信息的消息,包括:线速度、角速度、位置和朝向 消息路径:/opt/ros/humble/share/nav_msgs/msg/Odometry.msg 消息内容: # 包含父ID std_msgs/Header header# 子ID,即姿势所在的坐…...

AcWing 187 导弹防御系统 暴搜
代码 #include <bits/stdc.h> #define int long long using namespace std;const int N 200010, mod 1e9 7;int n, m, k, x, y, z, ans, t, depth; int w[N], f[N]; int up[N], down[N];bool dfs(int depth, int u, int su, int sd) {if (su sd > depth) return …...

SpringSecurity(三)——自定义优化器
在SpringSecurity中,如果我们在认证或者授权的过程中出现了异常会被ExceptionTranslationFilter捕 获到。在ExceptionTranslationFilter中会去判断是认证失败还是授权失败出现的异常。 一、自定义验证异常类 创建exception包,在exception包下创建自定义…...

STM32通用定时器TIM3的PWM输出实验配置步骤
通用定时器 PWM 输出实验 本小节我们来学习使用通用定时器的 PWM 输出模式。 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。我们可以让定时…...

device tree 预研
linux kernel 引入 dts 的背景 http://www.wowotech.net/linux_kenrel/why-dt.html 什么是 device tree device tree 是一种描述硬件资源的数据结构。device tree 可以描述的信息包括 cpu 的数量和类别、内存基地址和大小、clock 控制器和 clock 使用情况、外设基地址以及…...

英伟达股价分析:英伟达股价能否上涨到150美元,接下来该如何操作?
来源:猛兽财经 作者:猛兽财经 猛兽财经核心观点: (1)华尔街投行Oppenheimer已将英伟达的目标价上调到了150美元。 (2)产品方面的最新进展和合作伙伴关系进一步提升了英伟达的市场地位。 &…...

Rust 快速入门(一)
Rust安装信息解释 cargo:Rust的编译管理器、包管理器、通用工具。可以用Cargo启动新的项目,构建和运行程序,并管理代码所依赖的所有外部库。 Rustc:Rust的编译器。通常Cargo会替我们调用此编译器。 Rustdoc:是Rust的…...

java 程序在服务器出现时区错误问题(使用Date,LocalDateTime,ZonedDateTime都不正确)
排查 查询系统时区信息 timedatectl status打印java的时区信息 import java.util.TimeZone;public class CheckTimeZone {public static void main(String[] args) {TimeZone defaultTimeZone TimeZone.getDefault();System.out.println("Default TimeZone ID: "…...

Kotlin 语言的协程是什么?
目录 1. 什么是协程 2. 协程的基本概念 3. 如何使用协程 3.1. 引入依赖 3.2. 启动协程 3.3. 使用挂起函数 4. 结构化并发 5. 处理异常 6. 总结 Kotlin 的协程是一种轻量级的线程,可以用于简化异步编程。它允许你以顺序的方式编写异步代码,从而提…...

uniapp 游戏 - 使用 uniapp 实现的扫雷游戏
0. 思路 1. 效果图 2. 游戏规则 扫雷的规则很简单。盘面上有许多方格,方格中随机分布着一些雷。你的目标是避开雷,打开其他所有格子。一个非雷格中的数字表示其相邻 8 格子中的雷数,你可以利用这个信息推导出安全格和雷的位置。你可以用右键在你认为是雷的地方插旗(称为标…...