搜索
bottom↓
回复: 180

【开源】万能 SPI Flash 驱动库 SFUD 正式发布

  [复制链接]

出0入198汤圆

发表于 2016-7-26 21:27:27 | 显示全部楼层 |阅读模式
本帖最后由 sunnydragon 于 2016-7-26 21:27 编辑

SFUD (Serial Flash Universal Driver) 串行 Flash 通用驱动库
0、SFUD 是什么

SFUD 是一款开源的串行 SPI Flash 通用驱动库。由于现有市面的串行 Flash 种类居多,各个 Flash 的规格及命令存在差异, SFUD 就是为了解决这些 Flash 的差异现状而设计,让我们的产品能够支持不同品牌及规格的 Flash,提高了涉及到 Flash 功能的软件的可重用性及可扩展性,同时也可以规避 Flash 缺货或停产给产品所带来的风险。

  • 主要特点:面向对象(同时支持多个 Flash 对象)、可灵活裁剪、扩展性强、支持 4 字节地址
  • 资源占用

    • 标准占用:RAM:0.2KB ROM:5.5KB
    • 最小占用:RAM:0.1KB ROM:3.6KB

  • 设计思路:这里要首先跟大家介绍一个标准: SFDP ,它是 JEDEC (固态技术协会)制定的串行 Flash 功能的参数表标准,最新版 V1.6B (点击这里查看)。该标准规定了,每个 Flash 中会存在一个参数表,该表中会存放 Flash 容量、写粗粒度、擦除命令、地址模式等 Flash 规格参数。目前,除了部分厂家旧款 Flash 型号会不支持该标准,其他绝大多数新出厂的 Flash 均已支持 SFDP 标准。所以该库在初始化时会优先读取 SFDP 表参数,如果该 Flash 不支持 SFDP,则查询配置文件 ( /sfud/inc/sfud_flash_def.h ) 中提供的 Flash 参数信息表 中是否支持该款 Flash。如果不支持,则可以在配置文件中添加该款 Flash 的参数信息(添加方法详细见 2.5 添加库目前不支持的 Flash)。获取到了 Flash 的规格参数后,就可以实现对 Flash 的全部操作。


1、为什么选择 SFUD
  • 避免项目因 Flash 缺货、Flash 停产或产品扩容而带来的风险;
  • 越来越多的项目将固件存储到串行 Flash 中,例如:ESP8266 的固件、主板中的 BIOS 及其他常见电子产品中的固件等等,但是各种 Flash 规格及命令不统一。使用 SFUD 即可避免,在相同功能的软件平台基础下,无法适配不同 Flash 种类的硬件平台的问题,提高软件的可重用性;
  • 简化软件流程,降低开发难度。现在只需要配置好 SPI 通信,即可畅快的开始玩串行 Flash 了;
  • 可以用来制作 Flash 编程器/烧写器



2、SFUD 如何使用
2.1 已支持 Flash

下表为所有在 Demo 平台上进行过真机测试的 Flash。目前 SFUD 提供的 Flash 参数信息表 只包括下表中 不支持 SFDP 标准的 Flash,其他不支持 SFDP 标准的 Flash 需要大家以后 共同来完善和维护 (Github|OSChina|Coding) 。如果觉得这个开源项目很赞,可以点击 项目主页 右上角的 Star ,同时把它推荐给更多有需要的朋友。

[td]
型号
制造商
容量
最高速度
SFDP
备注
Winbond
4Mb
50Mhz
不支持
已停产
Winbond
8Mb
104Mhz
支持

Winbond
16Mb
104Mhz
支持

Winbond
32Mb
104Mhz
支持

Winbond
64Mb
80Mhz
支持

Winbond
128Mb
104Mhz
支持

Macronix
32Mb
86MHz
支持

Macronix
32Mb
86Mhz
支持

Microchip
16Mb
50MHz
不支持
SST 已被 Microchip 收购
Micron
32Mb
75Mhz
不支持

EON
32Mb
104MHz
不支持

GigaDevice
64Mb
120Mhz
不支持

Cypress
16Mb
65Mhz
不支持

AMIC
64Mb
104Mhz
支持

AMIC
8Mb
100Mhz
不支持

ESMT
4Mb
100Mhz
不支持

PCT
16Mb
80Mhz
不支持
SST 授权许可,会被识别为 SST25VF016B
ADESTO
16Mb
85MHz
不支持
ADESTO 收购 Atmel 串行闪存产品线
更多 API 说明 及 配置方法详见源码中的说明文档及 https://github.com/armink/SFUD

目前以支持如下平台下的 Demo

路径
平台描述
STM32F10X 裸机平台
STM32F2XX + RT-Thread 操作系统平台

项目采用 MIT 开源协议


再晒几张这些日子测试环境的图片:

ART-WiFi 开发板及 Flash 测试座。在这里要感谢 RT-Thread 开发团队提供的 ART-WiFi 开发板。


Flash 全家福。为了保证库的通用性及测试覆盖率,选购了尽可能多的各种品牌及型号的 SPI Flash。


全系列华邦 SPI Flash 模块


本坛下载:

最新版请关注 GitHub :https://github.com/armink/SFUD



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入198汤圆

 楼主| 发表于 2016-8-28 23:03:15 | 显示全部楼层
最近对软件主要做了以下两项更新,强烈建议大家将核心源码更新下。

1、【修复】采用 SFDP 参数在某些条件下,擦除命令选择不合适的问题;
2、【增加】全片擦除方法。

更多信息详见:

GitHub:https://github.com/armink/SFUD
OSChina:http://git.oschina.net/Armink/SFUD
Coding:https://coding.net/u/armink/p/SFUD/git

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出16170入6148汤圆

发表于 2020-6-23 16:18:41 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2020-6-22 12:42:01 来自手机 | 显示全部楼层
感谢楼主开源分享!

出0入0汤圆

发表于 2019-3-6 13:27:11 来自手机 | 显示全部楼层
谢谢分享,准备试试看

出0入46汤圆

发表于 2019-3-6 13:24:31 | 显示全部楼层
感谢楼主的无私分享,果断收藏!

出0入0汤圆

发表于 2019-3-6 10:29:14 | 显示全部楼层
在使用SFUD驱动GD25S513MD发现了个两个问题,(SFUD模式)
1、GD25S513MD在出厂默认BP0~BP3为保护状态,此时编程和4K擦除都是不执行的
  1. /* I found when the flash write mode is supported AAI mode. The flash all blocks is protected,
  2.      * so need change the flash status to unprotected before write and erase operate. */
  3.     if(flash->chip.write_mode & SFUD_WM_AAI)
  4.     {
  5.         result = sfud_write_status(flash, true, 0x00);
  6.         if(result != SFUD_SUCCESS)
  7.         {
  8.             return result;
  9.         }
  10.     }
复制代码


2、GD25S513MD内部是封装了两个Die,可以通过Software Die Select (C2H)命令可以选择,
如果使用SFUD库的话,您那边有什么好的实现方法嘛

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入198汤圆

 楼主| 发表于 2018-11-9 18:25:55 | 显示全部楼层
q457344370 发表于 2018-11-9 11:21
测试了两天,发现一个问题,如果在SPI Flash忙碌时MCU发生复位,重启后初始化是不响应查询SFUD信息命令的, ...

确实会有这个可能呀,SPI 的时序对不上,你有什么解决方法没?

出0入0汤圆

发表于 2018-11-9 11:21:47 | 显示全部楼层
测试了两天,发现一个问题,如果在SPI Flash忙碌时MCU发生复位,重启后初始化是不响应查询SFUD信息命令的,此时会报芯片不支持SFUD

出0入0汤圆

发表于 2017-12-11 20:09:38 | 显示全部楼层
楼主好东西,有没有各种EEPROM开源的?

出0入4汤圆

发表于 2017-12-9 17:35:25 | 显示全部楼层
这个很不错,可用在正在做的烧录器程序中。

出0入198汤圆

 楼主| 发表于 2017-11-27 08:25:54 | 显示全部楼层
tianxiaoMCU 发表于 2017-11-25 22:41
楼主,这个驱动怎么添加Dual SPI或者Quad SPI支持呢


https://github.com/armink/SFUD/b ... sfud_port.c#L55-L67

这个文件里有详细的说明,底层 SPI 是不需要 SFUD 关注的。

出0入198汤圆

 楼主| 发表于 2017-11-27 08:24:34 | 显示全部楼层
擦鞋匠 发表于 2017-11-10 17:41
大神是不是参与写过rtthread?署名armink?

嗯,我也是 RT-Thread 开发者。

出0入0汤圆

发表于 2017-11-25 22:41:50 | 显示全部楼层
楼主,这个驱动怎么添加Dual SPI或者Quad SPI支持呢

出0入0汤圆

发表于 2017-11-10 17:41:18 | 显示全部楼层
大神是不是参与写过rtthread?署名armink?

出0入0汤圆

发表于 2017-11-9 21:35:07 | 显示全部楼层
不错 不错 , SPI  FATS 也是一个麻烦  扇区4K   那么最小的一个文件是4K 不然,就得读出来,再写,就麻烦了.

出0入198汤圆

 楼主| 发表于 2017-11-9 10:54:39 | 显示全部楼层
游在云间 发表于 2017-11-9 06:48
想把代码移植到freertos中,spi_lock可以用freertos中什么替代?

mutex or sem

出0入0汤圆

发表于 2017-11-9 10:45:26 | 显示全部楼层
收藏收藏,马克一下!!

出0入0汤圆

发表于 2017-11-9 06:48:16 | 显示全部楼层
想把代码移植到freertos中,spi_lock可以用freertos中什么替代?

出0入0汤圆

发表于 2017-6-2 12:51:39 | 显示全部楼层
感谢楼主的开源

出0入198汤圆

 楼主| 发表于 2017-5-31 13:28:29 | 显示全部楼层
FireHe 发表于 2017-5-31 09:54
比如串口要用来作为其他用途的时候,这个跟调试的时候需要打印并不冲突

我是先将基础环境搭好,配置好硬 ...

好的,已经改好了。快从 GitHub: https://github.com/armink/SFUD 上下载下来试试吧,多谢你的反馈。

出0入0汤圆

发表于 2017-5-31 09:54:52 | 显示全部楼层
sunnydragon 发表于 2017-5-30 18:25
什么场景下不需要 info 日志的输出呢?目前我们产品出货时,info 日志也是必须开启的。 ...

比如串口要用来作为其他用途的时候,这个跟调试的时候需要打印并不冲突

我是先将基础环境搭好,配置好硬件,测试好SFUD,看日志输出,初始化正常了。然后再开始调试其他部分。这个时候串口需要输出自定义帧跟PC通讯了。如果有日志输出,会造成干扰。

这个每个项目的需求不同,都是不一样的,能作为一个可选配置就最好啦

另外,我现在这个项目也用上了esaylogger    真的很好用

出0入198汤圆

 楼主| 发表于 2017-5-30 18:25:24 | 显示全部楼层
FireHe 发表于 2017-5-29 12:52
这两天一个新项目又用上了SFUD,真的非常好用,快速开发。再次感谢  sunnydragon

再反馈一个细节:

什么场景下不需要 info 日志的输出呢?目前我们产品出货时,info 日志也是必须开启的。

出0入0汤圆

发表于 2017-5-29 12:52:19 | 显示全部楼层
这两天一个新项目又用上了SFUD,真的非常好用,快速开发。再次感谢  sunnydragon

再反馈一个细节:

SUFD_INFO 这个输出没有用宏定义管理,建议在cfg里面增加一个。这样跟debug信息一样可以配置是否输出了。

出0入198汤圆

 楼主| 发表于 2016-10-20 15:22:30 | 显示全部楼层
shentqlf 发表于 2016-10-20 14:15
也在里面呢啊。吧硬件SPI那部分屏蔽了,然后把软件SPI那些取消屏蔽就行了

...

这个注释我看到了,我指的是 SoftSpi 里具体的实现代码。

出0入17汤圆

发表于 2016-10-20 14:15:27 | 显示全部楼层
sunnydragon 发表于 2016-10-20 13:40
多谢分享~

刚看了下,使用 ebox 来做为底层驱动确实简单了不多。。。

也在里面呢啊。吧硬件SPI那部分屏蔽了,然后把软件SPI那些取消屏蔽就行了

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入198汤圆

 楼主| 发表于 2016-10-20 13:40:16 | 显示全部楼层
shentqlf 发表于 2016-10-20 01:03
楼主我的代码上传下,ebox下支持了sfud,
支持软件SPI和硬件SPI。
支持单条总线挂载多个FLASH。(eBox底层 ...

多谢分享~

刚看了下,使用 ebox 来做为底层驱动确实简单了不多。。。

另外软件模拟 SPI 代码在哪里?

出0入0汤圆

发表于 2016-10-20 10:06:39 | 显示全部楼层
感谢分享 !!!!!

出0入17汤圆

发表于 2016-10-20 01:03:02 | 显示全部楼层
本帖最后由 shentqlf 于 2016-10-20 01:43 编辑

楼主我的代码上传下,ebox下支持了sfud,
支持软件SPI和硬件SPI。
支持单条总线挂载多个FLASH。(eBox底层有总裁,可以是总线上的器件使用不同的总线配置,避免读写相互间的串扰)
支持多条总线挂载多个FLASH。

map文件



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2016-10-14 18:14:35 | 显示全部楼层
关于第三点,目前已经可以直接通过flash对象读取了。我之前没仔细看代码,不确认用户是否可见。后来确认了,目前是没有封装起来的。用户可见的,我个人的看法是没有必要再用函数返回了。用户直接调用这个就好了。

出0入0汤圆

发表于 2016-10-14 18:12:49 | 显示全部楼层
sunnydragon 发表于 2016-10-14 13:26
1、就是这样的

2、当Flash 不使用时,打开写保护是最好的,避免的外部信号干扰对芯片造成影响。接下来, ...

这些计划完全满足我对这个优秀的开源项目的未来展望啦

   感谢 sunnydragon~~~

出0入198汤圆

 楼主| 发表于 2016-10-14 13:26:47 | 显示全部楼层
FireHe 发表于 2016-10-14 10:12
1、哦,那个状态是可以保存在FLASH里面,掉电不丢失的。是吧?也可以写寄存器的方式,但掉电就会丢失?嗯 ...

1、就是这样的

2、当Flash 不使用时,打开写保护是最好的,避免的外部信号干扰对芯片造成影响。接下来,我打算独立出 Flash 全片写保护开启及关闭方法;增加空闲时自动开启写保护的宏定义,开启后必须先执行关闭写保护的方法后,才可以正确执行擦写操作,执行完擦写操作后将会自动对 Flash 开启写保护。另外,出于进一步提高可靠性的考虑,建议用户对关闭保护操作增加授权、校验操作,避免程序跑飞等其他异常场景导致 Flash 被错误的取消保护。

3、现在用户是可以通过 Flash 对象直接读取的。没有封装起来是什么意思,你的意思在写个方法来返回给用户吗?

出0入0汤圆

发表于 2016-10-14 10:12:22 | 显示全部楼层
sunnydragon 发表于 2016-10-14 08:30
1、is_volatile 的参数含义为该状态写入以后是否需要设置为易闪失的,即设置完的状态掉电后保不保存,tru ...

1、哦,那个状态是可以保存在FLASH里面,掉电不丢失的。是吧?也可以写寄存器的方式,但掉电就会丢失?嗯,如果是这样,这个描述应该是要针对状态寄存器的。开始我还以为是针对整个FLASH的

2、写保护统一接口那这个确实没有太好的办法。不过,是否提供给客户一个变量来控制目前是否需要写入数据的需求?
     比如一个应用场景,客户用FLASH来存储字库,基本上是只读的。只有系统更新的时候才可能会刷新版本写进去。那正常启动的时候,应该就是只读的。在系统更新的时候,通过开放的专门函数来打开读保护,然后再写。这样是否会更安全?有没有这个必要?
     因为我之前用EEPROM的时候,发现在上电或掉电的瞬间,如果没有读保护,容易造成里面的内容被错误改写的情况。不知道SPI FLASH有没有这个问题。

3、我说的就是 erase_gran  这个参数啦。刚刚看了一下代码,这个没有封装起来的。用户层面可以直接读取。那就ok了。

出0入198汤圆

 楼主| 发表于 2016-10-14 08:30:23 | 显示全部楼层
FireHe 发表于 2016-10-14 01:04
看啦

新的文档详细很多。很多细节都讲清楚了。这样更容易上手了

1、is_volatile 的参数含义为该状态写入以后是否需要设置为易闪失的,即设置完的状态掉电后保不保存,true 则不保存。这块你觉得在文档中需要怎么完善下才更好的理解?

2、Flash 写保护是这样的,可以全片也保护,也可以按照扇区写保护,不同的芯片,按照扇区保护的命令、数据差异非常大,所以这也是我一直没法统一的一个原因,最后就提供 sfud_write_status  方法还有 flash->spi.wr 方法给上层用户,用户自己参考芯片手册进行设置更为灵活。

3、初始化成功后 在 flash->chip 结构体中存放的芯片所有参数

  1. /* flash chip information */
  2. typedef struct {
  3.     char *name;                                  /**< flash chip name */
  4.     uint8_t mf_id;                               /**< manufacturer ID */
  5.     uint8_t type_id;                             /**< memory type ID */
  6.     uint8_t capacity_id;                         /**< capacity ID */
  7.     uint32_t capacity;                           /**< flash capacity (bytes) */
  8.     uint16_t write_mode;                         /**< write mode  @see sfud_write_mode */
  9.     uint32_t erase_gran;                         /**< erase granularity (bytes) */
  10.     uint8_t erase_gran_cmd;                      /**< erase granularity size block command */
  11. } sfud_flash_chip;
复制代码


如果芯片支持 SFDP ,还可以通过 flash->sfdp 看到更加全面的参数信息

  1. /**
  2. * the SFDP (Serial Flash Discoverable Parameters) parameter info which used on this library
  3. */
  4. typedef struct {
  5.     bool available;                              /**< available when read SFDP OK */
  6.     uint8_t major_rev;                           /**< SFDP Major Revision */
  7.     uint8_t minor_rev;                           /**< SFDP Minor Revision */
  8.     uint16_t write_gran;                         /**< write granularity (bytes) */
  9.     uint8_t erase_4k;                            /**< 4 kilobyte erase is supported throughout the device */
  10.     uint8_t erase_4k_cmd;                        /**< 4 Kilobyte erase command */
  11.     bool sr_is_non_vola;                         /**< status register is supports non-volatile */
  12.     uint8_t vola_sr_we_cmd;                      /**< volatile status register write enable command */
  13.     bool addr_3_byte;                            /**< supports 3-Byte addressing */
  14.     bool addr_4_byte;                            /**< supports 4-Byte addressing */
  15.     uint32_t capacity;                           /**< flash capacity (bytes) */
  16.     struct {
  17.         uint32_t size;                           /**< erase sector size (bytes). 0x00: not available */
  18.         uint8_t cmd;                             /**< erase command */
  19.     } eraser[SFUD_SFDP_ERASE_TYPE_MAX_NUM];      /**< supported eraser types table */
  20.     //TODO lots of fast read-related stuff (like modes supported and number of wait states/dummy cycles needed in each)
  21. } sfud_sfdp, *sfud_sfdp_t;
复制代码


不过这块可能需要文档描述下, 否则大家都不知道

出0入0汤圆

发表于 2016-10-14 01:04:43 | 显示全部楼层
sunnydragon 发表于 2016-10-13 21:11
新改的文档看了吗?  https://www.zybuluo.com/armink/note/363414

看啦

新的文档详细很多。很多细节都讲清楚了。这样更容易上手了

不过有一个地方我没看明白

sfud_write_status 这个函数,有一个 is_volatile 参数,这个具体是什么意义?


从这个函数也引发了一个思考。FLASH的写保护,目前默认是初始化就关闭的。从SPI FALSH的角度来说,这样是否存在数据风险?是否考虑这个开放一个接口出来给客户控制?

因为很多用SPI FLASH的用户,是只读的应用。并不需要写操作。

还有一个问题,兼容SFDP 标准的FLASH,对用户来说,主要区别就在于block的大小不同吧?(目前我用的好像都是一样的)这个是否也考虑做一个接口,给用户层调用,知道当前用的FLASH的最小擦除单位是多少,从而正确处理数据读写。

出0入198汤圆

 楼主| 发表于 2016-10-13 21:11:06 | 显示全部楼层
FireHe 发表于 2016-10-12 09:13
原来是这样

刚刚看了代码,确实是有自动读取配置的部分,之前阅读不仔细,没看到这个。


新改的文档看了吗?  https://www.zybuluo.com/armink/note/363414

出0入8汤圆

发表于 2016-10-12 17:20:00 | 显示全部楼层
真不错,关注下啊~~

出0入198汤圆

 楼主| 发表于 2016-10-12 11:58:32 | 显示全部楼层
FireHe 发表于 2016-10-12 09:13
原来是这样

刚刚看了代码,确实是有自动读取配置的部分,之前阅读不仔细,没看到这个。


是的,如果你的 Flash 支持 SFDP 参数表,甚至可以把 SFUD_USING_FLASH_INFO_TABLE 宏定义关闭,SFUD_FLASH_CHIP_TABLE 这个数组的配置就不需要了,这样代码量还能再降低。

关于芯片更换问题,如果你换的芯片依然支持 JEDEC SFDP 参数表,那么肯定没有任何影响,所有代码都不用改。如果新换的 Flash 不支持 JEDEC SFDP 参数表,就需要开启 SFUD_USING_FLASH_INFO_TABLE ,手动在里面添加 Flash 芯片参数来使用。

出0入198汤圆

 楼主| 发表于 2016-10-12 11:51:53 | 显示全部楼层
huarana 发表于 2016-10-12 08:35
spi nand应用场景还是有的。

要求可靠性的场合下,tf卡 sd卡都不是好的解决方案。 而并口的nand对单片机 ...

只驱动 SPI Nand 读写,难度并不大,这会是 SFUD 的主要工作。

就像你说的难度更大的是如何做好 FTL ,这块学问还是挺深的。你们现在是自己在写 FTL 还是用现成的?

出0入0汤圆

发表于 2016-10-12 09:45:07 | 显示全部楼层
对裸机系统有很大的帮助,试试移植楼主的代码。

出0入4汤圆

发表于 2016-10-12 09:22:29 | 显示全部楼层
FireHe 发表于 2016-10-12 09:04
eMMC 不就好了吗?

坏块管理和写平衡不是那么好做的。

eMMC的话 体积大了,而且焊接是个麻烦,另外容量也太大了点。 对于100M-1G之间的需求来说不太好找。

出0入0汤圆

发表于 2016-10-12 09:13:48 | 显示全部楼层
sunnydragon 发表于 2016-10-12 07:49
我明白你的意思了,那可能是不是我文档中写的不够明确,SFUD_FLASH_CHIP_TABLE 数组里只包含了不支持 JED ...

原来是这样

刚刚看了代码,确实是有自动读取配置的部分,之前阅读不仔细,没看到这个。

所以如果FLASH是支持SFUD的话,那根本就不需要做数组的配置,直接就可以用啦?如果从应用逻辑上是兼容的话,不修改代码直接换芯片也是不影响的,是吗?

出0入0汤圆

发表于 2016-10-12 09:05:57 | 显示全部楼层
谢谢分享! 学习下哈

出0入0汤圆

发表于 2016-10-12 09:04:55 | 显示全部楼层
huarana 发表于 2016-10-12 08:35
spi nand应用场景还是有的。

要求可靠性的场合下,tf卡 sd卡都不是好的解决方案。 而并口的nand对单片机 ...

eMMC 不就好了吗?

坏块管理和写平衡不是那么好做的。

出0入4汤圆

发表于 2016-10-12 08:35:55 | 显示全部楼层
sunnydragon 发表于 2016-10-12 08:00
暂时还没有,主要是 SPI 接口的 NandFlash 使用场景感觉太小,当时就没有开发。不过当时也做过部分调研, ...

spi nand应用场景还是有的。

要求可靠性的场合下,tf卡 sd卡都不是好的解决方案。 而并口的nand对单片机要求又高了。

所以 spi nand就是最佳选择。然而使用起来发现磨损平衡和坏块管理比较麻烦。  目前我们的嵌入式工程师正在攻关这一块

出0入198汤圆

 楼主| 发表于 2016-10-12 08:00:49 | 显示全部楼层
huarana 发表于 2016-10-11 23:35
有没有 spi nandflash的 版本= =


暂时还没有,主要是 SPI 接口的 NandFlash 使用场景感觉太小,当时就没有开发。不过当时也做过部分调研,想要增加 SPI NandFlash 工作量也并不会很大。有没有兴趣我来协助你尝试下?

出0入198汤圆

 楼主| 发表于 2016-10-12 07:49:31 | 显示全部楼层
FireHe 发表于 2016-10-11 23:15
第三点说的是,在说明文档 readme.md 中,有提到很多型号,但在代码的数组列表里面并没有这些型号。用户 ...


我明白你的意思了,那可能是不是我文档中写的不够明确,SFUD_FLASH_CHIP_TABLE 数组里只包含了不支持 JEDEC SFDP 参数表的 Flash 芯片。

如果这块 Flash 芯片支持 JEDEC 的 SFDP 参数表,那么用户是不需要对这块 Flash 芯片做任何参数配置,只要开启了本库的 SFDP 模式(即打开 SFUD_USING_SFDP 宏定义),本库是可以自动读取存放在 Flash 芯片中的 SFDP 参数表,实现对 Flash 自动初始化,非常省事的。

出0入0汤圆

发表于 2016-10-11 23:40:23 | 显示全部楼层
好东西,顶起,再也不怕不兼容了

出0入4汤圆

发表于 2016-10-11 23:35:34 | 显示全部楼层
有没有 spi nandflash的 版本= =

出0入0汤圆

发表于 2016-10-11 23:15:28 | 显示全部楼层
sunnydragon 发表于 2016-10-11 21:19
多谢你的反馈,写的非常仔细认真,我来逐条回复下:

1、这点我确实也感觉到了,大概一个月前把全片擦除  ...

第三点说的是,在说明文档 readme.md 中,有提到很多型号,但在代码的数组列表里面并没有这些型号。用户在用的时候,还需要自己再增加,比如我用的W25Q64FV。如果sunnydragon 已经做过测试了,建议把列表直接完善了。

其他的几点,我再去拜读最新版本代码去~~~

出30入0汤圆

发表于 2016-10-11 23:04:49 | 显示全部楼层
有见楼主发精品了,谢谢!

出0入198汤圆

 楼主| 发表于 2016-10-11 21:19:04 | 显示全部楼层
FireHe 发表于 2016-10-11 17:12
我已经用在了项目上,FLASH是WINBOND的 W25Q64FV

因为SFUD的软件做得非常好,所以几乎没有啥移植工作,直 ...

多谢你的反馈,写的非常仔细认真,我来逐条回复下:

1、这点我确实也感觉到了,大概一个月前把全片擦除 API:sfud_chip_erase 加入进去了。以后可以常去 GitHub ,关注项目进展哈:lol:} ;(建议点击 GitHub 项目右上角的 watch 按钮,这样项目有更新会邮件通知你)

2、已修改,详见 GitHub 最新代码;

3、这点没有搞太明白,是说代码中的 SFUD_FLASH_CHIP_TABLE 没有包含支持 SFDP 参数表的 Flash 芯片吗?

4、刚才也对文档做了更新,在这里: https://www.zybuluo.com/armink/note/363414 ,你看下还有没有要完善的。没问题的话,我就推送至 GitHub 了。

还有其他建议或想法也欢迎随时反馈。

出0入76汤圆

发表于 2016-10-11 18:14:37 | 显示全部楼层
非常感谢楼主分享, 这个真心不错

出0入0汤圆

发表于 2016-10-11 17:45:06 | 显示全部楼层
mark                  

出0入0汤圆

发表于 2016-10-11 17:41:52 | 显示全部楼层
感谢楼主的开源

出0入0汤圆

发表于 2016-10-11 17:12:39 | 显示全部楼层
我已经用在了项目上,FLASH是WINBOND的 W25Q64FV

因为SFUD的软件做得非常好,所以几乎没有啥移植工作,直接用就好了。实在是非常优秀的开源项目,感谢 sunnydragon

使用后有一些建议:

1、建议将 chip erase 这个函数开放出来。目前是包含在 sfud_erase 这个函数里面,通过判断起始地址为0和大小是flash的大小时就擦除整个芯片。这样感觉还不够方便。
2、在将 SFUD_DEBUG_MODE 宏定义关掉的时候,还有一个npn的变量的警告,作为一个强迫症患者,建议这个也可以顺手修改掉。
3、在说明文档中提到的那些flash型号,并没有更新到最新的代码列表中。建议增加进去。
4、建议增加更详细的函数应用说明,比如sfud_erase函数,擦除是按照地址和大小来的,实际擦除的是地址为起始,地址+大小为结束的范围,以擦除block为单位的擦除。

出0入198汤圆

 楼主| 发表于 2016-10-10 21:26:13 | 显示全部楼层
coolhorse 发表于 2016-9-29 10:18
是的,不好意思啊,支持 SFUD” 或 “不支持SFUD”,指的是 SFDP 参数表,SST26VF032B支持参数表的,上面打 ...

SST26VF032B 无法执行写操作的问题解决了吗?跟大家分享下进展吧。

出0入0汤圆

发表于 2016-10-9 08:24:46 | 显示全部楼层
不错,严重支持,有空我来试试。

出0入0汤圆

发表于 2016-10-8 21:42:17 来自手机 | 显示全部楼层
支持,经常用到华邦的芯片。

出0入8汤圆

发表于 2016-9-29 15:18:40 来自手机 | 显示全部楼层
好牛逼的样子

出0入198汤圆

 楼主| 发表于 2016-9-29 11:09:27 | 显示全部楼层
本帖最后由 sunnydragon 于 2016-9-29 11:11 编辑
coolhorse 发表于 2016-9-29 10:18
是的,不好意思啊,支持 SFUD” 或 “不支持SFUD”,指的是 SFDP 参数表,SST26VF032B支持参数表的,上面打 ...


对了,SST 的 Flash 是不是上电都默认是写保护的?我记得我测试 SST25 的时候就有这个问题, 同时 SST25 写数据还是很奇葩的 AAI 模式,所以我针对 支持 AAI 模式的 Flash 在初始化时,做了去除写保护处理,如图:



所以 SST26 系列,你可以这样尝试,两种方法:

第一种:使用 RT-Thread  Demo 可以使用我提供的
  1. flash_status <read|write> <device_index> [<1:volatile|0:non-volatile> <status>]
复制代码

命令,在 MSH 终端中输入:
  1. flash_status write 1 0
复制代码
,再进行写数据试试。

第二种:执行完 sfud_err sfud_init(void) 后,再增加  sfud_write_status(flash, true, 0x00); 代码,保证 Flash 被去除写保护

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2016-9-29 10:55:41 | 显示全部楼层
非常感谢楼主分享!!!

出0入198汤圆

 楼主| 发表于 2016-9-29 10:49:54 | 显示全部楼层
coolhorse 发表于 2016-9-29 10:18
是的,不好意思啊,支持 SFUD” 或 “不支持SFUD”,指的是 SFDP 参数表,SST26VF032B支持参数表的,上面打 ...

你用用 RT-Thread Demo 里面那个 sf 命令测试下这个 Flash 试试,命令教程在这里:https://github.com/armink/SFUD/tree/master/demo/stm32f2xx_rtt#111-flash-操作命令

先定位下问题,确实不好找,你再寄给我样品,不过要等国庆以后才能帮你测试了。

出0入0汤圆

发表于 2016-9-29 10:18:10 | 显示全部楼层
是的,不好意思啊,支持 SFUD” 或 “不支持SFUD”,指的是 SFDP 参数表,SST26VF032B支持参数表的,上面打印的就是SST26VF032B的信息,但是用上面的文件系统驱动,文件系统无法初始化成功,估计是SFDP写保护问题,无法执行写操作,楼主你帮我找找问题吧,我这里有SST26VF032B样品,要不要寄给你

出0入0汤圆

发表于 2016-9-29 09:39:29 | 显示全部楼层
好东西,顶上

出0入198汤圆

 楼主| 发表于 2016-9-29 09:38:26 | 显示全部楼层
coolhorse 发表于 2016-9-29 09:22
测试两款芯片:N25Q032A13ESE40F(支持SFUD)  SST25VF032B(不支持SFUD) 通过,  SST26VF032B (支持SFUD)不 ...


你的括号里面写的 “支持 SFUD” 或 “不支持SFUD”,应该指的是 SFDP 参数表吧。SFUD 是万能 SPI Flash 驱动库的名称,两个单词差一个字母

出0入198汤圆

 楼主| 发表于 2016-9-29 09:26:05 | 显示全部楼层
coolhorse 发表于 2016-9-29 09:22
测试两款芯片:N25Q032A13ESE40F(支持SFUD)  SST25VF032B(不支持SFUD) 通过,  SST26VF032B (支持SFUD)不 ...

SST26VF032B (支持SFUD)不通过,具体是什么现象?

出0入198汤圆

 楼主| 发表于 2016-9-29 09:23:56 | 显示全部楼层
coolhorse 发表于 2016-9-29 09:14
#include
#include
#include

多谢分享哈~~

出0入198汤圆

 楼主| 发表于 2016-9-29 09:23:02 | 显示全部楼层
coolhorse 发表于 2016-9-29 09:11
问题解决了,是我驱动写错了,现在上传文件系统驱动

解决完成就好,不过还是建议定期关注项目首页,及时采用最新源码。

出0入0汤圆

发表于 2016-9-29 09:22:23 | 显示全部楼层
测试两款芯片:N25Q032A13ESE40F(支持SFUD)  SST25VF032B(不支持SFUD) 通过,  SST26VF032B (支持SFUD)不通过,奇怪[SFUD](..\..\components\drivers\spi\sfud\src\sfud.c:78) Start initialize Serial Flash Universal Driver(SFUD) V0.08.25.
[SFUD](..\..\components\drivers\spi\sfud\src\sfud.c:712) The flash device manufacturer ID is 0xBF, memory type ID is 0x26, capacity ID is 0x42.
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:134) Check SFDP header is OK. The reversion is V1.6, NPN is 2.
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:175) Check JEDEC basic flash parameter header is OK. The table id is 0, reversion is V1.6, length is 16, parameter table pointer is[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:205) JEDEC basic flash parameter table info:
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:206) MSB-LSB  3    2    1    0
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:208) [0001] 0xFF 0xF1 0x20 0xFD
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:208) [0002] 0x01 0xFF 0xFF 0xFF
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:208) [0003] 0x6B 0x08 0xEB 0x44
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:208) [0004] 0xBB 0x80 0x3B 0x08
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:208) [0005] 0xFF 0xFF 0xFF 0xFE
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:208) [0006] 0xFF 0x00 0xFF 0xFF
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:208) [0007] 0x0B 0x44 0xFF 0xFF
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:208) [0008] 0xD8 0x0D 0x20 0x0C
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:208) [0009] 0xD8 0x10 0xD8 0x0F
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:217) 4 KB Erase is supported throughout the device. Command is 0x20.
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:236) Write granularity is 64 bytes or larger.
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:252) Block Protect bits in device's status register are solely volatile.
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:262) Flash device requires instruction 06h as the write enable prior to performing a volatile write to the status register.
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:273) 3-Byte only addressing.
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:307) Capacity is 4194304 Bytes.
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:313) Flash device supports 4KB block erase. Command is 0x20.
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:313) Flash device supports 8KB block erase. Command is 0xD8.
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:313) Flash device supports 32KB block erase. Command is 0xD8.
[SFUD](..\..\components\drivers\spi\sfud\src\sfud_sfdp.c:313) Flash device supports 64KB block erase. Command is 0xD8.
[SFUD]Find a SST flash chip. Size is 4194304 bytes.
[SFUD](..\..\components\drivers\spi\sfud\src\sfud.c:687) Flash device reset success.
[SFUD]XXXX flash device is initialize success.

出0入0汤圆

发表于 2016-9-29 09:14:41 | 显示全部楼层
#include <sfud.h>
#include <stdarg.h>
#include <rtthread.h>
#include <drivers/spi.h>

typedef struct {
    struct rt_semaphore lock;
        struct rt_spi_device * rt_spi_device;
} spi_user_data, *spi_user_data_t;

static spi_user_data spi2 = { .rt_spi_device = 0 };

static char log_buf[256];

void sfud_log_debug(const char *file, const long line, const char *format, ...);


static void spi_lock(const sfud_spi *spi) {
    spi_user_data_t spi_dev = (spi_user_data_t) spi->user_data;

    rt_sem_take(&spi_dev->lock, RT_WAITING_FOREVER);
}

static void spi_unlock(const sfud_spi *spi) {
    spi_user_data_t spi_dev = (spi_user_data_t) spi->user_data;

    rt_sem_release(&spi_dev->lock);
}

static void retry_delay_ms(void) {
    /* millisecond delay */
    rt_tick_from_millisecond(1);
}

static void retry_delay_100us(void) {
    /* 100 microsecond delay */
    rt_thread_delay((RT_TICK_PER_SECOND * 1 + 9999) / 10000);
}

/**
* SPI write data then read data
*/
static sfud_err spi_write_read(const sfud_spi *spi, const uint8_t *write_buf, size_t write_size, uint8_t *read_buf,
        size_t read_size) {
                       
        struct rt_spi_device * rt_spi_device;
    sfud_err result = SFUD_SUCCESS;
       
    spi_user_data_t spi_dev = (spi_user_data_t) spi->user_data;

    rt_spi_send_then_recv(spi_dev->rt_spi_device, write_buf,write_size, read_buf, read_size);

    return result;
}



sfud_err sfud_spi_port_init(sfud_flash *flash) {
        sfud_err result = SFUD_SUCCESS;
    struct rt_spi_device * rt_spi_device;
       
        rt_spi_device = (struct rt_spi_device *)rt_device_find("spi20");
        if(rt_spi_device == RT_NULL)
    {
        rt_kprintf("spi device %s not found!\r\n", "spi20");
        return -RT_ENOSYS;
    }
    spi2.rt_spi_device = rt_spi_device;

    /* config spi */
    {
        struct rt_spi_configuration cfg;
        cfg.data_width = 8;
        cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */
        cfg.max_hz = 50 * 1000 * 1000; /* 50M */
        rt_spi_configure(spi2.rt_spi_device, &cfg);
    }
       
        flash->spi.wr = spi_write_read;
        flash->spi.lock = spi_lock;
        flash->spi.unlock = spi_unlock;
        flash->spi.user_data = &spi2;
        /* 100 microsecond delay */
        flash->retry.delay = retry_delay_100us;
        /* 60 seconds timeout */
        flash->retry.times = 60 * 10000;

        rt_sem_init(&spi2.lock, "spi2 lock", 1, RT_IPC_FLAG_PRIO);

    return result;
}

/**
* This function is print debug info.
*
* @param file the file which has call this function
* @param line the line number which has call this function
* @param format output format
* @param ... args
*/
void sfud_log_debug(const char *file, const long line, const char *format, ...) {
    va_list args;

    /* args point to the first variable parameter */
    va_start(args, format);
    rt_kprintf("[SFUD](%s:%ld) ", file, line);
    /* must use vprintf to print */
    vsnprintf(log_buf, sizeof(log_buf), format, args);
    rt_kprintf("%s\n", log_buf);
    va_end(args);
}

/**
* This function is print routine info.
*
* @param format output format
* @param ... args
*/
void sfud_log_info(const char *format, ...) {
    va_list args;

    /* args point to the first variable parameter */
    va_start(args, format);
    rt_kprintf("[SFUD]");
    /* must use vprintf to print */
    vsnprintf(log_buf, sizeof(log_buf), format, args);
    rt_kprintf("%s\n", log_buf);
    va_end(args);
}

出0入0汤圆

发表于 2016-9-29 09:13:25 | 显示全部楼层
#include <rtthread.h>
#include <drivers/spi.h>
#include <sfud.h>

struct spi_flash_device
{
    struct rt_device flash_device;
       
        const sfud_flash  *flash;
    struct rt_device_blk_geometry   geometry;
};

static struct spi_flash_device  spi_flash_device;


/* RT-Thread device interface */
static rt_err_t sfud_flash_init(rt_device_t dev)
{
    return RT_EOK;
}

static rt_err_t sfud_flash_open(rt_device_t dev, rt_uint16_t oflag)
{
        struct spi_flash_device *aa = (struct spi_flash_device *)dev;
        const sfud_flash *flash = aa->flash;
       
    return RT_EOK;
}

static rt_err_t sfud_flash_close(rt_device_t dev)
{
    return RT_EOK;
}

static rt_err_t sfud_flash_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
    RT_ASSERT(dev != RT_NULL);

    if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
    {
        struct rt_device_blk_geometry *geometry;

        geometry = (struct rt_device_blk_geometry *)args;
        if (geometry == RT_NULL) return -RT_ERROR;

        geometry->bytes_per_sector = spi_flash_device.geometry.bytes_per_sector;
        geometry->sector_count = spi_flash_device.geometry.sector_count;
        geometry->block_size = spi_flash_device.geometry.block_size;
    }

    return RT_EOK;
}

static rt_size_t sfud_flash_read(rt_device_t dev,
                                   rt_off_t pos,
                                   void* buffer,
                                   rt_size_t size)
{
        struct spi_flash_device *aa = (struct spi_flash_device *)dev;
        const sfud_flash *flash = aa->flash;
        sfud_read(flash, pos*spi_flash_device.geometry.bytes_per_sector, size*spi_flash_device.geometry.bytes_per_sector, buffer);
       
    return size;
}

static rt_size_t sfud_flash_write(rt_device_t dev,
                                    rt_off_t pos,
                                    const void* buffer,
                                    rt_size_t size)
{
        rt_size_t i = 0;
    rt_size_t block = size;
    const uint8_t * ptr = buffer;
        struct spi_flash_device *aa = (struct spi_flash_device *)dev;
        const sfud_flash *flash = aa->flash;

        while(block--)
    {
        sfud_erase_write(flash,(pos + i)*spi_flash_device.geometry.bytes_per_sector,spi_flash_device.geometry.bytes_per_sector,ptr);
                //w25qxx_page_write((pos + i)*spi_flash_device.geometry.bytes_per_sector,ptr);
        ptr += spi_flash_device.geometry.bytes_per_sector;
        i++;
    }
       
    return size;
}

rt_err_t sfudxx_init(const char * flash_device_name)
{
    /* init flash */
        sfud_init();
        spi_flash_device.flash = sfud_get_device_table() + 0;
       
        spi_flash_device.geometry.bytes_per_sector = spi_flash_device.flash->chip.erase_gran;
    spi_flash_device.geometry.block_size = spi_flash_device.flash->chip.erase_gran;
        spi_flash_device.geometry.sector_count = spi_flash_device.flash->chip.capacity / spi_flash_device.geometry.bytes_per_sector;
    /* register device */
    spi_flash_device.flash_device.type    = RT_Device_Class_Block;
    spi_flash_device.flash_device.init    = sfud_flash_init;
    spi_flash_device.flash_device.open    = sfud_flash_open;
    spi_flash_device.flash_device.close   = sfud_flash_close;
    spi_flash_device.flash_device.read    = sfud_flash_read;
    spi_flash_device.flash_device.write   = sfud_flash_write;
    spi_flash_device.flash_device.control = sfud_flash_control;
    /* no private */
    spi_flash_device.flash_device.user_data = RT_NULL;

    rt_device_register(&spi_flash_device.flash_device, flash_device_name,
                       RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);

    return RT_EOK;
}

出0入0汤圆

发表于 2016-9-29 09:11:30 | 显示全部楼层
问题解决了,是我驱动写错了,现在上传文件系统驱动

出0入17汤圆

发表于 2016-9-29 09:07:46 | 显示全部楼层
赞一个,回头移植到ebox上不知道可行不

出0入17汤圆

发表于 2016-9-29 09:07:05 | 显示全部楼层
赞一个,回头移植到ebox上,不知道可行不

出0入0汤圆

发表于 2016-9-29 08:52:06 | 显示全部楼层
不错,支持楼主

出0入198汤圆

 楼主| 发表于 2016-9-29 08:31:07 | 显示全部楼层
coolhorse 发表于 2016-9-28 11:06
楼主你好,我移植了你的代码到RT THREAD,SPI FLASH挂载在/目录下,SPI FLASH创建了/SD目录,SD卡挂载在/SD ...

SFUD 本身只是驱动库,所有具体操作都要听从于上层应用的安排,所以它自己初始化时候是不会执行擦除的操作。

你这个现象倒是让我想到了,之前由于 EasyFlash 的 Log 功能还没有与 SPI Flash 对接好,所以当 EasyFlash 在 使用 SFUD 作为底层驱动时,Log 功能每次初始化在初始化过程中都会错误的擦除部分 Flash 区域。

不过这个 Bug 也很快修复了,如果使用了 EasyFlash ,建议也对其源码进行更新。

出0入198汤圆

 楼主| 发表于 2016-9-29 08:03:16 | 显示全部楼层
coolhorse 发表于 2016-9-28 11:06
楼主你好,我移植了你的代码到RT THREAD,SPI FLASH挂载在/目录下,SPI FLASH创建了/SD目录,SD卡挂载在/SD ...

是不是用最新源码测试的?当时一楼位置源码存在一个“采用 SFDP 参数在某些条件下,擦除命令选择不合适的问题”,后来修复了。

你可以在 GitHub : https://github.com/armink/SFUD 下载最新源码,并更换核心源码再试试。有结果了再跟帖留言。

出0入0汤圆

发表于 2016-9-28 11:06:40 | 显示全部楼层
楼主你好,我移植了你的代码到RT THREAD,SPI FLASH挂载在/目录下,SPI FLASH创建了/SD目录,SD卡挂载在/SD下,第一次启动后都可以正常挂载,第二次后发现/SD目录丢失,请问SPI FLASH每次初始化后都清除一次FLASH吗?

出0入0汤圆

发表于 2016-9-26 22:39:25 | 显示全部楼层
SPI——Flash驱动

出0入0汤圆

发表于 2016-9-25 16:44:39 | 显示全部楼层
感谢楼主的开源

出0入0汤圆

发表于 2016-9-17 10:55:31 | 显示全部楼层
强人开源代码不错,值得学习一下,谢谢分享!

出0入0汤圆

发表于 2016-9-17 10:42:56 | 显示全部楼层
这个东西真不错

出0入0汤圆

发表于 2016-9-17 10:04:15 | 显示全部楼层
感谢楼主分享

出0入0汤圆

发表于 2016-8-29 09:10:02 | 显示全部楼层
感谢无私分享

出0入0汤圆

发表于 2016-8-29 07:21:10 来自手机 | 显示全部楼层
这个得非常支持

出0入0汤圆

发表于 2016-8-29 05:54:18 | 显示全部楼层
感谢楼主分享,非常非常好的参考。谢谢。

出0入198汤圆

 楼主| 发表于 2016-8-28 22:57:32 | 显示全部楼层

刚才又推送更新了,建议选中 watch 项目,及时关注项目更新信息。

出0入198汤圆

 楼主| 发表于 2016-8-28 22:56:28 | 显示全部楼层
maimaige 发表于 2016-8-27 22:35
楼主,你的代码这么规范,是遵循的什么原则啊,有文档和资料或者书,参考一下不,或者遵循什么编码规范 ...

主要是借鉴的 RT-Thread 操作系统编程的规范。

出0入0汤圆

发表于 2016-8-28 17:24:37 来自手机 | 显示全部楼层
这份好,感谢楼主辛勤劳动

出0入0汤圆

发表于 2016-8-28 16:37:37 | 显示全部楼层
支持楼主,非常棒

出0入0汤圆

发表于 2016-8-27 23:48:02 | 显示全部楼层
谢谢分享,非常有用

出0入0汤圆

发表于 2016-8-27 22:54:42 | 显示全部楼层
已Clone到本地

出0入0汤圆

发表于 2016-8-27 22:54:12 | 显示全部楼层
谢谢分享!!!

出0入0汤圆

发表于 2016-8-27 22:52:33 | 显示全部楼层
很好啊,可以节省很多事情,可移植性强

出0入0汤圆

发表于 2016-8-27 22:35:01 | 显示全部楼层
楼主,你的代码这么规范,是遵循的什么原则啊,有文档和资料或者书,参考一下不,或者遵循什么编码规范

出0入0汤圆

发表于 2016-8-27 21:01:44 来自手机 | 显示全部楼层
有空学习学习,赞一个

出0入198汤圆

 楼主| 发表于 2016-8-27 20:34:47 | 显示全部楼层
coolhorse 发表于 2016-8-27 10:25
//软件版本号定义
const char sw_ver_name[] @ ".version" = "swver";
const char sw_ver_value[] @ ".vers ...

这里定义了两个字符串 sw_ver_name 及 sw_ver_value (软件版本号内容),和平时定义字符串的区别是这两个字符串是放在 ROM 的 ".version" 段内的。

而 ".version" 段可以固定在 ROM 的某个固定地址,这样上位机软件、BootLoader 软件获取到了软件 bin 后,可以访问 bin 文件的固定地址内容来获取此 bin 文件对应的软件版本号,以便于在更新软件时的对版本信息进行检查与确认。

出0入0汤圆

发表于 2016-8-27 10:25:50 | 显示全部楼层
//软件版本号定义
const char sw_ver_name[] @ ".version" = "swver";
const char sw_ver_value[] @ ".version" = "0.06.23";
这个用法还是第一次看到,作者能解释一下吗

出0入0汤圆

发表于 2016-8-27 09:05:37 | 显示全部楼层
万能 SPI Flash 驱动库  mark

出0入0汤圆

发表于 2016-8-27 08:55:31 | 显示全部楼层
感谢楼主开源,造福我们小白,虽然现在用不上,以后肯定能用上
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-14 17:34

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表