移植SFUD与测试验证-基于stm32cubemx5.0

1.时钟的配置主时钟为80M

2.配置QUSPI接口,同时使能上拉

3.QUSPI参数配置,开启全局中断 

4.生成工程文件

5.下载SFUD文件,提供下载地址

https://github.com/armink/SFUD

6.添加printf重定向与us延时函数,用于系统调试和移植。

7.添加SFUD文件,需要添加相应了路径

8.底层函数移植,只需修改两个文件

9.头文件sfud_cfg.h修改实例

10.核心接口.c示例源码


#include <sfud.h>
#include <stdarg.h>
#include "quadspi.h"
#include "delay.h"

typedef struct
{
    QSPI_HandleTypeDef *spix;
    GPIO_TypeDef       *cs_gpiox;
    uint16_t            cs_gpio_pin;
}   spi_user_data, *spi_user_data_t;

void sfud_log_info(const char *format, ...);
static char log_buf[256];
void sfud_log_debug(const char *file, const long line, const char *format, ...);
sfud_err qspi_send_then_recv(const void *send_buf, size_t send_length, void *recv_buf, size_t recv_length);
static void spi_lock  (const sfud_spi *spi);
static void spi_unlock(const sfud_spi *spi);
void sfud_log_debug(const char *file, const long line, const char *format, ...);
static void retry_delay_100us(void);




static spi_user_data spi1 = { .spix = &hqspi, .cs_gpiox = NULL, .cs_gpio_pin = NULL };

/**
 * 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
     */
    spi_user_data_t spi_dev = (spi_user_data_t) spi->user_data;
					

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

		
	  //CS EN
    if (spi_dev->cs_gpiox != NULL)
        HAL_GPIO_WritePin(spi_dev->cs_gpiox, spi_dev->cs_gpio_pin, GPIO_PIN_RESET);				
			
    //读写数据		
    if (write_size && read_size)
    {
        /* read data */
        qspi_send_then_recv(write_buf, write_size, read_buf, read_size);
    }
    else if (write_size)
    {
        /* send data */
        qspi_send_then_recv(write_buf, write_size, NULL, NULL);
    }					
				
    //CS DISABLE
    if (spi_dev->cs_gpiox != NULL)
        HAL_GPIO_WritePin(spi_dev->cs_gpiox, spi_dev->cs_gpio_pin, GPIO_PIN_SET);

		
    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
     */
    QSPI_CommandTypeDef Cmdhandler;
					
    /* set cmd struct */
    Cmdhandler.Instruction = qspi_read_cmd_format->instruction;
    if(qspi_read_cmd_format->instruction_lines == 0)
    {
        Cmdhandler.InstructionMode = QSPI_INSTRUCTION_NONE;
    }else if(qspi_read_cmd_format->instruction_lines == 1)
    {
        Cmdhandler.InstructionMode = QSPI_INSTRUCTION_1_LINE;
    }else if(qspi_read_cmd_format->instruction_lines == 2)
    {
        Cmdhandler.InstructionMode = QSPI_INSTRUCTION_2_LINES;
    }else if(qspi_read_cmd_format->instruction_lines == 4)
    {
        Cmdhandler.InstructionMode = QSPI_INSTRUCTION_4_LINES;
    }					
					
    Cmdhandler.Address = addr;
    Cmdhandler.AddressSize = QSPI_ADDRESS_24_BITS;
    if(qspi_read_cmd_format->address_lines == 0)
    {
        Cmdhandler.AddressMode = QSPI_ADDRESS_NONE;
    }else if(qspi_read_cmd_format->address_lines == 1)
    {
        Cmdhandler.AddressMode = QSPI_ADDRESS_1_LINE;
    }else if(qspi_read_cmd_format->address_lines == 2)
    {
        Cmdhandler.AddressMode = QSPI_ADDRESS_2_LINES;
    }else if(qspi_read_cmd_format->address_lines == 4)
    {
        Cmdhandler.AddressMode = QSPI_ADDRESS_4_LINES;
    }			

    Cmdhandler.AlternateBytes = 0;
    Cmdhandler.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
    Cmdhandler.AlternateBytesSize = 0;

    Cmdhandler.DummyCycles = qspi_read_cmd_format->dummy_cycles;

    Cmdhandler.NbData = read_size;
    if(qspi_read_cmd_format->data_lines == 0)
    {
        Cmdhandler.DataMode = QSPI_DATA_NONE;
    }else if(qspi_read_cmd_format->data_lines == 1)
    {
        Cmdhandler.DataMode = QSPI_DATA_1_LINE;
    }else if(qspi_read_cmd_format->data_lines == 2)
    {
        Cmdhandler.DataMode = QSPI_DATA_2_LINES;
    }else if(qspi_read_cmd_format->data_lines == 4)
    {
        Cmdhandler.DataMode = QSPI_DATA_4_LINES;
    }

    Cmdhandler.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
    Cmdhandler.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
    Cmdhandler.DdrMode = QSPI_DDR_MODE_DISABLE;
    Cmdhandler.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;

		HAL_QSPI_Command(&hqspi, &Cmdhandler, 5000);
		
		
		if (HAL_QSPI_Receive(&hqspi, read_buf, 5000) != HAL_OK)
    {
			//printf("myQSPI is ERR\n");
        sfud_log_info("qspi recv data failed(%d)!", hqspi.ErrorCode);
        hqspi.State = HAL_QSPI_STATE_READY;
        result = SFUD_ERR_READ;
    }
		//else printf("myQSPI is OK\n");
					
    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
     */
	  
	  switch (flash->index)
    {
        case SFUD_W25_DEVICE_INDEX:
        {
            /* set the interfaces and data */
            flash->spi.wr        = spi_write_read;
            flash->spi.qspi_read = qspi_read;
            flash->spi.lock      = spi_lock;
            flash->spi.unlock    = spi_unlock;
            flash->spi.user_data = &spi1;
            /* 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\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\n", log_buf);
    va_end(args);
}



sfud_err qspi_send_then_recv(const void *send_buf, size_t send_length, void *recv_buf, size_t recv_length)
{
	  assert_param(send_buf);
    assert_param(recv_buf);
    assert_param(send_length != 0);
	
    QSPI_CommandTypeDef Cmdhandler;
    unsigned char *ptr = (unsigned char *)send_buf;
    size_t   count = 0;
    sfud_err result = SFUD_SUCCESS;	
	
    /* get instruction */
    Cmdhandler.Instruction = ptr[0];
    Cmdhandler.InstructionMode = QSPI_INSTRUCTION_1_LINE;
    count++;	

    /* get address */
    if (send_length > 1)
    {
        if (send_length >= 4)
        {
            /* address size is 3 Byte */
            Cmdhandler.Address = (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
            Cmdhandler.AddressSize = QSPI_ADDRESS_24_BITS;
            count += 3;
        }
        else
        {
            return SFUD_ERR_READ;
        }
        Cmdhandler.AddressMode = QSPI_ADDRESS_1_LINE;
    }
    else
    {
        /* no address stage */
        Cmdhandler.Address = 0 ;
        Cmdhandler.AddressMode = QSPI_ADDRESS_NONE;
        Cmdhandler.AddressSize = 0;
    }	
	
		
		
    Cmdhandler.AlternateBytes = 0;
    Cmdhandler.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
    Cmdhandler.AlternateBytesSize = 0;
    
    Cmdhandler.SIOOMode            = QSPI_SIOO_INST_EVERY_CMD;
    Cmdhandler.AlternateByteMode   = QSPI_ALTERNATE_BYTES_NONE;
    Cmdhandler.DdrMode             = QSPI_DDR_MODE_DISABLE;
    Cmdhandler.DdrHoldHalfCycle    = QSPI_DDR_HHC_ANALOG_DELAY;
	

    if (send_buf && recv_buf)
    {
        /* recv data */
        /* set dummy cycles */
        if (count != send_length)
        {
            Cmdhandler.DummyCycles = (send_length - count) * 8;
        }
        else
        {
            Cmdhandler.DummyCycles = 0;
        }

        /* set recv size */
        Cmdhandler.DataMode = QSPI_DATA_1_LINE;
        Cmdhandler.NbData = recv_length;
        HAL_QSPI_Command(&hqspi, &Cmdhandler, 5000);
        
        if (recv_length != 0)
        {
            if (HAL_QSPI_Receive(&hqspi, recv_buf, 5000) != HAL_OK)
            {
							 // printf("rx is ERR\n");
                sfud_log_info("qspi recv data failed(%d)!", hqspi.ErrorCode);
                hqspi.State = HAL_QSPI_STATE_READY;
                result = SFUD_ERR_READ;
            }
						//else  printf("rx is OK\n");
						
        }

        return result;
    }
    else
    {
        /* send data */
        /* set dummy cycles */
        Cmdhandler.DummyCycles = 0;

        /* determine if there is data to send */
        if (send_length - count > 0)
        {
            Cmdhandler.DataMode = QSPI_DATA_1_LINE;
        }
        else
        {
            Cmdhandler.DataMode = QSPI_DATA_NONE;
        }

        /* set send buf and send size */
        Cmdhandler.NbData = send_length - count;
        HAL_QSPI_Command(&hqspi, &Cmdhandler, 5000);
        
        if (send_length - count > 0)
        {
            if (HAL_QSPI_Transmit(&hqspi, (uint8_t *)(ptr + count), 5000) != HAL_OK)
            {
							 // printf("tx is ER\n");
                sfud_log_info("qspi send data failed(%d)!", hqspi.ErrorCode);
                hqspi.State = HAL_QSPI_STATE_READY;
                result = SFUD_ERR_WRITE;
            }
						//else
							//printf("tx is OK\n");
        }
        
        return result;
    }

		
}


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

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


//需要移植时间延时函数
static void retry_delay_100us(void)
{
   delay_us(100);
}







12. APP功能测试

main添加头文件#include <sfud.h>

main添加测试代码

    printf("sfud_init is start\n");
    
    if (sfud_init() == SFUD_SUCCESS)
    {   printf("sfud_init is Ok\n");
        /* enable qspi fast read mode, set four data lines width */
        sfud_qspi_fast_read_enable(sfud_get_device(SFUD_W25_DEVICE_INDEX), 4);
        sfud_demo(0, sizeof(sfud_demo_test_buf), sfud_demo_test_buf);
    }   

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_W25_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;
    }
		printf("here---1\n");
    /* write test */
    result = sfud_write(flash, addr, size, data);
		
		printf("here---2\n");
    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);
    }

 

 13.观察串口打印效果

14.结束

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值