【C28汇编语言杂谈】
大家都知道,C语言编程方便,可读性好,移植容易,有与硬件联系密切的特点,使用提供的头文件可以对CPU的内部寄存器及外围编程。通用性强。但编译器并非智能型的,对于C语言编译连接后所产生的机器码不尽相同,且一般很难达到最简,执行效率没有汇编高。
汇编语言,是用文字助记符来表示机器指令的符号语言,是最接近机器码的一种语言。其主要优点是占用资源少、程序执行效率高。但是不同的CPU,其汇编语言可能有所差异,所以不易移植。
现举个例子。在使用C28 CPU处理PID问题时,使用的PWM频率为50KHz,1200个时钟周期。程序中用了这样一句:
return (pp->Proportion * Error // 比例项
+pp->Integral * pp->SumError // 积分项
+pp->Derivative * dError // 微分项
);
使用CCS V5编译,在未使用优化时,编译后产生31行代码,并调用几个过程:
LCR #L$$TOFS
LCR #FS$$MPY
LCR #FS$$ADD
LCR #FS$$TOL
共9次。在调试时发现,仅此句就占用了数百个时钟,而处理整个PID过程在中断中占用1034个时钟,
在使用2级优化时,产生30行代码,上述的四个过程仍调用9次。
如果使用汇编语言编程,处理这个问题的时钟数也不会超过100个。
对一般C语句,CCS的处理效率还是很高的。如:
GpioCtrlRegs.GPAMUX1.all = 0x0000; // GPIO functionality GPIO0-GPIO15
编译后的汇编语言为:
MOVB ACC,#0
MOVW DP,#_GpioCtrlRegs+6
MOVL @_GpioCtrlRegs+6,ACC
如果接下去的C语句,是在同一个DP页,那么编译器将省掉MOVW DP, #xxx,效率将更高。 如:
GpioCtrlRegs.GPAMUX1.all = 0x0000;
GpioCtrlRegs.GPAMUX2.all = 0x0000;
GpioCtrlRegs.GPBMUX1.all = 0x0000;
GpioCtrlRegs.AIOMUX1.all = 0x0000;
GpioCtrlRegs.GPADIR.all = 0x0000;
GpioCtrlRegs.GPBDIR.all = 0x0000;
GpioCtrlRegs.AIODIR.all = 0x0000;
因为GpioCtrlRegs的寄存器组在同一数据段内,所以省去DP的重新装载。就是以下这样:
MOVB ACC,#0
MOVW DP,#_GpioCtrlRegs+6
MOVL @_GpioCtrlRegs+6,ACC对应GPAMUX1
MOVL @_GpioCtrlRegs+8,ACC ;对应GPAMUX2
MOVL @_GpioCtrlRegs+22,ACC ; 对应GPBMUX1
MOVL @_GpioCtrlRegs+54,ACC ;对应AIOMUX1
MOVL @_GpioCtrlRegs+10,ACC ;对应GPADIR
MOVL @_GpioCtrlRegs+26,ACC ; 对应GPBDIR
MOV @_GpioCtrlRegs+58,#0 ;对应AIODIR
以上可见,后续的一条C语句,仅用一句汇编指令完成,执行周期一个时钟!从这里我们可以想到,如果有很需要对寄存器操作的语句,尽量把它们放在一起,且,同一数据页的放在一起!这样就不会频繁使用数据页指针寄存器DP。
C28的数据页分配如下: