参考资料:
(1) SPRU514 ---- TMS320F28x Optimizing C/C++ Compiler User’s Guide.pdf;
(2) spru430d ---- TMS320C28x DSP CPU and Instruction Set Reference Guide;
(3) spru513c ---- TMS320C28x Assembly Language Tools User's Guide.
一、编写C语言能调用的.asm文件
以delay.asm为例:
1、将文件保存为.asm文件;
2、在文件中编写如下代码:
;*********************************************************************/
;* 鲍正华 */
;* 2010.07.09 */
;*********************************************************************/
;//###########################################################################
; @FunctionName: Delay_asm
;
; @Brief: 延时1s
;
; @Param: unsigned long cnt 传给 ACC
;
; @Return: 无
;//###########################################################################
.def _Delay_asm
.global _Delay_asm
.sect".delayasmpage"
_Delay_asm:
SUB ACC,#1 ;1 clk
BF _Delay_asm,GEQ ;4/4 clk, Loop if ACC >= 0
LRETR ;4 clk
;There is a 9/10 cycle overhead and each loop
;takes five cycles. The LoopCount is given by
;the following formula:
; DELAY_CPU_CYCLES = 9 + 5*LoopCount
; LoopCount = (DELAY_CPU_CYCLES - 9) / 5
; The macro DELAY_US(A) performs this calculation for you
;***********************************************************************/
; No more
;***********************************************************************/
3、在步骤2中:
.def _Delay_asm用来定义函数名;
.global _Delay_asm将函数名全局化,以便在C文件中能够调用;
.sect".delayasmpage"将函数定位到定义的段中,也可以是.text,可以灵活运用;
_Delay_asm:为函数标号,注意一定在前面加上下划线_否则C文件不能调用;
LRETR是函数返回,采用了RPC时必须用该指令。
4、在C文件中对函数原型进行声明:
extern void Delay_asm(unsigned long cnt);
5、在C 文件中以C语言形式调用汇编函数:
//延时1s
Delay_asm(18000000L);
6、上边的参数unsigned long cnt传递给了累加器ACC。
二、C语言调用汇编函数时的参数传递
参考(1) SPRU514 ---- TMS320F28x Optimizing C/C++ Compiler User’s Guide.pdf中的page168~169中的内容。
要点:
1、如果汇编语言中修改了XAR1、XAR2和XAR3的值,必须对它们进行保护:
;保存XAR1、XAR2、XAR3,以防程序修改, 若程序没有修改可以不用压栈保护
PUSH XAR1 ;1 clk
PUSH XAR2 ;1 clk
PUSH XAR3 ;1 clk
.
.
.
;恢复XAR1、XAR2、XAR3
POP XAR3 ;1 clk
POP XAR2 ;1 clk
POP XAR1 ;1 clk
2、16位参数从左至右依次传递给:AL、AH、XAR4、XAR5;
3、指针参数依次传递给:XAR4、XAR5,其它指针参数放到stack中;
4、32位的参数传递给累加器ACC(AH/AL),其它32位参数放到stack中。
例子:
(1)汇编代码:
;//###########################################################################
; @FunctionName: _Xintf_memcpy_asm
;
; @Brief: copy指定xintf
;
; @Param: dest_addr, src_addr, length
;
; @Return: 无
;//###########################################################################
.def _Xintf_memcpy_asm ;函数定义
.global _Xintf_memcpy_asm ;函数全局声明,以便C能够调用
.sect".xintfmemcpyasmpage" ;以下为代码段
_Xintf_memcpy_asm: ;标号必须从第1列开始,而汇编语言助记符不能从第1列开始
;保存XAR1、XAR2、XAR3,以防程序修改, 若程序没有修改可以不用压栈保护
;PUSH XAR1 ;1 clk
;PUSH XAR2 ;1 clk
;PUSH XAR3 ;1 clk
;copy指定区域(从XAR4指定区域copy到XAR5指定区域)
$1:
MOV AR6, *XAR5++ ;4 clk
MOV *XAR4++, AR6 ;1 clk
SUB ACC, #1 ;1 clk
BF $1, GT ;4/4 clk, 大于则跳转
;恢复XAR1、XAR2、XAR3
;POP XAR3 ;1 clk
;POP XAR2 ;1 clk
;POP XAR1 ;1 clk
LRETR ;4 clk, 程序返回
(2)C文件中对函数原型的声明:
extern void Xintf_memcpy_asm(unsigned int* dest_addr, unsigned int* src_addr, unsigned long length);
(3)C文件中以函数原型形式对汇编函数进行调用:
Xintf_memcpy_asm((unsigned int*)ZONE6ADDRESS, (unsigned int*)ZONE2ADDRESS, 102400L);
(4)这里参数传递过程是:ZONE6ADDRESS 传递给XAR4, ZONE2ADDRESS 传递给XAR5, 102400L 传递给ACC
三、C语言与汇编语言之间的变量引用
1、C语言引用汇编语言中定义的变量:
(1)访问在.bss段中定义的变量
汇编语言:
;变量定义,需要在变量前加下划线:_
.bss _var, 1
.global _var
C语言:
//变量声明,不要在变量前加下划线:_
extern unsigned int var;
//变量使用
var = 0x0006;
注意:在变量窗口中var表示变量地址0x 000080A3,要看变量的值,可以将该地址值0x000080A3输入到view memory中观看,其值为0x0006。
2、汇编语言引用C语言中定义的变量:
C语言:
//变量定义,不要在变量前加下划线:_
unsigned int asmdata;
//给变量赋值
asmdata = 0x0023;
汇编语言:
;变量引用,需要在变量前加下划线:_
.global _asmdata
;调用C中定义的变量
MOVL XAR6, #_asmdata ;将asmdata变量地址存于XAR6中
MOV AL, *XAR6 ;将变量asmdata值存于AL中
;重新给asmdata赋值
MOV *XAR6, #0x2222
MOV AL, *XAR6
注意:这里在变量窗口中可以直接观察变量asmdata的值0x2222。
3、汇编语言引用C语言中定义的数组:
C语言:
//数组定义并初始化,不要在变量前加下划线:_
unsigned int asm_var1[4] = {1,2,3,4};
汇编语言:
;变量引用,需要在变量前加下划线:_
.global _asm_var1
;调用C中定义的数组,将其首地址存到XAR7中
MOVL XAR7, #_asm_var1
;zone2
MOVL XAR4, #0x080000 ;将zone2起始地址存入XAR4
;4 words
MOV @AR0, #0x0000 ;zone2写长度计数存入AR0
;写zone2
LOOP1:
;写1
MOV AL, *XAR7++ ;1 clk
MOV *XAR4++, AL
;写2
MOV AL, *XAR7++ ;1 clk
MOV *XAR4++, AL
;写3
MOV AL, *XAR7++ ;1 clk
MOV *XAR4++, AL
;写4
MOV AL, *XAR7++ ;1 clk
MOV *XAR4++, AL
BANZ LOOP1, AR0-- ;4/2 clk
注意:运行结果如下,可见zone2依次写入了数据:1、2、3、4。