基于ARM Cortex-A8的BeagleBone黑计算时钟周期计 [英] Compute clock cycle count on ARM Cortex-a8 BeagleBone Black

查看:856
本文介绍了基于ARM Cortex-A8的BeagleBone黑计算时钟周期计的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

欲计算时钟周期计数为我的C code内的特定功能,将要被编译并在BeagleBone黑色运行。我不知道我怎么能做到这一点。我搜索了网络,我发现这个指令:

I want to compute the clock cycle count for a specific function inside my c code which is going to be compiled and run on BeagleBone Black. I have no idea how I can do this. I searched over the web and I found this instruction:

在阿戴尔板时钟Read方法:

步骤1:插入内核模块,使用户空间访问PMU计数器。
解压附件arndale_clockread.tar.bz2,这是有Makefile文件和enableccnt.c。在Makefile中改变KERNELDIR你的内核源代码目录例如/ usr / src目录/ Linux内核版本然后运行命令。

Step-1: Inserting kernel module to enable user space access to PMU counters. Untar the attached file "arndale_clockread.tar.bz2" which is having Makefile and enableccnt.c. In Makefile change the "KERNELDIR" with your kernel source directory e.g. /usr/src/linux-kernel-version then run the command.

linaro@linaro-server:~/enableccnt$ make

上面的命令应该给为 enableccnt.ko 输出,这是内核模块以启用PMU计数器用户空间的访问。然后运行命令。

The above command should give output as enableccnt.ko, which is kernel module to enable userspace access to PMU counters. Then run the command.

linaro@linaro-server:~/enableccnt$ sudo insmod enableccnt.ko

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

The following command should show enableccnt module is being inserted in the running kernel.

linaro@linaro-server:~/enableccnt$ lsmod

步骤2:阅读从用户空间应用的计数器。
一旦内核模块被安装。以下功能可以被用来读取计数器

Step-2: Reading the counter from user space applications. Once the kernel module is being setup. Following function can be used to read the counter

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中的样子:

I believe this instruction should be working for any ARMv7 platforms. So, I followed the instruction and change the kernel source directory. This is how the Makefile looks like:

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

现在,当我运行制作,我有这个错误是抱怨 ARM-Linux的gnueabihf-AR

Now, when I run make, I've got this error which is complaining about arm-linux-gnueabihf-ar:

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 ,但它不工作。所以,我不知道我现在该怎么办!

I tried to install arm-linux-gnueabihf-ar but it doesn't work. So, I have no clue what should I do now!

EDIT1 - 正如在评论中提到的,我用我的补充工具链路径进入我的环境变量:

EDIT1- As it is mentioned in comments, I add my toolchain path into my environment variable by using:

export PATH=/path/to/mytoolchain/bin:$PATH

现在我没有得到previous错误。不过,我这有语法错误,我认为它涉及到内核头文件:

And now I don't get previous error. However, I've got this syntax error which I think it relates to the kernel header files:

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

这是我想到的唯一合理的解决办法就是下载内核源代码code。与它的头文件,并尝试重新进行。没有人有任何想法来解决这个问题?

The only reasonable solution that comes to my mind is to download kernel source code with its header files and try to make again. Does anyone have any idea to resolve this issue?

推荐答案

由于可以有沿途许多障碍,是完整的指南如何构建内核模块和用户空间应用程序。

As there can be many obstacles along the way, below is the complete guide how to build that kernel module and user-space application.

首先,你需要下载并安装2工具链:

First of all, you need to download and install 2 toolchains:


  1. 工具链建筑的内核(和内核模块):裸机(EABI)工具链

  2. 工具链构建用户空间应用程序: GNU / Linux的工具链

  1. Toolchain for building kernel (and kernel modules): bare-metal (EABI) toolchain
  2. Toolchain for building user-space application: GNU/Linux toolchain

我建议你使用ARM Linaro的工具链,因为他们是免费,可靠和优化为ARM。 这里你可以选择需要的工具链(以Linaro的工具链部分)。在BeagleBone黑你在默认情况下有小端架构(像大多数的ARMv7处理器),所以下载下两个档案:

I recommend you to use Linaro ARM toolchains, as they are free, reliable and well optimized for ARM. Here you can choose desired toolchains (in "Linaro Toolchain" section). On BeagleBone Black you have little-endian architecture by default (like on most ARMv7 processors), so download next two archives:


  1. Linaro的工具链生成的二进制文件(小端)裸机

  2. Linaro的工具链生成的二进制文件(小端)的Linux

  1. linaro-toolchain-binaries (little-endian) Bare Metal
  2. linaro-toolchain-binaries (little-endian) Linux

下载后,解压这些归档到 /选择目录。

Once downloaded, extract those archives into /opt directory.

首先,你需要找出其中的究竟的内核源代码被用于建造一闪现到你船上的内核。你可以尝试从 rel=\"nofollow\">。或者你可以创建自己的内核,它闪到你的董事会,现在你确切地知道哪些内核版本正在使用中。

First of all, you need to find out which exactly kernel sources were used to build the kernel which flashed to your board. You can try to figure that out (by your board revision) from here. Or you can build your own kernel, flash it to your board, and now you know exactly which kernel version is in use.

总之,你需要下载正确的内核源(对应于内核上的板)。这些源将被用于进一步构建内核模块。如果内核版本不正确,你将有模块加载魔术不匹配错误或类似的东西。

Anyway, you need to download correct kernel sources (which correspond to kernel on your board). Those sources will be used further to build kernel module. If kernel version is incorrect, you will have "magic mismatch" error or something like that on module loading.

我将使用稳定内核从 kernel.org 来源只是引用(它应该是在足够至少建模块)。

I will use stable kernel sources from kernel.org just for references (it should be sufficient at least to build the module).

在你的终端运行下一个命令为内核构建配置shell环境(裸机工具链):

Run next commands in your terminal to configure shell environment (bare-metal toolchain) for kernel building:

$ export PATH=/opt/gcc-linaro-5.1-2015.08-x86_64_arm-eabi/bin:$PATH
$ export CROSS_COMPILE=arm-eabi-
$ export ARCH=arm

使用defconfig您的主板配置的内核(从弓/ ARM / CONFIGS / )。我将使用 omap2plus_defconfig 例如:

$ make omap2plus_defconfig

现在无论是构建整个内核:

Now either build the whole kernel:

$ make -j4

或prepare所需的内核文件构建外部模块:

or prepare needed kernel files for building external module:

$ make prepare
$ make modules_prepare

在第二种情况下,模块不会有依赖列表,也许你需要加载时,它使用强制选项。因此,preferred选项构建整个内核。

In second case the module will not have dependency list and probably you will need to use "force" option when loading it. So the preferred option is building the whole kernel.

注意:在code我会用进一步从这个答案

NOTE: the code I'm gonna use further is from this answer.

首先你需要启用用户空间访问ARM性能计数器(细节的这里)。它只能在内核空间来完成。这里是模块code和的Makefile 你可以用这样做的:

First you need to enable ARM performance counter for user-space access (details are here). It can be done only in kernel-space. Here is the module code and Makefile you can use to do so:

perfcnt_enable.c

#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

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

构建内核模块

从previous步骤中使用配置shell环境,让我们的出口多了一个环境变量:

Build kernel module

Using configured shell environment from previous step, let's export one more environment variable:

$ export KDIR=/path/to/your/kernel/sources/dir

现在只需运行:

$ make

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

在ARM性能计数器在内核空间(由内核模块)功能的,你可以阅读它在用户空间的应用价值。下面是这种应用的例子。

Once ARM performance counter is enabled in kernel-space (by kernel module), you can read its value in user-space application. Here is the example of such application.

perfcnt_test.c

#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

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,你也许可以删除标志,以减少大小的通知结果二进制文件。

Notice that I added -static option just in case if you are using Android etc. If your distro has regular libc, you can probably remove that flag to reduce size of result binary.

prepare shell环境(Linux的工具链):

Prepare shell environment (Linux toolchain):

$ export PATH=/opt/gcc-linaro-5.1-2015.08-x86_64_arm-linux-gnueabihf/bin:$PATH
$ export CROSS_COMPILE=arm-linux-gnueabihf-

构建应用程序:

$ make

输出二进制文件 perfcnt_test


  1. 同时上传内核模块和用户空间应用程序到您的主板。

  2. 加载模块:

  1. Upload both kernel module and user-space application to your board.
  2. Load the module:

# insmod perfcnt_enable.ko


  • 运行应用程序:

  • Run the application:

    # ./perfcnt_test
    


  • 这篇关于基于ARM Cortex-A8的BeagleBone黑计算时钟周期计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆