前言
- 本次使用的是stm32f407zgt6
- 使用到上篇博客所用到的shell组件,加上之前所记录的filex组件
- 本篇博客的主要内容是关于上篇博客ota与filex的结合和filex与shell组件的结合
- 本篇主要是为后面去整合modulex模块,实现从filex里面去动态加载bin文件,然后动态运行作为bin文件的存储方案的规划记录
- 使用filex的时候,注意sd卡格式的问题.
本篇实验完成的目标
- ota 部分上传文件
- filex组件的结合
- filex和shell组件的结合
- shell组件扩展了源码中提供日志的模块
filex组件的结合(sdio)
公有头文件
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-4 shchl first version
*/
#ifndef MYPROJECT_INCLUDES_H
#define MYPROJECT_INCLUDES_H
/*
*********************************************************************************************************
* 标准库
*********************************************************************************************************
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*
*********************************************************************************************************
* OS
*********************************************************************************************************
*/
#include "tx_api.h"
#include "tx_timer.h"
#include "log.h"
#include "fx_api.h"
#define TX_CONV_STACK_SIZE(size) ((((UINT) size)+((sizeof(ULONG)) - ((UINT) 1)))/sizeof(ULONG))
#define TX_APP_DEFINE_LV1(fn) INIT_EXPORT(fn, "6.0")
#define TX_APP_DEFINE_EXPORT(fn) INIT_EXPORT(fn, "6.5")
#define TX_THREAD_EXPORT_LV1(fn) INIT_EXPORT(fn, "7.0")
#define TX_THREAD_EXPORT(fn) INIT_EXPORT(fn, "7.5")
#define TX_LOG_BUF_SZ 256
#define tx_log logDebug
//void tx_log(const char *fmt, ...) logDebug;
#define tx_printf printf
#define test_control_return(code) do{tx_printf("error code:%d",code);}while(0); return code;
#define return_if_fail(p) if(!(p)) \
{tx_printf("ERROR!\n%s:%d\nError: "#p" failed.\n", \
__FILE__, __LINE__);test_control_return(254);}
void tx_log_no_mutex(const char *fmt, ...);
/*
*********************************************************************************************************
* APP / BSP
*********************************************************************************************************
*/
#include <bsp.h>
#include "shell.h"
/*
*********************************************************************************************************
* 变量和函数
*********************************************************************************************************
*/
extern void *g_sd_cache_buffer;
extern FX_MEDIA g_sd_media_disk;
#ifdef FX_ENABLE_FAULT_TOLERANT
extern void *g_fault_tolerant_buffer;
#endif
void tx_mem_pool_init(void *start_addr);
void tx_mem_pool_static_init(void *start_addr, uint16_t byte_cnt);
void *app_malloc(ULONG size);
void app_free(void *mem_ptr);
void *app_realloc(void *ptr, ULONG size);
void app_task_info_out(void);
/* 方便RTOS里面使用 */
extern void SysTick_ISR(void);
#define bsp_ProPer1ms SysTick_ISR
#endif //MYPROJECT_INCLUDES_H
SDIO驱动层代码
头文件
/**
******************************************************************************
* @file stm324x9i_eval_sd.h
* @author MCD Application Team
* @brief This file contains the common defines and functions prototypes for
* the stm324x9i_eval_sd.c driver.
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM324x9I_EVAL_SD_H
#define __STM324x9I_EVAL_SD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#ifdef HAL_SD_MODULE_ENABLED
#if 1
/** @addtogroup BSP
* @{
*/
/** @addtogroup STM324x9I_EVAL
* @{
*/
/** @addtogroup STM324x9I_EVAL_SD
* @{
*/
/** @defgroup STM324x9I_EVAL_SD_Exported_Types STM324x9I EVAL SD Exported Types
* @{
*/
/**
* @brief SD Card information structure
*/
#define BSP_SD_CardInfo HAL_SD_CardInfoTypeDef
/**
* @}
*/
/** @defgroup STM324x9I_EVAL_SD_Exported_Constants STM324x9I EVAL SD Exported Constants
* @{
*/
/**
* @brief SD status structure definition
*/
#define MSD_OK 0x00
#define MSD_ERROR 0x01
/**
* @brief SD transfer state definition
*/
#define SD_TRANSFER_OK ((uint8_t)0x00)
#define SD_TRANSFER_BUSY ((uint8_t)0x01)
#define SD_PRESENT ((uint8_t)0x01)
#define SD_NOT_PRESENT ((uint8_t)0x00)
#define SD_DATATIMEOUT ((uint32_t)100000000)
/* DMA definitions for SD DMA transfer */
#define __DMAx_TxRx_CLK_ENABLE __HAL_RCC_DMA2_CLK_ENABLE
#define SD_DMAx_Tx_CHANNEL DMA_CHANNEL_4
#define SD_DMAx_Rx_CHANNEL DMA_CHANNEL_4
#define SD_DMAx_Tx_STREAM DMA2_Stream6
#define SD_DMAx_Rx_STREAM DMA2_Stream3
#define SD_DMAx_Tx_IRQn DMA2_Stream6_IRQn
#define SD_DMAx_Rx_IRQn DMA2_Stream3_IRQn
#define BSP_SD_IRQHandler SDIO_IRQHandler
#define BSP_SD_DMA_Tx_IRQHandler DMA2_Stream6_IRQHandler
#define BSP_SD_DMA_Rx_IRQHandler DMA2_Stream3_IRQHandler
#define SD_DetectIRQHandler() HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8)
/**
* @}
*/
/** @defgroup STM324x9I_EVAL_SD_Exported_Functions STM324x9I EVAL SD Exported Functions
* @{
*/
uint8_t BSP_SD_Init(void);
uint8_t BSP_SD_DeInit(void);
uint8_t BSP_SD_ITConfig(void);
void BSP_SD_DetectIT(void);
void BSP_SD_DetectCallback(void);
uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout);
uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout);
uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks);
uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks);
uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr);
uint8_t BSP_SD_GetCardState(void);
void BSP_SD_GetCardInfo(HAL_SD_CardInfoTypeDef *CardInfo);
uint8_t BSP_SD_IsDetected(void);
void BSP_SD_AbortCallback(void);
void BSP_SD_WriteCpltCallback(void);
void BSP_SD_ReadCpltCallback(void);
#endif
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif
#endif /* __STM324x9I_EVAL_SD_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
源文件
/*
*********************************************************************************************************
*
* 模块名称 : SD卡驱动模块
* 文件名称 : bsp_sdio_sd.c
* 版 本 : V1.0
* 说 明 : SD卡底层驱动。根据ST的驱动文件修改。
*
* 修改记录 :
* 版本号 日期 作者 说明
* V1.0 2018-09-08 armfly 正式发布
*
* Copyright (C), 2018-2030, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/
/**
******************************************************************************
* @file stm324x9i_eval_sd.c
* @author MCD Application Team
* @brief This file includes the uSD card driver mounted on STM324x9I-EVAL
* evaluation board.
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* File Info : -----------------------------------------------------------------
User NOTES
1. How To use this driver:
--------------------------
- This driver is used to drive the micro SD external card mounted on STM324x9I-EVAL
evaluation board.
- This driver does not need a specific component driver for the micro SD device
to be included with.
2. Driver description:
---------------------
+ Initialization steps:
o Initialize the micro SD card using the BSP_SD_Init() function. This
function includes the MSP layer hardware resources initialization and the
SDIO interface configuration to interface with the external micro SD. It
also includes the micro SD initialization sequence.
o To check the SD card presence you can use the function BSP_SD_IsDetected() which
returns the detection status
o If SD presence detection interrupt mode is desired, you must configure the
SD detection interrupt mode by calling the function BSP_SD_ITConfig(). The interrupt
is generated as an external interrupt whenever the micro SD card is
plugged/unplugged in/from the evaluation board. The SD detection interrupt
is handled by calling the function BSP_SD_DetectIT() which is called in the IRQ
handler file, the user callback is implemented in the function BSP_SD_DetectCallback().
o The function BSP_SD_GetCardInfo() is used to get the micro SD card information
which is stored in the structure "HAL_SD_CardInfoTypeDef".
+ Micro SD card operations
o The micro SD card can be accessed with read/write block(s) operations once
it is ready for access. The access can be performed whether using the polling
mode by calling the functions BSP_SD_ReadBlocks()/BSP_SD_WriteBlocks(), or by DMA
transfer using the functions BSP_SD_ReadBlocks_DMA()/BSP_SD_WriteBlocks_DMA()
o The DMA transfer complete is used with interrupt mode. Once the SD transfer
is complete, the SD interrupt is handled using the function BSP_SD_IRQHandler(),
the DMA Tx/Rx transfer complete are handled using the functions
BSP_SD_DMA_Tx_IRQHandler()/BSP_SD_DMA_Rx_IRQHandler(). The corresponding user callbacks
are implemented by the user at application level.
o The SD erase block(s) is performed using the function BSP_SD_Erase() with specifying
the number of blocks to erase.
o The SD runtime status is returned when calling the function BSP_SD_GetCardState().
------------------------------------------------------------------------------*/
/* Includes ------------------------------------------------------------------*/
#include "bsp.h"
#ifdef HAL_SD_MODULE_ENABLED
#if 1
/** @addtogroup BSP
* @{
*/
/** @addtogroup STM324x9I_EVAL
* @{
*/
/** @defgroup STM324x9I_EVAL_SD STM324x9I EVAL SD
* @{
*/
/** @defgroup STM324x9I_EVAL_SD_Private_Variables SD Private Variables
* @{
*/
SD_HandleTypeDef uSdHandle;
/**
* @}
*/
/** @defgroup STM324x9I_EVAL_SD_Private_Functions SD Private Functions
* @{
*/
/**
* @brief Initializes the SD card device.
* @retval SD status
*/
uint8_t BSP_SD_Init(void)
{
uint8_t SD_state = MSD_OK;
/* uSD device interface configuration */
uSdHandle.Instance = SDIO;
uSdHandle.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
uSdHandle.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
uSdHandle.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
uSdHandle.Init.BusWide = SDIO_BUS_WIDE_1B;
uSdHandle.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
uSdHandle.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV;
uSdHandle.SdCard.CardType = CARD_SDHC_SDXC;
#if 0
/* Configure IO functionalities for SD detect pin */
BSP_IO_Init();
/* Check if the SD card is plugged in the slot */
if(BSP_SD_IsDetected() != SD_PRESENT)
{
return MSD_ERROR;
}
#endif
if(HAL_SD_Init(&uSdHandle) != HAL_OK)
{
SD_state = MSD_ERROR;
}
/* Configure SD Bus width */
if(SD_state == MSD_OK)
{
/*在hal中进行修改了,初始化配置,
* 让其在初始化的时候使用自己配置的进行初始化,
* 所以不需要再配置*/
// /* Enable wide operation */
// if(HAL_SD_ConfigWideBusOperation(&uSdHandle, SDIO_BUS_WIDE_4B) != HAL_OK)
// {
// SD_state = MSD_ERROR;
// }
// else
// {
// SD_state = MSD_OK;
// }
}
return SD_state;
}
/**
* @brief DeInitializes the SD card device.
* @retval SD status
*/
uint8_t BSP_SD_DeInit(void)
{
uint8_t sd_state = MSD_OK;
uSdHandle.Instance = SDIO;
/* Set back Mfx pin to INPUT mode in case it was in exti */
//UseExtiModeDetection = 0;
/* HAL SD deinitialization */
if(HAL_SD_DeInit(&uSdHandle) != HAL_OK)
{
sd_state = MSD_ERROR;
}
/* Msp SD deinitialization */
uSdHandle.Instance = SDIO;
// BSP_SD_MspDeInit(&uSdHandle, NULL);
return sd_state;
}
/**
* @brief Configures Interrupt mode for SD detection pin.
* @retval Returns 0
*/
#if 0
uint8_t BSP_SD_ITConfig(void)
{
/* Configure Interrupt mode for SD detection pin */
BSP_IO_ConfigPin(SD_DETECT_PIN, IO_MODE_IT_FALLING_EDGE);
return 0;
}
#endif
/**
* @brief Detects if SD card is correctly plugged in the memory slot or not.
* @retval Returns if SD is detected or not
*/
#if 0
uint8_t BSP_SD_IsDetected(void)
{
__IO uint8_t status = SD_PRESENT;
/* Check SD card detect pin */
if(BSP_IO_ReadPin(SD_DETECT_PIN))
{
status = SD_NOT_PRESENT;
}
return status;
}
/** @brief SD detect IT treatment.
* @retval None
*/
void BSP_SD_DetectIT(void)
{
/* Clear all pending bits */
BSP_IO_ITClear();
/* To re-enable IT */
BSP_SD_ITConfig();
/* SD detect IT callback */
BSP_SD_DetectCallback();
}
#endif
/** @brief SD detect IT detection callback
* @retval None
*/
__weak void BSP_SD_DetectCallback(void)
{
/* NOTE: This function Should not be modified, when the callback is needed,
the BSP_SD_DetectCallback could be implemented in the user file
*/
}
/**
* @brief Reads block(s) from a specified address in an SD card, in polling mode.
* @param pData: Pointer to the buffer that will contain the data to transmit
* @param ReadAddr: Address from where data is to be read
* @param NumOfBlocks: Number of SD blocks to read
* @param Timeout: Timeout for read operation
* @retval SD status
*/
uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
{
if(HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) != HAL_OK)
{
return MSD_ERROR;
}
else
{
return MSD_OK;
}
}
/**
* @brief Writes block(s) to a specified address in an SD card, in polling mode.
* @param pData: Pointer to the buffer that will contain the data to transmit
* @param WriteAddr: Address from where data is to be written
* @param NumOfBlocks: Number of SD blocks to write
* @param Timeout: Timeout for write operation
* @retval SD status
*/
uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
{
if(HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) != HAL_OK)
{
return MSD_ERROR;
}
else
{
return MSD_OK;
}
}
/**
* @brief Reads block(s) from a specified address in an SD card, in DMA mode.
* @param pData: Pointer to the buffer that will contain the data to transmit
* @param ReadAddr: Address from where data is to be read
* @param NumOfBlocks: Number of SD blocks to read
* @retval SD status
*/
uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
{
/* Read block(s) in DMA transfer mode */
if(HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) != HAL_OK)
{
return MSD_ERROR;
}
else
{
return MSD_OK;
}
}
/**
* @brief Writes block(s) to a specified address in an SD card, in DMA mode.
* @param pData: Pointer to the buffer that will contain the data to transmit
* @param WriteAddr: Address from where data is to be written
* @param NumOfBlocks: Number of SD blocks to write
* @retval SD status
*/
uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
{
/* Write block(s) in DMA transfer mode */
if(HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) != HAL_OK)
{
return MSD_ERROR;
}
else
{
return MSD_OK;
}
}
/**
* @brief Erases the specified memory area of the given SD card.
* @param StartAddr: Start byte address
* @param EndAddr: End byte address
* @retval SD status
*/
uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)
{
if(HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) != HAL_OK)
{
return MSD_ERROR;
}
else
{
return MSD_OK;
}
}
/**
* @brief Initializes the SD MSP.
* @param hsd: SD handle
* @param Params : pointer on additional configuration parameters, can be NULL.
*/
void HAL_SD_MspInit(SD_HandleTypeDef *hsd)
{
static DMA_HandleTypeDef dmaRxHandle = {0};
static DMA_HandleTypeDef dmaTxHandle = {0};
GPIO_InitTypeDef GPIO_Init_Structure;
/* Enable SDIO clock */
__HAL_RCC_SDIO_CLK_ENABLE();
/* Enable DMA2 clocks */
__DMAx_TxRx_CLK_ENABLE();
/* Enable GPIOs clock */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/* Common GPIO configuration */
GPIO_Init_Structure.Mode = GPIO_MODE_AF_PP;
GPIO_Init_Structure.Pull = GPIO_PULLUP;
GPIO_Init_Structure.Speed = GPIO_SPEED_HIGH;
GPIO_Init_Structure.Alternate = GPIO_AF12_SDIO;
/* GPIOC configuration */
GPIO_Init_Structure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;
HAL_GPIO_Init(GPIOC, &GPIO_Init_Structure);
/* GPIOD configuration */
GPIO_Init_Structure.Pin = GPIO_PIN_2;
HAL_GPIO_Init(GPIOD, &GPIO_Init_Structure);
/* Configure DMA Rx parameters */
dmaRxHandle.Init.Channel = SD_DMAx_Rx_CHANNEL;
dmaRxHandle.Init.Direction = DMA_PERIPH_TO_MEMORY;
dmaRxHandle.Init.PeriphInc = DMA_PINC_DISABLE;
dmaRxHandle.Init.MemInc = DMA_MINC_ENABLE;
dmaRxHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
dmaRxHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
dmaRxHandle.Init.Mode = DMA_PFCTRL;
dmaRxHandle.Init.Priority = DMA_PRIORITY_VERY_HIGH;
dmaRxHandle.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
dmaRxHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
dmaRxHandle.Init.MemBurst = DMA_MBURST_SINGLE;
dmaRxHandle.Init.PeriphBurst = DMA_PBURST_INC4;
dmaRxHandle.Instance = SD_DMAx_Rx_STREAM;
/* Associate the DMA handle */
__HAL_LINKDMA(hsd, hdmarx, dmaRxHandle);
/* Deinitialize the stream for new transfer */
HAL_DMA_DeInit(&dmaRxHandle);
/* Configure the DMA stream */
HAL_DMA_Init(&dmaRxHandle);
/* Configure DMA Tx parameters */
dmaTxHandle.Init.Channel = SD_DMAx_Tx_CHANNEL;
dmaTxHandle.Init.Direction = DMA_MEMORY_TO_PERIPH;
dmaTxHandle.Init.PeriphInc = DMA_PINC_DISABLE;
dmaTxHandle.Init.MemInc = DMA_MINC_ENABLE;
dmaTxHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
dmaTxHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
dmaTxHandle.Init.Mode = DMA_PFCTRL;
dmaTxHandle.Init.Priority = DMA_PRIORITY_VERY_HIGH;
dmaTxHandle.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
dmaTxHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
dmaTxHandle.Init.MemBurst = DMA_MBURST_SINGLE;
dmaTxHandle.Init.PeriphBurst = DMA_PBURST_INC4;
dmaTxHandle.Instance = SD_DMAx_Tx_STREAM;
/* Associate the DMA handle */
__HAL_LINKDMA(hsd, hdmatx, dmaTxHandle);
/* Deinitialize the stream for new transfer */
HAL_DMA_DeInit(&dmaTxHandle);
/* Configure the DMA stream */
HAL_DMA_Init(&dmaTxHandle);
/* NVIC configuration for DMA transfer complete interrupt */
HAL_NVIC_SetPriority(SD_DMAx_Rx_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SD_DMAx_Rx_IRQn);
/* NVIC configuration for DMA transfer complete interrupt */
HAL_NVIC_SetPriority(SD_DMAx_Tx_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SD_DMAx_Tx_IRQn);
/* NVIC configuration for SDIO interrupts */
HAL_NVIC_SetPriority(SDIO_IRQn, 0x0, 0);
HAL_NVIC_EnableIRQ(SDIO_IRQn);
}
/**
* @brief DeInitializes the SD MSP.
* @param hsd: SD handle
* @param Params: Pointer to void
* @retval None
*/
void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd)
{
__HAL_RCC_SDIO_CLK_DISABLE();
/**SDIO GPIO Configuration
PC8 ------> SDIO_D0
PC9 ------> SDIO_D1
PC10 ------> SDIO_D2
PC11 ------> SDIO_D3
PC12 ------> SDIO_CK
PD2 ------> SDIO_CMD
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12);
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);
/* SDIO DMA DeInit */
HAL_DMA_DeInit(hsd->hdmarx);
HAL_DMA_DeInit(hsd->hdmatx);
/* SDIO interrupt DeInit */
HAL_NVIC_DisableIRQ(SDIO_IRQn);
}
/**
* @brief Gets the current SD card data status.
* @retval Data transfer state.
* This value can be one of the following values:
* @arg SD_TRANSFER_OK: No data transfer is acting
* @arg SD_TRANSFER_BUSY: Data transfer is acting
*/
uint8_t BSP_SD_GetCardState(void)
{
return((HAL_SD_GetCardState(&uSdHandle) == HAL_SD_CARD_TRANSFER ) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY);
}
/**
* @brief Get SD information about specific SD card.
* @param CardInfo: Pointer to HAL_SD_CardInfoTypedef structure
* @retval None
*/
void BSP_SD_GetCardInfo(HAL_SD_CardInfoTypeDef *CardInfo)
{
/* Get SD card Information */
HAL_SD_GetCardInfo(&uSdHandle, CardInfo);
}
/**
* @brief SD Abort callbacks
* @param hsd: SD handle
* @retval None
*/
void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd)
{
BSP_SD_AbortCallback();
}
/**
* @brief Tx Transfer completed callbacks
* @param hsd: SD handle
* @retval None
*/
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
{
BSP_SD_WriteCpltCallback();
}
/**
* @brief Rx Transfer completed callbacks
* @param hsd: SD handle
* @retval None
*/
void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
{
BSP_SD_ReadCpltCallback();
}
/**
* @brief BSP SD Abort callbacks
* @retval None
*/
__weak void BSP_SD_AbortCallback(void)
{
}
/**
* @brief BSP Tx Transfer completed callbacks
* @retval None
*/
__weak void BSP_SD_WriteCpltCallback(void)
{
}
/**
* @brief BSP Rx Transfer completed callbacks
* @retval None
*/
__weak void BSP_SD_ReadCpltCallback(void)
{
}
/*
*********************************************************************************************************
* 函 数 名: SDIO_IRQHandler
* 功能说明: SDIO中断
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
//void SDIO_IRQHandler(void)
//{
// HAL_SD_IRQHandler(&uSdHandle);
//}
//
//void DMA2_Stream6_IRQHandler(void)
//{
// HAL_DMA_IRQHandler(uSdHandle.hdmatx);
//}
//
//void DMA2_Stream3_IRQHandler(void)
//{
// HAL_DMA_IRQHandler(uSdHandle.hdmarx);
//}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
#endif
#endif
filex和SDIO驱动对接的代码
- 核心逻辑是dma+信号量的方式
头文件
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef FX_STM32_SD_DRIVER_H
#define FX_STM32_SD_DRIVER_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "fx_api.h"
#include "stm32f4xx_hal.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
extern TX_SEMAPHORE transfer_semaphore;
/* Exported constants --------------------------------------------------------*/
#define DEFAULT_TIMEOUT (10 * TX_TIMER_TICKS_PER_SECOND)
#define SD_INSTANCE 0
#define DEFAULT_SECTOR_SIZE 512
#define ENABLE_CACHE_MAINTENANCE 1
#define FX_DRIVER_CALLS_BSP_SD_INIT 1 /*fx来调用sd 驱动初始化*/
VOID fx_stm32_sd_driver(FX_MEDIA *media_ptr);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
#ifdef __cplusplus
}
#endif
#endif /* FX_STM32_SD_DRIVER_H */
源文件
/**************************************************************************/
/* */
/* Partial Copyright (c) Microsoft Corporation. All rights reserved.*/
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* Partial Copyright (c) STMicroelctronics 2020. All rights reserved */
/**************************************************************************/
/* Include necessary system files. */
#include "fx_stm32_sd_driver.h"
#include "bsp.h"
#include "tx_api.h"
#include "fx_api.h"
extern SD_HandleTypeDef uSdHandle;
UINT _fx_partition_offset_calculate(void *partition_sector, UINT partition, ULONG *partition_start, ULONG *partition_size);
static UINT sd_read_data(FX_MEDIA *media_ptr, ULONG sector, UINT num_sectors, UINT use_scratch_buffer);
static UINT sd_write_data(FX_MEDIA *media_ptr, ULONG sector, UINT num_sectors, UINT use_scratch_buffer);
TX_SEMAPHORE transfer_semaphore;
static uint8_t is_initialized = 0;
#define BSP_ERROR_NONE 0
#define BSP_ERROR_BUSY -3
static int32_t check_sd_status()
{
uint32_t start = tx_time_get();
while (tx_time_get() - start < DEFAULT_TIMEOUT)
{
if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
{
return BSP_ERROR_NONE;
}
}
return BSP_ERROR_BUSY;
}
/**
* @brief This function is the entry point to the STM32 SDIO disk driver. */
/* It relies on the STM32 peripheral library from ST.
* @param None
* @retval None
*/
VOID fx_stm32_sd_driver(FX_MEDIA *media_ptr)
{
int32_t status;
ULONG partition_start;
ULONG partition_size;
#if (FX_DRIVER_CALLS_BSP_SD_INIT == 0)
is_initialized = 1; /* the SD was initialized by the application*/
#endif
//TX_INTERRUPT_SAVE_AREA
/* before performing any operation, check the status of the SDMMC */
if (is_initialized == 1)
{
if (check_sd_status() != BSP_ERROR_NONE)
{
media_ptr->fx_media_driver_status = FX_IO_ERROR;
return;
}
}
/* Process the driver request specified in the media control block. */
switch(media_ptr->fx_media_driver_request)
{
case FX_DRIVER_INIT:
{
#if (FX_DRIVER_CALLS_BSP_SD_INIT == 1)
/* Initialize the SD instance */
if (is_initialized == 0)
{
status = BSP_SD_Init();
if (status == BSP_ERROR_NONE)
{
is_initialized = 1;
#endif
/* create a binary semaphore to check the DMA transfer status */
if (tx_semaphore_create(&transfer_semaphore, "sdmmc dma transfer semaphore", 0) != TX_SUCCESS)
{
media_ptr->fx_media_driver_status = FX_IO_ERROR;
}
else
{
media_ptr->fx_media_driver_status = FX_SUCCESS;
}
#if (FX_DRIVER_CALLS_BSP_SD_INIT == 1)
}
else
{
media_ptr->fx_media_driver_status = FX_IO_ERROR;
}
}
#endif
break;
}
case FX_DRIVER_UNINIT:
{
tx_semaphore_delete(&transfer_semaphore);
#if (FX_DRIVER_CALLS_BSP_SD_INIT == 1)
BSP_SD_DeInit();
is_initialized = 0;
#endif
/* Successful driver request. */
media_ptr->fx_media_driver_status = FX_SUCCESS;
break;
}
case FX_DRIVER_READ:
{
media_ptr->fx_media_driver_status = FX_IO_ERROR;
//TX_DISABLE /* disable interrupts */
if ((ULONG)(media_ptr->fx_media_driver_buffer) & 0x3)
{
if (sd_read_data(media_ptr, media_ptr->fx_media_driver_logical_sector + media_ptr->fx_media_hidden_sectors,
media_ptr->fx_media_driver_sectors, 1) == FX_SUCCESS)
{
media_ptr->fx_media_driver_status = FX_SUCCESS;
}
}
else
{
if (sd_read_data(media_ptr, media_ptr->fx_media_driver_logical_sector + media_ptr->fx_media_hidden_sectors,
media_ptr->fx_media_driver_sectors, 0) == FX_SUCCESS)
{
media_ptr->fx_media_driver_status = FX_SUCCESS;
}
}
//TX_RESTORE /* restore interrupts */
break;
}
case FX_DRIVER_WRITE:
{
media_ptr->fx_media_driver_status = FX_IO_ERROR;
//TX_DISABLE /* disable interrupts */
if (sd_write_data(media_ptr, media_ptr->fx_media_driver_logical_sector + media_ptr->fx_media_hidden_sectors,
media_ptr->fx_media_driver_sectors, 0) == FX_SUCCESS)
{
media_ptr->fx_media_driver_status = FX_SUCCESS;
}
//TX_RESTORE /* restore interrupts */
break;
}
case FX_DRIVER_FLUSH:
{
/* Return driver success. */
media_ptr->fx_media_driver_status = FX_SUCCESS;
break;
}
case FX_DRIVER_ABORT:
{
/* Return driver success. */
media_ptr->fx_media_driver_status = FX_SUCCESS;
break;
}
case FX_DRIVER_BOOT_READ:
{
/* the boot sector is the sector 0 */
status = BSP_SD_ReadBlocks_DMA((uint32_t*)media_ptr->fx_media_driver_buffer, 0, 1);
if (status != BSP_ERROR_NONE)
{
media_ptr->fx_media_driver_status = FX_IO_ERROR;
break;
}
if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) != TX_SUCCESS)
{
media_ptr->fx_media_driver_status = FX_IO_ERROR;
break;
}
/* Check if the sector 0 is the actual boot sector, otherwise calculate the offset into it.
Please note that this should belong to higher level of MW to do this check and it is here
as a temporary work solution */
partition_start = 0;
status = _fx_partition_offset_calculate(media_ptr -> fx_media_driver_buffer, 0,
&partition_start, &partition_size);
/* Check partition read error. */
if (status)
{
/* Unsuccessful driver request. */
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
return;
}
/* Now determine if there is a partition... */
if (partition_start)
{
if (check_sd_status() != BSP_ERROR_NONE)
{
media_ptr->fx_media_driver_status = FX_IO_ERROR;
return;
}
/* Yes, now lets read the actual boot record. */
status = BSP_SD_ReadBlocks_DMA((uint32_t*)media_ptr -> fx_media_driver_buffer, partition_start , 1);
/* Check status of SDIO Read. */
if (status != BSP_ERROR_NONE)
{
/* Unsuccessful driver request. */
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
return;
}
/* Wait for Rx Transfer completion */
if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) != TX_SUCCESS)
{
media_ptr->fx_media_driver_status = FX_IO_ERROR;
break;
}
}
/* Successful driver request. */
media_ptr -> fx_media_driver_status = FX_SUCCESS;
break;
}
case FX_DRIVER_BOOT_WRITE:
{
status = BSP_SD_WriteBlocks_DMA((uint32_t*)media_ptr->fx_media_driver_buffer, 0, 1);
if (status == BSP_ERROR_NONE)
{
if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) == TX_SUCCESS)
{
media_ptr->fx_media_driver_status = FX_SUCCESS;
}
else
{
media_ptr->fx_media_driver_status = FX_IO_ERROR;
}
}
break;
}
default:
{
media_ptr->fx_media_driver_status = FX_IO_ERROR;
break;
}
}
}
/**
* @brief BSP Tx Transfer completed callbacks
* @param Instance the SD instance
* @retval None
*/
void BSP_SD_WriteCpltCallback()
{
tx_semaphore_put(&transfer_semaphore);
}
/**
* @brief BSP Rx Transfer completed callbacks
* @param Instance the sd instance
* @retval None
*/
void BSP_SD_ReadCpltCallback()
{
tx_semaphore_put(&transfer_semaphore);
}
/**
* @brief 使用 BSP SD API 读取缓冲区,同时考虑暂存缓冲区
* @param FX_MEDIA *media_ptr 指针 FileX 主结构
* @param ULONG start_sector第一个开始读取的扇区
* @param UINT num_sectors要读取的扇区数量
* @param UINT use_scratch_buffer是否启用暂存缓冲区使用。
* @retval FX_SUCCESS成功FX_BUFFER_ERROR其他方面
*/
static UINT sd_read_data(FX_MEDIA *media_ptr, ULONG start_sector, UINT num_sectors, UINT use_scratch_buffer)
{
UINT status;
status = BSP_SD_ReadBlocks_DMA((uint32_t*)media_ptr->fx_media_driver_buffer, start_sector, num_sectors);
if (status == BSP_ERROR_NONE)
{
if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) == TX_SUCCESS)
{
status = FX_SUCCESS;
}
else
{
status = FX_BUFFER_ERROR;
}
}
return status;
}
/**
* @brief 使用 BSP SD API 写入缓冲区,同时考虑暂存缓冲区
* @param FX_MEDIA *media_ptr 指针 FileX 主结构
* @param ULONG start_sector第一个开始写作的sector
* @param UINT num_sectors要写入的扇区数
* @param UINT use_scratch_buffer是否启用暂存缓冲区使用。
* @retval FX_SUCCESS成功FX_BUFFER_ERROR其他方面
*/
static UINT sd_write_data(FX_MEDIA *media_ptr, ULONG start_sector, UINT num_sectors, UINT use_scratch_buffer)
{
UINT status;
status = BSP_SD_WriteBlocks_DMA((uint32_t*)media_ptr->fx_media_driver_buffer, start_sector, num_sectors);
if (status == BSP_ERROR_NONE)
{
if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) == TX_SUCCESS)
{
status = FX_SUCCESS;
}
else
{
status = FX_IO_ERROR;
}
}
return status;
}
void SDIO_IRQHandler(void)
{
HAL_SD_IRQHandler(&uSdHandle);
}
void DMA2_Stream6_IRQHandler(void)
{
HAL_DMA_IRQHandler(uSdHandle.hdmatx);
}
void DMA2_Stream3_IRQHandler(void)
{
HAL_DMA_IRQHandler(uSdHandle.hdmarx);
}
filex组件代码
头文件
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** FileX Component */
/** */
/** User Specific */
/** */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/* */
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* fx_user.h PORTABLE C */
/* 6.1.10 */
/* */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This file contains user defines for configuring FileX in specific */
/* ways. This file will have an effect only if the application and */
/* FileX library are built with FX_INCLUDE_USER_DEFINE_FILE defined. */
/* Note that all the defines in this file may also be made on the */
/* command line when building FileX library and application objects. */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
/* 09-30-2020 William E. Lamie Modified comment(s), and */
/* added product constants */
/* to enable code */
/* size optimization, */
/* resulting in version 6.1 */
/* 03-02-2021 William E. Lamie Modified comment(s), and */
/* added standalone support, */
/* resulting in version 6.1.5 */
/* 01-31-2022 Bhupendra Naphade Modified comment(s), and */
/* added product constant to */
/* support variable sector */
/* size in exFAT, */
/* resulting in version 6.1.10 */
/* */
/**************************************************************************/
#ifndef FX_USER_H
#define FX_USER_H
/* Defined, enables FileX fault tolerant service. */
#define FX_ENABLE_FAULT_TOLERANT
#define SD_CACHE_BUFFER_SIZE (2048)
#define FX_FAULT_TOLERANT_BUF_SIZE (2048) /*容错区*/
extern void *g_sd_cache_buffer;
extern FX_MEDIA g_sd_media_disk;
#ifdef FX_ENABLE_FAULT_TOLERANT
extern void *g_fault_tolerant_buffer;
#endif
#endif
源文件
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-16 shchl fx 组件入口函数
*/
#include "includes.h"
#if 1
#include "fx_api.h"
/*
*******************************************************************************************************
* 外部引入变量
*******************************************************************************************************
*/
/*
*******************************************************************************************************
* 变量
*******************************************************************************************************
*/
void *g_sd_cache_buffer; /*缓冲区指针*/
FX_MEDIA g_sd_media_disk; /*全局sd 文件硬盘结构体*/
#ifdef FX_ENABLE_FAULT_TOLERANT
void *g_fault_tolerant_buffer = NULL;
#endif
/*
*********************************************************************************************************
* 静态全局变量
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* 函数声明
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* 外部函数
*********************************************************************************************************
*/
int fx_application_define(void) {
/* 分配内存空间. */
g_sd_cache_buffer = app_malloc(SD_CACHE_BUFFER_SIZE);
#ifdef FX_ENABLE_FAULT_TOLERANT
g_fault_tolerant_buffer = app_malloc(FX_FAULT_TOLERANT_BUF_SIZE);
#endif
/*fx 初始化*/
fx_system_initialize();
return FX_SUCCESS;
}
TX_APP_DEFINE_EXPORT(fx_application_define); /*首先创建模块应用*/
/*
*********************************************************************************************************
* 内部函数
*********************************************************************************************************
*/
#endif
对filex函数进行封装了一层,提供程序进行调用(代码只进行了基本封装,待完善)
头文件
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-16 shchl first version
*/
#ifndef STM32_PROJECT_APP_FILE_API_H
#define STM32_PROJECT_APP_FILE_API_H
#include "includes.h"
UINT app_fx_open_sd();
UINT app_fx_close_sd();
UINT app_fx_file_create(const CHAR *file_name);
UINT app_fx_dir_create(const CHAR *dir_name);
UINT app_fx_file_open(FX_FILE *fp, CHAR *file_name, UINT open_type);
UINT app_fx_file_close(FX_FILE *fp);
UINT app_fx_file_delete(char *file_name);
UINT app_fx_dir_attr_read(char *dir_name,UINT *attr);
UINT app_fx_dir_delete(char *dir_name);
UINT app_fx_file_fprintf(FX_FILE *fp, const char *fmt, ...);
#endif //STM32_PROJECT_APP_FILE_API_H
源文件
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-16 shchl first version
*/
#include "app_file_api.h"
#include "fx_stm32_sd_driver.h"
#define FX_DATA_BUF_SIZE 256
static UINT init_flag = FX_NOT_OPEN;
static char fx_data_buf[FX_DATA_BUF_SIZE] = {0};
/**
* @brief 打开 sd
* @return
*/
UINT app_fx_open_sd() {
UINT status = 0;
if (init_flag != FX_SUCCESS) {
status = fx_media_open(&g_sd_media_disk,
"stm32 sd disk",
fx_stm32_sd_driver,
0,
g_sd_cache_buffer,
SD_CACHE_BUFFER_SIZE);
#ifdef FX_ENABLE_FAULT_TOLERANT
/* Enable the Fault-tolerant feature. */
status = fx_fault_tolerant_enable(&g_sd_media_disk,
g_fault_tolerant_buffer,
FX_FAULT_TOLERANT_BUF_SIZE);
#endif
init_flag = status;
}
return status;
}
UINT app_fx_close_sd() {
UINT status = 0;
if (init_flag == FX_SUCCESS) {
status = fx_media_close(&g_sd_media_disk);
if (fault_tolerant_buffer)app_free(fault_tolerant_buffer);
init_flag = FX_NOT_OPEN;
}
return status;
}
/**
* @brief 创建文件
* @param file_name 文件名
* @return
*/
UINT app_fx_file_create(const CHAR *file_name) {
UINT status;
status = fx_file_create(&g_sd_media_disk, (CHAR *) file_name);
fx_media_flush(&g_sd_media_disk);/*将缓存数据刷新到sd卡中*/
return status;
}
UINT app_fx_dir_create(const CHAR *dir_name) {
UINT status;
status = fx_directory_create(&g_sd_media_disk, (CHAR *) dir_name);
fx_media_flush(&g_sd_media_disk); /*将缓存数据刷新到sd卡中*/
return status;
}
/**
* @brief 打开文件,
* @param fp 文件指针
* @param file_name 文件名称
* @param open_type 打开类型
* @note 如果是 FX_OPEN_FOR_WRITE,文件如果不存在,则会创建新文件
* @return
*/
UINT app_fx_file_open(FX_FILE *fp, CHAR *file_name, UINT open_type) {
UINT status;
status = fx_file_open(&g_sd_media_disk, fp, file_name, open_type);
// 如果文件不存在,并且访问类型为写,则先创建文件,然后再打开一次
if (status == FX_NOT_FOUND && open_type == FX_OPEN_FOR_WRITE) {
status = fx_file_create(&g_sd_media_disk, file_name);
if (status == FX_SUCCESS) {
status = fx_file_open(&g_sd_media_disk, fp, file_name, open_type);
}
}
return status;
}
UINT app_fx_file_close(FX_FILE *fp) {
return fx_file_close(fp);
}
UINT app_fx_file_delete(char *file_name) {
return fx_file_delete(&g_sd_media_disk, file_name);
}
UINT app_fx_dir_delete(char *dir_name) {
return fx_directory_delete(&g_sd_media_disk, dir_name);
}
/**
* @brief 目录属性读取
* @param dir_name [in] 目录名
* @param attr [out] 返回
* @return
*/
UINT app_fx_dir_attr_read(char *dir_name, UINT *attr) {
return fx_directory_attributes_read(&g_sd_media_disk, dir_name, attr);
}
/**
* @brief 格式化文件写入数据
* @param fp
* @param fmt
* @param ...
* @return
*/
UINT app_fx_file_fprintf(FX_FILE *fp, const char *fmt, ...) {
if (!fp) return FX_PTR_ERROR;
va_list v_args;
va_start(v_args, fmt);
int len = vsnprintf((char *) fx_data_buf,
(size_t) sizeof(fx_data_buf),
(char const *) fmt,
v_args);
va_end(v_args);
if (len > FX_DATA_BUF_SIZE) return FX_NOT_ENOUGH_MEMORY;/*没有足够的内存*/
return fx_file_write(fp, fx_data_buf, len);
}
串口ota和filex组合(关于ota部分的内容,参考上篇)
增加filex的支持,将上传的文件保存到sd卡中
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-16 shchl first version
*/
#include "includes.h"
#include "ymodem.h"
#include "app_file_api.h"
static char upload_file_name[64] = {0};
static size_t update_file_total_size;
static size_t rec_data_len = 0;
static FX_FILE ota_file;
static enum rym_code ymodem_on_begin(struct rym_ctx *ctx, uint8_t *buf, size_t len) {
static char *tmp_file_name, *file_size;
UINT stat;
/* calculate and store file size */
tmp_file_name = (char *) &buf[0];
file_size = (char *) &buf[strlen(tmp_file_name) + 1];
memcpy(upload_file_name, tmp_file_name, strlen(tmp_file_name));
/*这里是保存的路径,现在是直接保存到根路径下*/
sprintf(upload_file_name, "%s", tmp_file_name);
stat = app_fx_file_open(&ota_file, upload_file_name, FX_OPEN_FOR_WRITE);
if (stat) {
return RYM_CODE_NAK;
}
fx_file_seek(&ota_file, FX_SEEK_BEGIN);
update_file_total_size = atol(file_size);
return RYM_CODE_ACK;
}
static enum rym_code ymodem_on_data(struct rym_ctx *ctx, uint8_t *buf, size_t len) {
/*TODO 接收升级数据包处理*/
fx_file_write(&ota_file, buf, len);
rec_data_len += len;
return RYM_CODE_ACK;
}
static void rym_delay_ms(size_t ms) {
tx_thread_sleep(ms);
}
static uint32_t rym_sys_tick_get() {
return tx_time_get();
}
static uint32_t rym_millisecond_to_tick(uint32_t ms) {
uint32_t tick;
tick = TX_TIMER_TICKS_PER_SECOND * (ms / 1000);
tick += (TX_TIMER_TICKS_PER_SECOND * (ms % 1000) + 999) / 1000;
/* return the calculated tick */
return tick;
}
static size_t rym_write(struct rym_ctx *self, size_t offset, const uint8_t *buf, size_t len) {
comSendBuf(COM1, (uint8_t *) (buf + offset), len);
return len;
}
static size_t rym_read_wait(struct rym_ctx *self, size_t offset, uint8_t *buf, size_t len,
uint32_t timeout) {
UNUSED(self);
size_t readCnt = 0;
uint32_t cur_tick = rym_sys_tick_get();
while (len) {
if (comGetChar(COM1, (uint8_t *) (buf + readCnt + offset)) == 1) {
readCnt++;
len--;
} else {
if (rym_sys_tick_get() > cur_tick + timeout) {
break;
}
}
}
return readCnt;
}
static inline void ota_ymodem_lock() {
/*由于shell 组件中已做了加锁处理,这里就可以不需要进行加锁*/
}
static inline void ota_ymodem_unlock() {
/*由于shell 组件中已做了加锁处理,这里就可以不需要进行解锁*/
}
void console_ota_func() {
struct rym_ctx rctx;
/*变量重新初始化*/
{
memset(upload_file_name, 0, strlen(upload_file_name));/*清除上次的文件名*/
rec_data_len = 0;
}
rctx.driver.rym_delay_ms = rym_delay_ms;
rctx.driver.rym_sys_tick_get = rym_sys_tick_get;
rctx.driver.rym_millisecond_to_tick = rym_millisecond_to_tick;
rctx.driver.rym_write = rym_write;
rctx.driver.rym_read_wait = rym_read_wait;
/*内存分配*/
#ifdef RYM_CTX_USE_ALLOC_CALLBACK
rctx.rym_malloc = (void *(*)(size_t)) app_malloc;
rctx.rym_free = (void (*)(void *)) app_free;
#endif
ota_ymodem_lock();/*加锁*/
int32_t status = rym_recv_on_device(&rctx,
ymodem_on_begin,
ymodem_on_data,
NULL, 1000);
/*todo 是否需要重启芯片(针对于ota升级)*/
/*关闭文件*/
app_fx_file_close(&ota_file);
ota_ymodem_unlock();/*解锁*/
tx_log("\r\n------------stats is:%d------------\r\n", status);
tx_log("file name:%s;file size:%d; rec lec:%d\r\n", upload_file_name, update_file_total_size, rec_data_len);
}
#ifdef SHELL_USING_CMD_EXPORT
/*shell 脚本来管理*/
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN,
ota, console_ota_func, "ymodem ota upgrade");
#endif
shell组件和filex组件的结合(实现类似linux下的文件操作的逻辑,这里实现了基本的函数,待完善)
ls 命令
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-16 shchl first version
*/
#include "includes.h"
#include "app_file_api.h"
/*
*******************************************************************************************************
* 外部引入变量
*******************************************************************************************************
*/
/*
*******************************************************************************************************
* 变量
*******************************************************************************************************
*/
/*
*********************************************************************************************************
* 静态全局变量
*********************************************************************************************************
*/
FX_PATH history_path; /*历史路径*/
/*
*********************************************************************************************************
* 函数声明
*********************************************************************************************************
*/
static UINT ls_simple_info();
/*
*********************************************************************************************************
* 外部函数
*********************************************************************************************************
*/
int fx_ls_func(int argc, char *argv[]) {
UINT stat = FX_ERROR_FIXED;
if (argc > 2) {
tx_printf("===========================USEG MANUAL=======================\r\n");
tx_printf("ls ------- list current dir all files or dirs\r\n");
tx_printf("ls <dir_name> ------- list <dir_name> all files or dirs(dir_name is absolute path) \r\n");
return (int) stat;
}
app_fx_open_sd();
char *path = NULL; /*如果只有一个参数,直接传null,底层会直接匹配到根目录*/
if (argc == 2) {
path = argv[1];
}
memcpy(&history_path, &g_sd_media_disk.fx_media_default_path, sizeof(FX_PATH));
fx_directory_local_path_set(&g_sd_media_disk, &history_path, path);
stat = ls_simple_info();
return (int) stat;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
ls, fx_ls_func, "list files");
/*
*********************************************************************************************************
* 内部函数
*********************************************************************************************************
*/
static UINT ls_simple_info() {
UINT status;
UINT attr;
ULONG size;
UINT count = 0;
CHAR entry_name[64];
fx_directory_first_full_entry_find(&g_sd_media_disk,
entry_name,
&attr, &size,
NULL, NULL, NULL,
NULL, NULL, NULL);
tx_printf("===========================%s==============================\r\n", entry_name);
tx_printf("%-5s %-50s %15s\r\n", "type", "filename", "size(byte)");
do {
tx_printf("%-5s %-50s %15lu\r\n",
(attr & FX_DIRECTORY) ? "dir" : "file", entry_name, size);
/* 读取目录项,索引会自动下移 */
status = fx_directory_next_full_entry_find(&g_sd_media_disk,
entry_name,
&attr, &size,
NULL, NULL, NULL,
NULL, NULL, NULL);
count++;
} while (status == FX_SUCCESS || entry_name[0] == 0);
tx_printf("===========================total:%u==============================\r\n", count);
return status;
}
cat 命令
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-17 shchl first version
*/
#include "includes.h"
#include "app_file_api.h"
/*
*******************************************************************************************************
* ??????
*******************************************************************************************************
*/
/*
*******************************************************************************************************
* ??
*******************************************************************************************************
*/
/*
*********************************************************************************************************
* ??????
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* ????
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* ????
*********************************************************************************************************
*/
int fx_cat_func(int argc, char *argv[])
{
FX_FILE file;
UINT stat = FX_ERROR_FIXED;
if (argc != 2)
{
tx_printf("===========================USEG MANUAL=======================\r\n");
tx_printf("cat <file_name> ------- read file content\r\n");
return (int)stat;
}
stat = app_fx_file_open(&file, argv[1], FX_OPEN_FOR_READ);
if (stat == SUCCESS)
{
uint8_t buf[128] = {0};
ULONG real_read_cnt;
do
{
stat = fx_file_read(&file, buf, 128, &real_read_cnt);
tx_printf("%s\r\n", buf);
} while (real_read_cnt >= 128 && stat == FX_SUCCESS);
fx_file_close(&file);
}
return (int)stat;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
cat, fx_cat_func, "cat file");
/*
*********************************************************************************************************
* ????
*********************************************************************************************************
*/
echo 命令
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-16 shchl first version
*/
#include "includes.h"
#include "app_file_api.h"
/*
*******************************************************************************************************
* 外部引入变量
*******************************************************************************************************
*/
/*
*******************************************************************************************************
* 变量
*******************************************************************************************************
*/
/*
*********************************************************************************************************
* 静态全局变量
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* 函数声明
*********************************************************************************************************
*/
static UINT ls_simple_info();
/*
*********************************************************************************************************
* 外部函数
*********************************************************************************************************
*/
int fx_echo_func(int argc, char *argv[])
{
UINT stat = FX_ERROR_FIXED;
if (argc == 1 || argc > 3)
{
tx_printf("===========================USEG MANUAL=======================\r\n");
tx_printf("echo \"your input content\"\r\n");
tx_printf("echo \"your input content\" file_name\r\n");
return (int)stat;
}
app_fx_open_sd();
switch (argc)
{
case 2:
{ /*TODO-----------扩展功能()-----------------*/
tx_printf("%s\r\n", argv[1]);
stat = FX_SUCCESS;
break;
}
default:
{
// @note 不可能执行到此处
char *content = argv[1];
char *file_name = argv[2];
static FX_FILE fp;
// 判断文件
stat = app_fx_file_open(&fp, file_name, FX_OPEN_FOR_WRITE);
if (stat)
{
logWarning("open file is error:%d", stat);
}
else
{
stat = fx_file_write(&fp, content, strlen(content));
if (stat)
{
logWarning("fx file write error[%d]", stat);
} else {
fx_media_flush(&g_sd_media_disk);
logDebug("write data ok");
app_fx_file_close(&fp);
}
return stat;
}
break;
}
}
return (int)stat;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
echo, fx_echo_func, "echo display");
/*
*********************************************************************************************************
* 内部函数
*********************************************************************************************************
*/
static UINT ls_simple_info()
{
char entry_name[64];
UINT status;
UINT attributes;
ULONG size;
UINT count = 0;
fx_directory_first_entry_find(&g_sd_media_disk, entry_name);
tx_printf("===========================%s==============================\r\n", entry_name);
tx_printf("%-5s %-50s %15s\r\n", "type", "filename", "size");
for (int cnt = 0;; cnt++)
{
/* 读取目录项,索引会自动下移 */
status = fx_directory_next_full_entry_find(&g_sd_media_disk,
entry_name,
&attributes, &size,
NULL, NULL, NULL,
NULL, NULL, NULL);
if (status != FX_SUCCESS || entry_name[0] == 0)
{
break;
}
// if (entry_name[0] == '.') {
// continue;
// }
tx_printf("%-5s %-50s %15lu\r\n",
(attributes & FX_DIRECTORY) ? "dir" : "file",
entry_name, size);
count++;
}
tx_printf("===========================total:%u==============================\r\n", count);
return status;
}
mkdir 命令
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-16 shchl first version
*/
#include "includes.h"
#include "app_file_api.h"
/*
*******************************************************************************************************
* 外部引入变量
*******************************************************************************************************
*/
/*
*******************************************************************************************************
* 变量
*******************************************************************************************************
*/
/*
*********************************************************************************************************
* 静态全局变量
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* 函数声明
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* 外部函数
*********************************************************************************************************
*/
int fx_mkdir_func(int argc, char *argv[]) {
UINT stat = FX_ERROR_FIXED;
if (argc != 2) {
logWarning("touch format err,use template {touch <filename>}");
} else {
app_fx_open_sd();/*内部逻辑只会调用一次,如果sd打开成功的话*/
/*获取文件名*/
char *dir_name = argv[1];
stat = app_fx_dir_create(dir_name);
if (stat == FX_SUCCESS) {
logInfo("create dir success");
} else {
logWarning("create dir error:%d", stat);
}
}
return (int)stat;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
mkdir, fx_mkdir_func, "create new dir");
/*
*********************************************************************************************************
* 内部函数
*********************************************************************************************************
*/
rm 命令
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-17 shchl first version
*/
#include "includes.h"
#include "app_file_api.h"
/*
*******************************************************************************************************
* 外部引入变量
*******************************************************************************************************
*/
/*
*******************************************************************************************************
* 变量
*******************************************************************************************************
*/
/*
*********************************************************************************************************
* 静态全局变量
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* 函数声明
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* 外部函数
*********************************************************************************************************
*/
int fx_rm_func(int argc, char *argv[]) {
UINT stat = FX_ERROR_FIXED;
UINT attr;
if (argc != 2) {
tx_printf("===========================USEG MANUAL=======================\r\n");
tx_printf("rm ------- list current dir all files or dirs\r\n");
tx_printf("ls <dir_name> ------- list <dir_name> all files or dirs(dir_name is absolute path) \r\n");
return (int) stat;
}
app_fx_open_sd();
/*获取删除的节点名称*/
char *entry_name = argv[1];
stat = app_fx_dir_attr_read(entry_name, &attr);
if (stat == FX_SUCCESS) { /*读取成功*/
/*执行删除目录*/
stat = app_fx_dir_delete(entry_name);
if (stat) {
logError("delete dir error:%lu", stat);
}
} else if (stat == FX_NOT_DIRECTORY) { /*不是目录,默认就是文件*/
stat = app_fx_file_delete(entry_name);
if (stat) {
logError("delete file error:%lu", stat);
}
} else if (stat == FX_NOT_FOUND) {
logWarning("%s is not exist", entry_name);
} else {
logError("happened unknown error:%lu", stat);
}
return (int) stat;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
rm, fx_rm_func, "delete file or empty dir");
/*
*********************************************************************************************************
* 内部函数
*********************************************************************************************************
*/
touch 命令
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-16 shchl first version
*/
#include "includes.h"
#include "app_file_api.h"
/*
*******************************************************************************************************
* 外部引入变量
*******************************************************************************************************
*/
/*
*******************************************************************************************************
* 变量
*******************************************************************************************************
*/
/*
*********************************************************************************************************
* 静态全局变量
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* 函数声明
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* 外部函数
*********************************************************************************************************
*/
int fx_touch_func(int argc, char *argv[]) {
UINT stat;
if (argc != 2) {
logWarning("touch format err,use template {touch <filename>}");
} else {
app_fx_open_sd();/*内部逻辑只会调用一次,如果sd打开成功的话*/
/*获取文件名*/
char *file_name = argv[1];
stat = app_fx_file_create(file_name);
if (stat == FX_SUCCESS) {
logInfo("create file success");
} else {
logWarning("create file error:%d", stat);
}
}
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
touch, fx_touch_func, "create new file");
/*
*********************************************************************************************************
* 内部函数
*********************************************************************************************************
*/
测试结果
ls测试
rm 测试(此命令暂时支持删除空目录和文件)
其他命令测试都测试通过这里就不过多说明
ota ymodem文件上传协议测试
总结
- 需要对filex的api函数有个基本的认识和理解
- filex组件使用起来,相较于其他的文件系统,更加容易和方便