QSPI驱动移植
由于要用到下载算法,需要先编写QSPI驱动并验证,这一章节使用CubeMx快速验证
Cubemx创建工程如下(只使用到QSPI,理论上工程越简单越好,能驱动QSPI就行,用Cubemx快速驱动起来)
QSPI flash最大频率133Mhz,在cubemx中配置为120Mhz
- 使用外部晶振25M
- 开启时钟480M
- 使用SYSTICK时基
QSPI配置如下


具体参数配置如下

时钟极性 CPOL
Low: 这意味着当QSPI总线处于空闲状态时,时钟线的电平为低。这对应于CPOL = 0。
High: 这意味着当QSPI总线处于空闲状态时,时钟线的电平为高。这对应于CPOL = 1。目前编直接写qspi驱动较困难,先找一个现成的移植看看,使用反客家的例程进行修改
该驱动带有QSPI初始化,可能引脚不一样, 我们使用自己的,将它屏蔽掉(懒得改)

哈哈我看到了什么,但是实话实说,安富莱的代码非常工整且有好多干货,

稍微修改以后调用初始化进行验证,由于我没有使能串口,就直接使用软件仿真了
调用初始化函数


仿真验证读取ID一致

接下来验证一下擦除,读写以及内存映射模式,提供了以下函数

编写qspi的测试,仿真测试ok的

data_checkou t函数如下,每隔4K验证一个字节,首先写进去,再逐字节读取对比, 成功之后进入内存映射模式再逐字节读取验证 ,验证成功返回0,在上面的函数中仿真可以执行到 state =3; 证明无误, 并没有全部读写验证, 太浪费时间了
#define QSPI_FLASH_SIZE (8 * 1024 * 1024) // 8M字节
#define INTERVAL (4 * 1024) // 4K字节
#define QSPI_BASE_ADDR 0x90000000UL
int data_checkout(void)
{
uint8_t writeData = 0xAA; // 写入的数据
uint8_t readData; // 用于存储读取的数据
int8_t status; // 用于存储函数的返回状态
// 遍历整个Flash,每隔4K字节写入数据
for (uint32_t addr = 0; addr < QSPI_FLASH_SIZE; addr += INTERVAL) {
status = QSPI_W25Qxx_WriteBuffer(&writeData, addr, 1); // 写入1字节数据
if (status != QSPI_W25Qxx_OK) {
return -1;
}
}
// 遍历整个Flash,每隔4K字节读取并验证数据
for (uint32_t addr = 0; addr < QSPI_FLASH_SIZE; addr += INTERVAL) {
status = QSPI_W25Qxx_ReadBuffer(&readData, addr, 1); // 读取1字节数据
if (status != QSPI_W25Qxx_OK) {
return -1;
}
if (readData != writeData) {
return -1;
}
}
// 开启内存映射模式
status = QSPI_W25Qxx_MemoryMappedMode();
if (status != QSPI_W25Qxx_OK) {
return -1;
}
// 使用内存映射模式验证数据
for (uint32_t addr = 0; addr < QSPI_FLASH_SIZE; addr += INTERVAL) {
readData = *(uint8_t *)(QSPI_BASE_ADDR + addr);
if (readData != writeData) {
return -1;
}
}
return 0;
}