|
下面,我们看看关于NVIC寄存器的描述,都在哪些手册里面有提到 在使用STM32F10x standard peripheral library写有关于stm32中断的程序的时候,需要开启某个特定中断的控制位,除了对应外设的寄存器之外,还需要设置NVIC的相关寄存器的对应位。例如: - /****** STM32 specific Interrupt Numbers *********************************************************/
}8 T n1 \ a8 e# y# l - WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */: m4 e0 t* i7 `9 i
- PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */ i5 L; x: Q2 Z+ m/ E, b ]
- TAMPER_IRQn = 2, /*!< Tamper Interrupt */
6 j [; p7 J6 J' P& L - RTC_IRQn = 3, /*!< RTC global Interrupt */
+ w, |( {# n! y* } - FLASH_IRQn = 4, /*!< FLASH global Interrupt */' a7 p2 Q3 c& k% q% M
- RCC_IRQn = 5, /*!< RCC global Interrupt */
" S2 S$ {/ Y* I' }& T* [ - EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt *// K5 ]5 B6 n5 N+ i1 q; g* J
- EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */! Y. k: G4 s) D2 T# |
- EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */8 A; u+ c4 H: C) g) L1 o0 T
- EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */2 j t- e* u8 x: `$ u9 z& J: L# P
- EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt *// D8 V# b2 |$ S. X
- DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */
6 V. i2 W2 r& h. Q" A ~1 { - DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */5 K( ^+ s0 K6 S0 B' J/ }+ w: C
- DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */
; O9 q; }+ d) ~1 {6 u - DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */
6 C& y, A0 x* l5 \+ M+ I - DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */! J' ^1 }+ f' r/ b
- DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */+ L' f! T1 A% U& h
- DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */
# R" \5 i: H0 ?; j r. {) s& z$ r - ' c* \) X, y) O2 a, f
- NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;5 E9 s( }5 [2 o6 p, f! q/ G
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
4 S2 L3 n. z `6 ~ - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;% b/ n2 @$ s7 \% S/ t& n1 p) v# A
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
# k- Y; q7 m- N$ @ - NVIC_Init(&NVIC_InitStructure);
复制代码
7 p% O+ ]# G- E! v4 J而NVIC_Init()这个函数: - /**, Y8 X. q3 e, n
- * @brief Initializes the NVIC peripheral according to the specified& o; \0 p) m N# s# c) t2 ^
- * parameters in the NVIC_InitStruct.4 i* V S2 o7 ^& w: C
- * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains3 w- y! X3 k, _; G
- * the configuration information for the specified NVIC peripheral.. X. r9 s6 Z0 Q* W! E2 V
- * @retval None( K) @: J8 m/ |$ a( P
- */
& j0 l0 K0 ~+ k6 O& T - void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
2 U, i2 W. {( z" C" j" u( R - {
$ _. ^- u5 b( r( E3 w' b: _, S: _ - uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
" Q8 b. |* T" t - 0 N# l3 l' K4 Y* e1 U) K. D7 W
- /* Check the parameters */$ [! w! A& `0 s1 X& d. ~9 b3 I
- assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));/ q9 y& s/ F9 }
- assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));
6 ^# s( |4 \/ [/ ^% x3 T9 @( F/ v - assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
+ g* ^& b0 M( P4 M - " L' T3 L9 |4 G2 [
- if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)9 A0 F1 `$ @7 e% z0 i
- { {# P% x; j# Q9 ]2 k% Z, Z
- /* Compute the Corresponding IRQ Priority --------------------------------*/
! Y9 a2 o3 }$ A" Z { - tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
) l: g4 v8 d$ M- K A% R - tmppre = (0x4 - tmppriority);+ {# \- N; W. t& {! e8 {
- tmpsub = tmpsub >> tmppriority;4 x5 `0 `: E- x9 Z1 n8 D
- 2 h0 a1 @4 z3 _
- tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;) O& g$ I$ V3 Y2 P" j9 b
- tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
! z! d6 _+ E7 ~9 I: M - tmppriority = tmppriority << 0x04;6 s4 D2 O6 F" _/ ^# k( p( B4 o
-
Y* ?' h1 t( `: M% O8 Q. I7 n4 h" Q - NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
+ c* y/ M$ Q: t. J' G+ {$ s -
, u' s5 g* X: L3 W) A. _ - /* Enable the Selected IRQ Channels --------------------------------------*/9 l" D7 h$ x( [
- NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
" C. ^& O5 a1 ~6 v - (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);8 @0 v: J& `& _6 E) ~4 M6 e& X
- }. |4 C" P, a8 V+ W/ m$ i
- else
4 l3 ]' R1 Q9 Y - {
+ ]" _6 p/ B: L1 r! z - /* Disable the Selected IRQ Channels -------------------------------------*/
" r# q" Q! v: [) Z. I - NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
1 `7 H; h; j7 }0 ^ - (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
/ W" g9 a9 C G1 @7 L" B! f7 j - }) V( S+ y# r& l# a, T) Y# O
- }
复制代码
5 O* c' _1 d/ ?可以看到,它会去设置几个寄存器:NVIC的IP,ISER,ICER等等,NVIC是基址,为: - #define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */
, Z9 h, r5 f( B1 q - #define NVIC_BASE (SCS_BASE + 0x0100) /*!< NVIC Base Address */1 k6 k1 d' O5 @" b/ [8 c/ {! b
- #define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */" U g% L' ]9 \: A0 o9 Z
4 t% m8 T3 U+ P. j: O1 ^( N. d* ~- # P+ z1 K c5 z w9 o( T. n) a
- #define NVIC ((NVIC_Type *) NVIC_BASE) /*!< NVIC configuration struct */
复制代码
8 Z# W% E0 w0 x" I7 t3 `NVIC_Type为: - /** @addtogroup CMSIS_CM3_NVIC CMSIS CM3 NVIC1 ?3 V2 V+ J7 I' e0 m! z$ h
- memory mapped structure for Nested Vectored Interrupt Controller (NVIC)
1 {' t! p$ D+ g5 |4 J - @{
- E! ?( {: h3 l$ _. o8 ^' \ - */
& {* k" x7 y+ h. v; r - typedef struct
J5 W. e& a6 b! y - {
& x) y" a- S& c - __IO uint32_t ISER[8]; /*!< Offset: 0x000 Interrupt Set Enable Register */! e+ p/ i/ D, F8 b
- uint32_t RESERVED0[24];
: h# X; f+ }- P; k, r - __IO uint32_t ICER[8]; /*!< Offset: 0x080 Interrupt Clear Enable Register */
2 @9 O2 x8 T3 B: |# _% C- @ - uint32_t RSERVED1[24];
9 I: @" b7 G! T5 p8 m' X - __IO uint32_t ISPR[8]; /*!< Offset: 0x100 Interrupt Set Pending Register */" R8 s7 Y2 M/ z/ n
- uint32_t RESERVED2[24];
! G+ K4 d! r3 d) X5 `+ S8 E - __IO uint32_t ICPR[8]; /*!< Offset: 0x180 Interrupt Clear Pending Register */
% p2 G/ \5 {2 \8 { - uint32_t RESERVED3[24]; 3 ~! Z% r% b1 u" n9 F( l: }$ H
- __IO uint32_t IABR[8]; /*!< Offset: 0x200 Interrupt Active bit Register */
- p& H( S% Y( n. @% D( L: E - uint32_t RESERVED4[56]; 6 _, g% K. Z8 T! H! \
- __IO uint8_t IP[240]; /*!< Offset: 0x300 Interrupt Priority Register (8Bit wide) */# z% R9 X% ~' D$ r4 D
- uint32_t RESERVED5[644];
4 }2 i' Y5 ^9 q* ?. R T* p' l7 a4 {7 d - __O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register */
' `$ f( h" H; q$ P. n* u8 j - } NVIC_Type; ; b0 h1 n: }* E/ |. D
- /*@}*/ /* end of group CMSIS_CM3_NVIC */
复制代码
( ?# F0 Y2 }0 G3 H0 j- k! z& R从上面可以了解到的是,NVIC的寄存器的基址是没有错的,《The Definitive Guide to the ARM Cortex-M3》 85页有个比较详细的内存图;或者查看《Cortex-M3 Technical Reference Manual Revision r1p1》3.4 System address map,6.3 NVIC programmers model: ( @3 ?# T) H$ }* z" o$ C0 G
2 I' D- g* ?: k1 k( p! |# A
以及:
2 B4 l: |3 k2 C$ y' v
4 k6 J' U. E8 J
B3.4 Nested Vectored Interrupt Controller (NVIC)的相关说明,例如: 7 i5 [, ?( V& d) U3 A3 U/ e
1 l& C; R+ _8 t5 W3 V [" R
当然,你看权威指南也可以的,在其APPENDIX D:NVIC Registers Quick Reference里面也有所描述。 但还有一个问题,我怎么知道这个Interrupt Set-Enable Registers寄存器的哪个位对应哪个中断呢?例如NVIC_ISER0的第0位对应哪个呢,其实,上面的表B3-31的说明已经说了,每一位对应一个中断号,所以我们还得看看stm32F103对应的中断号,可以查阅《RM0008:Reference manual》的第10章,Interrupts and events中的中断向量表,找到对应MD容量的那个表Table 63. Vector table for other STM32F10xxx devices,前面16个M3内核的中断,不可以从这个寄存器里控制,所以不管,我们从WWDG开始,可以看到这个表中的第一列即对应于寄存器中的某位(超过31的自己换算一下即可):
2 h& Y. ?4 t/ e) Z+ m; g) I
: J( U! M! i8 P
可以看到,STM32F10x standard peripheral library文件stm32f10x.h中的中断号的定义是能够与这里对应上的。 另外,stm32F103RB的Datasheet(CD00161566)里面的2.3.5 Nested vectored interrupt controller (NVIC)提到F103仅有43个可屏蔽中断,所以只需用到NVIC_ISER0和NVIC_ISER1来设置启用外设中断。
" v, w5 n6 {; i/ y |