ARM 之九 Cortex-M/R 內核啓動過程 / 程序啓動流程(基於ARMCC、Keil)

內核規範

  ARM Cortex-M/R 內核的復位啓動過程也被稱爲復位序列(Reset sequence)。ARM Cortex-M/R內核的復位啓動過程與其他大部分CPU不同,也與之前的ARM架構(ARM920T、ARM7TDMI等)不相同。大部分CPU復位後都是從 0x00000000 處取得第一條指令開始運行的,然而在ARM Cortex-M/R內核中並不是這樣的。其復位序列爲:

  1. 從地址 0x0000_0000 處取出 MSP 的初始值;
  2. 從地址 0x0000_0004 處取出PC的初始值,然後從這個值對應的地址處取指。事實上,地址 0x00000004 開始存放的就是默認中斷向量表
    在這裏插入圖片描述
    ARM Cortex-M/R 內核的中斷向量表佈局情況如下圖所示:
    在這裏插入圖片描述

注意:中斷向量表的位置可以改變,此處是默認情況下的設置。

  在 ARM Cortex-M/R 內核中,發生異常後,並不是去執行中斷向量表中對應位置處的代碼,而是將對應位置處的數據存入PC中,然後去此地址處進行取指。簡而言之,在ARM Cortex-M/R的中斷向量表中不應該放置跳轉指令,而是該放置 ISR 程序的入口地址。另外還有兩個細節問題需要注意:

  1. 0x00000000 處存放的 MSP 初始值最低三位需要是 0;
  2. 0x00000004 處存放的地址最低位必須是 1。

  第一條是因爲在ARM上編程,但凡涉及到調用,就需要遵循一套規約AAPCS ——《Procedure Call Standard for the ARM Architecture》。AAPCS 中對棧使用的約定是這樣的:

5.2.1.1
Universal stack constraints
At all times the following basic constraints must hold:
Stack-limit < SP <= stack-base. The stack pointer must lie within the extent of the stack.
SP mod 4 = 0. The stack must at all times be aligned to a word boundary.
5.2.1.2
Stack constraints at a public interface
The stack must also conform to the following constraint at a public interface:
SP mod 8 = 0. The stack must be double-word aligned.

簡而言之,規約規定棧任何時候都必須 4 字節對齊,在調用入口需8字節對齊,而且 SP 的最低兩位在硬件上就被置爲 0 了。
  第二條與 ARM 模式與 Thumb 模式有關。ARM 中 PC 中的地址必須是 32 位對齊的,其最低兩位也被硬件上置 0 了,故寫入PC 中的數據最低兩位並不代表真實的取址地址。ARM中使用最低一位來判斷這條指令是 ARM 指令還是 Thumb 指令,若最低位爲 0,代表 ARM 指令;若最低位爲 1,代表 Thumb 指令。在 Cortex-M/R 內核中,並不支持 ARM 模式,若強行切換到 ARM 模式會引發一個 Hard Fault。

啓動流程

  嵌入式應用程序在用戶定義的 main() 函數啓動之前需要初始化序列。 這稱爲啓動代碼或啓動代碼。 ARM C 庫包含啓動應用程序所必需的預編譯和預組裝代碼段。鏈接應用程序時,鏈接器會根據應用程序從 C 庫中包含必要的代碼,以便爲應用程序創建自定義啓動代碼。但需要注意的是,ARM 自己的編譯套件提供瞭如下三種庫:
在這裏插入圖片描述
根據ARM官方的文檔說明,以下分析描述的啓動代碼適用於標準 ARM C 庫。 它不適用於 ARM C 微庫。 啓動流程同樣適用於 ARMv4T 及更高版本的架構。如下圖清晰的表示了程序啓動到用戶的main() 之前的流程:
在這裏插入圖片描述

__main

  函數__main是C庫的入口點。 除非您更改它,否則__main是ARM鏈接器(armlink)在創建映像時使用的ELF映像的缺省入口點。 下圖顯示了C庫啓動期間__main調用的函數。
在這裏插入圖片描述

__scatterload

  Application code and data can be in a root region or a non-root region. Root regions have the same load-time and execution-time addresses. Non-root regions have different load-time and execution-time addresses. The root region contains a region table output by the ARM linker.應用程序代碼和數據可以位於根區域或非根區域中。 根區域具有相同的加載時間和執行時間地址。 非根區域具有不同的加載時間和執行時間地址。 根區域包含ARM鏈接器輸出的區域表。
  The region table contains the addresses of the non-root code and data regions that require initialization. The region table also contains a function pointer that indicates what initialization is needed for the region, for example a copying, zeroing, or decompressing function. region表包含需要初始化的非根代碼和數據區域的地址。 區域表還包含一個函數指針,指示區域需要初始化,例如複製,歸零或解壓縮功能。
__scatterload遍歷區域表並初始化各種執行時區域。 功能如下:

  • Initializes the Zero Initialized (ZI) regions to zero
  • Copies or decompresses the non-root code and data region from their load-time locations to the execute-time regions.

__main always calls this function during startup before calling __rt_entry .

__rt_entry

  __main調用__rt_entry來初始化堆棧,堆和其他C庫子系統。__rt_entry調用各種初始化函數,然後調用用戶級main()。以下列出了_rt_entry可以調用的函數。 這些函數按它們被調用的順序列出:

  1. _platform_pre_stackheap_init
  2. __user_setup_stackheap or setup the Stack Pointer (SP) by another method
  3. _platform_post_stackheap_init
  4. __rt_lib_init
  5. _platform_post_lib_init
  6. main()
  7. exit()

platform *函數不是標準C庫的一部分。 如果你定義它們,則鏈接器會在__rt_entry中對它們進行調用。
main()是用戶級應用程序的入口點。 寄存器r0r1包含main()的參數。 如果main()返回,則將其返回值傳遞給exit()並退出應用程序。
__rt_entry還負責設置堆棧和堆。 但是,設置堆棧和堆取決於用戶指定的方法。 可以通過以下任何方法設置堆棧和堆:

  • 調用__user_setup_stackheap。 這也獲得了堆使用的內存邊界(堆頂部和堆基)。
  • 使用符號__initial_sp的值加載 SP。
  • Using the top of the ARM_LIB_STACK or ARM_LIB_STACKHEAP region specified in the linker scatter file.

  __rt_entry and __rt_lib_init do not exist as complete functions in the C library. Small sections of these functions are present in several internal objects that are part of the C library. Not all of these code sections are useful for a given user application. The linker decides which subset of those code sections are needed for a given application, and includes just those sections in the startup code. The linker places these sections in the correct order to create custom __rt_entry and __rt_lib_init functions as required by the user application.__rt_entry和__rt_lib_init在C庫中不作爲完整函數存在。這些函數的小部分存在於作爲類庫一部分的幾個內部對象中。並非所有這些代碼段都對給定的用戶應用程序有用。鏈接器決定給定應用程序需要這些代碼段的哪個子集,並且只在啓動代碼中包含這些部分。鏈接器按照正確的順序放置這些部分,以便根據用戶應用程序的要求創建自定義的__rt_entry和__rt_lib_init函數。

_platform_pre_stackheap_init

  The standard C library does not provide this function but you can define it if you require it. You can use this function to setup hardware for example. __rt_entry calls this function, if you define it, before the code that initializes the stack and heap. 標準C庫不提供此函數,但您可以根據需要定義它。 例如,您可以使用此函數設置硬件。如果您定義了該函數,那麼`__rt_entry會在初始化堆棧和堆的代碼之前調用此函數。

__user_setup_stackheap

  This function enables you to setup and return the location of the initial stack and heap. The C library does not provide this function but you can define it if you require it. __rt_entry calls this function if you define it or if you define the legacy function __user_initial_stackheap . If you define __user_initial_stackheap , then the C library provides a default __user_setup_stackheap as a wrapper around your __user_initial_stackheap function. 此函數使您可以設置並返回初始堆棧和堆的位置。C庫不提供此函數,但您可以根據需要定義它。 如果你定義了該函數或者定義了老版本的函數__user_initial_stackheap,那麼__rt_entry 會調用此函數。 如果定義了__user_initial_stackheap,則C庫提供默認的__user_setup_stackheap作爲__user_initial_stackheap函數的包裝器。

_platform_post_stackheap_init

  The C library does not provide this function but you can define it if you require it. You can use this function to setup hardware for example. __rt_entry calls this function, if you define it, after the code that initializes the stack and heap. C庫不提供此功能,但您可以根據需要定義它。 例如,您可以使用此功能設置硬件。 如果您定義了該函數,那麼__rt_entry會在初始化堆棧和堆的代碼之後調用此函數。

__rt_lib_init

  This function initializes the various C library subsystems. It initializes the referenced library functions, initializes the locale and, if necessary, sets up argc and argv for main() . __rt_entry calls this function always during startup.此函數初始化各種C庫子系統。 它初始化引用的庫函數,初始化語言環境,並在必要時爲main()設置 argc 和 argv。 __rt_entry在啓動期間始終調用此函數。
  If you use the __user_setup_stackheap or __user_initial_stackheap functions to setup the stack pointer and heap, then the start and end address of the heap memory block are passed as arguments to __rt_lib_init in registers r0 and r1 respectively.如果使用了函數__user_setup_stackheap 或函數 __user_initial_stackheap來設置堆棧指針和堆,那麼堆內存塊的起始和結束地址將作爲參數通過寄存器 r0 和 r1傳遞給__rt_lib_init。
  The function returns argc and argv in registers r0 and r1 respectively if the user-level main() requires them. 如果用戶級main()需要,該函數分別在寄存器 r0 和 r1 中返回argc和argv。

The linker includes various initialization code sections from the internal object files to create a custom __rt_lib_int function. The linker places a function in __rt_lib_init only if it is needed by the application. This lists the functions that _rt_lib_init can call. The functions are listed in the order they get called:鏈接器包括內部對象文件中的各種初始化代碼部分,以創建自定義__rt_lib_int函數。 只有在應用程序需要時,鏈接器纔會在__rt_lib_init中放置一個函數。 以下列出了_rt_lib_init可以調用的函數。 這些函數按它們被調用的順序列出:

  1. _fp_init
  2. _init_alloc
  3. _rand_init
  4. _get_lc_collate
  5. _get_lc_ctype
  6. _get_lc_monetary
  7. _get_lc_numeric
  8. _get_lc_time
  9. _atexit_init
  10. _signal_init
  11. _fp_trap_init
  12. _clock_init
  13. _getenv_init
  14. _initio
  15. _ARM_get_argv
  16. _alloca_initialize
  17. _ARM_exceptions_init
  18. _cpp_initialize__aeabi

這裏就不一一介紹各函數了,想進一步瞭解的去查看官方文檔即可!

_platform_post_lib_init

  The C library does not provide this function but you can define it if you require it. You can use this function to setup hardware for example. __rt_entry calls this function, if you define it, after the call to __rt_lib_init and before the call to the user-level main() function. C庫不提供此功能,但您可以根據需要定義它。 例如,您可以使用此功能設置硬件。 如果定義了該函數,那麼__rt_entry在調用__rt_lib_init之後和調用用戶級main()函數之前,調用此函數。

ARM 庫分析

  上面介紹了各函數,這些函數全部位於 ARM 提供的 C 庫中。我們可以參看任意項目的map文件,來看看都用了哪些庫,如下:
在這裏插入圖片描述
其中,左側的圖爲 Image Symbol Table 部分;右側圖爲 Image component sizes 部分。從中可以看到:

  1. __main 位於 __main.o 中
  2. __scatterload 位於 __scatter.o 中

其他函數同理,這裏暫不說明。在右側可以看到,對應的 C 庫文件爲c_w.lfz_wm.l 。我們可以在 ARM 編譯套件的目錄下找到這兩個文件,路徑如下圖所示:
在這裏插入圖片描述
下面我們使用 ARM 編譯套件中相應的工具來看看具體文件。關於編譯套件的詳細使用說明可以參考博文《ARM 之 主流編譯器(armcc、iar、gcc for arm)詳細介紹》。具體使用的工具就是armar.exe,這是 ARM 的庫文件管理工具。

D:\ARM\ARM_Compiler_5.06u4>armar --zt ./lib/armlib/c_w.l

      Code    RO Data    RW Data    ZI Data      Debug   Object Name
        48          0          0          0         84   version.o
        58          0          0          0         68   __dczerorl.o
        90          0          0          0         68   __dczerorl2.o
       100          0          0          0         68   __dclz77c.o
         0          0         28          0          0   dc.o
       102         12          0          0        240   sys_io.o
        18          0          0          0         76   sys_tmpnam.o
        14          0          0          0         76   sys_wrch.o
        18          0          0          0         76   sys_system.o
        18          0          0          0         76   sys_remove.o
        32          0          0          0         80   sys_rename.o
        24          0          0          0         76   sys_command.o
         4          0          0          0         68   getenv.o
        32          0          4          0         84   sys_clock.o
        18          0          0          0         76   sys_time.o
        12          0          0          0         68   sys_exit.o
         8          0          0         96         68   libspace.o
         2          0          0          0         68   use_semi.o
         2          0          0          0         68   use_no_semi.o
         4          0          0          0         68   mutex_dummy.o
         2          0          0          0         68   use_no_semi_2.o
         0          0          0          0          0   indicate_semi.o
        48          0          0          0         80   sys_stackheap.o
        74          0          0          0         80   sys_stackheap_outer.o
        96          0          0          0          0   tempstk.o
         0          0          0          0          0   __rtentry.o
        32         40          0          0          0   __rtentry2.o
         4          8          0          0          0   __rtentry3.o
         6          8          0          0          0   __rtentry4.o
         8         24          0          0          0   __rtentry5.o
         8         24          0          0          0   __rtentry6.o
		............省略一大部分...........
         0          0          0          0          0   maybefptrapshutdown1.o
         0          0          0          0          0   maybefptrapshutdown2.o
        16          0          0          0         76   fptrapshutdown.o
         8          0          4          0         68   _signgam.o
        22          0          0          0        100   _rserrno.o
        18          0          0          0         76   isalnum.o
        18          0          0          0         76   isalpha.o
        18          0          0          0         76   iscntrl.o
        24          0          0          0         76   isdigit.o
        18          0          0          0         76   isgraph.o
        18          0          0          0         76   islower.o
        18          0          0          0         76   isprint.o
        18          0          0          0         76   ispunct.o
        18          0          0          0         76   isspace.o
        18          0          0          0         76   isupper.o
        22          0          0          0         76   isxdigit.o
        26          0          0          0         76   tolower.o
        30          0          0          0         76   toupper.o
       172       4490          0          0        164   wclass.o
        12          0          0          0         76   iswalnum.o
        12          0          0          0         76   iswalpha.o
        12          0          0          0         76   iswblank.o
        12          0          0          0         76   iswcntrl.o
        12          0          0          0         76   iswgraph.o
        12          0          0          0         76   iswprint.o
        12          0          0          0         76   iswpunct.o
         4          0          0          0         68   iswspace.o
        12          0          0          0         76   iswlower.o
        12          0          0          0         76   iswupper.o
        12          0          0          0         76   iswdigit.o
        12          0          0          0         76   iswxdigit.o
       148        888          0          0        152   towlower.o
       156        948          0          0        152   towupper.o
       356          0          0          0         92   wctype.o
        64          0          0          0         92   wctrans.o
        12          0          0          0         76   _iswspace.o
        86          0          0          0        136   _small_iswspace.o
       100          0          0          0         76   wclass_c.o
        10          0          0          0         68   towlower_c.o
        10          0          0          0         68   towupper_c.o
        32          0          0          0         76   isblank.o
        24          0          0          0         84   printf.o
        12          0          0          0         68   vprintf.o
        20          0          0          0         84   fprintf.o
        10          0          0          0         68   vfprintf.o
        44          0          0          0         84   sprintf.o
        36          0          0          0         76   vsprintf.o
        56          0          0          0         88   snprintf.o
        52          0          0          0         80   vsnprintf.o
        24          0          0          0         84   wprintf.o
        12          0          0          0         68   vwprintf.o
        20          0          0          0         84   fwprintf.o
        10          0          0          0         68   vfwprintf.o
        72          0          0          0         92   swprintf.o
        72          0          0          0         80   vswprintf.o
        54          0          0          0         92   asprintf.o
        56          0          0          0         96   vasprintf.o
        54          0          0          0         92   __ARM_asprintf.o
        56          0          0          0         96   __ARM_vasprintf.o
        56          0          0          0         88   __ARM_snprintf.o
        52          0          0          0         80   __ARM_vsnprintf.o
        24          0          0          0         84   _printf.o
        12          0          0          0         68   _vprintf.o
        20          0          0          0         84   _fprintf.o
        10          0          0          0         68   _vfprintf.o
        44          0          0          0         84   _sprintf.o
        36          0          0          0         76   _vsprintf.o
        56          0          0          0         88   _snprintf.o
        52          0          0          0         80   _vsnprintf.o
        24          0          0          0         84   _wprintf.o
        12          0          0          0         68   _vwprintf.o
        20          0          0          0         84   _fwprintf.o
        10          0          0          0         68   _vfwprintf.o
        72          0          0          0         92   _swprintf.o
        72          0          0          0         80   _vswprintf.o
        54          0          0          0         92   _asprintf.o
        56          0          0          0         96   _vasprintf.o
        54          0          0          0         92   ___ARM_asprintf.o
        56          0          0          0         96   ___ARM_vasprintf.o
        56          0          0          0         88   ___ARM_snprintf.o
        52          0          0          0         80   ___ARM_vsnprintf.o
        24          0          0          0         84   __0printf.o
        12          0          0          0         68   __0vprintf.o
        20          0          0          0         84   __0fprintf.o
        10          0          0          0         68   __0vfprintf.o
        44          0          0          0         84   __0sprintf.o
        36          0          0          0         76   __0vsprintf.o
        56          0          0          0         88   __0snprintf.o
        52          0          0          0         80   __0vsnprintf.o
        24          0          0          0         84   __0wprintf.o
        12          0          0          0         68   __0vwprintf.o
        20          0          0          0         84   __0fwprintf.o
        10          0          0          0         68   __0vfwprintf.o
        72          0          0          0         92   __0swprintf.o
        72          0          0          0         80   __0vswprintf.o
        54          0          0          0         92   __0asprintf.o
        56          0          0          0         96   __0vasprintf.o
        54          0          0          0         92   __0__ARM_asprintf.o
        56          0          0          0         96   __0__ARM_vasprintf.o
        56          0          0          0         88   __0__ARM_snprintf.o
        52          0          0          0         80   __0__ARM_vsnprintf.o
        24          0          0          0         84   c89printf.o
        12          0          0          0         68   c89vprintf.o
        20          0          0          0         84   c89fprintf.o
        10          0          0          0         68   c89vfprintf.o
        44          0          0          0         84   c89sprintf.o
        36          0          0          0         76   c89vsprintf.o
        56          0          0          0         88   c89snprintf.o
        52          0          0          0         80   c89vsnprintf.o
        24          0          0          0         84   c89wprintf.o
        12          0          0          0         68   c89vwprintf.o
        20          0          0          0         84   c89fwprintf.o
        10          0          0          0         68   c89vfwprintf.o
        72          0          0          0         92   c89swprintf.o
        72          0          0          0         80   c89vswprintf.o
        54          0          0          0         92   c89asprintf.o
        56          0          0          0         96   c89vasprintf.o
        54          0          0          0         92   c89__ARM_asprintf.o
        56          0          0          0         96   c89__ARM_vasprintf.o
        56          0          0          0         88   c89__ARM_snprintf.o
        52          0          0          0         80   c89__ARM_vsnprintf.o
        24          0          0          0         84   __2printf.o
        12          0          0          0         68   __2vprintf.o
        20          0          0          0         84   __2fprintf.o
        10          0          0          0         68   __2vfprintf.o
        44          0          0          0         84   __2sprintf.o
        36          0          0          0         76   __2vsprintf.o
        56          0          0          0         88   __2snprintf.o
        52          0          0          0         80   __2vsnprintf.o
        24          0          0          0         84   __2wprintf.o
        12          0          0          0         68   __2vwprintf.o
        20          0          0          0         84   __2fwprintf.o
        10          0          0          0         68   __2vfwprintf.o
        72          0          0          0         92   __2swprintf.o
        72          0          0          0         80   __2vswprintf.o
        54          0          0          0         92   __2asprintf.o
        56          0          0          0         96   __2vasprintf.o
        54          0          0          0         92   __2__ARM_asprintf.o
        56          0          0          0         96   __2__ARM_vasprintf.o
        56          0          0          0         88   __2__ARM_snprintf.o
        52          0          0          0         80   __2__ARM_vsnprintf.o
        24          0          0          0         84   __1printf.o
        12          0          0          0         68   __1vprintf.o
        20          0          0          0         84   __1fprintf.o
        10          0          0          0         68   __1vfprintf.o
        44          0          0          0         84   __1sprintf.o
        36          0          0          0         76   __1vsprintf.o
        56          0          0          0         88   __1snprintf.o
        52          0          0          0         80   __1vsnprintf.o
        24          0          0          0         84   __1wprintf.o
        12          0          0          0         68   __1vwprintf.o
        20          0          0          0         84   __1fwprintf.o
        10          0          0          0         68   __1vfwprintf.o
        72          0          0          0         92   __1swprintf.o
        72          0          0          0         80   __1vswprintf.o
        54          0          0          0         92   __1asprintf.o
        56          0          0          0         96   __1vasprintf.o
        54          0          0          0         92   __1__ARM_asprintf.o
        56          0          0          0         96   __1__ARM_vasprintf.o
        56          0          0          0         88   __1__ARM_snprintf.o
        52          0          0          0         80   __1__ARM_vsnprintf.o
		............省略一大部分...........
       104          0          0          0         84   __printf.o
        78          0          0          0        108   _printf_pad.o
        36          0          0          0         84   _printf_truncate.o
        82          0          0          0         80   _printf_str.o
       178          0          0          0         88   _printf_intcommon.o
       120          0          0          0         92   _printf_dec.o
        40          0          0          0         68   _printf_charcount.o
      1050          0          0          0        216   _printf_fp_dec.o
       764         38          0          0        100   _printf_fp_hex.o
        48          0          0          0         96   _printf_char_common.o
        10          0          0          0         68   _sputc.o
        16          0          0          0         68   _snputc.o
       128          0          0          0         84   _printf_fp_infnan.o
        40          0          0          0         84   __printf_nopercent.o
        44          0          0          0        108   _printf_char.o
        36          0          0          0         80   _printf_char_file.o
        64          0          0          0         84   _printf_char_file_locked.o
       188          8          0          0         92   _printf_wctomb.o
       144          8          0          0         88   _printf_mbtowc.o
        48          0          0          0         96   _printf_wchar_common.o
        16          0          0          0         68   _snputwc.o
        44          0          0          0        108   _printf_wchar.o
        86          0          0          0         80   _printf_wc.o
        36          0          0          0         80   _printf_wchar_file.o
        64          0          0          0         84   _printf_wchar_file_locked.o
       124          0          0          0         92   _printf_longlong_dec.o
       160          0          0          0         84   _printf_fp_infnan_snan.o
        84          0          0          0         80   _printf_oct_ll.o
        80          0          0          0         88   _printf_oct_int.o
       112          0          0          0        124   _printf_oct_int_ll.o
        92         40          0          0         88   _printf_hex_ll.o
        88         40          0          0         88   _printf_hex_int.o
       124         40          0          0        140   _printf_hex_int_ll.o
        84         40          0          0         88   _printf_hex_ptr.o
       124         40          0          0        144   _printf_hex_int_ptr.o
       120         40          0          0        124   _printf_hex_ll_ptr.o
       148         40          0          0        160   _printf_hex_int_ll_ptr.o
       148         17          0          0         84   __printf_flags.o
       184          0          0          0         84   __printf_ss.o
       236         17          0          0         88   __printf_flags_ss.o
       284          0          0          0        156   __printf_wp.o
       326         17          0          0        160   __printf_flags_wp.o
       366          0          0          0        156   __printf_ss_wp.o
       406         17          0          0        160   __printf_flags_ss_wp.o
         6          0          0          0          0   _printf_c.o
         6          0          0          0          0   _printf_s.o
         6          0          0          0          0   _printf_n.o
         6          0          0          0          0   _printf_x.o
         6          0          0          0          0   _printf_p.o
         6          0          0          0          0   _printf_o.o
         6          0          0          0          0   _printf_i.o
         6          0          0          0          0   _printf_d.o
         6          0          0          0          0   _printf_u.o
         6          0          0          0          0   _printf_f.o
         6          0          0          0          0   _printf_e.o
         6          0          0          0          0   _printf_g.o
         6          0          0          0          0   _printf_a.o
         0          0          0          0          0   _printf_percent.o
         4          0          0          0          0   _printf_percent_end.o
         6          0          0          0          0   _printf_lli.o
         6          0          0          0          0   _printf_lld.o
         6          0          0          0          0   _printf_llu.o
        10          0          0          0          0   _printf_ll.o
        10          0          0          0          0   _printf_l.o
         6          0          0          0          0   _printf_lc.o
         6          0          0          0          0   _printf_ls.o
         6          0          0          0          0   _printf_llo.o
         6          0          0          0          0   _printf_llx.o
        32          0          0          0         84   scanf.o
        24          0          0          0         84   fscanf.o
        60          0          0          0         84   sscanf.o
        24          0          0          0         80   vscanf.o
        16          0          0          0         80   vfscanf.o
        52          0          0          0         80   vsscanf.o
        60          0          0          0         84   swscanf.o
        52          0          0          0         80   vswscanf.o
        52          0          0          0         80   __ARM_vsscanf.o
        32          0          0          0         84   scanfn.o
        24          0          0          0         84   fscanfn.o
        60          0          0          0         84   sscanfn.o
		............省略一大部分...........
        16          0          0          0         80   vfwscanf.o
        28          0          0          0         68   _chval.o
       884          0          0          0        100   _scanf.o
       342          0          0          0        100   _scanf_longlong.o
       332          0          0          0         96   _scanf_int.o
       224          0          0          0         96   _scanf_str.o
      1202          0          0          0        216   scanf_fp.o
         0          0          0          0          0   scanf_nofp.o
       800          0          0          0        100   scanf_hexfp.o
        44          0          0          0         84   scanf_char.o
        64          0          0          0         84   _sgetc.o
        26          0          0          0         80   atoi.o
        26          0          0          0         80   atol.o
        26          0          0          0         80   atoll.o
       308          0          0          0        100   scanf_infnan.o
        24          0          0          0         68   scanf_char_file.o
        64          0          0          0         84   scanf_char_file_locked.o
		............省略一大部分...........
         8          0          0          0         68   feof.o
         8          0          0          0         68   ferror.o
       100          0          0          0        120   fflush.o
        26          0          0          0        136   fgetc.o
        32          0          0          0         80   fgetpos.o
        74          0          0          0         84   fgets.o
       570          0          0          0        132   filbuf.o
       470          0          0          0         88   flsbuf.o
        28          0          0          0        136   fputc.o
        34          0          0          0         80   fputs.o
        58          0          0          0         88   fread.o
       248          0          0          0         84   fseek.o
        40          0          0          0         80   fsetpos.o
        66          0          0          0         76   ftell.o
        50          0          0          0         84   fwrite.o
         4          0          0          0         68   getc.o
        12          0          0          0         68   getchar.o
        56          0          0          0         80   gets.o
        60          0          0          0         80   perror.o
         4          0          0          0         68   putc.o
        12          0          0          0         68   putchar.o
        44          0          0          0         84   puts.o
        22          0          0          0         80   rewind.o
        70          0          0          0         80   setvbuf.o
       240          0          0          0        156   stdio.o
        88          0          4        256        108   tmpnam.o
        72          0          0          0         68   ungetc.o
        78          0          0          0        112   __dup.o
       280          0          0          0         96   freadfast.o
       214          0          0          0         88   fread_bytes_avail.o
        26          0          0          0         76   fread_bytes_avail_replaced.o
       188          0          0          0         88   fwritefast.o
         0          0          4          0          0   streamlock.o
       312          0          0          0        112   initio.o
       236          0          0          0        128   fopen.o
        20          0          0          0         68   setbuf.o
         0          0         12        252          0   stdio_streams.o
        76          0          0          0         88   fclose.o
        56          0          0          0         80   flushlinebuffered.o
       102          0          0          0         96   fclose_tmpfile.o
        32          0          0          0         80   fgetc_locked.o
        36          0          0          0         80   fputc_locked.o
        32          0          0          0         80   ftell_locked.o
        52          0          0          0         80   fclose_locked.o
        36          0          0          0         80   ungetc_locked.o
        44          0          0          0         84   fseek_locked.o
        86          0          0          0         84   fgets_locked.o
        76          0          0          0         80   gets_locked.o
        54          0          0          0         80   fputs_locked.o
        64          0          0          0         80   puts_locked.o
		............省略一大部分...........
        16          0          0         42         68   locale.o
       114          0          0          0         76   _lconv.o
        16          0          0         48         76   localeconv.o
        36          0          0          0         76   aeabi_lconv.o
        16          0          0         56         76   aeabi_localeconv.o
        60          0          0          0         80   findlocale.o
       428          0          0          0        188   locale_r.o
         2          0          0          0         68   locale_8859.o
        16          0          0         88        136   mbdata.o
        68          0          0          0         84   mblen.o
       122          0          0          0         88   mbtowc.o
        56          0          0          0         80   wctomb.o
        80          0          0          0         88   mbstowcs.o
       100          0          0          0         92   wcstombs.o
        14          0          0          0         68   mbsinit.o
        36          0          0          0         88   mbrlen.o
       120          0          0          0         88   mbrtowc.o
        58          0          0          0         80   wcrtomb.o
       114          0          0          0         92   mbsrtowcs.o
       140          0          0          0        100   wcsrtombs.o
        40          0          0          0         80   btowc.o
        42          0          0          0         84   wctob.o
		............省略一大部分...........
         8          0          0          0         68   labs.o
        20          0          0          0         76   ldiv.o
        20          0          0          0         68   llabs.o
        24          0          0          0         80   lldiv.o
        20          0          0          0         68   imaxabs.o
        24          0          0          0         80   imaxdiv.o
       112          0          0        228        160   rand.o
        36          0          4          0         84   ANSI_rand.o
       120          0          0          0         92   rand_r.o
        28          0          0          0         84   ANSI_rand_r.o
        18          0          0          0         80   exit.o
        22          0          0          0         80   abort.o
         4          0          0          0         68   _Exit.o
   		............省略一大部分...........
        20          0          0          0         68   strchr.o
        32          0          0          0         80   strcspn.o
        36          0          0          0         76   strncat.o
        30          0          0          0         76   strpbrk.o
        28          0          0          0         80   strspn.o
        36          0          0          0         80   strstr.o
        80          0          0          0         84   strxfrm.o
       184          0          0          0         84   strlcat.o
       142          0          0          0         84   strlcpy.o
        88          0          0          0         76   memcmp.o
        72          0          0          0         80   strcpy.o
        50          0          0          0         84   strncasecmp.o
        42          0          0          0         84   strcasecmp.o
        22          0          0          0         68   strrchr.o
        62          0          0          0         76   strlen.o
        18          0          0          0         68   wcscpy.o
       		............省略一大部分...........
         8          0          0          0         76   memcpy.o
         8          0          0          0         76   memmove.o
       214          0          0          0         68   rt_memcpy.o
       202          0          0          0         68   rt_memmove.o
       100          0          0          0         80   rt_memcpy_w.o
       122          0          0          0         80   rt_memmove_w.o
        22          0          0          0         76   memset.o
        16          0          0          0         68   aeabi_memset.o
        16          0          0          0         68   aeabi_memset4.o
        18          0          0          0         68   rt_memset.o
        68          0          0          0         68   rt_memclr.o
        78          0          0          0         80   rt_memclr_w.o
       250          0          0          0        196   rt_neon_memcpy_w.o
        84          0          0          0        172   rt_neon_memclr_w.o
       128          0          0          0        172   rt_neon_memmove_w.o
       220          0          0          0        164   rt_neon_memcpy_ca8.o
       228          0          0          0        164   rt_neon_memcpy_ca9.o
       236          0          0          0        164   rt_neon_memmove_ca8.o
       236          0          0          0        164   rt_neon_memmove_ca9.o
       130          0          0          0         96   rt_memcpy_w_ca8.o
       118          0          0          0         96   rt_memcpy_w_qsp.o
       118          0          0          0         96   rt_memcpy_w_ca9.o
       216          0          0          0         96   rt_memcpy_w_ldrd.o
       118          0          0          0        192   rt_noneon_memcpy_w_ca9.o
    		............省略一大部分...........
        14          0          0          0         80   ctime.o
         4          0          0          0         68   gmtime.o
        12          0          0         44         68   localtime.o
       428          0          0          0        116   mktime.o
       864          0          0          0        184   strftime.o
         0         12          0          0          0   _monlen.o
         0          0          0          0          0   asctime_r.o
         0          0          0          0          0   localtime_r.o
       104          0          0          0         88   asctime_internal.o
       184          0          0          0         80   localtime_internal.o
      		............省略一大部分...........
         0          0          0          0          0   cpuinit.o
       264          0          0          0         96   _get_argv.o
       302          0          0          0        168   _get_argv_nomalloc.o
         4          0          0          0         84   _main.o
       320          0          0          0        152   _main_redirect.o
         2          0          0          0         68   _main_arg.o
         4          0          0          0         68   argv_veneer.o
         2          0          0          0         68   no_argv.o
         2          0          0          0         68   no_excepts.o
         2          0          0          0         68   no_errno.o
         2          0          0          0         68   use_snan.o
         2          0          0          0          0   libinit.o
       136          0          0          0          0   libinit2.o
        36          0          0          0          0   libinit3.o
        36          0          0          0          0   libinit4.o
        36          0          0          0          0   libinit5.o
         2          0          0          0          0   libshutdown.o
        28          0          0          0          0   libshutdown2.o
         8          0          0          0         68   __main.o
        52          0          0          0         68   __scatter.o
        76          0          0          0         68   __scatters.o
        26          0          0          0         68   __scatter_copy.o
        28          0          0          0         68   __scatter_zi.o
        32          0          0          0        272   irqnopfx.o
       314          0          0          0         92   bitcpy0.o
       322          0          0          0         92   bitcpy1.o
       362          0          0          0         92   bitcpy2.o
       608          0          0          0        100   bitcpy3.o
       468          0          0          0         92   bitmove0.o
       474          0          0          0         92   bitmove1.o
       508          0          0          0         92   bitmove2.o
       764          0          0          0        100   bitmove3.o
    		............省略一大部分...........
        34          0          0          0         76   prim_new.o
         2          8          0          0         68   init.o
        36          8          0          0         80   init_aeabi.o
        44          8          0          0         76   arm_relocate.o
        36          8          0          0         80   preinit_aeabi.o
         4          0          0          0         68   _memcpy.o
         8          0          0          0         84   _urdwr4.o
       		............省略一大部分...........
       112          0          0          0        104   fputwc.o
        36          0          0          0         80   fputws.o
       200          0          0          0        104   fgetwc.o
        82          0          0          0         84   fgetws.o
         4          0          0          0         68   getwc.o
        12          0          0          0         68   getwchar.o
         4          0          0          0         68   putwc.o
        12          0          0          0         68   putwchar.o
       108          0          0          0         68   ungetwc.o
        44          0          0          0         84   backspacewc.o
        44          0          0          0         68   fwide.o
        36          0          0          0         84   filbuf_fwide.o
        36          0          0          0         84   flsbuf_fwide.o
        36          0          0          0         80   fputwc_locked.o
        32          0          0          0         80   fgetwc_locked.o
        66          0          0          0         80   fwide_locked.o
       132          0          0          0         80   ungetwc_locked.o
        32          0          0          0         80   backspacewc_locked.o
        54          0          0          0         80   fputws_locked.o
        94          0          0          0         84   fgetws_locked.o
     73526      40563        112       1686      76484   TOTAL

ENTRY at offset 1 in section !!!main of __main.o

從中我們可以看到有__main.o等文件,接下來我們可以使用armar -x命令將c_w.l解壓出以上全部文件,然後使用fromelf來查看__main.o的詳細信息,這裏就不一一嘗試了!

啓動實例分析

  下面我們以STM32F407VG片子爲例,看看其調試時的彙編代碼(Keil5中)。直接進調試模式,注意:最好將彙編窗口右鍵改爲assembly mode。
在這裏插入圖片描述
首先看看定義的中斷向量表部分,如下圖:
在這裏插入圖片描述
其中,SystemInit爲 ST 提供的時鐘初始化函數(如果使用了外部RAM,可能還包含外部RAM的配置)。接着,就會有如下彙編代碼(具體看裏面的註釋即可):

0x08000180 0243      DCW           0x0243       ; 小端模式,地址:0x08000243
0x08000182 0800      DCW           0x0800
0x08000184 0243      DCW           0x0243       ; 小端模式,地址:0x08000243
0x08000186 0800      DCW           0x0800                                   
; 從此往上即爲中斷向量表,與開發環境的啓動文件中的中斷向量表相對應,32位地址,小端模式
; 下面就是上文介紹的啓動流程:
                 __main:
0x08000188 F000F802  BL.W          __scatterload (0x08000190)       ; 負責把RW/RO輸出段從裝載域地址複製到運行域地址,並完成了ZI運行域的初始化工作。
0x0800018C F000F83C  BL.W          __rt_entry (0x08000208)          ; 負責初始化堆、棧,完成C庫函數的初始化。其會調用一系列初始化函數,最後自動跳轉向main()函數。

; 執行完後,R10和R11就被賦給成了下面兩個值,Map文件中的symbol:
;       Region$$Table$$Base                      0x08000898   Number         0  anon$$obj.o(Region$$Table)
;       Region$$Table$$Limit                     0x080008b8   Number         0  anon$$obj.o(Region$$Table)
; !!!-----------注意:以下注釋中括號中的數據爲我在調試時的值,自行調試時值可能有變化-----------!!!
; !!!-----------注意:以下注釋中非括號中的數據一般爲左側地址或者立即數-----------!!!
                 __scatterload:
0x08000190 A00A      ADR           r0,{pc}+0x2C     ; 將基於PC相對偏移的地址值(0x080001BC)讀取到寄存器r0中。
0x08000192 E8900C00  LDM           r0,{r10-r11}     ; 將R0對應地址存放的的2個字copy到R10~R11中。即:r10 = 0x000006DC; r11 = 0x000006FC
0x08000196 4482      ADD           r10,r10,r0       ; r10 = r10 + r0 = 0x000006DC + 0x080001BC = 0x08000898
0x08000198 4483      ADD           r11,r11,r0       ; r11 = r11 + r0 = 0x000006FC + 0x080001BC = 0x080008B8
0x0800019A F1AA0701  SUB           r7,r10,#0x01     ; r7 = r10 - 0x01 = 0x08000898 - 0x01 = 0x08000897
                 __scatterload_null:
0x0800019E 45DA      CMP           r10,r11          ; 比較r10和r11。實際做r10-r11操作,根據結果修改CPSR中條件標誌位的值
0x080001A0 D101      BNE           0x080001A6       ; Z 標誌位不等於零時, 跳轉到0x080001A6
0x080001A2 F000F831  BL.W          __rt_entry (0x08000208)  ; 最後一步:在執行完__scatterload_copy和__scatterload_zeroinit後,r10 == r11 ,上面的跳轉不成立,執行該句
0x080001A6 F2AF0E09  ADR.W         lr,{pc}-0x07     ; 將基於PC相對偏移的地址值(0x0800019F)讀取到寄存器lr中。lr = 0x0800019F
0x080001AA E8BA000F  LDM           r10!,{r0-r3}     ; 將R10對應地址存放的的4個雙字copy到R0~R3中,!表示執行語句後將地址賦值給r10。r10 = r10 + 4*4 = 0x08000898 + 0x10 = 0x080008A8. 
                                                    ;       R0:表示的是程序加載視圖的RW區的起始地址(0x080008B8;       R1:要複製到的運行域地址(RAM中0x20000000;       R2:要複製的RW數據的個數(0x00000020;       R3:是__scatterload_copy函數的起始地址0x080001C4
0x080001AE F0130F01  TST           r3,#0x01         ; 
0x080001B2 BF18      IT            NE
0x080001B4 1AFB      SUBNE         r3,r7,r3
0x080001B6 F0430301  ORR           r3,r3,#0x01
0x080001BA 4718      BX            r3               ; 跳轉到r3,也就是__scatterload_copy函數,開始複製數據
0x080001BC 06DC      DCW           0x06DC
0x080001BE 0000      DCW           0x0000
0x080001C0 06FC      DCW           0x06FC
0x080001C2 0000      DCW           0x0000
                 __scatterload_copy:                ; 該函數負責將鏡像中的RW數據複製到芯片的ARM中
0x080001C4 3A10      SUBS          r2,r2,#0x10      ; 循環:R2=R2-0x10,SUBS中S表示把進位結果寫入CPSR。
0x080001C6 BF24      ITT           CS
0x080001C8 C878      LDMCS         r0!,{r3-r6}
0x080001CA C178      STMCS         r1!,{r3-r6}
0x080001CC D8FA      BHI           __scatterload_copy (0x080001C4)  ; 循環:條件成立跳轉到回去
0x080001CE 0752      LSLS          r2,r2,#29
0x080001D0 BF24      ITT           CS
0x080001D2 C830      LDMCS         r0!,{r4-r5}
0x080001D4 C130      STMCS         r1!,{r4-r5}
0x080001D6 BF44      ITT           MI
0x080001D8 6804      LDRMI         r4,[r0,#0x00]
0x080001DA 600C      STRMI         r4,[r1,#0x00]
0x080001DC 4770      BX            lr               ; 這裏返回到lr = 0x0800019F,即在此調用__scatterload_null。會繼續將R10對應地址存放的的4個雙字copy到R0~R3中,但是,此時的R10由於之前的一次調用,其值已經增加
                                                    ;       R0:是程序加載視圖的RW區的起始地址(0x080008D8 = 0x080008B8 + 0x20 上面執行後面的部分)
                                                    ;       R1:是要輸出的執行視圖的RW區的地址(RAM中 0x20000020;       R2:要複製的RW數據的個數(0x00000660;       R3:是__scatterload_zeroinit函數的起始地址0x080001E0
                                                    ;       接下來就會跳轉到__scatterload_zeroinit

0x080001DE 0000      MOVS          r0,r0
                 __scatterload_zeroinit:
0x080001E0 2300      MOVS          r3,#0x00
0x080001E2 2400      MOVS          r4,#0x00
0x080001E4 2500      MOVS          r5,#0x00
0x080001E6 2600      MOVS          r6,#0x00
0x080001E8 3A10      SUBS          r2,r2,#0x10      ; 循環:
0x080001EA BF28      IT            CS
0x080001EC C178      STMCS         r1!,{r3-r6}
0x080001EE D8FB      BHI           0x080001E8       ; 循環:條件成立跳轉到回去
0x080001F0 0752      LSLS          r2,r2,#29
0x080001F2 BF28      IT            CS
0x080001F4 C130      STMCS         r1!,{r4-r5}
0x080001F6 BF48      IT            MI
0x080001F8 600B      STRMI         r3,[r1,#0x00]
0x080001FA 4770      BX            lr               ; 這裏返回到lr = 0x0800019F,即在此調用__scatterload_null。這次回去後r10 == r11.回去後會跳轉到__rt_entry
                 __rt_lib_init:
0x080001FC B51F      PUSH          {r0-r4,lr}
                 __rt_lib_init_fp_1:
0x080001FE F000FB45  BL.W          _fp_init (0x0800088C)
                 __rt_lib_init_alloca_1:
0x08000202 BD1F      POP           {r0-r4,pc}
                 __rt_lib_shutdown:
0x08000204 B510      PUSH          {r4,lr}
                 __rt_lib_shutdown_cpp_1:
0x08000206 BD10      POP           {r4,pc}
                 __rt_entry:                        ; 在執行完__scatterload後,會緊接着執行該函數
0x08000208 F000F831  BL.W          __user_setup_stackheap (0x0800026E)  ; 設置堆棧的函數,該函數中會調用由用戶實現的__user_initial_stackheap函數,如第二節的啓動文件中最後的代碼即爲用戶實現的堆棧初始化該函數
0x0800020C 4611      MOV           r1,r2
                 __rt_entry_li:
0x0800020E F7FFFFF5  BL.W          __rt_lib_init (0x080001FC)   ; 初始化C庫
                 __rt_entry_main:
0x08000212 F000FA3B  BL.W          main (0x0800068C)            ; 跳轉到C的main函數
0x08000216 F000F84F  BL.W          exit (0x080002B8)            ; 如果main返回,則執行該函數,結束程序運行
                 __rt_exit:
0x0800021A B403      PUSH          {r0-r1}
                 __rt_exit_ls:
0x0800021C F7FFFFF2  BL.W          __rt_lib_shutdown (0x08000204)
                 __rt_exit_exit:
0x08000220 BC03      POP           {r0-r1}
0x08000222 F000F857  BL.W          _sys_exit (0x080002D4)
0x08000226 0000      MOVS          r0,r0
0x08000226 0000      MOVS          r0,r0
; 此處往下,就是定義的各個中斷向量的實現代碼,第一個就是復位中斷,程序就是從復位中斷開始執行的
                 Reset_Handler:
0x08000228 4809      LDR           r0,[pc,#36]  ; @0x08000250
0x0800022A 4780      BLX           r0
0x0800022C 4809      LDR           r0,[pc,#36]  ; @0x08000254
0x0800022E 4700      BX            r0
                 NMI_Handler:
0x08000230 E7FE      B             NMI_Handler (0x08000230)
                 HardFault_Handler:
0x08000232 E7FE      B             HardFault_Handler (0x08000232)
                 MemManage_Handler:            
0x08000234 E7FE      B             MemManage_Handler (0x08000234)
                 BusFault_Handler:
0x08000236 E7FE      B             BusFault_Handler (0x08000236)
                 UsageFault_Handler:
0x08000238 E7FE      B             UsageFault_Handler (0x08000238)
                 SVC_Handler:
0x0800023A E7FE      B             SVC_Handler (0x0800023A)
                 DebugMon_Handler:
0x0800023C E7FE      B             DebugMon_Handler (0x0800023C)
                 PendSV_Handler:
0x0800023E E7FE      B             PendSV_Handler (0x0800023E)
                 SysTick_Handler:
0x08000240 E7FE      B             SysTick_Handler (0x08000240)
                 Default_Handler:
0x08000242 E7FE      B             Default_Handler (0x08000242)
                 __user_initial_stackheap:
0x08000244 4804      LDR           r0,[pc,#16]  ; @0x08000258
0x08000246 4905      LDR           r1,[pc,#20]  ; @0x0800025C
0x08000248 4A05      LDR           r2,[pc,#20]  ; @0x08000260
0x0800024A 4B06      LDR           r3,[pc,#24]  ; @0x08000264
0x0800024C 4770      BX            lr
0x0800024E 0000      DCW           0x0000
0x08000250 0621      DCW           0x0621
0x08000252 0800      DCW           0x0800
0x08000254 0189      DCW           0x0189
0x08000256 0800      DCW           0x0800
0x08000258 0080      DCW           0x0080
0x0800025A 2000      DCW           0x2000
0x0800025C 0680      DCW           0x0680
0x0800025E 2000      DCW           0x2000
0x08000260 0280      DCW           0x0280
0x08000262 2000      DCW           0x2000
0x08000264 0280      DCW           0x0280
0x08000266 2000      DCW           0x2000
                 __use_two_region_memory:
0x08000268 4770      BX            lr
                 __rt_heap_escrow$2region:
0x0800026A 4770      BX            lr
                 __rt_heap_expand$2region:
0x0800026C 4770      BX            lr
                 __user_setup_stackheap:
0x0800026E 4675      MOV           r5,lr
0x08000270 F000F82C  BL.W          __user_libspace (0x080002CC)
0x08000274 46AE      MOV           lr,r5
0x08000276 0005      MOVS          r5,r0
0x08000278 4669      MOV           r1,sp
0x0800027A 4653      MOV           r3,r10
0x0800027C F0200007  BIC           r0,r0,#0x07
0x08000280 4685      MOV           sp,r0
0x08000282 B018      ADD           sp,sp,#0x60
0x08000284 B520      PUSH          {r5,lr}
0x08000286 F7FFFFDD  BL.W          __user_initial_stackheap (0x08000244)
0x0800028A E8BD4020  POP           {r5,lr}
0x0800028E F04F0600  MOV           r6,#0x00
0x08000292 F04F0700  MOV           r7,#0x00
0x08000296 F04F0800  MOV           r8,#0x00
0x0800029A F04F0B00  MOV           r11,#0x00
0x0800029E F0210107  BIC           r1,r1,#0x07
0x080002A2 46AC      MOV           r12,r5
0x080002A4 E8AC09C0  STM           r12!,{r6-r8,r11}
0x080002A8 E8AC09C0  STM           r12!,{r6-r8,r11}
0x080002AC E8AC09C0  STM           r12!,{r6-r8,r11}
0x080002B0 E8AC09C0  STM           r12!,{r6-r8,r11}
0x080002B4 468D      MOV           sp,r1
0x080002B6 4770      BX            lr
                 exit:
0x080002B8 B510      PUSH          {r4,lr}
0x080002BA 4604      MOV           r4,r0
0x080002BC F3AF8000  NOP.W         
0x080002C0 4620      MOV           r0,r4
0x080002C2 E8BD4010  POP           {r4,lr}
0x080002C6 F7FFBFA8  B.W           __rt_exit (0x0800021A)
0x080002CA 0000      MOVS          r0,r0
                 __user_libspace:
0x080002CC 4800      LDR           r0,[pc,#0]  ; @0x080002D0
0x080002CE 4770      BX            lr
0x080002D0 0020      DCW           0x0020
0x080002D2 2000      DCW           0x2000
                 _sys_exit:
0x080002D4 4901      LDR           r1,[pc,#4]  ; @0x080002DC
0x080002D6 2018      MOVS          r0,#0x18
0x080002D8 BEAB      BKPT          0xAB
0x080002DA E7FE      B             0x080002DA
0x080002DC 0026      DCW           0x0026
0x080002DE 0002      DCW           0x0002

啓動文件

  目前,多數 MCU 廠商都提供一個啓動文件。當然,編程者也可以自己編寫啓動文件,具體編寫要求ARM的網站上都有相關文檔進行說明。下面分析一下 STM32 啓動文件startup_stm32f407xx.s,具體看裏面的註釋。

;******************** (C) COPYRIGHT 2017 STMicroelectronics ********************
;* File Name          : startup_stm32f407xx.s
;* Author             : MCD Application Team
;* Version            : V2.6.1
;* Date               : 14-February-2017
;* Description        : STM32F407xx devices vector table for MDK-ARM toolchain. 
;*                      This module performs:
;*                      - Set the initial SP
;*                      - Set the initial PC == Reset_Handler
;*                      - Set the vector table entries with the exceptions ISR address
;*                      - Branches to __main in the C library (which eventually
;*                        calls main()).
;*                      After Reset the CortexM4 processor is in Thread mode,
;*                      priority is Privileged, and the Stack is set to Main.
;* <<< Use Configuration Wizard in Context Menu >>>   
;*******************************************************************************
; 
;* Redistribution and use in source and binary forms, with or without modification,
;* are permitted provided that the following conditions are met:
;*   1. Redistributions of source code must retain the above copyright notice,
;*      this list of conditions and the following disclaimer.
;*   2. Redistributions in binary form must reproduce the above copyright notice,
;*      this list of conditions and the following disclaimer in the documentation
;*      and/or other materials provided with the distribution.
;*   3. Neither the name of STMicroelectronics nor the names of its contributors
;*      may be used to endorse or promote products derived from this software
;*      without specific prior written permission.
;*
;* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
;* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
;* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
;* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
;* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
;* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
;* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
;* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
;* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
;* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
; 
;*******************************************************************************

; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Stack_Size      EQU     0x0800                                  ; 定義棧大小
                ; AREA 命令指示彙編器彙編一個新的代碼段或數據段。 
                AREA    STACK, NOINIT, READWRITE, ALIGN=3       ; 代碼段名稱爲STACK,未初始化,允許讀寫,8字節對齊
Stack_Mem       SPACE   Stack_Size                              ; 分配Stack_Size的棧空間,首地址賦給Stack_Mem
__initial_sp                                                    ; 棧頂指針,全局變量


; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Heap_Size      EQU     0x200

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base                                                     ; 堆末底部地址
Heap_Mem        SPACE   Heap_Size
__heap_limit                                                    ; 堆界限地址

                PRESERVE8                                       ; 指定當前文件保持堆棧八字節對齊
                THUMB                                           ; Thumb命令模式


; Vector Table Mapped to Address 0 at Reset                     ; 終端向量表 重啓時程序從這裏運行,必須將該地址映射到0x00000000
                AREA    RESET, DATA, READONLY                   ; 代碼段名稱爲RESET,DATA類型,只讀
                EXPORT  __Vectors                               ; 導出中斷向量表地址(供外部可以使用)
                EXPORT  __Vectors_End                           ; 導出中斷向量表結束指針(供外部可以使用)
                EXPORT  __Vectors_Size                          ; 中斷向量表大小(供外部可以使用)
__Vectors       DCD     __initial_sp               ; Top of Stack
                DCD     Reset_Handler              ; Reset Handler
                DCD     NMI_Handler                ; NMI Handler
                DCD     HardFault_Handler          ; Hard Fault Handler
                DCD     MemManage_Handler          ; MPU Fault Handler
                DCD     BusFault_Handler           ; Bus Fault Handler
                DCD     UsageFault_Handler         ; Usage Fault Handler
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     SVC_Handler                ; SVCall Handler
                DCD     DebugMon_Handler           ; Debug Monitor Handler
                DCD     0                          ; Reserved
                DCD     PendSV_Handler             ; PendSV Handler
                DCD     SysTick_Handler            ; SysTick Handler

                ; External Interrupts
                DCD     WWDG_IRQHandler                   ; Window WatchDog                                        
                DCD     PVD_IRQHandler                    ; PVD through EXTI Line detection                        
                DCD     TAMP_STAMP_IRQHandler             ; Tamper and TimeStamps through the EXTI line            
                DCD     RTC_WKUP_IRQHandler               ; RTC Wakeup through the EXTI line                       
                DCD     FLASH_IRQHandler                  ; FLASH                                           
                DCD     RCC_IRQHandler                    ; RCC                                             
                DCD     EXTI0_IRQHandler                  ; EXTI Line0                                             
                DCD     EXTI1_IRQHandler                  ; EXTI Line1                                             
                DCD     EXTI2_IRQHandler                  ; EXTI Line2                                             
                DCD     EXTI3_IRQHandler                  ; EXTI Line3                                             
                DCD     EXTI4_IRQHandler                  ; EXTI Line4                                             
                DCD     DMA1_Stream0_IRQHandler           ; DMA1 Stream 0                                   
                DCD     DMA1_Stream1_IRQHandler           ; DMA1 Stream 1                                   
                DCD     DMA1_Stream2_IRQHandler           ; DMA1 Stream 2                                   
                DCD     DMA1_Stream3_IRQHandler           ; DMA1 Stream 3                                   
                DCD     DMA1_Stream4_IRQHandler           ; DMA1 Stream 4                                   
                DCD     DMA1_Stream5_IRQHandler           ; DMA1 Stream 5                                   
                DCD     DMA1_Stream6_IRQHandler           ; DMA1 Stream 6                                   
                DCD     ADC_IRQHandler                    ; ADC1, ADC2 and ADC3s                            
                DCD     CAN1_TX_IRQHandler                ; CAN1 TX                                                
                DCD     CAN1_RX0_IRQHandler               ; CAN1 RX0                                               
                DCD     CAN1_RX1_IRQHandler               ; CAN1 RX1                                               
                DCD     CAN1_SCE_IRQHandler               ; CAN1 SCE                                               
                DCD     EXTI9_5_IRQHandler                ; External Line[9:5]s                                    
                DCD     TIM1_BRK_TIM9_IRQHandler          ; TIM1 Break and TIM9                   
                DCD     TIM1_UP_TIM10_IRQHandler          ; TIM1 Update and TIM10                 
                DCD     TIM1_TRG_COM_TIM11_IRQHandler     ; TIM1 Trigger and Commutation and TIM11
                DCD     TIM1_CC_IRQHandler                ; TIM1 Capture Compare                                   
                DCD     TIM2_IRQHandler                   ; TIM2                                            
                DCD     TIM3_IRQHandler                   ; TIM3                                            
                DCD     TIM4_IRQHandler                   ; TIM4                                            
                DCD     I2C1_EV_IRQHandler                ; I2C1 Event                                             
                DCD     I2C1_ER_IRQHandler                ; I2C1 Error                                             
                DCD     I2C2_EV_IRQHandler                ; I2C2 Event                                             
                DCD     I2C2_ER_IRQHandler                ; I2C2 Error                                               
                DCD     SPI1_IRQHandler                   ; SPI1                                            
                DCD     SPI2_IRQHandler                   ; SPI2                                            
                DCD     USART1_IRQHandler                 ; USART1                                          
                DCD     USART2_IRQHandler                 ; USART2                                          
                DCD     USART3_IRQHandler                 ; USART3                                          
                DCD     EXTI15_10_IRQHandler              ; External Line[15:10]s                                  
                DCD     RTC_Alarm_IRQHandler              ; RTC Alarm (A and B) through EXTI Line                  
                DCD     OTG_FS_WKUP_IRQHandler            ; USB OTG FS Wakeup through EXTI line                        
                DCD     TIM8_BRK_TIM12_IRQHandler         ; TIM8 Break and TIM12                  
                DCD     TIM8_UP_TIM13_IRQHandler          ; TIM8 Update and TIM13                 
                DCD     TIM8_TRG_COM_TIM14_IRQHandler     ; TIM8 Trigger and Commutation and TIM14
                DCD     TIM8_CC_IRQHandler                ; TIM8 Capture Compare                                   
                DCD     DMA1_Stream7_IRQHandler           ; DMA1 Stream7                                           
                DCD     FMC_IRQHandler                    ; FMC                                             
                DCD     SDIO_IRQHandler                   ; SDIO                                            
                DCD     TIM5_IRQHandler                   ; TIM5                                            
                DCD     SPI3_IRQHandler                   ; SPI3                                            
                DCD     UART4_IRQHandler                  ; UART4                                           
                DCD     UART5_IRQHandler                  ; UART5                                           
                DCD     TIM6_DAC_IRQHandler               ; TIM6 and DAC1&2 underrun errors                   
                DCD     TIM7_IRQHandler                   ; TIM7                   
                DCD     DMA2_Stream0_IRQHandler           ; DMA2 Stream 0                                   
                DCD     DMA2_Stream1_IRQHandler           ; DMA2 Stream 1                                   
                DCD     DMA2_Stream2_IRQHandler           ; DMA2 Stream 2                                   
                DCD     DMA2_Stream3_IRQHandler           ; DMA2 Stream 3                                   
                DCD     DMA2_Stream4_IRQHandler           ; DMA2 Stream 4                                   
                DCD     ETH_IRQHandler                    ; Ethernet                                        
                DCD     ETH_WKUP_IRQHandler               ; Ethernet Wakeup through EXTI line                      
                DCD     CAN2_TX_IRQHandler                ; CAN2 TX                                                
                DCD     CAN2_RX0_IRQHandler               ; CAN2 RX0                                               
                DCD     CAN2_RX1_IRQHandler               ; CAN2 RX1                                               
                DCD     CAN2_SCE_IRQHandler               ; CAN2 SCE                                               
                DCD     OTG_FS_IRQHandler                 ; USB OTG FS                                      
                DCD     DMA2_Stream5_IRQHandler           ; DMA2 Stream 5                                   
                DCD     DMA2_Stream6_IRQHandler           ; DMA2 Stream 6                                   
                DCD     DMA2_Stream7_IRQHandler           ; DMA2 Stream 7                                   
                DCD     USART6_IRQHandler                 ; USART6                                           
                DCD     I2C3_EV_IRQHandler                ; I2C3 event                                             
                DCD     I2C3_ER_IRQHandler                ; I2C3 error                                             
                DCD     OTG_HS_EP1_OUT_IRQHandler         ; USB OTG HS End Point 1 Out                      
                DCD     OTG_HS_EP1_IN_IRQHandler          ; USB OTG HS End Point 1 In                       
                DCD     OTG_HS_WKUP_IRQHandler            ; USB OTG HS Wakeup through EXTI                         
                DCD     OTG_HS_IRQHandler                 ; USB OTG HS                                      
                DCD     DCMI_IRQHandler                   ; DCMI  
                DCD     0                                 ; Reserved                                              
                DCD     HASH_RNG_IRQHandler               ; Hash and Rng
                DCD     FPU_IRQHandler                    ; FPU
                
                                         
__Vectors_End

__Vectors_Size  EQU  __Vectors_End - __Vectors              ; 計算中斷向量表的大小

                AREA    |.text|, CODE, READONLY             ; 代碼段,|.text| 用於表示由 C 編譯程序產生的代碼段,或用於以某種方式與 C 庫關聯的代碼段。 CODE類型,只讀
; 以下開始定義各種中斷,第一個便是復位中斷,順序與上面的終端向量表一致!
; Reset handler
Reset_Handler    PROC                                       ; 代碼開始,與ENDP成對出現    
                 EXPORT  Reset_Handler             [WEAK]   ; 復位中斷,[WEAK]修飾代表其他文件有函數定義優先調用
        IMPORT  SystemInit                                  ; 導入外部函數SystemInit
        IMPORT  __main                                      ; 導入外部函數__main

                 LDR     R0, =SystemInit
                 BLX     R0                                 ; 無返回調用SystemInit
                 LDR     R0, =__main
                 BX      R0                                 ; 有返回調用__main
                 ENDP                                       ; 代碼結束,與PROC成對出現

; Dummy Exception Handlers (infinite loops which can be modified)

NMI_Handler     PROC
                EXPORT  NMI_Handler                [WEAK]
                B       .
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler          [WEAK]
                B       .
                ENDP
MemManage_Handler\
                PROC
                EXPORT  MemManage_Handler          [WEAK]
                B       .
                ENDP
BusFault_Handler\
                PROC
                EXPORT  BusFault_Handler           [WEAK]
                B       .
                ENDP
UsageFault_Handler\
                PROC
                EXPORT  UsageFault_Handler         [WEAK]
                B       .
                ENDP
SVC_Handler     PROC
                EXPORT  SVC_Handler                [WEAK]
                B       .
                ENDP
DebugMon_Handler\
                PROC
                EXPORT  DebugMon_Handler           [WEAK]
                B       .
                ENDP
PendSV_Handler  PROC
                EXPORT  PendSV_Handler             [WEAK]
                B       .
                ENDP
SysTick_Handler PROC
                EXPORT  SysTick_Handler            [WEAK]
                B       .
                ENDP
; 終端向量表的External Interrupts部分。 默認的外部中斷,通常有外部實現。先導出各種符號以供外部使用,然後時默認的定義
Default_Handler PROC

                EXPORT  WWDG_IRQHandler                   [WEAK]                                        
                EXPORT  PVD_IRQHandler                    [WEAK]                      
                EXPORT  TAMP_STAMP_IRQHandler             [WEAK]         
                EXPORT  RTC_WKUP_IRQHandler               [WEAK]                     
                EXPORT  FLASH_IRQHandler                  [WEAK]                                         
                EXPORT  RCC_IRQHandler                    [WEAK]                                            
                EXPORT  EXTI0_IRQHandler                  [WEAK]                                            
                EXPORT  EXTI1_IRQHandler                  [WEAK]                                             
                EXPORT  EXTI2_IRQHandler                  [WEAK]                                            
                EXPORT  EXTI3_IRQHandler                  [WEAK]                                           
                EXPORT  EXTI4_IRQHandler                  [WEAK]                                            
                EXPORT  DMA1_Stream0_IRQHandler           [WEAK]                                
                EXPORT  DMA1_Stream1_IRQHandler           [WEAK]                                   
                EXPORT  DMA1_Stream2_IRQHandler           [WEAK]                                   
                EXPORT  DMA1_Stream3_IRQHandler           [WEAK]                                   
                EXPORT  DMA1_Stream4_IRQHandler           [WEAK]                                   
                EXPORT  DMA1_Stream5_IRQHandler           [WEAK]                                   
                EXPORT  DMA1_Stream6_IRQHandler           [WEAK]                                   
                EXPORT  ADC_IRQHandler                    [WEAK]                         
                EXPORT  CAN1_TX_IRQHandler                [WEAK]                                                
                EXPORT  CAN1_RX0_IRQHandler               [WEAK]                                               
                EXPORT  CAN1_RX1_IRQHandler               [WEAK]                                                
                EXPORT  CAN1_SCE_IRQHandler               [WEAK]                                                
                EXPORT  EXTI9_5_IRQHandler                [WEAK]                                    
                EXPORT  TIM1_BRK_TIM9_IRQHandler          [WEAK]                  
                EXPORT  TIM1_UP_TIM10_IRQHandler          [WEAK]                
                EXPORT  TIM1_TRG_COM_TIM11_IRQHandler     [WEAK] 
                EXPORT  TIM1_CC_IRQHandler                [WEAK]                                   
                EXPORT  TIM2_IRQHandler                   [WEAK]                                            
                EXPORT  TIM3_IRQHandler                   [WEAK]                                            
                EXPORT  TIM4_IRQHandler                   [WEAK]                                            
                EXPORT  I2C1_EV_IRQHandler                [WEAK]                                             
                EXPORT  I2C1_ER_IRQHandler                [WEAK]                                             
                EXPORT  I2C2_EV_IRQHandler                [WEAK]                                            
                EXPORT  I2C2_ER_IRQHandler                [WEAK]                                               
                EXPORT  SPI1_IRQHandler                   [WEAK]                                           
                EXPORT  SPI2_IRQHandler                   [WEAK]                                            
                EXPORT  USART1_IRQHandler                 [WEAK]                                          
                EXPORT  USART2_IRQHandler                 [WEAK]                                          
                EXPORT  USART3_IRQHandler                 [WEAK]                                         
                EXPORT  EXTI15_10_IRQHandler              [WEAK]                                  
                EXPORT  RTC_Alarm_IRQHandler              [WEAK]                  
                EXPORT  OTG_FS_WKUP_IRQHandler            [WEAK]                        
                EXPORT  TIM8_BRK_TIM12_IRQHandler         [WEAK]                 
                EXPORT  TIM8_UP_TIM13_IRQHandler          [WEAK]                 
                EXPORT  TIM8_TRG_COM_TIM14_IRQHandler     [WEAK] 
                EXPORT  TIM8_CC_IRQHandler                [WEAK]                                   
                EXPORT  DMA1_Stream7_IRQHandler           [WEAK]                                          
                EXPORT  FMC_IRQHandler                    [WEAK]                                             
                EXPORT  SDIO_IRQHandler                   [WEAK]                                             
                EXPORT  TIM5_IRQHandler                   [WEAK]                                             
                EXPORT  SPI3_IRQHandler                   [WEAK]                                             
                EXPORT  UART4_IRQHandler                  [WEAK]                                            
                EXPORT  UART5_IRQHandler                  [WEAK]                                            
                EXPORT  TIM6_DAC_IRQHandler               [WEAK]                   
                EXPORT  TIM7_IRQHandler                   [WEAK]                    
                EXPORT  DMA2_Stream0_IRQHandler           [WEAK]                                  
                EXPORT  DMA2_Stream1_IRQHandler           [WEAK]                                   
                EXPORT  DMA2_Stream2_IRQHandler           [WEAK]                                    
                EXPORT  DMA2_Stream3_IRQHandler           [WEAK]                                    
                EXPORT  DMA2_Stream4_IRQHandler           [WEAK]                                 
                EXPORT  ETH_IRQHandler                    [WEAK]                                         
                EXPORT  ETH_WKUP_IRQHandler               [WEAK]                     
                EXPORT  CAN2_TX_IRQHandler                [WEAK]                                               
                EXPORT  CAN2_RX0_IRQHandler               [WEAK]                                               
                EXPORT  CAN2_RX1_IRQHandler               [WEAK]                                               
                EXPORT  CAN2_SCE_IRQHandler               [WEAK]                                               
                EXPORT  OTG_FS_IRQHandler                 [WEAK]                                       
                EXPORT  DMA2_Stream5_IRQHandler           [WEAK]                                   
                EXPORT  DMA2_Stream6_IRQHandler           [WEAK]                                   
                EXPORT  DMA2_Stream7_IRQHandler           [WEAK]                                   
                EXPORT  USART6_IRQHandler                 [WEAK]                                           
                EXPORT  I2C3_EV_IRQHandler                [WEAK]                                              
                EXPORT  I2C3_ER_IRQHandler                [WEAK]                                              
                EXPORT  OTG_HS_EP1_OUT_IRQHandler         [WEAK]                      
                EXPORT  OTG_HS_EP1_IN_IRQHandler          [WEAK]                      
                EXPORT  OTG_HS_WKUP_IRQHandler            [WEAK]                        
                EXPORT  OTG_HS_IRQHandler                 [WEAK]                                      
                EXPORT  DCMI_IRQHandler                   [WEAK]                                                                                 
                EXPORT  HASH_RNG_IRQHandler               [WEAK]
                EXPORT  FPU_IRQHandler                    [WEAK]
                
WWDG_IRQHandler                                                       
PVD_IRQHandler                                      
TAMP_STAMP_IRQHandler                  
RTC_WKUP_IRQHandler                                
FLASH_IRQHandler                                                       
RCC_IRQHandler                                                            
EXTI0_IRQHandler                                                          
EXTI1_IRQHandler                                                           
EXTI2_IRQHandler                                                          
EXTI3_IRQHandler                                                         
EXTI4_IRQHandler                                                          
DMA1_Stream0_IRQHandler                                       
DMA1_Stream1_IRQHandler                                          
DMA1_Stream2_IRQHandler                                          
DMA1_Stream3_IRQHandler                                          
DMA1_Stream4_IRQHandler                                          
DMA1_Stream5_IRQHandler                                          
DMA1_Stream6_IRQHandler                                          
ADC_IRQHandler                                         
CAN1_TX_IRQHandler                                                            
CAN1_RX0_IRQHandler                                                          
CAN1_RX1_IRQHandler                                                           
CAN1_SCE_IRQHandler                                                           
EXTI9_5_IRQHandler                                                
TIM1_BRK_TIM9_IRQHandler                        
TIM1_UP_TIM10_IRQHandler                      
TIM1_TRG_COM_TIM11_IRQHandler  
TIM1_CC_IRQHandler                                               
TIM2_IRQHandler                                                           
TIM3_IRQHandler                                                           
TIM4_IRQHandler                                                           
I2C1_EV_IRQHandler                                                         
I2C1_ER_IRQHandler                                                         
I2C2_EV_IRQHandler                                                        
I2C2_ER_IRQHandler                                                           
SPI1_IRQHandler                                                          
SPI2_IRQHandler                                                           
USART1_IRQHandler                                                       
USART2_IRQHandler                                                       
USART3_IRQHandler                                                      
EXTI15_10_IRQHandler                                            
RTC_Alarm_IRQHandler                            
OTG_FS_WKUP_IRQHandler                                
TIM8_BRK_TIM12_IRQHandler                      
TIM8_UP_TIM13_IRQHandler                       
TIM8_TRG_COM_TIM14_IRQHandler  
TIM8_CC_IRQHandler                                               
DMA1_Stream7_IRQHandler                                                 
FMC_IRQHandler                                                            
SDIO_IRQHandler                                                            
TIM5_IRQHandler                                                            
SPI3_IRQHandler                                                            
UART4_IRQHandler                                                          
UART5_IRQHandler                                                          
TIM6_DAC_IRQHandler                            
TIM7_IRQHandler                              
DMA2_Stream0_IRQHandler                                         
DMA2_Stream1_IRQHandler                                          
DMA2_Stream2_IRQHandler                                           
DMA2_Stream3_IRQHandler                                           
DMA2_Stream4_IRQHandler                                        
ETH_IRQHandler                                                         
ETH_WKUP_IRQHandler                                
CAN2_TX_IRQHandler                                                           
CAN2_RX0_IRQHandler                                                          
CAN2_RX1_IRQHandler                                                          
CAN2_SCE_IRQHandler                                                          
OTG_FS_IRQHandler                                                    
DMA2_Stream5_IRQHandler                                          
DMA2_Stream6_IRQHandler                                          
DMA2_Stream7_IRQHandler                                          
USART6_IRQHandler                                                        
I2C3_EV_IRQHandler                                                          
I2C3_ER_IRQHandler                                                          
OTG_HS_EP1_OUT_IRQHandler                           
OTG_HS_EP1_IN_IRQHandler                            
OTG_HS_WKUP_IRQHandler                                
OTG_HS_IRQHandler                                                   
DCMI_IRQHandler                                                                                                             
HASH_RNG_IRQHandler
FPU_IRQHandler  
           
                B       .

                ENDP

                ALIGN

;*******************************************************************************
; User Stack and Heap initialization    編譯器預處理命令,主要是用來初始化用戶堆棧
;*******************************************************************************
                 IF      :DEF:__MICROLIB    ; "DEF"的用法爲 :DEF:X 就是說X定義了則爲真,否則爲假。若定義了__MICROLIB,則將__initial_sp,__heap_base,__heap_limit亦即棧頂地址,堆始末地址賦予全局屬性,使外部程序可以使用。
                
                 EXPORT  __initial_sp
                 EXPORT  __heap_base
                 EXPORT  __heap_limit
                
                 ELSE                       ; 如果沒定義__MICROLIB,則使用默認的C運行時庫
                
                 IMPORT  __use_two_region_memory        ; 用於指定存儲器模式爲雙段模式,即一部分儲存區用於棧空間,其他的存儲區用於堆空間,堆區空間可以爲0,但是,這樣就不能調用malloc()內存分配函數;堆區空間也可以由存儲器分配,也可以從執行環境中繼承。在彙編代碼中,通過 IMPORT __use_two_region_memory 表明使用雙段模式;在C語言中,通過 #pragma import(__use_two_region_memory)語句表明使用雙段模式。
                 EXPORT  __user_initial_stackheap
                 
__user_initial_stackheap                    ; 此處是初始化兩區的堆棧空間,堆是從由低到高的增長,棧是由高向低生長的,兩個是互相獨立的數據段,並不能交叉使用。

                 LDR     R0, =  Heap_Mem                        ; 保存堆始地址
                 LDR     R1, =(Stack_Mem + Stack_Size)          ; 保存棧的大小
                 LDR     R2, = (Heap_Mem +  Heap_Size)          ; 保存堆的大小
                 LDR     R3, = Stack_Mem                        ; 保存棧頂指針
                 BX      LR

                 ALIGN                                          ; 填充字節使地址對齊

                 ENDIF

                 END                                            ; END 命令指示彙編器,已到達一個源文件的末尾。

;************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE*****

參考

  1. Developing Software for ARM Processors.pdf
  2. ARM Compiler C Library Startup and Initialization.pdf
  3. ARM C and C++ Libraries and Floating-Point Support.pdf
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章