最近使用STM32时希望将systick的中断优先级降低,但是CMSIS里给出的例子都是类似 - NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
; @3 `8 O) Z8 ?- Y6 S4 b- I, t" v% p - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
, Z. ~* H1 k% N - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; # f. A7 ]* E D8 ^- r, g( N
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 2 F. T7 Q0 c3 P x. U
- NVIC_Init(&NVIC_InitStructure);
复制代码 3 M, p: M$ v* S8 C u
还是没有配置systick。
" t/ u- i6 r* C0 Y- B% F6 X5 s3 z( p+ d4 r$ N% D: X
后来阅读CM3的技术参考手册,讲解了NVIC的配置。 7 j' K/ E* I$ g0 j+ U- g3 ~; u* ^
中断分为内核中断和芯片的中断,配置的寄存器位置不同。芯片的中断配置在NVIC的IP内,内核的中断配置在SCB内。 可以直接调用core_cm3.h里的函数 - static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) , D; B/ a$ I" D
- {
) u( e. r- \7 H& p" P/ D - if(IRQn < 0) { ( B1 d9 o6 X. Y3 X; I5 D0 M7 {9 x
- SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */
复制代码这个函数实现了两类中断优先级的配置。 3 v; g/ C m9 |' }
但是直观上来看看不到抢先式优先级与子优先级。
3 o; ^( w5 _* x0 y/ _首先,配置优先级组,可以使用固件库的程序,也可以用core_cm3.h的函数。 - void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) 7 L3 l3 M# x: L, R: `
- {
3 E1 p- i. y1 g8 d- u9 Q8 K - /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
# f9 w* y6 m' q: h/ y: o - SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup; % q# `4 w1 `- x: V5 b5 @- R' b% T
- }
复制代码或 - static __INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) 9 h& u( Z5 _- b6 C8 @) k" c' F
- {
4 b3 w2 G2 n/ g4 ` - uint32_t reg_value; 0 F, o- s W9 ]$ S
- uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ 2 K2 p/ n, {9 h" l
-
" |( k" |5 B+ {6 j& P. z - reg_value = SCB->AIRCR; /* read old register configuration */
- l- p1 P. U9 i! k7 o) P& ]6 E( J - reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */
3 |! d7 S0 S2 o. h& ~& ^ - reg_value = (reg_value |
* g( B: k. n9 k# x/ I2 n# p - (0x5FA << SCB_AIRCR_VECTKEY_Pos) |
" q5 W5 h- H6 C h' x' q9 `1 u - (PriorityGroupTmp << 8)); /* Insert write key and priorty group */
' \* |/ w' w/ S. g ~" J' G - SCB->AIRCR = reg_value; 3 z- y% i: }- J% T2 O; F+ j
- }
复制代码
( \: E2 ]* s0 i* v: _参数范围为0~7,具体如下
5 u. ?9 H2 `% Y2 f! h; R% n# H6 h
& ] y: U, K: L9 H2 g5 x, G随后配置各个中断的优先级,对于外设的中断可以使用固件库的程序,比较直观。如最前面所给出的例子,但是根据其实现,是不能够用来配置内核中断的,例如 - NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn; 4 t, x# C3 L( q, K
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 7 k) N+ G( a& |& f: w% l5 `$ @1 R
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 8 O+ j! Y' [" h2 s1 b) V
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
6 F# ]$ P$ U, `& y - NVIC_Init(&NVIC_InitStructure);
复制代码这是错误的,因为内部使用IRQn寻址,而SysTick_IRQn为-1.
' E9 v1 L7 w1 K# F$ A所以对于Sysick使用core_cm3.h的函数 - NVIC_SetPriority(SysTick_IRQn, 4);
复制代码这时不能显式的看出抢先式优先级与子优先级,写入的优先级需要根据优先级组的配置来选择。 - NVIC_SetPriority(SysTick_IRQn, n); ' f3 j9 n0 U Z' Y) |9 O
- n=0x00~0x03 设置Systick为抢占优先级0
& ?8 v1 Z& p3 _ Z: [ - n=0x04~0x07 设置Systick为抢占优先级1 @' d" ~/ v1 X1 f) x2 V, e
- n=0x08~0x0B 设置Systick为抢占优先级2 & K! B! K2 _9 u; u/ _ n
- n=0x0C~0x0F 设置Systick为抢占优先级3
复制代码NVIC_SetPriority函数指定中断优先级的寄存器位(STM32只用4位来表示优先级)的数据,例如中断优先级组设置为了2,即高2位用于指定抢占式优先级,低2位用于指定响应优先级,0x00~0x03高2位为0,所以抢占优先级为0;0x04~0x07高2位为1,所以抢占优先级为1,以此类推。
- h5 T, X! }9 I- y! m |