[FlashDB]基于GD32纯代码裸机移植FlashDB数据库——三、移植SFUD

【相关文章导航】

[FlashDB]基于GD32纯代码裸机移植FlashDB数据库——一、介绍
[FlashDB]基于GD32纯代码裸机移植FlashDB数据库——二、移植前准备
[FlashDB]基于GD32纯代码裸机移植FlashDB数据库——三、移植SFUD
[FlashDB]基于GD32纯代码裸机移植FlashDB数据库——四、移植Fal
[FlashDB]基于GD32纯代码裸机移植FlashDB数据库——五、移植FlashDB

五、移植SFUD

5.1 移植步骤

  1. 移动源代码
  2. 在Keil的文件组中添加源文件
  3. 修改 sfud_flash_def.h 文件
  4. 修改 sfud_cfg.h 文件
  5. 修改 sfud_port.c 文件
  6. 测试SFUD

5.2 移动源码文件

移动源码文件到当前工程相应文件夹下,如下图:

在这里插入图片描述

5.3 在Keil的文件组中添加源文件

在这里插入图片描述

5.4 修改 sfud_flash_def.h 文件

当前使用Flash为GD25Q32sfud_flash_def.h文件的宏定义SFUD_FLASH_CHIP_TABLE中无此型号Flash芯片,在 line139添加此芯片型号。

如下图:

在这里插入图片描述

代码如下:

	{"GD25Q32B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x15, 4L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                 \

5.5 修改 sfud_cfg.h 文件

定义当前flash标识符。如下图:

在这里插入图片描述

代码如下:

#ifndef _SFUD_CFG_H_
#define _SFUD_CFG_H_

#define SFUD_DEBUG_MODE

#define SFUD_USING_SFDP

#define SFUD_USING_FLASH_INFO_TABLE

enum {
    SFUD_GD25Q32_DEVICE_INDEX = 0,
};

#define SFUD_FLASH_DEVICE_TABLE                                                \
{                                                                              \
    [SFUD_GD25Q32_DEVICE_INDEX] = {.name = "GD25Q32", .spi.name = "SPI0"},           \
}

#endif /* _SFUD_CFG_H_ */

说明:

  1. 此处定义的标识符在后面需要使用。

5.6 修改 sfud_port.c 文件

关键修改两处:

  1. 实现函数spi_write_read,即SPI的读写函数;

    调用自己实现的读写函数,从头文件bsp_flash_drv.h引用。

  2. 实现函数sfud_spi_port_init,即SPI的初始化;

    调用自己实现的SPI初始化函数,从头文件bsp_flash_drv.h引用。

上述两个函数的实现,请参考4.6。

请参考如下代码:(原代码未删除,仅屏蔽掉了。可做参考)

#include <sfud.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
//#include <stm32f4xx_hal.h>

#include "bsp_flash_drv.h"

//typedef struct {
//    SPI_TypeDef *spix;
//    SPI_HandleTypeDef *spi_handle;
//    GPIO_TypeDef *cs_gpiox;
//    uint16_t cs_gpio_pin;
//} spi_user_data, *spi_user_data_t;

/* 用户数据 */
uint32_t SPI_userData;

static char log_buf[256];

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

static SPI_HandleTypeDef hspi2;
//static void spi_configuration(spi_user_data_t spi)
//{
//    SPI_HandleTypeDef *spi_handle = spi->spi_handle;

//    spi_handle->Instance = spi->spix;
//    spi_handle->Init.Mode = SPI_MODE_MASTER;
//    spi_handle->Init.Direction = SPI_DIRECTION_2LINES;
//    spi_handle->Init.DataSize = SPI_DATASIZE_8BIT;
//    spi_handle->TxXferSize = 8;
//    spi_handle->RxXferSize = 8;
//    spi_handle->Init.CLKPhase = SPI_PHASE_1EDGE;
//    spi_handle->Init.CLKPolarity = SPI_POLARITY_LOW;
//    spi_handle->Init.NSS = SPI_NSS_SOFT;
//    spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
//    spi_handle->Init.FirstBit = SPI_FIRSTBIT_MSB;
//    spi_handle->Init.TIMode = SPI_TIMODE_DISABLE;
//    spi_handle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
//    spi_handle->State = HAL_SPI_STATE_RESET;
//    HAL_SPI_Init(spi_handle);
//}

static void spi_lock(const sfud_spi *spi) {
    __disable_irq();
}

static void spi_unlock(const sfud_spi *spi) {
    __enable_irq();
}

/**
 * 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) {
    sfud_err result = SFUD_SUCCESS;
//    spi_user_data_t spi_dev = (spi_user_data_t) spi->user_data;
//    HAL_StatusTypeDef state = HAL_OK;

    if (write_size) {
        SFUD_ASSERT(write_buf);
    }
    if (read_size) {
        SFUD_ASSERT(read_buf);
    }

//    HAL_GPIO_WritePin(spi_dev->cs_gpiox, spi_dev->cs_gpio_pin, GPIO_PIN_RESET);

//    if (write_size) {
//        state = HAL_SPI_Transmit(spi_dev->spi_handle, (uint8_t *)write_buf, write_size, 1000);
//        while (HAL_SPI_GetState(spi_dev->spi_handle) != HAL_SPI_STATE_READY);
//    }

//    if (state != HAL_OK) {
//        goto __exit;
//    }

//    if (read_size) {
//        memset((uint8_t *)read_buf, 0xFF, read_size);
//        state = HAL_SPI_Receive(spi_dev->spi_handle, read_buf, read_size, 1000);
//        while (HAL_SPI_GetState(spi_dev->spi_handle) != HAL_SPI_STATE_READY);
//    }

//__exit:

//    HAL_GPIO_WritePin(spi_dev->cs_gpiox, spi_dev->cs_gpio_pin, GPIO_PIN_SET);

	user_spi_flash_page_write(write_buf ,write_size);
	user_spi_flash_buffer_read(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 spi2 = { .spix = SPI2, .cs_gpiox = GPIOB, .cs_gpio_pin = GPIO_PIN_12, .spi_handle = &hspi2};
sfud_err sfud_spi_port_init(sfud_flash *flash) {
    sfud_err result = SFUD_SUCCESS;

//    if (!strcmp(flash->spi.name, "SPI2"))
//    {
//        GPIO_InitTypeDef GPIO_Initure;
//        /* SPI 外设初始化 */
//        spi_configuration(&spi2);
//        /* 初始化 CS 引脚 */
//        GPIO_Initure.Pin = spi2.cs_gpio_pin;
//        GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;
//        GPIO_Initure.Pull = GPIO_PULLUP;
//        GPIO_Initure.Speed = GPIO_SPEED_FREQ_HIGH;
//        HAL_GPIO_Init(spi2.cs_gpiox, &GPIO_Initure);
//        HAL_GPIO_WritePin(spi2.cs_gpiox, spi2.cs_gpio_pin, GPIO_PIN_SET);
//        /* 同步 Flash 移植所需的接口及数据 */
//        flash->spi.wr = spi_write_read;
//        flash->spi.lock = spi_lock;
//        flash->spi.unlock = spi_unlock;
//        flash->spi.user_data = &spi2;
//        /* about 100 microsecond delay */
//        flash->retry.delay = retry_delay_100us;
//        /* adout 60 seconds timeout */
//        flash->retry.times = 60 * 10000;
//    }

	switch (flash->index){
		case SFUD_GD25Q32_DEVICE_INDEX:{
			
			bsp_spi_flash_init();
			
			/* 同步 Flash 移植所需的接口及数据 */
			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);
    printf("[SFUD](%s:%ld) ", file, line);
    /* must use vprintf to print */
    vsnprintf(log_buf, sizeof(log_buf), format, args);
    printf("%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);
    printf("[SFUD]");
    /* must use vprintf to print */
    vsnprintf(log_buf, sizeof(log_buf), format, args);
    printf("%s\r\n", log_buf);
    va_end(args);
}

至此,SFUD移植完成!!!

然后测试SFUD移植是否成功。。。

5.7 测试SFUD

  1. SFUD测试函数实现:

    void sfud_test(uint32_t addr, size_t size, uint8_t *data)
    {
    	sfud_err result = SFUD_SUCCESS;
        extern sfud_flash *sfud_dev;
        const sfud_flash *flash = sfud_get_device(SFUD_GD25Q32_DEVICE_INDEX);
        size_t i;
        /* prepare write data */
        for (i = 0; i < size; i++)
        {
            data[i] = i;
        }
        /* erase test */
        result = sfud_erase(flash, addr, size);
        if (result == SFUD_SUCCESS)
        {
            printf("Erase the %s flash data finish. Start from 0x%08X, size is %zu.\r\n", flash->name, addr, size);
        }
        else
        {
            printf("Erase the %s flash data failed.\r\n", flash->name);
            return;
        }
        /* write test */
        result = sfud_write(flash, addr, size, data);
        if (result == SFUD_SUCCESS)
        {
            printf("Write the %s flash data finish. Start from 0x%08X, size is %zu.\r\n", flash->name, addr, size);
        }
        else
        {
            printf("Write the %s flash data failed.\r\n", flash->name);
            return;
        }
        /* read test */
        result = sfud_read(flash, addr, size, data);
        if (result == SFUD_SUCCESS)
        {
            printf("Read the %s flash data success. Start from 0x%08X, size is %zu. The data is:\r\n", flash->name, addr, size);
            printf("Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\r\n");
            for (i = 0; i < size; i++)
            {
                if (i % 16 == 0)
                {
                    printf("[%08X] ", addr + i);
                }
                printf("%02X ", data[i]);
                if (((i + 1) % 16 == 0) || i == size - 1)
                {
                    printf("\r\n");
                }
            }
            printf("\r\n");
        }
        else
        {
            printf("Read the %s flash data failed.\r\n", flash->name);
        }
        /* data check */
        for (i = 0; i < size; i++)
        {
    				
            if (data[i] != i % 256)
            {
                printf("Read and check write data has an error. Write the %s flash data failed.\r\n", flash->name);
                break;
            }
        }
        if (i == size)
        {
            printf("The %s flash test is success.\r\n", flash->name);
        }
    }
    
  2. 测试,主函数代码如下:

    #include "sfud.h"
    
    #define SFUD_DEMO_TEST_BUFFER_SIZE                     1024
    static uint8_t sfud_demo_test_buf[SFUD_DEMO_TEST_BUFFER_SIZE];
    
    int main(void)
    {
        systick_config();
    	
    	led_init();
    	
    	gd_eval_com_init(EVAL_COM);    //初始化串口1
    	
    	sfud_init();  //SFUD初始化
    	
    	sfud_test(0, sizeof(sfud_demo_test_buf), sfud_demo_test_buf);
    
        while(1) 
    	{
    		printf("测试成功!!!");
    		led_flash(5);
        }
    }
    
  3. 测试结果如下:

    在这里插入图片描述

    在这里插入图片描述

打印结果提示,Flash初始化成功! Flash测试成功!

至此,SFUD正常工作,移植完成。

接下来进行Fal移植。。。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值