色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

FSP庫啟動文件詳解

CHANBAEK ? 來源:doc.embedfire.com ? 作者:doc.embedfire.com ? 2023-02-15 15:48 ? 次閱讀

FSP庫啟動文件詳解

13.1. 什么是啟動文件

啟動文件是系統上電復位后執行的第一個程序。 主要做了以下工作:

  1. 初始化堆棧。
  2. 使能FPU(float-point unit,即浮點單元)。
  3. 定位中斷向量表。
  4. 配置系統時鐘
  5. 啟用CORTEX-M33棧監視器。
  6. 初始化C語言運行環境。
  7. 初始化變量SystemCoreClock,這個變量存放的是處理器時鐘的頻率。
  8. 初始化用于觸發NVIC中斷的ELC(Event Link Controller)事件。
  9. 初始化IO口

13.2. 啟動文件代碼講解

13.2.1. 復位程序

14-0:復位程序

void Reset_Handler (void)
{
    /* 使用BSP對系統進行初始化. */
    SystemInit();

    /* Call user application. */
    main();

    while (1)
    {
        /* Infinite Loop. */
    }
}

這是系統上電或復位后執行的第一個程序,使用BSP對系統進行初始化,隨后通過main函數進入用戶代碼。 BSP負責使MCU從復位狀態進入到用戶的應用程序。 在到達用戶的應用程序之前,BSP設置棧、堆、時鐘、中斷、C語言運行環境和堆棧監視器。

13.2.2. 棧區初始化

14-1:棧區初始化

/* Main stack */
static uint8_t g_main_stack[BSP_CFG_STACK_MAIN_BYTES + BSP_TZ_STACK_SEAL_SIZE]
BSP_ALIGN_VARIABLE(BSP_STACK_ALIGNMENT)   //宏展開后為“__attribute__((aligned(8)))”
BSP_PLACE_IN_SECTION(BSP_SECTION_STACK);  //宏展開后為“__attribute__((section( ".stack"))) __attribute__((__used__))”

棧是一種先進后出的內存結構,存放函數的參數值、返回值、局部變量等,在程序運行過程中實時加載和釋放。 如果代碼中使用的局部變量和函數嵌套較多,則需要增加棧區的大小,需要注意的是, 棧區分配大小不能超過RAM的大小。 宏“BSP_CFG_STACK_MAIN_BYTES”可以在FSP Configuration的“BSP”屬性欄中的“RA Common”中通過修改“Main stack size”設置,默認為1KB(0x400 B)。

宏“BSP_TZ_STACK_SEAL_SIZE”用于封裝棧頂,便于檢測并阻止攻擊者對棧的攻擊。 若使用TrustZone,則該宏為8,反之為0。

代碼中的“BSP_ALIGN_VARIABLE(BSP_STACK_ALIGNMENT)” ,宏展開后為“ attribute ((aligned(8)))”,

“BSP_PLACE_IN_SECTION(BSP_SECTION_STACK)”,宏展開后為“ attribute ((section( “.stack”))) attribute ((used ))”

__attribute__可以設置類型,變量或函數的屬性,下面將逐一解釋修飾“g_main_stack”的屬性。

  • attribute ((aligned(8))):參數“aligned”指定被修飾對象的對齊方式(以字節為單位)。 “aligned(8)”則意為棧區在分配時將 采用8字節對齊方式。
  • attribute ((section( “.stack”))):參數“section”可以將變量定義到指定的輸入段中。 “section( “.stack”)”則意為將棧 放到名為“.stack”的輸入段中。
  • attribute (( used )):參數“ used ”告訴編譯器,這個變量會被使用,即使沒被調用也不會被編譯器警告, 之所以要用這個屬性修飾變量,是因為使用C或C++語言的用戶一般不會直接操作棧, 絕大部分時候這個變量是不會被用戶直接調用的。

13.2.3. 堆區初始化

14-2:堆區初始化

/* Heap */
#if (BSP_CFG_HEAP_BYTES > 0)  //若分配堆區大小為0則不進行初始化

BSP_DONT_REMOVE static uint8_t g_heap[BSP_CFG_HEAP_BYTES]
BSP_ALIGN_VARIABLE(BSP_STACK_ALIGNMENT)  //宏展開后為“__attribute__((aligned(8)))”
BSP_PLACE_IN_SECTION(BSP_SECTION_HEAP);  //宏展開后為“__attribute__((section(".heap"))) __attribute__((__used__))”
#endif

堆沒有棧那樣先進后出的順序,用于動態內存分配,一般由程序員使用malloc和free進行分配和釋放。 BSP_CFG_HEAP_BYTES用于配置堆區大小,當這個宏定義為0,則不對堆區進行初始化。 由于MCU中可用的片上SRAM相對較少,且缺乏內存保護,這意味著必須非常小心地控制堆的使用,以避免內存泄漏、溢出和試圖過度分配。 因此默認堆區大小被設置為0。 如果用戶需要(例如一些C標準庫函數需要使用堆), 可以在FSP Configuration中“BSP”屬性欄的“RA Common”中通過修改“Heap size”來設置堆區大小。

代碼中的BSP_DONT_REMOVE只有在使用IAR編譯器的情況下才會被宏展開為“__root”,意為強制編譯, 保證沒有使用的函數或者變量也能夠包含在目標代碼中。 其他環境下這個宏沒有宏展開,可以忽略。

宏“BSP_ALIGN_VARIABLE(BSP_STACK_ALIGNMENT)”同樣也修飾棧,這里的作用和上文的修飾棧的宏相同。

宏“BSP_PLACE_IN_SECTION(BSP_SECTION_HEAP)”展開后為“ attribute ((section(“.heap”))) attribute ((used ))”, 這個宏與上文的BSP_PLACE_IN_SECTION(BSP_SECTION_STACK)作用差不多,只是參數“section”不同,這里的“section(“.heap”)” 意為將堆放到名為“.heap”的輸入段中。

13.2.4. 中斷向量表初始化

14-3:中斷向量表初始化

/* Vector table. */
BSP_DONT_REMOVE const exc_ptr_t __Vectors[BSP_CORTEX_VECTOR_TABLE_ENTRIES]
BSP_PLACE_IN_SECTION(BSP_SECTION_FIXED_VECTORS) =
{
    (exc_ptr_t) (&g_main_stack[0] + BSP_CFG_STACK_MAIN_BYTES), /*      Initial Stack Pointer     */
    Reset_Handler,                                             /*      Reset Handler             */
    NMI_Handler,                                               /*      NMI Handler               */
    HardFault_Handler,                                         /*      Hard Fault Handler        */
    MemManage_Handler,                                         /*      MPU Fault Handler         */
    BusFault_Handler,                                          /*      Bus Fault Handler         */
    UsageFault_Handler,                                        /*      Usage Fault Handler       */
    SecureFault_Handler,                                       /*      Secure Fault Handler      */
    0,                                                         /*      Reserved                  */
    0,                                                         /*      Reserved                  */
    0,                                                         /*      Reserved                  */
    SVC_Handler,                                               /*      SVCall Handler            */
    DebugMon_Handler,                                          /*      Debug Monitor Handler     */
    0,                                                         /*      Reserved                  */
    PendSV_Handler,                                            /*      PendSV Handler            */
    SysTick_Handler,                                           /*      SysTick Handler           */
};

宏“BSP_PLACE_IN_SECTION(BSP_SECTION_FIXED_VECTORS)”展開后為“ attribute ((section(“.fixed_vectors”))) attribute (( ** used** ))”。 意為將表放到名為“.fixed_vectors”的輸入段中,并且即使不被使用,編譯器也不會警告。

13.2.5. 系統初始化()

14-4:SystemInit()

void SystemInit (void)
{
#if __FPU_USED

    /* Enable the FPU only when it is used.
     * Code taken from Section 7.1, Cortex-M4 TRM (DDI0439C) */

    /* Set bits 20-23 (CP10 and CP11) to enable FPU. */
    SCB->CPACR = (uint32_t) CP_MASK;
#endif

#if BSP_TZ_SECURE_BUILD
    uint32_t * p_main_stack_top = (uint32_t *) __Vectors[0];
    *p_main_stack_top = BSP_TZ_STACK_SEAL_VALUE;
#endif

    .............. //由于篇幅所限,省略中間代碼

    /* Call Post C runtime initialization hook. */
    R_BSP_WarmStart(BSP_WARM_START_POST_C);

    /* Initialize ELC events that will be used to trigger NVIC interrupts. */
    bsp_irq_cfg();

    /* Call any BSP specific code. No arguments are needed so NULL is sent. */
    bsp_init(NULL);
}

這是MCU進入Reset_Handler后執行的第一個函數,正如函數的字面意思,用于初始化MCU和運行環境, 運行完這段代碼后將由main進入用戶的hal_entry函數,由于代碼較長,下面將分為幾個部分對代碼進行分析。

13.2.5.1. 使能FPU

14-5:使能 FPU

#if __FPU_USED

    /* Enable the FPU only when it is used.
     * Code taken from Section 7.1, Cortex-M4 TRM (DDI0439C) */

    /* Set bits 20-23 (CP10 and CP11) to enable FPU. */
    SCB->CPACR = (uint32_t) CP_MASK;
#endif

FPU(Float-Point Unit)支持單精度加、減、乘、除、乘、累加、平方根運算。 它還提供了定點和浮點數據格式以及浮點常量之間的轉換的命令。

13.2.5.2. 封裝棧頂

14-6:封裝棧頂

#if BSP_TZ_SECURE_BUILD
    uint32_t * p_main_stack_top = (uint32_t *) __Vectors[0];
    *p_main_stack_top = BSP_TZ_STACK_SEAL_VALUE;
#endif

這里獲取棧頂指針,并將棧頂賦值為“BSP_TZ_STACK_SEAL_VALUE”,它的宏展開為0xFEF5EDA5,不能用作程序地址,因為地址范圍從 0xE0000000到0xFFFFFFFF是不可執行的。 這個過程被稱為封棧(Sealing Stack),過程如圖。 如果有人針對棧進行攻擊,那么這個地址 的值會被覆蓋掉,這會被檢測并阻止。

圖

13.2.5.3. 設置中斷向量表的基地址

14-7:設置中斷向量表的基地址

#if !BSP_TZ_NONSECURE_BUILD
    SCB->VTOR = (uint32_t) &__Vectors;
#endif

這里通過直接設置SCB->VTOR的值來設置中斷向量表的基地址。 在非安全項目中,這一步會被跳過。

13.2.5.4. 熱啟動回調函數

14-8:函數聲明

void R_BSP_WarmStart(bsp_warm_start_event_t event) __attribute__((weak));

14-9:熱啟動回調函數

void R_BSP_WarmStart (bsp_warm_start_event_t event)
{
    if (BSP_WARM_START_RESET == event)
    {
        /* C runtime environment has not been setup so you cannot use globals. System clocks are not setup. */
    }

    if (BSP_WARM_START_POST_CLOCK == event)
    {
        /* C runtime environment has not been setup so you cannot use globals. Clocks have been initialized. */
    }
    else if (BSP_WARM_START_POST_C == event)
    {
        /* C runtime environment, system clocks, and pins are all setup. */
    }
    else
    {
        /* Do nothing */
    }
}

這個函數會被調用三次,分別在時鐘初始化前,時鐘初始化后和C語言運行環境初始化后被調用,這個函數被聲明了“weak”屬性,因此其可以被用戶重寫。 在默認情況下,這個函數會在hal_entry.c中被重寫。

14-10:hal_entry中被重寫的函數

void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
    if (BSP_WARM_START_RESET == event)
    {
#if BSP_FEATURE_FLASH_LP_VERSION != 0  //因為RA6M5上沒有這個功能,因此可以忽略這部分

        /* Enable reading from data flash. */
        R_FACI_LP->DFLCTL = 1U;

        /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
         * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
#endif
    }

    if (BSP_WARM_START_POST_C == event)
    {
        /* C runtime environment and system clocks are setup. */

        /* Configure pins. */
        R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
    }
}

默認情況下,這里只有在C語言運行環境初始化后,也就是函數傳入參數為“BSP_WARM_START_POST_C”時,才會對用戶在FSP Configuration中配置的引腳進行初始化,其他時候這里不會進行操作。

13.2.5.5. 時鐘初始化

14-11:時鐘初始化

bsp_clock_init();

根據bsp_clock_cfg.h中的設置來設置所有系統時鐘,這些配置來自于FSP Configuration中的Clocks選項卡。

13.2.5.6. 啟用CORTEX-M33棧監視器

14-12:啟用CORTEX-M33棧監視器

/* Use CM33 stack monitor. */
__set_MSPLIM(BSP_PRV_STACK_LIMIT);

設置主堆棧指針限制。 沒有ARMv8-M主擴展的設備(即Cortex-M23)缺乏不安全的堆棧指針限制寄存器,因此在非安全模式下此操作被忽略。

13.2.5.7. 初始化C語言運行環境

13.2.5.7.1. 初始化BSS區

14-13:BSS區初始化

/* Zero out BSS */
 #if defined(__ARMCC_VERSION)
    memset((uint8_t *) &Image$$BSS$$ZI$$Base, 0U, (uint32_t) &Image$$BSS$$ZI$$Length);
 #elif defined(__GNUC__)
    memset(&__bss_start__, 0U, ((uint32_t) &__bss_end__ - (uint32_t) &__bss_start__));
 #elif defined(__ICCARM__)
    memset((uint32_t *) __section_begin(".bss"), 0U, (uint32_t) __section_size(".bss"));
 #endif

BSS(Block Start by Symbol)指用來存放程序中未初始化的全局變量和靜態變量的一塊內存區域,在這里BSS區所有數據都會被初始化為0。

13.2.5.7.2. 初始化data區

14-14:DATA區初始化

/* Copy initialized RAM data from ROM to RAM. */
 #if defined(__ARMCC_VERSION)
    memcpy((uint8_t *) &Image$$DATA$$Base, (uint8_t *) &Load$$DATA$$Base, (uint32_t) &Image$$DATA$$Length);
 #elif defined(__GNUC__)
    memcpy(&__data_start__, &__etext, ((uint32_t) &__data_end__ - (uint32_t) &__data_start__));
 #elif defined(__ICCARM__)
    memcpy((uint32_t *) __section_begin(".data"), (uint32_t *) __section_begin(".data_init"),
           (uint32_t) __section_size(".data"));

data區是用來存放已初始化的全局變量,靜態變量和常量的一塊內存區域。 在這段代碼,數據會從ROM被拷貝到RAM的data區。

13.2.5.7.3. 調用全局對象的構造函數

14-15:調用全局或靜態對象的構造函數

#if defined(__ARMCC_VERSION)
int32_t count = Image$$INIT_ARRAY$$Limit - Image$$INIT_ARRAY$$Base;
for (int32_t i = 0; i < count; i++)
{
    void (* p_init_func)(void) =
        (void (*)(void))((uint32_t) &Image$$INIT_ARRAY$$Base + (uint32_t) Image$$INIT_ARRAY$$Base[i]);
    p_init_func();
}

#elif defined(__GNUC__)
    int32_t count = __init_array_end - __init_array_start;
    for (int32_t i = 0; i < count; i++)
    {
        __init_array_start[i]();
    }

#elif defined(__ICCARM__)
    void const * pibase = __section_begin("SHT$$PREINIT_ARRAY");
    void const * ilimit = __section_end("SHT$$INIT_ARRAY");
    __call_ctors(pibase, ilimit);
#endif

RA系列MCU是支持使用C++語言進行開發的,這段代碼用于調用C++的全局對象的構造函數。

13.2.5.8. 初始化SystemCoreClock的值

14-16:初始化SystemCoreClock的值

/* Initialize SystemCoreClock variable. */
SystemCoreClockUpdate();

初始化SystemCoreClock的值,這個值表示處理器時鐘的頻率,默認為200MHz。

13.2.5.9. 初始化ICU

14-17:初始化 ICU

/* Initialize ELC events that will be used to trigger NVIC interrupts. */
bsp_irq_cfg();

這個函數將初始化ICU(Interrupt Control Unit),即中斷控制器,以便配置的ELC事件觸發NVIC中斷。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • mcu
    mcu
    +關注

    關注

    146

    文章

    17168

    瀏覽量

    351408
  • 中斷
    +關注

    關注

    5

    文章

    898

    瀏覽量

    41524
  • 代碼
    +關注

    關注

    30

    文章

    4791

    瀏覽量

    68677
  • FSP
    FSP
    +關注

    關注

    0

    文章

    34

    瀏覽量

    7143
  • 啟動文件
    +關注

    關注

    0

    文章

    15

    瀏覽量

    2258
收藏 人收藏

    評論

    相關推薦

    詳解STM32啟動文件

    本文對STM32啟動文件startup_stm32f10x_hd.s的代碼進行講解,此文件的代碼在任何一個STM32F10x工程中都可以找到。
    發表于 06-10 17:19 ?1003次閱讀
    <b class='flag-5'>詳解</b>STM32<b class='flag-5'>啟動</b><b class='flag-5'>文件</b>

    啟動文件和HAL

    STM32F7xx —— 啟動文件和HAL 目錄STM32F7xx —— 啟動文件和HAL
    發表于 08-04 09:25

    【野火啟明6M5開發板體驗】開箱+認識開發板+資料

    10. 初識瑞薩FSP固件11. GPIO輸出——使用FSP點亮LED燈12. GPIO輸入——按鍵檢測13. FSP
    發表于 12-20 23:28

    BMP圖片文件詳解

    BMP圖片文件詳解,很好的資料,快來學習吧
    發表于 02-18 14:16 ?0次下載

    GIF文件格式詳解

    GIF文件格式詳解 GIF文件格式詳解 GIF文件格式詳解
    發表于 05-24 10:53 ?2次下載

    stm32f103zet6啟動文件詳解

    啟動文件這部分和arm11的還是很類似的,是開發板上電后執行的第一段代碼,唯一不同的感覺的就是比arm11的啟動文件簡單多了,下面的一些代碼解釋都是和arm11對照來說的,上代碼吧,先
    發表于 11-07 14:17 ?1.2w次閱讀

    詳解如何用AD生成Gerber文件

    詳解如何用AD生成Gerber文件
    發表于 11-23 11:07 ?0次下載

    STM32啟動文件內容詳解

    前言使用STM32單片機時候,必須導入對應型號的啟動文件。這個筆記在于對于啟動文件的內容的分析,基于基本的stm32F103型號的單片機的啟動
    發表于 11-30 13:21 ?8次下載
    STM32<b class='flag-5'>啟動</b><b class='flag-5'>文件</b>內容<b class='flag-5'>詳解</b>

    KEIL中啟動文件詳解(匯編語言)

    KEIL中啟動文件詳解(匯編語言)
    發表于 12-04 12:06 ?8次下載
    KEIL中<b class='flag-5'>啟動</b><b class='flag-5'>文件</b><b class='flag-5'>詳解</b>(匯編語言)

    STM32 之 標準外設版USB驅動詳解(架構+文件+函數+使用說明+示例程序)

    STM32 之 標準外設版USB驅動詳解(架構+文件+函數+使用說明+示例程序)
    發表于 12-08 20:36 ?0次下載
    STM32 之 標準外設版USB驅動<b class='flag-5'>庫</b><b class='flag-5'>詳解</b>(架構+<b class='flag-5'>文件</b>+函數+使用說明+示例程序)

    STM32F10-啟動文件解析

    STM32F10系列啟動文件詳解
    發表于 12-16 16:58 ?3次下載
    STM32F10-<b class='flag-5'>啟動</b><b class='flag-5'>文件</b>解析

    3-STM32啟動文件詳解

    啟動文件文章目錄啟動文件啟動文件簡介1--初始化棧指針MSP=_initial_sp。2--初始
    發表于 12-27 18:41 ?14次下載
    3-STM32<b class='flag-5'>啟動</b><b class='flag-5'>文件</b><b class='flag-5'>詳解</b>

    STM32啟動文件學習筆記

    STM32啟動文件學習筆記一、Stack–棧EQU:宏定義的偽指令,就是給數字取一個符號名,相當于C語言中的defineSPACE:分配內存空間AREA:告訴匯編語言一個新的代碼段或數據段
    發表于 12-27 18:44 ?2次下載
    STM32<b class='flag-5'>啟動</b><b class='flag-5'>庫</b><b class='flag-5'>文件</b>學習筆記

    FSP啟動文件說明

    FSP啟動文件說明
    的頭像 發表于 06-04 08:06 ?486次閱讀
    <b class='flag-5'>FSP</b><b class='flag-5'>庫</b><b class='flag-5'>啟動</b><b class='flag-5'>文件</b>說明

    RA MCU CANFD在FSP中的配置詳解

    RA MCU CANFD在FSP中的配置詳解
    的頭像 發表于 06-19 08:06 ?546次閱讀
    RA MCU CANFD在<b class='flag-5'>FSP</b>中的配置<b class='flag-5'>詳解</b>
    主站蜘蛛池模板: 三级黄色一级视频| 男人桶女人j的视频在线观看 | 国产成人亚洲精品午夜国产馆| 麻豆E奶女教师国产精品| 伊人精品视频直播| 精品一区二区三区高清免费观看| 亚洲成人综合在线| 国产中文在线观看| 亚洲精品免费在线视频| 国产一区二区三区内射高清| 小学生偷拍妈妈视频遭性教育 | 人妻 中文无码 中出| 99手机在线视频| 日本吃孕妇奶水免费观看| 把腿张开再深点好爽宝贝 | 国产午夜精品久久理论片| 亚洲a视频在线| 精品一卡2卡三卡4卡乱码精品视频| 亚洲精品午夜VA久久成人| 九九免费的视频| 2022精品福利在线小视频| 欧美阿v在线天堂| TIMI1TV天美传媒在线观看| 日本美女色| 国产人成无码视频在线观看| 亚洲精品中文字幕制| 久章草一区二区| jizzhd中国| 我和妽妽在厨房里的激情区二区 | 久久91精品国产91久久户| 优优色影院| 青柠视频在线观看高清HD| 国产成人高清精品免费5388密| 午夜国产精品影院在线观看| 久久99热成人精品国产| 99爱在线精品视频网站| 视频一区视频二区ae86| 精品一区二区三区色花堂| 99久久网站| 亚洲 日本 欧美 中文字幕| 久久精品中文騷妇女内射|