本发明属于计算机程序引导方法领域,具体涉及一种用c语言编写dsp二级bootloader的方法。
背景技术:
dsp芯片,也称数字信号处理器,是一种适合于数字信号处理运算的cpu。在通信、控制、导航、图像处理等领域具有广泛应用。ti公司的dsp占据了全球绝大部分市场份额。
bootloader是硬件上的一个存储器,dsp的硬件bootloader只能在上电时从外部存储器搬运一小段代码到内存并开始执行,这一小段代码一般用来搬运更多的用户代码到内存,并跳转到用户代码的程序入口开始执行,这部分代码我们称之为二级bootloader。
二级bootloader除了负责搬运用户代码,一般还要负责初始化锁相环,存储器接口,通讯接口等,甚至完成复杂的硬件驱动程序。限于代码体积,此时不能建立c语言的运行环境,二级bootloader一般只能用汇编语言编写。
如果将c语言的运行比作软件程序的话,在二级bootloader上运行的程序就如同操作系统,在正常情况下,只有操作系统正常运行了,才能在操作系统上运行c语言的各种程序。
用汇编语言编写二级bootloader的程序难度大,可读性差;汇编语言的程序是需要提前烧写到硬件模块中的,因此灵活性差;另外由于不同厂家和不同型号dsp使用不同的汇编语言,因此当需要在不同dsp上执行功能类似的程序时,必须重新进行汇编编程,因而通用性差,编写和维护都很困难。
技术实现要素:
本发明针对现有技术的缺陷提供一种用c语言编写dsp二级bootloader的方法。
本发明是这样实现的:一种用c语言编写dsp二级bootloader的方法,包括
步骤一:指定程序入口
将main函数指定为程序的唯一入口,
步骤二:建立栈
建立栈时建立三个指针,一个为入口指针、一个为当前指针、一个为栈长度指针,
步骤三:栈的使用
栈第一次使用时,将入口指针地址赋予当前指针,然后在栈长度范围内使用栈。
如上所述的一种用c语言编写dsp二级bootloader的方法,其中,所述的步骤一中将main函数指定为程序唯一入口通过建立c_int00函数实现,该c_int00为c语言的基本函数,从c语言的运行支持库rts.lib中得到。
如上所述的一种用c语言编写dsp二级bootloader的方法,其中,所述的步骤二中每次使用指针时均向系统申请一个新的入口地址,该入口地址与入口指针匹配,根据需要使用地址的长度设定栈长度,该栈长度与栈长度指针匹配。
如上所述的一种用c语言编写dsp二级bootloader的方法,其中,所述的步骤三中在每次使用一个栈地址的情况下,栈长度增加一个单位长度。
如上所述的一种用c语言编写dsp二级bootloader的方法,其中,所有局部变量均存储在cpu的寄存器中。
本发明的效果是:(1)本方法仅涉及程序的读写控制,且用c语言编写,不涉及任何汇编语言,因而通用性强,几乎可以适用任何一个编译器。(2)本发明近适用局部变量、仅在cpu的缓存中设置栈,因而与任何程序的兼容性都很强,同时由于读写都在cpu的缓存中,因而读写速度快,程序执行效率高。(3)本发明只适用了main函数,所以程序入口的位置是唯一的,不会出现地址与程序不匹配的问题。
具体实施方式
一种用c语言编写dsp二级bootloader的方法,包括下述步骤:
步骤一:指定程序入口
将main函数指定为程序的唯一入口,即整个程序只有一个main函数,没有其他函数。
将main函数指定为程序唯一入口通过建立c_int00函数实现,该c_int00为c语言的基本函数,可以从c语言的运行支持库(rts.lib)中得到。
步骤二:建立栈
建立栈时建立三个指针,一个为入口指针、一个为当前指针、一个为栈长度指针。
每次使用指针时均向系统申请一个新的入口地址,该入口地址与入口指针匹配,根据需要使用地址的长度设定栈长度,该栈长度与栈长度指针匹配。
步骤三:栈的使用
栈第一次使用时,将入口指针地址赋予当前指针,即栈的开始,然后在栈长度范围内使用栈,在每次使用一个栈地址的情况下,栈长度均增加一个单位长度。因而保证了栈的长度理论上可以无限大,可以实现任意大小程序的读写要求。
为了更好的对本发明进行说明,下面首先介绍c语言段的概念。编译器生成的可重定位的代码块和数据块称为段。段是我们理解c/c++语言的一个重要概念。tms320c6000编译器产生如下几种类型的段:
1、c语言初始化的段:已初始化的段包含数据和可执行代码。
(1)text,存放c程序的代码;
(2)cinit,存放c程序中的全局变量、静态变量的初值;
(3)const,存放c程序中的字符常量、浮点常量和用const声明的常量;
(4)switch,存放c程序中switch语句的跳转表;
2、c语言未初始化的段:存储器中的保留空间,程序在运行时用它来创建和存储变量。
(1)bss,为c程序中全局变量和静态变量保留空间;
(2)far,为c程序中用far声明的全局变量和静态变量保留空间;
(3)stack,为c系统栈区保留空间;
(4)sysmem,为c系统堆区保留空间。
加载程序时只需要处理c语言初始化的段。包括text段,cinit段,const段,switch段。
c程序开始运行时,必须首先初始化c语言运行环境,这是通过c_int00函数来完成的,这个函数在运行支持库(rts.lib)中。连接器会将这个函数的入口地址放在复位中断向量中,使其可以在初始化时被调用。
c_int00()函数如下所示,首先完成了对栈顶指针的初始化,之后是初始化全局变量指针,之后调用_auto_init()和_args_main(),最后就是exit(1)函数。这三个函数可以在rts.lib中找到。
代码1、c_int00()函数
用c语言编写bootloader,最大的困难就是设计不需要c语言运行环境的c程序。为此我们需要限制c语言的使用。
一个程序不能没有代码段,text段显然是必需的。如果不用动态内存分配,那么system段就不需要;如果没有全局变量和静态变量,那么cinit、bss、far这三个段就不需要;如果不定义常量,那么const段就不需要;不用switch语句,switch段也不需要。最后就剩下了stack段了。
函数调用、局部变量,都要用到栈区。假设只有main函数,main函数的调用也要用到栈区,main函数中的变量也是局部变量,还是要用到栈区。stack段看上去是必需的,其实不是。其实这就被c语言的运行环境给限制住了。
假设我们只有main函数,我们把程序的入口指定为main函数,就不用初始化函数调用main函数了。再把所有局部变量指定到寄存器,这样就不会占用任何内存了。也就不需要栈区了。最后程序只生成代码段。只有代码段的c程序就不需要初始化c语言的运行环境了,这就是c语言编写bootloader的基础。总结如下:
1.程序不设置栈区、堆区;
2.程序不包含全局变量、静态变量;
3.程序只包含main()函数,没有其他函数;
4.指定main()函数作为程序的入口;
5.局部变量定义用register关键词修饰,放在cpu内部寄存器中,而不是任何存储空间中。
据此编写基本的bootloader例程如下所示,该程序只是二级bootloader的基本内容,用户可以按照上述原则添加特定的硬件驱动程序。代码十分简单,可读性高,修改维护简单。
代码2、bootloader例程。