该部分主要是想使用较大维度的数组,我这里是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 = 0x0003B0
RAMM0 : origin = 0x000050, length = 0x0007B0
// RAML0 : origin = 0x008000, length = 0x001000
// RAML1 : origin = 0x009000, length = 0x001000
// RAML2 : origin = 0x00A000, length = 0x001000
// RAML3 : origin = 0x00B000, length = 0x001000
ZONE6A : 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 //0x000009
RESET : origin = 0x3FFFC0, length = 0x000002
IQTABLES : origin = 0x3FE000, length = 0x000b50
IQTABLES2 : origin = 0x3FEB50, length = 0x00008c
FPUTABLES : origin = 0x3FEBDC, length = 0x0006A0
BOOTROM : 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 = 0x001000
RAML4 : origin = 0x008000, length = 0x008000
ZONE7B : 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 = 0
ramfuncs : > 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 = 1
IQmath : > RAMM0, PAGE = 0 //RAML1
IQmathTables : > 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 = 1
ZONE7DATA : > 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即可。(有些也说可以在地址那里加上|,就是“或”别的地址,但好像还是不行,后面我就直接屏蔽掉一些,直接拼接成大段的地址空间)