当前位置: 首页 > news >正文

U-Boot 中增加 GIC-400中断服务程序

在 U-Boot 中为 GIC-400(GICv2 架构)添加中断服务程序需要以下关键步骤,这里提供完整实现指南:


步骤 1:启用 U-Boot 中断支持

在板级配置文件(如 include/configs/<board>.h)中添加:


#define CONFIG_USE_IRQ       // 启用中断支持
#define CONFIG_STACKSIZE_IRQ (8 * 1024)  // IRQ 栈大小
#define CONFIG_STACKSIZE_FIQ (4 * 1024)  // FIQ 栈大小

步骤 2:实现 GIC-400 驱动

创建 drivers/irq/gic400.c


#include <common.h>
#include <asm/io.h>
#include <asm/gic.h>// GIC-400 寄存器基址(根据 SoC 文档修改)
#define GICD_BASE 0x2C001000  // Distributor
#define GICC_BASE 0x2C002000  // CPU Interfacevoid gic400_init(void)
{// 1. 初始化 Distributorwritel(0x1, GICD_BASE + GICD_CTLR);  // 使能全局分发// 设置所有中断到 CPU0for (int i = 0; i < 32; i += 4) {writel(0x01010101, GICD_BASE + GICD_ITARGETSR + i);}// 2. 初始化 CPU Interfacewritel(0x1, GICC_BASE + GICC_CTLR);  // 使能 CPU 接口writel(0xF0, GICC_BASE + GICC_PMR);  // 设置优先级阈值
}uint32_t gic400_read_iar(void)
{return readl(GICC_BASE + GICC_IAR);
}void gic400_write_eoir(uint32_t irq)
{writel(irq, GICC_BASE + GICC_EOIR);
}

步骤 3:实现中断处理框架

修改 arch/arm/lib/interrupts.c


#include <asm/gic.h>// 定义最大中断号
#define MAX_IRQS 160// 中断处理函数指针数组
static irq_handler_t irq_handlers[MAX_IRQS];// 注册中断处理函数
void irq_register_handler(int irq, irq_handler_t handler)
{if (irq < MAX_IRQS)irq_handlers[irq] = handler;
}// 主中断处理函数
void do_irq(struct pt_regs *pt_regs)
{uint32_t irq = gic400_read_iar();uint32_t irq_num = irq & 0x3FF;  // 提取中断号if (irq_num < MAX_IRQS && irq_handlers[irq_num]) {irq_handlers[irq_num]();  // 调用注册的处理函数} else {printf("Unhandled IRQ: %u\n", irq_num);}gic400_write_eoir(irq);  // 结束中断
}

步骤 4:集成到启动流程

在板级初始化文件 board/<vendor>/<board>/<board>.c 中添加:


#include <asm/gic.h>void enable_interrupts(void)
{asm volatile("cpsie i");  // 使能 ARM 全局中断
}int interrupt_init(void)
{gic400_init();      // 初始化 GIC-400enable_interrupts(); // 使能中断return 0;
}

在启动序列中调用(修改 common/board_r.c):


static int initr_interrupts(void)
{interrupt_init();return 0;
}INIT_FUNC_WATCHDOG_INIT(initr_interrupts, 0, int, 0)

步骤 5:注册具体中断服务程序

以 GPIO 中断为例(假设中断号=42):


// 在驱动文件中注册
void gpio_irq_handler(void)
{printf("GPIO interrupt triggered!\n");// 添加具体处理逻辑// 清除中断标志...
}void gpio_init(void)
{// 初始化 GPIO 控制器...irq_register_handler(42, gpio_irq_handler);  // 注册中断// 在 GIC 中使能中断uint32_t reg_offset = 42 / 32;uint32_t bit_mask = 1 << (42 % 32);writel(bit_mask, GICD_BASE + GICD_ISENABLER + reg_offset * 4);
}

步骤 6:编译配置

  1. 修改 drivers/irq/Makefile

    
    obj-$(CONFIG_GIC_V2) += gic400.o

  2. 在 Kconfig 中添加配置项:

    
    config GIC_V2bool "GIC-400 Interrupt Controller"depends on USE_IRQdefault y


关键验证步骤

  1. 中断触发测试

    
    => mm 0xGPIO_REG_ADDR 0 0x1  # 模拟触发中断

    观察控制台输出 "GPIO interrupt triggered!"

  2. 寄存器检查

    
    => md.l 0x2C001000 10  # 查看 GICD 状态
    => md.l 0x2C002000 10  # 查看 GICC 状态

  3. 栈溢出防护

    
    #define CONFIG_DEBUG_IRQ_STACK  // 启用栈检查


常见问题解决

  1. 中断无法触发

    • 检查 GICD_CTLR[0] 和 GICC_CTLR[0] 是否置位

    • 确认中断信号是否路由到 CPU0

    • 验证向量表地址是否正确(CONFIG_SYS_EXCEPTION_VECTORS_HIGH

  2. 中断丢失

    
    // 在 do_irq 开头添加
    local_irq_disable();  // 防止嵌套
    // ...处理中断...
    local_irq_enable();   // 退出前恢复

  3. 性能优化

    
    // 使用宏替代函数调用
    #define QUICK_IRQ_HANDLER(name) \
    static void __attribute__((naked)) name(void) \
    { \asm volatile("b 1f"); \asm volatile("1: ..."); \
    }


注意:U-Boot 中断处理应保持极简原则:

  1. 处理时间 < 100μs

  2. 避免内存分配/复杂函数调用

  3. 优先使用轮询模式处理复杂任务

  4. 关键操作完成后立即清除中断标志

完成上述步骤后,可通过 make menuconfig 启用 CONFIG_GIC_V2 并编译测试。实际中断号需根据 SoC 文档确认,典型值:

  • SPI 中断范围:32-1019

  • PPI 中断范围:16-31

  • SGI 中断范围:0-15


文章转载自:
http://anglistics.zzyjnl.cn
http://aegyptus.zzyjnl.cn
http://bugle.zzyjnl.cn
http://belizean.zzyjnl.cn
http://accessorius.zzyjnl.cn
http://backer.zzyjnl.cn
http://cadenza.zzyjnl.cn
http://belittle.zzyjnl.cn
http://catabolize.zzyjnl.cn
http://characterisation.zzyjnl.cn
http://atherosclerotic.zzyjnl.cn
http://arched.zzyjnl.cn
http://britt.zzyjnl.cn
http://casing.zzyjnl.cn
http://bowed.zzyjnl.cn
http://attainment.zzyjnl.cn
http://baal.zzyjnl.cn
http://baggageman.zzyjnl.cn
http://annular.zzyjnl.cn
http://asseveration.zzyjnl.cn
http://beneficiary.zzyjnl.cn
http://acheomycin.zzyjnl.cn
http://bowels.zzyjnl.cn
http://asteroid.zzyjnl.cn
http://chronogram.zzyjnl.cn
http://barre.zzyjnl.cn
http://carding.zzyjnl.cn
http://chantress.zzyjnl.cn
http://backlash.zzyjnl.cn
http://barrable.zzyjnl.cn
http://www.dtcms.com/a/281145.html

相关文章:

  • Copula理论:覆盖相关性分析、极值相依性、回归建模、时间序列预测、贝叶斯网络,R/Python双语言实现+AI编程辅助(科研绘图与结果呈现)
  • Nestjs框架: 数据库多租户模式与动态模块初探
  • Oracle日期时间函数说明及与MySql区别说明
  • 同济医院R语言训练营第三期开讲!上交大张维拓老师主讲
  • RabbitMQ工作流程
  • SQL学习记录01
  • 15.图像 模板轮廓检测
  • 李白周游记50篇
  • linux-develop
  • 基于Alpine构建MySQL镜像
  • 第二阶段-第二章—8天Python从入门到精通【itheima】-129节(MySQL的安装)
  • 【前后端】Node.js 模块大全
  • 巨坑检查无误还报错is not mapped MappingException: Unknown entity:@Entity
  • DeepSWE:通过强化学习扩展训练开源编码智能体
  • 多层 `while` 循环中,`break` 的行为
  • ES2023 新特性解析_数组与对象的现代化操作指南
  • 二分查找栈堆
  • 【C语言进阶】字符函数和字符串函数的内部原理
  • “ModuleNotFoundError“深度解析:Python模块导入问题的终极指南
  • PHP语言基础知识(超详细)第二节
  • OSPFv3中LSA参数
  • dbever 导出数据库表的建表语句和数据插入语句
  • 嵌入式Linux:进程间通信机制
  • AJAX 开发中的注意点
  • ASRPRO系列语音模块(第十天)
  • AI 增强大前端数据加密与隐私保护:技术实现与合规遵
  • Python 程序设计讲义(2):Python 概述
  • pc浏览器页面语音播报功能
  • 多路文件IO的几个模型
  • K-means 聚类在肺炎患者分型中的应用(简单示例)