【问题标题】:Accessing /dev/mem from GNU Radio on ZedBoard从 ZedBoard 上的 GNU Radio 访问 /dev/mem
【发布时间】:2016-04-26 07:46:33
【问题描述】:

我正在尝试使用 /dev/mem 从 GNU Radio [ZedBoard] 访问自定义 IP 块。我测试了代码例程编写并从本地 c 文件中的 /dev/mem 进行迭代读取。直接从控制台运行的代码正确设置寄存器并读回正确的值。

我使用此代码制作了一个自定义 GNU Radio 块,但在执行 grc flow python 脚本时,我收到 /dev/mem 无法访问的错误。

我知道这不是与设备交互的安全方式,我正在开发驱动程序来替换它。目前我需要这个来进行测试和开发。我什至将 /dev/mem 的权限更改为 777,我也将我的本地用户 (Linaro) 添加到了 kmem 组。我也使用 sudo 执行流程图的 python 文件。

我忽略了什么?谢谢。

编辑:如果在 chmod 777 /dev/mem 之后从 sudo 运行,则添加输出错误为:“Permission Denied”,错误为:“Operation not allowed”

/* -*- c++ -*- */
/* 
 * Copyright 1970 <+YOU OR YOUR COMPANY+>.
 * 
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this software; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gnuradio/io_signature.h>
#include "qpskModulator_impl.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>

#define READ 0
#define WRITE 1

#define SAMPLES 64
#define INPUT_WIDTH 32

int memmap_fpga(int direction, char * address, float value);

namespace gr {
  namespace fpga_accelerators {

    qpskModulator::sptr
    qpskModulator::make()
    {
      return gnuradio::get_initial_sptr
        (new qpskModulator_impl());
    }

    /*
     * The private constructor
     */
    qpskModulator_impl::qpskModulator_impl()
      : gr::block("qpskModulator",
              gr::io_signature::make(1, 1, sizeof(float)),
              gr::io_signature::make(2, 2, sizeof(short)))
    {}

    /*
     * Our virtual destructor.
     */
    qpskModulator_impl::~qpskModulator_impl()
    {
    }

    void
    qpskModulator_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
    {
        ninput_items_required[0] = noutput_items;
        ninput_items_required[1] = noutput_items;
    }

    int
    qpskModulator_impl::general_work (int noutput_items,
                       gr_vector_int &ninput_items,
                       gr_vector_const_void_star &input_items,
                       gr_vector_void_star &output_items)
    {
        const float *in = (const float *) input_items[0];
        short *out0 = (short *) output_items[0]; // I CHANNEL
        short *out1 = (short *) output_items[1]; // Q CHANNEL

        short data_valid;
        const float BLANK = 0;
        float GO = 1;

    //int  hwI_mod[SAMPLES*INPUT_WIDTH/2];
    //int  hwQ_mod[SAMPLES*INPUT_WIDTH/2];
    int i;

    char * DATA_IN_ADDR = "0x43c00004";
    char * GO_ADDR = "0x43c00000";
    char * DATA_OUT_ADDR = "0x43c00008";
    char * DATA_VALID_ADDR = "0x43c0000C";

    // transfer input array and size to FPGA
    memmap_fpga(WRITE, DATA_IN_ADDR, *in);
    memmap_fpga(WRITE, GO_ADDR, GO); // assert go
    GO = 0;
    memmap_fpga(WRITE, GO_ADDR, GO); // reset go value

    data_valid = 0;
    while (data_valid == 0) {
        data_valid = memmap_fpga(READ, DATA_VALID_ADDR, BLANK);
        }

        // read the outputs back from the FPGA  
    unsigned temp_dataout;
    unsigned y;
     for (i=0; i < SAMPLES*INPUT_WIDTH/2 - 8; i++)
     {
     temp_dataout = memmap_fpga(READ, DATA_OUT_ADDR, BLANK);
        out0[i] = temp_dataout & 0xfff; // I channel
        y = out0[i] >> 11;
        if (y == 1)
            out0[i] = out0[i] - 4096;
        out1[i]  =   (temp_dataout >> 12) & 0xfff;
        y = out1[i] >> 11;
        if (y == 1)
             out1[i] = out1[i] - 4096;
        //printf("%d: HW: I_mod = %d and Q_mod = %d\n", i, hwI_mod[i], hwQ_mod[i]); 
    }

        // Do <+signal processing+>
        // Tell runtime system how many input items we consumed on
        // each input stream.
        consume_each (noutput_items);

        // Tell runtime system how many output items we produced.
        return noutput_items;
    }

  } /* namespace fpga_accelerators */
} /* namespace gr */

int memmap_fpga(int direction, char * address, float value){


    unsigned gpio_addr = strtoul(address, NULL, 0);

    /* DEBUG INFO
    printf("address: %08x\n",gpio_addr);
    if (direction == IN)
        printf("direction: IN\n");
    else
        printf("direction: OUT\n");
    printf("value: %d\n",value);
    */

    int fd;
    unsigned page_addr, page_offset;
    void *ptr;
    unsigned page_size=sysconf(_SC_PAGESIZE);
    short temp_value;

        if (gpio_addr == 0) {
            printf("GPIO physical address is required.\n");
            return -1;
        }

    /* Open /dev/mem file */
        fd = open ("/dev/mem", O_RDWR);
        if (fd < 1) {
            printf("Couldn't open /dev/mem\n");
            return -1;
        }


        /* mmap the device into memory */
        page_addr = (gpio_addr & (~(page_size-1)));
        page_offset = gpio_addr - page_addr;
        ptr = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, page_addr);

        if (direction == READ) {
        /* Read value from the device register */
            temp_value = *((unsigned *)(ptr + page_offset));
            //printf("gpio dev-mem test: input: %08x\n",temp_value);
            munmap(ptr, page_size);
            return(temp_value);
        } else {
        /* Write value to the device register */
            *((unsigned *)(ptr + page_offset)) = value;
                munmap(ptr, page_size);
             //printf("Wrote to register\n");
        }


        munmap(ptr, page_size);

return 0;
}

【问题讨论】:

  • 您应该添加您遇到的 verbatim 错误。很确定这与 GNU Radio 本身无关。
  • 程序打印出与这段代码对应的“无法打开/dev/mem”。我将其标记为 GNU Radio 问题的原因是,我仅在调用 Radio 块中嵌入的代码时才会遇到此问题。 /* Open /dev/mem file */ fd = open ("/dev/mem", O_RDWR); if (fd &lt; 1) { printf("Couldn't open /dev/mem\n"); return -1; }
  • @MarcusMüller IE 如果我运行this 我没有问题。只有当我运行嵌入在 gnu radio 实现中的同一组代码时。

标签: c++ mmap gnuradio


【解决方案1】:

两件事:

您多次打开和 memmap 同一个文件以进行读/写访问,而中间没有关闭它——这是灾难的根源。也许您只是用完了文件描述符(对此有限制)。实际上阅读errno(你应该这样做!!)会告诉你原因。

然后:即使反复打开 关闭文件也是一个坏主意,从性能方面来说——只需在构造函数中打开并mmap 一次。不断地重新打开它没有任何好处。

【讨论】:

  • 谢谢 - 我更新了代码以在每次读/写时关闭 fd,并在一个文件打开会话中迭代所有读取。至于其他访问问题,我从 GNU Radio 运行时得到的输出是:Couldn't open /dev/mem, Error: Permission denied 其中 Permission Denied 是 strerror(errorno)
  • 当我 chmod /dev/mem 到 777 并再次运行脚本时,我收到错误:“不允许操作”
猜你喜欢
  • 1970-01-01
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
  • 2014-09-04
  • 1970-01-01
  • 2021-02-14
  • 2017-07-19
  • 1970-01-01
相关资源
最近更新 更多