stm32开发之threadx+modulex+filex+shell组件(实现命令行动态加载程序)

前言

  1. 前几篇博客基本上已经将filex、levelx、threadx、modulex、shell 组件大概都记录了一遍.
  2. 本篇博客做个综合实际案例记录.

实现效果

在这里插入图片描述

代码程序

Modulex组件

源文件

/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-4-19     shchl   first version
 */
#include "includes.h"

#if 1
#define MODULE_DATA_SIZE           (20*1024)  /* 供动态APP使用 */
#define OBJECT_MEM_SIZE            (20*1024)    /* 供动态APP的动态内存管理申请使用 */
/*
*******************************************************************************************************
*                               外部引入变量
*******************************************************************************************************
*/

/*
*******************************************************************************************************
*                               变量
*******************************************************************************************************
*/
TX_QUEUE ResidentQueue;       /* 消息队列,用于主程序和动态APP通信 */
uint32_t MessageQueuesBuf[100];

/*
*********************************************************************************************************
*                                       静态全局变量
*********************************************************************************************************
*/
static ULONG memory_faults = 0;
static UCHAR *module_data_area;
static UCHAR *object_memory;

/*
*********************************************************************************************************
*                                      函数声明
*********************************************************************************************************
*/

static VOID module_fault_handler(TX_THREAD *thread, TXM_MODULE_INSTANCE *module);
/*
*********************************************************************************************************
*                                      外部函数
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*	函 数 名: module_application_define
*	功能说明: 创建 模块管理任务线程
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
int module_application_define(void) {
    UINT status;
    /*模块 分配内存空间(使用全局数组的方式)*/
    static UCHAR obj_mem[OBJECT_MEM_SIZE];
    static UCHAR data_area[MODULE_DATA_SIZE];
    /*使用 动态内存分配的方式*/
//    object_memory = app_malloc(OBJECT_MEM_SIZE);
//    module_data_area = app_malloc(MODULE_DATA_SIZE);
    object_memory = obj_mem;
    module_data_area = data_area;
    /* 创建常驻消息队列 */
    if (tx_queue_create(&ResidentQueue, "Resident Queue",
                        TX_1_ULONG, MessageQueuesBuf,
                        16 * sizeof(ULONG)) != TX_SUCCESS) {
        Error_Handler();
    }

    /* 初始化动态加载管理器,主要是给动态APP的数据空间使用  */
    status = txm_module_manager_initialize((VOID *) module_data_area, MODULE_DATA_SIZE);

    if (status != TX_SUCCESS) {
        Error_Handler();
    }
    /* 供动态APP使用的对象内存池,主要各种控制块申请 */
    status = txm_module_manager_object_pool_create(object_memory, OBJECT_MEM_SIZE);
    if (status != TX_SUCCESS) {
        Error_Handler();
    }
    /* 注册faults管理 */
    status = txm_module_manager_memory_fault_notify(module_fault_handler);
    if (status != TX_SUCCESS) {
        Error_Handler();
    }
    return TX_SUCCESS;
}

TX_THREAD_EXPORT_LV1(module_application_define); /*首先创建模块应用*/
/*
*********************************************************************************************************
*	函 数 名: module_fault_handler
*	功能说明: 监测faults
*	形    参: ---
*	返 回 值: 无
*********************************************************************************************************
*/
static VOID module_fault_handler(TX_THREAD *thread, TXM_MODULE_INSTANCE *module) {
    tx_log("module_fault_handler: thread[%s],module[%s]\r\n", thread->tx_thread_name, module->txm_module_instance_name);
    /* 统计错误消息  */
    memory_faults++;
}


#endif

Modulex 调用的api接口(对modulex提供的函数进行封装)

头文件

/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-4-19     shchl   first version
 */

#ifndef STM32_PROJECT_APP_MODULE_API_H
#define STM32_PROJECT_APP_MODULE_API_H

#include "txm_module.h"

/**
 * @brief 模块信息结构体
 */
typedef struct module_info_struct {
#define MODULE_NAME_LEN 32
    char module_name[MODULE_NAME_LEN]; /*模块名*/
    uint32_t load_addr; /*加载地址地址(适用于flash方式,定位bin数据)*/
    TXM_MODULE_INSTANCE instance;  /* 模块实例 */
} module_info;

UINT app_txm_module_read(module_info *info, void (*info_out_handle)(TXM_MODULE_INSTANCE *instance, ULONG prop));

UINT app_txm_module_start(module_info *info);

UINT app_txm_module_stop(module_info *info);

UINT app_txm_module_unload(module_info *info);

UINT app_txm_module_fx_load(module_info *info, FX_MEDIA *media_ptr, CHAR *file_name);

UINT app_txm_module_file_load(module_info *info, CHAR *file_name, void (*bin_data_handle)(uint8_t *data, uint16_t len));

#endif //STM32_PROJECT_APP_MODULE_API_H

源文件

/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-4-19     shchl   first version
 */

#include "includes.h"
#include "app_file_api.h"

static FX_FILE module_file;


/*默认实现模块输出*/
static void app_txm_module_info_out(TXM_MODULE_INSTANCE *instance, ULONG prop) {
    tx_printf("===============================app_txm_module_info_out================================\r\n");
    tx_printf("------------------module build info------------------\r\n");
    tx_printf("\t--Compiled for %s compiler\r\n",
              ((prop >> 25) == 1) ? "CubeIDE (GNU)" : ((prop >> 24) == 1) ? "ARM KEIL" : "IAR EW");
    tx_printf("\t--Shared/external memory access is %s\r\n", ((prop & 0x04) == 0) ? "Disabled" : "Enabled");
    tx_printf("\t--MPU protection is %s\r\n", ((prop & 0x02) == 0) ? "Disabled" : "Enabled");
    tx_printf("\t--%s mode execution is enabled for the module\r\n\r\n", ((prop & 0x01) == 0) ? "Privileged" : "User");
    tx_printf("------------------module application info------------------\r\n");
    tx_printf("\t--application id %#lx;instance id:%#lx;name:%s\r\n",
              instance->txm_module_instance_application_module_id,
              instance->txm_module_instance_id,
              instance->txm_module_instance_name);
    tx_printf("\t--code section【start addr: %#lx||end addr:%#lx||size(bytes):%lu】\r\n",
              (ULONG) instance->txm_module_instance_code_start,
              (ULONG) instance->txm_module_instance_code_end,
              instance->txm_module_instance_code_size);
    tx_printf("\t--data section【start addr: %#lx||end addr:%#lx||size(bytes):%lu】\r\n",
              (ULONG) instance->txm_module_instance_data_start,
              (ULONG) instance->txm_module_instance_data_end,
              instance->txm_module_instance_data_size);

    tx_printf("\t--shared_memory 【addr:%#lx||size(bytes): %lu】\r\n",
              instance->txm_module_instance_shared_memory_address,
              instance->txm_module_instance_shared_memory_length);
}


UINT app_txm_module_start(module_info *info) {
    UINT status;
    /*确保模块已加载,校验逻辑内部已提供*/
    status = txm_module_manager_start(&info->instance);
    return status;
}

UINT app_txm_module_stop(module_info *info) {
    UINT status;
    /*确保模块已加载,校验逻辑内部已提供*/
    status = txm_module_manager_stop(&info->instance);

    return status;
}

UINT app_txm_module_unload(module_info *info) {

    UINT status;
    /*确保模块已加载,校验逻辑内部已提供*/
    status = txm_module_manager_unload(&info->instance);

    return status;

}

UINT app_txm_module_fx_load(module_info *info, FX_MEDIA *media_ptr, CHAR *file_name) {
    UINT status;
    /*判断media 设备是否挂载*/
    if (media_ptr->fx_media_id != FX_MEDIA_ID) {

        return TX_NOT_AVAILABLE;
    }
    if (info->instance.txm_module_instance_id == TXM_MODULE_ID) {

        return TXM_MODULE_ALREADY_LOADED;
    }
    /*确保模块已加载,校验逻辑内部已提供*/
    status = txm_module_manager_file_load(&info->instance,
                                          info->module_name,
                                          media_ptr,
                                          file_name);
    return status;
}

/**
 * @brief 从文件中加载模块文件,自定义数据处理
 * @param addr
 * @param file_name
 * @return
 */
UINT app_txm_module_file_load(module_info *info, CHAR *file_name,
                              void (*bin_data_handle)(uint8_t *data, uint16_t len)) {
    TX_INTERRUPT_SAVE_AREA
    if (!bin_data_handle) {
        return TX_PTR_ERROR;
    }
    /*判断media 设备是否挂载*/

    if (info->instance.txm_module_instance_id == TXM_MODULE_ID) {

        return TXM_MODULE_ALREADY_LOADED;
    }
#define READ_BUF_SIZE 2048
    TX_DISABLE
    uint8_t *cache_buf = app_malloc(READ_BUF_SIZE);
    TX_RESTORE
    if (cache_buf == NULL) return TX_NO_MEMORY;
    UINT status = app_fx_file_open(&module_file, file_name, FX_OPEN_FOR_READ);
    ULONG actual_read;
    if (status) {
        tx_printf("app_txm_module_file_load error:%#x\r\n", status);
        return TX_NOT_AVAILABLE;
    }
    do {
        status = fx_file_read(&module_file, cache_buf, READ_BUF_SIZE, &actual_read);
        bin_data_handle(cache_buf, actual_read);
    } while (status &= FX_END_OF_FILE);
    fx_file_close(&module_file);
    TX_DISABLE
    app_free(cache_buf);
    TX_RESTORE
    return TX_SUCCESS;
#undef READ_BUF_SIZE
}

/**
 * @brief 模块信息读取
 * @param info
 * @param info_out_handle 信息输出(可为null,使用默认输出)
 * @return
 */
UINT app_txm_module_read(module_info *info, void (*info_out_handle)(TXM_MODULE_INSTANCE *instance, ULONG prop)) {
    UINT status = TX_SUCCESS;
    ULONG module_properties;
    /*确定 模块是否已加载*/
    if (info->instance.txm_module_instance_id == TXM_MODULE_ID) {
        /* 获取动态APP属性 */
        status = txm_module_manager_properties_get(
                &info->instance,
                &module_properties);
    } else {  // 未加载
        /* 加载动态APP */
        return TXM_MODULE_UNLOADED;
    }
    if (status) {
        tx_log("txm_module_manager_properties_get error:[%d]\r\n", status);
        return status;
    }
    if (!info_out_handle) {
        /*模块信息打印*/
        app_txm_module_info_out(&info->instance, module_properties);
    } else {
        info_out_handle(&info->instance, module_properties);
    }
    return status;
}


对接shell 组件(命令行控制)

/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-4-19     shchl   first version
 */
#include "includes.h"

#if 1

#include "app_module_api.h"

static module_info app_module;


/**
 * @brief sys_thread 命令
 * @param argc
 * @param argv
 * @return
 */
int app_module_fnc(int argc, char *argv[]) {
    UINT status = TX_NOT_AVAILABLE;
    if (argc < 2 || argc > 3) {
        tx_printf("===========================USEG MANUAL=======================\r\n");
        tx_printf("module load ------- load module\r\n");
        return -1;
    }
    char *cmd = argv[1];
    if (argc == 3) {

        if (strstr(cmd, "load")) {

            status = app_txm_module_fx_load(&app_module, &g_fx_media, argv[2]);
        }
    } else {
        if (strstr(cmd, "info")) {
            status = app_txm_module_read(&app_module, NULL);
        } else if (strstr(cmd, "unload")) {
            status = app_txm_module_unload(&app_module);
        } else if (strstr(cmd, "start")) {
            status = app_txm_module_start(&app_module);
        } else if (strstr(cmd, "stop")) {
            status = app_txm_module_stop(&app_module);
        } else {
            logWarning("not support cmd");
        }
    }
    if (status)logError("err result:%d", status)
    return 0;
}

SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) |
                 SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
                 module,
                 app_module_fnc,
                 "module load");

#endif

bin 文件上传(通过ota方式)

/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-4-19     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_printf("\r\n------------stats is:%ld------------\r\n", status);
    tx_printf("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

模块程序

#define TXM_MODULE


#include "txm_module.h"




/*
*********************************************************************************************************
*                                    宏定义
*********************************************************************************************************
*/
#define DEFAULT_STACK_SIZE        1024

#define App_Printf_ID1       (TXM_APPLICATION_REQUEST_ID_BASE)
#define App_Printf_ID2       (TXM_APPLICATION_REQUEST_ID_BASE + 1)


#define MODULE_THREAD_PRIO                         3
#define MODULE_THREAD_PREEMPTION_THRESHOLD         MODULE_THREAD_PRIO

ULONG      AppModuleStk[DEFAULT_STACK_SIZE/4];

/* 相关控制块 */
TX_THREAD               *thread_0;
TX_QUEUE                *resident_queue;

/* 函数 */
void thread_0_entry(ULONG thread_input);
void Error_Handler1(void);


/*
*********************************************************************************************************
*	函 数 名: default_module_start
*	功能说明: 动态APP入口
*	形    参: ---
*	返 回 值: 无
*********************************************************************************************************
*/
void  demo_module_start(ULONG id)
{
    CHAR    *pointer;

    /* 从主程序申请相关控制块,不在APP里面申请,防止APP出问题了影响主程序 */
    txm_module_object_allocate((void*)&thread_0, sizeof(TX_THREAD));
    /* 创建任务 */
    tx_thread_create(thread_0,
                     "module thread qqq",
                     thread_0_entry,
                     0,
                     &AppModuleStk[0],
                     DEFAULT_STACK_SIZE,
                     MODULE_THREAD_PRIO,
                     MODULE_THREAD_PREEMPTION_THRESHOLD,
                     TX_NO_TIME_SLICE,
                     TX_AUTO_START);

}

/*
*********************************************************************************************************
*	函 数 名: thread_0_entry
*	功能说明: 动态APP里面的任务
*	形    参: ---
*	返 回 值: 无
*********************************************************************************************************
*/
void thread_0_entry(ULONG thread_input)
{
    /* 防止警告 */
    UINT num = 0;
    while(1)
    {
        /* 调用主程序里面的串口打印 */
        num++;
        txm_module_application_request(App_Printf_ID1, num, 0, 0);
        tx_thread_sleep(1000);
    }
}

/*
*********************************************************************************************************
*	函 数 名: thread_0_entry
*	功能说明: 执行出错
*	形    参: ---
*	返 回 值: 无
*********************************************************************************************************
*/
void Error_Handler1(void)
{
    tx_thread_sleep(TX_WAIT_FOREVER);
}


加入宏定义

在txm_module_port.h中加入,不在txm_module_user.h加,由于我们编译模块的时候,是没有加入相关宏定义的,所以
txm_module_user.h中是不会生效的

#define FX_FILEX_PRESENT
#define TXM_MODULE_KERNEL_STACK_SIZE    2048  // 内核栈设置大一些,由于使用了filex

构建模块bin

  1. 由于加入filex ,所以构建模块时,脚本文件配置加入对应的filex头文件相关路径,然后重新生成库文件和模块bin文件
    在这里插入图片描述

测试

生成好的bin文件,通过ota上传到sd卡

在这里插入图片描述

加载module文件

在这里插入图片描述

查看module信息

在这里插入图片描述

启动模块

  1. 为了方便停止,10秒打印一次模块调用的信息
    在这里插入图片描述

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

查看线程信息

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

停止模块

在这里插入图片描述

总结

  1. 目前已经可以动态加载模块了,后面再补充两个模块之间通信的记录
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: STM32 FileX是一款嵌入式文件系统,专为STM32微控制器系列而设计和优化。它提供了一个强大而灵活的文件管理系统,适用于存储和管理嵌入式系统中的各种文件类型。 STM32 FileX具有以下特点和优势: 1. 系统资源占用低:FileX对内存资源的要求非常低,可以在有限的嵌入式系统中运行,而不会造成系统资源的浪费,从而使得STM32微控制器可以更加高效地执行其他任务。 2. 多种文件类型支持:FileX可以处理各种类型的文件,包括文本文件、二进制文件、图像文件等。它支持常见的文件操作,如打开、读取、写入、重命名、删除等,使得嵌入式系统可以灵活地处理不同类型的文件。 3. 文件系统安全性:FileX提供了数据完整性和文件系统安全性的保护机制。通过使用校验和、CRC校验、写入保护等技术,可以保证文件在读写过程中不会被破坏或损坏,确保数据的可靠性和完整性。 4. 支持多线程:FileX支持多线程操作,可以同时处理多个文件的读写操作。这在复杂的嵌入式系统中非常有用,可以提高系统的整体性能和效率。 5. 高度可配置FileX可以根据具体的应用需求进行灵活的配置。用户可以根据需要选择适合的文件系统大小、块大小、簇大小等参数,以满足自己的存储容量和性能要求。 总的来说,STM32 FileX是一款功能强大、高效可靠的嵌入式文件系统。它在不占用过多系统资源的同时,提供了丰富的文件操作功能,可以满足各种嵌入式系统对文件管理的需求。无论是嵌入式设备的开发者还是应用工程师,都能够通过使用STM32 FileX轻松实现文件的存储、管理和操作。 ### 回答2: STM32 FileX是STMicroelectronics开发的一款嵌入式文件系统。它是专门为STM32微控制器设计的,提供了可靠的文件系统功能,能够在嵌入式系统中进行文件的读写和管理。 STM32 FileX具有以下特点和功能: 1. 高性能和低资源占用:STM32 FileX采用了高效的算法和数据结构,使其能够在嵌入式系统中快速且高效地进行文件的读写操作,并且占用的系统资源较少,有利于节省处理器的计算能力和内存空间。 2. 可靠的数据保护:STM32 FileX提供了可靠的数据保护机制,包括存储介质上的文件一致性检查、写操作的缓存管理、数据的完整性和可靠性验证等,能够有效地防止数据损坏和丢失,保证了数据的可靠性和一致性。 3. 多种文件系统支持:STM32 FileX支持多种文件系统,包括FAT12、FAT16、FAT32等,能够适应不同的应用需求和存储介质类型。 4. 灵活的文件管理功能:STM32 FileX提供了丰富的文件管理功能,包括文件的创建、打开、读写、删除等操作,能够方便地进行文件的管理和维护。 5. 完善的API接口和开发工具:STM32 FileX提供了完善的API接口和开发工具,使开发者能够快速地集成和使用该文件系统,提高开发效率。 6. 应用广泛:STM32 FileX适用于多种嵌入式应用场景,包括工业自动化、智能家居、车载娱乐系统、医疗设备等,能够满足不同领域的文件管理需求。 总的来说,STM32 FileX是一款高性能、可靠的嵌入式文件系统,能够方便地进行文件的读写和管理,适用于各种嵌入式系统的开发。 ### 回答3: STM32 FileX是一个嵌入式文件系统,专为STM32系列微控制器开发的。它是一个可靠、高效、安全的文件系统,能够管理和操作嵌入式系统中的文件和文件夹。 STM32 FileX提供了许多功能,包括文件的创建、读取、写入、删除等。用户可以通过简单的API来访问这些功能,并可以根据自己的需求进行定制。 STM32 FileX能够有效地管理嵌入式系统中的存储器资源。它支持不同类型的存储介质,如RAM、Flash、SD卡等。通过使用FileX,开发人员可以轻松地在嵌入式系统中添加文件系统,从而使得数据的存储和管理更加方便。 STM32 FileX具有很高的性能和可靠性。它采用了先进的文件索引技术,能够快速地定位文件和文件夹。同时,它还具备数据保护机制,能够确保文件的完整性和安全性。 STM32 FileX是易于使用和集成的。它提供了一个直观的编程接口,使开发人员能够快速地熟悉和使用。此外,它还提供了丰富的示例代码和文档,帮助开发人员更好地理解和使用该文件系统。 总之,STM32 FileX是一个专为STM32系列微控制器开发的嵌入式文件系统。它具有高效、可靠、安全的特性,能够方便地管理和操作嵌入式系统中的文件和文件夹。无论是存储数据,还是进行软件更新和配置STM32 FileX都能够提供可靠的支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

詩不诉卿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值