|
最近使用STM32时希望将systick的中断优先级降低,但是CMSIS里给出的例子都是类似 - NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; 7 k* o6 }1 Y1 ?( x) f0 N) H
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
+ Q: t$ Z) n R7 f5 p - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
5 E1 y+ d5 d) C! r - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
; M5 E X* k" i3 y5 N5 W# |/ U - NVIC_Init(&NVIC_InitStructure);
复制代码
( {' [% B% k$ ] I还是没有配置systick。
% T$ R) _: ?) x2 k( ]4 I
9 [# r" _+ `$ k: ]后来阅读CM3的技术参考手册,讲解了NVIC的配置。 - G& v$ j, A0 J! t- u1 Z) K
中断分为内核中断和芯片的中断,配置的寄存器位置不同。芯片的中断配置在NVIC的IP内,内核的中断配置在SCB内。 可以直接调用core_cm3.h里的函数 - static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
$ z1 s0 i D% w+ z& }: F5 N - { ; N% Q) \3 u% c& T% z- ]# T
- if(IRQn < 0) { , e& X7 M$ R9 U" f
- SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */
复制代码这个函数实现了两类中断优先级的配置。
9 P& u, m5 w. L- M但是直观上来看看不到抢先式优先级与子优先级。
7 a8 S- d2 X. G" q1 f3 ^1 a% A首先,配置优先级组,可以使用固件库的程序,也可以用core_cm3.h的函数。 - void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) : L9 O0 a/ X! Z$ z7 j; _! F
- {
* W' l$ B3 B# F - /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */ / k( e+ l# _9 P+ p
- SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
. B; T2 K7 Y4 M' H2 q q - }
复制代码或 - static __INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
1 l, z. H* d. ?& o, ] - {
3 v9 l1 e* ?3 R# m# |& o9 j( Q - uint32_t reg_value; 1 c# t* @4 d" Z5 G, |
- uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ ' T. y8 b3 J: ~$ a* ^
- 4 V& o" t( A3 \& W# x
- reg_value = SCB->AIRCR; /* read old register configuration */
/ V g( U. O0 r - reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ : O t7 m0 r& B+ B+ J# y" s: G4 A
- reg_value = (reg_value |
! l. F d2 q$ B - (0x5FA << SCB_AIRCR_VECTKEY_Pos) | 4 H- }6 o3 i, u; Q6 j n P
- (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ : i% ~2 _. I! O: s2 c0 l
- SCB->AIRCR = reg_value; 8 V- v' \! [" P0 `% _- ^
- }
复制代码
1 ~5 d. L* b6 _5 l% h5 ?, S4 A: C7 k参数范围为0~7,具体如下
5 Y* ?6 f3 {: N# q9 J7 ^/ w' h6 V. U2 Z( R
随后配置各个中断的优先级,对于外设的中断可以使用固件库的程序,比较直观。如最前面所给出的例子,但是根据其实现,是不能够用来配置内核中断的,例如 - NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;
; B$ J" R* H& f' t+ g: L0 M - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- t! r1 X! z8 U- I# X; C - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; / l$ c4 O# ~9 s- }& b+ j& X, w
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
6 N& e. W# W, W# z+ r4 \ - NVIC_Init(&NVIC_InitStructure);
复制代码这是错误的,因为内部使用IRQn寻址,而SysTick_IRQn为-1. + ?( {$ _( ]$ ~; i
所以对于Sysick使用core_cm3.h的函数 - NVIC_SetPriority(SysTick_IRQn, 4);
复制代码这时不能显式的看出抢先式优先级与子优先级,写入的优先级需要根据优先级组的配置来选择。 - NVIC_SetPriority(SysTick_IRQn, n); 5 v( o+ e& a. A
- n=0x00~0x03 设置Systick为抢占优先级0 ) F. Z3 b1 R) A! x
- n=0x04~0x07 设置Systick为抢占优先级1
1 l0 e- l/ [3 p" y j - n=0x08~0x0B 设置Systick为抢占优先级2 2 V7 h$ N1 b9 C5 |2 |: H- S
- n=0x0C~0x0F 设置Systick为抢占优先级3
复制代码NVIC_SetPriority函数指定中断优先级的寄存器位(STM32只用4位来表示优先级)的数据,例如中断优先级组设置为了2,即高2位用于指定抢占式优先级,低2位用于指定响应优先级,0x00~0x03高2位为0,所以抢占优先级为0;0x04~0x07高2位为1,所以抢占优先级为1,以此类推。
# R+ j1 q, V: m& E* Y |