ARM_Linux NOTE_4
Vine Farer
2016.08.11
1、GPIO
———— 详见NOTE_3实例
2、外部中断IRQ
1)Contex-A9共160个中断源(0 ~ 159)
2)整个中断系统,以外部中断为例:
中断源(如:按键中断)—> GIC 中断控制器 —> 内核
中断触发后,中断源将中断请求发给 GIC
GIC 第一级 ICD 中断混合器,获取中断号并按请求选择相应内核来处理
GIC 第二级 ICC接口,Contex-A9四核处理器,每个处理器对应一个ICC
GIC中含中断向量表,选择相应CPU时,要配置寄存器; 160个中断源,每个分配8位地址空间,一共40个32位寄存器存放相关设置; 8位的空间默认最多可选择8个CPU,对应位置一,则选中相应CPU。若同时选中多个CPU,则这些CPU须要竞争; 如57号中断源,(57 + 1) / 4 = 14 余 2,则在推算对应寄存器位置时,找到第 14 行第 2 组的 8 位空间
芯片手册查询(too important! English must be good!)
获得中断源端口,到2.5章pin表中找对应标号
由对应标号到9.9.2的GIC Interrupt Table中找到对应中断号
中断流程中的寄存器配置(code)
GPX1.CON |= (
0xf <<
4);
EXT_INT41_CON = (EXT_INT41_CON & ~(
0xf <<
4)) | (
0x2 <<
4);
EXT_INT41_FLTCON0 |=
1 <<
15;
EXT_INT41_FLTCON0 &= ~(
1 <<
14);
EXT_INT41_MASK &= ~(
1 <<
1);
ICDISR.ICDISR1 &= ~(
1 <<
25);
ICDISER.ICDISER1 |= (
1 <<
25);
ICDIPTR.ICDIPTR14 = (ICDIPTR.ICDIPTR14 & ~(
0xff <<
8)) | (
0b00000001 <<
8);
ICDDCR =
1;
CPU0.ICCICR =
1;
多中断处理(code)
void (*irq_handler[
160])(
void);
void do_irq(
void)
{
int irq_num;
irq_num = CPU0.ICCIAR &
0x3ff;
printf(
"irq_num = %d\n", irq_num);
(*irq_handler[irq_num])();
CPU0.ICCEOIR = (CPU0.ICCEOIR & ~
0x3ff) | irq_num;
}
void key2(
void)
{
mydelay_ms(
30);
if (
0 == (GPX1.DAT & (
1 <<
1)))
printf(
"key2\n");
EXT_INT41_PEND |= (
1 <<
1);
ICDICPR.ICDICPR1 |= (
1 <<
25);
}
void key3(
void)
{
mydelay_ms(
20);
printf(
"key3\n");
EXT_INT41_PEND |= (
1 <<
2);
ICDICPR.ICDICPR1 |= (
1 <<
26);
}
另外,在main函数中加上这几句:
irq_handler[
57] = key2;
...
irq_handler[
58] = key3;
while (
1);
return 0;
3、时钟Timer
Exynos 4412 SCP has five 32-bit Pulse Width Modulation (PWM) timers.
Timer本身输出100M时钟信号
我们可以利用多级分频器和脉宽设置,最终输出所需要的时钟信号
4412 手册 P1292/1295 工作原理图
100M 时钟信号经过两级分频器
第一级系数0~255,第二级可设置系数1、1/2、1/4、1/8、1/16
再经过Control Logic单元 包括:TCNTBn、TCMPBn、TCNTn、TCMPn4个寄存器
1、TCNTBn填计数初值,这个值在Timer工作后会自减,TCMPBn填比较值。
正常情况下: *:If the timer reaches 0, then TCNTBn and TCMPBn registers are loaded into TCNTn and TCMPn. 反之:
若manual update = 1 手动更新, 初值和比较值从TCNTBn、TCMPBn填入到TCNTn、TCMPn。 则Timer从初值开始自减。初值自减到和比较值相等后,执行 * ,会使电平反转一次。 (第一次必须手动更新,因为TCNTn、TCMPn里面可能值为0,无法启动,手动给个值让它开始自减)然后Timer继续减到0,再次出发 * 的操作,电平再次反转。此轮手动更新结束; 之后设置manual update = 0,auto-reload = 1 自动装载。则后面一直自动装载,每减到0,电平翻转。形成再一级的时钟分频。 (可调节比较值改变时钟信号的占空比,输出特定的PWM波)
2、如果开启Timer定时中断,则只要设置一个初值,自动装载,减到 0 ,会触发interrupt request,再去IRQ中断处理函数执行
code(为beep输出稳定而精确的时钟信号)
GPD0.CON = (GPD0.CON & (~(
0xf <<
0))) | (
0x2 <<
0);
PWM.TCFG0 = (PWM.TCFG0 & (~(
0xff <<
0))) | (
99 <<
0);
PWM.TCFG1 = (PWM.TCFG1 & (~(
0xf <<
0))) | (
0b0010 <<
0);
PWM.TCNTB0 =
250 -
1;
PWM.TCMPB0 =
250 /
2;
PWM.TCON = (PWM.TCON & (~(
0xff <<
0))) | (
0b01010 <<
0);
PWM.TCON = (PWM.TCON & (~(
0xff <<
0))) | (
0b01001 <<
0);
转载请注明原文地址: https://ju.6miu.com/read-1295454.html