Cstyle的札记,Freertos内核详解,第4.2篇

    移植之前先认识下开发工具很重要,这里使用MDK(V5.16a)工具,默认使用Armcc,它能支持把c以及c++编译成arm或者是thumb机器码,支持以下的标准:ISO C 1990,ISO C 1999,ISO C++ 2003,ISO C++2011,默认输出格式是ELF格式,在编译结束之后可以转换成Hex格式烧进ROM。
    编译器支持在标准c,c++上提供一些GNU类似的扩展,支持使用不同的参数来选择使用不同的标准如:--c90,--strict,--c99,--cpp,--cp11等参数。还提供一些二进制格式的lib.例如最重要的部分就是标准C库和mircoC库,当然armcc库在标准库上面有一些扩展。
    下面说几个比较重要的部分,当然这些都是针对MDK以及arm架构而言的,其他的工具如gcc,iar机会也是类似的处理方法可以参考相关文档:
1.ARM处理器是如何跑第一条指令,以及如何跑到C语言的main方法当中去的呢.
2.main方法是不是必须的(不是)
3.main方法是否可以带参数(可以)
4.main方法是否可以退出,如何退出,退出之后程序会跑到哪里去(可以退出,被clib接管)

下面来逐个讨论:
1.arm的第一条指令跟x86一样都是进入到rest异常当中,不同的是x86会先进入实模式,arm却是在svc模式。这个时候c语言是不能运行的(因为c语言需要堆,栈来保存中间值和传递参数),所以这个时候我们需要做几件事情,这些一般都是用汇编来实现。
    a.最基本的初始化,时钟,模式等等,类似于EFI当中的SEC阶段,
    b.内存初始化,类似PEI阶段
    c.初始化堆栈
    d.调用C库的初始化
    e.由c库来调用main函数
    f.退出main或者其他
上代码:
                         AREA    RESET, CODE, READONLY  
Vectors         LDR     PC, Reset_Addr 
各种伪代码不解释,在表示是代码段,在链接脚本里面保证RESET在最前面被链接进去就行了,这样cpu就会在一上电就跳到Reset_Addr这个函数当中去,当然这个函数也是汇编写的。
接下来就是Reset_Addr表演了。这里不想说如何堆积arm指令和伪指令,也不想说如何初始化模式,clock,看门狗,内存,gpio等。
    在上面的各种初始化完了之后会调用一个__main函数,这个函数是c库函数,它会干以下几件事情:
  1. Copies non-root (RO and RW) execution regions from their load addresses to their execution addresses. Also, if any data sections are compressed, they are decompressed from the load address to the execution address.
  2. Zeroes ZI regions.
  3. Branches to __rt_entry.
    __rt_entry进去之后会干下面的几件事情:
  1. Sets up the stack and the heap by one of a number of means that include calling   __user_setup_stackheap(), calling   __rt_stackheap_init(), or loading the absolute addresses of scatter-loaded regions.
  2. Calls   __rt_lib_init()  to initialize referenced library functions, initialize the locale and, if necessary, set up argc and argv for   main().
    For C++, calls the constructors for any top-level objects by way of __cpp_initialize__aeabi_.
  3. Calls   main(), the user-level root of the application.
    From   main(), your program might call, among other things, library functions.
  4. Calls   exit()  with the value returned by   main().
   
通过上面的解释我们就可以明白了,处理器是如何执行第一条指令,下面我们要实际来编写汇编指令,实现对板子上的sdram的初始化,以及堆栈初始化,至于为何要这么做,原因在于freertos需要使用到堆来动态分配存储空间,所以我们先来做这一部分。


参考: http://www.keil.com/support/man/docs/armlib/armlib_chr1358938930116.htm
http://www.keil.com/support/man/docs/armlib/armlib_chr1358938929242.htm

转载请注明出处
[email protected]  //   http://blog.csdn.net/CStyle_0x007


你可能感兴趣的:(Freertos内核详解)