ARM

    xiaoxiao2025-01-13  7

    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)

    /************************* * key2 irq_set GPX1_1 * *************************/ GPX1.CON |= (0xf << 4); //WAKEUP_INT1 EXT_INT41_CON = (EXT_INT41_CON & ~(0xf << 4)) | (0x2 << 4); //Falling edge triggered EXT_INT41_FLTCON0 |= 1 << 15; //Enables Filter EXT_INT41_FLTCON0 &= ~(1 << 14); //Delays filter EXT_INT41_MASK &= ~(1 << 1); //Enables Interrupt ICDISR.ICDISR1 &= ~(1 << 25); // The corresponding interrupt is Secure ICDISER.ICDISER1 |= (1 << 25); //Enables the corresponding interrupt 57 ICDIPTR.ICDIPTR14 = (ICDIPTR.ICDIPTR14 & ~(0xff << 8)) | (0b00000001 << 8); //select CPU0 ICDDCR = 1; //monitors the peripheral interrupt signals andforwards pending interrupts to the CPU interfaces. CPU0.ICCICR = 1;

    多中断处理(code)

    void (*irq_handler[160])(void); void do_irq(void) //interrupt handler { int irq_num; irq_num = CPU0.ICCIAR & 0x3ff; //get the interrupt ID printf("irq_num = %d\n", irq_num); (*irq_handler[irq_num])(); CPU0.ICCEOIR = (CPU0.ICCEOIR & ~0x3ff) | irq_num; //The ACKINTID value from the corresponding ICCIAR access } void key2(void) { mydelay_ms(30); if (0 == (GPX1.DAT & (1 << 1))) printf("key2\n"); EXT_INT41_PEND |= (1 << 1); //Interrupt Occurs ICDICPR.ICDICPR1 |= (1 << 25); //The effect depends on whether the interrupt is edge-triggered or level-sensitive } void key3(void) { mydelay_ms(20); printf("key3\n"); EXT_INT41_PEND |= (1 << 2); //Interrupt Occurs ICDICPR.ICDICPR1 |= (1 << 26); //The effect depends on whether the interrupt is edge-triggered or level-sensitive }

    另外,在main函数中加上这几句:

    irq_handler[57] = key2; ... irq_handler[58] = key3; while (1); return 0; // mov pc,lr bx lr


    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); //beep设置为时钟控制模式 PWM.TCFG0 = (PWM.TCFG0 & (~(0xff << 0))) | (99 << 0); // 100M / (99 + 1) = 1MHz PWM.TCFG1 = (PWM.TCFG1 & (~(0xf << 0))) | (0b0010 << 0); // 1M / 4 = 250KHz PWM.TCNTB0 = 250 - 1;// 250K / 250 = 1KHz PWM.TCMPB0 = 250 / 2;// 50%占空比输出 PWM.TCON = (PWM.TCON & (~(0xff << 0))) | (0b01010 << 0); //Stops Timer 0、manual update、auto-reload PWM.TCON = (PWM.TCON & (~(0xff << 0))) | (0b01001 << 0); //Stops Timer 0、auto-reload
    转载请注明原文地址: https://ju.6miu.com/read-1295454.html
    最新回复(0)