DSP

DSP编程中的字节对齐

2019-07-13 09:55发布

PC上向ADI DSP平台移植时,经常会出现一些问题,其中很多问题和字节对齐有关。这类问题往往在PC上测试成功,在DSP上也能成功编译链接,但是运行却会出错,导致这类问题很难查出并解决。 问题成因: 我使用的是ADIBlackfin系列DSP,不知道其他平台是否有这个规定。就是char型数据类型地址可以任意,short型数据类型地址必须被2整除,int型数据类型地址必须被4整除,依此类推,即基础数据类型的地址必须被这种数据类型的大小整除。 而一般PC上是没有这个规定的。于是问题来了,比如下面的取数据函数,在PC上没有问题,在ADI DSP上运行肯定会出错的。 void get_data(unsigned char *inbuf) { char data1; short data2; int data3; data2 = *(((short *)inbuf)++);      //1 data1 = *(inbuf++);              //2 data3 = *((int *)inbuf);           //3   fprintf(stdout, “data1 = %d/ndata2 = %d/ndata3 = %d/n”, data1, data2, data3); return; } 根据上面的规定,显然不论输入的inbuf地址是多少,上面的程序都会出错。比如说inbuf是奇数,句1就是将一个奇数地址强制转换成了一个short型地址,出错。如果inbuf是偶数,经过句1和句2后,句3显然又将一个奇数地址强制转换成了一个int型的地址,出错。 这种问题不是我特意设置来钻牛角尖的,他普遍存在于从码流中读入不同类型的数据的程序中,比如音视频解析对码流的解析,码流中存在各种数据类型的语法元素,将他们读入内存的时候就有这种问题。   解决方法: 方法1 将一个长数据类型,分解成几个char类型来读取,比如一个int型的数据可以这样读取: //original unsigned char* inbuf;                          //注意一定是unsiged
unsigned int tmp1, tmp2, tmp3, tmp4; int res; tmp1 = (unsigned int)*(inbuf++); tmp2 = (unsigned int)*(inbuf++); tmp3 = (unsigned int)*(inbuf++); tmp4 = (unsigned int)*(inbuf++); res = (int)((tmp1 & 0xff) + ((tmp2 & 0xff)<<8) + ((tmp3 & 0xff)<<16) + ((tmp4 & 0xff)<<24));   //or macro #define GetUnalignedDword( pb, dw ) /             (dw) = ((unsigned int) *(pb + 3) << 24) + /                    ((unsigned int) *(pb + 2) << 16) + /                    ((unsigned int) *(pb + 1) << 8) + *pb; 方法2 定义一个包含基础数据类型的紧缩的结构体,将不对齐地址强制转化成此结构体,示例如下 #ifdef __GNUC__ #define GNUC_PACKED   __attribute__ ((packed)) #else #define GNUC_PACKED #endif   #ifdef __arm #define ARM_PACKED     __packed #else #define ARM_PACKED #endif   #if defined WIN32 || defined VDSP #pragma pack(1) #endif ARM_PACKED struct unaligned_32 { unsigned int data; } GNUC_PACKED; #if defined WIN32 || defined VDSP #pragma pack() #endif //struct defined upper   int data; data = ((struct unaligned_32 *)inbuf)->data;   方法2节省一些计算,不过一般来说码流解析不是主要占用系统资源的模块,不需要很高的效率。建议两种方法都可以试试,再根据实际的效果来选取效果最好的。   参考文章:http://blog.csdn.net/fmddlmyy/archive/2008/07/16/2663481.aspx   附:声明对齐数据类型的方法(摘自ffmpeg #if defined(__ICC) || defined(__SUNPRO_C)     #define DECLARE_ALIGNED(n,t,v)      t v __attribute__ ((aligned (n)))     #define DECLARE_ASM_CONST(n,t,v)    const t __attribute__ ((aligned (n))) v #elif defined(__GNUC__)     #define DECLARE_ALIGNED(n,t,v)      t v __attribute__ ((aligned (n)))     #define DECLARE_ASM_CONST(n,t,v)    static const t v attribute_used __attribute__ ((aligned (n))) #elif defined(_MSC_VER)     #define DECLARE_ALIGNED(n,t,v)      __declspec(align(n)) t v     #define DECLARE_ASM_CONST(n,t,v)    __declspec(align(n)) static const t v #else     #define DECLARE_ALIGNED(n,t,v)      t v     #define DECLARE_ASM_CONST(n,t,v)    static const t v #endif ffmpegDECLARE_ALIGNED宏只用于数据类型和数组,我认为他的作用在于将数据或数组的首地址按照参数n来对齐,n单位为byte。至于他能否用于结构体,我不知道……估计也是可以的。