2011年(94)
分类:
2011-05-28 10:58:36
模块划分
模块划分的"划"是规划的意思,意指怎样公道的将一个很大的软件划分为一系列功能独立的部分合作完成系统的需求。C语言作为一种结构化的程序设计语言,在模块的划分上主要依据功能(依功能进行划分在面向对象设计中成为一个错误,牛顿定律碰到了相对论),C语言模块化程序设计需理解如下概念:
(1) 模块即是一个.c文件和一个.h文件的结合,头文件(.h)中是对于该模块接口的声明;
(2) 某模块提供给其它模块调用的外部函数及数据需在.h中文件中冠以extern关键字声明;
(3) 模块内的函数和全局变量需在.c文件开头冠以static关键字声明;
(4) 永远不要在.h文件中定义变量!定义变量和声明变量的区别在于定义会产生内存分配的操纵,是汇编阶段的概念;而声明则只是告诉包含该声明的模块在连接阶段从其它模块寻找外部函数和变量。如:
/*module1.h*/ int a = 5; /* 在模块1的.h文件中定义int a */ /*module1 .c*/ #include "module1.h" /* 在模块1中包含模块1的.h文件 */ /*module2 .c*/ #include "module1.h" /* 在模块2中包含模块1的.h文件 */ /*module3 .c*/ #include "module1.h" /* 在模块3中包含模块1的.h文件 */ |
/*module1.h*/ extern int a; /* 在模块1的.h文件中声明int a */ /*module1 .c*/ #include "module1.h" /* 在模块1中包含模块1的.h文件 */ int a = 5; /* 在模块1的.c文件中定义int a */ /*module2 .c*/ #include "module1.h" /* 在模块2中包含模块1的.h文件 */ /*module3 .c*/ #include "module1.h" /* 在模块3中包含模块1的.h文件 */ |
后要从romInit()函数开始运行。因此,需要设计一个方案来加载编译工程得到的映象,而且要具备初始化CPU和SDRAM存储空间的功能。
首先,系统从romInit()函数中开始运行,完成CPU和SDRAM初始化,然后跳转到函数romStart()运行。加载第二份bootrom代码到系统的低地址处,然后运行壳代码中的sysInit()函数,并调用自己构造的解压函数usrInit(),将压缩后的工程映象文件解压缩到系统高地址处,然后系统继续运行解压后的bootrom代码。此时,系统开始运行sysInit()函数,然后调用vxWorks系统中的usrInit()函数,开始初始化系统硬件,内核以及其他外围设备。
壳函数usrInit()代码如下:
void usrInit(void)
{
volatile FUNCPTR absEntry;
if(inflate((UCHAR *)ROM_OFFSET(_binArrayStart),
(UCHAR *)(RAM_LOW_ADRS), _binArrayEnd - binArrayStart)!= OK)
return;
absEntry=(FUNCPTR)(RAM_LOW_ADRS);
(absEntry)();
}
其中RAM_LOW_ADRS为系统低地址,是操纵系统运行的起始地址,但bootrom可以利用低地址来实现在系统高地址的运行。宏ROM_OFFSET用于正确定位函数地址,由于在bootrom中运行的代码要求以相对地址方式来寻址,而不能以尽对地址方式来寻址。 _binArrayStart 为压缩后二进制代码的开始符,_binArrayEnd为压缩后二进制代码的结束符。Inflate()是vxWorks软件的解压缩函数,它用于解压缩通过deflate()压缩函数压缩的二进制文件映象。
同时,需要将下述代码添加到编译规则文件rules.vxWorks中的相应部分:
$(CC) -c $(CFLAGS) $(BSP_DIR)/unzip.c -o $(BSP_DIR)/unzip.o
$(LD) $(LDFLAGS) -e sysInit -Ttext $(RAM_LOW_ADRS) \
-o unzip_obj.o sysALib.o $(BSP_DIR)/unzip.o $(LIBS) flex.z.o
其中,unzip.c中包含构造的壳函数usrInit()。SysInit()为解压软件的进口函数。上述语句的功能:第一行完成壳文件的编译,第二、三行完成壳目标代码与第二份bootrom代码的链接。这样一个具有解压功能的壳函数就被链接到第二份bootrom映象中。
以前的系统运行方式与修改后的系统运行方式比较:
通过这两种方式的比较可以看出,以前系统运行方式与修改后的运行方式有下面两点差异:(1)第一份bootrom启动后,前者存在解压缩自身映象的操纵,而后者没有。(2)对于第二份bootrom,前者没有壳代码,而后者有。
2.3 缩减文件长度
通常第一份bootrom代码只有两个文件,一个是包含CPU和SDRAM初始化文件romInit.s,另外就是包含romStart()函数的bootInit.c文件,另外根据需要还可以添加提供串口轮询显示功能的文件。对于第一份bootrom代码,通常只有10K左釉定这是针对系统修改后的方式),而对于包含壳函数代码的,通过建立工程并编译而天生的第二份bootrom,则比较大通常为570K左右。(留意:这几个数值是通过特定的产品来得出的结论,并不应用于所有产品,但碰到类似的情况可以鉴戒处理。)。而其后面的一部分完全是0,可以考虑往掉这些0,但不能影响软件的功能。经过测试,得出结论:往掉后面的0对系统功能和性能没有任何影响。
通过文件的操纵来实现二份bootrom合并,合并后的大小要求小于或即是512K。假如不采用任何措施,直接将
,那么,中断服务对这样的实时代码执行时间没有直接的影响。
应用实例
音频解码器通常作为驱动器应用进行存取。驱动器的作用是从适当的输进设备提取引进的位流,并将经过解码的位流发送到音频输出设备,如下图所显示的那样。它也可以执行其他后处理功能,例如在发送到输出设备之前,对经过解码的音频位流进行低音控制。驱动器通过一个标准接口机制访问MIPS的音频产品,也就是MIPS的软音频接口(Soft Audio Inte***ce,SAI)。这个通用接口可使各种来自MIPS Technologies的音频解码器易于与主应用进行连接。
MIPS SAI可提供解码器和主程序,或高级控制和运算监控解码器RTOS之间的接口功能和结构。这种接口为访问控制解码器运算和访问状态和差错信息参数提供了机会。该接口可执行三个基本功能:一个是对解码器进行初始化,第二个是阅读帧标题,第三个实际上是进行解码处理。所有的解码器都具有与特定解码器有关的预确认字段数据结构。解码器对所有的帧进行阅读和结构更新。在帧开始或结束时,主程序可访问数据结构,阅读状态或改变控制参数。参考下面的代码实例,它说明了驱动程序的运行情况。MIPS SAI的功能用粗体字表示。
int main(void)
{
decoder_specific_struct dec_ptr
//Initialize the decoder.
mips_sai_dec_init(dec_ptr)
//Open the bitstream input device.
open_input()
//Open the audio output device.
open_output()
//Allocate buffers for decoder operation.
allocate_buffers(dec_ptr)
while(not-end-of-input-bitstream)
//Read the input bitstream.
read_input(dec_ptr)
//Read the frame header for encoded stream parameters.
mips_sai_dec_readheader(dec_ptr)
//Set up params for decoder operation.
setup_params(dec_ptr)
//Decode the frame
mips_sai_dec_process(dec_ptr)
//write the decoder output to the device driver.
write_output(dec_ptr)
end-while
//Close the input and output devices.
close_input()
close_output()
return 0 }
总之,MIPS处理器可供使用的各种特性为实现消费音频算法提供了一系列的上风。这些上风包括单一的可编程架构、更低的系统本钱和缩短上市时间。这使MIPS处理器成为从电池供电的移动音频播放器到高性能DVD刻录设备等消费电子产品音频应用的一种可行和具有吸引力的解决方案。
(
给主人留下些什么吧!~~
|