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