我尝试使用/ 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;
}
答案 0 :(得分:0)
两件事:
您可以多次打开并memmap同一个文件进行读/写访问,而不会在两者之间关闭它 - 这是一个灾难的处方。也许你刚刚用完文件描述符(这是有限制的)。实际上阅读public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
{
var principal = Thread.CurrentPrincipal as ClaimsPrincipal;
return base.ExecuteAsync(controllerContext, cancellationToken);
}
(你应该这样做!!)会告诉你原因。
然后:即使打开和重复关闭文件也是一个坏主意,性能明智 - 只需在构造函数中打开并errno
一次。重新开放它没有任何优势。