GD32手把手教你移植FlashDB(片外Flash) – 1.FlashDB-sfud移植
GD32手把手教你移植FlashDB(片外Flash) – 2.FlashDB移植
GD32手把手教你移植FlashDB(片外Flash) – 3.FlashDB使用
示例代码: https://gitee.com/ljmRD/GD32F427_FlashDB
1.FlashDB-sfud移植
我使用的是GD32F427开发板(标准库),上面使用SPI0连接W25Q128
使用片外Flash
,在使用FlashDB
库之前,需要先把sfud
移植好
FlashDB库下载:
https://gitee.com/Armink/FlashDB
1.添加sfud
到工程
路径:FlashDB\demos\stm32f405rg_spi_flash\sfud
2.修改sfud_cfg.h
#ifndef _SFUD_CFG_H_
#define _SFUD_CFG_H_
#define SFUD_DEBUG_MODE // 日志输出
#define SFUD_USING_SFDP // 使能SFDP读取
#define SFUD_USING_FLASH_INFO_TABLE // 使能Flash设备表读取
enum
{
SFUD_W25Q128_DEVICE_INDEX = 0, // 根据实际情况修改
};
// Flash列表
#define SFUD_FLASH_DEVICE_TABLE \
{ \
[SFUD_W25Q128_DEVICE_INDEX] = {.name = "W25Q128BV", .spi.name = "SPI0"}, \
}
#endif /* _SFUD_CFG_H_ */
3.修改sfud_port.c
sfud_port.c
:需要添加对应硬件驱动代码(也就行SPI的读/写)
示例中使用的是STM32的HAL库,需要更换为GD32标准库的代码
1.sfud-日志输出
2.修改sfud_spi_port_init
// 1.初始化CS引脚 (我的代码是在别的地方已经初始化了)
// 2.初始化SPI (我的代码是在别的地方已经初始化了)
// 3.同步 Flash 移植所需的接口及数据 (重点
)
sfud_err sfud_spi_port_init(sfud_flash *flash)
{
sfud_err result = SFUD_SUCCESS;
// 1.初始化CS引脚
// 2.初始化SPI
// 3.同步 Flash 移植所需的接口及数据
switch (flash->index)
{
case SFUD_W25Q128_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;
}
2.修改spi_write_read
直接看代码备注吧
下面是完整的sfud_port.c
#include <sfud.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "SEGGER_RTT.h"
#include "./BSP/NORFLASH/norflash.h"
static uint32_t SPI_userData; // 用户数据
static char log_buf[256]; // 日志缓存Buff
void sfud_log_debug(const char *file, const long line, const char *format, ...);
static void spi_lock(const sfud_spi *spi)
{
__disable_irq();
}
static void spi_unlock(const sfud_spi *spi)
{
__enable_irq();
}
/**
* @brief 这是GD32标准库提供的SPI读写接口
*
* @param byte
* @return uint8_t
*/
uint8_t bsp_spi_flash_send_byte(uint8_t byte)
{
while (RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_TBE)) // 等待发送缓冲区空
; //
spi_i2s_data_transmit(SPI0, byte); // 发送一个字节
//
while (RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE)) // 等待接收缓冲区非空
; //
return (spi_i2s_data_receive(SPI0)); // 返回收到的数据
}
/**
* @brief SPI连续写多个字节接口
*
* @param pbuffer
* @param num_byte_to_write
*/
void user_spi_flash_page_write(const uint8_t *pbuffer, uint16_t num_byte_to_write)
{
/* while there is data to be written on the flash */
while (num_byte_to_write--)
{
/* send the current byte */
bsp_spi_flash_send_byte(*pbuffer);
/* point on the next byte to be written */
pbuffer++;
}
}
/**
* @brief SPI连续读多个字节
*
* @param pbuffer
* @param num_byte_to_read
*/
void user_spi_flash_buffer_read(uint8_t *pbuffer, uint16_t num_byte_to_read)
{
/* while there is data to be read */
while (num_byte_to_read--)
{
/* read a byte from the flash */
*pbuffer = bsp_spi_flash_send_byte(0xFF);
/* point to the next location where the byte read will be saved */
pbuffer++;
}
}
/**
* @brief SIP读写接口
*
* @param spi
* @param write_buf 写缓存
* @param write_size 写长度
* @param read_buf 读缓存
* @param read_size 读长度
* @return sfud_err
*/
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);
}
NORFLASH_CS(0); // CS低
user_spi_flash_page_write(write_buf, write_size);
user_spi_flash_buffer_read(read_buf, read_size);
NORFLASH_CS(1); // CS高
return result;
}
/* about 100 microsecond delay */
static void retry_delay_100us(void)
{
uint32_t delay = 120;
while (delay--)
;
}
sfud_err sfud_spi_port_init(sfud_flash *flash)
{
sfud_err result = SFUD_SUCCESS;
// 1.初始化CS引脚
// 2.初始化SPI
// 3.同步 Flash 移植所需的接口及数据
switch (flash->index)
{
case SFUD_W25Q128_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;
}
/**
* 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);
LOG_DATA("[SFUD](%s:%ld) ", file, line);
/* must use vprintf to print */
vsnprintf(log_buf, sizeof(log_buf), format, args);
LOG_DATA("%s\r\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);
LOG_DATA("[SFUD]");
/* must use vprintf to print */
vsnprintf(log_buf, sizeof(log_buf), format, args);
LOG_DATA("%s\r\n", log_buf);
va_end(args);
}
3.在mian()里面初始化
#include "sfud.h"
int main(void)
{
// 别的东西初始化
sfud_init();
}
初始化过程输出的日志如下