你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】stm32和cortex M3学习内核简单总结

[复制链接]
STMCU小助手 发布时间:2022-2-9 21:52
Stm32综述
这可以说是我第一款认真学习的单片机了,学完这个就要开启我通往arm9的大门了,接下来把我学到的东西做一个系统的概述:

6 b6 m/ K8 }( p7 G7 L
842584-20160308203600538-146886588.jpg
% y' a1 [9 s+ G! B" H1 B4 `7 s* g
上图是stm32的系统结构。
' a# i. H7 b+ n' _8 Q  |
使用哈弗体系结构,取指和取数据分离,

+ z4 T6 R. \- J$ b
ICODE指令总线连接到flash闪存指令存储区,这个存储区的地址在0x00000000-0x1FFFFFFF之间,负责取指操作。
, k+ [& J& y4 v9 p8 z- o* n6 M; C
DCODE数据总线负责在0x00000000-0x1FFFFFFF之间的数据访问操作。这个数据存储区可以是SPRAM也可以是闪存和外设。

5 [' G; r9 F# L/ W
系统总线:负责在0x20000000-0xDFFFFFFF和0xE0100000-0xFFFFFFFF之间所有的数据传送。

4 E7 t$ I; ?" q2 \
注:看到这你可能会迷惑,M3内核不是只有指令总线和数据总线吗?对的,但是指令总线和ICODE指令总线不是一个,选取一张M3内核样例处理器的图就明白了:

; W# _7 i2 ~" S6 t6 \5 l
842584-20160308203603975-767604832.jpg
8 l2 f9 h8 }0 X7 N+ j/ y8 l. ~8 N+ s
个人理解,D-code总线和系统总线都是来源于M3内核引出的数据总线。
* t2 w7 w" J; \
DMA通过总线矩阵直接和内存相连。

# j) p7 O2 i( P! D" C1 n- r6 U3 S8 e. K; p
总线矩阵协调内核和DMA对SPRAM,闪存,外设的访问。

2 J$ z% K; R, m' m! G
AHP总线桥接两个APB总线,两个APB总显得最高速度不同,APB1最高速度限于36MHz,APB2限于72MHz。两个APB总线上挂接着不同速率的设备。
" i  Z3 h1 T/ K1 l
Stm32f10系列的静态SPRAM为64K,起始地址为0x20000000.

7 Z5 a/ ~, g4 z, y# |/ [( J6 j% S; \+ {, T
# d3 L2 i8 b; ^/ e5 z

9 {& U) o! A8 [# T$ n' i$ q7 b! |; r0 `9 L3 f
Stm32的启动方式有以下几种:

& J/ d% e8 B0 ^4 U% J" O
842584-20160308203606647-820585976.jpg

# u' }3 r- \( C% k

3 j/ B# m% h# o' J! `  Y) N1 C, A) e) K

9 J: ~1 h% M: T. S
& U5 O0 l/ w/ F4 G7 G' G- n
% u  \4 b0 e( N( o' q$ W
7 u% Q9 x6 T, U2 Y
& C; @* m" f6 U, s7 i5 S( f( l4 `. U& U6 o0 @

, _1 y' @, T6 h. _9 ?$ X0 S8 x- @& ]  Z8 R5 C" e: P9 x7 }& K3 e
下面的是stm32的时钟树,stm32有四个不同的时钟源:
1.HSE时钟:高速外部时钟信号,来自于外部晶振:可作为系统时钟源,也可被PLL倍频之后宫系统时钟使用。
2.HSI时钟:高速内部时钟信号,来自于内部RC振荡器:可直接作为系统时钟,或者二分频之后作为PLL输入,倍频之后供系统使用。
3.LSE时钟:低速外部时钟,来自于外部晶振:为定时时钟或者其他定时功能提供
4.LSI时钟:低速内部时钟,来自于内部RC振荡器:在停机或者待机的模式下,为独立看门狗或者自动唤醒单元提供时钟。

( j7 b- V+ A- @. n8 A& B
1 L" i3 F! V8 M* z
经过一些列倍频,分频得到了几个和开发有关的时钟:
1.SYSCLK:系统时钟大部分时钟的来源
2.HCLK:由AHB预分频器输出得到,高速总线AHB的时钟信号
3.FCLK:由AHB预分频器输出得到,自由运行时钟。
4.PCLK1:外设时钟,由APB1预分频器得到,最大36MHz
5.PCLK2:外设时钟,由APB2预分频器得到,最大72MHz
时钟树如下:

( u4 j( a0 M9 R" E; \. A2 Z
842584-20160308203612960-2102733665.jpg

# @0 x  i1 t; s# Z& v

6 u3 V" x1 Y2 M0 p) }
4 F+ h" E# f( s5 w8 A" I9 _6 v& Q4 c
* @3 ^% }, Y3 r8 b* L2 \
+ [2 u8 D6 _/ p. s
1 k! e+ s3 {9 O- g
Stm32的GPIO的8种模式:
(1)GPIO_Mode_AIN 模拟输入
% R3 S1 |5 c. k/ Y' h, e(2)GPIO_Mode_IN_FLOATING 浮空输入
! s! O3 P: U9 s(3)GPIO_Mode_IPD 下拉输入
) {: }$ p- [, `/ s: n! C(4)GPIO_Mode_IPU 上拉输入 # T1 `+ m% s: R# X  S) o
(5)GPIO_Mode_Out_OD 开漏输出- p9 c( o8 \8 e% Y: i' n
(6)GPIO_Mode_Out_PP 推挽输出- N$ c- Z/ K, U5 `
(7)GPIO_Mode_AF_OD 复用开漏输出 1 Y2 X& z( T1 K7 q* N6 M+ H
(8)GPIO_Mode_AF_PP 复用推挽输出
5 A  z: d2 s8 Y% ?& [: q$ D( @
4种输入:模拟输入和明显接受模拟信号,比如用于ADC,上拉输入和下拉输入就是默认时高电平和低电平。浮空输入在芯片内部既没有接上拉电阻也没有接下拉电阻,引脚电压是个不确定值,输入阻抗较大,常用语I2c,USART。

0 F- {, ?, f" ^. G* L! U" i
4种输出:分复用和非复用,复用为分配给片上外设,非复用为用作正常的IO口。推免输出为正常的输出,而在开漏输出模式,IO口可以由外部电路改变为低电平或不变。所以开漏模式可以读IO输入电平变化,实现C51的IO双向功能。

$ [" I5 B% g* C7 S& E
* F# [; `  c+ E; l' h+ J
7 p7 k9 s" W% M
6 t1 f" M( s& o! V4 B: w
" ~% T1 x7 E( B) K( ]/ l6 d* d. ~( q9 P2 ^: v7 S$ D; y  y, K0 b

7 J. \* |4 ~- {2 \+ [+ D6 M' F; F' [& [7 a; j+ o* e
; `. u  z7 d6 ^  E

$ J: t/ t& S" `# M6 }3 w7 k% g% k) j* L; ^0 j0 i& i6 }9 X

& \: |6 ?/ x) w, f5 O& ~! e
! E0 D3 \, s, @7 r$ c. j  I: f
! G, B3 }7 z. e- D' }$ Y- U7 {
1 p5 b* I" g' N) }5 i. D9 B
$ ]5 r/ C" V8 I8 |4 ~$ b% e* }+ A; r. ^4 j
8 r+ [4 M! X, d# O3 \! t, w
2 W$ T/ A* [5 }* D5 e' [! r3 z6 Y

: ]1 u+ R0 w3 p* R
* D& t! G& C3 y$ w$ r) e
& P- m: `) q& |  c0 I0 O" i( o
# u+ e" Y4 r) z+ n" p2 w4 q3 U3 R% ^9 {
当年看不懂的东西,现在越发清晰。
, J$ |& ]" L4 H% ]$ Z- T- w

* C) K5 A* P- Z9 K- k, K/ Q3 p寄存器组
这一部分就属于M3内核中的知识了。
M3内核中的寄存器主要如下:

) C( W1 U) s' F) P5 Z
842584-20160308203617757-828635669.jpg

# ]( a% g5 k/ D
842584-20160308203621522-2107100479.jpg
  I  h& A5 m4 ~6 J8 p; b' R% e
下面挨个解释

& P$ t; }+ H8 s6 |; I0 h! l
842584-20160308203623929-995530750.jpg

" l3 G% S* R& f
842584-20160308203643897-1571275885.jpg
) M% ]0 I0 {  u8 W
842584-20160308203645850-58036291.jpg
! I% M/ |& {# n* ]4 {# A( [
  n& C* A1 a. v: @
M3使用的是双堆栈,复位之后默认使用MSP,默认是特权级,如果想要切换需要手动修改。而上面的MSP和PSP的用途只是一种推荐用途,并不是一定要那么用,比如说复位之后你可以不修改,那么你的常规代码就一直是特权级,使用MSP(我就是这样滴。。方便至上)。

0 h. u: l5 L! y1 b
842584-20160308203646897-302961918.jpg
; [. N( m* ^0 k; n
      这个寄存器又叫LR寄存器,那么当函数是一级调用的时候,就可以将返回地址直接存到LR中,省去了访问内存,提高了效率,当函数调用高于一级,则需将前面的LR中的值压栈,以便存储新的值。

& w$ g, E9 u8 \0 ]( l+ h; T
      当进入异常的时候,LR寄存器的值更新为特殊的EXE_RETURN:
      
842584-20160308203700319-812289253.jpg   

8 {. `* J! H+ v2 U
842584-20160308203702288-2133184213.jpg
) m: v5 n* V4 N# ~
842584-20160308203704272-329667468.jpg

1 R' _; ]: I% d( d: t
842584-20160308203705319-1090289122.jpg

) \) o6 L. Q' a; A. y
就是PC嘛。。。。

9 n9 U" B  x3 x% S8 Z* F" G3 v
842584-20160308203706975-1238474005.jpg
      

# p6 ]& x* M$ R# U

0 D# l- A9 m* n- j0 h; E
     特殊功能寄存器一定要在特权级才能被访问(使用MSR和MRS指令),至于是Thread    模式还是handler模式无所谓。
     详细功能如下:
8 f! R2 m: K" n7 v  z. o( \; ]
842584-20160308203709460-1683866030.jpg
! y% C, ^  q. b: @8 L8 S; ?, g. ~5 g
    xPSR属于三合一寄存器,可以分出三个子状态寄存器
7 Z+ Q$ H3 m' n
842584-20160308203710022-1723143888.jpg
$ \! d0 J" o! p
    通过MRS和MSR这三个寄存器可以单独访问,也可以两两组合访问,也可以三合一访问,这个寄存器大致如下(看下就好):

( Q; I& [+ H- b+ w( A
842584-20160308203711335-412320091.jpg
( l# S# H9 }% ?

5 j9 k( h) s& t& m1 \. v4 ~2 m$ B6 y! S/ n6 S2 V9 t% J3 ?
    其实除了修改上面的寄存器可以开关中断,M3还有专门的开关中断指令:
+ f" x4 t+ e* e" k( q
842584-20160308203712804-1286990269.jpg

# i' I% @6 J& ?4 F

' G7 ~. P3 f  O5 _! ^3 o4 e* E2 J1 Z% E7 W4 k$ \
  ?: G9 |# }3 J, q7 ^* P) ^
    CONTROL寄存器功能如下:

" y# X! k! W" |9 ~0 i2 A
842584-20160308203715163-502120058.jpg
9 u& ?3 o7 S1 _( w' f

" l0 _  X. l0 ]0 D4 ]
9 t' E% V2 r- R0 {! Z" j( ^# W7 w
. T- X% o1 t! m4 u! Q5 [
! ^! f- j5 n3 o- B

/ M' r8 C' q2 v& B9 ~: K6 K, C2 w2 C4 V& \4 H

. O9 c1 }! N7 u+ S8 G( g
3 g2 G+ o( v* g3 b3 g; O; z) I) M4 V1 z# {
4 p% O& u- ^$ u3 k* N

; j! D  l+ Z& c& w/ s7 {+ t
2 q8 E) ?0 U0 ^
7 d2 W7 r4 R4 X2 @* r( B0 C5 S* U0 m" r8 x0 l- G4 y* x

! P- G2 |& L$ ~! |/ K$ d. o4 x$ A9 ^5 W
: Z* ^/ t2 z# g! H: D

* \  V8 F: e, s2 ~, O/ a' q3 H* L) I8 h% m
. j  O8 t; Q9 Q4 Q$ ?- c8 u
5 D- k0 c. e2 Q( y

) l- F; W8 [* [8 u' A* X
* [  {! [2 {, \2 M! m. e0 }  e  e. D6 h+ M3 {
! e* D% k' M6 I0 h
; R) J# |! O7 X% l- M
% P5 a! T0 B6 R, ^

3 {6 m# H0 j5 _0 s
' Y5 k& D, ^  L* O# I) g4 t/ N, l" `; R3 E- h+ @2 y# V& O
操作模式和特权等级
操作模式分为Thread模式和Handler模式,特权等级分为特权级和用户级。用户的程序代码一定是Thread模式,而异常一定是handler模式,用户程序代码程序代码可以是特权级和用户级,但是异常只能是特权级。
' H: a+ F/ M4 B. I
842584-20160308203716163-892187985.jpg

5 t7 l# P9 U' Q$ Q2 f
4 k5 s# ^0 G" o. P$ j
Thread模式+用户级,就不能访问系统控制空间(SCS)和特殊寄存器(除了APSR)。

( X: y; b" [( G) Z( F
特权级切换到用户级很容易,修改下control寄存器就好,用户级切换到特权级的方式只有触发一个异常,切换到handler模式,这个时候是特权级,然后修改control寄存器的零位,再返回就是特权级。

. C6 x# ?) I( j/ W
下图是一个各种切换的示意图:
7 t0 e* |. |( }4 q8 s
842584-20160308203717600-1039192697.jpg
) a9 w: P6 m9 Z, v% x$ s
2 E# O% A6 p( n, U$ u2 v# @7 m
这种设定的大致用意就是我们写普通代码的时候设置为用户级,这样的话可以防止对SCS和特殊寄存器这种敏感地带的误操作,想要访问这些的话就只能通过进入handler模式一步步去访问,而且这样的话异常是特权级用MSP,普通的用户代码使用户级用PSP,不会出现数据意外互相干扰和破坏,这样的话整个系统的可靠性就会很好,当然我们写小程序的时候不必这么拘谨,反正我一般都是一直特权级小程序。

: ^& ~1 {, R3 N+ R) A8 Y( Q3 x1 J) k1 @% h2 ]& N6 W+ D5 ]2 }

, |3 t% j. g. X/ N" G' D% \" a5 n+ x" S! t* q
  D8 P+ _/ N/ S  F& ~1 k/ [6 N

% @/ T. E9 U0 z0 G# f! t7 x8 _  D- [4 |

) O- Z( ~1 [' G7 o" W. s% G6 Y9 D2 y8 y6 M

: D8 {( a4 P% _2 L" X$ W存储器映射
      M3将内存分为8个主块,每块512MB,先上一张M3内核的存储器映射:
/ a; s0 {/ f) f0 v( g& \3 f
842584-20160308203721866-479801403.jpg
9 W: s% B. P! ?0 B) Z8 Z1 V
     所谓的SCS如下:
" V1 g: y1 [9 v2 b  x& a0 j
842584-20160308203724022-54566331.jpg
  g2 m0 t7 ?+ J+ }& t; b) w
. U% z' b& A0 s3 D4 r; m
$ f/ j+ M& Q- _3 g
     所谓的位带就是将位带区的1bit膨胀为位带别名区的32bit也就是一个字,通过访问位带别名区就能达到访问这个bit的目的,优势如下:

, K( h0 @; P+ @# `! l( ]
842584-20160308203726288-728254178.jpg
3 ~9 v$ f) L( W0 U$ ^1 P
     当然位带还有一个明显的好处,就是在多任务的系统中,两个任务同时去修改一个共享寄存器其中的两个bit的话可能会出现“紊乱现象”,所以就需要将“读-改-写”三条指令加上临界区等手段,但是有了位段,M3直接去写那个bit的位带别名区就可以了,这样就成为了一个原子操作。

. m2 h5 U$ d0 h) t$ T
     不过上面的图确实是粗线条,下面上芯片手册的详细图片一张:
6 `( M/ r' `- L
842584-20160308203736350-1162441161.jpg

" E, N) c, n8 ^: p3 }7 t: V

4 p) N1 O7 ~6 x/ n1 k% X/ }" ~1 X* `3 |' K8 i$ G" Q" ]) E6 l
   M3有些数据传送指令支持非对齐数据传送,如LDR/LDRH/LDRSH。其他指令不支持。
对按字传送来说,任何一个不能被4整除的地址都是非对齐的。而对于板子,任何一个不能被2整除的地址都是非对齐的。

( q; _- k- T9 }6 n" o$ z+ e, |$ L
   M3支持大端模式和小端模式,但是推荐使用小端模式。M3的大端模式是“字节不变大端”。

. Q& N8 D8 C! Z- b
5 e  p9 `0 b" c3 Q& Z7 h; Z7 w6 w( b& G) v; ~( o0 I
2 \! k- g1 Y  ]1 Z" X. _* N

& r3 t& }2 z7 e0 Z( g( s) k
$ o( B% H  _) c! M4 `$ C/ O) v
4 s& W8 ~6 {1 n9 B3 F2 C, v( }0 T
, X  B. `# R; X. g0 d# T4 C9 P0 }
! r4 o6 J9 o- q; a  O) l2 u! w( _  Q
5 A1 L5 d/ O5 q3 ]
; O  l: j1 f4 R4 v) L# w7 r

1 \# V# u; w7 N: d# d. n) ?. ^: O/ X  y2 g% X
- M1 i$ M  ~, C0 Z
$ c) w6 l2 [$ @

# ~. s( x! V+ x0 O3 X8 _* L4 [3 n7 `
4 p2 U2 n/ q, n8 k- v. I
7 u0 I0 _* x  D0 c0 I- S
6 t6 O5 ^: W$ k% }

( A/ v* O, s$ T" K) R1 U' ~9 v4 Y* D6 ~- L; R' x9 {

+ A+ G8 k/ @8 o- U3 ^
& ]5 v! u3 O: P
! Q+ l$ I! w6 U$ u$ z$ ?1 u( P" }4 G1 p0 {# U
6 h9 i' L1 V/ d: f/ w" L
7 Y: X8 \+ E! K9 _' V4 f2 g
6 x# e- F7 h7 V

8 {, o! I% _$ `% S3 z5 l/ L- s; H5 F4 g8 _$ B! h7 d
0 {  f$ ]; a. ^0 k$ J! ]# N8 @
8 \; B* R  Y* ?% R( _
4 ?5 B% @2 m* i
9 g/ o0 W  i( b8 T* }/ A
. R( ?4 B* u; f$ ]
7 J) v% B% \/ {/ C/ s

1 U7 \! ]. D- s( v2 W中断和异常
异常是指任何打断程序顺序执行的事件。在很多时候,中断和异常这两个概念是不做区分的,所以我以下也就不作区分了。
3 _# B. ]3 }3 p9 r' i+ x& l
M3的异常系统简直就是它的精华所在。
* n' ]2 i1 y9 c- a
M3的异常分为系统异常和外部中断。
系统异常如下(stm32沿用):
) |& S4 z# P, H- U- f% T* f
842584-20160308203741335-291544513.jpg
2 `3 l' k  |/ {3 {8 I
842584-20160308203743944-1399280562.jpg

9 \  E$ O5 s" ?3 @
外部中断M3内核支持240个,stm32只使用其中60个:
% t4 G( I. \; B3 }4 w. ]
842584-20160308203745350-80903858.jpg

! E8 F  C2 e, C  b5 p, U5 Z

5 y% \) P& U3 }$ e5 y' E
所有的异常,除了复位,NMI,硬FAULT优先级为-3,-2,-1固定,剩下的都是可编程优先级。

2 u# i  i/ V: |. f; d- k
" W0 g; `( S" w4 E
  b1 g3 u, H- D" B& }
优先级:
M3内核中优先级寄存器为8位,这8位不用全用到,最少用到3位(MSB对齐),stm32只用到其中高四位,所以stm32总共有16种优先级。
M3内核中对于外部中断有抢占优先级和响应优先级,高抢占优先级的中断可以打断低抢占优先级的中断。抢占优先级相同的两个中断同时到达,响应响应优先级高的中断。如果两个中断一切相同,那么响应序列号更小的那个。
因为外部中断的优先级寄存器总共八位,所以需要对其进行划分,响应优先级至少有一位,所以M3中外部中断抢占优先级最多其实是有128个而不是256个。下图是从bit5开始划分,总共用到三位设置优先级:
# M# I1 z# B/ L1 y: K' l7 @
842584-20160308203746585-2104768633.jpg

6 N5 `( V. R/ J  H! Q- N8 g4 z- G5 r; f

$ I* I+ b( U1 _/ r
具体的芯片决定优先级用到多少位,以及从哪一位开始划分抢占和响应,stm32用到4位设置中断,有5种分组:组0从7bit划分(全部都是响应优先级),组1从6bit划分,组2从5bit划分,组3从4bit划分,组4从3bit划分(就是只用到抢占优先级)。

" \# l& c6 v6 w) D' U
( E0 l, T2 T$ q0 D( I2 ~
向量表:
当发生了异常需要响应的时候,M3需要定位其服务例程的入口地址,这些入口地址就存在所谓的“向量表”。缺省情况下,这张表存在0地址处(当然也可修改NVIC中的向量表偏移寄存器来重定位向量表),每一个表项占4字节。
如下:

0 B! y! C5 Z1 W: D) _  H' C
842584-20160308203748538-1244447523.jpg
& ^; W$ X3 a* X- L& n8 v% w
9 I! a# q& N1 _- ~
首先向量表的开头是主堆栈的地址。
' F1 D$ O) ]. Q6 V- {( F
可以看出,不论如何一个向量表至少包含下面4个表项:
1.MSP初始值
2.复位向量
3.NMI
4.硬fault服务例程
2 |6 V" M( D. a. F8 s0 K
中断的输入与挂起:
当中断输入脚被置为有效后,该中断就被悬起,到了系统中它的优先级最高的时候,就会得到响应。
    但是当某个中断得到响应之前,其悬起位被清除,则中断被取消。(所以stm32都是在中断服务程序的最后清除中断标志位)
当某中断的服务例程开始执行的时候,就称此中断进入了“活跃”状态,并且其悬起位会被自动清除。  
5 h  M$ N% x. {4 z

  J* p" r6 f: E7 C* v! d6 p  {' E
SVC和PENDSVC:
首先SVC(系统服务调用)和PENDSVC(可挂起系统服务调用)的区别在于SVC异常必须立即得到相应,而PENDSVC则不是,他可以像普通中断一样被挂起,知道其他重要任务完成才执行它,挂起PENDSVC的方式为:手工写入NVIC的PENDSVC挂起寄存器。
SVC的用途:操作系统可以不让用户直接访问硬件,而是通过触发SVC异常来使用SVC系统调用来让用户程序简介访问硬件。好处:1.OS负责具体硬件,用户程序不必花费心思控制硬件。2.OS的代码应该是经过充分的测试的,所以整个系统可靠性高健壮性好。3.用户程序无需在特权级下执行,无需担忧因误操作让系统瘫痪。4.通过SVC机制,用户程序与硬件无关。

3 E' T$ q# ~0 F& `# j# _$ a4 |; V0 r
842584-20160308203750179-1918128768.jpg

( b2 {4 U; I# R1 V7 A7 i$ h
7 L* J" u1 |& [4 p& A: s- k( G
PENDSVC的用处:上下文切换,如ucos上下文切换就是用到PENDSVC的。

) `4 a( `( {3 ?3 q7 V5 Y
9 V5 |' `) {: ?* z2 D" Z2 n; v+ |' v; g1 A$ m2 S4 t0 q
NVIC:
中断向量控制器,也就是控制中断向量的地方,每个外部中断(系统中断由SCB控制)都在其中的寄存器占有一席之地,寄存器列表如下:
   
842584-20160308203751163-1669040342.jpg

5 l, m( \, H( I! g$ j+ x% A/ `/ x9 c1 d" H7 }: [  U* m
     其中悬起寄存器可以系统自动设置,也可以手工修改以悬起一个中断。
. K7 b7 c$ J+ a) ]5 z
     软件中断寄存器也蛮重要的,如下:
  I: b2 P8 y0 ]
842584-20160308203752913-1691985558.jpg

6 C, d2 d  D5 m% p/ x" j* W  k! l. n* B+ M0 I( |
4 X" {% X; ]; i. j7 m. ^

+ I$ J; R/ j9 |, `. u
9 i2 ?9 X- L# }2 @+ X: @- e9 j$ K
' i2 R$ R( E5 q+ v$ a$ d. d; w1 p6 R, a! e/ f. Q
中断的响应和返回:
     中断的响应:
9 I7 g9 q: ?5 v% [3 S( e& z% L9 {% x
842584-20160308203754100-2025311353.jpg
      
        8个寄存器以及入栈顺序如下:

' W) n; n; N/ w& z
842584-20160308203755960-1610934562.jpg    

* U. `+ Y" v( k: q. q6 a) ^" H
     中断的返回:
         首先触发中断返回的指令有三种:
         
842584-20160308203758647-880846930.jpg
3 H3 f) _( F. O' R# `
          返回了之后,做如下两件事:
          1.出栈,回复现场
          2.更新NVIC寄存器

* f# |4 c& }! H# m9 s; Y' t7 y- e  i0 `4 r# [: v/ i* v

* z. r& K+ q% W' \, E3 T; l% Q/ e. E
! J! m0 N) l( a3 t) D/ q8 `% I# ~
咬尾中断:
   一图以蔽之:

; I7 r2 Q9 m9 [- S* `
842584-20160308203759804-415386378.jpg
8 z) Y0 |" |$ F& T
其他
总结了一天,终于到了这一步,还有些零碎的知识点写上:
8 y  B& v8 C- r' Y! d8 ^- M
M3的堆栈是向下生长的。

6 X4 p' C0 ^6 \0 z9 S' W8 r
M3取指,解码,执行三级流水,因为其采用哈弗体结构,所以取指和访存可以同时执行,M3内部有解码模块,所以构成了三级流水。
5 k/ y% ]/ t3 Z* u' R
0 b% ]: z) j* c; }' A

  Q' e% H" |/ v1 z" |+ e0 |7 l7 H3 ^6 E8 I2 e1 [; e: ?4 Y* h
赞 收藏 评论0 发布时间:2022-2-9 21:52

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版