FreeRTOS移植SFUD
Posted 一地鸡毛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FreeRTOS移植SFUD相关的知识,希望对你有一定的参考价值。
1. SFUD
SFUD是一款串行 Flash 通用驱动库,GitHub:https://link.zhihu.com/?target=https%3A//github.com/armink/SFUD Gitee:https://gitee.com/Armink/SFUD
2. SFUD的移植
① 使用CubeMX配置spi
② 复制sfud源码文件到工程中,在keil中建立工程对应的目录,包含对应的头文件
③ 改写sfud_port.c中的函数
/*
* This file is part of the Serial Flash Universal Driver Library.
*
* Copyright (c) 2016-2018, Armink, <armink.ztl@gmail.com>
*
* 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 "main.h"
#include "spi.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "BSP_SPIFlash.h"
#include "BSP_DebugUART.h"
//#define SFUD_USE_ELOG
#ifdef SFUD_USE_ELOG
#include <elog.h>
#endif
static char log_buf[256];
void sfud_log_debug(const char *file, const long line, const char *format, ...);
static void spi_lock(const sfud_spi *spi) {
/* 裸机中使用开关中断方法 */
// __disable_irq();
/* OS 中使用临界区或互斥量,推荐互斥量方式 */
// taskENTER_CRITICAL(); /* 进入临界区 */
xSemaphoreTake(xMutexSPIFlash, portMAX_DELAY); /* 互斥信号量 */
}
static void spi_unlock(const sfud_spi *spi) {
/* 裸机中使用开关中断方法 */
// __enable_irq();
/* OS 中使用临界区或互斥量,推荐互斥量方式 */
// taskEXIT_CRITICAL(); /* 退出临界区 */
xSemaphoreGive(xMutexSPIFlash); /* 互斥信号量 */
}
/**
* 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);
}
// HAL_GPIO_WritePin(SPIFlashCS_GPIO_Port, SPIFlashCS_Pin, GPIO_PIN_RESET);
// if( HAL_OK != HAL_SPI_TransmitReceive(&hspi2, (uint8_t *)write_buf, (uint8_t *)read_buf, write_size+read_size, 1000) )
// result = SFUD_ERR_TIMEOUT;
// HAL_GPIO_WritePin(SPIFlashCS_GPIO_Port, SPIFlashCS_Pin, GPIO_PIN_SET);
if(read_size != NULL)
{
HAL_GPIO_WritePin(SPIFlashCS_GPIO_Port, SPIFlashCS_Pin, GPIO_PIN_RESET);
if( HAL_OK != HAL_SPI_Transmit(&hspi1, (uint8_t *)write_buf, write_size, 1000) )
result = SFUD_ERR_TIMEOUT;
// HAL_GPIO_WritePin(SPIFlashCS_GPIO_Port, SPIFlashCS_Pin, GPIO_PIN_SET);
// HAL_GPIO_WritePin(SPIFlashCS_GPIO_Port, SPIFlashCS_Pin, GPIO_PIN_RESET);
if( HAL_OK != HAL_SPI_Receive(&hspi1, (uint8_t *)read_buf, read_size, 1000) )
result = SFUD_ERR_TIMEOUT;
HAL_GPIO_WritePin(SPIFlashCS_GPIO_Port, SPIFlashCS_Pin, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(SPIFlashCS_GPIO_Port, SPIFlashCS_Pin, GPIO_PIN_RESET);
if( HAL_OK != HAL_SPI_Transmit(&hspi1, (uint8_t *)write_buf, write_size, 1000) )
result = SFUD_ERR_TIMEOUT;
HAL_GPIO_WritePin(SPIFlashCS_GPIO_Port, SPIFlashCS_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
*/
return result;
}
#endif /* SFUD_USING_QSPI */
/* about 100 microsecond delay */
static void retry_delay_100us(void) {
uint32_t delay = 1700*2;
while(delay--);
}
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: {
/* 同步 Flash 移植所需的接口及数据 */
flash->spi.wr = spi_write_read;
flash->spi.lock = spi_lock;
flash->spi.unlock = spi_unlock;
/* 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);
#ifdef SFUD_USE_ELOG
elog_raw("[SFUD](%s:%ld) ", file, line);
#else
BSP_Printf("[SFUD](%s:%ld) ", file, line);
#endif
/* must use vprintf to print */
vsnprintf(log_buf, sizeof(log_buf), format, args);
#ifdef SFUD_USE_ELOG
elog_raw("%s\\n", log_buf);
#else
BSP_Printf("%s\\n", log_buf);
#endif
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);
#ifdef SFUD_USE_ELOG
elog_raw("[SFUD]");
#else
BSP_Printf("[SFUD]");
#endif
/* must use vprintf to print */
vsnprintf(log_buf, sizeof(log_buf), format, args);
#ifdef SFUD_USE_ELOG
elog_raw("%s\\n", log_buf);
#else
BSP_Printf("%s\\n", log_buf);
#endif
va_end(args);
}
④ 改写sfud_cfg.h
/*
* This file is part of the Serial Flash Universal Driver Library.
*
* Copyright (c) 2016-2018, Armink, <armink.ztl@gmail.com>
*
* 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: It is the configure head file for this library.
* Created on: 2016-04-23
*/
#ifndef _SFUD_CFG_H_
#define _SFUD_CFG_H_
#define SFUD_DEBUG_MODE
#define SFUD_USING_SFDP
//#define SFUD_USING_FLASH_INFO_TABLE
enum {
SFUD_W25_DEVICE_INDEX = 0,
};
#define SFUD_FLASH_DEVICE_TABLE \\
{ \\
[SFUD_W25_DEVICE_INDEX] = {.name = "W25Q128F", .spi.name = "SPI1"}, \\
}
//#define SFUD_USING_QSPI
#endif /* _SFUD_CFG_H_ */
3. SFUD的使用
可单独使用,查看说明文档中的API。此处配合后面的easyflash使用
以上是关于FreeRTOS移植SFUD的主要内容,如果未能解决你的问题,请参考以下文章
stm32f103的 RT-Thread3.1.3移植SFUD+FAL+EasyFlash
stm32f103的 RT-Thread3.1.3移植SFUD+FAL+EasyFlash