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

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

3天内不再提示

物联网行业中Nor Flash的软件设计分享_W25Q128的软件设计方案

jf_94171069 来源:jf_94171069 作者:jf_94171069 2024-09-26 11:20 次阅读

一 概述

W25Q128是一种NOR Flash芯片,掉电后数据不丢失的特点。

W25Q128FV阵列被组织成65,536个可编程页面,每个页面256字节。每次最多可编程256字节。可以以16页为一组(即一个Sector)、128页为一组(8个Sector)、256页为一组(16个Sector)或整个芯片(芯片擦除)进行擦除。W25Q128FV分别有4,096个可擦除扇区和256个可擦除块。较小的4KB扇区为需要数据和参数存储的应用程序提供了更大的灵活性。

标准SPI通信支持时钟频率高达104MHz,Dual SPI通信支持时钟频率高达208MHz,QSPI通信支持时钟频率高达416MHz。

注意:W25Q128一共为128M bits(16M Byte),又分为256个块(每个块512K bit(64K Byte)),每个块又分为16个扇区(每个扇区32K bit(4 KByte)),每个扇区又分为16页(每个页2K bit(256 Byte))

二 物理特性

可以将 1 写成 0,但是不能将 0 写成 1,要想将 0 写成 1,必须进行擦除操作。如果要改变数据,就需要先擦除后写数据。

如果想要修改小于扇区大小的数据,需要将整个扇区的数据,在内存中进行备份,然后修改内存中的数据,再将数据写回到原扇区位置。因此,驱动要达到支持自动完成这个过程,用户可以使用驱动修改任意位置的数据。

三 存储结构

W25Q128可以存储16777216字节,存储一个字节占用一个地址,所以寻址范围是0-(16777216-1),对应的16进制为0-0xFFFFFF(所以寄存器地址是24位的)

wKgaomb00wqACUqfAAG4uUcIoAw154.jpg

四 命令总览

wKgZomb00w2Ac1-YAAHXaioKKxw748.jpg

五 组件的使用

1 Gitee链接地址

Demo位于amaziot_bloom_os_sdksample3rd2.1_W25Q128

Gitee源码地址:https://gitee.com/ning./hongdou

Github源码地址:https://github.com/ayumid/hongdou

编译指令:.build.bat -l .amaziot_bloom_os_sdksample3rd2.1_W25Q128

2 组件功能介绍

实现软件模拟SPI,驱动W25Q128芯片,实现数据存储。

3 代码讲解

1 drv_w25q128_delay_us

功能:该函数用于,延时。

参数:

参数 释义
count 死循环次数

返回值:无

示例:

//初始化i2c总线
ret = drv_xl9535_i2c_init();

2 drv_w25q128_gpio_set

功能:该函数用于,模拟SPI设置IO输出电平。

参数:

参数 释义
num 引脚号
val 0 低电平,1 高电平

返回值:0 成功,-1 失败

示例:

drv_w25q128_gpio_set(DRV_w25q128_SPI_CS, DRV_w25q128_GPIO_LOW);

3 drv_w25q128_byte_wr

功能:该函数用于,SPI写读一个字节 mode3。

参数:

参数 释义
byte 发送数据

返回值:flash返回数据

示例:

drv_w25q128_byte_wr(DRV_w25q128_DUMMY_BYTE);

4 drv_w25q128_byte_rd

功能:该函数用于,SPI只读一个字节。

参数:无

返回值:flash返回数据

示例:

drv_w25q128_byte_rd(DRV_w25q128_DUMMY_BYTE);

5 drv_w25q128_busy_wait

功能:该函数用于,W25Q128 忙等待。

参数:无

返回值:无

示例:

while(drv_w25q128_read_reg1() & BIT_BUSY);

6 drv_w25q128_read_reg

功能:该函数用于,读reg。

参数:无

返回值:无

示例:

while(drv_w25q128_read_reg() & BIT_BUSY);

7 drv_w25q128_read_jedecid

功能:该函数用于,读 W25Q128 JEDEC_ID(制造商、类型、容量)。

参数:无

返回值:无

示例:

sample_w25q128_uart_printf("identification is 0x%X, Device id is 0x%X, Manufacturer Device ID is 0x%X", 
                               drv_w25q128_read_identification(), drv_w25q128_read_device_id(), drv_w25q128_read_manufacturer_id());

8 drv_w25q128_read_manufacturer_id

功能:该函数用于,读 W25Q128 制造商 ID。

参数:无

返回值:无

示例:

sample_w25q128_uart_printf("identification is 0x%X, Device id is 0x%X, Manufacturer Device ID is 0x%X", 
                               drv_w25q128_read_identification(), drv_w25q128_read_device_id(), drv_w25q128_read_manufacturer_id());

9 drv_w25q128_read_device_id

功能:该函数用于,读 W25Q128 设备 ID。

参数:无

返回值:无

示例:

sample_w25q128_uart_printf("identification is 0x%X, Device id is 0x%X, Manufacturer Device ID is 0x%X", 
                               drv_w25q128_read_identification(), drv_w25q128_read_device_id(), drv_w25q128_read_manufacturer_id());

10 drv_w25q128_write_enable

功能:该函数用于,写使能。

参数:无

返回值:无

示例:

sample_w25q128_uart_printf("identification is 0x%X, Device id is 0x%X, Manufacturer Device ID is 0x%X", 
                               drv_w25q128_read_identification(), drv_w25q128_read_device_id(), drv_w25q128_read_manufacturer_id());

11 drv_w25q128_write_disable

功能:该函数用于,写失能。

参数:无

返回值:无

示例:

12 drv_w25q128_write_page

功能:该函数用于,页编程(调用本函数写入数据前需要先擦除扇区)。

参数:

参数 释义
pbuf 数据
addr 地址
len 长度

返回值:无

示例:

drv_w25q128_write_page(pbuf, addr, pageremain);

13 drv_w25q128_read

功能:该函数用于,读闪存数据。

参数:

参数 释义
pbuf 数据
addr 地址
len 长度

返回值:无

示例:

drv_w25q128_read((UINT8*)rx_buff1, 8181, strlen(tx_buff1));

14 drv_w25q128_sector_erase

功能:该函数用于,扇区擦除。

参数:

参数 释义
addr 地址

返回值:无

示例:

drv_w25q128_sector_erase(secpos * DRV_w25q128_SOCTOR_SIZE);

15 drv_w25q128_chip_rease

功能:该函数用于,FLASH整片擦除(为了安全起见,若要调用,请先调用 drv_w25q128_write_enable 函数)。

参数:无

返回值:无

示例:

16 drv_w25q128_powr_down

功能:该函数用于,掉电。

参数:无

返回值:无

示例:

17 drv_w25q128_release_powr_down

功能:该函数用于,读闪存数据。

参数:

参数 释义
pbuf 数据
addr 地址
len 长度

返回值:无

示例:

drv_w25q128_read((UINT8*)rx_buff1, 8181, strlen(tx_buff1));

18 drv_w25q128_write_nocheck

功能:该函数用于,写数据。

参数:

参数 释义
pbuf 数据
addr 地址
len 长度

返回值:无

示例:

drv_w25q128_write_nocheck(w25q128_buffer, secpos * DRV_w25q128_SOCTOR_SIZE, DRV_w25q128_SOCTOR_SIZE);

19 drv_w25q128_write

功能:该函数用于,写闪存数据,可以使任意地址。

参数:

参数 释义
pbuf 数据
addr 地址
len 长度

返回值:无

示例:

drv_w25q128_write((UINT8*)tx_buff1, 8181, strlen(tx_buff1));

20 drv_w25q128_init

功能:该函数用于,写数据。

参数:无

返回值:无

示例:

drv_w25q128_init();

4 Demo实战

4.1 创建一个Demo

复制20.1_file_xtu示例工程,到同一个文件夹下,修改文件名为3.1_SSD1315,如图:

wKgaomb00w-AFrO4AABzXQF3wLE458.jpg

4.2 修改makefile

增加文件组件所在目录头文件路径,和源文件路径,如图:

wKgZomb00xCAYBJCAABjS-wnlzE612.jpg

4.3 增加头文件

使用代码编辑器,将新建的工程文件加入代码编辑器中,打开main.c,修改main.c,加入am.h等头文件,如图:

wKgaomb00xGAG41CAAAJBaHV2rA635.jpg

4.4 修改代码

在Phase2Inits_exit 创建一个任务,如图:

wKgZomb00xKAS4x6AABJVrwH_NQ593.jpg

4.1 概述

上电后,按下按键,串口会打印出按下了哪一个按键

4.2 测试

测试步骤:

参考编译教程,和文档开头的编译指令,进行编译

按照编译教程选择对应的选项

烧录

4.3 宏定义介绍

sample_w25q128_uart_printf

输出日志到DEBUG 串口,日志比较少,可以输出到这个串口,如果日志比较多,需要输出到usb口,以免不必要的问题出现

sample_w25q128_catstudio_printf

输出日志到USB 串口,使用catstudio查看,catstudio查看日志需要更新对应版本mdb.txt文件,软件打开filtter过滤日志,只查看用户输出的日志

SAMPLE_W25Q128_STACK_SIZE

栈空间宏定义

4.4 全局变量介绍

sample_w25q128_task_ref

任务指针

4.5 函数介绍

Phase1Inits_enter

底层初始化,本例空

Phase1Inits_exit

底层初始化,本例空

Phase2Inits_enter

底层初始化,本例空

Phase2Inits_exit

创建主任务,初始化INT 引脚

代码片段:

void Phase2Inits_exit(void)
{
    int ret;

    sample_w25q128_task_stack = malloc(SAMPLE_W25Q128_STACK_SIZE);

    ret = OSATaskCreate(&sample_w25q128_task_ref, sample_w25q128_task_stack, SAMPLE_W25Q128_STACK_SIZE, 88, "sample_w25q128_task", sample_w25q128_task, NULL);
    ASSERT(ret == OS_SUCCESS);
}

sample_w25q128_task

主任务,代码发分为两部分,一部分是发送不定长数据;另一部分是上电后等待其它模块发送的数据,收到后打印到串口。

代码片段:

static void sample_w25q128_task(void *ptr)
{
    int ret = 0;
    uint32_t identification = 0;
//    unsigned char writeBuf[30] = {0};
//    unsigned char readBuf[30] = {0};

//    ret = ql_spi_init(QL_SPI_PORT0, QL_SPI_MODE3, QL_SPI_CLK_812_5KHZ);
//    sample_w25q128_catstudio_printf("ql_spi_init ret %d", ret);

    drv_w25q128_init();

    identification = drv_w25q128_read_jedecid();
    sample_w25q128_uart_printf("identification is 0x%X, Device id is 0x%X, Manufacturer Device ID is 0x%X", 
                               drv_w25q128_read_jedecid(), drv_w25q128_read_device_id(), drv_w25q128_read_manufacturer_id());
    
//    while(1)
//    {
//        drv_w25q128_gpio_set(DRV_w25q128_SPI_CS, 0);
//        sample_w25q128_uart_printf("low");
//        OSATaskSleep(5*200);
//        drv_w25q128_gpio_set(DRV_w25q128_SPI_CS, 1);
//        sample_w25q128_uart_printf("high");
//        OSATaskSleep(5*200);
//    }
    if(identification != JEDECID)
    {
        /* 读取错误处理 */
        sample_w25q128_uart_printf("SPI read-write Error, please check the connection between MCU and SPI Flashn");
    }
    else
    {
        //读取成功处理
        char tx_buff1[64] = "abcdefghigklmnopqrstuvwxyz0123456789";
        char rx_buff1[64] = {0};
        char tx_buff2[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ9876543210";
        char rx_buff2[64] = {0};
        int i = 0;
        //测试跨sector写,并且读出数据,写两次,第二次保留第一次部分数据,证明数据擦除,写入正常
        drv_w25q128_write((UINT8*)tx_buff1, 8181, strlen(tx_buff1));//从8181地址开始写数据,需要写第二和第三个扇区
        drv_w25q128_read((UINT8*)rx_buff1, 8181, strlen(tx_buff1));
        sample_w25q128_uart_printf("read flash:%s", rx_buff1);

        if(!strncmp(tx_buff1, rx_buff1, strlen(tx_buff1)))
        {
            sample_w25q128_uart_printf("SPI read-write succeed 1");
        }
        //验证驱动擦除扇区时,可以保留之前有效内容
        drv_w25q128_write((UINT8*)tx_buff2, 8186, strlen(tx_buff2));//从8186地址开始写数据,需要写第二和第三个扇区,同时不能擦掉8181 - 8186的5字节数据
        drv_w25q128_read((UINT8*)rx_buff2, 8181, strlen(tx_buff2) + 5);
        sample_w25q128_uart_printf("read flash:%s", rx_buff2);

        if(!strncmp(rx_buff2, "abcdeABCDEFGHIJKLMNOPQRSTUVWXYZ9876543210", strlen("abcdeABCDEFGHIJKLMNOPQRSTUVWXYZ9876543210")))
        {
            sample_w25q128_uart_printf("SPI read-write succeed 2");
        }
    }
//    memset(writeBuf, 0x00, sizeof(writeBuf));
//    memset(readBuf, 0x00, sizeof(readBuf));

//    writeBuf[0] = 0x9F;
    while (1)
    {
//        ret = ql_spi_write_read(QL_SPI_PORT0, readBuf, writeBuf, 1);
//        sample_w25q128_catstudio_printf("ql_spi_write_read ret %d, readBuf %02X,%02X,%02Xn", ret, readBuf[0], readBuf[1], readBuf[2]);
//        ret = ql_spi_write(QL_SPI_PORT0, writeBuf, 1);
//        sample_w25q128_catstudio_printf("ql_spi_write_read ret %d, readBuf %02Xn", ret, writeBuf[0]);
//        ret = ql_spi_read(QL_SPI_PORT0, readBuf, 3);
//        sample_w25q128_catstudio_printf("ql_spi_write_read ret %d, readBuf %02X,%02X,%02Xn", ret, readBuf[0], readBuf[1], readBuf[2]);
        OSATaskSleep(5 * 200);
    }
}

4.6 固件

wKgaomb00xOAAcqTAABoORGfLTA102.jpg

点击下载 Lora Demo固件

5 生态组件链接

SPI NOR FLASH

本文章源自奇迹物联开源的物联网应用知识库Cellular IoT Wiki,更多技术干货欢迎关注收藏Wiki:Cellular IoT Wiki 知识库(https://rckrv97mzx.feishu.cn/wiki/wikcnBvAC9WOkEYG5CLqGwm6PHf)

欢迎同学们走进AmazIOT知识库的世界!

这里是为物联网人构建的技术应用百科,以便帮助你更快更简单的开发物联网产品

Cellular IoT Wiki初心:

在我们长期投身于蜂窝物联网 ODM/OEM 解决方案的实践过程中,一直被物联网技术碎片化与产业资源碎片化的问题所困扰。从产品定义、芯片选型,到软硬件研发和测试,物联网技术的碎片化以及产业资源的碎片化,始终对团队的产品开发交付质量和效率形成制约。为了减少因物联网碎片化而带来的重复开发工作,我们着手对物联网开发中高频应用的技术知识进行沉淀管理,并基于 Bloom OS 搭建了不同平台的 RTOS 应用生态。后来我们发现,很多物联网产品开发团队都面临着相似的困扰,于是,我们决定向全体物联网行业开发者开放奇迹物联内部沉淀的应用技术知识库 Wiki,期望能为更多物联网产品开发者减轻一些重复造轮子的负担。

Cellular IoT Wiki沉淀的技术内容方向如下:

wKgaombqoM2AYL2RAAQrZ8e-uz8392.jpg

奇迹物联的业务服务范围:基于自研的NB-IoT、Cat1、Cat4等物联网模组,为客户物联网ODM/OEM解决方案服务。我们的研发技术中心在石家庄,PCBA生产基地分布在深圳、石家庄、北京三个工厂,满足不同区域&不同量产规模&不同产品开发阶段的生产制造任务。跟传统PCBA工厂最大的区别是我们只服务物联网行业客户。

连接我们,和10000+物联网开发者一起 降低技术和成本门槛

让蜂窝物联网应用更简单~~

哈哈你终于滑到最重要的模块了,

千万不!要!划!走!忍住冲动!~

欢迎加入飞书“开源技术交流”,随时找到我们哦~

点击链接如何加入奇迹物联技术话题群(https://rckrv97mzx.feishu.cn/docx/Xskpd1cFQo7hu9x5EuicbsjTnTf)可以获取加入技术话题群攻略

Hey 物联网从业者,

你是否有了解过奇迹物联的官方公众号“eSIM物联工场”呢?

这里是奇迹物联的物联网应用技术开源wiki主阵地,欢迎关注公众号,不迷路~

及时获得最新物联网应用技术沉淀发布

注:本文部分内容来源于网络,如有侵权,请及时联系我们。

审核编辑 黄宇

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

    关注

    2895

    文章

    43487

    浏览量

    366910
  • NOR flash
    +关注

    关注

    2

    文章

    89

    浏览量

    22944
收藏 人收藏

    评论

    相关推荐

    想问问外接一个flash有什么用如外接w25q128 spi接口flash

    stm32 外接了一个 spi接口的flash w25q128 不知道在实际应用到底 有什么作用求指教 大家可以把自己的用途 写上给大家看看谢谢了
    发表于 04-03 11:16

    外扩FLASH(W25Q128)如何存储数组的数据!?

    ]用于放数据,现外扩了一个带有SPI接口的FLASHW25Q128),如何将dat[4096]数据存入其内,并且可以读出呢? 非常感谢
    发表于 12-23 19:45

    W25Q128数据置顶

    请问各位大神一个问题,现在W25Q128保存着一段数据,但是我想把这段数据中间的某一段删除,同时把后面的数据全部向前移动,填满之前删除的数据功能类似于聊天记录置顶,大家有什么简单快捷的方法?
    发表于 04-09 12:37

    W25Q128芯片简介

    1、W25Q128 是华邦公司推出的一款 SPI 接口的 NOR Flash 芯片,其存储空间为 128Mbit,相当于 16M 字节。 W25Q1
    发表于 08-13 08:49

    求大佬分享stm32 cubemx u*** spi flash w25q128 u盘调试笔记

    求大佬分享stm32 cubemx u*** spi flash w25q128 u盘调试笔记
    发表于 02-14 07:57

    基于RT-Thread的W25Q128虚拟U盘和文件系统如何实现自由切换呢

    文件系统RT-Thread:W25Q128虚拟U盘并搭载文件系统RT-Thread:STM32F407虚拟U盘,无法识别拔出问题解决方案1、W25Q128分区使用fal组件给spi flash
    发表于 08-04 10:57

    flash型号为w25q128jv spi挂载失败是什么原因导致的

    SFDP.[SFUD] Warning: This flash device is not found or not support.[SFUD] Error: W25Q128 flash device
    发表于 10-09 14:33

    基于基于Qt的集成电路测试软件设计方案

    基于基于Qt的集成电路测试软件设计方案
    发表于 06-19 12:02 30次下载

    引射氏跨声速风洞流畅控制软件设计方案

    引射氏跨声速风洞流畅控制软件设计方案
    发表于 06-29 14:10 4次下载

    水下航行器通用的数据处理软件设计方案

    水下航行器通用的数据处理软件设计方案
    发表于 06-30 15:29 5次下载

    W25Q128 闪存芯片SPI详解

    。/WP为写保护管脚,/HOLD or /RESET为保持或复位引脚(通过寄存器配置)。原理图连接W25Q128(W25Q64)将16M(8M)的容量分为256(128)个块(Block),每个...
    发表于 11-26 17:36 263次下载
    <b class='flag-5'>W25Q128</b> 闪存芯片SPI详解

    FLASH芯片(W25Q128

    简介W25Q128FV (128M-bit)串行闪存为有限的空间、引脚和电源系统提供了存储解决方案25Q系列提供的灵活性和性能远远超过普通的串行F
    发表于 11-26 18:51 72次下载
    <b class='flag-5'>FLASH</b>芯片(<b class='flag-5'>W25Q128</b>)

    stm32 cubemx usb spi flash w25q128 u盘调试笔记

    基本代码确定使用需求 USB SPIusb以下配置保持默认配置即可,切记不要胡乱修改参数。spi调试spi flash我使用的flashw25q128 spi 通信模式,所以直接找一个别人写好的驱动就可以了。
    发表于 12-14 18:52 32次下载
    stm32 cubemx usb spi <b class='flag-5'>flash</b> <b class='flag-5'>w25q128</b> u盘调试笔记

    STM32CUBEMX(13)--SPI,W25Q128外部Flash移植

    省空间,提供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议,比如 EEPROM,FLASH,实时时钟,AD转换器。 W25Q128 是一款SPI接口的Flash芯片,其存储空间为
    的头像 发表于 11-14 16:54 3164次阅读
    STM32CUBEMX(13)--SPI,<b class='flag-5'>W25Q128</b>外部<b class='flag-5'>Flash</b>移植

    BQ79616-Q1软件设计参考

    电子发烧友网站提供《BQ79616-Q1软件设计参考.pdf》资料免费下载
    发表于 09-03 10:37 1次下载
    BQ79616-<b class='flag-5'>Q</b>1<b class='flag-5'>软件设计</b>参考