FlashDB移植

  • 硬件基础:野火霸道V2,外部Flash移植测试

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 高电平 */
    }
    
  • 在这里插入图片描述

fal移植

  • 可以参考事在人wёi的fal移植博客,他也有一篇sfud移植的博文,写的也很好
  • 移植好sfud后,fal移植比较简单,先修改fal_cfg.h,添加宏定义并根据需要修改宏定义
#define FAL_DEBUG 1
#define FAL_PART_HAS_TABLE_CFG
#define FAL_USING_SFUD_PORT

#define NOR_FLASH_DEV_NAME             "norflash0"

/* flash device table */
#define FAL_FLASH_DEV_TABLE                                          \
{                                                                    \
    &nor_flash0,                                                     \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE                                                               \
{                                                                                    \
    {FAL_PART_MAGIC_WORD,  "fdb_tsdb1",       "norflash0",           0, 1024*1024, 0}, \
    {FAL_PART_MAGIC_WORD,  "fdb_kvdb1",       "norflash0",   1024*1024, 1024*1024, 0}, \
}
  • 其次修改sfud_port.c,SFUD_W25Q64BV_DEVICE_INDEX为sfud_cfg中定义的
#else
    /* bare metal platform */
    // extern sfud_flash sfud_norflash0;
    // sfud_dev = &sfud_norflash0;
    sfud_dev = sfud_get_device(SFUD_W25Q64BV_DEVICE_INDEX); 
#endif
  • 最后在sfud初始化后调用fal_init()测试即可

fdb移植

  • 只需要将fdb_cfg头文件中的宏定义设置为1
#define FDB_WRITE_GRAN                1
  • 然后复制demo中的测试代码即可
  • 14
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值