Linux 学习记录58(ARM篇)
一、GIC相关寄存器
1. 系统框图
- PPI:私有外设中断号:(ID:0~15)
- SPI:共享外设中断号:(ID:16~31)
- SGI:软件产生的中断号:(ID:0~287)
总结:
GIC层一共管理288个中断号(ID:0 ~ 287),16个SGIS,16个PPIS,256个SPIS
2. 中断号对应关系
例:
二、GICD寄存器
1. GICD_CTLR
功能:使能CPU
2. GICD_ISENABLERx
功能:设置GICD层中断使能
该寄存器共有8个(0-8),用于使能GICD层的的288个中断号,每个寄存器32位,分别控制32个中断号的使能
计算方式
置1 为使能
int ID = 99//中断号,以外部中断号为99的ID为例
ID / 32 = 3
使用" GICD_ISENABLER3 "寄存器即可
ID % 32 = 3
使用" GICD_ISENABLER3 "寄存器的第 "3 bit位" 即可
3. GICD_IPRIORITYRx
功能:设置GICD层中断优先级
计算方式
备注:设置中断优先级值的范围在:0 ~ 2^5 -1 GICD层中断优先级,需要比GICC层中断优先级高 中断优先级的值越小,代表中断优先级越高
int ID = 99//中断号,以外部中断号为99的ID为例
ID / 4 = 24
使用" GICD_IPRIORITYR第24个"寄存器即可
ID % 4 = 3 (*8+3) =27
从" GICD_IPRIORITYR第24个 "寄存器的第 "27 ~ 37(27+4) bit位" 即可
4. GICD_ITARGETSRx
功能:分配给cpu0 或者 cpu1
该寄存器共有72个(0~71)个寄存器 [ 288个中断号/每个寄存器控制4个中断号的分配 ]
计算方式
int ID = 99//中断号,以外部中断号为99的ID为例
ID / 4 = 24
使用" GICD_ITARGETSR第24个"寄存器即可
ID % 4 = 3 (*8) =24
从" GICD_ITARGETSR第24个 "寄存器的第 "24 ~ 25(24+1) bit位" 即可
5. GICD_ICPENDRx
功能:清除GICD层挂起的中断标志位
该寄存器给共有8个寄存器[ 228个中断号/每个寄存器控制32个中断号的清除 ]
计算方式
置1为清除
int ID = 99//中断号,以外部中断号为99的ID为例
ID / 32 = 3
使用" GICD_ICPENDR第3个"寄存器即可
ID % 32 = 3
从" GICD_ICPENDR第3个 "寄存器的第 "3 bit位" 即可
三、GICC寄存器
1. GICC_PMR
功能:设置GICC层中断优先级
2. GICC_CTLR
功能:使能cpu中断
3. GICC_IAR
功能:获取中断号,这个寄存器只读
文章来源:https://www.toymoban.com/news/detail-609401.html
4. GICC_EOIR
功能:清除获取到中断号
文章来源地址https://www.toymoban.com/news/detail-609401.html
四、封装函数
1. 寄存器封装
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
#define __IO volatile
typedef struct{
__IO uint32_t RTSR1; // EXTI rising trigger selection register
__IO uint32_t FTSR1; // EXTI falling trigger selection register
__IO uint32_t SWIER1; // EXTI software interrupt event register
__IO uint32_t RPR1; // EXTI rising edge pending register
__IO uint32_t FPR1; // EXTI falling edge pending register
__IO uint32_t TZENR1; // EXTI TrustZone enable register
__IO uint32_t RES1[2];
__IO uint32_t RTSR2; // EXTI rising trigger selection register
__IO uint32_t FTSR2; // EXTI falling trigger selection register
__IO uint32_t SWIER2; // EXTI software interrupt event register
__IO uint32_t RPR2; // EXTI rising edge pending register
__IO uint32_t FPR2; // EXTI falling edge pending register
__IO uint32_t TZENR2; // EXTI TrustZone enable register
__IO uint32_t RES2[2];
__IO uint32_t RTSR3; // EXTI rising trigger selection register
__IO uint32_t FTSR3; // EXTI falling trigger selection register
__IO uint32_t SWIER3; // EXTI software interrupt event register
__IO uint32_t RPR3; // EXTI rising edge pending register
__IO uint32_t FPR3; // EXTI falling edge pending register
__IO uint32_t TZENR3; // EXTI TrustZone enable register
__IO uint32_t RES3[2];
__IO uint32_t EXTICR1; // EXTI external interrupt selection register 1
__IO uint32_t EXTICR2; // EXTI external interrupt selection register 2
__IO uint32_t EXTICR3; // EXTI external interrupt selection register 3
__IO uint32_t EXTICR4; // EXTI external interrupt selection register 4
__IO uint32_t RES4[4];
__IO uint32_t C1IMR1; // EXTI CPU1 wakeup with interrupt mask register
__IO uint32_t C1EMR1; // EXTI CPU1 wakeup with event mask register
__IO uint32_t RES5[2];
__IO uint32_t C1IMR2; // EXTI CPU1 wakeup with interrupt mask register
__IO uint32_t C1EMR2; // EXTI CPU1 wakeup with event mask register
__IO uint32_t RES6[2];
__IO uint32_t C1IMR3; // EXTI CPU1 wakeup with interrupt mask register
__IO uint32_t C1EMR3; // EXTI CPU1 wakeup with event mask register
__IO uint32_t RES7[6];
__IO uint32_t C2IMR1; // EXTI CPU2 wakeup with interrupt mask register
__IO uint32_t C2EMR1; // EXTI CPU2 wakeup with event mask register
__IO uint32_t RES8[2];
__IO uint32_t C2IMR2; // EXTI CPU2 wakeup with interrupt mask register
__IO uint32_t C2EMR2; // EXTI CPU2 wakeup with event mask register
__IO uint32_t RES9[2];
__IO uint32_t C2IMR3; // EXTI CPU2 wakeup with interrupt mask register
__IO uint32_t C2EMR3; // EXTI CPU2 wakeup with event mask register
__IO uint32_t RES10[2];
}EXTI_TypeDef;
#define EXTI ((EXTI_TypeDef*)0x5000D000)
typedef struct {
volatile unsigned int CTRL;
volatile unsigned int TYPER;
volatile unsigned int IIDR;
volatile unsigned int RES1[29];
volatile unsigned int IGROUPR[9];
volatile unsigned int RES2[23];
volatile unsigned int ISENABLER[9];
volatile unsigned int RES3[23];
volatile unsigned int ICENABLER[9];
volatile unsigned int RES4[23];
volatile unsigned int ISPENDR[9];
volatile unsigned int RES5[23];
volatile unsigned int ICPENDR[9];
volatile unsigned int RES6[23];
volatile unsigned int ISACTIVER[9];
volatile unsigned int RES7[23];
volatile unsigned int ICACTIVER[9];
volatile unsigned int RES8[23];
volatile unsigned int IPRIORITYR[72];
volatile unsigned int RES9[184];
volatile unsigned int ITARGETSR[72];
volatile unsigned int RES10[184];
volatile unsigned int ICFGR[18];
volatile unsigned int RES11[46];
}GICD_TypeDef;
#define GICD ((GICD_TypeDef*)0xA0021000)
typedef struct {
volatile unsigned int CTRL;
volatile unsigned int PMR;
volatile unsigned int BRR;
volatile unsigned int IAR;
volatile unsigned int EOIR;
volatile unsigned int RPR;
volatile unsigned int HPPIR;
volatile unsigned int ABPR;
volatile unsigned int AIAR;
volatile unsigned int AEOIR;
volatile unsigned int AHPPIR;
volatile unsigned int RES1[41];
volatile unsigned int APR0;
volatile unsigned int RES2[3];
volatile unsigned int NSAPR0;
volatile unsigned int RES3[6];
volatile unsigned int IIDR;
volatile unsigned int RES4[960];
volatile unsigned int DIRDIR;
}GICC_TypeDef;
#define GICC ((GICC_TypeDef*)0xA0022000)
2. EXTI初始化结构体/枚举封装
typedef enum
{
EXTI_GPIOA = 0x0,
EXTI_GPIOB,
EXTI_GPIOC,
EXTI_GPIOD,
EXTI_GPIOE,
EXTI_GPIOF,
EXTI_GPIOG,
EXTI_GPIOH,
EXTI_GPIOI,
EXTI_GPIOJ,
EXTI_GPIOK,
EXTI_GPIOZ,
}EXTI_GPIOxTypedef;
typedef enum
{
EXTI_Trigger_Rising = 0x0,//上升
EXTI_Trigger_Falling,//下降
EXTI_Trigger_Rising_Falling,//双边沿
}EXTI_TriggerTypedef;
typedef struct
{
uint16_t EXTI_GPIOx;//GPIO组号
uint16_t EXTI_Line;//中断线
uint8_t EXTI_Trigger;//触发方式
uint8_t EXTI_Wakeup;//是否屏蔽
}EXTI_InitTypeDef;
/*相关函数声明*/
/*外部中断初始化*/
void EXTI_Init(EXTI_InitTypeDef* EXTI_Init);
/*清除挂起标志位s*/
void EXTI_Clr_FPR1(uint16_t ID);
3. GICD初始化结构体/枚举
typedef enum
{/*和GICC共用*/
GIC_CPU0 = 0x1,//CPU0
GIC_CPU1,//CPU1
GIC_CPU1_0,//CPU1和CPU0
}GIC_CPUTypedef;
typedef struct
{
uint8_t GICD_CPU;//使能的CPU
uint8_t GICD_Allocation_CPU;//分配CPU
uint8_t GICD_priority;//设置优先级
uint16_t GICD_interrupt_ID;//使能的中断号
}GICD_InitTypeDef;
/*相关函数声明*/
/*GICD初始化*/
void GICD_Init(GICD_InitTypeDef* GICD_Init);
/*清除挂起标志位*/
void GICD_Clr_ICPENDR(uint16_t ID);
4. GICC初始化结构体/枚举
typedef struct
{
uint8_t GICC_priority;//设置优先级
uint8_t GICC_CPU;//使能的CPU
}GICC_InitTypeDef;
/*相关函数声明*/
/*GICC初始化*/
void GICC_Init(GICD_InitTypeDef* GICD_Init);
/*获取中断号*/
uint32_t GICC_Get_IAR(void);
/*清除中断号*/
void GICC_Clr_EOIR(uint32_t ID);
5. EXTI函数
void EXTI_Init(EXTI_InitTypeDef* EXTI_Init)
{
uint8_t py = 0;
py = EXTI_Init->EXTI_Line/4;
py++;
switch(py)
{
case 1:{
/*连接Pin到EXTI_line*/
EXTI->EXTICR1 &= ~(0xff << ((EXTI_Init->EXTI_Line%4) *8));
EXTI->EXTICR1 |= (EXTI_Init->EXTI_GPIOx << ((EXTI_Init->EXTI_Line%4) *8));
}break;
case 2:{
/*连接Pin到EXTI_line*/
EXTI->EXTICR2 &= ~(0xff << ((EXTI_Init->EXTI_Line%4) *8));
EXTI->EXTICR2 |= (EXTI_Init->EXTI_GPIOx << ((EXTI_Init->EXTI_Line%4) *8));
}break;
case 3:{
EXTI->EXTICR3 &= ~(0xff << ((EXTI_Init->EXTI_Line%4) *8));
EXTI->EXTICR3 |= (EXTI_Init->EXTI_GPIOx << ((EXTI_Init->EXTI_Line%4) *8));
}break;
case 4:{
/*连接Pin到EXTI_line*/
EXTI->EXTICR4 &= ~(0xff << ((EXTI_Init->EXTI_Line%4) *8));
EXTI->EXTICR4 |= (EXTI_Init->EXTI_GPIOx << ((EXTI_Init->EXTI_Line%4) *8));
}break;
default : break;
}
switch(EXTI_Init->EXTI_Trigger)
{
case EXTI_Trigger_Rising :{//上升沿
/*设置为上升降沿触发*/
EXTI->RTSR1 &= ~(0x1 << EXTI_Init->EXTI_Line);
EXTI->RTSR1 |= (0x1 << EXTI_Init->EXTI_Line);
}break;
case EXTI_Trigger_Falling :{//下降沿
/*设置为下降沿触发*/
EXTI->FTSR1 &= ~(0x1 << EXTI_Init->EXTI_Line);
EXTI->FTSR1 |= (0x1 << EXTI_Init->EXTI_Line);
}break;
case EXTI_Trigger_Rising_Falling :{//双边沿
/*设置下降沿触发*/
EXTI->FTSR1 &= ~(0x1 << EXTI_Init->EXTI_Line);
EXTI->FTSR1 |= (0x1 << EXTI_Init->EXTI_Line);
/*设置为上升降沿触发*/
EXTI->RTSR1 &= ~(0x1 << EXTI_Init->EXTI_Line);
EXTI->RTSR1 |= (0x1 << EXTI_Init->EXTI_Line);
}break;
}
/*设置EXTI不屏蔽*/
EXTI->C1IMR1 &= ~(0x1 << EXTI_Init->EXTI_Line);
EXTI->C1IMR1 |= (0x1 << EXTI_Init->EXTI_Line);
/*设置EXTI不屏蔽*/
EXTI->C1IMR1 &= ~(0x1 << EXTI_Init->EXTI_Line);
EXTI->C1IMR1 |= (0x1 << EXTI_Init->EXTI_Line);
}
/*清除挂起标志位s*/
void EXTI_Clr_FPR1(uint16_t ID)
{
EXTI->FPR1 |= 0x1 << ID;
}
6. GICD函数
/*GICD初始化*/
void GICD_Init(GICD_InitTypeDef* GICD_Init)
{
/*使能GICD*/
GICD->CTRL &= ~(0x3);
GICD->CTRL |= GICD_Init->GICD_CPU;
/*设置使能寄存器*/
GICD->ISENABLER[GICD_Init->GICD_interrupt_ID/32] |= 0x1<<(GICD_Init->GICD_interrupt_ID%32);
/*设置中断优先级*/
GICD->IPRIORITYR[GICD_Init->GICD_interrupt_ID/4] &= ~(0x1F << ((GICD_Init->GICD_interrupt_ID%32)*8+3));
GICD->IPRIORITYR[GICD_Init->GICD_interrupt_ID/4] |= GICD_Init->GICD_priority << ((GICD_Init->GICD_interrupt_ID%32)*8+3);
/*设置中断优先级*/
GICD->ITARGETSR[GICD_Init->GICD_interrupt_ID/4] &= ~(0x3 << ((GICD_Init->GICD_interrupt_ID%32)*8));
GICD->ITARGETSR[GICD_Init->GICD_interrupt_ID/4] |= GICD_Init->GICD_Allocation_CPU << ((GICD_Init->GICD_interrupt_ID%32)*8);
}
/*清除挂起标志位*/
void GICD_Clr_ICPENDR(uint16_t ID)
{
GICD->ICPENDR[ID/32] |= 0x1 << ID%32;
}
7. GICC函数
/*GICC初始化*/
void GICC_Init(GICC_InitTypeDef* GICC_Init)
{
/*使能CICC*/
GICC->CTRL &= ~(0x3);
GICC->CTRL |= GICC_Init->GICC_CPU;
/*中断优先级设置*/
GICC->PMR &= ~(0x1F << 3);
GICC->PMR |= GICC_Init->GICC_priority << 3;
}
8. 使用示例
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_GPIOx = EXTI_GPIOF;
EXTI_InitStructure.EXTI_Line = 9;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_Wakeup = 1;
EXTI_Init(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = 8;
EXTI_Init(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = 7;
EXTI_Init(&EXTI_InitStructure);
GICD_InitTypeDef GICD_InitStructure;
GICD_InitStructure.GICD_CPU = GIC_CPU0;
GICD_InitStructure.GICD_Allocation_CPU = GIC_CPU0;
GICD_InitStructure.GICD_priority = 0;
GICD_InitStructure.GICD_interrupt_ID = 99;
GICD_Init(&GICD_InitStructure);
GICD_InitStructure.GICD_priority = 1;
GICD_InitStructure.GICD_interrupt_ID = 98;
GICD_Init(&GICD_InitStructure);
GICD_InitStructure.GICD_priority = 2;
GICD_InitStructure.GICD_interrupt_ID = 97;
GICD_Init(&GICD_InitStructure);
GICC_InitTypeDef GICC_InitStructure;
GICC_InitStructure.GICC_priority = 4;
GICC_InitStructure.GICC_CPU = GIC_CPU0;
GICC_Init(&GICC_InitStructure);
到了这里,关于Linux 学习记录58(ARM篇)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!