STM32F10XXX中的中断的优先级用优先级组(占先式优先级 + 亚优先级)描述。STM32F10XXX的“优先级组”寄存器SCB_AIRCR.GROUP[10:8]配置一个中断“占先式优先级”在SCB_SHPRx.PRI_n[7:4]位段中占的最高位位数,“亚优先级”在SCB_SHPRx.PRI_n[7:4]位段中占的最低位位数。SCB_AIRCR.GROUP[10:8] = 0x6时表示某中断的占先式优先级用位段的最高1位(占优先级最大值(最低优先级)只可以为1),亚优先级用位段的最低3位(亚优先级的最大值(最低优先级)可以为7)。
固件库中关于中断配置的一些函数。它们都是在”misc.c”文件中被定义。
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
配置优先级组:占先式优先级和亚优先级配置。
//0位用来供占先式优先级,4位用来供亚优先级使用 //1位用来供占先式优先级,3位用来供亚优先级使用 //2位用来供占先式优先级,2位用来供亚优先级使用 //3位用来供占先式优先级,1位用来供亚优先级使用 //4位用来供占先式优先级,0位用来供亚优先级使用 #define NVIC_PriorityGroup_0 ((uint32_t)0x700) #define NVIC_PriorityGroup_1 ((uint32_t)0x600) #define NVIC_PriorityGroup_2 ((uint32_t)0x500) #define NVIC_PriorityGroup_3 ((uint32_t)0x400) #define NVIC_PriorityGroup_4 ((uint32_t)0x300)这些宏值针对AIRCR的bit[10:8]位,配置SCB_SHPRx.[7:4]位用于占先式优先级和亚优先级的位数。
SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;AIRCR_VECTKEY_MASK的值为((uint32_t)0x05FA0000),此值将SCB_AIRCR 的bit[31:16](VECTKEYSTAT[15:0]/ VECTKEY[15:0],寄存器钥匙 )( Cortex-M3内核编程手册中说明:对AIRCR的bit[31:16]进行写操作时这些位的值只有写入0x05fa才有效 )。
NVIC_PriorityGroup为参数中的NVIC_PriorityGroup_x,此参数配置AIRCR的bit[10:8]位,用于配置占先式优先级和亚优先级在SCB_SHPRx.PRI_n[7:4](SCB->IP[m]bit[7:4])中各占的位数。
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct); |
根据NVIC_InitStruct参数初始化NVIC外设通道。
typedef struct { uint8_t NVIC_IRQChannel; //指定需要被使能或者失能的中断请求通道,中断请求通道定义在<stm32f10x.h>中 uint8_t NVIC_IRQChannelPreemptionPriority; //指定NVIC_IRQChannel占先式优先级 uint8_t NVIC_IRQChannelSubPriority; //指定NVIC_IRQChannel亚优先级 FunctionalState NVIC_IRQChannelCmd; //指定NVIC_IRQChannel使能还是失能 } NVIC_InitTypeDef;
if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE){ tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08; tmppre = (0x4 - tmppriority); tmpsub = tmpsub >> tmppriority; tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre; tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub; tmppriority = tmppriority << 0x04; NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority; }
1. 中断使能情况下进入中断配置。DISABLE的值为0,这里表示失能中断通道的含义。
SCB->AIRCR[10:8] |
占先式优先级数目 |
亚优先级数目 |
描述(IPRx bit[7:4]中占位数,占先式占高位,副占低位) |
0x700 |
0 |
0-15 |
占先式优先级在中断优先级配置寄存器中占0位,亚优先级占4位 |
0x600 |
0 ~1 |
0-7 |
占先式优先级在中断优先级配置寄存器中占1位,亚优先级占3位 |
0x500 |
0-3 |
0-3 |
占先式优先级在中断优先级配置寄存器中占2位,亚优先级占2位 |
0x400 |
0-7 |
0-1 |
占先式优先级在中断优先级配置寄存器中占3位,亚优先级占1位 |
0x300 |
0-15 |
0 |
占先式优先级在中断优先级配置寄存器中占4位,亚优先级占0位 |
6~8. 计算得到某中断的中断优先级。6语句是将参数NVIC_IRQChannelPreemptionPriority的值向左移tmppre位再赋值给tmppriority,tmppre的值为占先式优先级需要向高位移走的位数。7语句是保留了参数NVIC_IRQChannelSubPriority的低tmpsub位再赋值给tmppriority,tmpsub正代表亚优先级需要占的位数。8语句将tmppriority的值放入bit[7:4]位中。这种算法实现后,用户输入的给优先级的数可以超出上表中的范围(不要超出赋值对象能表示的范围),此时这个算法保证占先式和亚优先级占合理(符合SCB->AIRCR bit[10:8]的配置)的位数。
10. 设定NVIC_IRQChannel中断通道的中断优先级组。设定中断x(中断号,定义在<stm32f10x.h>中,《RM008 stm32f10xx参考手册》表54~55,Page 132)中断优先级配置的寄存器为IPR0~IPR67,每个寄存器包含8位,只有bit[7:4]供用户配置。CMSIS为提高软件开发效率,指定在程序中使用IP[0]~IP[67]数组来代替IPR0~IPR67。
NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);使能NVIC_IRQChannel通道中断。中断号为0~31、32~63、64 ~67的中断分别在在ISER[0]、ISER[1]、ISER[2]中使能,NVIC_InitStruct->NVIC_IRQChannel >>0x05将中断号对应到了正确的ISER[x]中。在中断号为[0, 31]时,这些数对应着bit[5:0]的每一种状态(0 ~ 31),当中断号为[32, 63]时,这些数对应着bit[6]为1下bit[5:0]的每一种状态,bit[6]为1的数已经被对应到ISER[1]中,bit[5:0]已经能够标识在ISER[1]中不同的下标了。故而此语句就成功的使能了中断号为NVIC_InitStruct->NVIC_IRQChannel的中断。这是一种映射算法。
if (NVIC_InitStruct->NVIC_IRQChannelCmd == DISABLE){ NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); }当NVIC_InitStruct->NVIC_IRQChannelCmd ==DISABLE时,用[3]中的映射方法用向ICER[x]写1的方式将中断关闭。
NVIC_Init()函数内的算法可以参看“n位段高x低n-x位的存储与分组”笔记。
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset)
设置向量表位置和偏移量。
NVIC_VectTab:在FLASH或者RAM中设定向量表。
Offset:向量表的基址偏移值,必须为8的倍数。
SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80);NVIC_VectTab的值为((uint32_t)0x20000000)时表示中断向量表在RAM中,起始地址为0x00000000。NVIC_VectTab的值为((uint32_t)0x08000000)时表示中断向量表在FLASH中,起始地址为((uint32_t)0x08000000)。
Learning Note Over.