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

stm32f103的 RT-Thread3.1.3移植SFUD+FAL+EasyFlash

FreeRTOS移植

STM32F103移植freeRTOS(使用官方源码)

STM32G0学习手册——移植FreeRTOS v202107.00