You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jetson Xavier上通过Python访问硬件寄存器并生成定时中断

在Jetson Xavier上用Python配置TKE_AON_TIMER_TMR0生成100ms中断

前提准备

  • 必须以root权限运行脚本(硬件寄存器访问需要内核级权限)
  • 对照Jetson Xavier的Tegra技术参考手册(TRM)确认寄存器物理地址,以下示例基于公开标准地址(实际需匹配你的硬件版本):
    • TKE_AON_TIMER_TMR0_TMRCR_0 物理地址:0x0c2a0000
    • TKE_AON_TIMER_TMR0_TMR_RLD_0(重载寄存器):0x0c2a0004
    • TKE_AON_TIMER_TMR0_TMR_CNT_0(计数寄存器):0x0c2a0008
    • TKE_AON_TIMER_INT_ENB(中断使能寄存器):0x0c2a0010

核心逻辑

  1. 内存映射:将寄存器物理地址映射到用户空间,实现Python直接读写
  2. 计算重载值:AON定时器默认使用32768Hz低功耗时钟,100ms对应的计数值为 32768 * 0.1 = 3277(取整)
  3. 配置流程:先禁用定时器→设置递减计数+溢出中断模式→写入重载值→启用定时器并打开中断
  4. 中断响应:绑定中断信号,触发时执行传感器读取逻辑

Python代码示例

import mmap
import os
import signal
import time

# 寄存器地址配置
TKE_AON_TIMER_BASE = 0x0c2a0000
TMRCR_0_OFFSET = 0x00       # TKE_AON_TIMER_TMR0_TMRCR_0
TMR_RLD_0_OFFSET = 0x04     # 重载寄存器
INT_ENB_OFFSET = 0x10       # 中断使能寄存器

# 定时器参数
CLOCK_FREQ = 32768
INTERVAL_MS = 100
RELOAD_VALUE = int(CLOCK_FREQ * (INTERVAL_MS / 1000))
MAP_SIZE = 0x20  # 覆盖所需寄存器范围

# 中断处理函数
def handle_interrupt(signum, frame):
    # 替换为你的传感器读取逻辑
    print(f"[{time.strftime('%H:%M:%S')}] 触发中断,读取传感器数据")
    # 清除中断标志
    mm_regs[INT_ENB_OFFSET] &= ~(1 << 0)

def main():
    global mm_regs
    # 打开/dev/mem并映射寄存器
    with open('/dev/mem', 'r+b') as f:
        mm_regs = mmap.mmap(f.fileno(), MAP_SIZE, offset=TKE_AON_TIMER_BASE, prot=mmap.PROT_READ | mmap.PROT_WRITE)
        
        # 初始化定时器
        mm_regs[TMRCR_0_OFFSET] = 0x00  # 禁用定时器
        # 配置模式:递减计数+溢出中断使能(bit2=中断使能,bit1=0为递减)
        mm_regs[TMRCR_0_OFFSET] = (1 << 2) | (0 << 1)
        # 写入重载值
        mm_regs[TMR_RLD_0_OFFSET] = RELOAD_VALUE.to_bytes(4, byteorder='little')
        # 打开定时器中断
        mm_regs[INT_ENB_OFFSET] |= (1 << 0)
        # 启用定时器
        mm_regs[TMRCR_0_OFFSET] |= (1 << 0)
        
        # 绑定中断信号(需先将硬件中断映射到用户空间信号,示例用SIGUSR1)
        signal.signal(signal.SIGUSR1, handle_interrupt)
        
        print(f"定时器已配置为{INTERVAL_MS}ms中断,等待触发...")
        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            # 清理操作
            mm_regs[TMRCR_0_OFFSET] = 0x00
            mm_regs[INT_ENB_OFFSET] &= ~(1 << 0)
            print("\n已停止定时器")

if __name__ == "__main__":
    if os.geteuid() != 0:
        print("错误:必须以root权限运行脚本(使用sudo)")
        exit(1)
    main()

关键注意事项

  • 地址验证:务必根据你的Jetson型号TRM确认寄存器地址,不同版本可能有差异
  • 中断映射:需先通过sysfs将定时器中断号绑定到用户空间,示例命令(假设中断号为30):
    echo 30 > /proc/sys/kernel/irq/30/smp_affinity
    
  • 系统风险:直接操作硬件寄存器可能导致系统崩溃,测试前备份数据
  • 性能优化:中断处理函数应尽量简短,复杂逻辑可放到单独线程执行

内容的提问来源于stack exchange,提问作者jhorivas07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:50:13