sfud移植

news2024/9/27 19:27:16

sfud移植

  • 首先看readme文档
文件结构
  • inc文件夹:各种头文件,注意flash_def和cfg头文件

  • port文件夹:接口文件

  • src文件夹:代码源文件

移植
  • 基础:你的SPI没问题,用普通工程可以正常操作Flash

  • 首先打开flash_def头文件,SFUD_FLASH_CHIP_TABLE宏定义是否有你使用的FLASH

  • 若没有则添加,

    • 比着葫芦画个瓢,名字 厂商ID 类型id 容量id 8M容量 page 256字节 sector 4KB 擦除命令

    • 这几个参数可以在芯片pdf找到,Manufacturer and Device Identification表和BLOCK DIAGRAM框图

      • 请添加图片描述请添加图片描述

      • 请添加图片描述

    • {"W25Q64BV", SFUD_MF_ID_WINBOND, 0x40, 0x17, 8L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                    \
      
  • 打开cfg头文件,在枚举和宏定义,添加你的Flash型号

    • enum {
          SFUD_W25Q64BV_DEVICE_INDEX = 0,
      };
      
      #define SFUD_FLASH_DEVICE_TABLE                                                \
      {                                                                              \
          [SFUD_W25Q64BV_DEVICE_INDEX] = {.name = "W25Q64BV", .spi.name = "SPI1"},           \
      }
      
  • 主要修改两个函数:spi_write_read和sfud_spi_port_init,在init函数绑定一些函数和初始化外设, SPI 读写驱动(必选)、重试次数(必选)、重试接口(可选)及 SPI 锁(可选)的配置。

  • 分析代码后发现是各种函数都给在sfud.c实现了,例如开写保护发送0x06,在sfud.c中set_write_enabled实现,0x06命令对应宏定义SFUD_CMD_WRITE_ENABLE,如果命令与一般命令不同,可以通过自己定义宏定义进行覆盖。

  • 因此spi_write_read函数只需要实现单纯数据发送和接收,不需要考虑其他

  • 最后在主函数调用sfud_init()即可,最后打印success即移植成功

  • 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)
    {
        sfud_err result = SFUD_SUCCESS;
    
        if (write_size)
        {
            SFUD_ASSERT(write_buf);
        }
        if (read_size)
        {
            SFUD_ASSERT(read_buf);
        }
    
        SPI_FLASH_CS_LOW(); // 片选拉低
        if (write_size)
        {
            SPI_FLASH_Write_Simple((uint8_t *)write_buf, write_size);
        }
        if (read_size)
        {
            memset((uint8_t *)read_buf, 0xFF, read_size);
            SPI_FLASH_Read_Simple((uint8_t *)read_buf, read_size);
        }
        SPI_FLASH_CS_HIGH(); // 片选拉高
    
        return result;
    }
    
    /* about 100 microsecond delay */
    static void retry_delay_100us(void)
    {
        uint32_t delay = 120;
        while (delay--)
            ;
    }
    
    static spi_user_data SPI_userData = {.spix = SPI1, .cs_gpiox = GPIOA, .cs_gpio_pin = GPIO_Pin_4};
    sfud_err sfud_spi_port_init(sfud_flash *flash)
    {
        sfud_err result = SFUD_SUCCESS;
    
        // 直接调用自己的初始化函数
        SPI_FLASH_Init();
        // 追根溯源,sfud_flash这个参数有一部分为
        // sfud_cfg.h中的SFUD_FLASH_DEVICE_TABLE
        switch (flash->index)
        {
        case SFUD_W25Q64BV_DEVICE_INDEX: // 是在 sfud_cfg.h 中定义的
        {
            flash->spi.wr = spi_write_read;
            flash->spi.lock = spi_lock;
            flash->spi.unlock = spi_unlock;
            flash->spi.user_data = &SPI_userData;
            /* about 100 microsecond delay */
            flash->retry.delay = retry_delay_100us;
            /* adout 60 seconds timeout */
            flash->retry.times = 60 * 10000;
    
            break;
        }
        }
    
        return result;
    }
    
  • uint8_t SPI_FLASH_SendByte(uint8_t byte)
    {
        // 因为是全双工,接和收同时进行
        SPITimeout = SPIT_FLAG_TIMEOUT;
        /* 等待发送缓冲区为空,TXE事件 */
        while (SPI_I2S_GetFlagStatus(FLASH_SPIx, SPI_I2S_FLAG_TXE) == RESET)
        {
            if ((SPITimeout--) == 0)
                return SPI_TIMEOUT_UserCallback(0);
        }
    
        /* 写入数据寄存器,把要写入的数据写入发送缓冲区 */
        SPI_I2S_SendData(FLASH_SPIx, byte);
    
        SPITimeout = SPIT_FLAG_TIMEOUT;
        /* 等待接收缓冲区非空,RXNE事件 */
        while (SPI_I2S_GetFlagStatus(FLASH_SPIx, SPI_I2S_FLAG_RXNE) == RESET)
        {
            if ((SPITimeout--) == 0)
                return SPI_TIMEOUT_UserCallback(1);
        }
    
        /* 读取数据寄存器,获取接收缓冲区数据 */
        return SPI_I2S_ReceiveData(FLASH_SPIx);
    }
    void SPI_FLASH_Write_Simple(uint8_t *pBuffer, uint16_t NumByteToWrite)
    {
        // 片选统一使能
        /* 写入数据*/
        while (NumByteToWrite--)
        {
            /* 发送当前要写入的字节数据 */
            SPI_FLASH_SendByte(*pBuffer);
            /* 指向下一字节数据 */
            pBuffer++;
        }
    }
    void SPI_FLASH_Read_Simple(uint8_t *pBuffer, uint16_t NumByteToRead)
    {
        /* 选择FLASH: CS低电平 */
        /* 读取数据 */
        while (NumByteToRead--) /* while there is data to be read */
        {
            /* 读取一个字节*/
            *pBuffer = SPI_FLASH_SendByte(Dummy_Byte);
            /* 指向下一个字节缓冲区 */
            pBuffer++;
        }
        /* 停止信号 FLASH: CS 高电平 */
    }
    
  • 在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2089294.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

cloudways相关

服务器优惠链接: https://www.cloudways.com/en/?id1081165 cloudways 后台清缓存位置: 网站迁移到cloudways(用cloudways的自动迁移插件): 不管原网站是不是用的cloudways主机,都可以用这个方法。 1…

【React】react项目安装tailwindcss

创建React项目 首先,如果您还没有React项目,可以使用以下命令创建一个新项目: npx create-react-app my-tailwind-app cd my-tailwind-app安装Tailwind CSS 接下来,按照以下步骤安装Tailwind CSS: 安装必要的依赖: npm install -D tailwindcss postcss autoprefixer初始化…

Kubernetes 1.31 新功能: 细粒度补充组控制

这篇文章讨论了 Kubernetes 1.31 中的一个新特性,用于改善 Pod 中容器的补充组(Fine-grained SupplementalGroups control)处理。 动机:在容器镜像中的 /etc/group 定义的隐式组成员身份 尽管这种行为可能并不受许多 Kubernetes…

Redis安装+常用命令合集大全+Redis Desktop Manager

文章目录 一:Redis 简介二:安装和配置Redis第一步:下载Redis第二步:解压Redis第三步:配置Redis第四步:启动Redis服务器第五步:验证Redis安装第六步:设置Redis为全局命令 三&#xff…

不同品类商标一样属于侵权吗!

商标分类有45类,有网友问普推知产商标老杨,不同品类商标一样属于侵权吗,这个要从多个角度来分析,不同品类商标是相同一样的,这样的基本不侵权的。 在注册申请商标是会经常遇到别人在某类别注册,但是有一些类…

[Meachines] [Insane] Bankrobber XSS-MDOG+SQLI+XSRF+Local-RCE+Bankv2转账模拟应用缓冲区溢出

信息收集 IP AddressOpening Ports10.10.10.154TCP:80,443,445,3306 $ nmap -p- 10.10.10.154 --min-rate 1000 -sC -sV -Pn PORT STATE SERVICE VERSION 80/tcp open http …

各个击破:NetXpert XG2帮您解决“布线安装与维护”难题

在传输大量数据时,光纤变得越来越重要,而铜缆在未来也将继续发挥重要作用,因此我们不仅要比较两种类型布线的优缺点,还要探究光纤传输中的错误来源。 测试光缆传输损耗的准确性对于故障排除至关重要,特别是在光纤情况下…

hadoop技术

历史版本 HA:高可用 技术框架

[线程]线程不安全问题 --- 死锁

文章目录 一. 引出死锁二. 可重用锁三. 死锁的三种典型场景四. 死锁产生的四个必要条件(面试题)1. 锁具有互斥特性2. 锁不可抢占(不可被剥夺)3. 请求和保持4. 循环等待 五. 避免死锁问题 一. 引出死锁 class Counter{private int count;public void add(){synchronized(this){…

深度学习语义分割篇——DeeplabV3原理详解+源码实战

🍊作者简介:秃头小苏,致力于用最通俗的语言描述问题 🍊专栏推荐:深度学习网络原理与实战 🍊近期目标:写好专栏的每一篇文章 🍊支持小苏:点赞👍🏼、…

域内安全:委派攻击

目录 域委派 非約束性委派攻击: 主动访问: 被动访问(利用打印机漏洞) 约束性委派攻击: 域委派 域委派是指将域内用户的权限委派给服务账户,使得服务账号能够以用户的权限在域内展开活动。 委派是域中…

机器学习——决策树模型

决策树原理 算法概述 从根节点开始一步步走到叶子节点(决策) 所有数据最终都会落到叶子节点,既可以做分类也可以做回归 例如上例,输入一个数据后,先判断他的年龄,然后再判断性别 在决策树中&#xff0c…

day45.动态规划

1035.不相交的线: 在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。 现在,可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线,这些直线需要同时满足: nums1[i] nums2[j] 且绘制的直线不与任何其他连线(非水…

基站定位系统的创新应用:企业管理的新利器

在现代企业的管理中,基站定位系统已经成为不可或缺的技术手段。通过这一系统,企业能够实时掌握物资、人员的位置和状态,提升管理效率和安全性。常达智能物联凭借深厚的技术积累和丰富的项目经验,为各类企业提供了创新的基站定位系…

如何使用ChatGPT,提示词篇之【编程代码】

一、 ChatGPT可以做什么? ChatGPT能做的事情非常多!它不仅仅是一个对话AI。以下是一些主要功能: 1. 回答问题:无论是学术问题、技术问题,还是生活琐事,ChatGPT都能提供帮助。 2. 写作助手:可以…

Angular17(3):Angular项目中引入iconfont

在Angular项目中引入Iconfont(图标字体)是一个常见的需求,用于在应用中添加丰富的图标资源。 Iconfont-阿里巴巴矢量图标库 1、点击进入官网,注册并登录 2、登陆成功后,首页的 资源管理 > 我的项目 点击进入 3、…

网络通信---四次挥手

文章目录 概述四次挥手第一次挥手:第二次挥手:第三次挥手:第四次挥手: 问题:为什么是四次,而不是三次?确保数据传输完成:防止数据丢失:避免旧连接干扰:防止死…

C#的继承

继承是面向对象程序设计中最重要的概念之一.继承允许我们根据一个类来定义另一个类,这使得创建和维护应用程序变得更容易,同时,也有利用重用代码和节省开发时间. 当创建一个类时,程序员不需要完全重新编写新的数据成员和成员函数只需要设计一个新的类,继承了已有的类的成员即可…

斯坦福UE4 C++课学习补充23:AI自定义任务

文章目录 一、自定义任务节点二、优化1. 子弹发射冷却2. 攻击时面朝玩家 一、自定义任务节点 本节需要创建自定义任务节点BTTask,实现小兵进入角色范围后进射击的功能。对于BTTaskNode的子类,我们需要在代码中重写ExecuteTask函数即可。返回值为EBTNode…

博客自建(带避坑指南)4:hexo文章页设置和动画魔改设置

咕咕了好久,这次终于来更新一下 看完上一篇博客: 博客自建(带避坑指南)3:简单的hexo网页界面设置-CSDN博客 想必你已经完成了头像、图片等一些基础的设置,但是这些改动都是比较基础的,现在我们…