前往下载
其主要实现spi的不同芯片平台底层驱动包括:
使用操作系统的情况下直接使用开关总中断方式上锁解锁,则延时函数接口应使用操作系统的延时如
osDelay
不可使用HAL_Delay或其他利用中断计时的函数,避免systick无法进入中断导致线程无法运行或其他中断无法进入计时累积导致程序停留无法运行,如有使用出现问题注意此方向的排查
/*
* This file is part of the Serial Flash Universal Driver Library.
*
* Copyright (c) 2016-2018, Armink,
*
* 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
#include
/*=============================外部接口==============================*/
#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,
*
* 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
#include
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);
}
将自己板子上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);
}
}