SPI Flash 详解

本文详细介绍了SPI Flash的驱动实现,包括初始化、erase、write和read操作。通过解析JEDEC ID和SFDP标准获取Flash参数,实现对不同Flash型号的支持。初始化时,优先读取SFDP表参数,若不支持则依赖配置文件。erase操作涉及选择合适的擦除命令,write操作确保按页对齐写入,read操作相对简单。该开源库适合无OS或微内核系统的工程使用。
摘要由CSDN通过智能技术生成

一、序

     写这篇文章的目的是今天偶来间看到了 开源库https://github.com/armink/SFUD.git ,遥想起当年入职时的前几个任务就是针对自家的spi flash controller 写一个driver来驱动外置的flash,因为code 固化在rom 中,所以尽量需要兼容不同厂家的flash型号,当时也是折腾了很久。今天有幸看到这份源码,还是满满的回忆。

二. 源码剖析

2.1 初始化

初始化的核心函数在hardware_init中,也体现了识别板载flash型号的核心策略:


首先读取 JEDEC ID,其中包含了manufacturer ID, memory type ID 和flash capacity ID;

然后判断当前flash是否支持SFDP。SFDP标准是JEDEC (固态技术协会)制定的串行 Flash 功能的参数表标准,最新版 V1.6B ([点击这里查看](https://www.jedec.org/standards-documents/docs/jesd216b))。该标准规定了,每个 Flash 中会存在一个参数表,该表中会存放 Flash 容量、写粒度、擦除命令、地址模式等 Flash 规格参数。目前,除了部分厂家旧款 Flash 型号会不支持该标准,其他绝大多数新出厂的 Flash 均已支持 SFDP 标准。所以该库在初始化时会优先读取 SFDP 表参数。

 如果该 Flash 不支持 SFDP 标准,SFUD 会查询配置文件 中提供的 Flash 参数信息表 中是否支持该款 Flash。如果不支持,则可以在配置文件中添加该款 Flash 的参数信息。获取到了 Flash 的规格参数后,就可以实现对 Flash 的全部操作。


/**
 * hardware initialize
 */
static sfud_err hardware_init(sfud_flash *flash) {
    extern sfud_err sfud_spi_port_init(sfud_flash * flash);

    sfud_err result = SFUD_SUCCESS;
    size_t i;


    result = sfud_spi_port_init(flash);
    if (result != SFUD_SUCCESS) {
        return result;
    }

    /* if the user don't configure flash chip information then using SFDP parameter or static flash parameter table */
    if (flash->chip.capacity == 0 || flash->chip.write_mode == 0 || flash->chip.erase_gran == 0
            || flash->chip.erase_gran_cmd == 0) {
        /* read JEDEC ID include manufacturer ID, memory type ID and flash capacity ID */
        result = read_jedec_id(flash);
        if (result != SFUD_SUCCESS) {
            return result;
        }

#ifdef SFUD_USING_SFDP
        extern bool sfud_read_sfdp(sfud_flash *flash);
        /* read SFDP parameters */
        if (sfud_read_sfdp(flash)) {
            flash->chip.name = NULL;
            flash->chip.capacity = flash->sfdp.capacity;
            /* only 1 byte or 256 bytes write mode for SFDP */
            if (flash->sfdp.write_gran == 1) {
                flash->chip.write_mode = SFUD_WM_BYTE;
            } else {
                flash->chip.write_mode = SFUD_WM_PAGE_256B;
            }
            /* find the the smallest erase sector size for eraser. then will use this size for erase granularity */
            flash->chip.erase_gran = flash->sfdp.eraser[0].size;
            flash->chip.erase_gran_cmd = flash->sfdp.eraser[0].cmd;
            for (i = 1; i < SFUD_SFDP_ERASE_TYPE_MAX_NUM; i++) {
                if (flash->sfdp.eraser[i].size != 0 && flash->chip.erase_gran > flash->sfdp.eraser[i].size) {
                    flash-&
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值