请选择 进入手机版 | 继续访问电脑版

硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2664|回复: 21
收起左侧

[技术讨论] 软件框架讨论

  [复制链接]

73

主题

667

回帖

886

积分

金牌会员

积分
886
发表于 2022-4-14 22:13:44 | 显示全部楼层 |阅读模式
各位大佬有没有什么好的代码框架讨论一下。一直以来我本人都使用分层分模块的思想来写单片机代码,但是时间久了慢慢感觉还是有一些弊端。大家有什么好的框架推荐学习一下。
我个人一直使用的框架如下图所示

其中蓝色部分(SDK和硬件无关)不管裸机或者跑系统都会使用得到。裸机的时候使用黄色,跑系统的时候全部都需要。
功能模块部分分模块主要是方便维护,读起来清晰,分bsp、drv层主要是想减少耦合,这样如果换主控只需要修改bsp部分代码,换驱动IC只要接口不变可以只修改drv部分代码。

软件框架

软件框架
回复

使用道具 举报

6

主题

24

回帖

42

积分

新手上路

积分
42
发表于 2022-4-14 22:40:45 | 显示全部楼层
国产的rtthread值得了解下
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
105942
QQ
发表于 2022-4-15 01:51:06 | 显示全部楼层
CMSIS-Driver那种的驱动方式就行,简单直接高效,代码预留回调,方便OS接。

搞搞POSIX方式的,反倒麻烦。
回复

使用道具 举报

5

主题

196

回帖

211

积分

高级会员

积分
211
发表于 2022-4-15 01:52:54 | 显示全部楼层
封装不是拿文件夹对代码最归档,而是用数据结构抽象和封装资源。顶层只调用数据结构提供的接口,对底层实现不存在直接调用。
回复

使用道具 举报

73

主题

667

回帖

886

积分

金牌会员

积分
886
 楼主| 发表于 2022-4-15 09:36:18 | 显示全部楼层
eric2013 发表于 2022-4-15 01:51
CMSIS-Driver那种的驱动方式就行,简单直接高效,代码预留回调,方便OS接。

搞搞POSIX方式的,反倒麻烦 ...


CMSIS-Driver没有研究过。不过好像现在用的人挺多
回复

使用道具 举报

5

主题

179

回帖

194

积分

初级会员

积分
194
发表于 2022-4-16 14:28:56 | 显示全部楼层
弊端肯定有的,嵌入式的特点就是无法统一,有些厂家硬件驱动都有自己的特色
回复

使用道具 举报

5

主题

18

回帖

33

积分

新手上路

积分
33
发表于 2022-4-24 22:55:29 | 显示全部楼层
本来我只想造个轮子,无奈最后变成了变形金刚
回复

使用道具 举报

1

主题

17

回帖

20

积分

新手上路

积分
20
发表于 2022-4-27 09:39:31 | 显示全部楼层
我也一直想这么做,而且做了一半,感觉工作量太大了,感觉下层的驱动整理比应用层模块化工作量大得多。 image.png
回复

使用道具 举报

73

主题

667

回帖

886

积分

金牌会员

积分
886
 楼主| 发表于 2022-4-27 20:25:33 | 显示全部楼层
missyou213 发表于 2022-4-27 09:39
我也一直想这么做,而且做了一半,感觉工作量太大了,感觉下层的驱动整理比应用层模块化工作量大得多。

底层的东西不多。BSP负责初始化MCU接口,提供和MCU交互的API,DRV负责提供设备驱动,通过调用BSP的API初始化主板上面的硬件设备和提供操作这些硬件设备的API。业务层调用DRV层的API实现裸机和硬件控制
回复

使用道具 举报

1

主题

17

回帖

20

积分

新手上路

积分
20
发表于 2022-4-28 09:16:40 | 显示全部楼层
庄永 发表于 2022-4-27 20:25
底层的东西不多。BSP负责初始化MCU接口,提供和MCU交互的API,DRV负责提供设备驱动,通过调用BSP的API初 ...

如果想在不同的芯片之间较好的支持,就要考虑对芯片的比较统一的接口,对上层应用,要考虑不同的应用对下层控制或者数据处理方式不同,要提供较好的面向上层的接口,这个工作量就非常大了,要考虑常用芯片的不同特点,以及应用的不同特点,去抽象总结,还要方便以后扩展支持,感觉一两个人完成会非常恼火。
回复

使用道具 举报

1

主题

24

回帖

27

积分

新手上路

积分
27
发表于 2022-6-5 21:41:15 | 显示全部楼层
分层的话,还是有3-4层这样,再多就不合适了。而且楼主的要求很像面向对象的原理,尽量抽象一些共同特性,再留一些接口来使用。现在面向过程,面向对象,面向构件,这些思想看看也是很有启发的!!
回复

使用道具 举报

73

主题

667

回帖

886

积分

金牌会员

积分
886
 楼主| 发表于 2022-6-5 22:50:21 | 显示全部楼层
晴天一现 发表于 2022-6-5 21:41
分层的话,还是有3-4层这样,再多就不合适了。而且楼主的要求很像面向对象的原理,尽量抽象一些共同特性, ...

面向对象只是其中的一种实现方式。宏观上我想的是分层主要是尽量适应实际项目中硬件的尽可能多的迭代和优化,而不至于对软件进行大刀阔斧的修改;分模块主要是尽可能减低耦合和可移植性。但是层和模块的划分经验不足很难做出较为完善稳定的划分。
回复

使用道具 举报

19

主题

62

回帖

119

积分

初级会员

积分
119
发表于 2022-6-5 23:47:30 | 显示全部楼层
我这边的做法的进行虚拟化,目前实现的是下面几个方面的操作(很多是受rtt-hread的启发):
1.构建标准的磁盘抽象层FAL,将所有的flash全部抽象成磁盘,统一由FAL组件来管理,对上完全屏蔽flash相关信息
2.构建标准的虚拟文件系统层VFS,进行抽象,将所有的文件系统统一成类posix接口,对上层屏蔽掉文件系统的差异
3.构建标准的网络协议层SAL,屏蔽不同网络协议的差异,并支持多个协议栈混合使用,对上完全屏蔽网络协议的差异
4.构建标准的os操作层,使用cmsis_os2层对不同的os进行封装,对上屏蔽os的差异.
5.其他常规的外设按照自己的习惯进行封装,尽可能保证对接口稳定,目前基本算是稳定下来,可以做到不同mcu之间移植切换,上层代码95%左右不用调整
回复

使用道具 举报

1

主题

24

回帖

27

积分

新手上路

积分
27
发表于 2022-6-7 17:33:30 | 显示全部楼层
庄永 发表于 2022-6-5 22:50
面向对象只是其中的一种实现方式。宏观上我想的是分层主要是尽量适应实际项目中硬件的尽可能多的迭代和优 ...

我觉得硬件和软件的区别就在于有些功能就是只能又硬件提供,但是我们可以在硬件外表上套上一层软件的外壳。比如时间,可以是外部的芯片来提供也可以是MCU内部的RTC提供,但是最终还是提供的时间数据,只要把这个共性提取出来,然后给一个读写时间的接口,那无论换什么时间芯片,对应用层都毫无影响,因为软件外壳只提供了时间的数据!
回复

使用道具 举报

1

主题

24

回帖

27

积分

新手上路

积分
27
发表于 2022-6-7 18:12:22 | 显示全部楼层
mojinpan 发表于 2022-6-5 23:47
我这边的做法的进行虚拟化,目前实现的是下面几个方面的操作(很多是受rtt-hread的启发):
1.构建标准的磁盘 ...

你这个功能属性是属于非常复杂的了,连OS接口都是统一封装接口的,一般来说OS用了就很少会改,除非是需要交钱,为了减少成本才会改RTOS!
回复

使用道具 举报

19

主题

62

回帖

119

积分

初级会员

积分
119
发表于 2022-6-7 22:46:46 | 显示全部楼层
晴天一现 发表于 2022-6-7 18:12
你这个功能属性是属于非常复杂的了,连OS接口都是统一封装接口的,一般来说OS用了就很少会改,除非是需要 ...

其实没你想象的那么复杂,每一种虚拟化大概几百行代码而已,一旦虚拟化完成后,应用部分真的是不需要修改了,提供一个对flash进行抽象化的fal组件,以供参考:
fal.h
[C] 纯文本查看 复制代码
/** ****************************************************************************
* @file 	fal.h
* @author 	mojinpan
* @copyright copyright (c) 2018-20xx mojinpan. All rights reserved.
* @brief 	FAL (Flash Abstraction Layer)  Flash抽象层
* @version 	V1.3 
* @date 	2020-02-04
* 
* @par 功能说明
* @details
* 1.统一flash相关操作,为应用层操作flash提供统一接口
* 2.支持静态可配置分区表,可关联多个flash设备
* 3.支持分区访问权限和分区写入权限多用户区分设置
* 4.每个分区和用户分别拥有一个权限控制字,高16位表示写权限,低16位表示访问权限,两者相与不为0即表示拥有对应权限
* 5.访问权限为读权限,无访问权限则看不到分区,拥有写权限就自动拥访问权限
* 
* @par 移植说明 
* @details
* 1.编写接口函数read(),write()和erase()
* 2.实例化FAL_Flash结构体,并配置好参数和接口函数
* 3.建议参考fal_port部分示例进行移植
* 		
* @par 调用说明
* @details
* 1.初始化flash
* 2.FAL_Flash结构体,并配置好参数和接口函数
* 3.定义好分区配置表FAL_PART_TABLE
* 4.根据权限需求,在分区配置表中配置好权限位,并对于确定用户配置字
* 5.调用FalInit()初始化fal
*******************************************************************************/
#ifndef _FAL_H_
#define _FAL_H_

#include <stdint.h>
#include <stdio.h>
#include <string.h>
/*******************************************************************************
								Macro Definition 宏定义
*******************************************************************************/
#define FAL_SHELL_USED                      //开启FAL对shell的支持
#define FAL_SHELL_COLOR             1       //shell输出信息带颜色

#define FAL_DEV_NAME_MAX            24      //设备名称最大长度

#define FAL_OK                       0
#define FAL_PART_ERR                -1
#define FAL_PART_BUF_ERR            -2
#define FAL_PART_SIZE_ERR           -3
#define FAL_PART_NAME_ERR           -4
#define FAL_FLASH_TYPE_ERR          -5
#define FAL_FLASH_READ_ERR          -6
#define FAL_FLASH_WRITE_ERR         -7
#define FAL_FLASH_ERASE_ERR         -8
#define FAL_FLASH_READ_ONLY         -9

#define FAL_Assert(expr)        UlogAssert(expr,while(1))
#define FAL_ERR(fmt,...)        ULOG_E(fmt,##__VA_ARGS__)
#define FAL_WRNG(fmt,...)       ULOG_W(fmt,##__VA_ARGS__)
#define FAL_INFO(fmt,...)       ULOG_I(fmt,##__VA_ARGS__)
#define FAL_DBUG(fmt,...)       ULOG_D(fmt,##__VA_ARGS__)
/*******************************************************************************
								Data Type 数据类型
*******************************************************************************/
/// flash设备信息
typedef struct fal_flash
{
    void* dev;                          //设备对象 
    uint32_t addr;                      //flash设备起始地址
    size_t len;                         //fash设备长度
    size_t blk_size;                    //用于擦除最小粒度的闪存块大小
    size_t write_gran;  //最小写入颗粒度 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1)/ 64(stm32l4)
    struct
    {
        int32_t (*read)(void* dev,uint32_t addr, uint8_t *buf, size_t size);
        int32_t (*write)(void* dev,uint32_t addr, const uint8_t *buf, size_t size);
        int32_t (*erase)(void* dev,uint32_t addr, size_t size);
    } ops;
    char name[FAL_DEV_NAME_MAX];        //设备名称 
}FAL_Flash;
/// 分区信息
typedef struct 
{
    uint32_t magic_word;
    char name[FAL_DEV_NAME_MAX];        //分区名称
    FAL_Flash* flash;                   //flash设备对象
    uint32_t offset;                    //分区偏移地址
    size_t len;                         //分区大小
    uint32_t cfg;                       //权限配置
} FAL_Part;
/*******************************************************************************
							Function declaration 函数声明
*******************************************************************************/
int32_t FalInit(uint32_t cfg);
int32_t FalPartRead(const char *name,uint32_t addr, uint8_t *buf, size_t size);
int32_t FalPartWirte(const char *name,uint32_t addr,const uint8_t *buf, size_t size);
int32_t FalPartErase(const char *name,uint32_t addr, size_t size);
int32_t FalPartEraseAll(const char *name);
int32_t FalPartFindByName(FAL_Part** part,const char *name);
void FalHexDump(const char *name,uint32_t addr, uint32_t size);
void FalPartInfo(void);
//fal_port.c
int32_t FalFlashInit(FAL_Flash* fal,void *flash,uint8_t type,const char *name);

#endif /* _FAL_H_ */
/*********************************END OF FILE**********************************/

/*
//用户分区示例
#define FAL_PART_TABLE                                                                           \
{                                                                                                \
    {FAL_PART_MAGIC_WORD,        "bl",     &stm32_onchip,             0,   64*1024, 0xFFFFFFFF}, \
    {FAL_PART_MAGIC_WORD,       "app",     &stm32_onchip,       64*1024,  704*1024, 0xFFFFFFFF}, \
    {FAL_PART_MAGIC_WORD, "easyflash",     &norflash,                 0, 1024*1024, 0xFFFFFFFF}, \
    {FAL_PART_MAGIC_WORD,  "download",     &norflash,         1024*1024, 1024*1024, 0xFFFFFFFF}, \
} 
*/


fal.c
[C] 纯文本查看 复制代码
/** ****************************************************************************
* @file 	fal.c
* @author 	mojinpan
* @copyright copyright (c) 2018-20xx mojinpan. All rights reserved.
* @brief 	FAL (Flash Abstraction Layer)  Flash抽象层
* 
* @version 	V1.0 
* @date 	2020-06-17
* @details
* 1.RT-Thread中移植出fal
* 2.将log信息改用使用ulog输出
* 3.对一些宏定义的条件判断进行简化
*
* @version 	V1.1
* @date 	2020-07-22
* @details
* 1.完全重构整个组件,更进一步简化整个组件
* 2.取消flash设备表,合并到分区表中
* 3.暂时取消分区表储存在flash设备中
* 4.写操作增加最小写入颗粒和地址的对齐的判断
* 5.擦除操作增加最小擦除区域判断
* 6.增加权限配置,满足不同权限的用户对分区的可见程度的差异化配置
* 7.保留分区魔术字,后续如有需求可实现动态分区传递(主要可能是用boot和app之间交互用)
*
* @version 	V1.2
* @date 	2020-08-08
* @details
* 1.增加分区格式化的命令行模式
* 2.增加FAL_SHELL_USED 用于配置是否提供shell的支持
*
* @version 	V1.3
* @date 	2021-02-04
* @details
* 1.移除移植相关的接口函数,改为由下级驱动自行实现
* 2.将FAL_Flash中函数指针格式进行调整,改为传递void * flash,便于通用化调用
*
* @version 	V1.4
* @date 	2021-04-20
* @details
* 1.调整shell的调用命令
* 2.增加flash内容jump显示的功能,便于查看flash读写情况
*******************************************************************************/
#include <string.h>
#include "bsp.h"
#include "fal.h"
#ifdef FAL_SHELL_USED
#include "shell.h"
#endif


/*******************************************************************************
									Macro Definition 宏定义
*******************************************************************************/
//分区魔术字
#define FAL_PART_MAGIC_WORD         0x45503130
#define FAL_PART_MAGIC_WORD_H       0x4550L
#define FAL_PART_MAGIC_WORD_L       0x3130L
//flash jump格式
#if FAL_SHELL_COLOR == 1
#define flashPrintHead CSI(31) "    Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" CSI(39)
#define flashPrintAddr CSI(31)"0x%08x: "CSI(39)
#else
#define flashPrintHead "    Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"
#define flashPrintAddr "0x%08x: "
#endif
/*******************************************************************************
								Global Variables 全局变量
*******************************************************************************/
FAL_Part falPartLoadTab[] = FAL_PART_TABLE;
const uint32_t falPartLoadLen =  sizeof(falPartLoadTab)/sizeof(FAL_Part);

FAL_Part *falPartTab[sizeof(falPartLoadTab)/sizeof(FAL_Part)];
uint32_t falPartLen = 0;

uint32_t userCfg = 0;
/** ****************************************************************************
* @brief FAL初始化
* @param cfg 用户权限配置,高16位表示写权限,低16位表示访问权限,和分区权限配置向与不为零即表示拥有改权限
* @note 每个分区在高位和低位各使用一个bit表示写权限和访问权限,这样可以比较方便推导出用户权限字
* @note 访问权限为读权限,无访问权限则看不到分区,拥有写权限就自动拥访问权限
*******************************************************************************/
int32_t FalInit(uint32_t cfg)
{
    uint32_t i;
    userCfg = cfg;  //保存用户权限
    falPartLen = 0;

    //根据用户权限导出分区信息 
    for(i=0;i<falPartLoadLen;i++)
    {
        if((falPartLoadTab[i].cfg & userCfg) !=0)
        {
          falPartTab[falPartLen++]  = &falPartLoadTab[i];
        }
    }
#ifdef FAL_INFO_MODE
    if(falPartLen > 0)
    {
        FalPartInfo();
        FAL_INFO("FAL (Flash Abstraction Layer) init success!"); 
        return FAL_OK;   
    }
#endif
    return FAL_PART_ERR;
}
/** ****************************************************************************
* @brief 通过分区名称查找分区信息
* @param part 分区信息结构体
* @name 分区名称
* @return 操作结果
*******************************************************************************/
int32_t FalPartFindByName(FAL_Part** part,const char *name)
{
    uint32_t i;
         
    if(name == NULL)
    {
        FAL_ERR("partition name is empty!");
        return FAL_PART_NAME_ERR;
    }

    for (i = 0; i < falPartLen; i++)
    {
        if (!strncmp(name, falPartTab[i]->name, FAL_DEV_NAME_MAX)) 
        {
            *part = falPartTab[i];
            return FAL_OK;
        }
    }

    FAL_ERR("Cannot find partition by name %s!",name);
    return FAL_PART_NAME_ERR;
}
/** ****************************************************************************
* @brief 擦除数据
* @param name 分区名称
* @param addr 地址
* @param size 大小
* @return 操作结果
*******************************************************************************/
int32_t FalPartErase(const char *name,uint32_t addr, size_t size)
{
    int ret = 0;

    FAL_Part* part;
    if(FalPartFindByName(&part,name)!=FAL_OK)
    {
        return FAL_PART_NAME_ERR;
    }
    if((part->cfg & 0xFFFF0000 & userCfg) == 0)
    {
       FAL_ERR("Partition read only!");
       return FAL_FLASH_READ_ONLY;
    }

    if ( (addr + size) > (part->len))
    {
        FAL_ERR("Partition erase error! Partition erase size (0x%x) out of bound.",(addr + size));
        return FAL_PART_SIZE_ERR;
    }

    ret = part->flash->ops.erase(part->flash->dev,part->offset + addr, size);
    if (ret < 0)
    {
        FAL_ERR("Partition erase error! Flash device(%s) erase error!", part->flash->name);
        return ret;
    }
    return FAL_OK;
}
/** ****************************************************************************
* @brief 擦除整个分区
* @param name 分区名称
* @return 操作结果
*******************************************************************************/
int32_t FalPartEraseAll(const char *name)
{   
    FAL_Part* part;
    
    if(FalPartFindByName(&part,name)!=FAL_OK)
    {
        return FAL_PART_NAME_ERR;
    }

    if((part->cfg & 0xFFFF0000 & userCfg) == 0)
    {
       FAL_ERR("%s Partition read only!",name);
       return FAL_FLASH_READ_ONLY;
    }   
    return FalPartErase(name, 0, part->len);
}

/** ****************************************************************************
* @brief 读取数据
* @param name 分区名称
* @param addr 地址
* @param buf 数据指针
* @param size 大小
* @return 操作结果
*******************************************************************************/
int32_t FalPartRead(const char *name,uint32_t addr, uint8_t *buf, size_t size)
{
    int ret = 0;

    FAL_Part* part;

    if(FalPartFindByName(&part,name)!=FAL_OK)
    {
        return FAL_PART_NAME_ERR;
    }

    if(buf == NULL){
        FAL_ERR("Partition read buf error!");
        return FAL_PART_ERR;
    }   

    if (addr + size > part->len)
    {
        FAL_ERR("Partition read error! Partition address 0x%x out of bound.",addr + size);
        return FAL_PART_SIZE_ERR;
    }

    ret = part->flash->ops.read(part->flash->dev,part->offset + addr, buf, size);
    if (ret < 0)
    {
        FAL_ERR("Partition read error! Flash device(%s) read error!", part->flash->name);
    }

    return ret;
}

/** ****************************************************************************
* @brief 写数据
* @param name 分区名称
* @param addr 地址
* @param buf 数据指针
* @param size 大小
* @return 操作结果
*******************************************************************************/
int32_t FalPartWirte(const char *name,uint32_t addr,const uint8_t *buf, size_t size)
{
    int ret = 0;

    FAL_Part* part;

    if(FalPartFindByName(&part,name)!=FAL_OK)
    {
        return FAL_PART_NAME_ERR;
    }

    if((part->cfg & 0xFFFF0000 & userCfg) == 0)
    {
       FAL_ERR("Partition read only!");
       return FAL_FLASH_READ_ONLY;
    }

    if(buf == NULL){
        FAL_ERR("Partition Write buf error!");
        return FAL_PART_ERR;
    }   

    if (addr + size > part->len)
    {
        FAL_ERR("Partition write error! Partition address out of bound.");
        return FAL_PART_SIZE_ERR;
    }

    if (size < part->flash->write_gran)
    {
        FAL_ERR("Partition write error! Write size must be greater than %d",part->flash->write_gran);
        return FAL_PART_SIZE_ERR;
    }

    if (addr % part->flash->write_gran != 0)
    {
        FAL_ERR("Partition write error! The address must be %d-byte aligned",part->flash->write_gran);
        return FAL_PART_SIZE_ERR;
    }

    ret = part->flash->ops.write(part->flash->dev,part->offset + addr, buf, size);
    if (ret < 0)
    {
        FAL_ERR("Partition write error! Flash device(%s) write error!", part->flash->name);
    }

    return ret;
}
/** ****************************************************************************
* @brief 16进制输出
* @param name 分区名称
* @param addr 内存基址
* @param len 长度
*******************************************************************************/
void FalHexDump(const char *name,uint32_t addr, uint32_t size)
{
    char data;
    char buf[100];
    uint8_t *address;
    uint32_t len = size;
    uint32_t printLen = 0;

    if (size == 0)return;

    printf("memory of 0x%08x, size: %d:\r\n", addr, size);
    
    address = (uint8_t *)(addr & (~0x0000000F));
    size += addr - (uint32_t)address;
    size = (size + 15) & (~0x0000000F);

    printf(flashPrintHead"\r\n");

    while (size)
    {
        printLen += sprintf(buf + printLen, flashPrintAddr, (uint32_t)address);
        for (int i = 0; i < 16; i++)
        {
            if ((uint32_t)(address + i) < addr
                || (uint32_t)(address + i) >= addr + len)
            {
                buf[printLen ++] = ' ';
                buf[printLen ++] = ' ';
                buf[printLen ++] = ' ';
            }
            else
            {
                FalPartRead(name,(uint32_t)(address + i),(uint8_t*)&data,1);
                printLen += sprintf(buf + printLen, "%02x ", data);
            }
        }
        buf[printLen ++] = '|';
        buf[printLen ++] = ' ';
        for (int i = 0; i < 16; i++)
        {
            if ((uint32_t)(address + i) < addr
                || (uint32_t)(address + i) >= addr + len)
            {
                buf[printLen ++] = ' ';
            }
            else
            {
                FalPartRead(name,(uint32_t)(address + i),(uint8_t*)&data,1);
                if (data >= 32 && data<= 126)
                {
                    printLen += sprintf(buf + printLen, "%c", data);
                }
                else
                {
                    buf[printLen ++] = '.';
                }
            }
        }
        buf[printLen ++] = '|';
        buf[printLen ++] = '\r';
        buf[printLen ++] = '\n';
        printf("%*s",printLen,buf);
        address += 16;
        size -= 16;
        printLen = 0;
    }
}
/** ****************************************************************************
* @brief 分区信息显示
*******************************************************************************/
void FalPartInfo(void)
{
    char *item1 = "name", *item2 = "flash_dev";
    size_t i, part_name_max = strlen(item1), flash_dev_name_max = strlen(item2);
    FAL_Part *part;
    bool write_en;

    if (falPartLen)
    {
        for (i = 0; i < falPartLen; i++)
        {
            part = falPartTab[i];
            if (strlen(part->name) > part_name_max)
            {
                part_name_max = strlen(part->name);
            }
            if (strlen(part->flash->name) > flash_dev_name_max)
            {
                flash_dev_name_max = strlen(part->flash->name);
            }
        }
    }
    printf("==================== FAL partition table ====================\r\n");
    printf("| %-*.*s | %-*.*s |   offset   |    len  |   R/W\r\n", part_name_max, FAL_DEV_NAME_MAX, item1, flash_dev_name_max,
            FAL_DEV_NAME_MAX, item2);
    printf("-------------------------------------------------------------\r\n");
    for (i = 0; i < falPartLen; i++)
    {
        write_en =  (falPartTab[i]->cfg & 0xFFFF0000 & userCfg) == 0 ? false : true;
        printf("| %-*.*s | %-*.*s | 0x%08x | 0x%08x |   %s\r\n", 
            part_name_max, FAL_DEV_NAME_MAX, falPartTab[i]->name, 
            flash_dev_name_max,FAL_DEV_NAME_MAX, falPartTab[i]->flash->name, 
            falPartTab[i]->offset,falPartTab[i]->len,write_en ? "R/W":"R");
    }
    printf("=============================================================\r\n");
}
#ifdef FAL_SHELL_USED
/*******************************************************************************
* @brief FAL对shell的支持
*******************************************************************************/
void FalShell(uint32_t argc, void* argv[])
{
    uint8_t data;
    uint32_t addr;
    uint32_t len;
    char* part;
    Shell *shell;

    if(argc == 1)
    {//显示所有分区信息
        FalPartInfo();
        return;
    }
    else if(argc == 2 && !strcmp("-help",(char*)argv[1]))
    {
        //轮空,直接执行最后的显示信息
    }
    else if(argc == 3 && !strcmp("format",(char*)argv[1]))
    {//格式化分区
        printf("Format partition %s now? (Y/N) \r\n",(const char*)argv[2]);
        data = getchar();
        if(data == 'Y'|| data == 'y')
        {
            printf("Formatting ...... \r\n");
            if(FalPartEraseAll((const char*)argv[2])==FAL_OK)
            {
                printf("Format successful!\r\n");
            }
            else
            {
                printf("Format failed!\r\n");
            }
        }  
        return;
    }
    else if(argc == 5 && !strcmp("jump",(char*)argv[1]))
    {//格式化分区
        part = ((char*)argv[2]);
        addr = shellParsePara(argv[3]);
        len  = shellParsePara(argv[4]);
        FalHexDump(part,addr,len);
        return;
    }
    //无法识别指令时提示用户按要求输入指令
    printf("Fal command format : fal [OPTION] [part] [addr] [len]\r\n");
    printf("Fal print  : fal\r\n");
    printf("Fal format : fal format part \r\n");
    printf("Fal jump   : fal jump part addr len\r\n");
}
SHELL_EXPORT_CMD(fal, FalShell, use -help get more info);
#endif
/*********************************END OF FILE**********************************/

回复

使用道具 举报

73

主题

667

回帖

886

积分

金牌会员

积分
886
 楼主| 发表于 2022-6-7 22:49:54 | 显示全部楼层
mojinpan 发表于 2022-6-5 23:47
我这边的做法的进行虚拟化,目前实现的是下面几个方面的操作(很多是受rtt-hread的启发):
1.构建标准的磁盘 ...

RTT的这种好是挺好,但是POSIX挺麻烦的。
回复

使用道具 举报

19

主题

62

回帖

119

积分

初级会员

积分
119
发表于 2022-6-7 22:56:36 | 显示全部楼层
庄永 发表于 2022-6-7 22:49
RTT的这种好是挺好,但是POSIX挺麻烦的。

POSIX的实现也不算麻烦,只是看着没有常规实现那么高效,我按POSIX实现主要是为了RTOS上的程序和linux上的程序能比较方便的迁移
回复

使用道具 举报

1

主题

24

回帖

27

积分

新手上路

积分
27
发表于 2022-6-14 19:08:54 | 显示全部楼层
mojinpan 发表于 2022-6-7 22:46
其实没你想象的那么复杂,每一种虚拟化大概几百行代码而已,一旦虚拟化完成后,应用部分真的是不需要修改了, ...

这种抽象层就说我说的那种,只不过我没写过RTT所以不清楚RTT也是这样的接口!
回复

使用道具 举报

18

主题

228

回帖

282

积分

高级会员

积分
282
发表于 2022-6-15 15:13:41 | 显示全部楼层
do the right thing. 太过纠结这个心累,合适就行,没有什么一劳永逸的
回复

使用道具 举报

41

主题

214

回帖

337

积分

高级会员

积分
337
发表于 2022-6-15 17:52:46 | 显示全部楼层
周立功ametal,cmisis也可以呀。不要自己写。
回复

使用道具 举报

1

主题

19

回帖

22

积分

新手上路

积分
22
发表于 2022-7-6 23:54:37 | 显示全部楼层
留个记号 学习
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-3-29 21:20 , Processed in 0.267566 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表