彻底拿下QSPI双闪存W25Q256| STM32H750| QSPI 双FLASH |cubeIDE |下载算法(一)

Part1开发平台

野火STM32H750Pro开发板,QSPI双片W25Q256,原理图如下
在这里插入图片描述
参考资料:百度搜索datasheet5,进入该网站搜芯片型号W25Q256即可获取PDF。简要说明一下就是单个W25Q256使用按页(256字节一页)编程写入,按扇区(4KB)、块(64KB或32KB)、或整片来进行擦除。

Part2 搭建工程

首先按照这篇博客中的方法搭建工程:

(66条消息) stm32cubemx无法生成工程_工程师笔记 | 通过 STM32CubeMX制作外部Flash的烧写驱动 (.stdlr)…_瓷tun的博客-CSDN博客

这里我的工程结构与该文章保持一致,但是由于用的开发板和博主的不一样,FLASH芯片、模式也不一样,因此驱动那一块我还是按照开发板的例程来移植,不过main函数的执行流程还是可以借鉴的。

QSPI驱动可自行移步野火官方资料下载中心获取

Part3 调试过程中出现的问题——FLASH读写失败

第一次测试,main函数代码执行步骤为:

1.数组编号 0~FF的循环

2.擦除块,并写入

3.配置为直接映射

4.打开Memory监测

监测结果如下,0x90000000~0x900001FF 数据写入失败仍然为FF
在这里插入图片描述
之后的数据只有一片FLASH操作成功。
在这里插入图片描述
第二次测试,修改代码为:

1.擦除6块

2.配置为直接映射,打开Memory监测

其中块大小为0x10000,理论上0x90060000之后应该为非擦除状态

但是反而0x90060000之前的未擦掉,之后的擦掉了,也就是说FLASH的写入和擦除都未能成功
在这里插入图片描述
异常数据似乎没有规律

第三次测试:使用整片擦除代替上面的6块擦除,发现根本没有擦掉。而且整片擦除函数执行很快,明显不符合实际。

检查了一下cubeMX配置的工程,发现引脚有的是高速,有的是低速,修改好之后发现还是不行。

第四次测试:直接将工程修改为单个FLASH的模式,发现整片擦除不成功,只能块擦除,查看FLASH的3个寄存器,发现在reg1中BP3 BP2 BP1 BP0为0001,也就是说使能了某种保护机制,FLASH中有一小段无法被改动。抱着试一试的想法,向寄存器reg1写入全0之后,整片擦除函数得以运行。因此怀疑前三次FLASH的操作失败是由于两片FLASH均受到了保护机制影响。

第五次测试:将工程改回双FLASH模式,读取寄存器,发现两片FLASH reg1 为0x06fe 。也就是FLASH1 的 BP3 BP2 BP1 BP0为0001(不知道为啥,第四次明明改成全0了,现在又恢复了); FLASH2的 SRP TB BP 3 BP 2 BP 1 BP 0 WEL BUSY分别为11111110,也就是说除了BUSY为0其他全是1。根据W25Q256芯片手册,FLASH2处于硬件WP引脚有效的状态,即当WP引脚为高电平时,才能对寄存器进行改写,以及设置写使能,并且保护范围是整片。尝试了一下写全0,发现只有FLASH1可以改写寄存器,果然FLASH2还是受到WP引脚影响啊。

尝试了在初始化的时候将WP引脚设置成上拉,发现没有用。直接取消GPIO初始化复用QSPI引脚,初始化为普通输出IO,然后在写寄存器为全0之前,使用 HAL_GPIO_WritePin 将该引脚拉高,结果OK,寄存器被成功改写。成功解决。

再次测试写64MB数据,结果又失败了…重新Debug发现FLASH1的局部保护又被打开了。总结前面几次得到一个结论:如果操作不当,或者代码调试还有问题,那么有可能会触发芯片的保护机制,调试过程中难免的

调整宏定义大小:

#define W25Q256JV_FLASH_SIZE                  0x4000000 /* 双片 64MB  */
#define W25Q256JV_BLOCK_SIZE                  0x20000	/*单片64KBytes  256页为1个block,两片则为128KB*/
#define W25Q256JV_BLOCK_COUNT				  512		/* 512 个block */
#define W25Q256JV_SECTOR_SIZE                 0x2000   /* 4KBytes  *2*/
#define W25Q256JV_PAGE_SIZE                   0x200     /* 1页256*2字节 */

最终在单步调试的情况下得以解决
但是全速运行会出现有些Block只有一片FLASH成功,猜测应该是等待FLASH操作完成的判断写得不对,修改等待代码

void QSPI_FLASH_Wait_Busy(void)
{
	uint32_t _reg;
	while(1){
		_reg = QSPI_FLASH_ReadStatusReg(1);
		if((_reg & 0x0101)==0) break;
	}
}

将等待插入到FLASH操作之前,最终解决。

最后检查一下边界,即最多可以读写多少字节。

发现0x90000000~0x93FFFFFF 共64MB空间读写没问题。
在这里插入图片描述

Part4 main代码

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_QUADSPI_Init();
  /* USER CODE BEGIN 2 */
  uint8_t buffer_test[0x10000] = {0};/*按半个block来定义数组大小,否则占用内存太大,引起无法调试*/
  uint8_t readbuf[128] = {0};
  uint32_t var = 0;
  BSP_QSPI_Init();
  uint32_t reg[3] = {0};
//  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_9, 1);
  QSPI_FLASH_WriteStatusReg(1,0);
  reg[0] =  QSPI_FLASH_ReadStatusReg(1);
  reg[1] = QSPI_FLASH_ReadStatusReg(2);
  reg[2] = QSPI_FLASH_ReadStatusReg(3);
  var = QSPI_FLASH_ReadDeviceID();//读ID试试
  var = QSPI_FLASH_ReadID();
  BSP_QSPI_Read(readbuf,0,128);
  //初始化数组为
  for (var = 0; var < 0x10000; var++) {
    buffer_test[var] = (var & 0xff);
  }
  for (var = 0; var < W25Q256JV_BLOCK_COUNT; var++) {
	//扇区擦除
	BSP_QSPI_Erase_Block64(var * W25Q256JV_BLOCK_SIZE);
	QSPI_FLASH_Wait_Busy();
	//扇区写入
	BSP_QSPI_Write(buffer_test,var * W25Q256JV_BLOCK_SIZE,0x10000);//先写半个block
	QSPI_FLASH_Wait_Busy();
	BSP_QSPI_Write(buffer_test,var * W25Q256JV_BLOCK_SIZE + 0x10000,0x10000);//再写半个block
	QSPI_FLASH_Wait_Busy();
  }

  if (QSPI_EnableMemoryMappedMode() != QSPI_OK) {
    while (1){
	}
  }

    //比较内容
  for (var = 0; var < W25Q256JV_BLOCK_COUNT; var++) {
	if (memcmp(buffer_test,(uint8_t*) (0x90000000 + var * W25Q256JV_SECTOR_SIZE),
			W25Q256JV_SECTOR_SIZE) != HAL_OK) {
		while (1);

	}
  }
  /* USER CODE END 2 */
  while (1)
  {
  }
}
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
根据引用和引用的内容,可以总结出STM32h750 QSPI W25Q64驱动的一些关键信息。 首先,W25Q64是一种SPI NOR Flash芯片,它被连接到STM32h750的QSPI(Quad SPI)接口上。W25Q64的引脚连接为PB2、PB6、PF6、PF7、PF8和PF9。 在设置QSPI时,一些关键的配置参数需要注意。首先是时钟预分频器(clock prescaler),根据W25Q256的最高时钟频率为104MHz,因此需要将分频设置为2。其次是闪存大小(FLASH SIZE),W25Q64的大小为8MB,所以需要将设置为2的(22-1)次方。时钟模式(Clock Mode)应设置为Low,表示CLK空闲时为低电平。芯片选择(Chip Select)需要设置为High Time为5,以确保高电平持续时间大于50ns。 另外,为了保证正常的工作,所有的QSPI引脚都应该设置为very high,而NCS脚(PB6)必须设置为PULL-UP。关于为什么要设置为PULL-UP,具体原因在引用中没有提及。 最后,需要注意W25Q64与W25Q256之间的一些区别。首先是地址位数,W25Q64只支持24位地址,而W25Q256支持24位和32位地址。其次是读写状态寄存器的不同,W25Q64的读状态寄存器为05h和35h,而W25Q256的为05h、35h和15h。写状态寄存器也有所不同,W25Q64的为01h,而W25Q256的为01h、31h和11h。 综上所述,STM32h750的QSPI可以通过相应的配置来驱动W25Q64芯片。需要注意的是,具体的配置参数和引脚连接可能还取决于具体的硬件设计和应用需求。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [STM32H750 QSPI间接模式 W25Q64](https://blog.csdn.net/smallerlang/article/details/127921384)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [STM32H753 STM32H743 STM32H750 QSPI W25Q256 下载算法](https://blog.csdn.net/c101028/article/details/132073746)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值