作为我的一个习气,学习某一个渠道的东西,总是先要摸清楚中止的处理流程,当然是从文件代码级的流程剖析了。
下面就说下stm32的中止流程。咱们知道,stm32的库中写好了许多的驱动程序,能够说包含了一切的。一起也供给许多数据处理方法,例如串口的读写,用户能够挑选轮询、中止、DMA等3中方法来处理。
关于中止,stm32的库中做好了结构,用户只需填写好几个函数的完成就ok了,就像网上说的,这便是傻瓜式开发。
了解中止,首要要知道stm32f10x_it.c这个文件,一般情况下是和main文件在同一个目录下的。翻开这个文件,咱们能够看到xyz_IRQHandler函数的完成,尽管说是完成,可是简直都是空的。对了,这些函数便是要用户填写的中止处理函数,假如你用到了哪个中止来做相应的处理,你就要填写相应的中止处理函数,需求依据各外设的实际情况来填写,可是一般都会有封闭和敞开中止。在这个文件中还有许多体系相关的中止处理函数,例如体系时钟SysTickHandler。详细的完成能够参阅stm32fwlibFWLibexamples下的各比如。
到这儿,咱们也只不过看了中止的处理函数,而这些处理函数是怎样被硬件中止调用的呢?嗯,说到这儿就不得不提一下stm32f10x_vector.c这个文件了。内容如下:
typedef void( *intfunc )( void );
typedef union { intfunc __fun; void * __ptr; } intvec_elem;
typedef union { intfunc __fun; void * __ptr; } intvec_elem;
//IAR对所用言语(这儿是C)做的一些扩展,也便是说这儿能够用扩展的功用
#pragma language=extended#pragma segment=”CSTACK”
#pragma language=extended#pragma segment=”CSTACK”
void __iar_program_start( void );
#pragma location = “.intvec”
const intvec_elem __vector_table[] =
{
{ .__ptr = __sfe( “CSTACK” ) },
&__iar_program_start,
NMIException,
HardFaultException,
MemManageException,
BusFaultException,
UsageFaultException,
0, 0, 0, 0,
vPortSVCHandler,
DebugMonitor,
0,
xPortPendSVHandler,
xPortSysTickHandler,
WWDG_IRQHandler,
PVD_IRQHandler,
TAMPER_IRQHandler,
RTC_IRQHandler,
FLASH_IRQHandler,
RCC_IRQHandler,
EXTI0_IRQHandler,
EXTI1_IRQHandler,
EXTI2_IRQHandler,
EXTI3_IRQHandler,
EXTI4_IRQHandler,
DMAChannel1_IRQHandler,
DMAChannel2_IRQHandler,
DMAChannel3_IRQHandler,
DMAChannel4_IRQHandler,
DMAChannel5_IRQHandler,
DMAChannel6_IRQHandler,
DMAChannel7_IRQHandler,
ADC_IRQHandler,
USB_HP_CAN_TX_IRQHandler,
USB_LP_CAN_RX0_IRQHandler,
CAN_RX1_IRQHandler,
CAN_SCE_IRQHandler,
EXTI9_5_IRQHandler,
TIM1_BRK_IRQHandler,
TIM1_UP_IRQHandler,
TIM1_TRG_COM_IRQHandler,
TIM1_CC_IRQHandler,
vTimer2IntHandler,
TIM3_IRQHandler,
TIM4_IRQHandler,
I2C1_EV_IRQHandler,
I2C1_ER_IRQHandler,
I2C2_EV_IRQHandler,
I2C2_ER_IRQHandler,
SPI1_IRQHandler,
SPI2_IRQHandler,
vUARTInterruptHandler,
USART2_IRQHandler,
USART3_IRQHandler,
EXTI15_10_IRQHandler,
RTCAlarm_IRQHandler,
USBWakeUp_IRQHandler,
};
{
};
现在咱们清楚了,这儿便是中止向量表,每一个item对应一个中止或反常处理,这儿item的填写要和stm32spec中的Interrupt and exception vectors一节中的列表中的次序共同。
说道这儿,又有一个问题,这个向量表是放在何处的呢?上面临.intvec的解说能够看出是被链接器放到了一个地址上(这儿是0x08000000,NVIC_VectTab_FLASH)。可是stm32是怎样知道这个地址的呢,或许有个默认值,或者是就这一个固定值?)。咱们在stm32f10x_nvic.c文件中发现下面这样的一个函数
void NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset)
{
assert(IS_NVIC_VECTTAB(NVIC_VectTab));
assert(IS_NVIC_OFFSET(Offset));
SCB->ExceptionTableOffset = (((u32)Offset << 0x07) & (u32)0x1FFFFF80);
{
一起在example目录下有vectortable_relocation这样的一个比如:This example describes how to use the NVIC firmware library to set the CortexM3 vector table in a specific address other than default.
在这个比如里边便是直接调用了上面的那个函数,好像意思很明显了。可是SCB->ExceptionTableOffset是怎样起作用的呢?
侧重解说这个问题,先看一组界说:【stm32f10x_map.b】
#define SCS_BASE
#define SysTick_BASE (SCS_BASE + 0x0010)
#define NVIC_BASE (SCS_BASE + 0x0100)
#define SCB_BASE (SCS_BASE + 0x0D00)
#define NVIC_BASE
#define SCB_BASE
#ifdef _SCB
#define SCB ((SCB_TypeDef *) SCB_BASE)
#endif
#define SCB
#endif
typedef struct
{
vu32 CPUID;
vu32 IRQControlState;
vu32 ExceptionTableOffset;
vu32 AIRC;
vu32 SysCtrl;
vu32 ConfigCtrl;
vu32 SystemPriority[3];
vu32 SysHandlerCtrl;
vu32 ConfigFaultStatus;
vu32 HardFaultStatus;
vu32 DebugFaultStatus;
vu32 MemoryManageFaultAddr;
vu32 BusFaultAddr;
} SCB_TypeDef;
{
} SCB_TypeDef;
其实这儿首要便是要弄清楚这个SCB是什么意思,由于这个结构是映射到一个物理地址上的。像其他操控寄存器都是这么个玩法,难道这也是个某类操控器。google一下,公然关于体系操控寄存器组【上篇文章有说到】STM32的固件库中有如下界说:
typedef struct
{
vuc32 CPUID;
vu32 ICSR;
vu32 VTOR;
vu32 AIRCR;
vu32 SCR;
vu32 CCR;
vu32 SHPR[3];
vu32 SHCSR;
vu32 CFSR;
vu32 HFSR;
vu32 DFSR;
vu32 MMFAR;
vu32 BFAR;
vu32 AFSR;
} SCB_TypeDef;
{
} SCB_TypeDef;
它们对应ARM手册中的名称为
CPUID = CPUID Base Register
ICSR = Interrupt Control State Register
VTOR = Vector Table Offset Register
AIRCR = Application Interrupt/Reset Control Register
SCR = System Control Register
CCR = Configuration Control Register
SHPR = System Handlers Priority Register
SHCSR = System Handler Control and State Register
CFSR = Configurable Fault Status Registers
HFSR = Hard Fault Status Register
DFSR = Debug Fault Status Register
MMFAR = Mem Manage Address Register
BFAR = Bus Fault Address Register
AFSR = Auxiliary Fault Status Register
CPUID = CPUID Base Register
ICSR = Interrupt Control State Register
VTOR = Vector Table Offset Register
AIRCR = Application Interrupt/Reset Control Register
SCR = System Control Register
CCR = Configuration Control Register
SHPR = System Handlers Priority Register
SHCSR = System Handler Control and State Register
CFSR = Configurable Fault Status Registers
HFSR = Hard Fault Status Register
DFSR = Debug Fault Status Register
MMFAR = Mem Manage Address Register
BFAR = Bus Fault Address Register
AFSR = Auxiliary Fault Status Register
至此,咱们总算清楚了,这个中止向量表的地址,最终是要写到某个操控器中去。那这么说来,上述的0x08000000能够是个其他值了,只需确保这一处的地址不能被其他程序拜访就行了。