GD32上SFUD万能Flash驱动移植


SFUD (Serial Flash Universal Driver) 串行 Flash 通用驱动库

移植前提

下载源码

前往下载

测试效果

在这里插入图片描述
在这里插入图片描述

移植过程

添加文件到工程目录

主要关注sfud文件夹和sfud项目文件在这里插入图片描述

keil项目中添加如下文件到工程,设置头文件包含路径

在这里插入图片描述

修改sfud_port.c文件

其主要实现spi的不同芯片平台底层驱动包括:

  • SPI的初始化
  • ms延时
  • 保护锁(针对多线程,若非系统则使用开关总中断方式防止打断操作)

使用操作系统的情况下直接使用开关总中断方式上锁解锁,则延时函数接口应使用操作系统的延时如osDelay不可使用HAL_Delay或其他利用中断计时的函数,避免systick无法进入中断导致线程无法运行或其他中断无法进入计时累积导致程序停留无法运行,如有使用出现问题注意此方向的排查

  • 读写操作
/*
 * This file is part of the Serial Flash Universal Driver Library.
 *
 * Copyright (c) 2016-2018, Armink, <[email protected]>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * 'Software'), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Function: Portable interface for each platform.
 * Created on: 2016-04-23
 */

#include <sfud.h>
#include <stdarg.h>
/*=============================外部接口==============================*/
#include "gd32f4xx.h"
#include "cmsis_os.h"
#include "systick.h"
#define  SPI_FLASH_CS_LOW()        gpio_bit_reset(GPIOG,GPIO_PIN_9)
#define  SPI_FLASH_CS_HIGH()       gpio_bit_set(GPIOG,GPIO_PIN_9)
#define WRITE            0x02     /* write to memory instruction */
#define QUADWRITE        0x32     /* quad write to memory instruction */
#define WRSR             0x01     /* write status register instruction */
#define WREN             0x06     /* write enable instruction */

#define READ             0x03     /* read from memory instruction */
#define QUADREAD         0x6B     /* read from memory instruction */
#define RDSR             0x05     /* read status register instruction */
#define RDID             0x9F     /* read identification */
#define SE               0x20     /* sector erase instruction */
#define BE               0xC7     /* bulk erase instruction */

#define WTSR             0x05     /* write status register instruction */

#define WIP_FLAG         0x01     /* write in progress(wip) flag */
#define DUMMY_BYTE       0xA5
static void spi_flash_init(void);
static uint8_t spi_flash_send_byte(uint8_t byte);
static uint16_t spi_flash_send_halfword(uint16_t half_word);
static void spi_flash_buffer_read(uint8_t* pbuffer, uint16_t num_byte_to_read);
static void spi_flash_page_write(const uint8_t* pbuffer, uint16_t num_byte_to_write);
/*SPI锁初始化*/
static void SPI_Lock_Init(void);
static void SPI_unlock(const struct __sfud_spi *spi);
static void SPI_lock(const struct __sfud_spi *spi);
osSemaphoreId SPI5TaskBinarySem01Handle;
osStaticSemaphoreDef_t SPI5TaskBinarySem01ControlBlock;
/*重试延时*/
static void SPI_Delay(void);
/*用户数据*/
uint32_t SPI_userData;
/*=============================END 外部接口==============================*/

static char log_buf[256];

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

/**
 * 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;
    uint8_t send_data, read_data;

    /**
     * add your spi write and read code
     */
    if (write_size)
    {
    
    
        SFUD_ASSERT(write_buf);
    }
    if (read_size)
    {
    
    
        SFUD_ASSERT(read_buf);
    }
	spi_flash_page_write(write_buf ,write_size);
	spi_flash_buffer_read(read_buf ,read_size);
		
	/* deselect the flash: chip select high */
    SPI_FLASH_CS_HIGH();
	return result;
}

/*=============================外部接口==============================*/
/*!
    \brief      initialize SPI5 GPIO and parameter
    \param[in]  none
    \param[out] none
    \retval     none
*/
static void spi_flash_init(void)
{
    
    
    spi_parameter_struct spi_init_struct;

    rcu_periph_clock_enable(RCU_GPIOG);
    rcu_periph_clock_enable(RCU_SPI5);

    /* SPI5_CLK(PG13), SPI5_MISO(PG12), SPI5_MOSI(PG14),SPI5_IO2(PG10) and SPI5_IO3(PG11) GPIO pin configuration */
    gpio_af_set(GPIOG, GPIO_AF_5, GPIO_PIN_10|GPIO_PIN_11| GPIO_PIN_12|GPIO_PIN_13| GPIO_PIN_14);
    gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10|GPIO_PIN_11| GPIO_PIN_12|GPIO_PIN_13| GPIO_PIN_14);
    gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO_PIN_10|GPIO_PIN_11| GPIO_PIN_12|GPIO_PIN_13| GPIO_PIN_14);

    /* SPI5_CS(PG9) GPIO pin configuration */
    gpio_mode_set(GPIOG, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_9);
    gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);

    /* chip select invalid */
    SPI_FLASH_CS_HIGH();

    /* SPI5 parameter config */
    spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;
    spi_init_struct.device_mode          = SPI_MASTER;
    spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;
    spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
    spi_init_struct.nss                  = SPI_NSS_SOFT;
    spi_init_struct.prescale             = SPI_PSC_32;
    spi_init_struct.endian               = SPI_ENDIAN_MSB;
    spi_init(SPI5, &spi_init_struct);

    /* set crc polynomial */
    spi_crc_polynomial_set(SPI5,7);

    /* quad wire SPI_IO2 and SPI_IO3 pin output enable */
    qspi_io23_output_enable(SPI5);

    /* enable SPI5 */
    spi_enable(SPI5);
}
/*!
    \brief      send a byte through the SPI interface and return the byte received from the SPI bus
    \param[in]  byte: byte to send
    \param[out] none
    \retval     the value of the received byte
*/
static uint8_t spi_flash_send_byte(uint8_t byte)
{
    
    
    /* loop while data register in not emplty */
    while(RESET == spi_i2s_flag_get(SPI5,SPI_FLAG_TBE));

    /* send byte through the SPI5 peripheral */
    spi_i2s_data_transmit(SPI5,byte);

    /* wait to receive a byte */
    while(RESET == spi_i2s_flag_get(SPI5,SPI_FLAG_RBNE));

    /* return the byte read from the SPI bus */
    return(spi_i2s_data_receive(SPI5));
}

/*!
    \brief      send a half word through the SPI interface and return the half word received from the SPI bus
    \param[in]  half_word: half word to send
    \param[out] none
    \retval     the value of the received byte
*/
static uint16_t spi_flash_send_halfword(uint16_t half_word)
{
    
    
    /* loop while data register in not emplty */
    while(RESET == spi_i2s_flag_get(SPI5,SPI_FLAG_TBE));

    /* send half word through the SPI5 peripheral */
    spi_i2s_data_transmit(SPI5,half_word);

    /* wait to receive a half word */
    while(RESET == spi_i2s_flag_get(SPI5,SPI_FLAG_RBNE));

    /* return the half word read from the SPI bus */
    return spi_i2s_data_receive(SPI5);
}

/*!
    \brief      enable the write access to the flash
    \param[in]  none
    \param[out] none
    \retval     none
*/
void spi_flash_write_enable(void)
{
    
    
    /* select the flash: chip select low */
    SPI_FLASH_CS_LOW();

    /* send "write enable" instruction */
    spi_flash_send_byte(WREN);

    /* deselect the flash: chip select high */
    SPI_FLASH_CS_HIGH();
}

/*!
    \brief      poll the status of the write in progress(wip) flag in the flash's status register
    \param[in]  none
    \param[out] none
    \retval     none
*/
void spi_flash_wait_for_write_end(void)
{
    
    
    uint8_t flash_status = 0;

    /* select the flash: chip select low */
    SPI_FLASH_CS_LOW();

    /* send "read status register" instruction */
    spi_flash_send_byte(RDSR);

    /* loop as long as the memory is busy with a write cycle */
    do{
    
    
        /* send a dummy byte to generate the clock needed by the flash
        and put the value of the status register in flash_status variable */
        flash_status = spi_flash_send_byte(DUMMY_BYTE);
    }while(SET == (flash_status & WIP_FLAG));

    /* deselect the flash: chip select high */
    SPI_FLASH_CS_HIGH();
}

/*!
    \brief      write more than one byte to the flash
    \param[in]  pbuffer: pointer to the buffer
    \param[in]  write_addr: flash's internal address to write
    \param[in]  num_byte_to_write: number of bytes to write to the flash
    \param[out] none
    \retval     none
*/
static void spi_flash_page_write(const uint8_t* pbuffer, uint16_t num_byte_to_write)
{
    
    
    /* select the flash: chip select low */
    SPI_FLASH_CS_LOW();

    /* while there is data to be written on the flash */
    while(num_byte_to_write--){
    
    
        /* send the current byte */
        spi_flash_send_byte(*pbuffer);
        /* point on the next byte to be written */
        pbuffer++;
    }
}
/*!
    \brief      read a block of data from the flash
    \param[in]  pbuffer: pointer to the buffer that receives the data read from the flash
    \param[in]  read_addr: flash's internal address to read from
    \param[in]  num_byte_to_read: number of bytes to read from the flash
    \param[out] none
    \retval     none
*/
static void spi_flash_buffer_read(uint8_t* pbuffer, uint16_t num_byte_to_read)
{
    
    
    /* select the flash: chip slect low */
    SPI_FLASH_CS_LOW();

    /* while there is data to be read */
    while(num_byte_to_read--){
    
    
        /* read a byte from the flash */
        *pbuffer = spi_flash_send_byte(DUMMY_BYTE);
        /* point to the next location where the byte read will be saved */
        pbuffer++;
    }
}
/**
  * @brief  enable the flash quad mode
  * @param  None
  * @retval None
  */
void qspi_flash_quad_enable(void)
{
    
    
    /* enable the write access to the flash */
    spi_flash_write_enable();
    /* select the flash: chip select low */
    SPI_FLASH_CS_LOW();
    /* send "write status register" instruction */
    spi_flash_send_byte(WRSR);
    
    spi_flash_send_byte(0x00);
    spi_flash_send_byte(0x02);
    /* deselect the flash: chip select high */
    SPI_FLASH_CS_HIGH(); 
    /* wait the end of flash writing */
    spi_flash_wait_for_write_end();
}
/**
  * @brief  read a block of data from the flash using qspi
  * @param  pbuffer : pointer to the buffer that receives the data read from the flash
  * @param  read_addr : flash's internal address to read from
  * @param  num_byte_to_read : number of bytes to read from the flash
  * @retval None
  */
void qspi_flash_buffer_read(uint8_t* pbuffer, uint32_t read_addr, uint16_t num_byte_to_read)
{
    
    
		qspi_flash_quad_enable();
	
    /* select the flash: chip select low */
    SPI_FLASH_CS_LOW();

    /* enable the qspi */
    qspi_enable(SPI5); 
    /* enable the qspi read operation */
    qspi_read_enable(SPI5);
	
    /* send "quad fast read from memory " instruction */
    spi_flash_send_byte(QUADREAD);
      
    /* send read_addr high nibble address byte to read from */
    spi_flash_send_byte((read_addr & 0xFF0000) >> 16);
    /* send read_addr medium nibble address byte to read from */
    spi_flash_send_byte((read_addr & 0xFF00) >> 8);
    /* send read_addr low nibble address byte to read from */
    spi_flash_send_byte(read_addr & 0xFF);
    spi_flash_send_byte(0xA5);         
    /* while there is data to be read */
    while(num_byte_to_read--){
    
    
        /* read a byte from the flash */
        *pbuffer = spi_flash_send_byte(DUMMY_BYTE);
        /* point to the next location where the byte read will be saved */
        pbuffer++;
    }
    /* deselect the flash: chip select high */
    SPI_FLASH_CS_HIGH();
    /* disable the qspi */
    qspi_disable(SPI5);
		/* wait the end of flash writing */
    spi_flash_wait_for_write_end();
}

/**
  * @brief  write more than one byte to the flash using qspi
  * @param  pbuffer : pointer to the buffer
  * @param  write_addr : flash's internal address to write to
  * @param  num_byte_to_write : number of bytes to write to the flash
  * @retval none
  */
void qspi_flash_page_write(uint8_t* pbuffer, uint32_t write_addr, uint16_t num_byte_to_write)
{
    
    
    /* enable the flash quad mode */
    qspi_flash_quad_enable();
    /* enable the write access to the flash */
    spi_flash_write_enable();

    /* select the flash: chip select low */
    SPI_FLASH_CS_LOW();
    /* send "quad write to memory " instruction */
    spi_flash_send_byte(QUADWRITE);
    /* send writeaddr high nibble address byte to write to */
    spi_flash_send_byte((write_addr & 0xFF0000) >> 16);
    /* send writeaddr medium nibble address byte to write to */
    spi_flash_send_byte((write_addr & 0xFF00) >> 8);
    /* send writeaddr low nibble address byte to write to */
    spi_flash_send_byte(write_addr & 0xFF);
    /* enable the qspi */ 
    qspi_enable(SPI5); 
    /* enable the qspi write operation */
    qspi_write_enable(SPI5);

    /* while there is data to be written on the flash */
    while(num_byte_to_write--){
    
    
        /* send the current byte */
        spi_flash_send_byte(*pbuffer);
        /* point on the next byte to be written */
        pbuffer++;
    }

    /* deselect the flash: chip select high */
    SPI_FLASH_CS_HIGH();
    /* disable the qspi function */ 
    qspi_disable(SPI5); 
    /* wait the end of flash writing */
    spi_flash_wait_for_write_end();
}

static void SPI_Lock_Init(void)
{
    
    
	osSemaphoreStaticDef(SPI5TaskBinarySem01, &SPI5TaskBinarySem01ControlBlock);
	SPI5TaskBinarySem01Handle = osSemaphoreCreate(osSemaphore(SPI5TaskBinarySem01), 1);
	 xSemaphoreGive(SPI5TaskBinarySem01Handle);
}
/* lock SPI bus */
static void SPI_lock(const struct __sfud_spi *spi)
{
    
    
	xSemaphoreTake(SPI5TaskBinarySem01Handle,(TickType_t)0xffffffUL);
}
/* unlock SPI bus */
static void SPI_unlock(const struct __sfud_spi *spi)
{
    
    
	xSemaphoreGive(SPI5TaskBinarySem01Handle);
}

static void SPI_Delay(void)
{
    
    
	delay_1ms(1000);
}
/*=============================END 外部接口==============================*/

#ifdef SFUD_USING_QSPI
/**
 * read flash data by QSPI
 */
static sfud_err qspi_read(const struct __sfud_spi *spi, uint32_t addr, sfud_qspi_read_cmd_format *qspi_read_cmd_format,
        uint8_t *read_buf, size_t read_size) {
    
    
    sfud_err result = SFUD_SUCCESS;

    /**
     * add your qspi read flash data code
     */
		qspi_flash_buffer_read(read_buf, addr, read_size);
    return result;
}
#endif /* SFUD_USING_QSPI */

sfud_err sfud_spi_port_init(sfud_flash *flash) {
    
    
    sfud_err result = SFUD_SUCCESS;

    /**
     * add your port spi bus and device object initialize code like this:
     * 1. rcc initialize
     * 2. gpio initialize
     * 3. spi device initialize
     * 4. flash->spi and flash->retry item initialize
     *    flash->spi.wr = spi_write_read; //Required
     *    flash->spi.qspi_read = qspi_read; //Required when QSPI mode enable
     *    flash->spi.lock = spi_lock;
     *    flash->spi.unlock = spi_unlock;
     *    flash->spi.user_data = &spix;
     *    flash->retry.delay = null;
     *    flash->retry.times = 10000; //Required
     */
		spi_flash_init();
		SPI_Lock_Init();
		flash->spi.wr = spi_write_read;
		flash->spi.lock = SPI_lock;
    	flash->spi.unlock = SPI_unlock;
		flash->spi.user_data = &SPI_userData;
		flash->retry.delay = SPI_Delay;
		flash->retry.times = 60; //60 Sec
    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);
}

针对STM32则接口修改如下:

/*
 * This file is part of the Serial Flash Universal Driver Library.
 *
 * Copyright (c) 2016-2018, Armink, <[email protected]>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * 'Software'), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Function: Portable interface for each platform.
 * Created on: 2016-04-23
 */

#include <sfud.h>
#include <stdarg.h>

static char log_buf[256];

void sfud_log_debug(const char *file, const long line, const char *format, ...);
/************************ 外部接口 ********************************/
#include "main.h"
#include "cmsis_os.h"
extern SPI_HandleTypeDef hspi2;
osSemaphoreId SPI2TaskBinarySem01Handle;
osStaticSemaphoreDef_t SPI2TaskBinarySem01ControlBlock;
uint32_t SPI_userData = 0;
/**
  ******************************************************************
  * @brief   使能Flash
  * @param   [in]None
  * @retval  None
  * @author  aron566
  * @version v1.0
  * @date    2020/6/9
  ******************************************************************
  */
static void HAL_W25QXX_CS_ENABLE(void)
{
    
    
	HAL_GPIO_WritePin(SPI2_CS_GPIO_Port,SPI2_CS_Pin, GPIO_PIN_RESET);
}

/**
  ******************************************************************
  * @brief   失能Flash
  * @param   [in]None
  * @retval  None
  * @author  aron566
  * @version v1.0
  * @date    2020/6/9
  ******************************************************************
  */
static void HAL_W25QXX_CS_DISABLE(void)
{
    
    
	HAL_GPIO_WritePin(SPI2_CS_GPIO_Port,SPI2_CS_Pin, GPIO_PIN_SET);
}

/**
  ******************************************************************
  * @brief   SPI发送一个字节
  * @param   [in]byte
  * @retval  None
  * @author  aron566
  * @version v1.0
  * @date    2020/6/9
  ******************************************************************
  */
static void HAL_SPI_Send_Byte(uint8_t byte)
{
    
    
	HAL_SPI_Transmit(&hspi2,&byte,1,0xFFFF);
}

/**
  ******************************************************************
  * @brief   SPI接收一个字节
  * @param   [in]None
  * @retval  字节
  * @author  aron566
  * @version v1.0
  * @date    2020/6/9
  ******************************************************************
  */
static uint8_t HAL_SPI_Receive_Byte(void)
{
    
    
	uint8_t data = 0xFF;
	HAL_SPI_Receive(&hspi2,&data,1,0xFFFF);
	return data;
}

/**
  ******************************************************************
  * @brief   SPI多字节发送
  * @param   [in]pbyte 发送字节数
  * @retval  None
  * @author  aron566
  * @version v1.0
  * @date    2020/6/9
  ******************************************************************
  */
static void HAL_Flash_Page_Write(const uint8_t* pbuffer, uint16_t num_byte_to_write)
{
    
    
    /* select the flash: chip select low */
    HAL_W25QXX_CS_ENABLE();

    /* while there is data to be written on the flash */
    while(num_byte_to_write--){
    
    
        /* send the current byte */
        HAL_SPI_Send_Byte(*pbuffer);
        /* point on the next byte to be written */
        pbuffer++;
    }
}

/**
  ******************************************************************
  * @brief   SPI多字节接收
  * @param   [in]pbyte 接收字节数
  * @retval  None
  * @author  aron566
  * @version v1.0
  * @date    2020/6/9
  ******************************************************************
  */
static void HAL_Flash_Buffer_Read(uint8_t* pbuffer, uint16_t num_byte_to_read)
{
    
    
    /* select the flash: chip slect low */
    HAL_W25QXX_CS_ENABLE();

    /* while there is data to be read */
    while(num_byte_to_read--){
    
    
        /* read a byte from the flash */
        *pbuffer = HAL_SPI_Receive_Byte();
        /* point to the next location where the byte read will be saved */
        pbuffer++;
    }
}

/**
  ******************************************************************
  * @brief   SPI信号量初始化
  * @param   [in]None
  * @retval  None
  * @author  aron566
  * @version v1.0
  * @date    2020/6/9
  ******************************************************************
  */
static void SPI_Lock_Init(void)
{
    
    
	osSemaphoreStaticDef(SPI2TaskBinarySem01, &SPI2TaskBinarySem01ControlBlock);
	SPI2TaskBinarySem01Handle = osSemaphoreCreate(osSemaphore(SPI2TaskBinarySem01), 1);
	xSemaphoreGive(SPI2TaskBinarySem01Handle);
}
/* lock SPI bus */
static void SPI_lock(const struct __sfud_spi *spi)
{
    
    
	xSemaphoreTake(SPI2TaskBinarySem01Handle,(TickType_t)0xffffffUL);
}
/* unlock SPI bus */
static void SPI_unlock(const struct __sfud_spi *spi)
{
    
    
	xSemaphoreGive(SPI2TaskBinarySem01Handle);
}

static void SPI_Delay(void)
{
    
    
    uint32_t delay = 120;
    while(delay--);
}
/********************** END 外部接口 ******************************/

/**
 * 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;

    /**
     * add your spi write and read code
     */
    if (write_size)
    {
    
    
        SFUD_ASSERT(write_buf);
    }
    if (read_size)
    {
    
    
        SFUD_ASSERT(read_buf);
    }
    HAL_W25QXX_CS_ENABLE();
	HAL_Flash_Page_Write(write_buf ,write_size);
	HAL_Flash_Buffer_Read(read_buf ,read_size);
    HAL_W25QXX_CS_DISABLE();
    return result;
}

#ifdef SFUD_USING_QSPI
/**
 * read flash data by QSPI
 */
static sfud_err qspi_read(const struct __sfud_spi *spi, uint32_t addr, sfud_qspi_read_cmd_format *qspi_read_cmd_format,
        uint8_t *read_buf, size_t read_size) {
    
    
    sfud_err result = SFUD_SUCCESS;

    /**
     * add your qspi read flash data code
     */

    return result;
}
#endif /* SFUD_USING_QSPI */

sfud_err sfud_spi_port_init(sfud_flash *flash) {
    
    
    sfud_err result = SFUD_SUCCESS;

    /**
     * add your port spi bus and device object initialize code like this:
     * 1. rcc initialize
     * 2. gpio initialize
     * 3. spi device initialize
     * 4. flash->spi and flash->retry item initialize
     *    flash->spi.wr = spi_write_read; //Required
     *    flash->spi.qspi_read = qspi_read; //Required when QSPI mode enable
     *    flash->spi.lock = spi_lock;
     *    flash->spi.unlock = spi_unlock;
     *    flash->spi.user_data = &spix;
     *    flash->retry.delay = null;
     *    flash->retry.times = 10000; //Required
     */
    SPI_Lock_Init();
    flash->spi.wr = spi_write_read;
    flash->spi.lock = SPI_lock;
    flash->spi.unlock = SPI_unlock;
    flash->spi.user_data = &SPI_userData;
    flash->retry.delay = SPI_Delay;
    flash->retry.times = 60*10000; //60 Sec
    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_cfg.h文件

将自己板子上flash信息添加上,我的是一个spi flash设备GD25Q16B

注意根据qspi启用状态://#define SFUD_USING_QSPI,我这里打开;当然选择不启用,简单点操作会减少很多异常问题

#ifndef _SFUD_CFG_H_
#define _SFUD_CFG_H_

#define SFUD_DEBUG_MODE

#define SFUD_USING_SFDP

#define SFUD_USING_FLASH_INFO_TABLE

enum {
    
    
    SFUD_GD25Q16B_DEVICE_INDEX = 0,
};

#define SFUD_FLASH_DEVICE_TABLE                                                \
{                                                                              \
    [SFUD_GD25Q16B_DEVICE_INDEX] = {.name = "GD25Q16B", .spi.name = "SPI5"},           \
}

#define SFUD_USING_QSPI

#endif /* _SFUD_CFG_H_ */

添加获取初始化状态,可加可不加

声明一个局部变量,存储初始化的状态:
static sfud_err ALL_flash_result = SFUD_SUCCESS;
sfud_init(void)中加入以下代码:

ALL_flash_result = all_flash_result;

/**
  ******************************************************************
  * @brief   获取初始化完成状态
  * @param   None
  * @retval  SFUD_SUCCESS 成功
  * @author  aron566
  * @version v1.0
  * @date    2020/6/8
  ******************************************************************
  */
sfud_err sfud_GetInitState(void)
{
    
    
    return ALL_flash_result;
}

验证测试

这里可以参考官方例程的测试代码
在main.c中加入以下代码

注意根据qspi启用状态:调用sfud_qspi_fast_read_enable,我这里打开;当然选择不启用,简单点操作会减少很多异常问题

    if (sfud_init() == SFUD_SUCCESS)
    {
    
    
        /* enable qspi fast read mode, set four data lines width */
        sfud_qspi_fast_read_enable(sfud_get_device(SFUD_GD25Q16B_DEVICE_INDEX), 4);
        sfud_demo(0, sizeof(sfud_demo_test_buf), sfud_demo_test_buf);
    }
#include "sfud.h"
/**
 * SFUD demo for the first flash device test.
 *
 * @param addr flash start address
 * @param size test flash size
 * @param size test flash data buffer
 */
void sfud_demo(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_GD25Q16B_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);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_42892101/article/details/106588125