0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何利用AS32系列MCU芯片使用简洁单线模式操作QSPI FLASH?

安芯 来源:jf_29981791 作者:jf_29981791 2025-12-14 23:36 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

QSPI(Quad Serial Peripheral Interface) 是一种高速串行通信接口,在标准SPI(Serial Peripheral Interface)的基础上扩展至4条数据线(Quad Mode),显著提升数据传输速率。它广泛应用于Flash存储器、传感器微控制器之间的通信。AS32系列MCU芯片开发板集成了一块S25FL512SAGMFVG13型号的QSPI FLASH,本文我们将介绍该系列芯片使用简洁单线模式操作QSPI FLASH。

代码详解:

1、扇区擦除函数

根据指导手册我们知道,在进行扇区擦除命令之前必须先给一个WREN 命令,该命令会将状态寄存器中的写使能锁存器(WEL)置位,以允许任何写入操作。此外,本文用例使用3字节地址,根据时序图可知,应先发送指令(长度可配置)接着发送一个24位地址。

我们开始讲解扇区擦除函数,代码如下:

#define WRITE_ENABLE_INST 0x06

#define WRITE_DISBALE_INST 0x04

#define ERASE_SECTOR_INST 0xD8

#define READ_RIGISTER1_INST 0x05

#define PAGE_PROGRAME_INST 0x02

#define READ_FLASH_INST 0x03

void QSPI_FlashErase(uint32_t block_start, uint32_t sector_num)

{

uint32_t dst;

uint32_t SR_Status;

uint8_t erase_status = 1;

dst = block_start;

uint32_t num = sector_num-1;

if (dst + num * 0x3FFFF> 0xFFFFFF)

{

Printf("error :Exceeds the erase range.rn");

}

QSPI_Reset();

QSPI_Deinit();

QSPI_StructInitenable();

QSPI_WriteEnable();

while ( (QSPI_GetFlagStatus(QSPI_FLAG_BUSY) == 1));

for (uint32_t i = 0; i < num; i++)

{

QSPI_SectorErase();

while ( (QSPI_GetFlagStatus(QSPI_FLAG_BUSY) == 1));

QSPI_SetAddr(dst + num*0x3FFFF);

while ( (QSPI_GetFlagStatus(QSPI_FLAG_BUSY) == 1));

}

while (erase_status)

{

QSPI_SetDataLength(0);

QSPI_ReadStatus_Rigister1();

delay_ms(10);

erase_status = QSPI_ReadData();

}

QSPI_ReadFlash(dst, PROGRAME_SIZE, QSPI_BUFFER );

}

首先看第16行,对QSPI结构体初始化,分别配置片选高电平时间,QSPI时钟信号在指令之间的电平,QSPI时钟分频。

接着第17行,发送写使能命令。该函数主要配置QSPI->CCR寄存器,主要配置指令写使能指令和简介写模式,其余配置读者可查阅AS32X601设计手册的QSPI章节,这里不做过多赘述。

第22行,进行扇区擦除,和写使能函数一致,区别在于配置不同的指令,第24行设置需要擦除区域的首地址。

第30行,配置QSPI数据长度寄存器(DLR)为0,我们需要读取1字节,即SR1寄存器8位。第31行,我们发送读取QSPI FLASH的SR1寄存器指令。第33行,读取QSPI FLASH返回的8位数据,直到erase_status = 0时,我们擦除操作完成。这里是间接读取模式,还可使用轮询模式,减少CPU等待时间,完全交给QSPI FLASH来处理数据。

以下是读取SR1寄存器的相关配置,和擦除函数一致,区别在于指令,当然读者可以自行配置QSPI 为2线或4线。

2、读QSPI FLASH

接上节,我们在最后调用了QSPI_ReadFlash函数,本章节详细讲解该函数,先看FLASH手册,

该指令允许从存储器阵列的任意字节地址开始读取。每输出一个字节数据后,地址会自动递增至下一个更高地址(按顺序连续递增)。因此,只需提供起始地址000000h并发送一次读指令,即可连续读取整个存储器的内容。当到达最高地址后,地址计数器将自动回绕至000000h,从而支持无限循环的连续读取操作。

函数如下:

void QSPI_ReadFlash(uint32_t block_start, uint32_t byte_num, uint32_t buffer[])

{

uint32_t FIFO_LEVEL = 0;

QSPI_WriteEnable();

QSPI_SetDataLength(byte_num);

QSPI_Read_Flash();

QSPI_SetAddr(block_start);

delay_ms(10);

FIFO_LEVEL = QSPI_GetFIFOLevel();

while (FIFO_LEVEL != 0)

{

for (uint32_t i=0;i

{

buffer[i] = QSPI_ReadData();

Printf("%xt",buffer[i]);

}

FIFO_LEVEL = QSPI_GetFIFOLevel();

}

QSPI_WriteDisable();

}

同样在读数据之前需要解锁QSPI FLASH,并在操作完成后上锁。第5行,设置读取需要读取的字节数,第6行,调用QSPI_READ_FLASH(),函数如下,第9行,获取FIFO中有效字节数,当FIFO非空时,读QSPI->DR寄存器获取数据,直到FIFO为空。

3、下板验证

程序初始化后,调用QSPI_FlashErase(0x00, 1),从0地址开始,擦除1个扇区,观察打印信息,并截取了逻辑分析仪片段。

4、页编程函数

主要内容:若地址的最低9位(A8-A0)不全为0,则超出当前页末尾的传输数据将从同一页的起始地址(即最低9位全为0的地址)开始编程,即地址会在页对齐的边界内回绕。这是因为用户只需输入单个页地址即可覆盖整个页边界。

如果发送给设备的数据不足一页,这些数据字节将从所提供地址开始按顺序编程,而不会影响同一页内的其他字节。

为优化时序,使用页编程(PP)命令在页边界内加载整个页大小的编程缓冲器,相比于加载不足一页的数据到编程缓冲器,将节省总体编程时间。

int QSPI_FlashWrite(uint32_t block_start,uint32_t offset_into_block, uint32_t count, uint32_t buffer[])

{

uint32_t dst;

uint32_t ii;

uint32_t num;

dst = block_start + offset_into_block;

num = count;

if (dst%4 != 0)

{

Printf( "the addr must 4-byte alignmentrn");

return 0;

}

QSPI_Deinit();

if ((dst%256) == 0)

{ int loop = 0;

Printf( "the first packge is 256 bytesrn");

while (num > 256)

{

QSPI_StructInitenable();

QSPI_SetDataLength(0xff);

QSPI_WriteEnable();

QSPI_PageProgram();

QSPI_SetAddr(dst);

for (ii = loop256/4; ii < loop256/4+64; ii++)

{

QSPI->DR = buffer[ii];

}

while ( (QSPI_GetFlagStatus(QSPI_FLAG_BUSY) == 1));

dst += 256;

num -= 256;

delay_ms(20);

loop++;

}

QSPI_StructInitenable();

QSPI_SetDataLength(block_start + offset_into_block + count - dst -1);

QSPI_WriteEnable();

QSPI_PageProgram();

QSPI_SetAddr(dst);

for (ii = 256loop/4; ii < (256loop+block_start + offset_into_block + count - dst)/4; ii++)

{

QSPI->DR = buffer[ii];

}

while ( (QSPI_GetFlagStatus(QSPI_FLAG_BUSY) == 1));

dst += block_start + offset_into_block + count – dst;

}

else

{

QSPI_StructInitenable();

QSPI_WriteEnable();

QSPI_PageProgram();

QSPI_SetAddr(dst);

QSPI_SetDataLength(256-(dst%256));

for (ii = 0; ii < (256-(dst%256))/4; ii++)

{

QSPI->DR = buffer[ii];

}

while ( (QSPI_GetFlagStatus(QSPI_FLAG_BUSY) == 1));

dst += 256-(dst%256);

while (num > 256)

{

QSPI_StructInitenable();

QSPI_WriteEnable();

QSPI_PageProgram();

QSPI_SetAddr(dst);

QSPI_SetDataLength(256-1);

for (ii = 0; ii < 64; ii++)

{

QSPI->DR = buffer[ii];

}

while ( (QSPI_GetFlagStatus(QSPI_FLAG_BUSY) == 1));

dst += 256;

num -= 256;

}

QSPI_StructInitenable();

QSPI_WriteEnable();

QSPI_PageProgram();

QSPI_SetAddr(dst);

QSPI_SetDataLength(block_start + offset_into_block + count - dst -1);

for (ii = 0; ii < (block_start + offset_into_block + count - dst)/4; ii++)

{

QSPI->DR = buffer[ii];

}

while ( (QSPI_GetFlagStatus(QSPI_FLAG_BUSY) == 1));

dst += block_start + offset_into_block + count - dst;

}

QSPI_WriteDisable();

while ( (QSPI_GetFlagStatus(QSPI_FLAG_BUSY) == 1));

QSPI_ReadFlash(block_start,PROGRAME_SIZE,QSPI_BUFFER);

return 0; //RESULT_OK

}

第1至13行定义了函数参数并计算目标地址,同时检查地址是否4字节对齐,若未对齐则报错返回。第14行对QSPI控制器进行复位。第15至48行处理目标地址256字节对齐的情况:第16至35行循环写入完整的256字节数据页,每次写入前初始化硬件、设置数据长度、使能写入、发送页编程命令并设置地址,随后通过循环写入64个32位数据,等待操作完成后更新地址和剩余计数;第36至47行处理剩余不足256字节的数据尾部,采用类似的流程但数据长度根据剩余量动态计算。第49至88行处理目标地址未256字节对齐的情况:第51至60行先写入从起始地址到下一个256字节边界的首部数据片段;第61至75行循环写入后续完整的256字节页;第76至87行处理最后的尾部数据。

5、下板验证

准备写入1024个数,0-0x3FF,共4K,从0地址开始,观察打印信息

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FlaSh
    +关注

    关注

    10

    文章

    1717

    浏览量

    154774
  • QSPI
    +关注

    关注

    0

    文章

    48

    浏览量

    13245
  • MCU芯片
    +关注

    关注

    3

    文章

    259

    浏览量

    12560
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    编译可在QSPI Flash上运行的程序

    在前文中已经实现了一个能够在 MDK 平台进行下载代码到 QSPI Flash 中的下载算法,以及一个能跳转执行应用程序的 2nd Bootloader,但若想将代码下载到 QSPI Flas
    的头像 发表于 03-31 09:50 4615次阅读
    编译可在<b class='flag-5'>QSPI</b> <b class='flag-5'>Flash</b>上运行的程序

    在软件SDK中选择不同的下载模式时,是哪个部件更改了QSPI0中寄存器的值?

    请问如果我需要更换MCU_Flash,不使用兆易创新的Flash 我如何去配置QSPI的寄存器呢?我观察到如果是XIP模式的话,需要使能QSPI
    发表于 01-10 08:10

    STM32H750 QSPI flash重映射模式下有方法能实现读写操作吗?

    STM32H750 QSPI flash重映射模式下有方法能实现读写操作
    发表于 03-25 08:06

    STM32 QSPI怎么退出映射模式

    FLASH 中,多 QSPI 进行ERASE 和 PROGRAMME, 这个时候我就需要退出映射模式,请问怎么退出映射模式
    发表于 03-29 08:15

    xilinx-A7 fpga 使用QSPI模式启动,项目需要用MCU做FPGA程序升级,请问MCU怎么操作SPIFLASH?

    A7_fpga 使用QSPI模式启动,项目需要用MCU做FPGA程序升级,用MCU同时升级FPGA存放在SPIflash中的程序,请问:1、MCU
    发表于 12-03 22:23

    如何对STM32 QSPI进行调试

    STM32之QSPI调试记录先声明一下,STM32的QSPI外设同样支持单线模式(兼容普通spi),只是相比普通的spi少了一些特性(比如只支持模式
    发表于 08-12 07:23

    如何制作适用于MM32F5270系列MCUQSPI Flash下载算法呢?

    。  QSPI Flash 支持单线,双线和四线操作,本文为方便编程,仅描述实现单线模式
    发表于 03-17 14:46

    什么是QSPI?如何使用QSPIQSPI Flash进行通信呢?

    。一般来说,在与 QSPI Flash 通信时,并不是全程都是四根数据信号线传输数据,当同一时间只有一根数据线在传输数据的模式可称为单线模式
    发表于 03-17 15:17

    先楫hpm6000的SPI外设使用四线模式操作读写华邦flash

    的spi_master_timing_init api接口进行SPI频率调整。 (四)指令操作单线模式SPI操作) 1、华邦相关flash
    发表于 06-28 20:01

    AT32系列MCU flash具体操作说明

    AT32 MCU Flash Application Note为了让用户能够更全面的了解Artery AT32 系列flash 相关操作
    发表于 10-23 06:51

    如何使用QSPI Flash控制器开发板上的 QSPI Flash进行写读操作

    学习内容 本文首先介绍FlashQSPI Flash控制器的相关内容,然后使用 QSPI Flash 控制器,开发板上的
    的头像 发表于 06-10 17:08 1.6w次阅读
    如何使用<b class='flag-5'>QSPI</b> <b class='flag-5'>Flash</b>控制器开发板上的 <b class='flag-5'>QSPI</b> <b class='flag-5'>Flash</b>进行写读<b class='flag-5'>操作</b>

    QSPI flash上运行毫米波芯片的测试代码

    QSPI flash上运行毫米波芯片的测试代码
    发表于 10-28 12:00 0次下载
    在<b class='flag-5'>QSPI</b> <b class='flag-5'>flash</b>上运行毫米波<b class='flag-5'>芯片</b>的测试代码

    使用Complete FDCB模式恢复擦写异常的QSPI Flash

    当遇到片外的Flash无论如何用四线模式擦写读取都异常的时候(如下所示读出的内容始终是0xbb,也无法用四线模式擦除),可以尝试用如下方式,当然如果 ID都读不出来,那估计是芯片损坏了
    的头像 发表于 03-06 13:44 1888次阅读

    FreeRTOS 在 AS32系列RISC-V 架构MCU电机驱动中的应用实践与优化

    一、AS32系列 RISC-V MCU与 FreeRTOS 融合的电机驱动架构解析 1.1 硬件层: AS32系列 架构的优势 在电机驱动系
    的头像 发表于 11-13 23:33 555次阅读

    AS32系列MCU芯片中CRC计算模块的应用介绍

    、执行器动作异常甚至整个控制系统宕机。循环冗余校验(CRC)作为一种高效的错误检测技术,如同数据传输与存储过程中的"安全校验屏障",持续保障MCU与外部设备交互数据的准确性。本文将系统阐述国科安芯推出的AS32系列
    的头像 发表于 11-21 15:20 1136次阅读
    <b class='flag-5'>AS32</b><b class='flag-5'>系列</b><b class='flag-5'>MCU</b><b class='flag-5'>芯片</b>中CRC计算模块的应用介绍