stm32开发之threadx+letter-shell+filex+ymodem组合使用(实现文件上传和文件shell命令)

前言

  1. 本次使用的是stm32f407zgt6
  2. 使用到上篇博客所用到的shell组件,加上之前所记录的filex组件
  3. 本篇博客的主要内容是关于上篇博客ota与filex的结合和filex与shell组件的结合
  4. 本篇主要是为后面去整合modulex模块,实现从filex里面去动态加载bin文件,然后动态运行作为bin文件的存储方案的规划记录
  5. 使用filex的时候,注意sd卡格式的问题.

本篇实验完成的目标

  1. ota 部分上传文件
  2. filex组件的结合
  3. filex和shell组件的结合
  4. 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>&copy; 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>&copy; 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驱动对接的代码

  1. 核心逻辑是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文件上传协议测试

在这里插入图片描述
在这里插入图片描述

总结

  1. 需要对filex的api函数有个基本的认识和理解
  2. filex组件使用起来,相较于其他的文件系统,更加容易和方便
  • 19
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
内置 "cmd-list" 命令获取所有命令列表 支持 tab 键补全命令 支持 backspace 回退,这个在 putty 上有 bug ,还没修复。在secureCRT正常。 支持上下箭头回溯历史,这个功能没有做的很好; 支持左右箭头编辑当前命令行输入; 提供 shell_cmdparam()函数转换命令后所跟的数字参数(字符串转整型),详见 demo 提供 shell_option_suport() 函数,使命令行支持 getopt()函数,详见 demo 系统共有9个文件,全部与硬件无关,编译语言要在 C99 以上(keil 在 project -> Options .. -> c/c++ -> C99 勾上) kernel.h // 一些必要的宏定义 shell.c,shell.h //具体的命令行解释的实现 ustdio.c,ustdio.h //非标准输出文件,重新链接 printf ,并提供一个小巧型的 printk 函数 avltree.c,avltree.h //平衡二叉树支持,shell 默认用链表建立查询机制,有必要可在shell.h 中开启二叉树 getopt.c,getopt.h //网上找的 getopt() 源码 除了 getopt.c,getopt.h 两个文件是我从网上找的源码,主要实现命令行的 getopt()解析,其他的都是笔者所写。 使用: 1,首先把 shell.c ustdio.c 加入工程,这两个文件是必须的。 如果不用 getopt()函数可以不添加getopt.c文件shell默认使用链表来构建查询系统,但也提供了平衡二叉树的方式,在shell.h中有开启的开关,如不需要可以不添加avltree.c。 include "shell.h" 2,先对硬件进行基本的初始化。 撰写串口发送函数,形如 void usart_puts(char * str , uint16_t len) ; 调用函数 shell_init("shell >",usart_puts); //初始化shell的输入标志和默认输出指向 串口接收以包为单位。 3,新建全局变量 struct shell_input serial_shell ; 并初始化 SHELL_INPUT_INIT(&serial;_shell ,usart_puts);初始化输入缓存和输出交互; 4,串口接收到一整包函数后,调用 shell_input(&serial;_shell , packet , pktlen) ;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

詩不诉卿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值