[ M3 LN ] FW(固件)库函数NVIC_Xxx()

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”文件中被定义。


1 NVIC_PriorityGroupConfig()

(1)原型

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);

[1] 功能

配置优先级组:占先式优先级和亚优先级配置。


[2] 参数

NVIC_PriorityGroup:优先级分组。针对SCB_AIACR的bit[10:8]( PRIGROUP,中断优先级配置位 )配置占先式优先级和亚优先级所占的位数。这个参数可以是以下宏,

//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]位用于占先式优先级和亚优先级的位数。


(2) 源码

[1] 断言

“USART_Init()”断言assert_param()部分。


[2] 配置NVIC优先级组

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])中各占的位数。


2 NVIC_Init()

(1) 原型

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

[1] 功能

根据NVIC_InitStruct参数初始化NVIC外设通道。


[2] 参数

NVIC_InitStruct是NVIC_InitTypeDef类型指针变量,NVIC_InitTypeDef结构体被定义在”misc.h”文件中,
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;

(2) 源码

[1] 断言assert_param()

“USART_Init()”断言assert_param()部分。


[2]计算中断请求优先级

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,这里表示失能中断通道的含义。
2~4. 得占先式优先级移位位数及亚优先级保留位位数。 当SCB->AIRCR的bit[10:8]位的值为NVIC_PriorityGroup_x时,tmppriority的值为x(它表示占先式优先级数占用的位数)。3语句中tmppre的值为4-x,含义为占先式优先级移出位的数目。tmpsub的初值为0x0f,4语句根据占先式优先级数占位数目而保留的亚优先级数占用位的数目。占先式优先级与亚优先级一共占4位,根据SCB->AIRCR的bit[10:8]的配置得到两个优先级的占用位,

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。


[3] 中断通道使能

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的中断。这是一种映射算法


[4] 关闭中断

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位的存储与分组”笔记。


3 NVIC_SetVectorTable()

(1) 原型

void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset)

[1] 功能

设置向量表位置和偏移量。


[2] 参数

NVIC_VectTab:在FLASH或者RAM中设定向量表。

Offset:向量表的基址偏移值,必须为8的倍数。


(2) 源码

[1] 断言assert_param()

“ USART_Init()”断言assert_param()部分。


[2] 设置向量表基址

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.

你可能感兴趣的:([ M3 LN ] FW(固件)库函数NVIC_Xxx())