DSP28335使用时的经验总结 主要是使用大维度的二维数组的一些问题
该部分主要是想使用较大维度的数组,我这里是112X112的。
1.数组or指针
首先是数组的使用,可以用指针,也可以直接数组,其实在内存当中的二维数组就是一维的,它是先存一行,再存其他行,在连续地址当中的存储顺序就是:a[0][0]、a[0][1]、a[0][2]....a[1][0]、a[1][1]、a[1][2].............'关于指针跟上面等效表示数组就是:(*((Uint16 *)a+(N*i)+j)),其中N是数组的列数大小,即一行有多少个数据,然后i是行号,j是列。关于直接使用数组和指针的区别其实是程序运行速度,一般来讲指针会运行的更快一些,但也要取决于代码怎么写,因为他们的实质都是内存地址,所以如果是小白开始学,只是想实现功能,直接使用数组就好。
2.当数组作为参数传给函数时
因为数组和指针是共用的,所以定义了a[][]之后,使用a也是可以的,甚至使用&,也是可以调用定义的数组,只是各自含义不同,所以当函数的输入参数有数组或者指针时要注意。这里可以给个实例,在函数里面
float *factor(float e,Uint16 n)
{Uint16 i = 0;Uint16 j = 0;float factor0[3];for(i=0;i<n;i++){for(j=0;j<n;j++){*((float *)e+(n*i)+j) = n*i+j;}}factor0[0] = *((float *)e); //[0][0]factor0[1] = *((float *)e+1);; //[0][1]factor0[2] = *((float *)e+n); //[1][0]return factor0;
}
然后在main里面调用时:
float e[N][N];
float * factor0;factor0 = factor((float )e,N)
一定要注意当数组时函数输入或者输出时,调用的方式,大家可以自行对比,如果理解比较困难,就照着写就行,或者在CCSdebug窗口当中观测这些变量的值,总之如果使用不当,进行数据传输时,可能传的就是一些地址。
3.关于在CCS当中使用大数组时
我这里是V6版本,首先是不能进行纯软件仿真的,所以需要根据以前的版本进行软件配置,才能进行纯软件仿真,最后其实是配置不同的仿真器参数,进行纯软件仿真或者连开发板进行硬件仿真,这个大家可以百度一下CCS配置软件仿真就可以完成。然后是关于内存大小的问题,我起初是将二维数组的N设置成define,把算法功能完成之后,当N较小的时候,是可以进行计算的,但是当N调大之后,程序就不能成功运行,甚至会卡在main函数最开始的几步变量声明和系统时钟初始化里面,一直循环,不会进行下面的算法计算,但是不会报任何的错。
起初以为是内存分配的问题,在view里面是可以看到内存使用的情况的,我已经分配了一个较大内存,甚至是xintf里面的zone7外扩地址,但还是不行。经过几天的实验,总结如下:
当进行大规模的数组运算时:
要使用全局变量或者动态分配,其中全局变量就是定义在main上面的变量,测试是可以实现大规模数组的,动态分配没有测试成功,应该是我不会分配。其中为什么全局变量可以,局部变量不可以,好像是因为,局部变量是在当前一个固定的部分进行定义的,这个大小好像是固定且较小的,所以当数组本身就大时,就没有连续的其余地址来放置,而全局变量是放在cmd文件当中的,可以自定义大小。
而这个cmd文件,其实归根结底是对28335的内存地址的声明和分配,就是在page0和page1当中对地址段进行命名以及起始地址和长度,这个是根据28335的实际内存地址进行分配,要注意的就是对xintf的地址进行使用时,应该是要先配置或者初始化的,我之前就是直接将.bss分配到zone7的地址当中,那么在debug时,就会在该部分的变量后面显示,该地址不可读。还有就是cmd文件是可以自己修改的,因为是初学,以为是配置文件。将芯片内存地址分好段之后(是可以将某些地址段拼起来的,只要地址不重复就行),就要对程序当中的代码段,变量等分配内存,就像是.text,.ebss,这些大家百度一下就知道。下面是我修改的一些cmd:
MEMORY
{
PAGE 0 :/* BEGIN is used for the "boot to SARAM" bootloader mode *//* BOOT_RSVD is used by the boot ROM for stack. *//* This section is only reserved to keep the BOOT ROM from *//* corrupting this area during the debug process */BEGIN : origin = 0x000000, length = 0x000002 /* Boot to M0 will go here */BOOT_RSVD : origin = 0x000002, length = 0x00004E /* Part of M0, BOOT rom will use this for stack */ // RAMM0 : origin = 0x000050, length = 0x0003B0RAMM0 : origin = 0x000050, length = 0x0007B0
// RAML0 : origin = 0x008000, length = 0x001000
// RAML1 : origin = 0x009000, length = 0x001000// RAML2 : origin = 0x00A000, length = 0x001000
// RAML3 : origin = 0x00B000, length = 0x001000ZONE6A : origin = 0x100000, length = 0x00FC00 /* XINTF zone 6 - program space */ CSM_RSVD : origin = 0x33FF80, length = 0x000076 /* Part of FLASHA. Program with all 0x0000 when CSM is in use. */CSM_PWL : origin = 0x33FFF8, length = 0x000008 /* Part of FLASHA. CSM password locations in FLASHA */ADC_CAL : origin = 0x380080, length = 0x000009 //0x000009RESET : origin = 0x3FFFC0, length = 0x000002IQTABLES : origin = 0x3FE000, length = 0x000b50IQTABLES2 : origin = 0x3FEB50, length = 0x00008cFPUTABLES : origin = 0x3FEBDC, length = 0x0006A0BOOTROM : origin = 0x3FF27C, length = 0x000D44 PAGE 1 :
// RAMM1 : origin = 0x000400, length = 0x000400 //0x000400 /* on-chip RAM block M1 */// RAML4 : origin = 0x00C000, length = 0x001000// RAML5 : origin = 0x00D000, length = 0x001000
// RAML6 : origin = 0x00E000, length = 0x001000// RAML7 : origin = 0x00F000, length = 0x001000RAML4 : origin = 0x008000, length = 0x008000ZONE7B : origin = 0x20FC00, length = 0x000400 //0x000400 /* XINTF zone 7 - data space */SARAML0 : origin = 0x3F8000, length = 0x002000
}SECTIONS
{/* Setup for "boot to SARAM" mode: The codestart section (found in DSP28_CodeStartBranch.asm)re-directs execution to the start of user code. */codestart : > BEGIN, PAGE = 0ramfuncs : > RAMM0, PAGE = 0 //RAML0.text : > RAML4, PAGE = 1 //RAML1.cinit : > RAMM0, PAGE = 0 //RAML0.pinit : > RAMM0, PAGE = 0 //RAML0.switch : > RAMM0, PAGE = 0 //RAML0.stack : > RAMM0, PAGE = 0 //RAMM1.ebss : > RAML4, PAGE = 1 //RAML4.econst : > RAML4, PAGE = 1 //RAML5.esysmem : > RAMM0, PAGE =0 //RAMM1.bss : > RAML4, PAGE = 1IQmath : > RAMM0, PAGE = 0 //RAML1IQmathTables : > IQTABLES, PAGE = 0, TYPE = NOLOAD IQmathTables2 : > IQTABLES2, PAGE = 0, TYPE = NOLOAD FPUmathTables : > FPUTABLES, PAGE = 0, TYPE = NOLOAD DMARAML4 : > RAML4, PAGE = 1
// DMARAML5 : > RAML5, PAGE = 1// DMARAML6 : > RAML6, PAGE = 1
// DMARAML7 : > RAML7, PAGE = 1ZONE7DATA : > ZONE7B, PAGE = 1.reset : > RESET, PAGE = 0, TYPE = DSECT /* not used */csm_rsvd : > CSM_RSVD PAGE = 0, TYPE = DSECT /* not used for SARAM examples */csmpasswds : > CSM_PWL PAGE = 0, TYPE = DSECT /* not used for SARAM examples *//* Allocate ADC_cal function (pre-programmed by factory into TI reserved memory) */.adc_cal : load = ADC_CAL, PAGE = 0, TYPE = NOLOAD}
然后说一下测试过程:当我使用局部变量数组进行小维度计算时,是没有任何问题的,当把维度扩大,不会扩大,只是程序一直在初始化循环。然后将数组定义成全局变量,cmd文件就会报错,因为存放全局变量的.ebss地址是不够用的,(就是当程序只有内存问题时,是会自动报错的,因为之前一直在想是不是动态内存不够,因为算了一些这些变量的内存是够的,但是程序运行不成功,以为是计算过程中还有其他消耗内存,但现在看来就不是,在程序编译的时候,就已经自动考虑了内存的问题),所以拼接一块大的地址段给ebss即可。(有些也说可以在地址那里加上|,就是“或”别的地址,但好像还是不行,后面我就直接屏蔽掉一些,直接拼接成大段的地址空间)