月度归档:2015年06月

STM32+UCOS-II实现临界区不关闭重要中断

在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

实际测试,这样改写后,接收的维根读头数据每次都正确。