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() 替代完全禁用时钟中断,以保持系统基本功能运作。

相关推荐
AOI小白新手上路19 分钟前
江科协51单片机 17-2 红外遥控电机调速实验调试总结
单片机·嵌入式硬件·51单片机
oshan20122 小时前
零基础STM32入门教程--10-PWM 呼吸灯
stm32·单片机·嵌入式硬件
记帖3 小时前
STM32C5A3R开发(7)----ADC电压采集
嵌入式硬件·adc·dac·stm32cubeide·stm32c5·stm32cubemx2·stm32c5a3rgt6
自小吃多5 小时前
器件移动、旋转、镜像、对齐、等间距操作笔记
笔记·嵌入式硬件
jianqiang.xue6 小时前
智能体整体架构设计:四大模块与目录组织
单片机·嵌入式硬件·物联网·架构·esp32
东莞市永盛电气8 小时前
三相208V变380V变压器,出海工业设备供电适配方案
python·单片机·嵌入式硬件
Learn-Share_HY9 小时前
[IT Network]如何配置反向路徑過濾器(rp_filter),以解決路由不對稱問題?
linux·嵌入式硬件·物联网·网络协议·tcp/ip·http·iot
深圳市宝华视联10 小时前
医院内网部署手术示教系统注意事项
嵌入式硬件·实时互动·音视频·实时音视频·视频编解码·嵌入式实时数据库
星河单片机10 小时前
STM32驱动Y01-3IN1空气质量模块+OLED显示完整教程
stm32·单片机·嵌入式硬件·空气质量·甲醛检测·二氧化碳检测·tvoc检测
宣宣猪的小花园.10 小时前
【控制算法】PID 不只是三个参数:比例、积分、微分各在解决什么问题
人工智能·嵌入式硬件·机器学习