在ZedBoard上访问GNU Radio的/ dev / mem

时间:2016-04-25 16:10:43

标签: c++ mmap gnuradio

我尝试使用/ 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运行,则错误是:"操作不被允许"

/* -*- 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;
}

1 个答案:

答案 0 :(得分:0)

两件事:

您可以多次打开并memmap同一个文件进行读/写访问,而不会在两者之间关闭它 - 这是一个灾难的处方。也许你刚刚用完文件描述符(这是有限制的)。实际上阅读public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) { var principal = Thread.CurrentPrincipal as ClaimsPrincipal; return base.ExecuteAsync(controllerContext, cancellationToken); } (你应该这样做!!)会告诉你原因。

然后:即使打开重复关闭文件也是一个坏主意,性能明智 - 只需在构造函数中打开并errno一次。重新开放它没有任何优势。

相关问题