精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

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

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

3天內不再提示

深入剖析Cortex-M中斷

嵌入式大雜燴 ? 來源:嵌入式大雜燴 ? 作者:嵌入式大雜燴 ? 2023-06-10 14:17 ? 次閱讀

嵌入式系統開發中,中斷是十分重要的知識點,在大部分單片機構建的應用產品中,基本都是以前后臺方式(大循環加中斷)的方式來實現功能,在主循環中處理應用,并在中斷中處理外部的觸發信號,以及對響應時間有要求的應用,如用于時間相關處理的定時器中斷,對按鍵響應的外部中斷,用于通訊的收發和異常處理的串口中斷,SPI中斷, 網絡中斷等。另外,對于大部分RTOS來說,如Cortex-M系統中的systick中斷和PendSV中斷,又是實現基于隊列和任務調度算法的RTOS的核心。

1 異常類型

單片機開發中,對于中斷的表示方法也因為內核的不同有很大的差異,如51使用中斷號來表示指定中斷,而ARM Cortex-M內核中則使用中斷向量表的方式配合內核中的NVIC控制器來實現中斷的處理,不過考慮到目前的主流單片機方案,因此以典型的Cortex-M3內核說明單片機中的中斷控制機制, 另外Cortex-M系列中的其它內核中的中斷流程也基本一致。

Cortex-M3內核支持256個中斷,其中 16個內核中斷和240個外部中斷,并具有256級可編程中斷設置,其中015為系統異常,主要處理系統執行中產生的復位,錯誤,主動觸發的SVC,異常等,編號16255則是由芯片設計廠商自定義設計,用于滿足芯片功能需求的中斷(芯片廠商可以自由定制,不超過最大編號且不重復即可)。STM32并沒有使用Cortex-M3的全部內容,而是使用了一部分。 STM32有84個中斷,包括16個內核中斷和68個可屏蔽中斷,具有16級可編程中斷優先級 。STM32F103 在內核水平上搭載了一個異常響應系統, 支持為數眾多的系統異常和外部中斷。其中系統異常有 8 個(如果把 Reset 和 HardFault 也算上的話就是 10 個), 外部中斷有 60個 。除了個別異常的優先級被定死外,其它異常的優先級都是可編程的。

下面以STM32F1舉例,有關具體的系統異常和外部中斷可在標準庫文件 stm32f10x.h 這個頭文件查詢到,在 IRQn_Type 這個結構體里面包含了Cortex-M的異常聲明。系統異常清單見下表。

表1 系統異常清單

1686377467770on7xf63u56

表2 STM32F103 外部中斷清單

1686377468419ki0aetj6rn

反映在軟件實現就是在startup_xxx.s啟動文件中定義的中斷向量表,具體結構如下:

1686377469062y9txop95s5

其中External Interrupts就是由廠商定義的中斷類型,另外中斷號為0的位置為空,設計上就用來存儲堆棧指針。

在芯片在上電的過程中就是執行復位機制根據SCB->VTOR查詢向量表,找到Reset_Handler入口,并加載__initial_sp到堆棧指針R13中,后續就可以正常的工作了。

在上述結構中,系統中斷是在內核定義時確定的,外部中斷在芯片設計時被確定,將中斷編號和指定外設的中斷觸發信號綁定,就構建了完整的中斷向量表。

2 中斷向量表

中斷向量表每一位為一個32bit的地址。每一個地址對應一個中斷函數的地址(第一位除外)。除了第一位以外,所有地址的目標都為尋址寄存器(PC)。當相應中斷觸發時,ARM Cortex-M硬件會自動把中斷向量表中相應的中斷函數地址裝載入尋址寄存器(PC)然后開始執行中斷函數。如上所述,前16位為ARM保留的系統中斷,建議讀者熟記。之后的中斷為芯片自定義的外部中斷,可以在使用時查詢手冊或者廠商提供的驅動程序。表中每個向量大小都是 4 字節,除了第 0 個向量外,其余向量都是函數地址,這個表集中保存了系統全部的中斷處理函數(xxxIRQHandler)地址。

對于內嵌 Flash 的 MCU 來說,初始中斷向量表一般會被要求固定鏈接到 Flash 起始地址處,因為系統啟動總是從 Flash 起始地址獲取第 0(初始棧)、1個向量(初始PC,復位函數ResetHandler)來開始應用程序代碼的執行。對于一些包含 BootROM 或者沒有內部 Flash 的 MCU,初始中斷向量表也許可以放到 Flash 中的其他地址處,這要取決于具體芯片設計。

當應用程序執行起來后,如果發生了中斷,系統會根據發出請求的外設中斷號來中斷向量表里找到對應的外設中斷響應函數并去執行。Cortex-M 內核(除了CM0)模塊 SCB 里有個專門的 VTOR 寄存器用來控制中斷向量表首地址(注意,地址需要 128 字節對齊),程序運行起來后用戶可以配置 SCB->VTOR 寄存器來重設中斷向量表地址。

2.1 中斷向量表定義

中斷向量表可以通過匯編語言定義也可以通過C語言定義。以下列出兩種方式的示例程序。

  • C語言定義

這里我們定義了一個數組,數組的每一項對應相應的中斷函數。如上所述,數組的第一項為初始棧指針,第二項為入口函數地址。余下的所有中斷都指向了一個通用中斷函數。開發者可以根據需求替代相應的中斷函數。

上文還提到中斷向量表需要放置于閃存起始地址處。這里__attribute__((section(".vectors")))為gcc的特定語法(如果開發者使用IAR或者其他編譯器,語法有所不同),目的是告訴編譯器在鏈接所有對象文件(objects)時把_vector[]數組放在鏈接腳本(linker script)中的.vectors段落(section)。在鏈接腳本中,.vector段落被定義于閃存起始處。

#ifndef ARMV7M_PERIPHERAL_INTERRUPTS
#  error ARMV7M_PERIPHERAL_INTERRUPTS must be defined to the number of I/O interrupts to be supported
#endif

extern void exception_common(void);
unsigned _vectors[] __attribute__((section(".vectors"))) =
{
  /* Initial stack */
  IDLE_STACK,
  /* Reset exception handler */
  (unsigned)&__start,
  /* Vectors 2 - n point directly at the generic handler */
  [2 ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)] = (unsigned)&exception_common
};
  • Assembly語言定義

這里以STM32Cube生成的startup_stm32f103xe.s為示例。同樣的,匯編程序中也定義了默認中斷函數。所有中斷也都指向了默認的中斷函數Default_Handler(默認為無限循環)。

/**
 * @brief  This is the code that gets called when the processor receives an
 *         unexpected interrupt.  This simply enters an infinite loop, preserving
 *         the system state for examination by a debugger.
 *
 * @param  None
 * @retval : None
*/
    .section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
  b Infinite_Loop
  .size Default_Handler, .-Default_Handler

之后是中斷向量表。這里為了縮減示例代碼長度,略去了中間的中斷函數定義。注意在初始處 .section .isr_vector,"a",%progbits語句指定了g_pfnVectors在鏈接是需要被放置在isr_vector段落,也就是閃存起始地址處。

/******************************************************************************
*
* The minimal vector table for a Cortex M3.  Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
******************************************************************************/
  .section .isr_vector,"a",%progbits
  .type g_pfnVectors, %object
  .size g_pfnVectors, .-g_pfnVectors


g_pfnVectors:

  .word _estack
  .word Reset_Handler
  .word NMI_Handler
  .word HardFault_Handler
  .word MemManage_Handler
  .word BusFault_Handler
  .word UsageFault_Handler
  .word 0
  .word 0
  .word 0
  .word 0
  .word SVC_Handler
  .word DebugMon_Handler
  .word 0
  .word PendSV_Handler
  .word SysTick_Handler
  .word WWDG_IRQHandler
  .word PVD_IRQHandler
……

在中斷向量表的定義之后,程序還將所有函數定義為.weak。也就是說如果開發者在其他地方重新定義了同樣名稱的中斷函數,那么默認的中斷函數實現會被自動覆蓋。weak是GNU GCC編譯器定義的關鍵詞,如果采用其他編譯器會有對應的關鍵詞。

/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/

  .weak NMI_Handler
  .thumb_set NMI_Handler,Default_Handler

  .weak HardFault_Handler
  .thumb_set HardFault_Handler,Default_Handler

  .weak MemManage_Handler
  .thumb_set MemManage_Handler,Default_Handler

  .weak BusFault_Handler
  .thumb_set BusFault_Handler,Default_Handler

  .weak UsageFault_Handler
  .thumb_set UsageFault_Handler,Default_Handler
……

2.2 中斷向量表偏移寄存器

ARM Cortex-M默認的中斷向量表地址位于閃存起始地址處。但是ARM Cortex-M3/4系列提供了一個中斷向量表偏移寄存器(Vector Table Offset Reigster)。系統中中斷向量表的位置是0x00000000加上偏移寄存器的值。上電復位后這個寄存器值為0,所以中斷向量表默認位于0x00000000閃存起始處。這個寄存器的目的是為了讓開發者可以重新設置中斷向量表的位置。

中斷向量表偏移寄存器第29位(bit 29)定義了中斷向量表的位置。0表示位于閃存程序(code)中,1表示位于內存中(SRAM)。

中斷向量表寄存器低7位(bit 6~0)為系統預留位。

偏移地址寄存器值有對齊要求。這個要求和系統中斷數量或者說中斷向量表長度相關。偏移地址寄存器值至少是128 (32words = 128bytes)的整數倍,這也意味著中斷偏移寄存器中地址的低7位始終會是0。如果系統中斷數量大于16個,則總中斷數為ARM預留的16個中斷加上n個系統中斷。如果(n+2)不為2的指數,則向上找到最近的2的指數m。每個地址為4bytes所以對齊要求為m*4。例如系統有21個中斷,加上ARM預留的16個中斷位,則中斷向量表有效長度為37words。最近的2的指數值為64words = 256bytes。所以偏移寄存器的值必須為256的整數倍。

3 NVIC 簡介

在講如何配置中斷優先級之前,我們需要先了解下 NVIC。NVIC 是嵌套向量中斷控制器,控制著整個芯片中斷相關的功能,它跟內核緊密耦合,是內核里面的一個外設。但是各個芯片廠商在設計芯片的時候會對 Cortex-M內核里面的 NVIC 進行裁剪,把不需要的部分去掉,所以說 STM32 的 NVIC 是 Cortex-M的 NVIC 的一個子集。

3.1 NVIC 寄存器簡介

在固件庫中, NVIC 的結構體定義可謂是頗有遠慮,給每個寄存器都預留了很多位,恐怕為的是日后擴展功能。不過 STM32F103 可用不了這么多,只是用了部分而已,具體使用了多少可參考《Cortex-M3內核編程手冊》的NVIC 寄存器映射。

1686377469416cg9c14iupo

[ps] NVIC 結構體定義,來自固件庫頭文件: core_cm3.h。

在配置中斷的時候我們一般只用 ISER、 ICER 和 IP 這三個寄存器, ISER 用來使能中斷, ICER 用來失能中斷,IP 用來設置中斷優先級。

3.2 NVIC 中斷配置固件庫

固件庫文件 core_cm3.h 的最后,還提供了 NVIC 的一些函數,這些函數遵循 CMSIS 規則,只要是 Cortex-M3 的處理器都可以使用,具體如下:

表3符合 CMSIS 標準的 NVIC 庫函數

NVIC庫函數 描述
void NVIC_EnableIRQ(IRQn_Type IRQn) 使能中斷
void NVIC_DisableIRQ(IRQn_Type IRQn) 失能中斷
void NVIC_SetPendingIRQ(IRQn_Type IRQn) 設置中斷懸起位
void NVIC_ClearPendingIRQ(IRQn_Type IRQn) 清除中斷懸起位
uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) 獲取懸起中斷編號
void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) 設置中斷優先級
uint32_t NVIC_GetPriority(IRQn_Type IRQn) 獲取中斷優先級
void NVIC_SystemReset(void) 系統復位

這些庫函數我們在編程的時候用的都比較少,甚至基本都不用。

4 優先級的定義

4.1 優先級定義

在 NVIC 有一個專門的寄存器:中斷優先級寄存器 NVIC_IPRx,用來配置外部中斷的優先級, IPR 寬度為 8bit,原則上每個外部中斷可配置的優先級為 0~255,數值越小,優先級越高。但是絕大多數 CM3 芯片都會精簡設計,以致實際上支持的優先級數減少,在F103 中,只使用了高 4bit,如下所示:

表4 STM32F103 使用 4bit 表達優先級

1686377469719a199v0rbx7

用于表達優先級的這 4bit,又被分組成搶占優先級和子優先級。如果有多個中斷同時響應,搶占優先級高的就會 搶占 搶占優先級低的優先得到執行,如果搶占優先級相同,就比較子優先級。如果搶占優先級和子優先級都相同的話,就比較他們的硬件中斷編號,編號越小,優先級越高。

4.2 優先級分組

優先級的分組由內核外設 SCB 的應用程序中斷及復位控制寄存器 AIRCR 的PRIGROUP[10:8]位決定,STM32F103 分為了 5 組,具體如下:主優先級=搶占優先級。

表5優先級分組

1686377469962qaq6biazqu

設置優先級分組可調用庫函數 NVIC_PriorityGroupConfig()實現,有關 NVIC 中斷相關的庫函數都在庫文件 misc.c 和 misc.h 中。

/**
  * 配置中斷優先級分組:搶占優先級和子優先級
 * 形參如下:
 * @arg NVIC_PriorityGroup_0: 0bit for 搶占優先級
 *                            4 bits for 子優先級
 * @arg NVIC_PriorityGroup_1: 1 bit for 搶占優先級
 *                            3 bits for 子優先級
 * @arg NVIC_PriorityGroup_2: 2 bit for 搶占優先級
 *                            2 bits for 子優先級
 * @arg NVIC_PriorityGroup_3: 3 bit for 搶占優先級
 *                            1 bits for 子優先級
 * @arg NVIC_PriorityGroup_4: 4 bit for 搶占優先級
 *                            0 bits for 子優先級
 * @注意 如果優先級分組為 0,則搶占優先級就不存在,優先級就全部由子優先級控制
 */
 void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
 {
     // 設置優先級分組
     SCB- >AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
 }

表6 優先級分組真值表

168637747023651nvqpjs0d

5 中斷編程

在配置每個中斷的時候一般有 3 個編程要點:

1、使能外設某個中斷,這個具體由每個外設的相關中斷使能位控制。比如串口有發送完成中斷,接收完成中斷,這兩個中斷都由串口控制寄存器的相關中斷使能位控制。

2、初始化 NVIC_InitTypeDef 結構體,配置中斷優先級分組,設置搶占優先級和子優先級,使能中斷請求。 NVIC_InitTypeDef 結構體在固件庫頭文件 misc.h 中定義。

typedef struct {
    uint8_t NVIC_IRQChannel; // 中斷源
    uint8_t NVIC_IRQChannelPreemptionPriority; // 搶占優先級
    uint8_t NVIC_IRQChannelSubPriority; // 子優先級
    FunctionalState NVIC_IRQChannelCmd; // 中斷使能或者失能
} NVIC_InitTypeDef;

有關 NVIC 初始化結構體的成員我們一一解釋下:

1) NVIC_IROChannel:用來設置中斷源,不同的中斷中斷源不一樣,且不可寫錯,即使寫錯了程序也不會報錯,只會導致不響應中斷。具體的成員配置可參考 stm32f10x.h 頭文件里面的 IRQn_Type 結構體定義,這個結構體包含了所有的中斷源。

typedef enum IRQn {
    //Cortex-M3 處理器異常編號
    NonMaskableInt_IRQn = -14,
    MemoryManagement_IRQn = -12,
    BusFault_IRQn = -11,
    UsageFault_IRQn = -10,
    SVCall_IRQn = -5,
    DebugMonitor_IRQn = -4,
    PendSV_IRQn = -2,
   SysTick_IRQn = -1,
   //STM32 外部中斷編號
   WWDG_IRQn = 0,
   PVD_IRQn = 1,
   TAMP_STAMP_IRQn = 2,

   //限于篇幅,中間部分代碼省略,具體的可查看庫文件 stm32f10x.h

   DMA2_Channel2_IRQn = 57,
   DMA2_Channel3_IRQn = 58,
   DMA2_Channel4_5_IRQn = 59
} IRQn_Type;

2) NVIC_IRQChannelPreemptionPriority:搶占優先級,具體的值要根據優先級分組來確定,具體參考表6優先級分組真值表 。

3) NVIC_IRQChannelSubPriority:子優先級,具體的值要根據優先級分組來確定,具體參考表6優先級分組真值表 。

4) NVIC_IRQChannelCmd:中斷使能( ENABLE)或者失能( DISABLE)。操作的是 NVIC_ISER 和 NVIC_ICER 這兩個寄存器。

3、編寫中斷服務函數

在啟動文件 startup_stm32f10x_hd.s 中我們預先為每個中斷都寫了一個中斷服務函數,只是這些中斷函數都是為空,為的只是初始化中斷向量表。實際的中斷服務函數都需要我們重新編寫,為了方便管理我們把中斷服務函數統一寫在 stm32f10x_it.c 這個庫文件中。關于中斷服務函數的函數名必須跟啟動文件里面預先設置的一樣,如果寫錯,系統就在中斷向量表中找不到中斷服務函數的入口,直接跳轉到啟動文件里面預先寫好的空函數,并且在里面無限循環,實現不了中斷。

審核編輯:湯梓紅

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

    關注

    6032

    文章

    44525

    瀏覽量

    633257
  • 嵌入式
    +關注

    關注

    5072

    文章

    19026

    瀏覽量

    303515
  • 中斷
    +關注

    關注

    5

    文章

    895

    瀏覽量

    41401
  • Cortex-M
    +關注

    關注

    2

    文章

    227

    瀏覽量

    29733
  • Systick
    +關注

    關注

    0

    文章

    62

    瀏覽量

    13045
收藏 人收藏

    評論

    相關推薦

    為什么說Cortex-M是低功耗應用的首選

    雖然Cortex-M處理器家族目標瞄準效能光譜較低端的區域,但是和大多數微控制器(MCU)采用的其他典型處理器相比,Cortex-M的效能依然算相當強悍。舉例來說,像是許多高效能微控制器所采用的Cortex-M4與
    發表于 07-28 09:44 ?3466次閱讀
    為什么說<b class='flag-5'>Cortex-M</b>是低功耗應用的首選

    如何選擇正確的Cortex-M處理器?

    本文將通過比較Cortex-M系列處理器之間的產品特性,告訴你如何根據產品應用選擇正確的Cortex-M處理器。同時也會詳細地進行Cortex-M系列處理器的指令集和高級中斷處理能力,
    發表于 10-22 08:16

    STM32中斷系統和Cortex-M中斷系統有何異同

    中斷是什么?STM32中斷系統和Cortex-M中斷系統有何異同?
    發表于 11-29 07:43

    STM32中斷系統和Cortex-M中斷系統的異同是什么?

    中斷是什么?STM32中斷系統和Cortex-M中斷系統的異同是什么?
    發表于 11-30 07:16

    Cortex-M中斷向量表對齊原則

    關注+星標公眾號,不錯過精彩內容來源| 痞子衡嵌入式一、Cortex-M中斷向量表對齊原則中斷向量表就是一個集中保存系統全部中斷處理函數(xxxIRQHandler)地址的常量數組(函
    發表于 01-25 07:10

    Cortex-M中斷向量表對齊的原則是什么?

    Cortex-M中斷向量表對齊的原則是什么?
    發表于 01-26 08:09

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

    ARM Cortex-M處理器家族現在有8款處理器成員。在本文中,會比較Cortex-M系列處理器之間的產品特性,重點講述如何根據產品應用選擇正確的Cortex-M處理器。本文中會詳細的對照C
    發表于 04-20 15:34 ?39次下載

    關于Cortex-M 調試應用的介紹

    Cortex-M 調試應用
    的頭像 發表于 07-10 00:56 ?2596次閱讀

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

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

    Cortex-M中斷向量表原理及其重定向方法~

    大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是Cortex-M中斷向量表原理及其重定向方法。接著前文《嵌入式Cortex-M裸機環境下臨界區保護的三種實現》繼續聊,嵌...
    發表于 12-01 12:21 ?9次下載
    <b class='flag-5'>Cortex-M</b><b class='flag-5'>中斷</b>向量表原理及其重定向方法~

    痞子衡嵌入式:嵌入式Cortex-M中斷向量表對齊原則的深入研究

      大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是Cortex-M中斷向量表對齊原則。  今天這篇文章的內容主要來自于五年前做 Kinetis K32W 系列雙核啟動時的發現
    發表于 12-01 12:51 ?0次下載
    痞子衡嵌入式:嵌入式<b class='flag-5'>Cortex-M</b><b class='flag-5'>中斷</b>向量表對齊原則的<b class='flag-5'>深入</b>研究

    Cortex-M中斷及FreeRTOS中斷優先級配置原理

    下面就來說說關于Cortex-M中斷,及FreeRTOS中斷優先級配置原理。
    發表于 02-08 15:30 ?3次下載
    <b class='flag-5'>Cortex-M</b><b class='flag-5'>中斷</b>及FreeRTOS<b class='flag-5'>中斷</b>優先級配置原理

    深入理解Cortex-M內存管理(GCC)

    在討論Cortex-M的內存之前,先來看看Cortex-M的存儲器系統,我們知道,Cortex-M系列的處理器,大都可以對32的存儲器進行尋址,因此存儲器的尋址空間能夠達到4G,這就意味著指定和數
    的頭像 發表于 04-27 10:58 ?2825次閱讀
    <b class='flag-5'>深入</b>理解<b class='flag-5'>Cortex-M</b>內存管理(GCC)

    Cortex-M 內核中斷/異常系統、中斷優先級/嵌套 詳解

    Cortex-M 內核中斷/異常系統、中斷優先級/嵌套 詳解
    的頭像 發表于 09-27 15:29 ?2021次閱讀
    <b class='flag-5'>Cortex-M</b> 內核<b class='flag-5'>中斷</b>/異常系統、<b class='flag-5'>中斷</b>優先級/嵌套 詳解

    Cortex-M位帶操作的原理

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