MSP430内存对齐问题

今天终于遇到了内存对齐的问题。
定义了一个数组 u16 xyz[3],
定义了一个指针 u8 *p_xyz = (u8*)xyz
定义了如下宏

1
2
3
4
5
6
#define   XHi   *(p_xyz)
#define   XLo   *(p_xyz + 1)
#define   YHi   *(p_xyz + 2)
#define   YLo   *(p_xyz + 3)
#define   ZHi   *(p_xyz + 4)
#define   ZLo   *(p_xyz + 5)

通信函数通过以上六个宏访问 xyz 进行数据发送,发送时要求大端对齐,即MSB在前(数据包中的低字节)。
但实际的结果和预想的不同,数据的高位和地位恰好颠倒了。

原因在于MSP430的内存是小端对齐问题,即LSB在前(内存中的低字节)。指针 p_xyz 指向的是数组 xyz[] 的首地址0x200,即xyz[0]的地址为0x200,而 xyz[0] 的高字节的地址为 0x201,低字节地址为 0x200。所以,以上的宏定义有误。

结论,在使用指针访问内存时应该注意所使用CPU的内存对齐方式。

1
2
3
4
5
6
#define   XLo   *(p_xyz)
#define   XHi   *(p_xyz + 1)
#define   YLo   *(p_xyz + 2)
#define   YHi   *(p_xyz + 3)
#define   ZLo   *(p_xyz + 4)
#define   ZHi   *(p_xyz + 5)

附两个测试Bit Endian的小程序
method_1

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main(int argc, char *argv[])
{
  int c = 1;
  if ((*(char *)&c) == 1)
  {
    printf("little endian\n");
  }
  else
    printf("big endian");

  return 0;
}

int c 在内存中的表达为: 0x00000001. (这里假设int为4字节). 用char可以截取一个字节. LSB为0x01, 若它出现在c的低地址, 则为小端.

method_2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
int main(void)
{
/* Each component to a union type is allocated storage at the beginning of the union */
  union {
  short n;
  char c[sizeof(short)];
}un;

un.n = 0x0102;

  if ((un.c[0] == 1 && un.c[1] == 2))
    printf("big endian\n");
  else if ((un.c[0] == 2 && un.c[1] == 1))
    printf("little endian\n");
  else
    printf("error!\n");
  return 0;
}

union中元素的起始地址都是相同的——位于联合的开始. 用char来截取感兴趣的字节.
区分大端与小端有什么用呢? 如果两个不同Endian的机器进行通信时, 就有必要区分了

分享到: 更多
版权申明:

本站保留所有原创文章的版权,本站地址:奔跑的博客[http://www.elecbench.com]

原创文章转载时请注明出处,并添加文章所在页面的链接:http://www.elecbench.com/msp430%e5%86%85%e5%ad%98%e5%af%b9%e9%bd%90%e9%97%ae%e9%a2%98/

本站所有 2010年3月4日 以后发表、未标明为“转载”的文章均是本站原创。

发表评论


(设置自己的个性头像)

*

申请属于你的免费顶级域名