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

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

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

Cortex-M核心寄存器和位域

云深之無跡 ? 來源:云深之無跡 ? 2023-05-29 10:28 ? 次閱讀

我相信昨天的文章你一定大飽眼福了,沒關(guān)系,接下來的更精彩,也會(huì)對(duì)C語言有個(gè)全新的理解。

今天這個(gè)文件屬于CM3核心定義:有CMSIS核心的所有結(jié)構(gòu)和符號(hào)

Cortex-M核心寄存器和位域,Cortex-M核心外設(shè)基址。

c188ca58-fd23-11ed-90ce-dac502259ad0.png

今天的對(duì)象在這里

c1a8bd68-fd23-11ed-90ce-dac502259ad0.png

先看h文件的前面幾行

根據(jù)前面三行宏定義,最終計(jì)算出的CMSIS HAL庫完整版本號(hào)為:__CM3_CMSIS_VERSION = (0x01 << 16) | 0x30 = 0x010030所以,完整的版本號(hào)為0x010030。

其中:__CM3_CMSIS_VERSION_MAIN = 0x01,主版本號(hào)為0x01__CM3_CMSIS_VERSION_SUB = 0x30,子版本號(hào)為0x30通過左移16位實(shí)現(xiàn)主版本號(hào) occupies 的高16位,子版本號(hào)占低16位,然后按位或生成完整32位的版本號(hào)0x010030。

這個(gè)32位版本號(hào)包含了CMSIS HAL庫的主版本號(hào)與子版本號(hào)信息,通過該版本號(hào),根據(jù)這三行宏定義,可以知道當(dāng)前使用的CMSIS HAL庫的版本號(hào)為0x010030。其中高16位0x01表示主版本號(hào),低16位0x30表示子版本號(hào)。

0x010030

= 0x01 * (2^16) + 0x30 * (2^0)

= 1 * 65536 + 48 * 1

= 65536 + 48

= 65680

這是轉(zhuǎn)成10進(jìn)制的數(shù)字。

其中,主版本號(hào)0x01對(duì)應(yīng)的10進(jìn)制數(shù)為1,子版本號(hào)0x30對(duì)應(yīng)的10進(jìn)制數(shù)為48。

通過將主版本號(hào)的值×2^16,子版本號(hào)的值×2^0相加,我們可以得出CMSIS HAL庫完整版本號(hào)對(duì)應(yīng)的10進(jìn)制數(shù)65680。

這個(gè)10進(jìn)制數(shù)同樣包含了主版本號(hào)1和子版本號(hào)48的信息,我們可以清楚知道當(dāng)前使用的CMSIS HAL庫版本號(hào)為1.48。

1代表主版本號(hào),48代表子版本號(hào),兩者組合即為完整版本號(hào)1.48。

所以,總結(jié)來說,CMSIS-HAL庫的版本號(hào)0x010030

可以表示為:

Hex: 0x010030

Decimal: 65680

Version: 1.48

那不免有疑問,明明可以直接10進(jìn)制文件的,為啥這么復(fù)雜呢?讓我來斗膽的分析一下。

主要有以下幾個(gè)考慮因素:

1. 兼容性:使用位運(yùn)算生成的版本號(hào)格式0x010030與CMSIS HAL庫一致,這樣可以最大限度保證與庫的兼容性。

2. 擴(kuò)展性:使用位運(yùn)算,主版本號(hào)占高16位,子版本號(hào)占低16位,這樣主版本號(hào)可以擴(kuò)展到65536,子版本號(hào)也有很高擴(kuò)展空間,更利于版本的長期維護(hù)與擴(kuò)展。

3. 信息包含:32位的版本號(hào)可以同時(shí)包含主版本號(hào)與子版本號(hào),一目了然,這個(gè)信息直接清楚可見。如果只使用1.48形式,無法同時(shí)看到主子版本號(hào)的值,信息表達(dá)不夠直接。

4. 處理方便:位運(yùn)算生成的版本號(hào)可以通過簡單的移位與位運(yùn)算提取主版本號(hào)與子版本號(hào)的值,這在編程處理時(shí)比較方便。

5. 標(biāo)準(zhǔn)形式:0x開頭的十六進(jìn)制數(shù)是MCU編程中常用的標(biāo)準(zhǔn)表達(dá)形式,使用起來比較習(xí)慣。

所以,總體來說,雖然直接使用1.48的形式更簡單直觀,但使用位運(yùn)算生成0x010030格式的版本號(hào),可以在兼容性、擴(kuò)展性、信息包含以及處理方便性等方面獲得優(yōu)勢,也符合編程習(xí)慣的標(biāo)準(zhǔn)表達(dá)形式??紤]到CMSIS HAL庫作為MCU的底層支撐庫,需要長期維護(hù)與迭代,所以選擇使用位運(yùn)算生成版本號(hào)格式可以獲得更多優(yōu)點(diǎn),這可能也是CMSIS HAL庫設(shè)計(jì)者選擇這種版本號(hào)格式的主要考量因素。

c1f86a66-fd23-11ed-90ce-dac502259ad0.png

接下來看這個(gè)

這段代碼主要完成了MCU內(nèi)核類型與數(shù)據(jù)類型的定義。

__CORTEX_M (0x03) 此宏定義指定了內(nèi)核類型為Cortex-M3,其十六進(jìn)制值為0x03。

#include 此行包含stdint.h頭文件,用于定義標(biāo)準(zhǔn)數(shù)據(jù)類型,如Uint8_t、int32_t等。

#if defined(__ICCARM__) 此行條件判斷是否使用IAR編譯器,如果使用則包含intrinsics.h頭文件。

#include 此行包含intrinsics.h頭文件,該頭文件定義了IAR C/C++編譯器的內(nèi)嵌匯編指令。

所以,這段代碼主要完成了兩方面的工作:

1. 通過__CORTEX_M宏定義指定了MCU使用的內(nèi)核類型為Cortex-M3。2. 包含stdint.h頭文件,定義了標(biāo)準(zhǔn)的數(shù)據(jù)類型,用于MCU開發(fā)時(shí)使用。

3. 如果使用IAR編譯器,則額外包含intrinsics.h頭文件,可以使用IAR編譯器提供的內(nèi)嵌匯編指令。

這段簡短的代碼定義和包含了MCU開發(fā)最基礎(chǔ)的信息:

1. 內(nèi)核類型:我們知道目標(biāo)MCU使用的內(nèi)核是Cortex-M3。

2. 數(shù)據(jù)類型:通過stdint.h我們可以使用標(biāo)準(zhǔn)的數(shù)據(jù)類型,如Uint32_t等。

3. 如果使用IAR編譯器,可以使用內(nèi)嵌匯編指令來優(yōu)化程序。

c238e4c4-fd23-11ed-90ce-dac502259ad0.png

這幾個(gè)macro是頻繁出現(xiàn)的,細(xì)說一下

這段代碼主要定義了中斷優(yōu)先級(jí)位數(shù)和IO操作權(quán)限。

#ifndef __NVIC_PRIO_BITS

#define __NVIC_PRIO_BITS 4

#endif

這兩行定義了中斷優(yōu)先級(jí)位數(shù)為4,如果__NVIC_PRIO_BITS未定義,則進(jìn)行定義,否則忽略。

#ifdef __cplusplus

#define __I volatile

#else

#define __I volatile const

#endif

這幾行判斷是否使用C++編譯器,如果使用C++編譯器,__I定義為volatile,否則定義為volatile const,表示只讀屬性。

#define __O volatile

此行定義__O為volatile,表示只寫屬性。

#define __IO volatile

此行定義__IO為volatile,表示讀寫屬性。

所以,這段代碼主要完成了:

1. 如果__NVIC_PRIO_BITS未定義,則定義中斷優(yōu)先級(jí)位數(shù)為4。否則忽略。

2. 根據(jù)編譯器選擇定義只讀屬性__I為volatile或volatile const。

3. 定義只寫屬性__O為volatile。

4. 定義讀寫屬性__IO為volatile。

5. 這四個(gè)屬性主要用于定義外設(shè)寄存器的訪問權(quán)限,以確保編譯器不會(huì)對(duì)訪問的代碼作優(yōu)化,影響讀取的準(zhǔn)確性。

也就是說,這段代碼為寄存器的訪問屏蔽了編譯器的優(yōu)化,在編譯過程中讓編譯器明確區(qū)分:

這是一個(gè)只讀寄存器,值可能會(huì)被其他因素改變,讀取時(shí)總是獲取最新值。

這是一個(gè)只寫寄存器,每次寫入的值必須被外設(shè)接收。

這個(gè)寄存器是可讀寫的,讀取與寫入都必須準(zhǔn)確地映射到外設(shè)。這樣可以最大限度地確保我們的程序以預(yù)期的方式使用這些寄存器,也不會(huì)因?yàn)榫幾g器的優(yōu)化而導(dǎo)致意外的結(jié)果。

c2932402-fd23-11ed-90ce-dac502259ad0.png

接下來我們看這個(gè),知識(shí)點(diǎn)有點(diǎn)密集

c2dbe444-fd23-11ed-90ce-dac502259ad0.png

中斷到中斷向量的映射

顯示了中斷(或IRQ號(hào))如何映射到中斷寄存器和相應(yīng)的CMSIS變量(每個(gè)中斷有一位)。

這段代碼定義了NVIC_Type結(jié)構(gòu)體,用于表示NVIC(嵌套向量中斷控制器)的控制與狀態(tài)寄存器。

NVIC_Type結(jié)構(gòu)體包含以下成員:

__IO uint32_t ISER[8]; 中斷使能置位寄存器,用于使能中斷,數(shù)組8個(gè)成員對(duì)應(yīng)NVIC的8個(gè)中斷組。

__IO uint32_t ICER[8]; 中斷清除使能寄存器,用于禁止中斷,數(shù)組8個(gè)成員對(duì)應(yīng)NVIC的8個(gè)中斷組。

__IO uint32_t ISPR[8]; 中斷待處理置位寄存器,用于置位某中斷的待處理標(biāo)志,數(shù)組8個(gè)成員對(duì)應(yīng)NVIC的8個(gè)中斷組。

__IO uint32_t ICPR[8]; 中斷待處理清除寄存器,用于清除某中斷的待處理標(biāo)志,數(shù)組8個(gè)成員對(duì)應(yīng)NVIC的8個(gè)中斷組。

__IO uint32_t IABR[8]; 中斷激活寄存器,指示哪些中斷被激活,數(shù)組8個(gè)成員對(duì)應(yīng)NVIC的8個(gè)中斷組。

__IO uint8_t IP[240]; 中斷優(yōu)先級(jí)寄存器,設(shè)置優(yōu)先級(jí),共240個(gè)成員,每個(gè)成員1字節(jié),對(duì)應(yīng)MCU中的240個(gè)中斷優(yōu)先級(jí)設(shè)置。

__O uint32_t STIR; 軟件觸發(fā)中斷寄存器,用于軟件觸發(fā)指定的中斷。

所以,這個(gè)結(jié)構(gòu)體包含了NVIC所有的控制與狀態(tài)寄存器,通過這些寄存器,我們可以完成:

1. 中斷使能與失能設(shè)置。

2. 中斷待處理標(biāo)志的置位與清除。

3. 檢測哪些中斷被激活。

4. 設(shè)置各個(gè)中斷的優(yōu)先級(jí)。

5. 軟件觸發(fā)某個(gè)指定的中斷。

簡單來說,這個(gè)結(jié)構(gòu)體高度抽象和集成地代表了NVIC及其所有的功能與控制寄存器,使用時(shí)直接通過相應(yīng)的成員來操作寄存器。

這個(gè)NVIC_Type結(jié)構(gòu)體代表的不是某個(gè)具體的存儲(chǔ)區(qū)域,而是概念性地將NVIC所有的寄存器集成在一個(gè)結(jié)構(gòu)體中,以方便我們管理和訪問這些寄存器。
結(jié)構(gòu)體中的每個(gè)成員,如__IO uint32_t ISER[8]都代表NVIC中的一個(gè)實(shí)際的32位寄存器。
這些寄存器的地址在MCU的外設(shè)地址映射中已經(jīng)固定,結(jié)構(gòu)體將它們邏輯上集成在一起,方便我們按功能管理和訪問。
所以,當(dāng)我們需要操作NVIC使能某個(gè)中斷時(shí),只需要像下面這樣使用ISER成員:

NVIC->ISER[2]|=(1<
在MDK或IAR等IDE中,這些寄存器的具體地址將在外設(shè)地址映射Memap窗口中顯示。

例如,ISER[2]可能映射到0xE000E200這樣的實(shí)際地址,這個(gè)地址上的32位寄存器包含對(duì)應(yīng)的位用于使能第6個(gè)中斷。

所以,總結(jié)來說:
1. NVIC_Type 結(jié)構(gòu)體邏輯上將NVIC的所有寄存器集成在一起,方便管理和訪問,但本身不代表實(shí)際的存儲(chǔ)區(qū)域。
2. 結(jié)構(gòu)體中的每個(gè)成員代表NVIC中的一個(gè)實(shí)際物理寄存器,映射到固定的地址。
3. 我們通過結(jié)構(gòu)體操作這些寄存器,然后編譯器會(huì)將其映射到實(shí)際的物理地址上。
4. 這些寄存器的具體地址將在MCU的外設(shè)地址映射中指定,我們可以在IDE的Memap窗口中查看。
5. 所以結(jié)構(gòu)體更像是一個(gè)邏輯上的抽象,將NVIC的寄存器方便地集成在一起,在程序中按功能管理和訪問。

c300fa2c-fd23-11ed-90ce-dac502259ad0.png更多詳細(xì)的內(nèi)容得看這個(gè)

c3627d88-fd23-11ed-90ce-dac502259ad0.png

嵌套中斷矢量控制器

Cortex-M3 NVIC寄存器的CMSIS映射為了提高軟件效率,CMSIS簡化了NVIC寄存器的表示。

在CMSIS中:Set-enable, Clear-enable, Set-pending, Clear-pending和Active Bit寄存器映射到32位整數(shù)數(shù)組,因此:

c3a81820-fd23-11ed-90ce-dac502259ad0.png

看這個(gè)IS,IC,下面就不放了

數(shù)組ISER[O] ~ ISER[2]對(duì)應(yīng)寄存器ISERO-ISER2,

數(shù)組ICER[O] ~ ICER[2]對(duì)應(yīng)寄存器ICERO-ICER2,

數(shù)組ISPR[0] ~ ISPR[2]對(duì)應(yīng)寄存器ISPRO-ISPR2,

數(shù)組ICPR[O] ~ ICPR[2]對(duì)應(yīng)寄存器ICPRO-ICPR2,

數(shù)組IABR[O] ~ IABR[2]對(duì)應(yīng)寄存器IABRO-IABR2。

中斷優(yōu)先級(jí)寄存器的8位字段映射到一個(gè)8位整數(shù)數(shù)組,因此數(shù)組IP[O]到IP[67]對(duì)應(yīng)于寄存器IPRO-IPR67,數(shù)組]條目IP[n]保持中斷n的中斷優(yōu)先級(jí)。

CMSIS提供線程安全的代碼,提供對(duì)中斷優(yōu)先級(jí)寄存器的原子訪問。

我繼續(xù)說更多的細(xì)節(jié),__IO uint32_t ISER[8];比如這種寫法前面的__IO 是干嘛用的?我來解釋一下,看不懂的應(yīng)該是沒學(xué)過C。

__IO的定義如下:

#define __IO volatile

它被定義為volatile,意味著ISER[8]成員所代表的寄存器是一個(gè)讀寫寄存器。

所以,__IO的作用是:

1.通知編譯器ISER[8]成員所對(duì)應(yīng)寄存器的讀寫屬性,是可讀可寫的。

2.阻止編譯器對(duì)讀寫這些寄存器的代碼做優(yōu)化。因?yàn)檫@些寄存器的值可能會(huì)被其他因素改變,每次讀寫的值必須準(zhǔn)確對(duì)應(yīng)于寄存器的當(dāng)前值。如果不使用__IO對(duì)其進(jìn)行修飾,編譯器在編譯過程中可能會(huì)對(duì)訪問這些寄存器的代碼作優(yōu)化,這會(huì)導(dǎo)致我們讀到的值不是寄存器的真實(shí)值,產(chǎn)生意外的后果。

所以,__IO關(guān)鍵字通過定義為volatile,告訴編譯器:

1. ISER[8]成員代表的寄存器是可讀可寫的。

2. 每次讀取該寄存器必須從外設(shè)獲取最新值,寫入時(shí)必須將新值準(zhǔn)確寫入外設(shè)。

3. 編譯器在編譯過程中不得對(duì)其進(jìn)行任何優(yōu)化。

簡單來說,__IO關(guān)鍵字修飾uint32_t ISER[8]成員,目的是通知編譯器其對(duì)應(yīng)的寄存器屬性和訪問要求,進(jìn)而阻止編譯器的優(yōu)化,確保我們的程序以預(yù)期的方式正確訪問這些寄存器。這有利于我們編寫的代碼正常工作,不會(huì)因?yàn)榫幾g器的優(yōu)化引入意外的副作用,訪問寄存器時(shí)總是獲取最新的準(zhǔn)確值。

說完了嗎?還沒有,我還想bibi幾句:

在C語言中,__IO這樣在標(biāo)識(shí)符(如結(jié)構(gòu)體成員名)前面加上的關(guān)鍵字被稱為修飾符(qualifier)。修飾符的作用是為標(biāo)識(shí)符添加某種屬性或額外的語義。__IO 就是一個(gè)典型的修飾符例子,它被用來表示標(biāo)識(shí)符代表的是一個(gè)讀寫寄存器,并禁止編譯器對(duì)其優(yōu)化。

所以,__IO 在這里相當(dāng)于一個(gè)寄存器的修飾符,為其添加讀寫以及volatile 的屬性。

在C語言中,常見的修飾符還有:

1.const:常量修飾符,用于表示標(biāo)識(shí)符是一個(gè)常量。

2.volatile:指示值可能會(huì)被其他因素改變的修飾符,告訴編譯器每次讀取該值必須重新從內(nèi)存中獲取。

3.restrict:表示某指針是唯一訪問某塊內(nèi)存的手段,可以用來提高效率。

4.inline:表示該函數(shù)是內(nèi)聯(lián)函數(shù),由編譯器直接將函數(shù)體插入調(diào)用處。

5. extern:表示該標(biāo)識(shí)符(如變量或函數(shù))的定義在其他地方,extern int a;

所以,總結(jié)來說:

1.修飾符是放在標(biāo)識(shí)符(如變量名、函數(shù)名、結(jié)構(gòu)體成員名)前面的關(guān)鍵字。2.修飾符的作用是為標(biāo)識(shí)符添加某種屬性或語義。

3.__IO 是作為寄存器修飾符使用的,表示寄存器是可讀寫的,并禁止編譯器對(duì)其優(yōu)化。

4.const、volatile、restrict、inline、extern都是常見的修飾符,用來表示常量性、值變化、函數(shù)內(nèi)聯(lián)等屬性。

5.使用修飾符可以為程序添加重要的額外信息,引導(dǎo)編譯器作出正確的處理。

再擴(kuò)展一些,這個(gè)東西可以在函數(shù)上面用嗎?我這里先噴,以前不懂這個(gè)群里面問半天,結(jié)果都雞兒半桶水,讓我寫什么程序自己實(shí)驗(yàn),真心累啊。

在C語言中修飾符也可以用于修飾函數(shù)。

常見的用于修飾函數(shù)的修飾符有:
1. inline:表示該函數(shù)是內(nèi)聯(lián)函數(shù),主要作用是鼓勵(lì)編譯器將函數(shù)體直接插入所有調(diào)用點(diǎn),以減少函數(shù)調(diào)用的開銷。
2. extern:表示該函數(shù)的定義在其他地方,用于函數(shù)前向聲明。例如: inline void func1() { ... } // 內(nèi)聯(lián)函數(shù)
extern void func2(); // 函數(shù)前向聲明
void func2() { ... } // 函數(shù)定義 在這個(gè)例子中:
func1被inline修飾,表示其是一個(gè)內(nèi)聯(lián)函數(shù),編譯器可以選擇將其函數(shù)體插入調(diào)用處。
func2首先被extern修飾,進(jìn)行前向聲明,然后給出函數(shù)定義。

另外,static、volatile 等修飾符也可以用于修飾函數(shù),區(qū)別如下:
static:static修飾的函數(shù)只在定義它的文件內(nèi)可見,表示私有函數(shù)。
volatile:volatile修飾的函數(shù)其地址可能改變,每次調(diào)用時(shí)必須從內(nèi)存中獲取最新地址。

主要用于嵌入式中斷函數(shù)等。所以,總結(jié)來說:

1.C語言中的修飾符不僅可以用于修飾變量,也可以用于修飾函數(shù)。
2.常見的用于修飾函數(shù)的修飾符有inline、extern、static、volatile等。3.inline表示內(nèi)聯(lián)函數(shù),extern表示函數(shù)前向聲明,static表示私有函數(shù),volatile表示地址可能改變的函數(shù)。
4.使用修飾符可以為函數(shù)添加額外的屬性和語義,引導(dǎo)編譯器生成我們期望的代碼,這在優(yōu)化程序性能方面具有很好的作用。

那我在這個(gè)函數(shù)前面就放一個(gè)用宏定義的修飾符,宏什么都不定義。這個(gè)會(huì)報(bào)錯(cuò)了,一定要記住程序是最確定的東西。

#define __MY_MODIFIER

__MY_MODIFIER void func() { ... }

這里的__MY_MODIFIER宏未進(jìn)行任何定義,所以編譯器并不知道它表示什么屬性或語義。在編譯這個(gè)代碼時(shí),編譯器會(huì)報(bào)類似下面的錯(cuò)誤:undefined identifier '__MY_MODIFIER'這是因?yàn)榫幾g器并不識(shí)別__MY_MODIFIER這個(gè)未定義標(biāo)識(shí)符,所以不明白它作為函數(shù)修飾符的作用,這會(huì)導(dǎo)致編譯錯(cuò)誤。要使用我們自己定義的修飾符,需要為其給出明確的定義,例如:

#define __MY_MODIFIER static

__MY_MODIFIER void func() { ... }

這里我們定義__MY_MODIFIER為static,這樣編譯器就能理解其作用,并將func函數(shù)定義為靜態(tài)的。所以,總結(jié)來說:1. 若要使用自定義的修飾符,必須為其給出明確的定義,否則編譯器無法理解其作用,會(huì)報(bào)錯(cuò)。2.自定義修飾符的定義可以通過#define來實(shí)現(xiàn),例如#define __MY_MODIFIER static。3. 定義后,修飾符可以用于修飾變量、函數(shù)等,編譯器會(huì)根據(jù)其定義來理解其修飾的作用。4. 未定義的修飾符會(huì)導(dǎo)致編譯錯(cuò)誤,因?yàn)榫幾g器不知道如何處理這個(gè)未知的標(biāo)識(shí)符。5. 自定義修飾符的一個(gè)重要應(yīng)用就是,當(dāng)標(biāo)準(zhǔn)修飾符無法滿足需要時(shí),我們可以定義自己的修飾符來擴(kuò)展語言和表達(dá)程序語義。

c3df5b6e-fd23-11ed-90ce-dac502259ad0.png

對(duì)于這個(gè)中斷的寄存器就是這些,不要陷入太深,繼續(xù)往下看

系統(tǒng)控制塊(SCB)系統(tǒng)控制塊(System control block, SCB)提供系統(tǒng)實(shí)現(xiàn)信息和系統(tǒng)控制。這包括系統(tǒng)異常的配置、控制和報(bào)告。

Cortex-M3 SCB寄存器的CMSIS映射為了提高軟件效率,CMSIS簡化了SCB寄存器的表示。

在CMSIS中,字節(jié)數(shù)組SHP[0]到SHP[12]對(duì)應(yīng)寄存器SHPR1-SHPR3。

c404a874-fd23-11ed-90ce-dac502259ad0.png

接著就是這個(gè)了

這個(gè)結(jié)構(gòu)體定義了SCB(系統(tǒng)控制塊)的寄存器集。SCB模塊是Cortex-M內(nèi)核的一部分,用于系統(tǒng)控制與配置。

SCB_Type 結(jié)構(gòu)體包含以下主要成員:

__I uint32_t CPUID; CPUID寄存器,包含設(shè)備ID和修訂信息。

__IO uint32_t ICSR; 中斷控制狀態(tài)寄存器,用于中斷使能、優(yōu)先級(jí)設(shè)置和掛起狀態(tài)控制。

__IO uint32_t VTOR; 向量表偏移寄存器,配置中斷/異常向量表的位置和偏移。

__IO uint32_t AIRCR; 應(yīng)用中斷/復(fù)位控制寄存器,用于配置中斷優(yōu)先級(jí)組和系統(tǒng)復(fù)位。

__IO uint32_t SCR; 系統(tǒng)控制寄存器,用于配置中斷優(yōu)先級(jí)組、SLEEPDEEP位等。

__IO uint32_t CCR; 配置控制寄存器,用于配置存儲(chǔ)器mapped模式和無效指令報(bào)告位。

__IO uint8_t SHP[12]; 系統(tǒng)句柄程序優(yōu)先級(jí)寄存器,設(shè)置不同異常的優(yōu)先級(jí)。

__IO uint32_t SHCSR; 系統(tǒng)句柄控制和狀態(tài)寄存器,報(bào)告不同異常的掛起和激活狀態(tài)。

CFSR、HFSR、DFSR; 可配置故障狀態(tài)寄存器,用于報(bào)告各種故障和異常的狀態(tài)。

MMFAR、BFAR;內(nèi)存錯(cuò)誤和總線故障地址寄存器,報(bào)告相關(guān)故障的地址。PFR、DFR、ADR; 寄存器用于報(bào)告處理器特征、調(diào)試功和輔助功能。MMFR、ISAR; 寄存器用于報(bào)告內(nèi)存模型和指令集架構(gòu)的特征。

所以,SCB_Type結(jié)構(gòu)體包含SCB模塊所有的控制/狀態(tài)寄存器和ID寄存器,通過這些寄存器我們可以完成:

1. 中斷控制(使能/禁止)和優(yōu)先級(jí)設(shè)置。

2. 配置向量表位置和系統(tǒng)復(fù)位。

3. 設(shè)置不同異常的優(yōu)先級(jí)別。

4. 獲取設(shè)備ID、內(nèi)核修訂版本以及各種特征信息。

5. 獲取并處理不同類型的故障和異常。

6. 配置系統(tǒng)控制位,如SLEEPDEEP。

c46b9746-fd23-11ed-90ce-dac502259ad0.png

接下來定義的是這樣的東西,本來這種細(xì)節(jié)的東西就不寫了,但是為了精通這個(gè)小目標(biāo)是要寫的。

上面這個(gè)代碼可能看起來有點(diǎn)懵逼,這里其實(shí)都是底層的寄存器,不妨去看看這個(gè):

c4aa6174-fd23-11ed-90ce-dac502259ad0.png這個(gè)就是對(duì)應(yīng)的寄存器布局,我們只是想知道里面是啥而已

這些宏定義用于讀取SCB->CPUID寄存器中的設(shè)備ID和修訂信息。其中:SCB_CPUID_IMPLEMENTER_Pos和SCB_CPUID_IMPLEMENTER_Msk用于讀取IMPLEMENTER字段,該字段包含CPU的制造商ID。SCB_CPUID_VARIANT_Pos和SCB_CPUID_VARIANT_Msk用于讀取VARIANT字段,該字段包含CPU的變體編號(hào)。SCB_CPUID_PARTNO_Pos和SCB_CPUID_PARTNO_Msk用于讀取PARTNO字段,該字段包含CPU的具體型號(hào)。SCB_CPUID_REVISION_Pos和SCB_CPUID_REVISION_Msk用于讀取REVISION字段,該字段包含CPU的修訂版本。所以,通過這些宏,我們可以從SCB->CPUID寄存器中提取關(guān)鍵的設(shè)備信息:制造商ID:

uint32_t implementer = (SCB->CPUID & SCB_CPUID_IMPLEMENTER_Msk) >> SCB_CPUID_IMPLEMENTER_Pos;

變體編號(hào):

uint32_t variant = (SCB->CPUID & SCB_CPUID_VARIANT_Msk) >> SCB_CPUID_VARIANT_Pos;

CPU型號(hào):

uint32_t partNo = (SCB->CPUID & SCB_CPUID_PARTNO_Msk) >> SCB_CPUID_PARTNO_Pos;

CPU修訂版本:

uint32_t revision = (SCB->CPUID & SCB_CPUID_REVISION_Msk) >> SCB_CPUID_REVISION_Pos;

ARM Cortex-M內(nèi)核的CPUID寄存器包含這些關(guān)鍵字段,方便識(shí)別和區(qū)分不同的芯片,并獲取其精確的型號(hào)與修訂信息。宏定義極大地簡化提取這些信息的過程,只需要通過位域操作和移位就可以獲得所需要的ID參數(shù),這在很大程度上增強(qiáng)了代碼的可讀性。

c4da47cc-fd23-11ed-90ce-dac502259ad0.png

不在乎含義,在乎寫法,接下來看寫法

SCB_CPUID_IMPLEMENTER_Pos代表:

IMPLEMENTER字段在CPUID寄存器中的起始位置(偏移),其值為24。

SCB_CPUID_IMPLEMENTER_Msk代表:

IMPLEMENTER字段的掩碼,通過將0xFF左移24位得到,其值為0xFF000000。所以,要讀取IMPLEMENTER字段,我們可以像下面這樣使用這兩個(gè)宏:

uint32_t implementer = (SCB->CPUID & SCB_CPUID_IMPLEMENTER_Msk) >> SCB_CPUID_IMPLEMENTER_Pos;

該語句通過與SCB_CPUID_IMPLEMENTER_Msk的位與操作獲取IMPLEMENTER字段,然后右移SCB_CPUID_IMPLEMENTER_Pos(24)位,將其移到最低8位,obtaining the implementer code.

例如,如果CPUID的值為0x410FC241,那么:SCB->CPUID = 0x410FC241
SCB_CPUID_IMPLEMENTER_Msk = 0xFF000000
通過與操作:0x410FC241 & 0xFF000000 = 0x41000000
右移24位:0x41000000 >> 24 = 0x41 = 65(十進(jìn)制)所以,IMPLEMENTER字段的值為65(十進(jìn)制),表示CPU的制造商是ARM。位域操作通過掩碼獲取目標(biāo)字段,位移則將其移到需要的位置。

位域和位移都是位運(yùn)算的概念,用于在二進(jìn)制位級(jí)別操作和訪問數(shù)據(jù)。位域操作用于在一個(gè)數(shù)據(jù)域(如寄存器)的不同位上訪問多個(gè)字段。它通過掩碼來選擇和操作目標(biāo)字段中的位。

常用的位域操作有:與(&):如果兩個(gè)操作數(shù)的對(duì)應(yīng)比特位都是1,則該位的結(jié)果為1,否則為0。用于選取目標(biāo)字段。或(|):只要兩個(gè)操作數(shù)的對(duì)應(yīng)比特位有一個(gè)為1,則該位的結(jié)果為1。用于修改或設(shè)置字段的值。非(~) :反轉(zhuǎn)操作數(shù)的每一位,0變1,1變0。用于對(duì)字段取反。

位移則用于將數(shù)據(jù)的位向左或向右移動(dòng)給定的位數(shù),實(shí)際上是在給定方向上對(duì)數(shù)據(jù)的表示形式進(jìn)行擴(kuò)展或截?cái)唷?/p>

按方向分為:左移(<<):向左移動(dòng),低位補(bǔ)0,用于擴(kuò)展數(shù)據(jù)類型或?qū)崿F(xiàn)乘法。右移(>>):向右移動(dòng),根據(jù)數(shù)據(jù)類型,高位或補(bǔ)0或補(bǔ)符號(hào)位,用于縮小數(shù)據(jù)類型或?qū)崿F(xiàn)除法。

所以,要訪問SCB->CPUID寄存器的不同字段,我們可以:1.使用與操作和掩碼獲取目標(biāo)字段,例如用SCB_CPUID_IMPLEMENTER_Msk獲取IMPLEMENTER字段。2.必要時(shí)使用位移將字段移到需要的位置,例如用SCB_CPUID_IMPLEMENTER_Pos右移24位將IMPLEMENTER移到低8位。3.組合位域操作讀取和修改字段。例如用或操作將某位設(shè)置為1,用與操作清0某位。

例如,要讀取CPUID的IMPLEMENTER字段:

uint32_t implementer = (SCB->CPUID & SCB_CPUID_IMPLEMENTER_Msk) >> SCB_CPUID_IMPLEMENTER_Pos;

要設(shè)置CPUID的REVISION字段的第3位:

SCB->CPUID |= (1 << 3); // 用或操作將第3位設(shè)置為1

要清CPUID的VARIANT字段的低4位:

SCB->CPUID &= ~((0xF) << SCB_CPUID_VARIANT_Pos); // 用與操作和反碼清除低4位

繼續(xù)放大鏡看這個(gè)代碼,我們看這個(gè)1ul的定義方式:

c4ffb6f6-fd23-11ed-90ce-dac502259ad0.png

1ul

1ul是一個(gè)無符號(hào)長整型(unsigned long)常量,其值為1。在C語言中,整型常量的默認(rèn)類型為int,但可以通過后綴來指定不同的類型。常見的后綴有:無符號(hào)(unsigned):- u或U:無符號(hào)整型,如1u
- ul或UL:無符號(hào)長整型,如1ul長整型(long):- l或L:長整型,如1l無符號(hào)長整型(unsigned long):- ul或UL:無符號(hào)長整型,如1ul大小寫無關(guān),所以1u、1ul、1U和1UL都是等價(jià)的。

使用這些后綴的主要目的是為了在某些情況下指定常量的精確類型,避免由默認(rèn)類型帶來的怪異行為。例如,在32位系統(tǒng)上,int和unsigned int都是32位,所以1和1u的值相同。
但long可能是32位,而unsigned long是64位,所以1l和1ul的值會(huì)不同。所以,當(dāng)我們需要一個(gè)無符號(hào)的32/64位整型常量時(shí),就可以使用1u或1ul來指定其精確類型,這可以避免一些潛在的問題。

另外,這些后綴也常用于定義寄存器和位域的掩碼常量,例如:

#define UART_DATA_MASK   0xFFul     // 8位無符號(hào)數(shù)據(jù)掩碼  
#define UART_PARITY_MASK 0x01ul     // 1位無符號(hào)奇偶校驗(yàn)位掩碼

這里使用ul是為了確保掩碼常量被定義為32位,與寄存器大小一致。所以,總結(jié)來說:1. 1ul是一個(gè)無符號(hào)長整型常量,其值為1。2. 后綴u、ul、U和UL用于定義無符號(hào)整型和無符號(hào)長整型常量。3. 使用這些后綴可以指定常量的精確類型,避免默認(rèn)類型帶來的問題。4. 這些后綴常用于定義寄存器和位域的掩碼常量,確保其大小與目標(biāo)寄存器一致。

c522fdfa-fd23-11ed-90ce-dac502259ad0.png

這個(gè)結(jié)構(gòu)體定義了SysTick定時(shí)器的寄存器集。SysTick是Cortex-M內(nèi)核的一部分,用于生成定時(shí)中斷和延時(shí)。

SysTick_Type結(jié)構(gòu)體包含以下成員:

__IO uint32_t CTRL; SysTick控制和狀態(tài)寄存器,用于使能SysTick定時(shí)器,選擇時(shí)鐘源和計(jì)數(shù)模式。

__IO uint32_t LOAD; SysTick重載值寄存器,設(shè)置SysTick定時(shí)器的重載值,該值決定定時(shí)周期。

__IO uint32_t VAL; SysTick當(dāng)前值寄存器,在運(yùn)行過程中存儲(chǔ)SysTick定時(shí)器的當(dāng)前值。

__I uint32_t CALIB; SysTick校準(zhǔn)值寄存器,提供設(shè)備特定的時(shí)鐘頻率信息,用于計(jì)算延時(shí)。

所以,通過這個(gè)結(jié)構(gòu)體,我們可以訪問SysTick定時(shí)器的所有控制/狀態(tài)寄存器和校準(zhǔn)寄存器,并完成:

1. 使能或關(guān)閉SysTick定時(shí)器。

2. 選擇SysTick的時(shí)鐘源,如內(nèi)核時(shí)鐘AHB或外部參考時(shí)鐘。

3. 選擇遞減計(jì)數(shù)模式或遞增計(jì)數(shù)模式。

4.設(shè)置SysTick定時(shí)器的重載值,配置其定時(shí)周期。

5.讀取當(dāng)前的計(jì)數(shù)值VAL。

6.獲取設(shè)備的時(shí)鐘頻率信息CALIB,用于生成精確延時(shí)。

7.SysTick定時(shí)器溢出時(shí)產(chǎn)生中斷,所以也用作系統(tǒng)的節(jié)拍定時(shí)器。

SysTicktimer(STK)處理器有一個(gè)24位系統(tǒng)計(jì)時(shí)器SysTick,它從重新加載值開始計(jì)數(shù)到零,在下一個(gè)時(shí)鐘邊緣重新加載(封裝到)LOAD寄存器中的值,然后在隨后的時(shí)鐘上計(jì)數(shù)。當(dāng)處理器停止調(diào)試時(shí),計(jì)數(shù)器不會(huì)減少。

再詳細(xì)一些介紹這個(gè):

1.最大計(jì)數(shù)值為24位,所以最大延時(shí)為16777216個(gè)時(shí)鐘周期。

2.可以選擇內(nèi)核時(shí)鐘AHB或外部參考時(shí)鐘作為時(shí)鐘源。

3.可以選擇遞增計(jì)數(shù)模式或遞減計(jì)數(shù)模式。

4.重載值寄存器LOAD用于設(shè)置定時(shí)周期,每次定時(shí)器溢出時(shí)重新裝載該值。

5.當(dāng)前值寄存器VAL存儲(chǔ)定時(shí)器的實(shí)時(shí)計(jì)數(shù)值。

6.定時(shí)器溢出時(shí)觸發(fā)SysTick異常請(qǐng)求,可以配置為產(chǎn)生中斷。

7.時(shí)鐘頻率預(yù)分頻因子固定為8,不可配置。

8. 中斷優(yōu)先級(jí)固定為最低級(jí)別,僅可屏蔽但不可修改。

9.包含一設(shè)備特定的校準(zhǔn)寄存器,提供系統(tǒng)時(shí)鐘頻率信息,用于實(shí)現(xiàn)準(zhǔn)確延時(shí)?;?/p>

于以上特性,我們可以這樣配置和使用SysTick定時(shí)器:

1.使能SysTick定時(shí)器,選擇AHB時(shí)鐘源。

2.配置 SysTick_LOAD寄存器為重載值(如1000),每1000個(gè)時(shí)鐘周期產(chǎn)生一個(gè)中斷。

3.等待SysTick定時(shí)器中斷,并在中斷服務(wù)程序內(nèi)進(jìn)行任務(wù)調(diào)度或其他定時(shí)任務(wù)。

4.獲取SysTick_CALIB的值,例如0x0320,表明每個(gè)時(shí)鐘周期大約為30.5us。

5.要延時(shí)100ms,計(jì)算需要的時(shí)鐘周期數(shù):100ms / 30.5us = 3276。寫入SysTick_LOAD,使能定時(shí)器。

6.等待SysTick定時(shí)器中斷,表示延時(shí)完成。

所以,SysTick模塊為Cortex-M3內(nèi)核提供了一個(gè)簡單而高效的定時(shí)器,可用于RTOS的任務(wù)調(diào)度、軟件延時(shí)和其他定時(shí)事件。它的24位計(jì)數(shù)器和微秒級(jí)精度可以滿足大多數(shù)應(yīng)用的需要。

和其它的定時(shí)器外設(shè)比較有什么區(qū)別?

SysTick定時(shí)器有以下主要用途:

1.提供系統(tǒng)節(jié)拍定時(shí)器,用于RTOS的任務(wù)調(diào)度。RTOS可以配置SysTick產(chǎn)生中斷,并在中斷處理程序中進(jìn)行任務(wù)切換。

2.實(shí)現(xiàn)軟件延時(shí)。我們可以根據(jù)SysTick的定時(shí)周期計(jì)算需要的計(jì)數(shù)值來生成所需延時(shí)。

3.其他定時(shí)事件。SysTick定時(shí)器可以用于系統(tǒng)的各種定時(shí)任務(wù),如定時(shí)監(jiān)測、看門狗喂狗等。

與其他定時(shí)器外設(shè)相比,SysTick定時(shí)器有以下區(qū)別:

1.SysTick定時(shí)器是Cortex-M內(nèi)核的一部分,而其他定時(shí)器屬于MCU的外設(shè)。所以SysTick定時(shí)器更輕量,通用性更強(qiáng)。

2.SysTick定時(shí)器的時(shí)鐘源只能選擇內(nèi)核時(shí)鐘或外部參考時(shí)鐘,而其他定時(shí)器通常有更多時(shí)鐘源選擇。

3.SysTick定時(shí)器的計(jì)數(shù)器只有24位,范圍更小。其他定時(shí)器的計(jì)數(shù)器可以達(dá)32位或更高。

4.SysTick定時(shí)器的中斷優(yōu)先級(jí)固定為最低,無法配置。其他定時(shí)器的中斷通??梢耘渲脙?yōu)先級(jí)。

5.SysTick定時(shí)器只有比較基本的控制寄存器,更簡單。其他定時(shí)器通常具有更豐富的控制與配置選項(xiàng)。

6.SysTick定時(shí)器的溢出事件只能產(chǎn)生中斷,無法產(chǎn)生DMA請(qǐng)求等。部分定時(shí)器可以通過多種方式響應(yīng)溢出事件。

讓我來說下這個(gè)計(jì)數(shù)模式:

遞增計(jì)數(shù)模式和遞減計(jì)數(shù)模式是定時(shí)器的兩種不同的計(jì)數(shù)方式:

遞增計(jì)數(shù)模式:定時(shí)器的計(jì)數(shù)器從初始值(通常為0)開始遞增,當(dāng)計(jì)數(shù)器達(dá)到重載值時(shí),定時(shí)器溢出。然后計(jì)數(shù)器重載為初始值,重新開始遞增。如果配置為產(chǎn)生中斷,則在計(jì)數(shù)器達(dá)到重載值時(shí)觸發(fā)中斷。

例如,如果初始值為0,重載值為100,則計(jì)數(shù)序列為:

0, 1, 2, 3, ... 98, 99, 100 - 觸發(fā)中斷 - 0, 1, 2, 3 ...

遞減計(jì)數(shù)模式:

定時(shí)器的計(jì)數(shù)器從重載值開始遞減,當(dāng)計(jì)數(shù)器達(dá)到0時(shí),定時(shí)器溢出。然后計(jì)數(shù)器重載為重載值,重新開始遞減。如果配置為產(chǎn)生中斷,則在計(jì)數(shù)器達(dá)到0時(shí)觸發(fā)中斷。

例如,如果重載值為100,則計(jì)數(shù)序列為:

100, 99, 98, 97 ... 3, 2, 1, 0 - 觸發(fā)中斷 - 100, 99, 98 ...

所以,主要差異在于計(jì)數(shù)器的初始值和溢出條件不同:

遞增模式:

初始值:通常為0

溢出條件:計(jì)數(shù)器達(dá)到重載值

遞減模式:

初始值:等于重載值

溢出條件:計(jì)數(shù)器達(dá)到0

讓我們來探究一下這個(gè)設(shè)計(jì)意圖,就是定時(shí)器的設(shè)計(jì)意圖。

1.適應(yīng)開發(fā)者的習(xí)慣。有的開發(fā)者更習(xí)慣從0開始遞增計(jì)數(shù),有的更習(xí)慣從最大值開始遞減計(jì)數(shù),所以提供兩種模式以滿足不同習(xí)慣。

2.方便實(shí)現(xiàn)定時(shí)器的溢出中斷。無論是遞增模式從0溢出到重載值,還是遞減模式從重載值溢出到0,都可以很簡單地通過比較計(jì)數(shù)器與重載值/0來檢測溢出事件并產(chǎn)生中斷。

3.擴(kuò)展定時(shí)范圍。24位的定時(shí)器,遞增模式下最大延時(shí)為2^24個(gè)周期,若選擇遞減模式,最大延時(shí)可擴(kuò)展為2^24 + 重載值個(gè)周期,所以可獲得較大的定時(shí)范圍。

4. 不同模式下的溢出事件可用于不同用途。例如,可以選擇遞增模式用于周期性中斷,而選擇遞減模式用于超時(shí)檢測。兩種事件可以同時(shí)使用,擴(kuò)展定時(shí)器的應(yīng)用。

5. 簡化硬件設(shè)計(jì)。提供兩種模式而非只有一種,可以在軟件中通過配置來選擇模式,而不需要硬件支持兩套完全不同的定時(shí)與計(jì)數(shù)邏輯,簡化了定時(shí)器模塊的設(shè)計(jì)。

接下來說這個(gè)設(shè)計(jì)上面的簡便性,這個(gè)就比較深?yuàn)W了,之后我如果把玩FPGA我會(huì)寫詳細(xì)的。

如果SysTick定時(shí)器僅支持遞增模式或遞減模式中的一種,則其硬件結(jié)構(gòu)可以簡單設(shè)計(jì)為:

- 24位計(jì)數(shù)器寄存器

- 24位重載寄存器

- 比較邏輯,比較計(jì)數(shù)器與重載寄存器,產(chǎn)生溢出事件

但是,為了支持兩種模式,SysTick定時(shí)器的硬件結(jié)構(gòu)可以設(shè)計(jì)為:

- 24位計(jì)數(shù)器寄存器

- 24位重載寄存器

- 1位遞增/遞減模式選擇位

- 比較邏輯,當(dāng)模式選擇位選擇遞增模式時(shí),比較計(jì)數(shù)器與重載寄存,當(dāng)選擇遞減模式時(shí), 比較計(jì)數(shù)器與0,以產(chǎn)生溢出事件。

可以看到,僅添加一個(gè)1位的模式選擇邏輯,SysTick定時(shí)器就可以支持兩種模式,而不需要實(shí)現(xiàn)兩套完全獨(dú)立的計(jì)數(shù)/比較邏輯。在軟件層面,我們只需要設(shè)置MODE位為0選擇遞增模式,設(shè)置為1選擇遞減模式,然后處理溢出事件中斷即可。

硬件層面已經(jīng)為兩種模式實(shí)現(xiàn)了統(tǒng)一的定時(shí)邏輯。可以想象,如果定時(shí)器需要同時(shí)支持4種或更多種模式,僅靠硬件實(shí)現(xiàn)各自獨(dú)立的定時(shí)機(jī)制會(huì)變得非常復(fù)雜。

而采用類似SysTick的方式,通過軟件配置選擇定時(shí)模式,硬件只需實(shí)現(xiàn)一套相對(duì)通用的定時(shí)機(jī)制,這無疑可以大大簡化定時(shí)器模塊的設(shè)計(jì)。

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

    關(guān)注

    31

    文章

    5294

    瀏覽量

    119816
  • Cortex
    +關(guān)注

    關(guān)注

    2

    文章

    202

    瀏覽量

    46415
  • CM3
    CM3
    +關(guān)注

    關(guān)注

    0

    文章

    5

    瀏覽量

    1645

原文標(biāo)題:Cortex-M3精通之路-2(CMSIS核心結(jié)構(gòu))?

文章出處:【微信號(hào):TT1827652464,微信公眾號(hào):云深之無跡】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    為什么說Cortex-M是低功耗應(yīng)用的首選

    雖然Cortex-M處理家族目標(biāo)瞄準(zhǔn)效能光譜較低端的區(qū)域,但是和大多數(shù)微控制(MCU)采用的其他典型處理相比,Cortex-M的效能依
    發(fā)表于 07-28 09:44 ?3453次閱讀
    為什么說<b class='flag-5'>Cortex-M</b>是低功耗應(yīng)用的首選

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

    Cortex-M處理家族的編程模型是高度一致的。例如所有的Crotex-M處理都支持R0到R15,PSR, CONTROL 和 PRIMASK。兩個(gè)特殊的
    發(fā)表于 10-22 08:16

    Cortex-M 系列處理特點(diǎn)和區(qū)別詳解

    。接受中斷時(shí),處理會(huì)從該矢量表中提取地址。為了減少門數(shù)并增強(qiáng)系統(tǒng)靈活性,Cortex-M 處理器使用一個(gè)基于堆棧的異常模型。出現(xiàn)異常時(shí),系統(tǒng)會(huì)將關(guān)鍵通用寄存器推送到堆棧上。完成入棧和指令提取后,將執(zhí)行
    發(fā)表于 01-14 10:13

    Cortex-M系列MCU錯(cuò)誤追蹤庫有何作用

    @2019-02-14【小記】  CmBacktrace: ARM Cortex-M 系列 MCU 錯(cuò)誤追蹤庫,用來將單片機(jī)故障狀態(tài)寄存器值翻譯出來輸出至終端上以便排錯(cuò)CmBacktrace: ARM Cortex-M 系列 M
    發(fā)表于 01-25 06:39

    如何利用C語言的操作去實(shí)現(xiàn)對(duì)寄存器每一的控制

    在單片機(jī)的編程中,會(huì)使用到一些IC里面的寄存器,而有些寄存器并不是每一都是有效的,例如:這里的1-3則是保留的,不可以***作的。所以在對(duì)一些
    發(fā)表于 02-25 06:41

    如何使用Ozone分析Cortex-M故障?

    Cortex-M UsageFault 異常。UFSR寄存器提供已發(fā)生的UsageFault 異常; INVSTATE被置,表示在無效的 CPU 狀態(tài)下執(zhí)行指令。USGFAULTENA 表示已啟用
    發(fā)表于 09-23 11:26

    32寄存器,32寄存器是什么意思

    32寄存器,32寄存器是什么意思  從X8086開始學(xué)了一年,第一個(gè)ASM的程序就是變32換16進(jìn)制的程序,不過現(xiàn)在叫我從新開始寫ASM程
    發(fā)表于 03-08 17:26 ?1.7w次閱讀

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

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

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

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

    Cortex-M3 內(nèi)部寄存器

    寄存器組R0-R12R0-R12,通用寄存器;R0-R12都是32通用寄存器,用于數(shù)據(jù)操作;但是絕大多數(shù)16Thumb指令只能訪問R0-
    發(fā)表于 11-26 16:21 ?39次下載
    <b class='flag-5'>Cortex-M</b>3 內(nèi)部<b class='flag-5'>寄存器</b>

    Cortex-M3寄存器等基礎(chǔ)知識(shí)

    Cortex-M3擁有R0~R15通用寄存器和一些特殊功能寄存器。R0~R12這些通用寄存器,復(fù)位初始值都是不可預(yù)料的。
    發(fā)表于 02-08 16:28 ?2次下載
    <b class='flag-5'>Cortex-M</b>3<b class='flag-5'>寄存器</b>等基礎(chǔ)知識(shí)

    基于32Arm Cortex-M內(nèi)核N32系列MCU應(yīng)用

    國民技術(shù)N32系列MCU產(chǎn)品基于32Arm Cortex-M內(nèi)核,內(nèi)置嵌入式高速閃存、低功耗電源管理,集成數(shù)?;旌想娐罚?nèi)置硬件密碼算法加速引擎以及安全單元。
    發(fā)表于 03-28 11:35 ?824次閱讀

    深入理解Cortex-M內(nèi)存管理(Keil)

    在討論Cortex-M的內(nèi)存之前,先來看看Cortex-M的存儲(chǔ)系統(tǒng),我們知道,Cortex-M系列的處理,大都可以對(duì)32的存儲(chǔ)
    的頭像 發(fā)表于 04-27 10:41 ?4973次閱讀
    深入理解<b class='flag-5'>Cortex-M</b>內(nèi)存管理(Keil)

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

    在討論Cortex-M的內(nèi)存之前,先來看看Cortex-M的存儲(chǔ)系統(tǒng),我們知道,Cortex-M系列的處理,大都可以對(duì)32的存儲(chǔ)
    的頭像 發(fā)表于 04-27 10:58 ?2784次閱讀
    深入理解<b class='flag-5'>Cortex-M</b>內(nèi)存管理(GCC)

    Cortex-M帶操作的原理

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