不知有多少搞嵌入式软件程序猿都是从main函数开始自己的第一行代码。遥想当年,第一次编写嵌入式软件代码还是在IAR的开发环境下写的,当时按照傻瓜式说明从安装开发IAR,配置开发环境到建立工程。还记得IAR自动生成了一个main.c文件,并且该文件中自动生成了voidmain();函数,只需在main函数中编写自己的代码,编译,烧录,调试,系统会自动从main函数的第一行开始运行,看到流水灯跑起来时的兴奋之情依然历历在目。很长一段时间均想当然的认为程序理所当然的应该从main函数开始运行啊。哎,现在想想真是soyoung so naïve啊~~~殊不知上电后从第一行代码到main函数第一行代码之间隔了十万八千里啊。有幸接触到DJYOS,那鄙人就在这里班门弄斧,谈谈DJYOS是怎么走完这十万八千里的吧,如有不当之处,请轻拍~~~
废话少说,从DJYOS官方提供的MCB1700工程为例。上电后CPU从启动地址处取出第一条指令开始运行(关于启动方式在这里就不展开了),MCB1700工程是将中断向量表放在启动地址处(这个在lds文件中指定,想想,貌似很多都是从中断向量表开始的)。
可以看出,上电之后首先给主栈指针赋值(msp_top也是在lds中指定的),接着就调用Init_Cpu函数。在Init_Cpu函数中初始化栈指针、时钟初始化等等,在这部分可能根据不同CPU需要初始化存储器、映射存储器、cache、mmu等。完成了这些,就可以加载代码了,将代码搬到运行地址去。
不得不说DJYOS加载代码蛮有特色的,它分为两个步骤,在正式加载之前,多了个预加载(Load_Preload),这么做据说是为了实现安全钩子,即某些紧急代码先于操作系统执行。想想工业控制领域,这个功能确实还蛮有用的,毕竟不同于消费电子产品,手机开机,来个十多秒没关系,可工业控制领域,恐怕有些还是吃不消的。废话少说,继续看代码~~~紧急代码包括critical.c以及中断相关的代码,在Load_Preload函数中将紧急代码搬到执行区之后,调用了Pre_Start函数,在该函数中依次初始化了准静态内存分配、异常组件以及中断模块(也就是操作系统加载之前就可以使用中断来处理一些紧急事情了)。接着就开始运行critical函