钱 丹, 李 飞, 路而红 ,王建新, 金华建
(1.成都信息工程学院 四川 成都 610225;2.北京电子科技学院 北京 100070;3.中国人民解放军73022部队 浙江 杭州 310024)
近年来,嵌入式技术已广泛应用于家电、无线通信、电子商务平台中[1]。基于嵌入式技术开发的各类电子产品核心部件(CPU)的国产化,符合我国信息安全的战略利益,是我国广大科研人员努力的必然方向。值得一提的是,2001年苏州国芯公司吸收和优化了M*Core技术,形成了具有我国自主知识产权的C*Core技术,随后,基于此技术的首款国产32位芯片CCM3118被推出[2]。然而,C*Core系统函数库中自带的动态内存分配函数在脱离Winsdows操作系统等情况下会失效,这给基于C*Core的内存动态开发带来阻碍。笔者正是针对这一问题,提出一种基于C*Core的动态内存分配方案。
以CCM3118芯片为例,其片内含2 kB ROM、64 kB SRAM,存储器中整数型操作数格式是标准二进制补码形式[3],地址空间映射如图1所示。
C*Core C指令系统中的操作数大小只可在两处定义:1)在指令编码中明确定义(装载/存储指令);2)在指令操作中间接定义。一般地,指令作用在32位源操作数和生成32位结果。在本方案实现部分,存储器默认采用大端(big-endian)方式存储数据 (如图2所示),即字的最重要字节在地址低位。在寄存器中,一个字对应的数值是以第31位作为最重要位(如图3所示),而0字节是最重要字节[4]。
图1 内存地址空间映射Fig.1 Memory address mapping
图2 内存数据组织Fig.2 Memory data organization
图3 寄存器数据组织Fig.3 Register data organization
由图1可知,C*Core系列芯片内存资源有限,在计算量较大的情况下,例如在利用CCM3118芯片做椭圆曲线密码算法(ECC)实现计算中,倘若采用全局数组进行ECC底层算法计算实现[5],芯片内存不能提供足够资源,但采用本方案可有效解决此问题。此外嵌入式系统对整个系统的安全和稳定起着重要作用,故此程序的可靠与否关系着整个系统的安全运行,此方案的实现利用标准C*Core C语言编写,可确保程序实现的可靠性与安全性。
程序定义一个结构体实体Mem,如图4所示,内含两类无符号字符型数据成员list[m]、meb[n],m、n大小自定。在编译阶段,Mem存储空间被分配,相应地其数据成员被分配内存大小,共m+n个字节大小。
图4 结构体Mem示意图Fig.4 Mem schematic structure
将list[0]~list[m-1]作为管理列表,用来管理数据块meb[0]~meb[n-1]。list[]中的每一项都为8位数据,其每一比特位1或0标识一个meb[]项的分配与否,如图5所示。
图5 管理列表对应数据块示意图Fig.5 The corresponding block diagram of a list about Management
例如,假定 list[]大小为 10,meb[]大小为 80,list[0]~list[9]管理meb[0]~meb[79]示意图如图6所示。动态内存分配时,程序通过list[]找到适宜的数据块meb[k],返回meb[k]首地址给用户操作即可。已分配的meb[]对应list[]设置为1,表示忙,避免二次分配。分配了的内存不使用时,及时回收,以免造成内存浪费。
图6 管理内存实例块示意图Fig.6 Example block diagram of memory management
2.2.1 管理列表和内存块分配
程序利用C*Core C语言实现,编译器不能识别除C*Core C自带以外的其他关键字。程序封装一结构体,由方案原理可知,若管理列表list[]大小为10字节,数据数组meb[]大小为80字节。当定义一结构体实体Mem后,其内含的两数据成员内存大小共90字节的存储空间在编译阶段便得以分配。伪代码如下所示:
定义结构体typedef struct
{
定义无符号字符型变量 list[10];//假定管理大小为10个字节
定义无符号字符型变量 meb[80];//假定数据块大小为80个字节
}MEM;MEM Mem;//定义结构体实体,至此90个字节的内存被分配出来,其中80个位的管理机构(list[0]~list[7])与80个字节的内存块(meb[0]~meb[79])
2.2.2 实现动态内存分配
程序核心部分源码
INT8*Malloc(UINT8 Size)
{
UINT8 i,j,k;UINT8 Enter;
if(Size>MEM_COUNT||Size<1)
return' ';//超限,内存开辟失败,返回空指针
for(i=0; i { Enter=128;//赋值为 0x80 for(j=0; j<7; j++) { if((Mem.list[i]&Enter) !=Enter) return&Mem.meb[(i<<3) +j]; //返回分配首地址 Enter>>=1; //移位查找 } } return' ';//内存开辟失败,返回空指针 } 2.2.3 方案实例运行结果分析 程序运行的软件环境为CodeWarrior IDE[6],硬件环境为国芯公司的CS32XDV10开发板。为了使结果更加明显,设计时使程序分配255个字节单元数据,当主函数Malloc()成功分配255个字节块后,返回首地址给p,同时对应的list[]管理列表设置为1。 图7 内存分配检验图Fig.7 Test diagram of memory allocation 如图7所示,在地址为:0X0080_C090~0X0080_C0AE即管理列表list[0]~list[29]中数值都为 0XFF,共248位,0X0080_C0AE为:0XFE,共7位设置为1,故总共255位都设置为 1,表示 255个字节块已经被分配。对(p+0)~(p+9)对应单元分别赋值0~9,在图8中查看结果,显示正确。对(p+251)~(p+254)对应单元即meb[251]~meb[254]分别赋值 0XF8~0XFB,在图4中查看结果,显示正确。 图8 内存分配临界部分示意图Fig.8 Diagram of critical part of the memory allocation 笔者较为详细地阐述了基于C*Core的动态内存分配方案,结合程序在苏州国芯公司的CS32XDV10开发板上的演示情况,成功动态分配了255个字节的内存单元。实验证明此方案可在不受操作系统影响情况下动态分配一定大小的C*Core系列芯片内存,在C*Core系列芯片的开发过程中,此方案可有效管理芯片中有限的内存资源,此外该方案在51 单片机上也成功实现了动态分配内存的功能。相比较一些操作系统中自带的基于链表数据结构的动态内存分配函数,本方案可避免出现内存碎片等情况,具有较高的稳定性和可靠性。 [1]王宜怀,刘晓升.嵌入式应用基础基础教程[M].北京:清华大学出版社,2005. [2]王宜怀,朱巧明,郑茳.C*Core与M*Core的嵌入式系统[M].北京:清华大学出版社,2006. [3]苏州国芯科技有限公司.CCM3118DQ Advance Information[M].1 版.苏州:[s.n.],2003. [4]马鸣锦,蒋烈辉,杜威.基于M·CORE微控制器的嵌入式系统[M].北京:国防工业出版社,2003. [5]Hankerson D,Menezes A,Vanstone S.椭圆曲线密码学导论[M].张焕国,等译.北京:电子工业出版社,2005. [6]Metrowerks.Codewarrior IDE user guide [EB/OL].(2000)[2010-11-20].http://read.pudn.com/downloads14/ebook/55460/ADS_CodeWarriorIDEGuide.pdf.3 结 论