[转载] TMS320F240学习及ucOSII移植心得(转贴)
虽然240芯片有些老了,但作者写的这篇文章的价值还是很大的,在此对作者表示感谢,如果有机会结交的话更好了.以下仅是原文的一部分:
该芯片汇编的细节应用,
1.对形如:y=a1*x1+a2*x2+a3*x3的多项式编程,240指令的装载临时寄存器的指令有LT、LTD、LTP、LTA、LTS,乘法指令有MPY、MPYS、MPYA、MPYU,这些指令中有很多可以同时执行几步,如果能巧妙的结合利用,程序很简洁、效率很高.还有块移动指令,它们和流水线有关,所以效率很高.
2.程序中有这么两句:
MPY #7FFBH
MPYA #0H
我看不出有问题,而且和书上是一模一样的呀.我就查软件中的帮助,发现原来书上用错了!那个错误实在是非常容易犯的!对MPY #k指令,*作数为立即数时为只能是 “13-bit short immediate value”.对MPYA指令根本就没有立即数寻址方式,只有直接或间接寻址方式.
3、寄存器问题.如等待状态发生寄存器WSGR在IO空间中,对它赋值就要用out指令而不是常用的splk.还有如COMCON,要配置为PWM模式,为保证全比较单元的正确操作,需要对它连续两次写操作.还有时钟控制寄存器CKCR0、CKCR1,编程时,必须先使CKCR0的CLKMD1=0,禁止PLL,然后根据要求设置CKCR1设置其他位,最后使CLKMD1=1,允许PLL工作(如果使用PLL的话).还有定时器的控制寄存器TxCON有时也需要写两次,第一次配置,第二次启动.总之,对一些需要比较“特殊”的做法,如果注意总结会对整体有个清晰的把握.
硬件中断、软件中断两种中断只是汇编中普通的中断,现在知道了可以用任何一个软中断的.
4、c编程问题:
1.cmd文件写法可以参照CC‘C2000帮助文件中的例子,还可以查阅TI文档spru024D的2.8.3.
2.寄存器映射地址头文件,和汇编中的不同,要重新定义,定义方法如下:
#define CKCR0 (volatile unsigned int *) 0x702B
使用方法: *CKCR0=0x0041;
5、中断向量表的第一条语句应该跳转到_c_int0对于这点我最初不是很明白,因为我看到的程序都是以main开始的.后来逐渐明白了,_c_int0是程序真正开始的地方,只是这个开始不是开发者写出来的,而是编译器自动为我们做好的,你要配合它做的是就是在Build Option中对linker的C Initialization的选项选择ROM Autoinitialization Model或RAM Autoinitialization Model,而不是汇编中的No Autoinitialization,开发者的程序要以main函数开始,初始化结束后会跳转到main函数.在反汇编代码中可以看到这些过程.两种初始化的方式详见上面文档的同一节.
6、比较难的是C调用汇编函数,汇编函数的写法.这时要在汇编函数的开始和结束加入一些语句.C中用三个寄存器管理堆栈和局部帧:AR1作为堆栈指针SP,AR0作为帧指针FP,AR2最为局部变量指针LVP.调用函数时当前指针必须为AR1,首先要在软件堆栈中保存函数返回地址、FP,分配局部帧空间,空间的大小是局部变量的个数加1,如果被调函数中可能修改寄存AR6、AR7,也要保存(当编译器优化时它们被用作保存寄存器变量).函数实现过程中注意调用它的函数传递的参数的存放次序:从右到左按照堆栈增长的方向放置.函数退出时和进入函数时的操作相反.这个规则的原因也可以从生成的交叉列表中找到答案,和上面的原因大同小异,C语句编译后的汇编代码可以看出在任何一个函数调用前都会有这样的“保存”工作,结束时做相应的恢复.详见spru024D的4.2.2,4.2.4和4.3节.
7、在UCOS中的中断编程和一般的中断编程稍有不同.共同的是:
1.中断矢量表.中断矢量表一定要定位在程序空间的地址0开始的地方,0000h~003Fh为中断矢量.第0 行跳转到代码开始的地方、第1到第6行是硬件中断跳转指令,除NMI中断其他是软件中断指令(INTk最大为INT31).发生硬件中断后,处理器自动到前面查表跳转到相应位置.软件中断是在程序中执行了INTk指令才会发生,然后根据x查中断矢量表跳转到相应的ISR(移植系统时用到了软件中断指令,即任务切换函数).
8.volatile类型限定符.用它修饰的对象叫易变对象,用于告诉编译程序它所修饰的对象(可以是变量或常量)的值可能会以程序中未显式指定的方式发生变化,即不是由程序中的赋值、初始化等显式指定的方式发生变化.如,其变化可能式由中断程序或IO端口所施加的.再如,在程序中可能会把某个全局变量的地址传送给*作系统的时钟并用于存放系统的实际时间,尽管程序中没有对这个变量使用赋值语句赋值,但它的内容还是变了.举个例子:
volatile int ticks;
interrupt timer( )
{
ticks++;
}
wait (int time)
{
ticks = 0;
while (ticks < time ) ;
}
如果ticks没有声明为易失变量,编译程序可能会把它当作寄存器变量分配,从而wait函数执行永远不会中止.
上例中的interrupt 关键字是修饰中断函数的,表示改函数与中断相联系.
文章评论(0条评论)
登录后参与讨论