2016-04-25 113 views
0

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

我用这段代码做了一个自定义的GNU Radio块,但是当执行grc flow python脚本时,我收到/ dev/mem无法访问的错误。

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

我在忽略什么?谢谢。

编辑:添加输出错误是: “权限被拒绝” 如果搭配chmod 777的/ dev后,从sudo的运行/ MEM的错误是: “不允许操作”

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

你应该添加你得到的* verbatim *错误。很确定这与GNU Radio本身无关。 –

+0

该程序正在打印出与本段代码对应的“无法打开/ dev/mem”。我将它标记为GNU无线电问题的原因是,当我调用嵌入在无线电模块中的代码时,我只会遇到这个问题。 '/ *打开/ dev/mem文件*/ fd = open(“/ dev/mem”,O_RDWR);如果(fd <1)printf(“无法打开/ dev/mem \ n”); return -1; }' – gutelfuldead

+0

@MarcusMüllerIE如果我运行[this](http://pastebin.com/tpNjQzbK)我没有问题。只有当我运行嵌入在gnu无线电实现中的同一组代码时。 – gutelfuldead

回答

0

两件事情:

您可以多次打开并重新映射相同的文件以进行读/写访问,而无需在两者之间关闭 - 这是一种灾难。也许你只是用完文件描述符(这是有限制的)。其实读errno(你应该这样做!!)会告诉你的原因。

然后:即使打开反复关闭该文件是一个坏主意,性能明智 - 只是打开它,并在构造函数中一次打开mmap。经常重新打开它没有优势。

+0

谢谢 - 我更新了代码来关闭fd每个读/写以及使所有读取迭代在文件的一个会话中打开。 至于其他接入问题而言,从GNU无线电运行这个时候我得到的输出是: '无法打开的/ dev/MEM,错误:权限denied' 凡拒绝权限是' strerror(errorno)' – gutelfuldead

+0

当我chmod/dev/mem到777并再次运行脚本时,我收到错误:“Operation not permitted” – gutelfuldead