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

内核模块调用get_cycles()失败:未知符号,求ARM平台精确计时方案

问题描述

我需要精确计时以测量工频,参考《Linux设备驱动程序》调用<linux/timex.h>里的get_cycles()函数实现,代码能编译,但执行insmod时报错:

insmod: ERROR: could not insert module ./fmod.ko: Unknown symbol in module

硬件平台为ARM架构的i.MX 6UltraLite应用处理器(Arm® Cortex®-A7内核),系统信息:

root@ts-imx6ul:/home/holden# uname -a                                            
Linux ts-imx6ul 4.1.15-g9c4c55a #2 SMP PREEMPT Wed May 3 15:57:11 PDT 2023 armvx

用到的代码:

#include <linux/module.h>       /* Needed by all modules */
#include <linux/kernel.h>       /* Needed for KERN_INFO */
#include <linux/init.h>         /* Needed for the macros */

#include <linux/timex.h>

static int __init hello_start(void)
{
    printk(KERN_INFO "Loading hello module...\n");
    printk(KERN_INFO "Hello world\n");

    cycles_t time = get_cycles();

    return 0;
}

static void __exit hello_end(void)
{
    printk(KERN_INFO "Goodbye Mr.\n");
}

module_init(hello_start);
module_exit(hello_end);
精确计时方案

一、修复get_cycles()未知符号问题

get_cycles()在ARM架构下并非所有内核版本都导出为模块可用符号,针对你的场景可以直接改用Cortex-A7原生的系统计数器寄存器实现:
Cortex-A7属于ARMv7-A架构,支持读取CNTVCT_EL0寄存器获取系统周期计数,这是通用的高精度计时方式,代码示例如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/arch_timer.h>

static inline cycles_t my_get_cycles(void)
{
    return read_cntvct_el0();
}

static int __init hello_start(void)
{
    printk(KERN_INFO "Loading hello module...\n");
    printk(KERN_INFO "Hello world\n");

    cycles_t time = my_get_cycles();
    printk(KERN_INFO "Current cycle count: %llu\n", (unsigned long long)time);

    return 0;
}

static void __exit hello_end(void)
{
    printk(KERN_INFO "Goodbye Mr.\n");
}

module_init(hello_start);
module_exit(hello_end);
MODULE_LICENSE("GPL");

注意:需确保内核配置中CONFIG_ARM_ARCH_TIMER已启用(i.MX6UL平台默认开启该配置)。

二、其他适用于工频测量的精确计时方案

工频测量需要微秒级及以上精度,以下是几种可靠替代方案:

  • 内核高精度定时器(hrtimer):适合周期性计时或单次高精度延迟,精度可达纳秒级,可用于捕获信号周期。
  • i.MX6UL硬件GPT定时器:直接操作平台自带的通用定时器寄存器,或使用内核提供的定时器API,实现硬件级别的精确计时。
  • ktime系列函数:内核提供的ktime_get()、ktime_get_ns()等函数,返回纳秒级系统时间,适合计算时间差,示例:
#include <linux/ktime.h>

static int __init hello_start(void)
{
    ktime_t start, end;
    s64 delta_ns;

    start = ktime_get();
    // 执行需要计时的操作
    end = ktime_get();

    delta_ns = ktime_to_ns(ktime_sub(end, start));
    printk(KERN_INFO "Time elapsed: %lld ns\n", delta_ns);

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 19:22:50