IMX6UL开发板的GPIO中断实验(二)

        在上一节编写完成中断向量表后,这一节就开始配置具体的IRQ的中断服务函数

        在嵌入式系统或微控制器的编程中,特别是在启动代码(如启动文件或复位中断服务例程)中,处理全局中断(也称为全局中断使能或中断屏蔽位)的方式对于系统的稳定性和可靠性至关重要
        首先在复位中断函数中,关闭全局中断

	Reset_Handler:



		cpsid i   /*关闭全局中断 */


		MRC p15, 0, r0, c1, c0, 0

		bic	r0 , r0, #(0x1 << 12)	/*关闭Icache*/

		bic r0 , r0 ,#(0x1 << 11)	/*关闭分支预测 */

		bic r0 , r0 ,#(0x1 << 2)	/*关闭Dcache */

		bic r0 , r0 ,#( 1 <<  1)	/*关闭对齐 */

		bic r0 , r0 ,#( 1 <<  0)	/*关闭MMU */

		MCR p15, 0 , r0, c1, c0, 0 

        然后再在进入main函数之前,再次打开全局中断

/* 进入SVC模式 */

	mrs r0, cpsr

	bic r0, r0, #0x1f 	/* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 	*/

	orr r0, r0, #0x13 	/* r0或上0x13,表示使用SVC模式					*/

	msr cpsr, r0		/* 将r0 的数据写入到cpsr_c中 					*/

	ldr sp,=0X80200000	/* 设置用户模式下的栈首地址为0X80200000,大小为2MB */


	cpsie i


	b main				/* 跳转到main函数 										*/

        首先,需要了解什么是全局中断,,全局中断是指通过控制一个特定的使能位(或者寄存器)来影响系统对所有中断请求的响应能力。当全局中断被关闭时,系系统将不会响应任何中断请求,即使这些请求被我们配置或者使能。然而如果全局中断被打开时,系统能够正常地响应和处理中断请求
        复位中断是系统启动时首先执行的中断服务例程,用于进行系统的初始化。这个时候关闭全局中断,在复位中断服务函数执行期间,系统正在进行关键的初始化操作,如时钟配置、内存初始化等。如果此时允许中断,中断服务例程可能会与初始化代码产生冲突,导致初始化失败或系统状态不一致。
        然后要在程序进入主函数之前重新打开,全局中断函数

        在之后,出发的所有中断都是在IRQ的中断服务函数中执行,所以现在就要开始编写IRQ中断服务函数,

IRQ_Handler:
	push, {lr}  /*保存lr的地址 */

	push, {r0-r3, r12}

        首先lr指令(Link Register,叫做链接寄存器),push在英文当中也是推、压的意思,所以可以理解位将lr的值压入堆栈中。在我们ARM架构中,lr寄存器用于存储函数调用或中断发生前的返回地址。当从中断处理程序中返回时,这个地址会被用来继续执行被中断的代码。保存lr是为了在中断处理完成后,程序能够正确地返回到原来的执行点
        然后下一条,这条指令将多个寄存器的值压入堆栈中,具体是r0到r3以及r12。这些寄存器在ARM架构中常用于存储函数的参数、返回值和局部变量。可能唯一需要注意的就是这里里面ARM寄存器应该是从r0-r15但是这里为什么只存入了r0-r3和r12,因为其余的寄存器都是它自动将其保存在了栈中,而没有保存的,我们在上面才将其用手动的方式保存


        然后这里先读取CPSR的寄存器,然后同样将他的值存入到R0中,SPSR一个特殊的寄存器,用于在发生异常(如中断)时保存当前程序状态寄存器(CPSR, Current Program Status Register)的内容。CPSR 包含了当前处理器的状态信息,如条件码(如N、Z、C、V标志)、中断禁止位、模式控制位等。
        因此,mrs r0, spsr 这条指令的目的是在发生异常处理之前(或之后,具体取决于上下文),将当前保存的处理器状态信息(即之前CPSR的内容)读取到 r0 寄存器中,以便后续可以对其进行检查或修改。
        同样堆栈常用于通常用于保存临时数据、寄存器或者控制程序的执行流程,这里将之前通过MRS的指令从SPSR读取的值压入当前活动的堆栈中在ARM中通常与堆栈指针(SP, Stack Pointer)寄存器相关联。在执行 push {r0} 指令时,SP寄存器的值会自动减少(向下增长),以在堆栈上为新数据腾出空间,然后 r0 寄存器的值被写入到这个新分配的堆栈位置。
        所以新增的两端代码则表示,将从SPSR寄存器中读取的处理器状态信息保存到 r0 寄存器中,然后将这个信息压入堆栈。用于保存异常发生前的处理器状态,以便在异常处理完成后能够恢复执行。

IRQ_Handler:

	
	push {lr}  /*保存lr的地址 */

	push {r0-r3, r12}

	mrs  r0, spsr

	push {r0}

        接下来我们要读取下面的,CP15的CBAR寄存器,还是需要了解什么是CBAR,点击下面的蓝色链接跳转

        CBAR寄存器(Coprocessor Barrier Address Register),它是协处理器(Coprocessor)的一个特殊寄存器,用于存储中断控制器(GIC,Generic Interrupt Controller)寄存器组的物理地址(或基地址)

        GIC寄存器组偏移0x1000-0x10FFF是分发器,0x2000-0x3FFF对应GIC组中的CPU接口端,知道了这些那有什么作用呢,意味着我们就可以访问GIC控制器了
        其实总结回来就是,CPU需要通过CBAR寄存器来获取GIC(或类似的中断控制器)的基地址。这个基地址是访问GIC寄存器组所有其他寄存器(如分发器、CPU接口端等)的起点,在进行中断处理时,CPU会首先从CBAR寄存器中读取GIC的基地址。
        然后,CPU会根据这个基地址加上适当的偏移量来访问GIC寄存器组中的其他寄存器,目前大概流程

1.  就是当一个中断发生时,CPU会跳转到中断向量表,并执行相应的中断服务例程(ISR)
2.  在ISR中,CPU首先会从CBAR寄存器中读取GIC的基地址。
3.  接着,CPU会从GICC_IAR寄存器中读取中断ID,以确定是哪个中断源触发了中断。
4.  处理完中断后,CPU会将中断ID写入GICC_EOIR寄存器,以标记该中断已被处理

### 关于IMX6ULL开发板的设备树配置 对于IMX6ULL开发板而言,设备树(Device Tree, DT)用于描述硬件特性给操作系统。通过修改和定制设备树源文件(DTS),可以实现对不同外设的支持以及调整现有功能。 #### 创建自定义设备树覆盖层 为了使IMX6ULL支持USB接口FC游戏手柄,在原有基础上创建一个新的dts文件来扩展或更改现有的DTB是非常常见的做法[^1]: ```bash cp arch/arm/boot/dts/imx6ul-14x14-evk.dts my-imx6ul-custom.dts ``` 编辑`my-imx6ul-custom.dts`并加入必要的节点以启用所需的功能。例如,如果要增加对手柄的支持,则可能需要确保相应的GPIO引脚被正确分配,并且指定了合适的中断线。 #### 修改内核配置以便包含新的选项 使用预定义好的defconfig可以帮助快速设置好大部分参数,之后再根据实际需求微调其他细节部分[^2]: ```bash make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- 100ask_imx6ull_defconfig ``` 这一步骤将会把`.config`初始化为目标平台的标准配置状态,从而简化后续操作流程中的复杂度。 #### 测试输入事件处理程序 当完成了上述工作后,还需要验证新添加的手柄能否正常工作。为此可以从主机端移植一些实用工具如`libevdev`和`evtest`来进行调试测试[^3]: ```bash ./configure --prefix=$PWD/../libevdev-1.11.0-build --host=arm-linux-gnueabihf make && make install ``` 以上过程展示了如何针对特定应用场景构建适合自己的Linux发行版镜像及其配套软件包的方法论;同时也强调了理解整个体系结构的重要性——从最底层的物理连接直到最高层次的应用交互逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值