欧美性猛交xxxx免费看_牛牛在线视频国产免费_天堂草原电视剧在线观看免费_国产粉嫩高清在线观看_国产欧美日本亚洲精品一5区

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

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

3天內(nèi)不再提示

ARM Cortex-M學習筆記:Cortex-M啟動流程詳解

CHANBAEK ? 來源:嵌入式實驗樓 ? 作者: BruceOu ? 2023-05-15 14:54 ? 次閱讀

開發(fā)環(huán)境:

處理器STM32F103

MDK:5.30

STM32立方體MX:6.0.1

對于我們常用的桌面操作系統(tǒng)而言,我們在開發(fā)應(yīng)用時,并不關(guān)心系統(tǒng)的初始化,絕大多數(shù)應(yīng)用程序是在操作系統(tǒng)運行后才開始運行的,操作系統(tǒng)已經(jīng)提供了一個合適的運行環(huán)境,然而對于嵌入式設(shè)備而言,在設(shè)備上電后,所有的一切都需要由開發(fā)者來設(shè)置,這里處理器是沒有堆棧,沒有中斷,更沒有外圍設(shè)備,這些工作是需要軟件來指定的,而且不同的CPU類型、 不同大小的內(nèi)存和不同種類的外設(shè),其初始化工作都是不同的。 本文將以STMF103(基于Cortex-M3)為例進行講解。

在開始正式講解之前,你需要了解ARM寄存器匯編以及反編譯相關(guān)的知識,這些可以參考筆者博文。

下面我們就來具體看一下用戶從Flash啟動STM32的過程,主要講解從上電復位到main函數(shù)的過程。 主要有以下步驟:

1.初始化堆棧指針 SP=_initial_sp,初始化 PC 指針=Reset_Handler

2.初始化中斷向量表

3.配置系統(tǒng)時鐘

4.調(diào)用 C 庫函數(shù)_main 初始化用戶堆棧,然后進入 main 函數(shù)。

在開始講解之前,我們需要了解STM32的啟動模式。

3.1 STM32的啟動模式

首先要講一下STM32的啟動模式,因為啟動模式?jīng)Q定了向量表的位置,STM32有三種啟動模式:

1)主閃存存儲器(Main Flash)啟動 :從STM32內(nèi)置的Flash啟動(0x08000000-0x0807 FFFF),一般我們使用JTAG或者SWD模式下載程序時,就是下載到這個里面,重啟后也直接從這啟動程序。 以0x08000000 對應(yīng)的內(nèi)存為例,則該塊內(nèi)存既可以通過0x00000000 操作也可以通過0x08000000 操作,且都是操作的同一塊內(nèi)存。

2)系統(tǒng)存儲器(System Memory)啟動 :從系統(tǒng)存儲器啟動(0x1FFFF000 - 0x1FFFF7FF),這種模式啟動的程序功能是由廠家設(shè)置的。一般來說,我們選用這種啟動模式時,是為了從串口下載程序,因為在廠家提供的ISP程序中,提供了串口下載程序的固件,可以通過這個ISP程序?qū)⒂脩舫绦蛳螺d到系統(tǒng)的Flash中。以0x1FFFFFF0對應(yīng)的內(nèi)存為例,則該塊內(nèi)存既可以通過0x00000000 操作也可以通過0x1FFFFFF0操作,且都是操作的同一塊內(nèi)存。

3)片上SRAM啟動 :從內(nèi)置SRAM啟動(0x20000000-0x3FFFFFFF),既然是SRAM,自然也就沒有程序存儲的能力了,這個模式一般用于程序調(diào)試。SRAM 只能通過0x20000000進行操作,與上述兩者不同。從SRAM 啟動時,需要在應(yīng)用程序初始化代碼中重新設(shè)置向量表的位置。

用戶可以通過設(shè)置BOOT0和BOOT1的引腳電平狀態(tài),來選擇復位后的啟動模式。如下圖所示:

啟動模式只決定程序燒錄的位置 ,加載完程序之后會有一個重映射(映射到0x00000000地址位置);真正產(chǎn)生復位信號的時候,CPU還是從開始位置執(zhí)行。

值得注意的是STM32上電復位以后,代碼區(qū)都是從0x00000000開始的,三種啟動模式只是將各自存儲空間的地址映射到0x00000000中。

3.2 STM32的啟動文件分析

因為啟動過程主要是由匯編完成的,因此STM32的啟動的大部分內(nèi)容都是在啟動文件里。筆者的啟動文件是startup_stm32f103xe.s,不管使用標準庫還是使用HAL庫,啟動文件都是差不多的。

3.2.1堆棧定義

1. Stack棧

棧的作用是用于局部變量,函數(shù)調(diào)用,函數(shù)形參等的開銷,棧的大小不能超過內(nèi)部SRAM 的大小。 當程序較大時,需要修改棧的大小,不然可能會出現(xiàn)的HardFault的錯誤。

第33行:表示開辟棧的大小為 0X00000400(1KB),EQU是偽指令,相當于C 中的 define。

第35行:開辟一段可讀可寫數(shù)據(jù)空間,ARER 偽指令表示下面將開始定義一個代碼段或者數(shù)據(jù)段。 此處是定義數(shù)據(jù)段。 ARER 后面的關(guān)鍵字表示這個段的屬性。 段名為STACK,可以任意命名; NOINIT 表示不初始化; READWRITE 表示可讀可寫,ALIGN=3,表示按照 8 字節(jié)對齊。

第36行:SPACE 用于分配大小等于 Stack_Size連續(xù)內(nèi)存空間,單位為字節(jié)。

第37行: __initial_sp表示棧頂?shù)刂贰?棧是由高向低生長的。

2.Heap堆

堆主要用來動態(tài)內(nèi)存的分配,像 malloc()函數(shù)申請的內(nèi)存就在堆中。

開辟堆的大小為 0X00000200(512 字節(jié)),名字為 HEAP,NOINIT 即不初始化,可讀可寫,8字節(jié)對齊。 __heap_base 表示對的起始地址,__heap_limit 表示堆的結(jié)束地址。

3.2.2向量表

向量表是一個WORD( 32 位整數(shù))數(shù)組,每個下標對應(yīng)一種異常,該下標元素的值則是該 ESR 的入口地址。 向量表在地址空間中的位置是可以設(shè)置的,通過 NVIC 中的一個重定位寄存器來指出向量表的地址。 在復位后,該寄存器的值為 0。 因此,在地址 0 (即 FLASH 地址 0)處必須包含一張向量表,用于初始時的異常分配。

值得注意的是這里有個另類: 0 號類型并不是什么入口地址,而是給出了復位后 MSP 的初值,后面會具體講解。

......

第55行:定義一塊代碼段,段名字是RESET,READONLY 表示只讀。

第56-58行:使用EXPORT將3個標識符申明為可被外部引用,聲明 __Vectors、__Vectors_End 和__Vectors_Size 具有全局屬性。 這幾個變量在Keil分散加載時會用到。

第60行:__Vectors 表示向量表起始地址,DCD 表示分配 1 個 4 字節(jié)的空間。 每行 DCD 都會生成一個 4 字節(jié)的二進制代碼,中斷向量表存放的實際上是中斷服務(wù)程序的入口地址。 當異常(也即是中斷事件)發(fā)生時,CPU 的中斷系統(tǒng)會將相應(yīng)的入口地址賦值給 PC 程序計數(shù)器,之后就開始執(zhí)行中斷服務(wù)程序。 在60行之后,依次定義了中斷服務(wù)程序的入口地址。

第138行:__Vectors_End 為向量表結(jié)束地址。

第139行:__Vectors_Size則是向量表的大小,向量表的大小是通過__Vectors 和__Vectors_End 相減得到的。

上述向量表可以在《Reference manual》中找到的,筆者這里只截取了部分。

3.2.3復位程序

復位程序是系統(tǒng)上電后執(zhí)行的第一個程序 ,復位程序也是中斷程序,只是這個程序比較特殊,因此單獨提出來講解。

第145行:定義了一個服務(wù)程序,PROC表示程序的開始。

第146行:使用EXPORT將Reset_Handler申明為可被外部引用,后面WEAK表示弱定義,如果外部文件定義了該標號則首先引用該標號,如果外部文件沒有聲明也不會出錯。 這里表示復位程序可以由用戶在其他文件重新實現(xiàn),這種寫法在HAL庫中是很常見的。

第147-148行:表示該標號來自外部文件,SystemInit()是一個庫函數(shù),在system_stm32f1xx.c中定義的,__main 是一個標準的 C 庫函數(shù),主要作用是初始化用戶堆棧,這個是由編譯器完成的,該函數(shù)最終會調(diào)用我們自己寫的main函數(shù),從而進入C世界中。

第149行:這是一條匯編指令,表示從存儲器中加載SystemInit到一個寄存器R0的地址中。

第150行:匯編指令,表示跳轉(zhuǎn)到寄存器R0的地址,并根據(jù)寄存器的 LSE 確定處理器的狀態(tài),還要把跳轉(zhuǎn)前的下條指令地址保存到 LR。

第151行:和149行是一個意思,表示從存儲器中加載__main到一個寄存器R0的地址中。

第152行:和150稍微不同,這里跳轉(zhuǎn)到至指定寄存器的地址后,不會返回。

第153行:和PROC是對應(yīng)的,表示程序的結(jié)束。

值得注意的是,這里的__main和C語言中的main()不是一樣東西,__main是C lib中的函數(shù),也就是在Keil中自帶的; 而main()函數(shù)是C的入口,main()會被__main調(diào)用。

3.2.4中斷服務(wù)程序

我們平時要使用哪個中斷,就需要編寫相應(yīng)的中斷服務(wù)程序,只是啟動文件把這些函數(shù)留出來了,但是內(nèi)容都是空的,真正的中斷復服務(wù)程序需要我們在外部的 C 文件里面重新實現(xiàn),這里只是提前占了一個位置罷了。

這部分沒啥好說的,和服務(wù)程序類似的,只需要注意‘B .’ 語句,B表示跳轉(zhuǎn),這里跳轉(zhuǎn)到一個‘.’,即表示無線循環(huán)。

3.2.5堆棧初始化

堆棧初始化是由一個IF條件來實現(xiàn)的,MICROLIB的定義與否決定了堆棧的初始化方式。

這個定義是在Options->Target中設(shè)置的。

如果沒有定義__MICROLIB ,則會使用雙段存儲器模式,且聲明了__user_initial_stackheap具有全局屬性,這需要開發(fā)者自己來初始化堆棧。

這部分也沒啥講的,需要注意的是,ALIGN表示對指令或者數(shù)據(jù)存放的地址進行對齊,缺省表示4字節(jié)對齊。

3.2.6其他

第50行:PRESERVE8 用于指定當前文件的堆棧按照 8 字節(jié)對齊。

第51行:THUMB 表示后面指令兼容 THUMB 指令。 現(xiàn)在 Cortex-M 系列的都使用 THUMB-2 指令集,THUMB-2 是 32 位的,兼容 16 位和 32 位的指令,是 THUMB 的超集。

3.3 STM32的啟動流程實例分析

有了前面的分析,接下來就來具體看看STM32啟動流程的具體內(nèi)容。

3.3.1初始化SP、PC、向量表

當系統(tǒng)復位后,處理器首先讀取向量表中的前兩個字(8 個字節(jié)),第一個字存入 MSP,第二個字為復位向量,也就是程序執(zhí)行的起始地址。

這里通過J-Flash打開hex文件。

硬件這時自動從0x0800 0000位置處讀取數(shù)據(jù)賦給棧指針SP,然后自動從0x0800 0004位置處讀取數(shù)據(jù)賦給PC,完成了復位操作,SP= 0x0200 0410,PC = 0x0800 0145。

初始化SP、PC緊接著就初始化向量表,如果感覺看HEX文件抽象,我們看看反匯編文件吧。

是不是更容易些,是不是和《Reference manual》中的向量表對應(yīng)起來了。 其實看反匯編文件更好理解STM32的啟動流程,只是有些抽象。

3.3.2設(shè)置系統(tǒng)時鐘

細心的朋友可能發(fā)現(xiàn),PC=0x08000145的地址是沒有對齊的。 然后在反匯編文件中卻是這樣的:

這里是硬件自動對齊到 0x08000144,并執(zhí)行SystemInit函數(shù)初始化系統(tǒng)時鐘。

當然也可通過硬件調(diào)試來確認上面的分析:

接下來就會進入SystemInit函數(shù)中。

SystemInit函數(shù)內(nèi)容如下:

/**
 * @brief  Setup themicrocontroller system
 *         Initialize the EmbeddedFlash Interface, the PLL and update the
 *         SystemCoreClockvariable.
 * @note   This function should beused only after reset.
 * @param  None
 * @retval None
 */
void SystemInit (void)
{
 /* Reset the RCC clock configuration to the default reset state(fordebug purpose) */
 /* Set HSION bit */
 RCC->CR |= 0x00000001U;

 /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#if !defined(STM32F105xC)&& !defined(STM32F107xC)
 RCC->CFGR &= 0xF8FF0000U;
#else
 RCC->CFGR &= 0xF0FF0000U;
#endif /* STM32F105xC */  

 /* Reset HSEON, CSSON and PLLON bits */
 RCC->CR &= 0xFEF6FFFFU;

 /* Reset HSEBYP bit */
 RCC->CR &= 0xFFFBFFFFU;

 /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
 RCC->CFGR &= 0xFF80FFFFU;

#if defined(STM32F105xC) ||defined(STM32F107xC)
 /* Reset PLL2ON and PLL3ON bits */
 RCC->CR &= 0xEBFFFFFFU;

 /* Disable all interrupts and clear pending bits  */
 RCC->CIR = 0x00FF0000U;

 /* Reset CFGR2 register */
 RCC->CFGR2 = 0x00000000U;
#elif defined(STM32F100xB) ||defined(STM32F100xE)
 /* Disable all interrupts and clear pending bits  */
 RCC->CIR = 0x009F0000U;

 /* Reset CFGR2 register */
 RCC->CFGR2 = 0x00000000U;     
#else
 /* Disable all interrupts and clear pending bits  */
 RCC->CIR = 0x009F0000U;
#endif /* STM32F105xC */

#if defined(STM32F100xE) ||defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) ||defined(STM32F103xG)
 #ifdef DATA_IN_ExtSRAM
    SystemInit_ExtMemCtl();
 #endif /* DATA_IN_ExtSRAM */
#endif

#ifdef VECT_TAB_SRAM
 SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocationin Internal SRAM. */
#else
 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocationin Internal FLASH. */
#endif
}

前面部分是配置時鐘的,具體參考手冊吧,這里需要注意以下代碼:

#ifdef VECT_TAB_SRAM
 SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocationin Internal SRAM. */
#else
 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocationin Internal FLASH. */
#endif

默認是沒有開啟VECT_TAB_SRAM,則從FLASH中啟動,VTOR 寄存器存放的是中斷向量表的起始地址,在IAP升級會修改這里的偏移量,后面講解IAP升級在細講吧。

3.3.3初始化堆棧并進入main

執(zhí)行指令LDR R0, =__main,然后就跳轉(zhuǎn)到__main程序段運行,當然這里指標準庫的__main函數(shù)。

這中間初始化了棧區(qū)。

這段代碼是個循環(huán)(BCC 0x08000192),實際運行時候循環(huán)了兩次。 第一次運行的時候,讀取“加載數(shù)據(jù)段的函數(shù)”的地址并跳轉(zhuǎn)到該函數(shù)處運行(注意加載已初始化數(shù)據(jù)段和未初始化數(shù)據(jù)段用的是同一個函數(shù)); 第二次運行的時候,讀取“初始化棧的函數(shù)”的地址并跳轉(zhuǎn)到該函數(shù)處運行。

最后就進入C文件的main函數(shù)中,至此,啟動過程到此結(jié)束。

最后,總結(jié)下STM32從flash的啟動流程。

MCU上電后從0x0800 0000處讀取棧頂?shù)刂凡⒈4妫缓髲?x0800 0004讀取中斷向量表的起始地址,這就是復位程序的入口地址,接著跳轉(zhuǎn)到復位程序入口處,初始向量表,然后設(shè)置時鐘,設(shè)置堆棧,最后跳轉(zhuǎn)到C空間的main函數(shù),即進入用戶程序。

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

    關(guān)注

    68

    文章

    19440

    瀏覽量

    231326
  • ARM
    ARM
    +關(guān)注

    關(guān)注

    134

    文章

    9180

    瀏覽量

    369476
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    6901

    瀏覽量

    123815
  • Cortex-M3
    +關(guān)注

    關(guān)注

    9

    文章

    270

    瀏覽量

    59610
  • stm32cubemx
    +關(guān)注

    關(guān)注

    5

    文章

    284

    瀏覽量

    15052
收藏 人收藏

    評論

    相關(guān)推薦

    ARM Cortex-M學習筆記:初識Systick定時器

    Cortex-M的內(nèi)核中包含Systick定時器了,只要是Cortex-M系列的MCU就會有Systick,因此這是通用的,下面詳細分析。
    的頭像 發(fā)表于 05-15 15:01 ?3267次閱讀
    <b class='flag-5'>ARM</b> <b class='flag-5'>Cortex-M</b><b class='flag-5'>學習</b><b class='flag-5'>筆記</b>:初識Systick定時器

    ARM Cortex-M處理器詳解 精選資料分享

    ARM Cortex-M處理器家族現(xiàn)在有8款處理器成員。在本文中,我們會比較Cortex-M系列處理器之間的產(chǎn)品特性,重點講述如何根據(jù)產(chǎn)品應(yīng)用選擇正確的Cortex-M處理器。本文中會
    發(fā)表于 07-16 07:57

    ARM Cortex-M堆棧機制介紹

      大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是ARM Cortex-M堆棧機制?! 〗裉旖o大家分享的這篇依舊是2016年之前痞子衡寫的技術(shù)文檔,花了點時間重新編排了一下
    發(fā)表于 12-16 06:26

    ARM Cortex-M內(nèi)核的相關(guān)資料推薦

      大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是ARM Cortex-M功能模塊,不過側(cè)重點是三款安全特性處理器。  ARM Cortex-M處理器家族發(fā)展至今(2
    發(fā)表于 12-27 07:21

    Arm Cortex-M處理器—Cortex-M85介紹

    Arm發(fā)布了新一代的Cortex-M處理器,Cortex-M85。簡單粗暴的打個比方:Cortex-M85 ≈ Cortex-M7Trust
    發(fā)表于 07-15 14:59

    ARM Cortex-M 系列微控制器(ST)

    ARM Cortex-M 系列微控制器(ST) 意法半導體(ST)宣布在基于ARM Cortex-M系列處理器內(nèi)核的微控制器研發(fā)項目上取得突破,推出全球業(yè)內(nèi)首款采用90nm技術(shù)嵌入式
    發(fā)表于 11-02 09:29 ?965次閱讀

    ARM白皮書】ARM Cortex-M處理器入門

    ARM Cortex-M處理器家族現(xiàn)在有8款處理器成員。在本文中,會比較Cortex-M系列處理器之間的產(chǎn)品特性,重點講述如何根據(jù)產(chǎn)品應(yīng)用選擇正確的Cortex-M處理器。本文中會詳細
    發(fā)表于 04-20 15:34 ?39次下載

    傳統(tǒng)的單片機和ARM較量 助推MCU踏上高端Cortex-M市場

    據(jù)有關(guān)市場調(diào)研機構(gòu)稱,基于ARM Cortex-M內(nèi)核的MCU在2010年創(chuàng)紀錄地實現(xiàn)了100%的出貨量增長。而整個MCU市場才增長了37%。MCU市場的增長也幾乎是來自于ARM Cortex
    發(fā)表于 04-28 10:00 ?1656次閱讀

    Atmel Studio 6軟件中如何調(diào)試ARM Cortex-M

    Atmel Studio 6軟件中如何調(diào)試ARM Cortex-M
    的頭像 發(fā)表于 07-04 10:49 ?4288次閱讀

    關(guān)于Cortex-M 調(diào)試應(yīng)用的介紹

    Cortex-M 調(diào)試應(yīng)用
    的頭像 發(fā)表于 07-10 00:56 ?2668次閱讀

    米爾科技Cortex-M Prototyping System +介紹

    ARM? Cortex?-M原型系統(tǒng) MPS2+,為Cortex-M 系列微處理器設(shè)計的原型驗證評估系統(tǒng),包含最新的Cortex-M7 及
    的頭像 發(fā)表于 11-14 10:45 ?1990次閱讀
    米爾科技<b class='flag-5'>Cortex-M</b> Prototyping System +介紹

    Cortex-MCortex-A認識ARM處理器

    Cortex-MCortex-A認識ARM處理器
    的頭像 發(fā)表于 03-08 11:34 ?3530次閱讀

    分析ARM Cortex-M內(nèi)核復位啟動過程

    ARM Cortex-M內(nèi)核的復位啟動過程也被稱為復位序列(Reset sequence),下面就來簡要總結(jié)分析下這一過程。
    的頭像 發(fā)表于 03-20 09:58 ?2561次閱讀

    Cortex-M 內(nèi)核中斷/異常系統(tǒng)、中斷優(yōu)先級/嵌套 詳解

    Cortex-M 內(nèi)核中斷/異常系統(tǒng)、中斷優(yōu)先級/嵌套 詳解
    的頭像 發(fā)表于 09-27 15:29 ?2461次閱讀
    <b class='flag-5'>Cortex-M</b> 內(nèi)核中斷/異常系統(tǒng)、中斷優(yōu)先級/嵌套 <b class='flag-5'>詳解</b>

    Cortex-M位帶操作的原理

    Cortex-M位帶操作的原理
    的頭像 發(fā)表于 10-24 15:27 ?937次閱讀
    <b class='flag-5'>Cortex-M</b>位帶操作的原理