chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

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

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

3天內不再提示

STM32 啟動流程的詳細講解

ouxiaolong ? 來源:嵌入式大雜燴 ? 作者:嵌入式大雜燴 ? 2022-03-06 15:26 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

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

處理器STM32F103

MDK:5.30

STM32CubeMX:6.0.1

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

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

深入理解ARM寄存器:https://bruceou.blog.csdn.net/article/details/117866186

ARM匯編入門:https://bruceou.blog.csdn.net/article/details/117897496

Keil反編譯入門(一):https://bruceou.blog.csdn.net/article/details/118314875

Keil反編譯入門(二):https://bruceou.blog.csdn.net/article/details/118400368

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

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

2.初始化中斷向量表

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

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

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

1 STM32的啟動模式

首先要講一下STM32的啟動模式,因為啟動模式決定了向量表的位置,STM32有三種啟動模式:

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

2)系統(tǒng)存儲器(System Memory)啟動:從系統(tǒng)存儲器啟動(0x1FFFF000 - 0x1FFF F7FF),這種模式啟動的程序功能是由廠家設置的。一般來說,我們選用這種啟動模式時,是為了從串口下載程序,因為在廠家提供的ISP程序中,提供了串口下載程序的固件,可以通過這個ISP程序將用戶程序下載到系統(tǒng)的Flash中。以0x1FFFFFF0對應的內存為例,則該塊內存既可以通過0x00000000操作也可以通過0x1FFFFFF0操作,且都是操作的同一塊內存。

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

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

poYBAGGm-NuAD4bcAAB4W9j4wms335.png

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

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

2 STM32的啟動文件分析

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

2.1堆棧定義

1.Stack棧

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

pYYBAGGm-NyAO9D2AAB5BNYbnlQ498.png

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

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

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

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

2.Heap堆

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

pYYBAGIkYG2AKWA_AAB_1MjIEWw739.png

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

2.2向量表

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

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

pYYBAGIkYIWAalemAAEzAzwzIsM222.png

……

poYBAGGm-OGAYKu-AACYtV0J3wM865.png

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

第56-58行:使用EXPORT將3個標識符申明為可被外部引用,聲明 __Vectors、__Vectors_End和__Vectors_Size具有全局屬性。

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

第138行:__Vectors_End為向量表結束地址。

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

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

poYBAGIkYJqAea1JAAXNebKDzzY290.png

2.3復位程序

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

pYYBAGGm-OSAPptXAACAL8cSWmk466.png

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

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

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

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

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

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

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

第153行:和PROC是對應的,表示程序的結束。

2.4中斷服務程序

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

pYYBAGIkYMeAUS-_AADPgbuSoi0636.png

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

2.5堆棧初始化

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

這個定義是在Options->Target中設置的。

poYBAGIkYNuAYXyDAAGMgB83ta4038.png

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

pYYBAGIkYOqALSSLAAEVrV020ZY840.png

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

2.6其他

poYBAGGm-OqAGc6jAAASCQvb2jQ569.png

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

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

3 STM32的啟動流程實例分析

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

3.1初始化SP、PC、向量表

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

pYYBAGGm-OuAQF1vAAByWiO3WGs335.jpg

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

pYYBAGIkYSWAP1kUAAK0V6w8j5Y782.png

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

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

poYBAGIkYV-ACQ07AAI1iaHeQ28403.png

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

3.2設置系統(tǒng)時鐘

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

pYYBAGIkYXGAF4_rAAHcuom8E2I251.png

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

當然也可通過硬件調試來確認上面的分析:

pYYBAGIkYYCAPxBeAALPXJh0jEs254.png

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

poYBAGGm-POAQf9bAADXhfB5j74822.png

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

/**
 * @brief Setup the microcontroller system
 *        Initialize the Embedded Flash Interface, the PLL and update the 
 *        SystemCoreClock variable.
 * @note  This function should be used only after reset.
 * @param None
 * @retval None
 */
void SystemInit (void)
{
 /* Reset the RCC clock configuration to the default reset state(for debug 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 Relocation in Internal SRAM. */
#else
 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif 
}

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

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

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

3.3初始化堆棧并進入main

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

pYYBAGIkYcWABomfAAFzw58xdfQ653.png

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

poYBAGIkYcqAcd5VAAHfb4agIdk973.png

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

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

最后,總結下STM32從flash的啟動流程。

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

pYYBAGIkYduAHd6EAAIBGqGQGI0878.png

審核編輯:符乾江

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

    關注

    2309

    文章

    11162

    瀏覽量

    373475
  • 啟動流程
    +關注

    關注

    0

    文章

    14

    瀏覽量

    6666
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    RGB時序燈條的工作原理講解

    圖文配合講解了RGB時序燈條的應用場景、什么是RGB時序燈條、信號格式與傳輸規(guī)則、燈珠芯片的工作流程、顏色與動態(tài)效果控制方式等
    發(fā)表于 02-06 11:36 ?0次下載

    3562 單板機 Linux 系統(tǒng)固化完全指南:從 SD 卡啟動到 eMMC 永久部署

    本文為創(chuàng)龍科技 3562 單板機系統(tǒng)固化操作指南,核心涵蓋 SD 啟動卡、升級卡制作,以及 eMMC 芯片系統(tǒng)固化與啟動驗證。文檔詳細說明專用工具使用、鏡像燒錄參數(shù)配置、多方式啟動測試
    的頭像 發(fā)表于 02-04 10:34 ?926次閱讀
    3562 單板機 Linux 系統(tǒng)固化完全指南:從 SD 卡<b class='flag-5'>啟動</b>到 eMMC 永久部署

    初識ros2 功能包建立與可執(zhí)行文件的配置

    本文介紹了ROS2程序的兩種啟動方式:直接運行可執(zhí)行文件(ros2 run)和使用啟動文件(ros2 launch)。重點講解了Python軟件包的結構,包括package.xml、setup.py
    的頭像 發(fā)表于 01-22 13:41 ?243次閱讀

    如何在Zynq UltraScale+ MPSoC平臺上通過JTAG啟動嵌入式Linux鏡像

    流程教程)。本文則進一步講解如何在 Zynq UltraScale+ MPSoC 平臺上通過 JTAG 逐步啟動 Linux,并提供了完整的過程與關鍵命令。只要按步驟操作,即使是復雜的 Linux 鏡像也能成功通過 JTAG
    的頭像 發(fā)表于 01-13 11:45 ?4459次閱讀

    d1哪吒開發(fā)板的啟動流程分析

    的可以研究很深的開發(fā)板。本文主要從研究D1啟動流程的角度出發(fā),探索一下D1的裸機開發(fā)實踐。對于研究D1的底層裸機開發(fā),首先需要知道可以玩那些東西,也可以對RISCV相關的軟件生態(tài)有比較透徹的理解,本文會
    發(fā)表于 10-29 06:44

    STM32C011開發(fā)(3)----Flash操作

    STM32C011 系列微控制器內置 Flash 存儲器,支持程序存儲與數(shù)據(jù)保存,具備頁面擦除、雙字寫入、讀寫保護等功能。本文將簡要介紹 STM32C011 的 Flash 結構與特性,并通過實際代碼示例,講解 Flash 的擦
    的頭像 發(fā)表于 09-18 16:48 ?4923次閱讀
    <b class='flag-5'>STM32</b>C011開發(fā)(3)----Flash操作

    求助,關于K230啟動流程疑問求解

    , GNU ld (GNU Binutils) 2.35) #1 SMP Sat Jun 21 23:51:35 CST 2025 [ 0.000000] earlycon: sbi0 上面是啟動流程
    發(fā)表于 07-11 06:42

    一文看懂芯片的設計流程

    差異。接下來,我們就以數(shù)字芯片為例,詳細看看芯片到底是如何設計出來的。芯片設計的主要流程芯片的設計,總體分為規(guī)格定義、系統(tǒng)設計、前端設計(Front-EndDesi
    的頭像 發(fā)表于 07-03 11:37 ?2579次閱讀
    一文看懂芯片的設計<b class='flag-5'>流程</b>

    ElfBoard技術貼|【RK3588】ELF 2開發(fā)板開機自啟動詳解

    在嵌入式系統(tǒng)開發(fā)中,合理管理開機自啟動項目能夠優(yōu)化系統(tǒng)啟動流程,確保關鍵服務和應用按時加載運行。本文將詳細介紹在ELF2開發(fā)板Linux5.10.209系統(tǒng)下基于SystemVinit
    的頭像 發(fā)表于 06-27 16:20 ?2050次閱讀
    ElfBoard技術貼|【RK3588】ELF 2開發(fā)板開機自<b class='flag-5'>啟動</b>詳解

    使用USB轉TTL串口板和ST-LINK調試下載器給STM32單片機下載程序

    本文詳細介紹如何使用ST-LINK/V2和USB轉TTL串口板為STM32單片機下載程序,包括STM32啟動模式、JTAG與SWD接口對比、驅動安裝及官方軟件
    的頭像 發(fā)表于 06-20 17:26 ?2762次閱讀
    使用USB轉TTL串口板和ST-LINK調試下載器給<b class='flag-5'>STM32</b>單片機下載程序

    詳細的反激式開關電源電路圖講解

    電容或加LC噪聲濾波器可以改善)  今天以最常用的反激開關電源的設計流程及元器件的選擇方法為例。給大家講解如何讀懂反激開關電源電路圖!  三, 畫框圖  一般來說,總的來分按變壓器初測部分和次側部
    發(fā)表于 03-27 16:30

    STM32CubeIDE無法啟動正常調試是哪里出了問題?

    STM32CubeIDE始終正常使用中,昨日系統(tǒng)升級為 macOS Sequoia 版本,啟動調試出現(xiàn)錯誤提示,重新安裝應用程序及 st-stlink-server 驅動,仍提示同樣錯誤。 目前
    發(fā)表于 03-14 16:30

    STM32MP135 Nor Flash啟動,MX25L51245G_STM32MP135C-CUSTOM_HW_A7.bin如何修改?

    的MX25L51245G_STM32MP135C-CUSTOM_HW_A7.bin文件源碼有人知道在哪么,該如何修改,我把Nor Flash的型號換了下,換成MT25QL02GCBB芯片,在啟動流程這一步,不知道
    發(fā)表于 03-14 07:13

    封裝失效分析的流程、方法及設備

    本文首先介紹了器件失效的定義、分類和失效機理的統(tǒng)計,然后詳細介紹了封裝失效分析的流程、方法及設備。
    的頭像 發(fā)表于 03-13 14:45 ?2186次閱讀
    封裝失效分析的<b class='flag-5'>流程</b>、方法及設備

    不要再找啦,關于Cortex-Mx芯片的啟動沒有比這里更清楚啦(可下載)

    啟動流程(此文章知識廣泛適用于 CPU 為 Cortex-Mx 系列的 MCU)如上圖為 STM32F0 系列單片機系統(tǒng)存儲器的映射圖(其他系列型號,映射圖會有區(qū)別
    發(fā)表于 03-12 15:11 ?0次下載