section 1
這作為stm32f10x單片機的啟動代碼
.extern xPortPendSVHandler.extern xPortSysTickHandler.extern vPortSVCHandler
.extern xPortPendSVHandler:聲明xPortPendSVHandler是一個外部符號。在FreeRTOS操作系統中,xPortPendSVHandler是PendSV中斷的處理函數,PendSV中斷用于任務調度。
.extern xPortSysTickHandler:聲明xPortSysTickHandler是一個外部符號。在FreeRTOS操作系統中,xPortSysTickHandler是系統滴答定時器中斷的處理函數,用于生成系統時鐘滴答,從而實現任務的時間管理。
.extern vPortSVCHandler:聲明vPortSVCHandler是一個外部符號。在FreeRTOS操作系統中,vPortSVCHandler是SVCall中斷的處理函數,SVCall中斷通常用于操作系統的上下文切換。
PendSV(Pending Service Call)中斷是ARM Cortex-M處理器的一個特殊中斷,它主要用于操作系統的任務調度。在實時操作系統(RTOS)如FreeRTOS中,PendSV中斷被用來實現上下文切換,即從一個任務切換到另一個任務。
以下是PendSV中斷的一些關鍵特性:
高優先級中斷:PendSV中斷具有很高的優先級,通常只比NMI(非屏蔽中斷)和硬錯誤中斷低。這意味著它通常不會被其他低優先級的中斷所打斷。
軟件觸發:PendSV中斷不是由硬件事件觸發的,而是由軟件觸發。在Cortex-M處理器中,可以通過向系統控制寄存器(SCB)中的“PendSVSet”位寫入1來觸發PendSV中斷。
上下文切換:在RTOS中,PendSV中斷的中斷服務例程(ISR)通常負責保存當前任務的上下文(如寄存器狀態),并恢復下一個要執行的任務的上下文。這個過程稱為上下文切換。
可配置性:RTOS可以實現自己的PendSV處理例程,以適應不同的調度策略和優化需求。例如,FreeRTOS提供了自己的xPortPendSVHandler函數來處理PendSV中斷。
節省資源:使用PendSV中斷進行任務調度可以減少對定時器中斷的依賴,從而節省資源。在某些情況下,可以通過減少定時器中斷的頻率來降低功耗。
靈活的調度時機:PendSV中斷可以在任何時刻被觸發,這為操作系統提供了靈活性,可以在需要時立即進行任務調度,而不必等待下一個定時器中斷。
與SysTick中斷的關系:在許多RTOS實現中,SysTick中斷用于定期觸發PendSV中斷,以實現周期性的任務調度。但是,PendSV中斷也可以由其他事件觸發,如任務主動放棄CPU或任務阻塞等待某個事件。
在FreeRTOS中,PendSV中斷通常與SysTick中斷配合使用,SysTick中斷用于定期調用操作系統的tick函數,而PendSV中斷則用于處理任務調度。這種組合提供了一種高效且可預測的任務調度機制。
SVCall(SuperVisor Call)中斷是ARM Cortex-M處理器中的一種軟件觸發的異常,用于操作系統或應用程序從用戶態切換到內核態。SVCall通常用于調用操作系統的服務,比如任務調度、同步原語(如信號量、互斥鎖)和內存管理等。
以下是SVCall中斷的一些關鍵特性:
軟件觸發:SVCall中斷是由軟件觸發的,通常是通過執行特定的指令(如SVC指令)來實現的。在Cortex-M處理器中,執行SVC指令會觸發SVCall異常。
特權級別切換:SVCall中斷允許從較低的特權級別(如用戶態)切換到較高的特權級別(如內核態)。這是通過改變程序狀態字(PRIMASK)和控制寄存器(CONTROL)來實現的。
操作系統服務:在RTOS中,SVCall中斷通常用于實現操作系統的系統調用接口。應用程序可以通過SVCall請求操作系統的服務,如創建任務、刪除任務、發送信號量等。
優先級:SVCall中斷的優先級通常比PendSV低,這意味著它通常在PendSV中斷之后處理。然而,它的優先級仍然高于大多數其他中斷,確保了操作系統服務的及時響應。
上下文保存和恢復:與PendSV中斷類似,SVCall中斷的處理也需要保存當前任務的上下文,并在返回用戶態之前恢復上下文。這確保了任務切換的正確性和數據的一致性。
可配置性:操作系統可以根據需要實現自己的SVCall處理例程。例如,FreeRTOS提供了vPortSVCHandler函數來處理SVCall中斷。
安全性:SVCall中斷提供了一種安全的方式來訪問操作系統的服務,因為它允許操作系統在處理請求時保持對資源的控制和保護。
性能考慮:雖然SVCall中斷提供了一種方便的方式來調用操作系統服務,但頻繁的SVCall調用可能會影響系統性能,因為它涉及到特權級別的切換和上下文保存/恢復。因此,設計時應盡量減少SVCall的使用。
在FreeRTOS中,SVCall中斷通常用于實現系統調用,如xTaskCreate、xSemaphoreCreateMutex等。這些調用通過SVCall觸發,由操作系統在內核態處理,然后返回結果給用戶態的任務。這種機制使得操作系統能夠提供豐富的服務,同時保持系統的穩定性和安全性。
系統滴答定時器中斷(SysTick Interrupt)是ARM Cortex-M微控制器中的一個內置定時器,它提供了一個可配置的周期性中斷源。這個定時器通常用于操作系統的定時任務,如任務調度、時間管理、系統監控等。
以下是系統滴答定時器中斷的一些關鍵特性:
周期性中斷:SysTick定時器可以在一個可配置的時間間隔后產生中斷,這個時間間隔由定時器的重載值(Reload Value)決定。當定時器的計數器達到這個重載值時,它會重置并產生一個中斷。
可配置性:SysTick定時器的重載值、計數器和中斷使能都可以在運行時配置。這允許開發者根據需要調整定時器的頻率。
高優先級中斷:SysTick中斷通常具有固定的優先級,這個優先級可以在系統啟動時通過配置系統控制塊(SCB)來設置。在大多數RTOS實現中,SysTick中斷的優先級被設置得足夠高,以確保它能夠及時響應。
操作系統的Tick函數:在RTOS中,SysTick中斷通常用于觸發操作系統的Tick函數。這個函數負責更新操作系統的時間管理機制,如任務的時間片、定時器等。
上下文切換:在某些RTOS實現中,SysTick中斷也可以用來觸發任務的上下文切換。例如,當一個任務用完了它的時間片時,操作系統可以在SysTick中斷中觸發PendSV中斷,從而實現任務切換。
系統監控:SysTick定時器還可以用于系統監控,如看門狗定時器的喂狗操作。在某些RTOS實現中,SysTick中斷可以用來定期重置看門狗定時器,以防止系統因為死鎖而復位。
低功耗模式:在低功耗應用中,SysTick定時器可以用來喚醒處理器,執行必要的任務,然后再進入低功耗模式。這樣可以在保證系統響應性的同時,降低功耗。
編程接口:在Cortex-M微控制器的庫中,通常提供了一套編程接口來配置和使用SysTick定時器。這些接口允許開發者輕松地設置定時器的重載值、使能或禁用中斷等。
在FreeRTOS中,SysTick中斷的處理函數通常被命名為xPortSysTickHandler。這個函數在每次SysTick中斷發生時被調用,它負責調用RTOS的Tick函數,更新系統的時間管理機制,并可能觸發任務調度。通過這種方式,SysTick定時器為操作系統提供了一個穩定的時基,確保了系統的準時性和可靠性。
section 2
.global reset_handler .section .vectors, 'ax' .code 16 .align 0 .global _vectors
這段代碼是嵌入式系統中的匯編語言代碼,用于定義中斷向量表。中斷向量表是系統啟動時用于處理中斷和異常的跳轉地址列表。下面是對這段代碼的逐行解釋:
.section .vectors, 'ax':
.section 指令用于指定接下來的代碼應該放在哪個段(section)中。
.vectors 是段的名稱,這里命名為 vectors,通常用于存放中斷向量表。
'ax' 參數指定了段的屬性。在這里,'ax' 表示該段是可讀(a)可執行(x)的。.code 16:
.code 指令用于指定接下來的代碼應該使用哪種處理器模式。
16 表示代碼應該在16位模式下運行,這是針對某些處理器架構的特定模式。.align 0:
.align 指令用于指定對齊方式。
0 表示不對齊,但這通常是一個錯誤,因為中斷向量表通常需要特定的對齊方式以確保快速訪問。在實際使用中,這個值可能會被設置為處理器要求的對齊值,比如4或8。.global _vectors:
.global 指令用于聲明一個全局符號,使得其他文件也可以引用這個符號。
_vectors 是一個符號,通常用于在其他代碼中引用中斷向量表的開始位置。
這段代碼的目的是定義一個中斷向量表,并將其標記為全局可訪問,以便在程序的其他部分可以引用它。中斷向量表通常包含了一系列函數指針,每個指針對應一個特定的中斷或異常處理函數。當處理器遇到中斷或異常時,它會跳轉到這個表中相應的地址去執行處理函數。
在實際的嵌入式系統開發中,中斷向量表是非常重要的,因為它確保了系統能夠正確響應各種硬件和軟件事件。開發者需要根據具體的硬件架構和操作系統要求來正確配置這個表。
section 3
.macro DEFAULT_ISR_HANDLER name= .thumb_func .weak name name:1: b 1b /* endless loop */.endm
這段代碼是一個匯編語言的宏定義(macro),用于創建默認的中斷服務例程(ISR)處理函數。在嵌入式系統中,當一個中斷發生,但相應的中斷服務例程沒有被正確定義時,可以使用這種默認的處理函數來處理中斷。下面是對這段代碼的逐行解釋:
.macro DEFAULT_ISR_HANDLER name=:
這行定義了一個名為 DEFAULT_ISR_HANDLER 的宏,它接受一個參數 name,這個參數默認值為空。.thumb_func:
這是一個指令,用于指定接下來的函數應該在 thumb 模式下運行。thumb 是ARM處理器的一種32位指令集,它用于在16位的代碼空間內執行,以節省內存空間。.weak name:
.weak 指令用于聲明一個弱符號。弱符號允許在鏈接時被其他具有相同名稱的強符號覆蓋。在這里,它聲明了宏參數 name 指定的函數為弱符號,這意味著如果程序中有同名的強符號函數,它將覆蓋這個默認的處理函數。name::
這行定義了一個標簽,標簽的名稱由宏參數 name 指定。這個標簽標記了中斷服務例程的開始位置。1: b 1b /* endless loop */:
1: 是一個標簽。
b 1b 是一條分支指令,它會使程序跳轉到標簽 1,形成一個無限循環。當CPU執行到這條指令時,它會不停地跳轉到自身,從而形成一個空循環。這通常用于默認的中斷處理函數,因為如果沒有特定的處理邏輯,中斷服務例程應該什么都不做,或者至少不返回,以避免執行到不正確的代碼。.endm:
這行標記了宏定義的結束。
總的來說,這個宏定義了一個默認的中斷服務例程,它什么也不做,只是進入一個無限循環。在實際的嵌入式系統開發中,開發者通常會為每個中斷源定義具體的處理函數,但如果某個中斷源沒有定義處理函數,可以使用這個默認的處理函數來避免鏈接錯誤。這個宏可以被多次調用,每次調用都會生成一個新的默認中斷處理函數,每個函數都可以通過不同的名稱來引用。
section 4
向量表
_vectors: .word __stack_end__ #ifdef STARTUP_FROM_RESET .word reset_handler #else .word reset_wait #endif /* STARTUP_FROM_RESET */ .word NMIException .word HardFaultException .word MemManageException .word BusFaultException .word UsageFaultException ... .word I2C1_EV_IRQHandler .word I2C1_ER_IRQHandler .word I2C2_EV_IRQHandler .word I2C2_ER_IRQHandler .word SPI1_IRQHandler .word SPI2_IRQHandler ... .word ADC3_IRQHandler .word FSMC_IRQHandler .word SDIO_IRQHandler .word TIM5_IRQHandler .word SPI3_IRQHandler .word UART4_IRQHandler .word UART5_IRQHandler ... ... ...
在中斷向量表中,每個 .word 指令定義的條目通常占用4字節(在32位系統中),并且這些條目是連續存儲的。如果 _vectors 符號對應的地址是0,那么存儲的布局將如下:
地址 0x00:存儲 __stack_end__ 的地址。
地址 0x04:存儲 reset_handler 或 reset_wait 的地址,取決于是否定義了 STARTUP_FROM_RESET 宏。
地址 0x08:存儲 NMIException 的地址。
地址 0x0C:存儲 HardFaultException 的地址。
地址 0x10:存儲 MemManageException 的地址。
地址 0x14:存儲 BusFaultException 的地址。
地址 0x18:存儲 UsageFaultException 的地址。
地址 0x1C:存儲一個保留的值,這里是 0。
這種布局確保了當處理器遇到特定的中斷或異常時,它可以通過查閱中斷向量表中的相應條目來找到并跳轉到正確的處理函數。每個中斷處理函數的地址都是按照順序存儲的,每個條目之間相隔4字節。這種結構使得處理器能夠快速地定位到每個中斷或異常的處理函數。
這段代碼是嵌入式系統中用于定義中斷向量表的一部分。中斷向量表是處理器在啟動時或遇到中斷/異常時跳轉執行的一系列函數地址列表。這段代碼通常位于程序的啟動文件(如匯編語言編寫的啟動文件)中。下面是對這段代碼的逐行解釋:
_vectors::
這是中斷向量表的標簽,用于標記中斷向量表的開始。.word __stack_end__:
.word 指令用于定義一個32位的字(在ARM架構中通常是4字節)。
__stack_end__ 是一個符號,通常代表堆棧的頂部或末尾。這里將其地址放在中斷向量表的第一個位置,是因為在Cortex-M處理器中,當發生異常時,處理器會自動將當前的程序計數器(PC)、程序狀態寄存器(PSR)和一組寄存器的值壓入堆棧。因此,中斷向量表的第一個條目通常是堆棧指針的初始值。#ifdef STARTUP_FROM_RESET:
這是一個預處理指令,用于條件編譯。如果定義了 STARTUP_FROM_RESET 宏,則編譯器會包含接下來的代碼。.word reset_handler:
如果定義了 STARTUP_FROM_RESET,則這里會放置 reset_handler 函數的地址。reset_handler 是處理器復位后執行的第一個函數,通常用于初始化硬件和設置堆棧。#else:
如果沒有定義 STARTUP_FROM_RESET,則執行 #else 和 #endif 之間的代碼。.word reset_wait:
如果沒有定義 STARTUP_FROM_RESET,則這里會放置 reset_wait 函數的地址。這個函數可能用于在啟動過程中等待某些條件滿足,比如外部設備的初始化。#endif /* STARTUP_FROM_RESET */:
這是 #ifdef 條件編譯塊的結束。接下來的幾行定義了其他中斷和異常的處理函數地址:
NMIException:非屏蔽中斷(Non-Maskable Interrupt)異常處理函數。
HardFaultException:硬件故障異常處理函數。
MemManageException:內存管理異常處理函數。
BusFaultException:總線故障異常處理函數。
UsageFaultException:使用錯誤異常處理函數。
.word 0 // Reserved:保留的條目,這里設置為0,表示未使用或不處理。
每個 .word 指令定義了中斷向量表中的一個條目,這些條目包含了對應中斷或異常處理函數的地址。當相應的中斷或異常發生時,處理器會跳轉到這些地址執行相應的處理函數。
section 5
.section .init, 'ax' .thumb_func reset_handler:#ifndef __FLASH_BUILD /* If this is a RAM build, configure vector table offset register to point to the RAM vector table. */ ldr r0, =0xE000ED08 ldr r1, =_vectors str r1, [r0]#endif b _start
這段代碼是嵌入式系統中的匯編語言代碼,通常用于初始化程序的啟動過程。它定義了一個名為 reset_handler 的函數,這個函數是處理器在復位后執行的第一個函數。下面是對這段代碼的逐行解釋:
.section .init, 'ax':
.section 指令用于指定接下來的代碼應該放在哪個段(section)中。
.init 是段的名稱,這里命名為 init,通常用于存放初始化代碼。
'ax' 參數指定了段的屬性。在這里,'ax' 表示該段是可讀(a)可執行(x)的。.thumb_func:
這是一個指令,用于指定接下來的函數應該在 thumb 模式下運行。thumb 是ARM處理器的一種16位指令集,它用于在16位的代碼空間內執行,以節省內存空間。reset_handler::
這是 reset_handler 函數的標簽,標記了函數的開始位置。這個函數是處理器復位后執行的第一個函數。#ifndef __FLASH_BUILD:
這是一個預處理指令,用于條件編譯。如果沒有定義 __FLASH_BUILD 宏,則編譯器會包含接下來的代碼。/* If this is a RAM build, configure vector table offset register to point to the RAM vector table. */:
這是一個注釋,解釋了接下來的代碼塊的目的。如果這是一個在RAM中構建的程序(而不是在Flash中),則需要配置向量表偏移寄存器以指向RAM中的向量表。ldr r0, =0xE000ED08:
ldr 指令用于加載立即數到r0寄存器中。
=0xE000ED08 是立即數,這是向量表偏移寄存器(VTOR)的地址。VTOR用于指定中斷向量表的基地址。ldr r1, =_vectors:
ldr 指令用于加載立即數到r1寄存器中。
=_vectors 是立即數,這是中斷向量表的符號地址。str r1, [r0]:
str 指令用于存儲寄存器的內容到內存中。
r1 是源寄存器,它包含了中斷向量表的地址。
[r0] 是目標內存地址,它指向VTOR寄存器的地址。這行代碼將中斷向量表的地址寫入VTOR寄存器,從而配置處理器使用RAM中的中斷向量表。#endif:
這是 #ifndef 條件編譯塊的結束。b _start:
b 指令是分支指令,用于跳轉到另一個地址執行。
_start 是跳轉的目標地址,通常是程序的入口點,即 main 函數的地址。
總的來說,這段代碼的目的是初始化程序的啟動過程,特別是當程序在RAM中運行時,它配置了處理器的VTOR寄存器以指向RAM中的中斷向量表。然后,它跳轉到程序的實際入口點 _start,開始執行程序。
section 6
此處對應上面的向量表
使用宏 DEFAULT_ISR_HANDLER 將為每個中斷函數定義為一個無線循環
但由于這個定義時weak的,可以被覆蓋
DEFAULT_ISR_HANDLER NMIException DEFAULT_ISR_HANDLER HardFaultException DEFAULT_ISR_HANDLER MemManageException DEFAULT_ISR_HANDLER BusFaultException DEFAULT_ISR_HANDLER UsageFaultException ... DEFAULT_ISR_HANDLER I2C1_EV_IRQHandler DEFAULT_ISR_HANDLER I2C1_ER_IRQHandler DEFAULT_ISR_HANDLER I2C2_EV_IRQHandler DEFAULT_ISR_HANDLER I2C2_ER_IRQHandler DEFAULT_ISR_HANDLER SPI1_IRQHandler DEFAULT_ISR_HANDLER SPI2_IRQHandler ... ... ...
section 7
#ifndef STARTUP_FROM_RESETDEFAULT_ISR_HANDLER reset_wait#endif /* STARTUP_FROM_RESET */ // STM32 library requires these .global __WFI .global __WFE .global __SEV .global __ISB.........
這段代碼是ARM Cortex-M處理器的匯編語言代碼,定義了一系列特殊的函數,這些函數通常由操作系統或底層硬件抽象層(如STM32庫)使用。這些函數提供了對處理器特定功能的直接訪問,包括低功耗模式、異常處理、寄存器訪問和數據同步等。下面是對這段代碼的逐行解釋:
上一篇:位帶操作
下一篇:功耗測評 | STM32F103C8T6
推薦閱讀最新更新時間:2025-04-25 12:24


設計資源 培訓 開發板 精華推薦
- DC1753A-A,基于 LTC3880EUJ 雙相單輸出的演示板 (RSENSE),PMBus 降壓,6.5V = VIN = 24V,VOUT = 0.5V 至 3.3V @ 40A
- LT3020IDD-1.8 100mA、低電壓、極低壓差線性穩壓器的典型應用電路
- 使用 Microchip Technology 的 MIC2774H-XXBM5 的參考設計
- 偉納SP200S編程器#
- AD-FMCOMMS3-EBZ,評估板使用 AD9361 高性能、高度集成的射頻收發器,用于射頻應用
- 【廣西師大校賽】波形發生
- EEPROM
- 使用 Analog Devices 的 LTC3119MPFE 的參考設計
- LTC1261LIMS8-4.5 -4V 發生器的典型應用電路,具有電源有效開關電容器穩壓逆變器
- 菠蘿2航模遙控器主板