stm32中字节对齐问题

ARM下的对齐处理   
from DUI0067D_ADS1_2_CompLib

3.13 type  qulifiers

有部分摘自ARM编译器文档对齐部分  
对齐的使用:  
1.__align(num)  
   这个用于修改最高级别对象的字节边界。在汇编中使用LDRD或者STRD时  
   就要用到此命令__align(8)进行修饰限制,来保证数据对象是相应对齐。  
   这个修饰对象的命令最大是8个字节限制,可以让2字节的对象进行4字节  
   对齐,但是不能让4字节的对象2字节对齐。  
   __align是存储类修改,他只修饰最高级类型对象,不能用于结构或者函数对象。

比如:__align(4) u8 mem1base[MEM1_MAX_SIZE];//保证分配的数组空间4字节对齐,同时保证数组首地址可被4整除
     
2.__packed   
  __packed是进行一字节对齐  
  1.不能对packed的对象进行对齐  
  2.所有对象的读写访问都进行非对齐访问  
  3.float及包含float的结构联合及未用__packed的对象将不能字节对齐  
  4.__packed对局部整形变量无影响  
  5.强制由unpacked对象向packed对象转化是未定义,整形指针可以合法定  
  义为packed。  
     __packed int* p;  //__packed int 则没有意义  
  6.对齐或非对齐读写访问带来问题  
  __packed struct STRUCT_TEST  
{  
  char a;  
  int b;  
  char c;  
}  ;    //定义如下结构此时b的起始地址一定是不对齐的  
         //在栈中访问b可能有问题,因为栈上数据肯定是对齐访问[from CL]  
//将下面变量定义成全局静态不在栈上   
static char* p;  
static struct STRUCT_TEST a;  
void Main()  
{  
__packed int* q;  //此时定义成__packed来修饰当前q指向为非对齐的数据地址下面的访问则可以

p = (char*)&a;            
q = (int*)(p+1);

*q = 0x87654321;   
/*     
得到赋值的汇编指令很清楚  
ldr      r5,0x20001590 ; = #0x12345678  
[0xe1a00005]   mov      r0,r5  
[0xeb0000b0]   bl       __rt_uwrite4  //在此处调用一个写4byte的操作函数   
        
[0xe5c10000]   strb     r0,[r1,#0]   //函数进行4次strb操作然后返回保证了数据正确的访问  
[0xe1a02420]   mov      r2,r0,lsr #8  
[0xe5c12001]   strb     r2,[r1,#1]  
[0xe1a02820]   mov      r2,r0,lsr #16  
[0xe5c12002]   strb     r2,[r1,#2]  
[0xe1a02c20]   mov      r2,r0,lsr #24  
[0xe5c12003]   strb     r2,[r1,#3]  
[0xe1a0f00e]   mov      pc,r14  
*/

/*  
如果q没有加__packed修饰则汇编出来指令是这样直接会导致奇地址处访问失败  
[0xe59f2018]   ldr      r2,0x20001594 ; = #0x87654321  
[0xe5812000]   str      r2,[r1,#0]  
*/

//这样可以很清楚的看到非对齐访问是如何产生错误的  
//以及如何消除非对齐访问带来问题  
//也可以看到非对齐访问和对齐访问的指令差异导致效率问题  
}

比如:

typedef __packed struct READ_Command
{
    u_char code;
    u_int addr;
    u_char len;
} READ_Command;

typedef  struct READ_Command
{
    u_char code;
    u_int addr;
    u_char len;
} READ_Command;
的区别是什么啊?
回答:没有__packed的会出现字对齐等也就是,char型的有可能是占用4个字节的长度的内存空间有__packed 的就不会,就肯定是1个字节的内存空间,是gcc编译器的关键字。(不止vc下面32位的系统里面的内存数据的存取是32位的,处理的时候都是4个字节为单位,通常也就是int的长度。如果不定义压缩方式,也就是编译选项没有诸如#pragma pack(1)之类的,那么系统会进行4字节对齐)

注意:_packed只是某种编译器的格式压缩,有的是pack呢,对不同的CPU压缩的对齐方式也不一样,在使用了该关键以后在进行操作时需要格外小心。

声明结构类型时,可以包含一个保留字packed,用于实现压缩数据存储。

当一个记录类型在   {$A-}   状态下声明或者声明中包括了保留字   packed   时,记录中的字段不被调整,而替换为赋予连续的偏移量。这样一个压缩记录的总尺寸就是所有字段的尺寸的和。因为数据调整尺寸可能改变(如不同版本的编译器对同一种数据类型的调整值可能不同),所以当想要把记录写入磁盘时或者在内存中传递到另一模块而该模块由不同版本的编译器编译时,最好还是压缩所有的记录。(delphi borland 中也有该关键字)

3.在 Cotex-M3 programming manual 中有提到对齐问题
  1.通常编译器在生成代码的时候都会进行结构体填充,保证(结构体内部成员)最高性能的对齐方式。
  2.编译器自动分配出来结构体的内存(比如定义为全局变量或局部变量)肯定是对齐的。

3.查阅帮助文档的malloc部分,mdk的标准malloc申请的内存区时8字节对齐的。

4.若自定义的malloc本身没有实现4字节或以上的对齐,分配出来的不对齐的内存,编译器是不知道的,所以很可能会产生问题。

此时最好的解决方式在内存池数组前添加__align(4)关键字,只需保证自定义malloc分配出来的首地址是4字节对齐。

比如:__align(4) u8 mem1base[MEM1_MAX_SIZE];

相关更多stm32字节对齐问题的讨论,请参考正点原子相关帖子http://www.openedv.com/thread-7415-1-1.html。

其中问题的关键就在于正点原子自定义的mymalloc函数没有实现4字节对齐。

时间: 2024-10-17 14:19:47

stm32中字节对齐问题的相关文章

c++内存中字节对齐问题详解[转载]

一.什么是字节对齐,为什么要对齐?     现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐.     对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同.一些平台对某些特定类型的数据只能从某些特定地址开始存取.比如有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在

c++内存中字节对齐问题详解

一.介绍 什么是字节对齐 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐. 字节对齐的原因和作用 各个硬件平台对存储空间的处理上有很大的不同.一些平台对某些特定类型的数据只能从某些特定地址开始存取.比如有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字

c++中字节对齐问题

三个基本原则 1.struct或者union或者class里,每个成员的对齐开始位必须是成员自己的大小的整数倍: 2.每个结构体的大小必须是结构体内最大成员的整数倍,(第二个补齐方式) 3.结构体a内的结构体b的开始位必须是b里的最大成员的整数倍. 例一: typedef struct BB { int id;             //[0]....[3] double weight;      //[8].....[15] 原则1 float height;      //[16]..[1

计算机字节对齐

定义是long至少不小于int,long long至少不小于long: 在32位机器中,一般long和int同,为32,long long为64: c++内存中字节对齐问题详解 一.什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐. 对齐的作用和原因:各个硬件平台对

仔细讨论 C/C++ 字节对齐问题

字节对齐的原因 为了提高 CPU 的存储速度,编译器会对 struct 和 union的存储进行优化,即进行字节对齐. 对齐方式 对于 struct 或 union 中的 struct 或者 union 来说,它们的字节对齐标准就是它的所有成员中字节数最大的数据的字节数. 一般情况下 C/C++ 的变量所占用的字节数 char:    1字节: short:   2字节: int:       4字节: long:    4字节: long long: 8字节: float:    4字节: d

C/C++中避免系统的字节对齐

在定义了一个新的Struct后. 系统会按照一定的规则将新生命的类型变量进行字节对齐,如下结构体: typedef struct Test{ int a; char b[6]; }Test; 该结构体类型可能会被对齐为12个字节. 那么,在内存流和文件流操作中可能会出现这样的用法: fwrite(strPtr,1,sizeof(Test)*len,fp); 事实上,被写入了len*12个字节,因为sizeof(Test)实际上不等于10,而是12. 那么,如下简单地操作可以避免在流操作中出现的一

C++中的字节对齐

本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三二一.小鱼)相关研究.学习内容所做的笔记,欢迎广大朋友指正! 字节对齐 1. 基本概念字节对齐:计算机存储系统中以Byte为单位存储数据,不同数据类型所占的空间不同,如:整型(int)数据占4个字节,字符型(char)数据占一个字节,短整型(short)数据占两个字节,等等.计算机为了高速的读写数据,默认情况下将数据存放在某个地址的起始位置,如:整型数据(int)默认存储在地址能被4整除的起始位置,字

c/c++中的字节对齐

参加了很多面试,遇到字节对齐的问题不是1次2次,但一直没有彻底弄明白是什么意思,清明节刚好闲下来,彻底研究了一下,得到下面的结论,希望对以后的面试和工作有作用: 第一种结论: 首先提出几个概念 ①基本类型:像int,char,float,double之类的基本类型 ②复合类型:结构体,类,联合体之类的类型,由基本类型构成 ③数据类型的宽度: 用sizeof (type)计算出来的宽度,一般int为4 Bytes,char为1 Byte... ④有效对齐模数N: 编译器默认对齐模数为M,M可以用#

python struct.pack中的对齐字节问题

最近测试涉及到了序列字节化相关问题,碰到一个头疼的问题 buff = struct.pack("3s","B00")    print repr(buff) 输出:'B00' buff = struct.pack('i',10172) print repr(buff) 输出:"\xbc'\x00\x00" buff = struct.pack("3si","B00",10172)print repr(buf