一、手柄代码篇
我们直接看代码部分,然后逐步深入了解,如有不对的地方,欢迎大家指证!!
第一阶段——设备内部的初始化
NVIC_SetVectorTable(FIRMWARE_START_ADDR,0);
/**
* @brief Sets the vector table location and Offset.
* @param NVIC_VectTab: specifies if the vector table is in RAM or FLASH memory.
* This parameter can be one of the following values:
* @arg NVIC_VectTab_RAM
* @arg NVIC_VectTab_FLASH
* @param Offset: Vector Table base offset field. This value must be a multiple
* of 0x200.
* @retval None
*/
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset)
{
/* Check the parameters */
assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));
assert_param(IS_NVIC_OFFSET(Offset));
SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80);
}
功能
1、设置向量表的位置和偏移
参数
#define FIRMWARE_START_ADDR (FLASH_BASE + BOOTLOADER_SIZE)
指定向量表位置在 RAM 还是在程序存储器:这里是位于FLASH中
0
向量表基地址的偏移量
返回值
指定中断活动位的新状态
具体实现
存放的是中断服务函数的入口地址,当发生中断时,CPU在这个表中查询,以此获取中断函数的入口地址
在stm32 的启动文件中,设置完成堆栈,就来设置中断向量表
既然看到这里了,我们不妨再进一步看看NVIC到底是什么?
NVIC概览
1、向量中断控制器,简称
NVIC
,是
Cortex‐M3
不可分离的一 部分。
2、它与 CM3
内核的逻辑紧密耦合,有一部分甚至水乳交融在一起。
3、NVIC
的寄存器以存储 器映射的方式来访问。
4、除了包含控制寄存器和中断处理的控制逻辑之外,NVIC
还包含了
MPU 的控制寄存器、SysTick
定时器以及调试控制。
5、NVIC
共支持
1
至
240
个外部中断输入(通常外部中断写作
IRQs
)
6、NVIC
的访问地址是
0xE000_E000
。
7、NVIC 的中断控制/状态寄存器都只能在特权级下访问。
有一个例外——软件触发中断寄存器可以在用户级下访问以产生软件中断。
参考:Cortex-M3权威指南第8章-NVIC与中断控制
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
/**
* @brief Configures the priority grouping: pre-emption priority and subpriority.
* @param NVIC_PriorityGroup: specifies the priority grouping bits length.
* This parameter can be one of the following values:
* @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority
* 4 bits for subpriority
* @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority
* 3 bits for subpriority
* @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority
* 2 bits for subpriority
* @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority
* 1 bits for subpriority
* @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority
* 0 bits for subpriority
* @retval None
*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
/* Check the parameters */
assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
/* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
看这个函数之前,我们回顾之前学习的一些关于中断优先级的相关知识
第0组:所有4位用于指定响应优先级(16种)
第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级(8种)
第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级(4种)
第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级(2种)
第4组:所有4位用于指定抢占式优先级
根据我上面给出的优先级分组,大家应该很容易可以看出,他使用的第4组,就是2^4组(16组)
delay_init()
void delay_init()
{
u32 reload;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟 HCLK
fac_us=SystemCoreClock/1000000; //不论是否使用OS,fac_us都需要使用
reload=SystemCoreClock/1000000; //每秒钟的计数次数 单位为M
reload*=1000000/configTICK_RATE_HZ; //根据configTICK_RATE_HZ设定溢出时间
//reload为24位寄存器,最大值:16777216,在72M下,约合0.233s左右
fac_ms=1000/configTICK_RATE_HZ; //代表OS可以延时的最少单位
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断
SysTick->LOAD=reload; //每1/configTICK_RATE_HZ秒中断一次
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
}