平常咱们触摸最多的或许是X86渠道,在这种体系上写程序简直不需求考虑太多问题,但ARM上就不相同了,最常见也最简单被疏忽的问题或许便是字节的对齐,即便像我这样有六七年程序开发经历的才手也经常难于防范,最近就有一个BUG,花了一天时间终究发现是对齐引发的,在此与咱们共享,希望咱们可以留意到。
实践上,这类问题在ARM体系上很常见,让人防不胜防,以下是我的一些比如。
1,解析数据流时应该时间留意。假如需求把一个数据流(BUFFER)转化成结构进行取值,就应该把这个结构界说为按字节存取.考虑如下结构:
struct a{
char a;
short b;
long c;
};
假如某个数据流中包括这样的结构,并且咱们要直接将数据流的指针转化成该结构的指针,然后直接取结构成员的值,咱们就应该将这个结构界说成按字节拜访,即将其夹在句子
#pragma pack(push,1)
…
#pragma pack(pop)
之中。假如咱们不这样做,编译器会将成员b的地址对齐到short指针的地址,即在a之后加上一个char即8位的成员,将C对齐到LONG,即在B之后再加一个char成员。如此一来,成员B和成员C就得不到正确的值了。
假如咱们界说一个一般的结构用来寄存一些数据,则不必界说成按字节存取,编译器会加上一些占位成员,但并不会影响程序的运转。从这个意义上讲,在ARM中,将结构成员界说成CHAR和SHORT来节省内存是没有意义的。
一个典型的比如就文件体系的驱动程序,文件是以一些现已界说好的结构寄存在存储介质上的,它们被读取到一个BUFFER中,而详细取某个文件、目录结构时,咱们会将地址转化成结构而读取其间的值。
2,拜访外设时。
例如,磁盘驱动通常以16BIT的方法存取数据,即每次存取两个字节,这样就要求传给它的BUFFER是双字节对齐的,驱动程序应该至上层传来的指针做出正确的处理以确保数据的正确性。
3.有时,咱们没有将数据流指针转化为结构指针取值,但假如咱们读取的是双字节或者是四字节的数据,相同需求留意对齐的问题,例如,假如从一个BUFFER的偏移10处读取一个四字节值,则实践得到的值是偏移8处的
地址上的DWORD值。


翻开之前做wince内核定制烧写的工程,把驱动文件,假定叫A.dll, 拷贝到工程目录下,D:\WINCE420\PUBLIC\wince工程\RelDir\SAMSUNG_SMDK2410_ARMV4Release 这个下边.然后在pb工作环境中,找到ParameterView区,打开树型列表,找到project.bib和project.reg两个文件,要对他们进行修正.
修正 project.bib 增加 A.dll $(_FLATRELEASEDIR)\A.dll NK SH 这样一行 .
将产家供给的reg文件里的内容copy到project.reg里.
以上做好后,由于我是pb4.2的环境,这时候点bulide菜单下的make image.等完成后,再从头烧写一遍镜像文件(nk) 到开发板上就可以了。留意我这儿选make image而不是build platform。假如选build platform会抱错的,说找不到dll等等几个过错。我买的周建功的一本书上是在pb5.0环境下,到这一步时说 在菜单buuild os中,不选clean before building。然后再挑选sysgen从头编译生成新的wince映像
物理地址映射方法分为两种,一种静态映射另一种为动态映射。在OEMAddressTable中界说了物理地址与虚拟地址的映射联系归于静态映射,用VirtualCopy映射归于动态映射,选用哪种方法都可以。问题中说到的归于静态映射,2440的BSP在map.a文件中界说了IIC操控寄存器的物理开始地址和对应的虚拟地址如下:
DCD 0x91400000, 0x54000000, 1 ;
在OEMAddressTable中界说的虚拟地址范围在0x8000 0000—0x9FFF FFFF,这部分可缓存,合适内核程序和应用程序运用,一起WINCE内核在0xA000 0000—0xBFFF FFFF中映射了另一份,指向了相同的物理地址,这部分不行缓存,合适驱动程序运用。三星ARM处理器带有L1级高速缓存,可缓存会进步履行功率。关于特别的设备寄存器合适映射到不行缓存的虚拟地址。
当驱动程序调用VirtualCopy对0xB1400000地址读写时,WINCE主动将这个地址减去0x2000 0000,也便是0x91400000,对应的物理地址便是0x54000000,也便是I%&&&&&%操控寄存器的物理开始地址。