Internet of Things|cortex-M シリーズ CPU のコアを探る|ストレージ システム|割り込みと例外処理|リセットとリセットのタイミング|Cortex-M シリーズ CPU で遊ぶ基礎ゼロの Internet of Things 開発シリーズ コース - 学習ノート (4)

第2段階~理論的根拠~cortex-MシリーズCPUのコアを探る

参考:Cortex-M3 Definitive Guide 中国語版

Cortex-M アーキテクチャ CPU コア ストレージ システム

記憶単位は1バイト、1バイト=8ビット

ストレージシステムの特徴

1 ストレージシステムの主な特長

4GB のリニア アドレス空間
B=byte bbit: bit 1byte=8bit
ARM 社が提供する定義済みのメモリ マップ。チップ メーカーは、
ビッグ エンディアン モードとリトル エンディアン モードをサポートするよう改良しています (両方とも設定可能で、デフォルト モードは次のとおりです: 必須データシート)
ビットバンド アクセスをサポート (オプション) 領域制限があり、直接 AND または演算
メモリ保護ユニットをサポート (オプション) CPU メーカーは、不正な読み取りおよび書き込み操作を防止するために、それを含めるかどうかを規定します
非整列送信をサポートします

ヒント 1: 4GB アドレス空間の起源

32 ビット ストレージ システム、32 個の 0 または 32 個の 1。
電卓は最初に 32 個の 1 を 2 進数で入力し、次にそれらを 10 進数表示に変換し、次に 1 を追加して (アドレス空間がアドレス 0 から始まるため)、バイトの合計サイズを示します
ここに画像の説明を挿入
ここに画像の説明を挿入
。 1024をまずKBにして1024を割って4096MBになり1024を割って4GBになるか、
2の32乗で1024を3割する。ここに画像の説明を挿入

Tip2: ビッグエンディアンモードとリトルエンディアンモードについて

ビッグエンディアン モード: 上位バイトはメモリの下位アドレスに格納され、下位バイトはメモリの上位アドレスに格納されます; 文字列として、アドレスは小さなものから大きなものへと増加します. リトルエンディアン モード
:ビッグエンディアンの反対。アドレスの上位ビットと下位ビットは、データの上位ビットと下位ビットに一致します。人の論理的な考え方に近い。
例: 0X1234
上位および下位の
ビッグ エンディアン 0x12 0x34
リトル エンディアン 0x34 0x12元のここに画像の説明を挿入
記事への参照リンク
. 一般的なアーム チップは、デフォルトでリトル エンディアン ストレージ モードを使用します. CM3 の場合、REV/REVH およびその他の関連する命令を使用してリバースすることができますエンディアン モードを完了するためのバイト オーダー。
注: CM3 では、ストレージ モードはリセット時に決定され、実行時に変更することはできません。また、命令のプリフェッチでは常にリトル エンディアン モードが使用され、構成制御ストレージ スペースへのアクセスでは常にリトル エンディアン モード (NVIC、FPB などを含む) が使用されます。また、外部専用バスアドレス領域 0xE0000000 ~ 0xE00FFFFF は、常にリトル エンディアン モードを使用します。

STM32のサイズとサイズをテストする

int a = 0x12345678;
int i;
char b[4];
int main(void)
{
	for (i = 0; i < 4; i++){
		b[i] = *((char*)&a + i);
	}
}

▲ ポインタを使用して、STM32 がスモール エンディアン ストレージであることを確認する
したがって、STM32 はデフォルトでスモール エンディアン ストレージを使用します。

もちろん、共用体を使用してテストすることもできます。

union B_t{
	char b[4];
	int a;
};
union B_t B;
int main(void)
{
	B.a = 0x12345678;
}

Tip1: Cortex-MアーキテクチャCPUの割り込みとARM7アーキテクチャの割り込みの違い

FIQ 高速割り込み Cortex-M 12 ティック
IRQ 共通割り込み ARM72 種類が持つ

ヒント 2: 整列転送と非整列転送

ARM9、10 はアラインされた転送である必要があり、
coretx_m3、m4 はアラインされていない転送をサポートし、単一のデータ、複数のデータ、ビット ストリップ、スタックなどに限定されます
アラインされていないコードは非効率的です。
後で使用するために、位置合わせして配置してみてください。

ストレージ システムのマップ

ストレージ システム マップの簡単な分析

ここに画像の説明を挿入
ここに画像の説明を挿入
内部プライベート ペリフェラル バスを含むプライベート ペリフェラル
0xFFFFFFFF
ビルトイン割り込みコントローラ
(NVIC) およびデバッグ
コンポーネント
OxEO000000
OXDFFFFFFF
主に外部外部
ペリフェラルに使用
OxA0000000OxSFFFFFF
主に外部外部メモリ
メモリに使用
Ox60000000
主にペリフェラルに使用 オンチップ ペリフェラル
Ox5FFFFFF0x40000000
主に使用データ メモリ
0x3FFFFFFF
(例: スタティック RAM)
Ox20000000
主にプログラム
0x1FFFFFF
コードに使用。例外
ベクタ テーブルにも使用
Ox00000000

スタック ストレージ モデル


1 スタックとは:プログラミング モデルにおけるLIFO モード (後入れ先出し) スタックの機能
(1) 関数呼び出し
(2) 割り込みおよび例外処理
(3) ローカル変数の保存
2 でのスタックの実装Cortex-M アーキテクチャ
が下位 成長するスタックがいっぱい システムが起動すると、スタック ポインタはシステム スタックの最後にある セグメントが入力されるたびに、SP コンテンツ -4 (スタック アライメント) が実行され、スタック操作は+4で、すべてのポジションが使用できます。
3 MDK-ARM5.13のシミュレーションデモ

Cortex-M アーキテクチャ CPU コアの割り込みおよび例外処理

☆割り込みと例外の考え方
1 例外と割り込みとは?
現在正常に動作しているプログラムの流れを変える事象で、プロセッサが現在のタスクを中断し、例外ハンドラを実行する.
割り込みが特殊な例外の場合、
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
2 割り込みの種類3
共通の割り込み要因
I/O 割り込み、タイマー割り込み、ソフトウェア割り込み…
☆例外処理の流れ
例外が処理条件を満たしているかどうかの判定
MCU の動作状態、
例外 EN (イネーブル) NMI、HardFault 常に
PR ハイの応答処理シーケンスをイネーブル
非マスク例外プッシュ操作: PSR、PC、LR、L12、R0-R13フェッチ ベクタ (例外ベクタ テーブル)更新レジスタ SP、PSR、PC 、LR例外処理 ハンドル:異常復帰処理を処理するシーケンス:スタック操作、NVIC





Tip1: 割り込みベクタテーブル

各例外ハンドラの開始アドレスを格納する配列。使用するたびに、NVIC はこの値を 0 に更新します。

典型的な割り込みベクタ テーブル:
ここに画像の説明を挿入
ここに画像の説明を挿入
最後のビットが 1 であることを観察します, これはサブ状態にあることを意味するので, 最後のビットは 1 に設定されます (最下位ビット LSB). 初期アドレスは MSP に格納されます (メインの初期
値スタックポインタ)
☆NVIC 紹介 (割り込みコントローラ) 1 NVICネスト割り込みベクタコントローラ
とは:機能: 優先度の設定、有効化、マスク、サスペンドネスト: 割り込み条件をトリガして、別の割り込みベクタをトリガできます: 割り込み/異常ローディングのサポート内部テーブル エントリ2 NVIC の機能柔軟な割り込みおよび例外管理ネストされた割り込み/例外のサポート内部テーブル エントリへの割り込み/異常ロードのサポート







Tip1: 割り込みをマスクできるコア特殊レジスタ群


PRIMASK 1 ビット、1 を設定、すべてのマスク可能な例外を
閉じます。NMI のみ、HardFault を閉じることはできません閉じて、数字が大きいほどレベルが低くなります。

Cortex-M アーキテクチャの CPU リセットとリセットのタイミング

☆3つのリセット方法
リセットには遅延があり、主にクロックソースがリセットして安定するまでの時間を待ちます。メーカーやCPUは異なります1.パワー
オンリセット
2.システムリセット(デバッグコンポーネントをリセットしないでください)
3.プロセッサのリセット (デバッグ コンポーネントとペリフェラルはリセットされません)
☆リセットのタイミングの説明
ここに画像の説明を挿入

リセット状態を抜けた後、CM3 が最初に行うことは、次の 2 つの 32 ビット整数値を読み取ることです。 アドレス ox0000,0000 から MSP の初期値を取得します。
アドレス ox0000,0004 から PC の初期値を取得します。この値はリセット ベクターで、LSB は 1 でなければなりません。次に、この値に対応するアドレスから値を取得します。

ヒント 1: 例外がメイン スタック ポインターを内部テーブルの開始位置 (つまり、アドレス 0) に格納する理由

これは従来の ARM アーキテクチャとは異なることに注意してください。実際、他のほとんどの MCU とは異なります。従来の ARM アーキテクチャでは、常にアドレス 0 から最初の命令が実行されます。それらのアドレス 0 は常にジャンプ命令です。CM3 では、MSP の初期値がアドレス 0 で提供され、その後にベクター テーブルが続きます (ベクター テーブルは将来、他の場所に移動できます - 注釈)。ベクタテーブルの値はジャンプ命令ではなく32ビットアドレスです。ベクタ テーブルの最初のエントリは、リセット後に実行する必要がある最初の命令を指します。
CM3 は下方向に成長するフル スタックを使用するため、MSP の初期値はスタック メモリの最後のアドレス + 1 でなければなりません。たとえば、スタック領域が 0x20007C00 ~ 0x20007FFF の場合、MSP の初期値は 0x20008000 でなければなりません。
ベクタ テーブルは、MSP の初期値、つまり 2 番目のエントリに従います。CM3 は Thumb 状態で実行されるため、ベクタ テーブルの各値は LSB を 1 (つまり、奇数) に設定する必要があることに注意してください。このため、図 3.18 でアドレス 0x100 を表すために 0x101 が使用されています。0x100 の命令が実行されると、プログラムの実行が正式に開始されます。最初の命令が実行される前に NMI またはその他の障害が発生する可能性があるため、この前に MSP を初期化する必要があります。MSP が初期化された後、スタックはサービス ルーチン用に準備されます。
開発ツールが異なれば、MSP の初期値とリセット ベクトルを設定するために異なる形式を使用する必要があります。開発ツール自体によって計算および生成されるものもあります。詳細を知りたい場合は、開発ツールが提供するサンプル プロジェクトの 1 つを参照するのが最も簡単な方法です。この本の第 10 章と第 20 章では ARM が提供する開発ツールを紹介し、第 19 章では GCC ツール チェーンを紹介します。
☆スタートアップコードの説明
1.スタートアップコードの主な機能 スタック
空間の定義 割り込みベクタテーブルの
格納
リセット割り込み関数(Reset_Handler);
その他の割り込み例外サービス関数とweak[WEAK]文;weak文、ユーザー定義の場合、ユーザー定義を入力し、プログラムのクラッシュを防ぎます。
スタック アドレスをライブラリ関数に渡し、ライブラリ関数を使用してスタックを初期化し、ライブラリ関数自体を初期化します。
ヒント 1: スタートアップ コードを記述せずに以前の 8 ビットおよび 16 ビット MCU を使用する理由
2. ST が提供する Cortex-M4 スタートアップ コードの簡単な分析
以前のプロジェクトを開いて、次を開きます: F:\IOT\PRJ\first_prj\ RTE\Device \STM32F407ZGTx\startup_stm32f407xx.s
の最初の行の有効なコードは次のとおりです: Heap_Size EQU 0x00000200
カーソルを EQU に移動し、F1 を押してコメントを開きます:
ここに画像の説明を挿入
AREA STACK, NOINIT, READWRITE, ALIGN=3; ここで 3 は 2 です3 乗、8 バイト アライン、

Stack_Size      EQU     0x00000400

                AREA    STACK, NOINIT, READWRITE, ALIGN=3   ;这里的3是2的3次方,8字节对齐,
Stack_Mem       SPACE   Stack_Size ;定义我们的0x00000400大小的存储块,值均为0
__initial_sp  ;标号,指示当前堆栈的初始位置
具体地址见工程下的map文件:F:\IOT\PRJ\first_prj\Listings\first_prj.map
    __initial_sp                             0x20000670   Data           0  startup_stm32f407xx.o(STACK)
这个是最高地址,向下压栈。
; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Heap_Size       EQU     0x00000200

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3  ;定义堆空间
__heap_base
Heap_Mem        SPACE   Heap_Size  ;定义堆空间大小为 0x00000200
__heap_limit

                PRESERVE8 ;指示当前堆栈是8字节对齐
                THUMB ;告诉汇编器以下均为32位的THUMB指令


; Vector Table Mapped to Address 0 at Reset   向量表映射
                AREA    RESET, DATA, READONLY  ;定义复位向量段
                EXPORT  __Vectors  ;导出后,其他部位也能使用此全局标号
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size

__Vectors       DCD     __initial_sp               ; Top of Stack 分配4字节32位地址
                DCD     Reset_Handler              ; Reset Handler
                DCD     NMI_Handler                ; NMI Handler
                DCD     HardFault_Handler          ; Hard Fault Handler
                DCD     MemManage_Handler          ; MPU Fault Handler
                DCD     BusFault_Handler           ; Bus Fault Handler
                DCD     UsageFault_Handler         ; Usage Fault Handler

; 取引をリセットする

Reset_Handler    PROC ;标记函数的开始
                 EXPORT  Reset_Handler             [WEAK] ;弱声明
        IMPORT  SystemInit	;从其他文件导入.\first_prj\RTE\Device\STM32F407ZGTx\system_stm32f4xx.c
        IMPORT  __main ;从其他文件导入

                 LDR     R0, =SystemInit ; 函数入口地址加入到R0, =把入口地址传给R0
				 ;MOV	 R1,PC
                 BLX     R0  ; 地址0x080002D1后面的1代表是sub状态
                 LDR     R0, =__main
                 BX      R0
                 ENDP ;函数结束

; Dummy Exception Handlers (infinite loops which can be modified)

NMI_Handler     PROC
                EXPORT  NMI_Handler                [WEAK]
                B       .  ;死循环
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler          [WEAK]
                B       .
                ENDP

;**************************************************** *** ****************************
; ユーザースタックとヒープの初期化 ユーザースタックの初期化
;******** ** ************************************************ ***** ********************
ここに画像の説明を挿入

                 IF      :DEF:__MICROLIB   ;如果勾选了,就会执行

                 EXPORT  __initial_sp
                 EXPORT  __heap_base
                 EXPORT  __heap_limit

                 ELSE

                 IMPORT  __use_two_region_memory   ;未勾选执行此部分,使用双堆栈
                 EXPORT  __user_initial_stackheap

__user_initial_stackheap

                 LDR     R0, =  Heap_Mem
                 LDR     R1, =(Stack_Mem + Stack_Size)
                 LDR     R2, = (Heap_Mem +  Heap_Size)
                 LDR     R3, = Stack_Mem
                 BX      LR

                 ALIGN

                 ENDIF

                 END

デモコード

リセット後、まずスタック ポインタ sp を 0x20000670 にポイントします。ここに画像の説明を挿入

ここに画像の説明を挿入
実際に実行されると、リセット ハンドラーに入り、前のハンドラーは CPU によって自動的に完了されます。つまり、
ここに画像の説明を挿入
シングル ステップの実行、エントリ アドレスの取得、および SystemInit へのジャンプです。ここに画像の説明を挿入

ここに画像の説明を挿入

ジャンプしてメイン関数に入ります。
ここに画像の説明を挿入

参考書:

Cortex M3 and M4 Authoritative Guide.pdf 2014
Protel Schematic.pdfls 2009
STM32F4xx English Reference Manual.pdf 2014
STM32F4xx Chinese Reference Manual.pdf 2014
STM32F407ZGT6.pdf 2014

宿題: STM32F031C8 コア原理テストと起動コード分析

おすすめ

転載: blog.csdn.net/Medlar_CN/article/details/130530133