首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算ARM Cortex-a8 BeagleBone黑的时钟周期计数

计算ARM Cortex-a8 BeagleBone黑的时钟周期计数
EN

Stack Overflow用户
提问于 2015-12-04 04:58:57
回答 1查看 1.9K关注 0票数 2

我希望计算c代码中特定函数的时钟周期计数,该函数将在BeagleBone黑色上编译和运行。我不知道该怎么做。我在网上搜索发现了这样的指令:

阿恩代尔板上的时钟读取方法:

步骤-1:插入内核模块以允许用户空间访问PMU计数器.解压附带的文件“arndale_clockread.tar.bz2”,它具有Makefile和enableccnt.c。在Makefile中,用内核源目录(例如/usr/src/linux-kernel-version )修改“KERNELDIR”,然后运行命令。

代码语言:javascript
复制
linaro@linaro-server:~/enableccnt$ make

上面的命令应该以enableccnt.ko的形式给出输出,它是内核模块,用于支持对PMU计数器的用户空间访问。然后运行命令。

代码语言:javascript
复制
linaro@linaro-server:~/enableccnt$ sudo insmod enableccnt.ko

下面的命令应该显示enableccnt模块被插入到正在运行的内核中。

代码语言:javascript
复制
linaro@linaro-server:~/enableccnt$ lsmod

步骤2:从用户空间应用程序读取计数器的。一旦内核模块被设置。下面的函数可用于读取计数器

代码语言:javascript
复制
static void readticks(unsigned int *result)
{   
  struct timeval t;
  unsigned int cc;
  if (!enabled) {
   // program the performance-counter control-register:
    asm volatile("mcr p15, 0, %0, c9, c12, 0" :: "r"(17));
   //enable all counters.
    asm volatile("mcr p15, 0, %0, c9, c12, 1" :: "r"(0x8000000f));
   //clear overflow of coutners
    asm volatile("mcr p15, 0, %0, c9, c12, 3" :: "r"(0x8000000f));
    enabled = 1;
  }
  //read the counter value.
  asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(cc));
  gettimeofday(&t,(struct timezone *) 0);
  result[0] = cc;
  result[1] = t.tv_usec;
  result[2] = t.tv_sec;
}

我认为这个指令应该适用于任何ARMv7平台。因此,我按照指令并更改内核源目录。Makefile是这样的:

代码语言:javascript
复制
KERNELDIR := /usr/src/linux-headers-3.8.13-bone70

obj-m := enableccnt.o
CROSS=arm-linux-gnueabihf-

all:
        CC=arm-cortex_a15-linux-gnueabihf-gcc $(MAKE) ARCH=arm -C $(KERNELDIR) M=`pwd`  CROSS_COMPILE=$(CROSS) -I/lib/arm-linux-gnueabihf/lib

现在,当我运行make时,我得到了这个错误,它是对arm-linux-gnueabihf-ar的抱怨

代码语言:javascript
复制
CC=arm-cortex_a08-linux-gnueabihf-gcc make ARCH=arm -C /usr/src/linux-headers-3.8.13-bone70 M=`pwd`  CROSS_COMPILE=arm-linux-gnueabihf- -I/lib/arm-linux-gnueabihf/
make[1]: Entering directory `/usr/src/linux-headers-3.8.13-bone70'
  LD      /root/crypto_project/Arndale_enableccnt/built-in.o
/bin/sh: 1: arm-linux-gnueabihf-ar: not found
make[2]: *** [/root/crypto_project/Arndale_enableccnt/built-in.o] Error 127
make[1]: *** [_module_/root/crypto_project/Arndale_enableccnt] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.8.13-bone70'
make: *** [all] Error 2

我试着安装arm-linux-gnueabihf-ar,但它不起作用。所以,我不知道我现在该怎么做!

正如注释中提到的EDIT1 1-,我使用以下方法将工具链路径添加到环境变量中:

代码语言:javascript
复制
export PATH=/path/to/mytoolchain/bin:$PATH

现在我不知道以前的错误了。但是,我发现了这个语法错误,我认为它与内核头文件有关:

代码语言:javascript
复制
CC=arm-cortex_a15-linux-gnueabihf-gcc make ARCH=arm -C /usr/src/linux-headers-3.8.13-bone70 M=`pwd`  CROSS_COMPILE=arm-linux-gnueabihf- -I/lib/arm-linux-gnueabihf/bin
/root/gcc-linaro-arm-linux-gnueabihf-4.7-2012.11-20121123_linux/bin/arm-linux-gnueabihf-gcc: 1: /root/gcc-linaro-arm-linux-gnueabihf-4.7-2012.11-20121123_linux/bin/arm-linux-gnueabihf-gcc: Syntax error: "(" unexpected
make[1]: Entering directory `/usr/src/linux-headers-3.8.13-bone70'
  LD      /root/crypto_project/Arndale_enableccnt/built-in.o
/root/gcc-linaro-arm-linux-gnueabihf-4.7-2012.11-20121123_linux/bin/arm-linux-gnueabihf-ar: 1: /root/gcc-linaro-arm-linux-gnueabihf-4.7-2012.11-20121123_linux/bin/arm-linux-gnueabihf-ar: Syntax error: "(" unexpected
make[2]: *** [/root/crypto_project/Arndale_enableccnt/built-in.o] Error 2
make[1]: *** [_module_/root/crypto_project/Arndale_enableccnt] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.8.13-bone70'
make: *** [all] Error 2

我想到的唯一合理的解决方案是下载内核源代码及其头文件,然后再次尝试。有人想办法解决这个问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-12-07 16:58:34

由于在此过程中可能存在许多障碍,下面是如何构建内核模块和用户空间应用程序的完整指南。

工具链

首先,您需要下载并安装两个工具链:

  1. 构建内核(和内核模块)的工具链:裸金属(EABI)工具链
  2. 用于构建用户空间应用程序的工具链:GNU/Linux工具链

我建议您使用Linaro工具链,因为它们是免费的,可靠的,并且很好地优化了ARM。这里您可以选择所需的工具链(在"Linaro“部分)。在BeagleBone Black上,默认情况下您有很少的endian体系结构(就像在大多数ARMv7处理器上一样),所以请下载下面两个档案:

  1. linaro-工具链-二进制文件(小端)裸金属
  2. linaro-工具链-二进制文件(小端) Linux

下载后,将这些档案解压缩到/opt目录中。

核源

首先,您需要知道到底使用了哪些内核源来构建闪烁到您的板上的内核。您可以尝试(通过您的董事会修订)从这里中找出这一点。或者,您可以构建自己的内核,将其闪现到您的板上,现在您可以确切地知道使用的是哪个内核版本。

无论如何,您需要下载正确的内核源(它们对应于您的板上的内核)。这些源将进一步用于构建内核模块。如果内核版本不正确,那么在加载模块时就会出现“神奇的错配”错误或类似的错误。

我将使用来自稳定kernel.org内核源代码作为引用(至少应该足以构建模块)。

构建内核

在终端中运行下一步命令,为内核构建配置shell环境(裸金属工具链):

代码语言:javascript
复制
$ export PATH=/opt/gcc-linaro-5.1-2015.08-x86_64_arm-eabi/bin:$PATH
$ export CROSS_COMPILE=arm-eabi-
$ export ARCH=arm

使用defconfig为您的板配置内核(来自arch/arm/configs/)。例如,我将使用omap2plus_defconfig

代码语言:javascript
复制
$ make omap2plus_defconfig

现在要么构建整个内核:

代码语言:javascript
复制
$ make -j4

或者准备构建外部模块所需的内核文件:

代码语言:javascript
复制
$ make prepare
$ make modules_prepare

在第二种情况下,模块将没有依赖列表,在加载时可能需要使用“强制”选项。因此,首选选项是构建整个内核。

核模块

注意到:我要进一步使用的代码来自这个答案

首先,您需要为用户空间访问启用ARM性能计数器(详细信息为这里)。它只能在内核空间中完成。下面是您可以使用的模块代码和Makefile

perfcnt_enable.c

代码语言:javascript
复制
#include <linux/module.h>

static int __init perfcnt_enable_init(void)
{

    /* Enable user-mode access to the performance counter */
    asm ("mcr p15, 0, %0, C9, C14, 0\n\t" :: "r"(1));

    /* Disable counter overflow interrupts (just in case) */
    asm ("mcr p15, 0, %0, C9, C14, 2\n\t" :: "r"(0x8000000f));

    pr_debug("### perfcnt_enable module is loaded\n");
    return 0;
}

static void __exit perfcnt_enable_exit(void)
{
}

module_init(perfcnt_enable_init);
module_exit(perfcnt_enable_exit);

MODULE_AUTHOR("Sam Protsenko");
MODULE_DESCRIPTION("Module for enabling performance counter on ARMv7");
MODULE_LICENSE("GPL");

Makefile

代码语言:javascript
复制
ifneq ($(KERNELRELEASE),)

# kbuild part of makefile

CFLAGS_perfcnt_enable.o := -DDEBUG
obj-m := perfcnt_enable.o

else

# normal makefile

KDIR ?= /lib/modules/$(shell uname -r)/build

module:
    $(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
    $(MAKE) -C $(KDIR) M=$(PWD) clean

.PHONY: module clean

endif

构建内核模块

使用前面步骤中配置的shell环境,让我们再导出一个环境变量:

代码语言:javascript
复制
$ export KDIR=/path/to/your/kernel/sources/dir

现在就跑吧:

代码语言:javascript
复制
$ make

模块构建(perfcnt_enable.ko文件)。

用户空间应用

一旦在内核空间(通过内核模块)启用了ARM性能计数器,您就可以在用户空间应用程序中读取其值。以下是此类应用程序的示例。

perfcnt_test.c

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static unsigned int get_cyclecount(void)
{
    unsigned int value;

    /* Read CCNT Register */
    asm volatile ("mrc p15, 0, %0, c9, c13, 0\t\n": "=r"(value));

    return value;
}

static void init_perfcounters(int32_t do_reset, int32_t enable_divider)
{
    /* In general enable all counters (including cycle counter) */
    int32_t value = 1;

    /* Peform reset */
    if (do_reset) {
        value |= 2; /* reset all counters to zero */
        value |= 4; /* reset cycle counter to zero */
    }

    if (enable_divider)
        value |= 8; /* enable "by 64" divider for CCNT */

    value |= 16;

    /* Program the performance-counter control-register */
    asm volatile ("mcr p15, 0, %0, c9, c12, 0\t\n" :: "r"(value));

    /* Enable all counters */
    asm volatile ("mcr p15, 0, %0, c9, c12, 1\t\n" :: "r"(0x8000000f));

    /* Clear overflows */
    asm volatile ("mcr p15, 0, %0, c9, c12, 3\t\n" :: "r"(0x8000000f));
}

int main(void)
{
    unsigned int overhead;
    unsigned int t;

    /* Init counters */
    init_perfcounters(1, 0);

    /* Measure the counting overhead */
    overhead = get_cyclecount();
    overhead = get_cyclecount() - overhead;

    /* Measure ticks for some operation */
    t = get_cyclecount();
    sleep(1);
    t = get_cyclecount() - t;

    printf("function took exactly %d cycles (including function call)\n",
            t - overhead);

    return EXIT_SUCCESS;
}

Makefile

代码语言:javascript
复制
CC = gcc
APP = perfcnt_test
SOURCES = perfcnt_test.c
CFLAGS = -Wall -O2 -static

default:
    $(CROSS_COMPILE)$(CC) $(CFLAGS) $(SOURCES) -o $(APP)

clean:
    -rm -f $(APP)

.PHONY: default clean

注意,我添加了-static选项,以防使用Android等。如果您的发行版有固定的libc,您可能可以删除该标志以减小结果二进制文件的大小。

构建用户空间应用程序

准备shell环境(Linux工具链):

代码语言:javascript
复制
$ export PATH=/opt/gcc-linaro-5.1-2015.08-x86_64_arm-linux-gnueabihf/bin:$PATH
$ export CROSS_COMPILE=arm-linux-gnueabihf-

构建应用程序:

代码语言:javascript
复制
$ make

输出二进制是perfcnt_test

测试

  1. 上传内核模块和用户空间应用程序到您的董事会。
  2. 加载模块:insmod perfcnt_enable.ko
  3. 运行应用程序:./perfcnt_test
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34081183

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档