SoC嵌入式软件架构设计之七:嵌入式文件系统设计

最后更新于:2022-04-01 07:01:44

嵌入式的系统区(system disk,SD)包括操作系统、驱动、中间件、应用和字库、UI资源等文件,本文讲述SD区的文件系统设计。文件系统最主要的目标是为了实现单个文件的定位和读写。因为一般代码都是不可自修改的,即量产之后不会有写操作,嵌入式系统的SD文件系统就是为了能够简单、高效地定位某个文件和读取文件中的数据。设计原则和要点有以下几方面: 1\. 逻辑连续存储单个文件,以扇区对齐。 SD区的单个代码和资源文件一般都不大,所以不必要像fat32文件系统那样用fat表把文件簇串起来,直接逻辑连续地存储起来即可,这样定位也会更加简单快速,当然文件应该以扇区来对齐,方便读取,文件偏移信息也能用扇区数来记录。   2\. SD头 这是对整个SD区属性的描述,包括校验码、版本号、日期、OEM厂商等等。有时为了保证知识产权,还会加上一些防止拷贝的加密ID信息。 3\. DIR节 DIR节就是目录信息,即每个文件在SD区中的定位信息,是SD文件系统最重要的数据结构,文件的定位就是依赖于目录信息进行。打包工具会按一定的顺序将各个文件打包,并相应按顺序产生每个文件对应的目录信息。每个文件的目录数据结构如下: 1)文件名,一般是8+3格式 2)文件属性,区分系统文件和应用文件、隐藏文件等 3)文件在SD区中的偏移量,以扇区为单位 4)文件大小,字节为单位 5)校验码 4\. 文件数据 DIR节之后就是一个个真实的代码和资源和配置等文件。 5\. fopen 打开文件即根据文件名在DIR节中匹配,匹配成功即可获得文件在SD中的偏移量,将这偏移量右移9位(即512字节,一个扇区)即是文件的位置。fopen返回的是一个句柄,该句柄对应一个数据结构,结构一般包括:文件的起始位置、长度、当前读指针位置等。记录起始位置和长度是为了防止越界读取。 6\. fread 根据句柄的当前读指针进行读取,读后要修改当前读指针。 7\. fseek 根据模式来直接修改读指针。 需要清除的是:SD区是一个逻辑区,其只是固件的一部分。一个固件会包括引导区、SD区、VM区、特定功能区(如VM),之后才是数据区,这个数据区就会部署fat32或者exfat等标准文件系统。下一节再继续讲解固件分布设计。 更多嵌入式和物联网原创技术分享敬请关注微信公众号:嵌入式企鹅圈 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-13_5695f8f8d24b2.jpg)
';

SoC嵌入式软件架构设计之六:API设计方法

最后更新于:2022-04-01 07:01:42

在嵌入式系统中,驱动都是以API的方式提供给应用进行调用。这里介绍嵌入式系统的API设计和管理方法。 驱动在系统中会按模块进行分类,例如按键驱动、LCD驱动、文件系统、card驱动、I2C驱动等等;每个模块又有多个接口,例如LCD驱动有光标定位、画点、画直线等,而文件系统有fread、fwrite、fseek、fopen等接口。以下举例将以文件系统的fopen为例,工具链为mips。 **一、API设计方法** 1\. 驱动接口声明:extern FILE * fopen(const char * path,const char * mode),位于fs.h中 2\. 驱动接口定义:FILE * open(const char * path,const char * mode){...},位于fs.c中 3\. 驱动接口API: fopen :li  v1,FILE_OPEN;                                                   syscall;  位于api.S中,是汇编代码。 4\. 驱动接口函数指针数组:struct file_operations fs_fops {                                                       open,read,write,seek}; 5\. 文件系统被加载时,会将文件系统的接口函数指针数组fops注册到系统的API管理数组中。 6\. 系统对驱动进行分类管理,其有一个记录各个驱动接口函数指针数组基址的数组,各个驱动事先按顺序进行约定,如数组的第一个元素就是按键驱动的key_fops,而第二个就是LCD驱动的lcd_fops,以此类推。某个驱动被加载时,驱动会把对应的fops通过API管理的接口记录到该数组的对应位置。 这个约定一般会在api.h中,如#define KEY 0 //表示key驱动是约定在数组的第一个位置,  #define FS 2//表示FS是约定在数组的第三个位置 7\. FILE_OPEN定义:#define FILE_OPEN (FS 8\. 应用调用时,path和mode等形参会压入栈,然后进入fopen的API,其将FILE_OPEN常量赋值给v1,通过syscall陷入到异常,进行内核态,这时即可以进入到API管理中,API根据FILE_OPEN提供的两部分信息可以迅速找到open的地址,异常返回时即跳到open的地址执行,此即进行实际的接口调用。整个过程完成。 请关注本人原创的嵌入式架构设计专栏:[SoC嵌入式软件架构设计](http://blog.csdn.net/column/details/fw-arch-design.html),谢谢! 更多嵌入式和物联网原创技术分享敬请关注微信公众号:嵌入式企鹅圈 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-13_5695f8f8d24b2.jpg)
';

SoC嵌入式软件架构设计之五:可执行程序的重构

最后更新于:2022-04-01 07:01:40

低端控制器对执行效率要求很高,成本敏感,因而SoC内置SRAM是紧缺资源。代码分块管理就是为了充分利用内存,提高内存的复用效率而提出的一种设计方法。代码分块管理不仅涉及到硬件,同样对操作系统和应用、驱动的设计都有要求,这些模块共同努力以使执行效率达到最高。 本节讲述代码分块(Bank)管理思想下可执行文件的重构,即对程序编译后的可执行文件进行重新组织、打包,以在加载阶段获得最高的执行效率,减少内存占用。要使执行效率高,意味着可执行文件的格式尽可能简单,解析执行文件的流程简单,相应地,解析过程代码量少,即能够减少内存的占用。 keil产生的Hex或者Bin,其实也是keil对axf调试文件进行抽取,重新打包生成。Hex和Bin可以通过烧写器下载到flash。GCC工具链会生成可执行格式ELF,也可以离线对ELF格式内容进行抽取,重新打包生产Hex格式,并烧写到flash中。本次讲述的是可执行文件存储在外存储设备(card,nand flash,硬盘)中,在运行前由操作系统将其加载到内存再执行这种情况。 要对工具链生成的可执行文件(如ELF)进行重构,自然需要熟悉该执行文件的格式,如ELF,里面会包括文件头,SECTION节,符号段,代码段,数据段,还有调试信息等等。而程序的运行往往只需要其中较少的段信息。可执行文件就是要得到必要的段的信息和数据,将不必要的通通删除,并且根据代码分块管理的特点进行自定义格式的编制。这里不再对ELF等标准执行文件进行分析(以后可能另写文章),只描述重构后的目标格式,看看什么段信息和数据是操作系统必要要知道和获取的。 1\. 文件头             1)格式标识符,如应用,驱动等             2)版本号             3)常驻代码段在文件中偏移             4)常驻代码长度             5)常驻代码段在内存中的起始地址                         6)常驻数据(.DATA)段在文件中偏移             7)常驻数据(.DATA)长度             8)常驻数据段(.DATA)在内存中的起始地址             9).bss段长度             10).bss段在内存中的起始地址             11)程序入口地址ENTRY:第一行代码的地址,不是main哦,是运行时库的一行代码地址             12)reserved,对齐到扇区或者1024字节。如果是驱动类型,则会增加两个字段:驱动入口地址和驱动退出地址。              2\. 代码块头              1)第一个Bank组的头,按顺序是第一个Bank的块信息、第二个Bank的块信息、。。。第N个Bank的块信息。一个Bank组最大含有N个Bank,不够的填0.              2)第二个Bank组的头,按顺序是第一个Bank的块信息、第二个Bank的块信息、。。。第N个Bank的块信息。一个Bank组最大含有N个Bank,不够的填0.              .....              有几个Bank组由文件头的格式标识符来判定,由架构师事先约定。              每个Bank块的块信息包括:bank块数据(代码和数据)在文件中的偏移,Bank长度,BAnk对应的内存地址。 3.常驻代码段数据,对齐扇区 4.常驻数据段数据,对齐扇区 5.第一组Bank的数据,对齐扇区,只记录真实的Bank数据,一个Bank组不够N个bank时不需补0. 6. 第二组Bank的数据,对齐扇区,只记录真实的Bank数据,一个Bank组不够N个bank时不需补0. 7\. 最后一个组的Bank数据。 加载时解析该文件头,获得常驻代码段和数据段的信息,将两者加载到内存,对Bss段清0,然后读取到程序的ENTRY入口,跳到该地址执行即可,简单高效! Bank切换时,根据Bank组号和Bank号即快速定位到Bank的段信息地址,读出该Bank在文件中的偏移和Bank长度,进而读取并加载到复用的内存空间。     请关注SoC嵌入式软件架构设计(控制器SoC固件架构)系列博文: [SoC嵌入式软件架构设计之一:系统内存需求评估 ](http://blog.csdn.net/yueqian_scut/article/details/24602941) [SoC嵌入式软件架构设计之二:没有MMU的CPU实现虚拟内存管理的设计方法](http://blog.csdn.net/yueqian_scut/article/details/24816757) [SoC嵌入式软件架构设计之三:代码分块(Bank)设计原则](http://blog.csdn.net/yueqian_scut/article/details/24911021) [SoC嵌入式软件架构设计之四:内存空间规划分配](http://blog.csdn.net/yueqian_scut/article/details/24910877) [SoC嵌入式软件架构设计之五:可执行程序的重构](http://blog.csdn.net/yueqian_scut/article/details/24910951) [嵌入式:节省内存的软件设计技巧](http://blog.csdn.net/yueqian_scut/article/details/22522821) 更多嵌入式和物联网原创技术分享敬请关注微信公众号:嵌入式企鹅圈 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-13_5695f8f8d24b2.jpg)
';

SoC嵌入式软件架构设计之四:内存空间规划分配

最后更新于:2022-04-01 07:01:38

本文继续阐述基于低端控制器CPU的SoC固件架构设计。第一节 [SoC嵌入式软件架构设计之一:系统内存需求评估](http://blog.csdn.net/yueqian_scut/article/details/24602941) 讲述了系统内存需求的评估。这一节讲述内存空间的具体规划分配。CPU有两种体系结构:哈佛结构和冯诺依曼结构。哈佛结构是一种将程序指令存储和数据存储分开的存储器结构,如80251,代码空间与数据空间完全分开,独立编址;冯诺依曼结构是一种将程序指令存储器和数据存储器合并在一起的存储器结构,如MIPS,ARM等,其代码和数据空间是统一编址。这里就以冯诺依曼体系结构为例。  **一、嵌入式系统软件分层** 系统软件层次包括:启动、驱动、操作系统、文件系统、libc、中间件、应用框架、应用等层次。 1)驱动、文件系统和操作系统的时间管理、中断管理等接口一般都是通过API来进行调用; 2)libc和中间件、应用框架在系统中的处理可能以API的形式进行调用,也可以直接作为静态库与应用直接进行链接。 3)libc和中间件、应用框架作为静态库时,会减少API的占用空间(API往往是常驻空间,没理由调用API时还要从外存储中将API的代码加载到内存,这样效率太低),省去API层也可以提高调用速度,但会增加库函数的代码空间。如果库函数链接时可以运行在Bank内存中,由于Bank内存可以复用,增加的代码空间可以忽略,从这一点来看其又是一个优点。如判断某个文件是哪种解码格式时,其可以作为中间件来实现,并链接到应用的Bank空间,因为这是音乐解码前的预处理,可以和解码时刻的控制流复用同一块Bank空间。 4)libc和中间件、应用框架以API形式来调用时,会产生API的常驻内存空间需求,在内存中也只存在一份真正的代码,供所有模块共同调用,而且应用开发者无需关心接口实现,也不允许开发者去修改。 各个模块应根据实际情况来决定其供上层调用的形式。 代码分页(块,Bank)设计请参考:[ SoC嵌入式软件架构设计之二:没有MMU的CPU实现虚拟内存管理的设计方法](http://blog.csdn.net/yueqian_scut/article/details/24816757) 和 [SoC嵌入式软件架构设计之三:代码分块(Bank)设计原则](http://blog.csdn.net/yueqian_scut/article/details/24911021)。 **二、程序段组成** 这里程序段是指可执行文件中出现的段名,如.CODE、.DATA、.BSS等默认段名和其他自定义的段名。GNU工具链,各种编译输出段名称是可以在链接脚本中指定的,当然在编写代码时也可以指定函数或者代码的编译输出段名称,如在定义一个数据变量时添加一个属性__attribute__((section("bank_data")))时,该数据变量将会被重定位在bank_data段。下图是具有Bank代码段的程序与可执行文件段名的对应关系图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-13_5695fa713c6d8.jpg) **三、SoC内置内存规划** 一般地,如果SOC中内置SRAM超过32K,数字工程师也会将内置内存进行分块,一是为了减少电路延时,二是为了让内存得到更有效率的利用。如某块内存在某个时刻是作为代码使用,有时也可能作为数据使用(如果是哈佛结构,那就要切换内存的选址译码电路,从代码空间转到数据空间),有时也可能用作特别的解码buffer使用,而有些解码的缓存是以24bit作为单位,如果所有内存都作为一块来设计,显然是满足不了这样的需求的。下图是常见的SRAM示意图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-13_5695fa71594ba.jpg) **四、程序内存空间分配** 根据软件分层和程序段综合考虑,一般在物理内存的基础上先进行分层划分内存区域,再进行各层程序的段内存划分。有以下原则: 1)各层的常驻段(代码和数据)应该紧凑分配,而各层的Bank空间与常驻空间分块,也应该紧凑分配。 2)Bank空间的起始地址应该与扇区单位对齐,可取得最好的加载代码性能。 3)先把常见的场景的内存分配好,再考虑特殊场景的需求,看看特殊场景能否复用普通场景的内存空间。 4)buffer的划分也要考虑场景的复用,否则太浪费。如解码的buffer可以在未解码的时候用作预处理时的媒体文件有效性判断的buffer。 5)有时两组Bank空间可以合并起来当作另一个场景的一组Bank空间来使用。如解码时的软件分层比较多,涉及到应用中间件和算法中间件,而文件浏览应用则没有这么多层次,可以将两个中间件的Bank合并起来当一组Bank来使用。 6)一个模块的代码不应该跨越两个物理内存块,否则访问性能会降低。 7)尽可能提高内存利用率,避免内存碎片。 8)内存分配的细节要以公共链接文件出现,并用有意义的名称来定义各段的起始地址和长度,除架构设计师外,其他人不允许修改该文件。 下图是一个系统的局部分配,程序内存空间分配大致如此:Rcode是常驻段,Bank是复用内存的代码块。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-13_5695fa717beec.jpg) 请关注SoC嵌入式软件架构设计(控制器SoC固件架构)系列博文: [SoC嵌入式软件架构设计之一:系统内存需求评估 ](http://blog.csdn.net/yueqian_scut/article/details/24602941) [SoC嵌入式软件架构设计之二:没有MMU的CPU实现虚拟内存管理的设计方法](http://blog.csdn.net/yueqian_scut/article/details/24816757) [SoC嵌入式软件架构设计之三:代码分块(Bank)设计原则](http://blog.csdn.net/yueqian_scut/article/details/24911021) [SoC嵌入式软件架构设计之四:内存空间规划分配](http://blog.csdn.net/yueqian_scut/article/details/24910877) [SoC嵌入式软件架构设计之五:可执行程序的重构](http://blog.csdn.net/yueqian_scut/article/details/24910951) [嵌入式:节省内存的软件设计技巧](http://blog.csdn.net/yueqian_scut/article/details/22522821) 更多嵌入式和物联网原创技术分享敬请关注微信公众号:嵌入式企鹅圈 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-13_5695f8f8d24b2.jpg)
';

SoC嵌入式软件架构设计之三:代码分块(Bank)设计原则

最后更新于:2022-04-01 07:01:35

上一节讲述了在没有MMU的CPU(如80251、MIPS M控制器系列、ARM cortex m系列)上实现虚拟内存管理的集成硬件设计方法,新设计的内存管理管理单元要实现虚拟内存管理还需要操作系统、代码分块(Bank)的支持,详见[SoC嵌入式软件架构设计之二:没有MMU的CPU实现虚拟内存管理的设计方法](http://blog.csdn.net/yueqian_scut/article/details/24816757)。这里要阐述Bank设计的一些原则。 Bank设计是为了实现不同时刻运行的Bank(代码块)运行在同一块内存上,所以在运行之前操作系统需要将已存在内存的代码/数据进行缓存处理,并加载将要运行的Bank到该内存上。为了实现这个目的,需要明确以下要点: 1.为了提高效率,我们认为代码是不会自修改的,即代码是只读的,则在Bank切换的时候可以直接将已经存在内存的Bank代码丢弃。我们只需要将当前已经存在内存的Bank代码的Bank号入栈即可,新加载的代码可以直接覆盖该块内存。不同的Bank有不同的虚拟地址,为什么可以放到同样的物理内存?其实是新设计的内存管理单元的电路决定的。参考前一节的文章([SoC嵌入式软件架构设计之二:没有MMU的CPU实现虚拟内存管理的设计方法](http://blog.csdn.net/yueqian_scut/article/details/24816757))介绍,关键是同一个Bank组的不同虚拟地址信号对应的物理输出信号是一样的。 2.程序调用后返回到一个Bank的某一行时同样需要加载该Bank代码,这时操作系统会将之前的Bank号出栈,并根据Bank号将对应的代码加载到该块内存。从1和2来看,调用Bank代码和返回一个Bank设计到Bank号的入栈和出栈,如果设计的Bank代码中的函数的虚拟运行地址带有明确的Bank号信息,那函数的调用和返回就是一个入栈和出栈过程,这样操作系统可以减少出入栈的工作,代码运行也更顺畅。 3.Bank代码中的变量数据处理: 1)全局变量。如果全局变量定义在公共区域,那Bank代码切换过程中不需对其进行处理。如果全局变量定义在Bank内存区域,则Bank切换时需要对这部分全局变量进行缓存处理。即在Bank号入栈之后,将Bank中的数据存到堆中,在Bank返回时除了从外存储设备加载对应的代码时,还要将其对应的数据从堆中恢复到Bank内存。为了加快数据的恢复,往往默认一个Bank数据空间的最大值,这样就不需要记录每个Bank的数据空间的大小。 2)静态变量。跟全局变量一样。 3)常量段。其是只读,跟代码一块处理。 4)局部变量。局部变量是在栈中分配空间的,所以不需要进行缓存。 5)buffer。假如该Buffer只是某个Bank调用,而该Bank除了代码还有剩余空间大于buffer大小,那将buffer设置在代码段之后,并定义一个指针局部变量,程序中直接指向该buffer的首地址。 如果我们将Bank内的全局变量全部转为局部变量,那操作系统就不需要对数据进行缓存管理,就不需要堆空间。但是局部变量对应的栈空间就加大了。一个Bank可能有多个函数,而多个函数是可能会用到同样的全局变量的。但这种情况需要的全局变量往往不大,可以考虑都转为局部变量。如果不需要进行数据缓存,那系统管理将会非常简单。 4.中断处理不能进行Bank切换。Bank切换需要进行读写外存储设备,会造成很大的延时,所以在中断里面不应该产生Bank切换。 5.操作系统、驱动、应用各层次频繁调用的代码应设置为常驻代码,如果发生切换会损失效率。如果频繁调用的代码很固定,如操作系统的调度管理等代码可以固化到ROM中,以减少成本。 6.Bank内存分块大小要适中,在保持切换性能的基础上选择较小的内存块。Bank块设置过小,就会导致Bank切换频繁,损失效率,Bank设置过大会造成内存浪费。 7.Bank内存的起始地址应该对齐扇区(512字节),这样读外存储设备能够达到最好的性能。 请关注SoC嵌入式软件架构设计(控制器SoC固件架构)系列博文: [SoC嵌入式软件架构设计之一:系统内存需求评估 ](http://blog.csdn.net/yueqian_scut/article/details/24602941) [SoC嵌入式软件架构设计之二:没有MMU的CPU实现虚拟内存管理的设计方法](http://blog.csdn.net/yueqian_scut/article/details/24816757) [SoC嵌入式软件架构设计之三:代码分块(Bank)设计原则](http://blog.csdn.net/yueqian_scut/article/details/24911021) [SoC嵌入式软件架构设计之四:内存空间规划分配](http://blog.csdn.net/yueqian_scut/article/details/24910877) [SoC嵌入式软件架构设计之五:可执行程序的重构](http://blog.csdn.net/yueqian_scut/article/details/24910951) [嵌入式:节省内存的软件设计技巧](http://blog.csdn.net/yueqian_scut/article/details/22522821) 更多嵌入式和物联网原创技术分享敬请关注微信公众号:嵌入式企鹅圈 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-13_5695f8f8d24b2.jpg)
';

SoC嵌入式软件架构设计之一:系统内存需求评估

最后更新于:2022-04-01 07:01:33

内存是SoC(System on Chip,片上系统)集成设计的重要模块,是SoC中成本比重较大的部分。内存管理的软硬件设计是SoC软件架构设计的重要一环,架构设计师必须要在成本和效率中取得平衡,做到在节省内存的同时保证整个系统的性能。系统内存需求评估是对嵌入式软件架构师的最基本要求,同时也是其最重要的技能之一。一般在SoC项目立项的时候,架构师就要完成系统内存需求评估。 下面以一个多媒体电子解决方案中的SoC设计为原型,说明大致的评估流程: 1\. 根据产品规格,对各个应用场景进行功能和性能分解 产品规格一般会描述应用功能场景和性能。架构师要对各个场景进行功能和性能分解,分析各个场景在内存使用上的关系。包括: 1)列出所有的应用场景,明确各个应用的生命周期,在什么时候开始,什么时候结束。 2)系统是否要同时支持多个应用(多进程),例如听歌曲的时候要浏览图片,这意味中两个应用是同时利用内存,不能进行应用内存分时复用; 3)系统是否要同时支持多种介质,例如同时访问卡设备和闪存设备,一般在单进程时都只是访问单种存储设备,除非是实现数据复制,但在多进程的时候,不同的进程访问不同的存储设备也很正常,同时访问不同的存储设备意味着两种驱动是同时使用内存。 4)系统是否要同时支持多种文件系统。不同的存储设备可能部署不同的文件系统,其同样存在2)中的问题。 5)明确系统支持的编解码格式,其表现为算法内存需求。不同的编解码格式对内存的要求不同的,同样的算法时,不同的速率也导致不同的内存需求。 6)系统性能要求,例如LCD刷屏,有大块framebuffer自然会有更好的性能 2.对系统软件进行分层,明确每一层模块的组成      1)系统分启动、驱动、操作系统、文件系统、中间件(算法、UI)、应用框架、应用等层次,一般的消费类电子产品,如多媒体设备、游戏机等产品系统都会分成多个层次。每个层次又会有多个模块组成,如驱动分字符设备驱动和块设备驱动,一般按键属于字符设备,存储设备一般属于块设备;存储设备里可能支持nand flash、SD-MMC card、Uhost等;文件系统又有FAT32、exfat等等;应用层当然会包括很多个应用程序。 2)明确每个应用实现所需要的软件层次。有些应用可能要很多层,如音乐,从应用到应用框架(UI+按键)、API、中间件(解码)、操作系统、驱动等层次,而设置应用是不需要解码中间件的。 3\. 明确每个软件层次中内存分时复用的模块,找出最大内存需求的模块 如《[节省内存的软件设计技巧](http://blog.csdn.net/yueqian_scut/article/details/22522821)》这篇文章提到,应用、驱动、中间件、数据段都存在着复用的需求。要在2)中的各个软件层次中区分各个不同的组成模块,明确各个模块是否能够进行分时复用。在复用的情况下,找出最大内存需求的模块,如nand flash驱动要比card驱动复杂,那nand flash驱动的内存需求自然要高;而音乐应用自然要比设置或者FM等应用要复杂,其内存需求自然也要更多。 4.对最大内存需求模块的代码进行分析,大致明确其常驻内存代码和分块(bank)管理的代码。 常驻代码段一般是调用频繁的、性能要求高的代码段,如中断管理、消息管理等。一般应用中大量的代码是可以按需加载执行的,如音乐的音效管理和音量设置这些功能代码并不要求很高的执行性能,其是可以分时加载到内存执行,能够达到内存分时复用的目的。 5.确定各个软件层次的常驻代码空间和分时复用内存的空间 在成本的要求下尽可能减少常驻代码空间,会导致代码执行性能的降低,因为bank代码执行前要先进行加载,一般是从nand flash或者card中读取;在成本的要求下我们也想尽可能减少bank代码复用的内存空间,同样会导致bank代码切换频繁而降低性能,因此也不能一味地减少内存,而是仔细分析各个子模块的功能和性能对内存的大致要求。例如两个子模块的函数实现是8k和4k,那我们可以考虑2K的复用空间,即前者分成4个bank,后者2个bank,是否能够达到性能;如果复用空间设置为4K,效率会高一些,但成本会增加;如果设置为1k,那前者就会有8个bank,切换次数过多。 6.明确可以固化的代码空间 应用的常驻代码是不能固化的,因为不同的应用都需要常驻代码,即其是变化的,而像操作系统的中断管理、时间管理、任务调度管理等代码一般是不变的,其可以固化到ROM中,这样能达到节省内存的目的。 7.考虑其他特殊的需求 通过6,我们可以大致得到整个系统的内存需求。这时要考虑一些特殊的场景的内存需求,看之前制定的内存是否能够满足这个场景。例如启动阶段的内存需求分布,OS引导初始化时的内存要求等。这些并不是产品的规格,同样是架构设计师要考虑的。 一般会对6中得到的内存再次评估,以进行细微的调整。 请关注SoC嵌入式软件架构设计(控制器SoC固件架构)系列博文: [SoC嵌入式软件架构设计之一:系统内存需求评估 ](http://blog.csdn.net/yueqian_scut/article/details/24602941) [SoC嵌入式软件架构设计之二:没有MMU的CPU实现虚拟内存管理的设计方法](http://blog.csdn.net/yueqian_scut/article/details/24816757) [SoC嵌入式软件架构设计之三:代码分块(Bank)设计原则](http://blog.csdn.net/yueqian_scut/article/details/24911021) [SoC嵌入式软件架构设计之四:内存空间规划分配](http://blog.csdn.net/yueqian_scut/article/details/24910877) [SoC嵌入式软件架构设计之五:可执行程序的重构](http://blog.csdn.net/yueqian_scut/article/details/24910951) [嵌入式:节省内存的软件设计技巧](http://blog.csdn.net/yueqian_scut/article/details/22522821) 更多嵌入式和物联网原创技术分享敬请关注微信公众号:嵌入式企鹅圈 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-13_5695f8f8d24b2.jpg)
';

前言

最后更新于:2022-04-01 07:01:31

> 原文出处:[架构设计专栏文章](http://blog.csdn.net/column/details/fw-arch-design.html) > 作者:[吴跃前](http://blog.csdn.net/yueqian_scut) **本系列文章经作者授权在看云整理发布,未经作者允许,请勿转载!** #SoC嵌入式软件架构设计 > 专栏讲述基于控制器CPU的集成芯片(SoC)设计中的软件架构设计方法,包括软、硬件整合技术、系统软件架构、应用框架、节省内存的软件设计技巧、工具链、应用设计等内容。
';