TI中文支持网
TI专业的中文技术问题搜集分享网站

OMAPL138 平台用sysbios系统时指针赋值耗时很长的问题

最近遇到一个很奇怪的现象,不知如何解决。指针赋值例如*p=20要比变量赋值a=20花费的时间长好几十倍。

我在CCS5.5里面新建一个sysbios的工程,然后做了如下测试代码:

int test;
int *pda;
long long t1,t2,t3,t4,tover,tdelt1,tdelt2;
Int main()
{
pda= &test;
TSCH=0;
TSCL=0;
t1 = _itoll (TSCH, TSCL);
*pda = 30;
t2 = _itoll (TSCH, TSCL);
tdelt1 = t2-t1;
return 0;
}

此时的tdelt1 的值调试发现是307,也就是一个指针赋值*pda = 30 花费的307个指令周期。这也太长了。查看了它的汇编代码也没异常,如下:

27 t1 = _itoll (TSCH, TSCL);
c30025c4: 02A803E2 MVC.S2 TSCL,B5
c30025c8: 022C03E2 MVC.S2 TSCH,B4
c30025cc: 0280047E STW.D2T2 B5,*+B14[4]
c30025d0: 0200057E STW.D2T2 B4,*+B14[5]
28 *pda = 30;
c30025d4: 0200026E LDW.D2T2 *+B14[2],B4
c30025d8: DA93 MVK.S2 30,B5
c30025da: 4C6E NOP 3
c30025dc: E8000000 .fphead n, l, W, BU, nobr, nosat, 1000000
c30025e0: 029002F6 STW.D2T2 B5,*+B4[0]
29 t2 = _itoll (TSCH, TSCL);
c30025e4: 02A803E2 MVC.S2 TSCL,B5
c30025e8: 022C03E2 MVC.S2 TSCH,B4
c30025ec: 0280067E STW.D2T2 B5,*+B14[6]
c30025f0: 0200077E STW.D2T2 B4,*+B14[7]
30 tdelt1 = t2-t1;
c30025f4: 0300056E LDW.D2T2 *+B14[5],B6
c30025f8: 0200046E LDW.D2T2 *+B14[4],B4
c30025fc: 0380076E LDW.D2T2 *+B14[7],B7
c3002600: 00004000 NOP 3
c3002604: 0210A5FA SUBU.L2 B5,B4,B5:B4
c3002608: CAE3 EXT.S2 B5,24,24,B6
c300260a: EB51 || SUB.L2 B7,B6,B5
c300260c: 02000E7F STW.D2T2 B4,*+B14[14]
c3002610: 0218A07A || ADD.L2 B5,B6,B4

以上是它的汇编语句。没有发现异常,而我此时将测试代码中*pda = 30这句改成test =30;也就是直接变量赋值,如下:

int test;
int *pda;
long long t1,t2,t3,t4,tover,tdelt1,tdelt2;
Int main()
{
pda= &test;
TSCH=0;
TSCL=0;
t1 = _itoll (TSCH, TSCL);
test = 30;
t2 = _itoll (TSCH, TSCL);
tdelt1 = t2-t1;
return 0;
}

此时调试发现tdelt1的值是6,也就是直接变量赋值花费的只有6个指令周期。这个差距也太大了。这里变量赋值的汇编语句是这样的:

27 t1 = _itoll (TSCH, TSCL);
c30025bc: 02A803E2 MVC.S2 TSCL,B5
c30025c0: 022C03E2 MVC.S2 TSCH,B4
c30025c4: 0280047E STW.D2T2 B5,*+B14[4]
c30025c8: 0200057E STW.D2T2 B4,*+B14[5]
28 test = 30;
c30025cc: 01800F28 MVK.S1 0x001e,A3
c30025d0: 0180017C STW.D2T1 A3,*+B14[1]
29 t2 = _itoll (TSCH, TSCL);
c30025d4: 02A803E2 MVC.S2 TSCL,B5
c30025d8: 022C03E2 MVC.S2 TSCH,B4
c30025dc: 0280067E STW.D2T2 B5,*+B14[6]
c30025e0: 0200077E STW.D2T2 B4,*+B14[7]
30 tdelt1 = t2-t1;
c30025e4: 0300056E LDW.D2T2 *+B14[5],B6
c30025e8: 0200046E LDW.D2T2 *+B14[4],B4
c30025ec: 0380076E LDW.D2T2 *+B14[7],B7
c30025f0: 00004000 NOP 3
c30025f4: 0210A5FA SUBU.L2 B5,B4,B5:B4
c30025f8: CAE3 EXT.S2 B5,24,24,B6
c30025fa: EB51 || SUB.L2 B7,B6,B5
c30025fc: E8001000 .fphead n, l, W, BU, nobr, nosat, 1000000
c3002600: 02000E7F STW.D2T2 B4,*+B14[14]

对此,不能理解,为何使用指针赋值时要花费这么长的时间,而变量赋值就这么短,这样下去指针都不能用了,请哪位大侠帮忙分析一下,是什么原因呢。?

Denny%20Yang99373:

可能是没开cache问题

把这个内存放到片上L2试试。

keven john:

回复 Denny%20Yang99373:

这是我的内存配置,我试过如果将Data Memory 选择为L2_RAM的话,变量赋值的指令周期不变,而指针赋值的那个语句的指令周期确实是缩短了,变成27,但是这个27还是变量赋值语句的好几倍。感觉这个应该不是片上内存和外部ddr引起的差别。

你说的cache没有打开是指什么,应该怎么配置它打开呢?


Denny%20Yang99373:

回复 keven john:

可以通过CCS的CLOCK工具,单步追一下汇编

看看是那行运行导致这么多个cycle

keven john:

回复 Denny%20Yang99373:

恩,我用你说的办法,查看了汇编代码,现在现象已经可以定位到,每次指令周期长都消耗在了

c30025d4: 0200026E LDW.D2T2 *+B14[2],B4 这样的汇编语句上。

就是每次从内存读取数据到寄存器这样的汇编语句,花费的在指令周期会很长。而普通变量赋值没有这个语句,直接是赋值给寄存器,然后寄存器写值到内存,这样的时间很快。

我用的是外设DDR。同时我片上内存也试过,片上内存时间差会小很多。

但是,只要包含这样的汇编语句,LDW.D2T2这种语句的赋值都会花费相对较多的时间,这个语句不就是从内存B14[2]的地方读值到B4寄存器吗,

同样的内存,为啥从内存读到寄存器会耗时很长,而从寄存器写值到内存确耗时很短呢?

这跟 ccs里面sysbios设置或者内存设置有什么关系吗?

Tony Tang:

keven johnInt main(){ pda= &test; TSCH=0; TSCL=0; t1 = _itoll (TSCH, TSCL); *pda = 30; t2 = _itoll (TSCH, TSCL); tdelt1 = t2-t1; return 0;}

观察第一句代码,在开始对pda赋值了,

注意观察两段汇编的区别,时间多在哪里。

第一段:

keven john28 *pda = 30;c30025d4: 0200026E LDW.D2T2 *+B14[2],B4c30025d8: DA93 MVK.S2 30,B5c30025da: 4C6E NOP 3c30025dc: E8000000 .fphead n, l, W, BU, nobr, nosat, 1000000c30025e0: 029002F6 STW.D2T2 B5,*+B4[0]

第二段:

keven john28 test = 30;c30025cc: 01800F28 MVK.S1 0x001e,A3c30025d0: 0180017C STW.D2T1 A3,*+B14[1]

第一段里先从堆栈取回pda的值放到B4,将30赋值给B5,再将B5的值赋值给B4指向的地址, 因为LDW指令的延时,所以加了3个NOP,才能把B5的值赋给真正的B4的地址。

而第二段代码里没有这个过程,因为这次不是赋值给pda,而是test,所以不需要从堆栈取值,直接将立即数赋值给没有用到的通用寄存器A3。

keven john:

回复 Tony Tang:

恩,对,您说的没有错,我也注意到了这个多出来的比较耗时的语句。但是我奇怪的是为什么这样的LDW的语句要花费这么长的时间,指针赋值相对直接立即数赋值要长上百倍的时间,在一个中断里面有大量的这样指针,那这个时间就要长好多了。我觉得不应该差距这么大,要是这样的话指针就不能随便用上了,理论上稍微多三四个指令周期,不应该多上百个以上的周期。这跟别的还有什么关系吗?

Tony Tang:

回复 keven john:

除了指令周期之外额外多出来的时间是在内存的stall,估计你目前的程序是跑在DDR上吧。

关于指令的说明请参况文档:sprufe8b.

keven john:

回复 Tony Tang:

恩,是的,我目前的程序是跑在外设ddr上面的。我试过我如果跑在omap的片上内存里面的话,确实不存在这么大的差距,基本消耗时间是一样的。由于我的程序数据量比较大,全设片上内存的话不够用,所以就跑在外部ddr了。

请问外部ddr2一般有什么设置可以调整这个问题的现象的吗?如果没有就只能把使用频率高的变量单独定义到内部内存了吧?

keven john:

回复 Tony Tang:

恩,好的,明白了,非常感谢你的回答。我去试试这种方式。

赞(0)
未经允许不得转载:TI中文支持网 » OMAPL138 平台用sysbios系统时指针赋值耗时很长的问题
分享到: 更多 (0)