ARM裸机 - 中断处理编程实战_arm断电文件内容丢失

#define exception_vector_table_base 0xD0037400
#define exception_reset (exception_vector_table_base + 0x00)
#define exception_undef (exception_vector_table_base + 0x04)
#define exception_sotf_int (exception_vector_table_base + 0x08)
#define exception_prefetch (exception_vector_table_base + 0x0C)
#define exception_data (exception_vector_table_base + 0x10)
#define exception_irq (exception_vector_table_base + 0x18)
#define exception_fiq (exception_vector_table_base + 0x1C)

#define r_exception_reset (*(volatile unsigned int )exception_reset)
#define r_exception_undef (
(volatile unsigned int )exception_undef)
#define r_exception_sotf_int (
(volatile unsigned int )exception_sotf_int)
#define r_exception_prefetch (
(volatile unsigned int )exception_prefetch)
#define r_exception_data (
(volatile unsigned int )exception_data)
#define r_exception_irq (
(volatile unsigned int )exception_irq)
#define r_exception_fiq (
(volatile unsigned int *)exception_fiq)

// 中断源编号
#define INT_LIMIT (96)

//INT NUM - VIC0
#define NUM_EINT0 (0)
#define NUM_EINT1 (1)
#define NUM_EINT2 (2)
#define NUM_EINT3 (3)
#define NUM_EINT4 (4)
#define NUM_EINT5 (5)
#define NUM_EINT6 (6)
#define NUM_EINT7 (7)
#define NUM_EINT8 (8)
#define NUM_EINT9 (9)
#define NUM_EINT10 (10)
#define NUM_EINT11 (11)
#define NUM_EINT12 (12)
#define NUM_EINT13 (13)
#define NUM_EINT14 (14)
#define NUM_EINT15 (15)
#define NUM_EINT16_31 (16)
#define NUM_Reserved17 (17)
#define NUM_MDMA (18)
#define NUM_PDMA0 (19)
#define NUM_PDMA1 (20)
#define NUM_TIMER0 (21)
#define NUM_TIMER1 (22)
#define NUM_TIMER2 (23)
#define NUM_TIMER3 (24)
#define NUM_TIMER4 (25)
#define NUM_SYSTIMER (26)
#define NUM_WDT (27)
#define NUM_RTC_ALARM (28)
#define NUM_RTC_TICK (29)
#define NUM_GPIOINT (30)
#define NUM_FIMC3 (31)

//INT NUM - VIC1
#define NUM_CORTEX0 (32+0)
#define NUM_CORTEX1 (32+1)
#define NUM_CORTEX2 (32+2)
#define NUM_CORTEX3 (32+3)
#define NUM_CORTEX4 (32+4)
#define NUM_IEM_APC (32+5)
#define NUM_IEM_IEC (32+6)
#define NUM_Reserved39 (32+7)
#define NUM_NFC (32+8)
#define NUM_CFC (32+9)
#define NUM_UART0 (32+10)
#define NUM_UART1 (32+11)
#define NUM_UART2 (32+12)
#define NUM_UART3 (32+13)
#define NUM_I2C (32+14)
#define NUM_SPI0 (32+15)
#define NUM_SPI1 (32+16)
#define NUM_SPI2 (32+17)
#define NUM_AUDIO (32+18)
#define NUM_I2C_PMIC (32+19)
#define NUM_I2C_HDMI (32+20)
#define NUM_HSIRX (32+21)
#define NUM_HSITX (32+22)
#define NUM_UHOST (32+23)
#define NUM_OTG (32+24)
#define NUM_MSM (32+25)
#define NUM_HSMMC0 (32+26)
#define NUM_HSMMC1 (32+27)
#define NUM_HSMMC2 (32+28)
#define NUM_MIPI_CSI (32+29)
#define NUM_MIPI_DSI (32+30)
#define NUM_ONENAND_AUDI (32+31)

//INT NUM - VIC2
#define NUM_LCD0 (64+0)
#define NUM_LCD1 (64+1)
#define NUM_LCD2 (64+2)
#define NUM_LCD3 (64+3)
#define NUM_ROTATOR (64+4)
#define NUM_FIMC_A (64+5)
#define NUM_FIMC_B (64+6)
#define NUM_FIMC_C (64+7)
#define NUM_JPEG (64+8)
#define NUM_2D (64+9)
#define NUM_3D (64+10)
#define NUM_MIXER (64+11)
#define NUM_HDMI (64+12)
#define NUM_HDMI_I2C (64+13)
#define NUM_MFC (64+14)
#define NUM_TVENC (64+15)
#define NUM_I2S0 (64+16)
#define NUM_I2S1 (64+17)
#define NUM_I2S2 (64+18)
#define NUM_AC97 (64+19)
#define NUM_PCM0 (64+20)
#define NUM_PCM1 (64+21)
#define NUM_SPDIF (64+22)
#define NUM_ADC (64+23)
#define NUM_PENDN (64+24)
#define NUM_KEYPAD (64+25)
#define NUM_Reserved90 (64+26)
#define NUM_HASH (64+27)
#define NUM_FEEDCTRL (64+28)
#define NUM_PCM2 (64+29)
#define NUM_SDM_IRQ (64+30)
#define NUM_SMD_FIQ (64+31)

//INT NUM - VIC3
#define NUM_IPC (96+0)
#define NUM_HOSTIF (96+1)
#define NUM_HSMMC3 (96+2)
#define NUM_CEC (96+3)
#define NUM_TSI (96+4)
#define NUM_MDNIE0 (96+5)
#define NUM_MDNIE1 (96+6)
#define NUM_MDNIE2 (96+7)
#define NUM_MDNIE3 (96+8)
#define NUM_ADC1 (96+9)
#define NUM_PENDN1 (96+10)
#define NUM_ALL (200)

#endif



**-> 中断控制器初始化,绑定异常向量表到异常处理程序**



void reset_exception(void)
{
printf(“reset_exception.\n”);
}

void undef_exception(void)
{
printf(“undef_exception.\n”);
}

void sotf_int_exception(void)
{
printf(“sotf_int_exception.\n”);
}

void prefetch_exception(void)
{
printf(“prefetch_exception.\n”);
}

void data_exception(void)
{
printf(“data_exception.\n”);
}

// 主要功能:绑定第一阶段异常向量表;禁止所有中断;选择所有中断类型为IRQ;
// 清除VICnADDR为0
void system_init_exception(void)
{
// 第一阶段处理,绑定异常向量表
r_exception_reset = (unsigned int)reset_exception;
r_exception_undef = (unsigned int)undef_exception;
r_exception_sotf_int = (unsigned int)sotf_int_exception;
r_exception_prefetch = (unsigned int)prefetch_exception;
r_exception_data = (unsigned int)data_exception;
r_exception_irq = (unsigned int)IRQ_handle;
r_exception_fiq = (unsigned int)IRQ_handle;

// 初始化中断控制器的基本寄存器
intc_init();

}



**-> intc\_init()的函数展开(禁止所有中断源;选择所有中断类型为IRQ;清理VICnADDR寄存器为0)**



// 清除需要处理的中断的中断处理函数的地址
void intc_clearvectaddr(void)
{
// VICxADDR:当前正在处理的中断的中断处理函数的地址
VIC0ADDR = 0;
VIC1ADDR = 0;
VIC2ADDR = 0;
VIC3ADDR = 0;
}

// 初始化中断控制器
void intc_init(void)
{
// 禁止所有中断
// 为什么在中断初始化之初要禁止所有中断?
// 因为中断一旦打开,因为外部或者硬件自己的原因产生中断后一定就会寻找isr
// 而我们可能认为自己用不到这个中断就没有提供isr,这时它自动拿到的就是乱码
// 则程序很可能跑飞,所以不用的中断一定要关掉。
// 一般的做法是先全部关掉,然后再逐一打开自己感兴趣的中断。一旦打开就必须
// 给这个中断提供相应的isr并绑定好。
VIC0INTENCLEAR = 0xffffffff;
VIC1INTENCLEAR = 0xffffffff;
VIC2INTENCLEAR = 0xffffffff;
VIC3INTENCLEAR = 0xffffffff;

// 选择中断类型为IRQ
VIC0INTSELECT = 0x0;
VIC1INTSELECT = 0x0;
VIC2INTSELECT = 0x0;
VIC3INTSELECT = 0x0;

// 清VICxADDR
intc_clearvectaddr();

}



**-> 中断的使能与禁止**


思路是先根据中断号判断这个**中断属于VIC几**,然后在用中断源减去这个**VIC的偏移量**,得到这个中断号在**本VIC中**的偏移量,然后1<<x位,写入相应的VIC的INTENABLE/INTENCLEAR寄存器即可。



// 使能中断
// 通过传参的intnum来使能某个具体的中断源,中断号在int.h中定义,是物理中断号
void intc_enable(unsigned long intnum)
{
unsigned long temp;
// 确定intnum在哪个寄存器的哪一位
// <32就是0~31,必然在VIC0
if(intnum<32)
{
temp = VIC0INTENABLE;
temp |= (1<<intnum); // 如果是第一种设计则必须位操作,第二种设计可以
// 直接写。
VIC0INTENABLE = temp;
}
else if(intnum<64)
{
temp = VIC1INTENABLE;
temp |= (1<<(intnum-32));
VIC1INTENABLE = temp;
}
else if(intnum<96)
{
temp = VIC2INTENABLE;
temp |= (1<<(intnum-64));
VIC2INTENABLE = temp;
}
else if(intnum<NUM_ALL)
{
temp = VIC3INTENABLE;
temp |= (1<<(intnum-96));
VIC3INTENABLE = temp;
}
// NUM_ALL : enable all interrupt
else
{
VIC0INTENABLE = 0xFFFFFFFF;
VIC1INTENABLE = 0xFFFFFFFF;
VIC2INTENABLE = 0xFFFFFFFF;
VIC3INTENABLE = 0xFFFFFFFF;
}

}

// 禁止中断
// 通过传参的intnum来禁止某个具体的中断源,中断号在int.h中定义,是物理中断号
void intc_disable(unsigned long intnum)
{
unsigned long temp;

if(intnum<32)
{
    temp = VIC0INTENCLEAR;
    temp |= (1<<intnum);
    VIC0INTENCLEAR = temp;
}
else if(intnum<64)
{
    temp = VIC1INTENCLEAR;
    temp |= (1<<(intnum-32));
    VIC1INTENCLEAR = temp;
}
else if(intnum<96)
{
    temp = VIC2INTENCLEAR;
    temp |= (1<<(intnum-64));
    VIC2INTENCLEAR = temp;
}
else if(intnum<NUM_ALL)
{
    temp = VIC3INTENCLEAR;
    temp |= (1<<(intnum-96));
    VIC3INTENCLEAR = temp;
}
// NUM_ALL : disable all interrupt
else
{
    VIC0INTENCLEAR = 0xFFFFFFFF;
    VIC1INTENCLEAR = 0xFFFFFFFF;
    VIC2INTENCLEAR = 0xFFFFFFFF;
    VIC3INTENCLEAR = 0xFFFFFFFF;
}

return;

}



**-> 绑定自己实现的isr到VICnVECTADDR**


搞清楚2个寄存器的区别:VICnVECTADDR和VICnADDR.


VICVECTADDR寄存器一共有4×32个,每个中断源都有一个VECTADDR寄存器,我们应该将自己为这个中断源写**的isr地址**丢到这个中断源对应的VECTADDR寄存器中即可。



// 绑定我们写的isr到VICnVECTADDR寄存器
// 绑定过之后我们就把isr地址交给硬件了,剩下的我们不用管了,硬件自己会处理
// 等发生相应中断的时候,我们直接到相应的VICnADDR中去取isr地址即可。
// 参数:intnum是int.h定义的物理中断号,handler是函数指针,就是我们写的isr

// VIC0VECTADDR定义为VIC0VECTADDR0寄存器的地址,就相当于是VIC0VECTADDR0~31这个
// 数组(这个数组就是一个函数指针数组)的首地址,然后具体计算每一个中断的时候
// 只需要首地址+偏移量即可。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数嵌入式工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!

img

img

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以+V:Vip1104z获取!!! (备注:嵌入式)

img

最后

资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!

[外链图片转存中…(img-9QyweP1b-1712230268993)]

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以+V:Vip1104z获取!!! (备注:嵌入式)

img

最后

资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!

更多资料点击此处获qu!!

  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值