栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

【Linux】ARM篇八--中断实验

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Linux】ARM篇八--中断实验


ARM篇八--中断实验
  • 一、前言
  • 二、准备工作
  • 三、CPU与硬件的交互方式
  • 四、轮询方式实现按键实验
    • 1、电路原图
    • 2、按键的实现
  • 五、RAM中断实现原理
  • 六、GPIO中断
    • 1、GPX1CON
    • 2、EXT_INT41CON寄存器
    • 3、EXT_INT41_MASK寄存器
  • 七、中断控制器
    • 1、ICDDCR寄存器
    • 2、ICDISER寄存器
    • 3、ICDIPTR寄存器
  • 八、中断的实现
    • 1、ICCIAR寄存器
    • 2、EXT_INT41_PEND寄存器
    • 3、ICCEOIR寄存器
  • 九、完整代码与烧入
    • 1、中断完整代码
    • 2、程序烧入步骤
  • 十、实验现象
    • 1、轮询按键实验现象
    • 2、中断按键实验现象


一、前言

本篇使用华清远见的FS4412开发板,进行中断实验,知识包括CPU与硬件的交互方式、中断的原理、中断的实现,本篇通过中断信号的产生,中断信号的传递、中断程序的实现来对中断进行详细讲解。


二、准备工作
  • FS4412开发板,我用的是华清远见的FS4412开发板
  • ubuntu下linux操作系统(包含交叉编译工具)
  • serial-com8程序烧入执行工具
  • 开发板电路原理图、芯片手册
  • 开发程序模板

开发板资料、交叉编译工具、程序烧入工具下载(包含教程)
开发板可选择到华清远见官网进行租赁。
工程模板文件下载


三、CPU与硬件的交互方式
  • 轮询
    CPU执行程序时不断地询问硬件是否需要其服务,若需要则给予其服务,若不需要一段时间后再次询问,周而复始
  • 中断
    CPU执行程序时若硬件需要其服务,对应的硬件给CPU发送中断信号,CPU接收到中断信号后,将当前的程序暂停下来,转而去执行中断服务程序,执行完成后再返回到被打断的点继续执行
  • DMA
    硬件产生数据后,硬件控制器可将产生的数据直接写入到存储器中,整个过程无需CPU的参与

四、轮询方式实现按键实验 1、电路原图



2、按键的实现

在【Linux】ARM篇四–简单使用汇编点亮LED灯这篇文章中以讲述了GPIO寄存器,这里不在讲述,直接上代码,实验现象在文章最末。

#include "exynos_4412.h"

#define LED2_ON (GPX2.DAT |= (1 << 7))    //LED2亮
#define LED2_OFF GPX2.DAT &= (~(1 << 7))  //LED2灭

int main()
{
	int i = 1;
	
	GPX1.CON &= (~(0xF << 8));

	
	GPX2.CON |= (0x1 << 28);

	while(1)
	{
		
		if(!(GPX1.DAT & (1 << 2)))  
		{
			if(i % 2 == 1)
				LED2_ON;
			else
				LED2_OFF;
			while(!(GPX1.DAT & (1 << 2))); //等待手松开按键
			i++;

		}
		else
		{
		
		}
	}
	return 0;
}

五、RAM中断实现原理

由外设硬件产生中断信号,中断信号经过中断控制器传递给CPU处理。

  • Exynos4412的外设硬件产生的中断被视为FIQ或者IRQ的异常信号
  • Exynos4412总共160个中断,包括16个软件生成中断(SGIs)、16个私有外围中断(PPIs)和 128个支持共享外围中断(spi)。
  • Exynos4412有四个CPU处理器,下面中断实验统一将中断信号发送给CPU0

关于RAM的异常处理,在这篇文章中有详细讲解:【Linux】ARM篇二–寄存器组织与异常处理


六、GPIO中断

外设硬件中断的产生方式 可以通过控制相应寄存器产生,这里已GPIO外部引脚中断为例,配置中断的产生。

1、GPX1CON

按键k3是GPX1_2引脚,配置相应位,使引脚为中断模式。


2、EXT_INT41CON寄存器

功能:中断触发方式设置

40-GPX0, 41-GPX1, 42-GPX2, 43-GPX3

GPX1_2引脚对应的是EXT_INT41CON[2],设置该四位为下降沿触发,(根据按键原理图,引脚接高电平,按键按下时,变为引脚电平变为低电平,所以为下降沿)。


3、EXT_INT41_MASK寄存器

功能:中断触发开关

40-GPX0, 41-GPX1, 42-GPX2, 43-GPX3

  • 0:外设中断触发使能
  • 1:外设触发屏蔽

因此配置程序为:

GPX1.CON |= (0xF << 8);


EXT_INT41_CON = EXT_INT41_CON & (~(0x7)) | (0x2 << 8); 


EXT_INT41_MASK &= (~(1 << 2));

七、中断控制器

外设产生的中断信号需要通过中断控制器,才能将信号发送给CPU。

有人会问,为啥不直接把信号传递给CPU?

主要是中断控制器有这些功能:

  • 多个中断同时产生时,可对这些中断挂起排队,然后按照优先级依次发送给CPU处理
  • 可以为每一个中断分配一个优先级
  • 一个中断正在处理时若又产生其它中断,可将新的中断挂起,待CPU空闲时再发送
  • 可以为每一个中断选择一个CPU处理
  • 可以为每一个中断选择一个中断类型(FIQ或IRQ)
  • CPU接收到中断信号后并不能区分是哪个外设产生的,此时CPU可查询中断控制器
  • 来获取当前的中断信号是由哪个硬件产生的,然后再进行对应的处理
    可以打开或禁止每一个中断

可以在(4412手册完整版)SEC_Exynos 4412 SCP_Users Manual_Ver.0.10.00_Preliminary,第749页,找到对应外设中断信号的ID


1、ICDDCR寄存器

功能:中断的总开关

  • 0 : 忽略外部所用中断
  • 1 : 监控外部中断

2、ICDISER寄存器

功能:对应外设中断通道开关


  • 0 :关闭对应通道中断
  • 1 :打开对应通道中断

一个寄存器只有32位,但是我们有160个中断,因此用了5个寄存器来分配相应的中断位。(根据中断ID号寻找对应的位)


3、ICDIPTR寄存器

功能:选择哪个CPU处理中断

  • 只有寄存器只有0-7控制,每一位控制一个寄存器的选择,因此可支持8个CPU处理(8核),对应着CPU0-CPU8
  • 位置1时,选择该位对应的寄存器处理中断,例如:值为0x3时,中断被发送到处理器0和处理器1。
  • 一个寄存器可以控制4个外设中断的选择,有160中断,因此需要40个寄存器控制
    对应表如下:

本实验中断控制器配置程序为:

ICDDCR |= 1;


ICDISER.ICDISER1 |= (1 << 26);


ICDIPTR.ICDIPTR14 = ICDIPTR.ICDIPTR14 & (~(0xFF << 16)) | (0x01 << 16);


CPU0.ICCICR |= 1;
八、中断的实现

ARMCPU对中断的处理跟ARM本身对异常的相应有关,详情看【Linux】ARM篇二–寄存器组织与异常处理RAM异常响应部分。
因此根据异常响应原理,我们在启动文件中,改变和添加相应的代码:


相应代码:

//外部硬件中断处理
IRQ_handler:

SUB LR, LR, #4


STMFD sp!, {R0-R12, LR}


BL do_IRQ


LDMFD sp!, {R0-R12, PC}^

1、ICCIAR寄存器

功能:CPU向中断控制器中获得对应中断ID号

0~9位存放着中断ID号。


2、EXT_INT41_PEND寄存器

功能:中断信号进入中断控制器后,会将相应的挂起并将信号发给CPU,挂起状态需要手动清除,否则会不断将信号发送给CPU。

  • 相应位置1,清除挂起状态。

3、ICCEOIR寄存器

功能通知中断控制器CPU已经执行完中断

  • 0~9位 :写入中断ID。

因此,在interface.c里写中断执行函数:

void do_IRQ()
{
	unsigned int interrupt_id = 0;
	interrupt_id = CPU0.ICCIAR & 0x3FF;  //获得中断id
	switch(interrupt_id)  //选择执行相应的外设中断
	{
		case 0:
			break;
		case 1:
			break;
			// ... ...
		case 58:
			flag++;
			printf("%dn", flag);
			if(flag%2 == 1)
				LED2_ON;
			else
				LED2_OFF;
			
			EXT_INT41_PEND = (1 << 2);   

			
			CPU0.ICCEOIR = CPU0.ICCEOIR & (~0x3FF) | 58;
			break;
			// ... ...
		case 159:
			break;
		default:
			break;
	}
}

九、完整代码与烧入 1、中断完整代码
#include "exynos_4412.h"

#define LED2_ON GPX2.DAT |= (1 << 7)
#define LED2_OFF GPX2.DAT &= (~(1 << 7))
#define LED3_ON GPX1.DAT |= (1 << 0)
#define LED3_OFF GPX1.DAT &= (~(1 << 0))

int flag = 0;

void delay(unsigned int i)
{
	while(i--);
}

void do_IRQ()
{
	unsigned int interrupt_id = 0;
	interrupt_id = CPU0.ICCIAR & 0x3FF;  //获得中断id
	switch(interrupt_id)  //选择执行相应的外设中断
	{
		case 0:
			break;
		case 1:
			break;
			// ... ...
		case 58:
			flag++;
			printf("%dn", flag);
			if(flag%2 == 1)
				LED2_ON;
			else
				LED2_OFF;
			
			EXT_INT41_PEND = (1 << 2);   

			
			CPU0.ICCEOIR = CPU0.ICCEOIR & (~0x3FF) | 58;
			break;
			// ... ...
		case 159:
			break;
		default:
			break;
	}
}

void key3_init()
{
	//外设中断配置
	
	GPX1.CON |= (0xF << 8);

	
	EXT_INT41_CON = EXT_INT41_CON & (~(0x7)) | (0x2 << 8); 

	
	EXT_INT41_MASK &= (~(1 << 2));

	//中断处理器配置
	
	ICDDCR |= 1;

	
	ICDISER.ICDISER1 |= (1 << 26);

	
	ICDIPTR.ICDIPTR14 = ICDIPTR.ICDIPTR14 & (~(0xFF << 16)) | (0x01 << 16);

	
	CPU0.ICCICR |= 1;
	
}

int main()
{
	
	GPX2.CON |= (0x1 << 28);
	GPX1.CON |= (0x1 << 0);
	
	key3_init();

	while(1)
	{
		LED3_ON;
		delay(1000000);
		LED3_OFF;
		delay(1000000);
	}
	return 0;
}

2、程序烧入步骤

1.输入make生成.bin文件


2.将.bin文件复制到共享文件夹





输入:

cp ARM_LED.bin /mnt/hgfs/cca

将文件复制到cc文件夹


3.打开serial-com8,连接开发板(COM2接口),烧入程序
①查看端口

②打开serial-com8设置


③接通开发板电源,迅速按enter键,使其快速进入裸机模式。

④烧入程序

输入:

loadb 40008000

选择可执行文件烧入

烧入成功:


⑤执行程序
输入:

go 40008000


十、实验现象 1、轮询按键实验现象

2、中断按键实验现象


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/838851.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号