linux 4.14 kernel屏蔽arm arch timer的方法

在 ARMv7 架构的单核 CPU 系统中,完全禁用 coretime 时钟中断(通常是 ARM 私有定时器中断)需要谨慎操作,因为这会导致调度器无法工作,系统可能失去响应。以下是实现方法及注意事项:


方法 1:通过 GIC 屏蔽中断(推荐)

ARM 的时钟中断(通常是 PPI 中断号 30)通过 GIC(Generic Interrupt Controller)管理:

cpp 复制代码
#include <linux/irq.h>

// 获取时钟中断号(通常是30)
#define TIMER_IRQ 30

// 屏蔽中断
void disable_timer_irq(void)
{
    struct irq_desc *desc = irq_to_desc(TIMER_IRQ);
    if (desc) {
        raw_spin_lock_irq(&desc->lock);
        irq_settings_set_disabled(desc);  // 标记为禁用
        desc->irq_data.chip->irq_mask(&desc->irq_data); // 硬件屏蔽
        raw_spin_unlock_irq(&desc->lock);
    }
}

// 恢复中断
void enable_timer_irq(void)
{
    struct irq_desc *desc = irq_to_desc(TIMER_IRQ);
    if (desc) {
        raw_spin_lock_irq(&desc->lock);
        desc->irq_data.chip->irq_unmask(&desc->irq_data);
        irq_settings_clr_disabled(desc);
        raw_spin_unlock_irq(&desc->lock);
    }
}

方法 2:直接操作定时器寄存器

通过 ARM CP15 协处理器控制私有定时器:

cpp 复制代码
// 禁用定时器中断
static void disable_arm_private_timer(void)
{
    u32 ctrl;
    // 读控制寄存器 (CP15 c14)
    asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (ctrl));
    ctrl &= ~(1 << 2);  // 清除中断使能位
    asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (ctrl));
}

// 恢复定时器中断
static void enable_arm_private_timer(void)
{
    u32 ctrl;
    asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (ctrl));
    ctrl |= (1 << 2);  // 设置中断使能位
    asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (ctrl));
}

关键注意事项

  1. 系统稳定性风险

    • 禁用时钟中断后,调度器 (scheduler_tick()) 停止工作

    • 无抢占发生,当前任务将独占 CPU

    • 时间相关功能(jiffiesgettimeofday)停止更新

  2. 必要操作前准备

    cpp 复制代码
    local_irq_save(flags);    // 保存中断状态并禁用所有中断
    preempt_disable();        // 禁用内核抢占
    disable_timer_irq();      // 禁用时钟中断
  3. 恢复操作

    cpp 复制代码
    enable_timer_irq();       // 先恢复时钟中断
    preempt_enable();         // 启用抢占
    local_irq_restore(flags); // 恢复中断状态
  4. 最大禁用时间

    • 典型时钟中断周期 1-10ms

    • 禁用时间不应超过 100ms,否则可能触发看门狗或导致系统不稳定

  5. 替代方案建议

    cpp 复制代码
    // 临时禁用抢占(更安全)
    preempt_disable();
    // 执行关键操作
    preempt_enable();

典型使用场景

  1. 极短时延关键操作

    cpp 复制代码
    unsigned long flags;
    local_irq_save(flags);
    disable_timer_irq();
    
    // 执行时间敏感操作(< 100us)
    asm volatile("nop; nop; ...");
    
    enable_timer_irq();
    local_irq_restore(flags);
  2. 低功耗状态进入前

    cpp 复制代码
    disable_timer_irq();
    wfi();  // 进入WFI状态
    enable_timer_irq(); // 被其他中断唤醒后执行

调试与验证

  1. 检查中断状态:

    bash 复制代码
    cat /proc/interrupts | grep arch_timer
    • 禁用后计数器应停止增长
  2. 监控系统状态:

    bash 复制代码
    perf stat -e irq_vectors:local_timer_entry
  3. 内核日志确认:

    dmesg

    bash 复制代码
    [  123.456] Disabled arch_timer interrupt

重要警告

  1. 避免在用户空间进程中使用 - 仅限内核模块或核心代码

  2. 禁用期间不可调用任何调度相关函数 (如 schedule(), msleep()

  3. 禁止在中断上下文中使用此操作

  4. 多核系统中需配合 get_cpu()/put_cpu() 处理 CPU 亲和性

如非必要,建议使用 preempt_disable()local_irq_disable() 替代完全禁用时钟中断,以保持系统基本功能运作。

相关推荐
清风66666632 分钟前
基于单片机与DAC0832的双路波形信号发生系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
azwsm2 小时前
电路元器件和GPIO控制器
单片机·嵌入式硬件
kebidaixu5 小时前
FreeRTOS 移植到 STM32F407VETX 记录(一)
stm32·单片机·嵌入式硬件
CSDN官方博客5 小时前
「谁说嵌入式只是调包和焊板子?」—— 2026嵌入式全栈技术征锋令
嵌入式硬件·物联网·embedding
点灯小铭6 小时前
基于单片机的数码管定时插座设计与定时开关功能实现
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
云栖梦泽6 小时前
玩转RK3506SDK
linux·嵌入式硬件
数智工坊8 小时前
机器人四大主控板系统分层选型指南:树莓派、ESP32、STM32与Arduino的能力边界与实战定位
stm32·嵌入式硬件·机器人
进击的小头9 小时前
第8篇:IGBT 从零到精通:核心原理、关键参数、选型指南与工业级应用要点
经验分享·嵌入式硬件·学习
点灯小铭9 小时前
基于单片机的多模式智能洗衣机设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
项目題供诗9 小时前
STM32-AD单通道&AD多通道(十九)
stm32·单片机·嵌入式硬件