1. 程式人生 > >Ardupilot chibios編譯,啟動,main函式學習(2)

Ardupilot chibios編譯,啟動,main函式學習(2)

目錄

文章目錄

摘要



本節繼續研究Chibios,歡迎批評指正!!!



1. Chibios編譯過程



這裡我使用的是ubuntu系統,編譯程式碼用的是gcc-arm-none-eabi-5_4-2016q3,在進入程式碼分析之前我的疑惑


1.我看gcc-arm-none-eabi-5_4就是不順眼,這是什麼鬼?
答;這鬼是一種交叉編譯工具,更詳細的是下面內容

在這裡插入圖片描述
在這裡插入圖片描述

還要注意:GCC(GNU Compiler Collection,GNU編譯器套件),是由 GNU 開發的程式語言編譯器。
我們採用的編輯器是gcc,編輯的物件型別滿足arm-none-eabi

# ARM Cortex-Mx common makefile scripts and rules.
#ARM Cortex-Mx  通用的的檔案檔案指令碼和規則。
##############################################################################
# Processing options coming from the upper Makefile.
# 處理選項來自上面的Makefile檔案

# Compiler options
OPT    := $(USE_OPT)
COPT   := $(USE_COPT)
CPPOPT := $(USE_CPPOPT)

# Garbage collection
ifeq ($(USE_LINK_GC),yes)
  OPT   += -ffunction-sections -fdata-sections -fno-common
  LDOPT := ,--gc-sections
else
  LDOPT :=
endif

# Linker extra options
ifneq ($(USE_LDOPT),)
  LDOPT := $(LDOPT),$(USE_LDOPT)
endif

# Link time optimizations
ifeq ($(USE_LTO),yes)
  OPT += -flto
endif

# FPU options default (Cortex-M4 and Cortex-M7 single precision).
ifeq ($(USE_FPU_OPT),)
  USE_FPU_OPT = -mfloat-abi=$(USE_FPU) -mfpu=fpv4-sp-d16
endif

# FPU-related options
ifeq ($(USE_FPU),)
  USE_FPU = no
endif
ifneq ($(USE_FPU),no)
  OPT    += $(USE_FPU_OPT)
  DDEFS  += -DCORTEX_USE_FPU=TRUE
  DADEFS += -DCORTEX_USE_FPU=TRUE
else
  DDEFS  += -DCORTEX_USE_FPU=FALSE
  DADEFS += -DCORTEX_USE_FPU=FALSE
endif

# Process stack size
ifeq ($(USE_PROCESS_STACKSIZE),)
  LDOPT := $(LDOPT),--defsym=__process_stack_size__=0x400
else
  LDOPT := $(LDOPT),--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE)
endif

# Exceptions stack size
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
  LDOPT := $(LDOPT),--defsym=__main_stack_size__=0x400
else
  LDOPT := $(LDOPT),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE)
endif

# Output directory and files
ifeq ($(BUILDDIR),)
  BUILDDIR = build
endif
ifeq ($(BUILDDIR),.)
  BUILDDIR = build
endif

# Dependencies directory
ifeq ($(DEPDIR),)
  DEPDIR = .dep
endif
ifeq ($(DEPDIR),.)
  DEPDIR = .dep
endif

OUTFILES := $(BUILDDIR)/$(PROJECT).elf \
            $(BUILDDIR)/$(PROJECT).hex \
            $(BUILDDIR)/$(PROJECT).bin \
            $(BUILDDIR)/$(PROJECT).dmp \
            $(BUILDDIR)/$(PROJECT).list

ifdef SREC
  OUTFILES += $(BUILDDIR)/$(PROJECT).srec
endif

# Source files groups and paths
ifeq ($(USE_THUMB),yes)
  TCSRC   += $(CSRC)
  TCPPSRC += $(CPPSRC)
else
  ACSRC   += $(CSRC)
  ACPPSRC += $(CPPSRC)
endif
ASRC      := $(ACSRC) $(ACPPSRC)
TSRC      := $(TCSRC) $(TCPPSRC)
SRCPATHS  := $(sort $(dir $(ASMXSRC)) $(dir $(ASMSRC)) $(dir $(ASRC)) $(dir $(TSRC)))

# Various directories
OBJDIR    := $(BUILDDIR)/obj
LSTDIR    := $(BUILDDIR)/lst

# Object files groups
ACOBJS    := $(addprefix $(OBJDIR)/, $(notdir $(ACSRC:.c=.o)))
ACPPOBJS  := $(addprefix $(OBJDIR)/, $(notdir $(ACPPSRC:.cpp=.o)))
TCOBJS    := $(addprefix $(OBJDIR)/, $(notdir $(TCSRC:.c=.o)))
TCPPOBJS  := $(addprefix $(OBJDIR)/, $(notdir $(TCPPSRC:.cpp=.o)))
ASMOBJS   := $(addprefix $(OBJDIR)/, $(notdir $(ASMSRC:.s=.o)))
ASMXOBJS  := $(addprefix $(OBJDIR)/, $(notdir $(ASMXSRC:.S=.o)))
OBJS      := $(ASMXOBJS) $(ASMOBJS) $(ACOBJS) $(TCOBJS) $(ACPPOBJS) $(TCPPOBJS)

# Paths
IINCDIR   := $(patsubst %,-I%,$(INCDIR) $(DINCDIR) $(UINCDIR))
LLIBDIR   := $(patsubst %,-L%,$(DLIBDIR) $(ULIBDIR))
LLIBDIR   += -L$(dir $(LDSCRIPT))

# Macros
DEFS      := $(DDEFS) $(UDEFS)
ADEFS     := $(DADEFS) $(UADEFS)

# Libs
LIBS      := $(DLIBS) $(ULIBS)

# Various settings
MCFLAGS   := -mcpu=$(MCU)
ODFLAGS   = -x --syms
ASFLAGS   = $(MCFLAGS) $(OPT) -Wa,-amhls=$(LSTDIR)/$(notdir $(<:.s=.lst)) $(ADEFS)
ASXFLAGS  = $(MCFLAGS) $(OPT) -Wa,-amhls=$(LSTDIR)/$(notdir $(<:.S=.lst)) $(ADEFS)
CFLAGS    = $(MCFLAGS) $(OPT) $(COPT) $(CWARN) -Wa,-alms=$(LSTDIR)/$(notdir $(<:.c=.lst)) $(DEFS)
CPPFLAGS  = $(MCFLAGS) $(OPT) $(CPPOPT) $(CPPWARN) -Wa,-alms=$(LSTDIR)/$(notdir $(<:.cpp=.lst)) $(DEFS)
LDFLAGS   = $(MCFLAGS) $(OPT) -nostartfiles $(LLIBDIR) -Wl,-Map=$(BUILDDIR)/$(PROJECT).map,--cref,--no-warn-mismatch,--library-path=$(RULESPATH)/ld,--script=$(LDSCRIPT)$(LDOPT)

# Thumb interwork enabled only if needed because it kills performance.
ifneq ($(strip $(TSRC)),)
  CFLAGS   += -DTHUMB_PRESENT
  CPPFLAGS += -DTHUMB_PRESENT
  ASFLAGS  += -DTHUMB_PRESENT
  ASXFLAGS += -DTHUMB_PRESENT
  ifneq ($(strip $(ASRC)),)
    # Mixed ARM and THUMB mode.
    CFLAGS   += -mthumb-interwork
    CPPFLAGS += -mthumb-interwork
    ASFLAGS  += -mthumb-interwork
    ASXFLAGS += -mthumb-interwork
    LDFLAGS  += -mthumb-interwork
  else
    # Pure THUMB mode, THUMB C code cannot be called by ARM asm code directly.
    CFLAGS   += -mno-thumb-interwork -DTHUMB_NO_INTERWORKING
    CPPFLAGS += -mno-thumb-interwork -DTHUMB_NO_INTERWORKING
    ASFLAGS  += -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -mthumb
    ASXFLAGS += -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -mthumb
    LDFLAGS  += -mno-thumb-interwork -mthumb
  endif
else
  # Pure ARM mode
  CFLAGS   += -mno-thumb-interwork
  CPPFLAGS += -mno-thumb-interwork
  ASFLAGS  += -mno-thumb-interwork
  ASXFLAGS += -mno-thumb-interwork
  LDFLAGS  += -mno-thumb-interwork
endif

# Generate dependency information
ASFLAGS  += -MD -MP -MF $(DEPDIR)/$(@F).d
ASXFLAGS += -MD -MP -MF $(DEPDIR)/$(@F).d
CFLAGS   += -MD -MP -MF $(DEPDIR)/$(@F).d
CPPFLAGS += -MD -MP -MF $(DEPDIR)/$(@F).d

# Paths where to search for sources
VPATH     = $(SRCPATHS)

#
# Makefile rules
#

all: PRE_MAKE_ALL_RULE_HOOK $(OBJS) $(OUTFILES) POST_MAKE_ALL_RULE_HOOK

PRE_MAKE_ALL_RULE_HOOK:

POST_MAKE_ALL_RULE_HOOK:

$(OBJS): | $(BUILDDIR) $(OBJDIR) $(LSTDIR) $(DEPDIR)

$(BUILDDIR):
ifneq ($(USE_VERBOSE_COMPILE),yes)
	@echo Compiler Options
	@echo $(CC) -c $(CFLAGS) -I. $(IINCDIR) main.c -o main.o
	@echo
endif
	@mkdir -p $(BUILDDIR)

$(OBJDIR):
	@mkdir -p $(OBJDIR)

$(LSTDIR):
	@mkdir -p $(LSTDIR)

$(DEPDIR):
	@mkdir -p $(DEPDIR)

$(ACPPOBJS) : $(OBJDIR)/%.o : %.cpp $(MAKEFILE_LIST)
ifeq ($(USE_VERBOSE_COMPILE),yes)
	@echo
	$(CPPC) -c $(CPPFLAGS) $(AOPT) -I. $(IINCDIR) $< -o [email protected]
else
	@echo Compiling $(<F)
	@$(CPPC) -c $(CPPFLAGS) $(AOPT) -I. $(IINCDIR) $< -o [email protected]
endif

$(TCPPOBJS) : $(OBJDIR)/%.o : %.cpp $(MAKEFILE_LIST)
ifeq ($(USE_VERBOSE_COMPILE),yes)
	@echo
	$(CPPC) -c $(CPPFLAGS) $(TOPT) -I. $(IINCDIR) $< -o [email protected]
else
	@echo Compiling $(<F)
	@$(CPPC) -c $(CPPFLAGS) $(TOPT) -I. $(IINCDIR) $< -o [email protected]
endif

$(ACOBJS) : $(OBJDIR)/%.o : %.c $(MAKEFILE_LIST)
ifeq ($(USE_VERBOSE_COMPILE),yes)
	@echo
	$(CC) -c $(CFLAGS) $(AOPT) -I. $(IINCDIR) $< -o [email protected]
else
	@echo Compiling $(<F)
	@$(CC) -c $(CFLAGS) $(AOPT) -I. $(IINCDIR) $< -o [email protected]
endif

$(TCOBJS) : $(OBJDIR)/%.o : %.c $(MAKEFILE_LIST)
ifeq ($(USE_VERBOSE_COMPILE),yes)
	@echo
	$(CC) -c $(CFLAGS) $(TOPT) -I. $(IINCDIR) $< -o [email protected]
else
	@echo Compiling $(<F)
	@$(CC) -c $(CFLAGS) $(TOPT) -I. $(IINCDIR) $< -o [email protected]
endif

$(ASMOBJS) : $(OBJDIR)/%.o : %.s $(MAKEFILE_LIST)
ifeq ($(USE_VERBOSE_COMPILE),yes)
	@echo
	$(AS) -c $(ASFLAGS) -I. $(IINCDIR) $< -o [email protected]
else
	@echo Compiling $(<F)
	@$(AS) -c $(ASFLAGS) -I. $(IINCDIR) $< -o [email protected]
endif

$(ASMXOBJS) : $(OBJDIR)/%.o : %.S $(MAKEFILE_LIST)
ifeq ($(USE_VERBOSE_COMPILE),yes)
	@echo
	$(CC) -c $(ASXFLAGS) $(TOPT) -I. $(IINCDIR) $< -o [email protected]
else
	@echo Compiling $(<F)
	@$(CC) -c $(ASXFLAGS) $(TOPT) -I. $(IINCDIR) $< -o [email protected]
endif

$(BUILDDIR)/$(PROJECT).elf: $(OBJS) $(LDSCRIPT)
ifeq ($(USE_VERBOSE_COMPILE),yes)
	@echo
	$(LD) $(OBJS) $(LDFLAGS) $(LIBS) -o [email protected]
else
	@echo Linking [email protected]
	@$(LD) $(OBJS) $(LDFLAGS) $(LIBS) -o [email protected]
endif

%.hex: %.elf
ifeq ($(USE_VERBOSE_COMPILE),yes)
	$(HEX) $< [email protected]
else
	@echo Creating [email protected]
	@$(HEX) $< [email protected]
endif

%.bin: %.elf
ifeq ($(USE_VERBOSE_COMPILE),yes)
	$(BIN) $< [email protected]
else
	@echo Creating [email protected]
	@$(BIN) $< [email protected]
endif

%.srec: %.elf
ifdef SREC
  ifeq ($(USE_VERBOSE_COMPILE),yes)
	$(SREC) $< [email protected]
  else
	@echo Creating [email protected]
	@$(SREC) $< [email protected]
  endif
endif

%.dmp: %.elf
ifeq ($(USE_VERBOSE_COMPILE),yes)
	$(OD) $(ODFLAGS) $< > [email protected]
	$(SZ) $<
else
	@echo Creating [email protected]
	@$(OD) $(ODFLAGS) $< > [email protected]
	@echo
	@$(SZ) $<
endif

%.list: %.elf
ifeq ($(USE_VERBOSE_COMPILE),yes)
	$(OD) -S $< > [email protected]
else
	@echo Creating [email protected]
	@$(OD) -S $< > [email protected]
	@echo
	@echo Done
endif

lib: $(OBJS) $(BUILDDIR)/lib$(PROJECT).a

$(BUILDDIR)/lib$(PROJECT).a: $(OBJS)
	@$(AR) -r [email protected] $^
	@echo
	@echo Done

clean: CLEAN_RULE_HOOK
	@echo Cleaning
	@echo - $(DEPDIR)
	@-rm -fR $(DEPDIR)/* $(BUILDDIR)/* 2>/dev/null
	@-if [ -d "$(DEPDIR)" ]; then rmdir -p --ignore-fail-on-non-empty $(subst ./,,$(DEPDIR)) 2>/dev/null; fi
	@echo - $(BUILDDIR)
	@-if [ -d "$(BUILDDIR)" ]; then rmdir -p --ignore-fail-on-non-empty $(subst ./,,$(BUILDDIR)) 2>/dev/null; fi
	@echo
	@echo Done

CLEAN_RULE_HOOK:

#
# Include the dependency files, should be the last of the makefile
#
-include $(wildcard $(DEPDIR)/*)

# *** EOF ***

這部分還沒有細緻分析



2. Chibios啟動程式碼



在這裡插入圖片描述



1.startup_stm32f7xx.mk檔案



#CHIbios通用STM32 F7XX啟動和CMSIS(微控制器軟體介面標準)檔案列表 ---List of the ChibiOS generic STM32F7xx startup and CMSIS files.

#變數定義
STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
   #變數定義       
STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
             $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
#變數定義
STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
             $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
             $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32F7xx \
             $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
             $(CHIBIOS)/os/common/ext/ST/STM32F7xx
#變數定義
STARTUPLD  = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld

#共享變數---- Shared variables
ALLXASMSRC += $(STARTUPASM)  //彙編檔案目錄
ALLCSRC    += $(STARTUPSRC)      //原始檔目錄
ALLINC     += $(STARTUPINC)          //標頭檔案包含

1.crt1.c

定義啟動程式碼時,需要的一些函式,這些函式在彙編中會跳轉過來

STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c #定義一個原始檔
/**
 * @file    ARMCMx/compilers/GCC/crt1.c
 * @brief   Startup stub functions.
 *
 * @addtogroup ARMCMx_GCC_STARTUP
 * @{
 */

#include <stdint.h>
#include <stdbool.h>

#include "cmparams.h"

/*===========================================================================*/
/*模組區域性定義---- Module local definitions.                                                 */
/*===========================================================================*/

#if !defined(CRT1_AREAS_NUMBER) || defined(__DOXYGEN__)
#define CRT1_AREAS_NUMBER                   8
#endif

#if (CRT1_AREAS_NUMBER < 0) || (CRT1_AREAS_NUMBER > 8)
#error "CRT1_AREAS_NUMBER must be within 0 and 8"
#endif

/*===========================================================================*/
/* 模組匯出變數。----Module exported variables.                                                */
/*===========================================================================*/

/*===========================================================================*/
/* 模組本地型別。---Module local types.                                                       */
/*===========================================================================*/

/**
 * @brief   要初始化的區域的型別。----Type of an area to be initialized.
 */
typedef struct
{
  uint32_t              *init_text_area;
  uint32_t              *init_area;
  uint32_t              *clear_area;
  uint32_t              *no_init_area;
} ram_init_area_t;

/*===========================================================================*/
/*區域性變數的模組。--- Module local variables.                                                   */
/*===========================================================================*/

#if (CRT1_AREAS_NUMBER > 0) || defined(__DOXYGEN__)
extern uint32_t __ram0_init_text__, __ram0_init__, __ram0_clear__, __ram0_noinit__;
#endif
#if (CRT1_AREAS_NUMBER > 1) || defined(__DOXYGEN__)
extern uint32_t __ram1_init_text__, __ram1_init__, __ram1_clear__, __ram1_noinit__;
#endif
#if (CRT1_AREAS_NUMBER > 2) || defined(__DOXYGEN__)
extern uint32_t __ram2_init_text__, __ram2_init__, __ram2_clear__, __ram2_noinit__;
#endif
#if (CRT1_AREAS_NUMBER > 3) || defined(__DOXYGEN__)
extern uint32_t __ram3_init_text__, __ram3_init__, __ram3_clear__, __ram3_noinit__;
#endif
#if (CRT1_AREAS_NUMBER > 4) || defined(__DOXYGEN__)
extern uint32_t __ram4_init_text__, __ram4_init__, __ram4_clear__, __ram4_noinit__;
#endif
#if (CRT1_AREAS_NUMBER > 5) || defined(__DOXYGEN__)
extern uint32_t __ram5_init_text__, __ram5_init__, __ram5_clear__, __ram5_noinit__;
#endif
#if (CRT1_AREAS_NUMBER > 6) || defined(__DOXYGEN__)
extern uint32_t __ram6_init_text__, __ram6_init__, __ram6_clear__, __ram6_noinit__;
#endif
#if (CRT1_AREAS_NUMBER > 7) || defined(__DOXYGEN__)
extern uint32_t __ram7_init_text__, __ram7_init__, __ram7_clear__, __ram7_noinit__;
#endif

/**
 * @brief  要初始化的區域的靜態表。---- Static table of areas to be initialized.
 */
#if (CRT1_AREAS_NUMBER > 0) || defined(__DOXYGEN__)
static const ram_init_area_t ram_areas[CRT1_AREAS_NUMBER] = {
  {&__ram0_init_text__, &__ram0_init__, &__ram0_clear__, &__ram0_noinit__},
#if (CRT1_AREAS_NUMBER > 1) || defined(__DOXYGEN__)
  {&__ram1_init_text__, &__ram1_init__, &__ram1_clear__, &__ram1_noinit__},
#endif
#if (CRT1_AREAS_NUMBER > 2) || defined(__DOXYGEN__)
  {&__ram2_init_text__, &__ram2_init__, &__ram2_clear__, &__ram2_noinit__},
#endif
#if (CRT1_AREAS_NUMBER > 3) || defined(__DOXYGEN__)
  {&__ram3_init_text__, &__ram3_init__, &__ram3_clear__, &__ram3_noinit__},
#endif
#if (CRT1_AREAS_NUMBER > 4) || defined(__DOXYGEN__)
  {&__ram4_init_text__, &__ram4_init__, &__ram4_clear__, &__ram4_noinit__},
#endif
#if (CRT1_AREAS_NUMBER > 5) || defined(__DOXYGEN__)
  {&__ram5_init_text__, &__ram5_init__, &__ram5_clear__, &__ram5_noinit__},
#endif
#if (CRT1_AREAS_NUMBER > 6) || defined(__DOXYGEN__)
  {&__ram6_init_text__, &__ram6_init__, &__ram6_clear__, &__ram6_noinit__},
#endif
#if (CRT1_AREAS_NUMBER > 7) || defined(__DOXYGEN__)
  {&__ram7_init_text__, &__ram7_init__, &__ram7_clear__, &__ram7_noinit__},
#endif
};
#endif

/*===========================================================================*/
/* Module local functions.                                                   */
/*===========================================================================*/

/*===========================================================================*/
/* Module exported functions.                                                */
/*===========================================================================*/

/**
 * @brief   與體系結構相關的核心初始化。---Architecture-dependent core initialization.
 * @details 在堆疊初始化之後和在資料和BSS段初始化之前立即呼叫此鉤子。This hook is invoked immediately after the stack initialization
 *          。---and before the DATA and BSS segments initialization.
 * @note    注意:這個函式是一個弱符號。----This function is a weak symbol.
 */
#if !defined(__DOXYGEN__)
__attribute__((weak))
#endif
/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/

//核心初始化函式,會被在彙編使用
void __core_init(void)
{

#if CORTEX_MODEL == 7
  SCB_EnableICache();//使能I-cache指令快取
  SCB_EnableDCache();//使能D-cache資料快取。
#endif
}

/**
 * @brief   早期初始化。-----Early initialization.
 * @details 在堆疊初始化之後和在資料和BSS段初始化之前立即呼叫此鉤子
 *                                   This hook is invoked immediately after the stack and core
 *                                   initialization and before the DATA and BSS segments
 *                                   initialization.
 * @note    注意:這個函式是一個弱符號----This function is a weak symbol.
 */
#if !defined(__DOXYGEN__)
__attribute__((weak))
#endif
/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/
#ifndef _ARDUPILOT_
void __early_init(void) {} //該函式在板層初始化完成
#endif
/*lint -restore*/

/**
 * @brief   後期初始化函式Late initialization.
 * @details This hook is invoked after the DATA and BSS segments
 *          initialization and before any static constructor. The
 *          default behavior is to do nothing.
 * @note    This function is a weak symbol.
 */
#if !defined(__DOXYGEN__)
__attribute__((weak))
#endif
/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/
#ifndef _ARDUPILOT_
void __late_init(void) {}//該函式在板層初始化完成
#endif
/*lint -restore*/

/**
 * @brief   Default @p main() function exit handler.
 * @details This handler is invoked or the @p main() function exit. The
 *          default behavior is to enter an infinite loop.
 * @note    This function is a weak symbol.
 */
#if !defined(__DOXYGEN__)
__attribute__((noreturn, weak))
#endif
/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/
void __default_exit(void) 
{
/*lint -restore*/

  while (true) 
  {
  }
}

/**
 * @brief  執行各種RAM區域的初始化彙編中使用--- Performs the initialization of the various RAM areas.
 */
void __init_ram_areas(void) 
{
#if CRT1_AREAS_NUMBER > 0
  const ram_init_area_t *rap = ram_areas;

  do {
    uint32_t *tp = rap->init_text_area;
    uint32_t *p = rap->init_area;

    /* Copying initialization data.*/
    while (p < rap->clear_area) 
    {
      *p = *tp;
      p++;
      tp++;
    }

    /* Zeroing clear area.*/
    while (p < rap->no_init_area) 
    {
      *p = 0;
      p++;
    }
    rap++;
  }
  while (rap < &ram_areas[CRT1_AREAS_NUMBER]);
#endif
}

/** @} */



上述檔案需要注意的函式:



1.核心初始化函式



//核心初始化函式,會被在彙編使用
void __core_init(void)
{

#if CORTEX_MODEL == 7
  SCB_EnableICache();//使能I-cache指令快取
  SCB_EnableDCache();//使能D-cache資料快取。
#endif
}


2.__early_init初始化函式



/***********************************************************************************************************************
*函式原型:void __early_init(void)
*函式功能:早期初始化
*修改日期:2018-10-30
*修改作者:cihang_uav
*備註資訊:
*************************************************************************************************************************/
void __early_init(void)
{
#ifndef STM32F100_MCUCONF //看到這應該明白了,這是那個協處理器
  stm32_gpio_init();
#endif
  stm32_clock_init();
}

函式:stm32_gpio_init()

static void stm32_gpio_init(void) 
{

  /* Enabling GPIO-related clocks, the mask comes from the
     registry header file.*/
  rccResetAHB1(STM32_GPIO_EN_MASK);
  rccEnableAHB1(STM32_GPIO_EN_MASK, true);

  /* Initializing all the defined GPIO ports.*/
#if STM32_HAS_GPIOA
  gpio_init(GPIOA, &gpio_default_config.PAData);
#endif
#if STM32_HAS_GPIOB
  gpio_init(GPIOB, &gpio_default_config.PBData);
#endif
#if STM32_HAS_GPIOC
  gpio_init(GPIOC, &gpio_default_config.PCData);
#endif
#if STM32_HAS_GPIOD
  gpio_init(GPIOD, &gpio_default_config.PDData);
#endif
#if STM32_HAS_GPIOE
  gpio_init(GPIOE, &gpio_default_config.PEData);
#endif
#if STM32_HAS_GPIOF
  gpio_init(GPIOF, &gpio_default_config.PFData);
#endif
#if STM32_HAS_GPIOG
  gpio_init(GPIOG, &gpio_default_config.PGData);
#endif
#if STM32_HAS_GPIOH
  gpio_init(GPIOH, &gpio_default_config.PHData);
#endif
#if STM32_HAS_GPIOI
  gpio_init(GPIOI, &gpio_default_config.PIData);
#endif
#if STM32_HAS_GPIOJ
  gpio_init(GPIOJ, &gpio_default_config.PJData);
#endif
#if STM32_HAS_GPIOK
  gpio_init(GPIOK, &gpio_default_config.PKData);
#endif
}

函式:stm32_clock_init(),有STM32F1和STM32F7都會使用

F1晶片時鐘

void stm32_clock_init(void) 
{

#if !STM32_NO_INIT
  /* HSI setup, it enforces the reset situation in order to handle possible
     problems with JTAG probes and re-initializations.*/
  RCC->CR |= RCC_CR_HSION;                  /* Make sure HSI is ON.         */
  while (!(RCC->CR & RCC_CR_HSIRDY))
    ;                                       /* Wait until HSI is stable.    */

  /* HSI is selected as new source without touching the other fields in
     CFGR. Clearing the register has to be postponed after HSI is the
     new source.*/
  RCC->CFGR &= ~RCC_CFGR_SW;                /* Reset SW, selecting HSI.     */
  while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
    ;                                       /* Wait until HSI is selected.  */

  /* Registers finally cleared to reset values.*/
  RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value.              */
  RCC->CFGR = 0;                            /* CFGR reset value.            */

#if STM32_HSE_ENABLED
#if defined(STM32_HSE_BYPASS)
  /* HSE Bypass.*/
  RCC->CR |= RCC_CR_HSEBYP;
#endif
  /* HSE activation.*/
  RCC->CR |= RCC_CR_HSEON;
  while (!(RCC->CR & RCC_CR_HSERDY))
    ;                                       /* Waits until HSE is stable.   */
#endif

#if STM32_LSI_ENABLED
  /* LSI activation.*/
  RCC->CSR |= RCC_CSR_LSION;
  while ((RCC->CSR & RCC_CSR_LSIRDY) == 0)
    ;                                       /* Waits until LSI is stable.   */
#endif

  /* Settings of various dividers and multipliers in CFGR2.*/
  RCC->CFGR2 = STM32_PLL3MUL | STM32_PLL2MUL | STM32_PREDIV2 |
               STM32_PREDIV1 | STM32_PREDIV1SRC;

  /* PLL2 setup, if activated.*/
#if STM32_ACTIVATE_PLL2
  RCC->CR |= RCC_CR_PLL2ON;
  while (!(RCC->CR & RCC_CR_PLL2RDY))
    ;                                        /* Waits until PLL2 is stable. */
#endif

  /* PLL3 setup, if activated.*/
#if STM32_ACTIVATE_PLL3
  RCC->CR |= RCC_CR_PLL3ON;
  while (!(RCC->CR & RCC_CR_PLL3RDY))
    ;                                        /* Waits until PLL3 is stable. */
#endif

  /* PLL1 setup, if activated.*/
#if STM32_ACTIVATE_PLL1
  RCC->CFGR |= STM32_PLLMUL | STM32_PLLSRC;
  RCC->CR   |= RCC_CR_PLLON;
  while (!(RCC->CR & RCC_CR_PLLRDY))
    ;                           /* Waits until PLL1 is stable.              */
#endif

  /* Clock settings.*/
#if STM32_HAS_OTG1
  RCC->CFGR = STM32_MCOSEL | STM32_OTGFSPRE | STM32_PLLMUL | STM32_PLLSRC |
              STM32_ADCPRE | STM32_PPRE2    | STM32_PPRE1  | STM32_HPRE;
#else
  RCC->CFGR = STM32_MCO    |                  STM32_PLLMUL | STM32_PLLSRC |
              STM32_ADCPRE | STM32_PPRE2    | STM32_PPRE1  | STM32_HPRE;
#endif

  /* Flash setup and final clock selection.   */
  FLASH->ACR = STM32_FLASHBITS; /* Flash wait states depending on clock.    */

  /* Switching to the configured clock source if it is different from HSI.*/
#if (STM32_SW != STM32_SW_HSI)
  RCC->CFGR |= STM32_SW;        /* Switches on the selected clock source.   */
  while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2))
    ;
#endif

#if !STM32_HSI_ENABLED
  RCC->CR &= ~RCC_CR_HSION;
#endif
#endif /* !STM32_NO_INIT */
}

F7晶片時鐘

void stm32_clock_init(void) 
{

#if !STM32_NO_INIT
  /* PWR clock enabled.*/
#if defined(HAL_USE_RTC) && defined(RCC_APB1ENR_RTCEN)
  RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_RTCEN;
#else
  RCC->APB1ENR = RCC_APB1ENR_PWREN;
#endif

  /* PWR initialization.*/
  PWR->CR1 = STM32_VOS;

  /* HSI setup, it enforces the reset situation in order to handle possible
     problems with JTAG probes and re-initializations.*/
  RCC->CR |= RCC_CR_HSION;                  /* Make sure HSI is ON.         */
  while (!(RCC->CR & RCC_CR_HSIRDY))
    ;                                       /* Wait until HSI is stable.    */

  /* HSI is selected as new source without touching the other fields in
     CFGR. Clearing the register has to be postponed after HSI is the
     new source.*/
  RCC->CFGR &= ~RCC_CFGR_SW;                /* Reset SW, selecting HSI.     */
  while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
    ;                                       /* Wait until HSI is selected.  */

  /* Registers finally cleared to reset values.*/
  RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value.              */
  RCC->CFGR = 0;                            /* CFGR reset value.            */

#if STM32_HSE_ENABLED
  /* HSE activation.*/
#if defined(STM32_HSE_BYPASS)
  /* HSE Bypass.*/
  RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP;
#else
  /* No HSE Bypass.*/
  RCC->CR |= RCC_CR_HSEON;
#endif
  while ((RCC->CR & RCC_CR_HSERDY) == 0)
    ;                           /* Waits until HSE is stable.               */
#endif

#if STM32_LSI_ENABLED
  /* LSI activation.*/
  RCC->CSR |= RCC_CSR_LSION;
  while ((RCC->CSR & RCC_CSR_LSIRDY) == 0)
    ;                           /* Waits until LSI is stable.               */
#endif

#if STM32_ACTIVATE_PLL
  /* PLL activation.*/
  RCC->PLLCFGR = STM32_PLLQ | STM32_PLLSRC | STM32_PLLP | STM32_PLLN |
                 STM32_PLLM;
  RCC->CR |= RCC_CR_PLLON;

  /* Synchronization with voltage regulator stabilization.*/
  while ((PWR->CSR1 & PWR_CSR1_VOSRDY) == 0)
    ;                           /* Waits until power regulator is stable.   */

#if STM32_OVERDRIVE_REQUIRED
  /* Overdrive activation performed after activating the PLL in order to save
     time as recommended in RM in "Entering Over-drive mode" paragraph.*/
  PWR->CR1 |= PWR_CR1_ODEN;
  while (!(PWR->CSR1 & PWR_CSR1_ODRDY))
      ;
  PWR->CR1 |= PWR_CR1_ODSWEN;
  while (!(PWR->CSR1 & PWR_CSR1_ODSWRDY))
      ;
#endif /* STM32_OVERDRIVE_REQUIRED */

  /* Waiting for PLL lock.*/
  while (!(RCC->CR & RCC_CR_PLLRDY))
    ;
#endif /* STM32_OVERDRIVE_REQUIRED */

#if STM32_ACTIVATE_PLLI2S
  /* PLLI2S activation.*/
  RCC->PLLI2SCFGR = STM32_PLLI2SR | STM32_PLLI2SN;
  RCC->CR |= RCC_CR_PLLI2SON;

  /* Waiting for PLL lock.*/
  while (!(RCC->CR & RCC_CR_PLLI2SRDY))
    ;
#endif

#if STM32_ACTIVATE_PLLSAI
  /* PLLSAI activation.*/
  RCC->PLLSAICFGR = STM32_PLLSAIR | STM32_PLLSAIQ | STM32_PLLSAIP |
                    STM32_PLLSAIN;
  RCC->CR |= RCC_CR_PLLSAION;

  /* Waiting for PLL lock.*/
  while (!(RCC->CR & RCC_CR_PLLSAIRDY))
    ;
#endif

  /* Other clock-related settings (dividers, MCO etc).*/
  RCC->CFGR = STM32_MCO2SEL | STM32_MCO2PRE | STM32_MCO1PRE | STM32_I2SSRC |
              STM32_MCO1SEL | STM32_RTCPRE  | STM32_PPRE2   | STM32_PPRE1  |
              STM32_HPRE;

  /* DCKCFGR1 register initialization, note, must take care of the _OFF
     pseudo settings.*/
  {
    uint32_t dckcfgr1 = STM32_PLLI2SDIVQ | STM32_PLLSAIDIVQ | STM32_PLLSAIDIVR;
#if STM32_SAI2SEL != STM32_SAI2SEL_OFF
    dckcfgr1 |= STM32_SAI2SEL;
#endif
#if STM32_SAI1SEL != STM32_SAI1SEL_OFF
    dckcfgr1 |= STM32_SAI1SEL;
#endif
    RCC->DCKCFGR1 = dckcfgr1;
  }

  /* Peripheral clock sources.*/
  RCC->DCKCFGR2 = STM32_SDMMC2SEL | STM32_SDMMC1SEL | STM32_CK48MSEL  |
                  STM32_CECSEL    | STM32_LPTIM1SEL | STM32_I2C4SEL   |
                  STM32_I2C3SEL   | STM32_I2C2SEL   | STM32_I2C1SEL   |
                  STM32_UART8SEL  | STM32_UART7SEL  | STM32_USART6SEL |
                  STM32_UART5SEL  | STM32_UART4SEL  | STM32_USART3SEL |
                  STM32_USART2SEL | STM32_USART1SEL;

  /* Flash setup.*/
  FLASH->ACR = FLASH_ACR_ARTEN | FLASH_ACR_PRFTEN | STM32_FLASHBITS;

  /* Switching to the configured clock source if it is different from HSI.*/
#if (STM32_SW != STM32_SW_HSI)
  RCC->CFGR |= STM32_SW;        /* Switches on the selected clock source.   */
  while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2))
    ;
#endif
#endif /* STM32_NO_INIT */

  /* SYSCFG clock enabled here because it is a multi-functional unit shared
     among multiple drivers.*/
  rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true);
}


3.__late_init函式



/***********************************************************************************************************************
*函式原型:void __late_init(void)
*函式功能:後期初始化
*修改日期:2018-10-30
*修改作者:cihang_uav
*備註資訊:
*************************************************************************************************************************/
void __late_init(void)
{
  halInit(); //硬體抽象層初始化
  chSysInit();//chibios系統初始化
#if CH_CFG_USE_HEAP == TRUE
  malloc_init(); //記憶體處理初始化
#endif
#ifdef HAL_USB_PRODUCT_ID
  setup_usb_strings(); //初始化usb字串
#endif
}



1. halInit()函式


void halInit(void)
{

  /* 初始化OS的硬體抽象層Initializes the OS Abstraction Layer.*/
  osalInit();

  /*平臺低層初始化---- Platform low level initializations.*/
  hal_lld_init();

#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
#if defined(PAL_NEW_INIT)
  palInit();
#else
  palInit(&pal_default_config);
#endif
#endif
#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__)
  adcInit();
#endif
#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__)
  canInit();
#endif
#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__)
  cryInit();
#endif
#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__)
  dacInit();
#endif
#if (HAL_USE_EXT == TRUE) || defined(__DOXYGEN__)
  extInit();
#endif
#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__)
  gptInit();
#endif
#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
  i2cInit();
#endif
#if (HAL_USE_I2S == TRUE) || defined(__DOXYGEN__)
  i2sInit();
#endif
#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__)
  icuInit();
#endif
#if (HAL_USE_EICU == TRUE) || defined(__DOXYGEN__)
  eicuInit();
#endif
#if (HAL_USE_MAC == TRUE) || defined(__DOXYGEN__)
  macInit();
#endif
#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__)
  pwmInit();
#endif
#if (HAL_USE_QSPI == TRUE) || defined(__DOXYGEN__)
  qspiInit();
#endif
#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
  sdInit();
#endif
#if (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__)
  sdcInit();
#endif
#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
  spiInit();
#endif
#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
  uartInit();
#endif
#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
  usbInit();
#endif
#if (HAL_USE_MMC_SPI == TRUE) || defined(__DOXYGEN__)
  mmcInit();
#endif
#if (HAL_USE_SERIAL_USB == TRUE) || defined(__DOXYGEN__)
  sduInit();
#endif
#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__)
  rtcInit();
#endif
#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__)
  wdgInit();
#endif

  /* Community driver overlay initialization.*/
#if defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__)
#if (HAL_USE_COMMUNITY == TRUE) || defined(__DOXYGEN__)
  halCommunityInit();
#endif
#endif

  /*板專用初始化----- Board specific initialization.*/
  boardInit();

/*
 *  The ST driver is a special case, it is only initialized if the OSAL is
 *  configured to require it.
 *  ST驅動器是一種特殊情況,只有在OSAR是初始化時才初始化。
 *  配置為需要它。
 */
#if OSAL_ST_MODE != OSAL_ST_MODE_NONE
  stInit();
#endif
}


2. chSysInit()函式


void chSysInit(void)
{

  _scheduler_init();
  _vt_init();
  _trace_init();

#if CH_DBG_SYSTEM_STATE_CHECK == TRUE
  ch.dbg.isr_cnt  = (cnt_t)0;
  ch.dbg.lock_cnt = (cnt_t)0;
#endif
#if CH_CFG_USE_TM == TRUE
  _tm_init();
#endif
#if CH_CFG_USE_MEMCORE == TRUE
  _core_init();
#endif
#if CH_CFG_USE_HEAP == TRUE
  _heap_init();
#endif
#if CH_CFG_USE_FACTORY == TRUE
  _factory_init();
#endif
#if CH_DBG_STATISTICS == TRUE
  _stats_init();
#endif

#if CH_CFG_NO_IDLE_THREAD == FALSE
  /* Now this instructions flow becomes the main thread.*/
#if CH_CFG_USE_REGISTRY == TRUE
  currp = _thread_init(&ch.mainthread, (const char *)&ch_debug, NORMALPRIO);
#else
  currp = _thread_init(&ch.mainthread, "main", NORMALPRIO);
#endif
#else
  /* Now this instructions flow becomes the idle thread.*/
  currp = _thread_init(&ch.mainthread, "idle", IDLEPRIO);
#endif

#if CH_DBG_ENABLE_STACK_CHECK == TRUE
  {
    /* Setting up the base address of the static main thread stack, the
       symbol must be provided externally.*/
    extern stkalign_t __main_thread_stack_base__;
    currp->wabase = &__main_thread_stack_base__;
  }
#elif CH_CFG_USE_DYNAMIC == TRUE
  currp->wabase = NULL;
#endif

  /* Setting up the caller as current thread.*/
  currp->state = CH_STATE_CURRENT;

  /* Port layer initialization last because it depend on some of the
     initializations performed before.*/
  port_init();

#if CH_DBG_STATISTICS == TRUE
  /* Starting measurement for this thread.*/
  chTMStartMeasurementX(&currp->stats);
#endif

  /* Initialization hook.*/
  CH_CFG_SYSTEM_INIT_HOOK();

  /* It is alive now.*/
  chSysEnable();

#if CH_CFG_NO_IDLE_THREAD == FALSE
  {
    static const thread_descriptor_t idle_descriptor = {
      "idle",
      THD_WORKING_AREA_BASE(ch_idle_thread_wa),
      THD_WORKING_AREA_END(ch_idle_thread_wa),
      IDLEPRIO,
      _idle_thread,
      NULL
    };

    /* This thread has the lowest priority in the system, its role is just to
       serve interrupts in its context while keeping the lowest energy saving
       mode compatible with the system status.*/
    (void) chThdCreate(&idle_descriptor);
  }
#endif
}


3. malloc_init()函式



void malloc_init(void)
{
#if defined(CCM_RAM_SIZE_KB)
    chHeapObjectInit(&ccm_heap, (void *)CCM_BASE_ADDRESS, CCM_RAM_SIZE_KB*1024);
#endif

#if defined(DTCM_RAM_SIZE_KB)
    chHeapObjectInit(&dtcm_heap, (void *)DTCM_BASE_ADDRESS, DTCM_RAM_SIZE_KB*1024);
#endif

#if DMA_RESERVE_SIZE != 0
    /*
      create a DMA reserve heap, to ensure we keep some memory for DMA
      safe memory allocations
     */
    void *dma_reserve = malloc_dtcm(DMA_RESERVE_SIZE);
    if (!dma_reserve) {
        dma_reserve = chHeapAllocAligned(NULL, DMA_RESERVE_SIZE, MIN_ALIGNMENT);
    }
    chHeapObjectInit(&dma_reserve_heap, dma_reserve, DMA_RESERVE_SIZE);
#endif //#if DMA_RESERVE_SIZE != 0
}


4. setup_usb_strings()函式


void setup_usb_strings(void)
{
    setup_usb_string(&vcom_strings[1], HAL_USB_STRING_MANUFACTURER, vcom_buffers[0]); //"ArduPilot"
    setup_usb_string(&vcom_strings[2], HAL_USB_STRING_PRODUCT, vcom_buffers[1]);      //"%BOARD%"
    setup_usb_string(&vcom_strings[3], HAL_USB_STRING_SERIAL, vcom_buffers[2]);       //"%SERIAL%"
}

4.記憶體初始化函式

/**
 * @brief  執行各種RAM區域的初始化彙編中使用--- Performs the initialization of the various RAM areas.
 */
void __init_ram_areas(void)
{
#if CRT1_AREAS_NUMBER > 0
  const ram_init_area_t *rap = ram_areas;

  do {
    uint32_t *tp = rap->init_text_area;
    uint32_t *p = rap->init_area;

    /* Copying initialization data.*/
    while (p < rap->clear_area)
    {
      *p = *tp;
      p++;
      tp++;
    }

    /* Zeroing clear area.*/
    while (p < rap->no_init_area)
    {
      *p = 0;
      p++;
    }
    rap++;
  }
  while (rap < &ram_areas[CRT1_AREAS_NUMBER]);
#endif
}


2.彙編檔案



STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
             $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S


包含兩個彙編檔案crt0_v7m.S和vectors.S



1.crt0_v7m.S核心啟動檔案


/**
/**
 * @file    crt0_v7m.S
 * @brief   Generic ARMv7-M (Cortex-M3/M4/M7) startup file for ChibiOS.
 *
 * @addtogroup ARMCMx_GCC_STARTUP_V7M
 * @{
 */

/*===========================================================================*/
/* Module constants.                                                         */
/*===========================================================================*/

#if !defined(FALSE) || defined(__DOXYGEN__)
#define FALSE                               0
#endif

#if !defined(TRUE) || defined(__DOXYGEN__)
#define TRUE                                1
#endif

#define CONTROL_MODE_PRIVILEGED             0
#define CONTROL_MODE_UNPRIVILEGED           1
#define CONTROL_USE_MSP                     0
#define CONTROL_USE_PSP                     2
#define CONTROL_FPCA                        4

#define FPCCR_ASPEN                         (1 << 31)
#define FPCCR_LSPEN                         (1 << 30)

#define SCB_VTOR                            0xE000ED08
#define SCB_CPACR                           0xE000ED88
#define SCB_FPCCR                           0xE000EF34
#define SCB_FPDSCR                          0xE000EF3C

/*===========================================================================*/
/*模組預編譯設定------Module pre-compile time settings.                                         */
/*===========================================================================*/

/**
 * @brief強制初始化MSP-----------Enforces initialization of MSP.
 * @note    This is required if the boot process is not reliable for whatever
 *          reason (bad ROMs, bad bootloaders, bad debuggers=.
 * 這是必需的,如果引導過程是不可靠的,無論什麼原因(壞ROM,壞載入程式,壞偵錯程式=)。
 */
#if !defined(CRT0_FORCE_MSP_INIT) || defined(__DOXYGEN__)
#define CRT0_FORCE_MSP_INIT                 TRUE
#endif

/**
 * @briefVTor特殊暫存器初始化--------------VTOR special register initialization.
 * @detailsVTor初始化為指向向量表-----------VTOR is initialized to point to the vectors table.
 */
#if !defined(CRT0_VTOR_INIT) || defined(__DOXYGEN__)
#define CRT0_VTOR_INIT                      TRUE
#endif

/**
 * @brief      浮點運算單元初始化開關-----   FPU initialization switch.
 */
#if !defined(CRT0_INIT_FPU) || defined(__DOXYGEN__)
#if defined(CORTEX_USE_FPU) || defined(__DOXYGEN__)
#define CRT0_INIT_FPU                       CORTEX_USE_FPU
#else
#define CRT0_INIT_FPU                       FALSE
#endif
#endif

/**
 * @brief 控制特殊暫存器初始化值。-------  Control special register initialization value.
 * @details The system is setup to run in privileged mode using the PSP
 *          stack (dual stack mode).
 *該系統設定為使用PSP棧(雙棧模式)以特權模式執行。
 */
#if !defined(CRT0_CONTROL_INIT) || defined(__DOXYGEN__)
#define CRT0_CONTROL_INIT                   (CONTROL_USE_PSP |              \
                                             CONTROL_MODE_PRIVILEGED)
#endif

/**
 * @brief 核心初始化開關。----------Core initialization switch.
 */
#if !defined(CRT0_INIT_CORE) || defined(__DOXYGEN__)
#define CRT0_INIT_CORE                      TRUE
#endif

/**
 * @brief  堆疊段初始化開關---------Stack segments initialization switch.
 */
#if !defined(CRT0_STACKS_FILL_PATTERN) || defined(__DOXYGEN__)
#define CRT0_STACKS_FILL_PATTERN            0x55555555
#endif

/**
 * @brief  堆疊段初始化開關。--------Stack segments initialization switch.
 */
#if !defined(CRT0_INIT_STACKS) || defined(__DOXYGEN__)
#define CRT0_INIT_STACKS                    TRUE
#endif

/**
 * @brief  資料段初始化開關。-------- DATA segment initialization switch.
 */
#if !defined(CRT0_INIT_DATA) || defined(__DOXYGEN__)
#define CRT0_INIT_DATA                      TRUE
#endif

/**
 * @briefBSS(BSS段通常是指用來存放程式中未初始化的全域性變數和靜態變數的一塊記憶體區域。)段初始化開關--------BSS segment initialization switch.
 */
#if !defined(CRT0_INIT_BSS) || defined(__DOXYGEN__)
#define CRT0_INIT_BSS                       TRUE
#endif

/**
 * @brief RAM區域初始化開關--------------  RAM areas initialization switch.
 */
#if !defined(CRT0_INIT_RAM_AREAS) || defined(__DOXYGEN__)
#define CRT0_INIT_RAM_AREAS                 TRUE
#endif

/**
 * @brief   建構函式呼叫開關。--------------Constructors invocation switch.
 */
#if !defined(CRT0_CALL_CONSTRUCTORS) || defined(__DOXYGEN__)
#define CRT0_CALL_CONSTRUCTORS              TRUE
#endif

/**
 * @brief   解構函式呼叫開關。--------------Destructors invocation switch.
 */
#if !defined(CRT0_CALL_DESTRUCTORS) || defined(__DOXYGEN__)
#define CRT0_CALL_DESTRUCTORS               TRUE
#endif

/**
 * @brief  FPU(浮點運算) FPCCR暫存器初始化值-----FPU FPCCR register initialization value.
 * @note    Only used if @p CRT0_INIT_FPU is equal to @p TRUE.
 */
#if !defined(CRT0_FPCCR_INIT) || defined(__DOXYGEN__)
#define CRT0_FPCCR_INIT                     (FPCCR_ASPEN | FPCCR_LSPEN)
#endif

/**
 * @brief   暫存器初始化值CPACR register initialization value.
 * @note    Only used if @p CRT0_INIT_FPU is equal to @p TRUE.
 */
#if !defined(CRT0_CPACR_INIT) || defined(__DOXYGEN__)
#define CRT0_CPACR_INIT                     0x00F00000
#endif

/*=======================================================================================================================================*/
/*程式碼段---- Code section.
*Doxygen是一種開源跨平臺的,以類似JavaDoc風格描述的文件系統,完全支援C、C++、Java、Objective-C和IDL語言,部分支援PHP、C#。
*註釋的語法與Qt-Doc、KDoc和JavaDoc相容。Doxygen可以從一套歸檔原始檔開始,生成HTML格式的線上類瀏覽器,或離線的LATEX、RTF參考手冊。
*MRS 指令:  對狀態暫存器CPSR和SPSR進行讀操作。通過讀CPSR可以獲得當前處理器的工作狀態。讀SPSR暫存器可以獲得進入異常前的處理器狀態(因為只有異常模式下有SPSR暫存器)。

*MSR指令:    對狀態暫存器CPSR和SPSR進行寫操作。與MRS配合使用,可以實現對CPSR或SPSR暫存器的讀-修改-寫操作,可以切換處理器模式、或者允許/禁止IRQ/FIQ中斷等。                                                        */
/*=======================================================================================================================================*/

#if !defined(__DOXYGEN__)

                .syntax unified     //是一個指示,說明下面的指令是ARM和THUMB通用格式的
                .cpu    cortex-m3   //CPU核心
#if CRT0_INIT_FPU == TRUE
                .fpu    fpv4-sp-d16 //浮點運算
#else
                .fpu    softvfp
#endif

                .thumb             //thumb指令格式
                .text              //程式碼段

/*
 * CRT0進入點------CRT0 entry point.
 */
                .align  2         //4位元組對齊
                .thumb_func
                .global _crt0_entry
_crt0_entry:
                /*中斷是全域性遮蔽的---- Interrupts are globally masked initially.*/
                cpsid   i

#if CRT0_FORCE_MSP_INIT == TRUE
                /*MSP堆疊指標初始化--- MSP stack pointers initialization.*/
                ldr     r0, =__main_stack_end__
                msr     MSP, r0
#endif

                /*PSP堆疊指標初始化----- PSP stack pointers initialization.*/
                ldr     r0, =__process_stack_end__
                msr     PSP, r0

#if CRT0_VTOR_INIT == TRUE
                ldr     r0, =_vectors
                movw    r1, #SCB_VTOR & 0xFFFF
                movt    r1, #SCB_VTOR >> 16
                str     r0, [r1]
#endif

#if CRT0_INIT_FPU == TRUE
                /*FPU FPCCR暫存器初始化------- FPU FPCCR initialization.*/
                movw    r0, #CRT0_FPCCR_INIT & 0xFFFF
                movt    r0, #CRT0_FPCCR_INIT >> 16
                movw    r1, #SCB_FPCCR & 0xFFFF
                movt    r1, #SCB_FPCCR >> 16
                str     r0, [r1]
                dsb
                isb

                /*CPACR初始化---------- CPACR initialization.*/
                movw    r0, #CRT0_CPACR_INIT & 0xFFFF
                movt    r0, #CRT0_CPACR_INIT >> 16
                movw    r1, #SCB_CPACR & 0xFFFF
                movt    r1, #SCB_CPACR >> 16
                str     r0, [r1]
                dsb
                isb

                /*FPU FPSCR初始化清除----- FPU FPSCR initially cleared.*/
                mov     r0, #0
                vmsr    FPSCR, r0

                /*FPU FPDSCR初始化清除---- FPU FPDSCR initially cleared.*/
                movw    r1, #SCB_FPDSCR & 0xFFFF
                movt    r1, #SCB_FPDSCR >> 16
                str     r0, [r1]

                /*在控制暫存器中強制執行FPCA位--- Enforcing FPCA bit in the CONTROL register.*/
                movs    r0, #CRT0_CONTROL_INIT | CONTROL_FPCA

#else
                movs    r0, #CRT0_CONTROL_INIT
#endif

                /*配置暫存器控制初始化---- CONTROL register initialization as configured.*/
                msr     CONTROL, r0
                isb

#if CRT0_INIT_CORE == TRUE
                /*跳轉到核心初始化,該函式在crt1.c中實現-----Core initialization.*/
                bl      __core_init  //BL Label ;跳轉到Label對應的地址,並且把跳轉前的下條指令地址儲存到LR
#endif

                /*跳轉到早期初始化------Early initialization.*/
                bl      __early_init

#if CRT0_INIT_STACKS == TRUE
                ldr     r0, =CRT0_STACKS_FILL_PATTERN
                /* Main Stack initialization. Note, it assumes that the
                   stack size is a multiple of 4 so the linker file must
                   ensure this.*/
                 //主棧初始化。注意,它假定堆疊大小是4的倍數,因此連結器檔案必須確保這一點。
                ldr     r1, =__main_stack_base__
                ldr     r2, =__main_stack_end__
msloop:
                cmp     r1, r2  //比較指令
                itt     lo       //接下來的兩條指令條件執行
                strlo   r0, [r1], #4
                blo     msloop   //小於(無符號數)跳轉

                /* Process Stack initialization. Note, it assumes that the
                   stack size is a multiple of 4 so the linker file must
                   ensure this.*/
                //程序堆疊初始化。注意,它假定堆疊大小是4的倍數,因此連結器檔案必須確保這一點。
                ldr     r1, =__process_stack_base__
                ldr     r2, =__process_stack_end__
psloop:
                cmp     r1, r2
                itt     lo
                strlo   r0, [r1], #4
                blo     psloop
#endif

#if CRT0_INIT_DATA == TRUE
                /*Data initialization. Note, it assumes that the DATA size
                  is a multiple of 4 so the linker file must ensure this.*/
                //資料初始化。注意,它假定資料大小是4的倍數,因此連結器檔案必須確保這一點。
                ldr     r1, =_textdata_start
                ldr     r2, =_data_start
                ldr     r3, =_data_end
dloop:
                cmp     r2, r3
                ittt    lo
                ldrlo   r0, [r1], #4
                strlo   r0, [r2], #4
                blo     dloop
#endif

#if CRT0_INIT_BSS == TRUE
                /* BSS initialization. Note, it assumes that the DATA size
                  is a multiple of 4 so the linker file must ensure this.*/
                //BSS初始化。注意,它假定資料大小是4的倍數,因此連結器檔案必須確保這一點
                //BSS存放的是未初始化的全域性變數和靜態變數,資料段存放的是初始化後的全域性變數和靜態變數。
                //BSS(Block Started by Symbol)通常是指用來存放程式中未初始化的全域性變數和靜態變數的一塊記憶體區域
                movs    r0, #0
                ldr     r1, =_bss_start
                ldr     r2, =_bss_end
bloop:
                cmp     r1, r2
                itt     lo
                strlo   r0, [r1], #4
                blo     bloop
#endif

#if CRT0_INIT_RAM_AREAS == TRUE
                /*記憶體區域初始化------RAM areas initialization.*/
                bl      __init_ram_areas
#endif

                /*後期初始化,該函式在板層board.c中實現----- Late initialization..*/
                bl      __late_init

#if CRT0_CALL_CONSTRUCTORS == TRUE
                /*建構函式的呼叫---- Constructors invocation.*/
                ldr     r4, =__init_array_start
                ldr     r5, =__init_array_end
initloop:
                cmp     r4, r5
                bge     endinitloop  //大於或等於才跳
                ldr     r1, [r4], #4
                blx     r1
                b       initloop    //跳轉,不返回
endinitloop:
#endif

                /*主程式呼叫,包含返回值R0。---- Main program invocation, r0 contains the returned value.*/
                bl      main   //該函式將會跳轉到標準的C++,應用main函式,然後呼叫arducopter中的main()函式

#if CRT0_CALL_DESTRUCTORS == TRUE
                /*解構函式呼叫---- Destructors invocation.*/
                ldr     r4, =__fini_array_start
                ldr     r5, =__fini_array_end
finiloop:
                cmp     r4, r5
                bge     endfiniloop
                ldr     r1, [r4], #4
                blx     r1
                b       finiloop
endfiniloop:
#endif

                /*分支到定義的退出處理程式---- Branching to the defined exit handler.*/
                b       __default_exit

#endif /* !defined(__DOXYGEN__) */

/** @} */




2.vectors.S中斷向量表


#if !defined(__DOXYGEN__)

        .syntax unified
        .cpu    cortex-m0
        .thumb

        .section    .vectors, "ax"
        .align      4
        .globl      _vectors
_vectors:
        .long       __main_stack_end__
        .long       Reset_Handler
        .long       NMI_Handler
        .long       HardFault_Handler
        .long       MemManage_Handler
        .long       BusFault_Handler
        .long       UsageFault_Handler
        .long       Vector1C
        .long       Vector20
        .long       Vector24
        .long       Vector28
        .long       SVC_Handler
        .long       DebugMon_Handler
        .long       Vector34
        .long       PendSV_Handler
        .long       SysTick_Handler
        .long       Vector40,   Vector44,   Vector48,   Vector4C
#if CORTEX_NUM_VECTORS > 4
        .long       Vector50,   Vector54,   Vector58,   Vector5C
#endif
#if CORTEX_NUM_VECTORS > 8
        .long       Vector60,   Vector64,   Vector68,   Vector6C
#endif
#if CORTEX_NUM_VECTORS > 12
        .long       Vector70,   Vector74,   Vector78,   Vector7C
#endif
#if CORTEX_NUM_VECTORS > 16
        .long       Vector80,   Vector84,   Vector88,   Vector8C
#endif
#if CORTEX_NUM_VECTORS > 20
        .long       Vector90,   Vector94,   Vector98,   Vector9C
#endif
#if CORTEX_NUM_VECTORS > 24
        .long       VectorA0,   VectorA4,   VectorA8,   VectorAC
#endif
#if CORTEX_NUM_VECTORS > 28
        .long       VectorB0,   VectorB4,   VectorB8,   VectorBC
#endif
........後面內容省略......


3. Chibios run()函式學習



1.HAL_ChibiOS的run()函式




void HAL_ChibiOS::run(int argc, char * const argv[], Callbacks* callbacks) const
{
    /*
     * -系統初始化-------------------------------------System initializations.
     * -Chibios 硬體抽象層初始化,也就是進行驅動配置--------ChibiOS HAL initialization, this also initializes the configured device drivers
     * -和執行特殊的板層配置-----------------------------and performs the board-specific initializations.
     * -核心初始化、主函式()成為一個執行緒,然後啟用RTOS------ Kernel initialization, the main() function becomes a thread and the
     *   RTOS is active.
     */

#ifdef HAL_USB_PRODUCT_ID
  setup_usb_strings(); //動態分配USB描述符字串,建議先不要去研究這個
#endif
    
#ifdef HAL_STDOUT_SERIAL
    //標準輸出初始化--------STDOUT Initialistion
    SerialConfig stdoutcfg =
    {
      HAL_STDOUT_BAUDRATE,
      0,
      USART_CR2_STOP1_BITS,
      0
    };
    sdStart((SerialDriver*)&HAL_STDOUT_SERIAL, &stdoutcfg);
#endif

    assert(callbacks);       //用來讓程式測試條件,如果條件正確繼續執行,如果條件錯誤,報錯。
    g_callbacks = callbacks; //函式定義傳遞

    //接管執行main------------Takeover main
    main_loop();
}


2.HAL_ChibiOS的main_loop()函式



static void main_loop()
{
    daemon_task = chThdGetSelfX(); //返回當前執行緒

    /*
      把main loop的優先順序切換到高優先順序-----switch to high priority for main loop
     */
    chThdSetPriority(APM_MAIN_PRIORITY); //180

#ifdef HAL_I2C_CLEAR_BUS
    //- Clear all I2C Buses. This can be needed on some boards which
    // can get a stuck I2C peripheral on boot
    //清除所有的I2C匯流排。這可能需要在一些板上,可以得到一個卡住的I2C外圍裝置啟動。
    ChibiOS::I2CBus::clear_all();
#endif

#if STM32_DMA_ADVANCED
    ChibiOS::Shared_DMA::init(); //不使能DMA
#endif
    peripheral_power_enable();   //啟用外圍電源
        
    hal.uartA->begin(115200);   //初始化USB的波特率

#ifdef HAL_SPI_CHECK_CLOCK_FREQ
    //SPI時鐘頻率的可選測試---- optional test of SPI clock frequencies
    ChibiOS::SPIDevice::test_clock_freq();
#endif 

    //初始化SD卡和檔案系統-----Setup SD Card and Initialise FATFS bindings
    sdcard_init();

    hal.uartB->begin(38400);  //GPS波特率38400
    hal.uartC->begin(57600);  //串列埠波特率設定
    hal.analogin->init();     //模擬輸入初始化,主要測試ADC功能,檢查電源電壓


    hal.scheduler->init();   //初始化任務init執行緒

    /*
        run setup() at low priority to ensure CLI doesn't hang the system, and to allow initial sensor read loops to run
     */

    //以低優先順序執行SETUP()以確保CLI(命令列介面)不掛起系統,並允許初始感測器讀取迴圈執行。
    hal_chibios_set_priority(APM_STARTUP_PRIORITY); //APM_STARTUP_PRIORITY=10

    schedulerInstance.hal_initialized(); //_hal_initialized = true

    g_callbacks->setup();                 //呼叫應用層的setup()函式
    hal.scheduler->system_initialized(); //系統初始化

    thread_running = true;
    chRegSetThreadName(SKETCHNAME);
    
    /*
      main loop切換到低優先順序-------switch to high priority for main loop
     */
    chThdSetPriority(APM_MAIN_PRIORITY);

    hal.uartG->printf("UARTG\r\n"); //自己新增列印函式


    while (true)
    {
        g_callbacks->loop();  //呼叫APP的loop執行緒

        /*
          give up 250 microseconds of time if the INS loop hasn't
          called delay_microseconds_boost(), to ensure low priority
          drivers get a chance to run. Calling
          delay_microseconds_boost() means we have already given up
          time from the main loop, so we don't need to do it again
          here
          如果INS迴路回撥Delay-MySudiSsBooSth()函式沒有響應,則放棄250微秒的時間。
         以確保低優先順序。有機會執行。回撥延遲函式delay_microseconds_boost意味著我們已經放棄了主迴路迴圈,所以我們不需要再做一次。
         */
        hal.uartG->printf("MMM\r\n"); //自己新增列印函式
        if (!schedulerInstance.check_called_boost())
        {
        	hal.uartG->printf("NNN\r\n"); //自己新增列印函式
            hal.scheduler->delay_microseconds(250);
        }
    }
    thread_running = false;
}




3.HAL_ChibiOS的init()函式



  • hal.scheduler->init(); //初始化任務init執行緒


相關推薦

Ardupilot chibios編譯啟動main函式學習2

目錄 文章目錄 目錄 摘要 1. Chibios編譯過程 2. Chibios啟動程式碼 1.startup_stm32f7xx.mk檔案 1.crt1.c 1.核心初始化函式

TensorFlow 入門 第一課--基本函式學習2:tf.nn.conv2d 、tf.contrib.layers.flatten、tf.nn.max_pool 詳解

Tensorflow 提供了一些內建的API實現了CNN網路結構中的卷積,池化,全連線網路等運算操作。tf.nn.conv2d(input,filter, strides, padding, data_

Ardupilot chibios函式學習1

目錄 文章目錄 目錄 摘要 0序言 第一部分chibios主函式 **(1)主回撥函式入口** **(2)主回撥函式入口** **(3)主回撥函式入口** **(4)主回撥函式入口** 1.函式h

輸入m個學生每個學生有4門課在主調函式中輸入學生的相關資訊編寫三個函式1求第一門課的平均分; (2)找出有兩門課以上不及格的學生並輸出他們的學號和全部成績要求用指標函式實現:fl

  輸入m個學生,每個學生有4門課,在主調函式中輸入學生的相關資訊,編寫三個函式: (1)求第一門課的平均分; (2)找出有兩門課以上不及格的學生,並輸出他們的學號和全部成績,要求用指標函式實現:float*Search(float(*p)[4],int n); (3)找出

如何發起、防禦和測試XSS攻擊我們用DVWA來學習

上一篇我們瞭解了XSS攻擊的原理,並且利用DVWA嘗試了簡單的XSS攻擊,這一篇我們來實現更復雜的攻擊,然後探討防禦機制和測試理念。   前面我們通過指令碼注入讓網頁彈出了使用者cookie資訊,可以光彈窗是沒有什麼用的,接下來我們想辦法把這些資訊傳送出去。   2.1 使用反射型

com4j學習2:Visio自定義模具和形狀並新增連線點

前言: 既然我們想繪製跟自己業務相關的圖形,並讀取Visio圖形中的結構資訊,那麼我們自然會想到要自定義圖形,本文詳細講解如何自定義圖形。 正文: 首先我們要明白什麼是模具,什麼是形狀,以及兩者之間的關係?模具就相當於一個容器,裡面有很多個形狀,我們可

JAVA學習2——輸入學生的5門成績計算平均成績

import java.util.Scanner; public class Demo01 { public static void main( String[] args ) { System.out.println( "請輸入學生姓名" ); Scann

spring cloud 學習2核心: Eureka: 提供服務註冊和發現 註冊中心負載均衡故障轉移

官方描述:雲端服務發現,一個基於 REST 的服務,用於定位服務,以實現雲端中間層服務發現和故障轉移 Eureka 一個服務中心,一個註冊中心,將可以提供的服務都註冊到這個元件中, ,其他呼叫者需要的時候去註冊中心去獲取,然後再呼叫,避免了服務間的直接呼叫,實現了服務間的解耦

Knockout學習2之observableArray監控陣列展示下拉框

ko對於陣列下拉框,監控跟蹤屬性值關鍵字為:observableArray,繫結值關鍵字為:options例子如下:@{ ViewBag.Title = "Index2"; } <h2>Index2</h2> <head>

理解神經網路從簡單的例子開始2使用python建立多層神經網路

這篇文章將講解如何使用python建立多層神經網路。在閱讀這篇文章之前,建議先閱讀上一篇文章:理解神經網路,從簡單的例子開始。講解的是單層的神經網路。如果你已經閱讀了上一篇文章,你會發現這篇文章的程式碼和上一篇基本相同,理解起來也相對容易。 上一篇文章使用了9

樹的孩子表示法樹的兄弟表示法樹的儲存結構詳解,資料結構-樹的學習2

樹的儲存結構: 孩子表示法:把每個結點的孩子結點排列起來,以單鏈表作儲存結構,則n個結點有n個孩子連結串列,如果是葉子結點則此單鏈表為空。然後n個頭指標又組成一個線性表,採用順序儲存結構,存放進一個一維陣列中。 為此,設計兩種結點結構,一個是孩子連結串列的孩子結點    |

引用 html選項卡效果資料夾式的選單2

引用 荊釵 的 html選項卡效果,資料夾式的選單(2)<HTML><HEAD><script>var Num=4; //這裡是增加選項卡的數目var carNum=2+Numfunction document.onselectstart(){var obj=event.

Zabbix 4.0添加Linux監控主機2

include onf blog 地址 x86_64 ges 監控模板 根據 logfile 一、安裝Zabbix-agent 以下操作在所需加入監控的Linux主機上進行:實驗為,192.168.100.51 # rpm -ivh http://repo.zabbix.c

OpenCV計算機視覺學習2——影象算術運算 & 掩膜mask操作數值計算影象融合邊界填充

如果需要處理的原圖及程式碼,請移步小編的GitHub地址   傳送門:請點選我   如果點選有誤:https://github.com/LeBron-Jian/ComputerVisionPractice   在OpenCV中我們經常會遇到一個名字:Mask(掩膜)。很多函式都使用到它,那麼這個Mask到底是

嵌入式開發學習2<S5PV210啟動過程詳解>

nan ios eight img 啟動方式 margin 需要 外部 啟動 基本概念: 內存:   SRAM 靜態內存 特點:容量小、價格高,優點:不需要軟件初始化,上電就能用。   DRAM 動態內存 特點:容量大、價格低,缺點:上電不能用,需要軟件初始化。  

python函式手冊2

logging 配置方式 顯式建立記錄器Logger、處理器Handler和格式化器Formatter,並進行相關設定; 通過簡單方式進行配置,使用basicConfig()函式直接進行配置; 通過配置檔案進行配置,使用fileConfig()函式讀取配置檔案

Python學習2——函式

1、函式的引數 (1)要注意定義可變引數和關鍵字引數的語法: *args是可變引數,args接收的是一個tuple; **kw是關鍵字引數,kw接收的是一個dict。 (2)呼叫函式時如何傳入可變引數和關鍵字引數的語法: 可變引數既可以直接傳入:func(1, 2, 3),又

python內建函式彙總2

原文地址:https://docs.python.org/3/library/functions.html 函式名 功能 id(object) 返回物件object的識別符號,識別符號型別為整數

vue原始碼學習2——建構函式

vue原始碼學習——建構函式 下圖從上到下是從package.json沿路找到建構函式的路徑;從下到上是建構函式的構造路徑,檢視建構函式添加了什麼方法。        PS: 以上的流程掛載了很多方法,但是注意:這個時候方法並沒有被呼

redis啟動報錯詳解2Unrecoverable error: corrupted cluster config file.

➜ 7000 ../redis-server redis.conf & [1] 11045 11045:C 24 Oct 2018 19:26:52.320 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 1104