在ARM7内核芯片中,在临界区不关闭快速中断,可以避免丢失重要的中断信号。STM32要实现类似功能,需要用到BASEPRI寄存器。
比如一个产品需要外接维根读头,STM32利用外部中断解码。如果在临界区关闭所有中断,那么在刷卡时,有可能丢掉部分外部中断信号,导致解码错误。
系统简化中断设置,只设置抢占式优先级,不要子优先级。抢占式优先级(0-15),子优先级都为0.
UCOS的SYSTICK中断及PENDSV中断设定在最低优先级
#define ConfigKERNEL_INTERRUPT_PRIORITY_PENSV (15)
#define ConfigKERNEL_INTERRUPT_PRIORITY_SYSTICK (14)
Pendsvde 的优先级在OS_CPU_A.S的OSStartHighRdy中设置,优先级最低为15.
Systick在core_cm3.h的systick_config()中设置,pendsv的优先级寄存器0Xe000ed22的值为0Xf0,抢占式优先级为15,亚优先级为0。Systick的优先级寄存器0XE000ED23的值为0Xe0,抢占式优先级为14,亚优先级为0.
维根读头的外部中断设置为0号抢占式优先级。
如果OS_ENTER_CRITIAL()函数,即OS_CPU_A.S中的OSCPUSAVESR如下
MRS R0,PRIMASK
CPSID I
BX LR
那么程序进入临界区后,所有外部中断都会关闭,包括维根读头使用的外部中断0,导致接收维根数据出错。这时应该使用BASEPRI寄存器。
BASEPRI寄存器最多有9位(由表达优先级的位数决定,STM32F103中,高4位有效),它定义了被屏蔽优先级的阈值。当它设定成某个值后,所有优先级大于等于此值的中断都被关(优先级号越大,优先级越低)。小于此值的中断不会被关闭。若设成0,则不关闭任何中断,0是缺省值。
此处要保证维根读头使用的中断优先级0不被关闭,所以要设置BASEPRI高4位为1.
MASK_INTERRUPT_PRIORITY EQU 0X01
OSCPUSAVESR
MRS R0,BASEPRI
MOVS R1,#(MASK_INTERRUPT_PRIORITY<< 4)
MSR BASEPRI,R1
BX LR
OSCPURESTORESR
MSR BASEPRI,R0
BX LR
实际测试,这样改写后,接收的维根读头数据每次都正确。