linux - I/O 内存访问可以在 Linux (ARM) 下的 ISR 中使用吗?
问题描述
我正在为 Linux 下的 FPGA 通信创建驱动程序。FPGA 通过 GPMC 接口连接。当我从驱动程序上下文测试读/写时 - 一切都完美无缺。但问题是我需要在中断时读取一些地址。所以我创建了中断处理程序,注册它并将 iomemory 读取放入其中(readw 函数)。但是当中断被触发时 - 只读取零。我从上到下测试了驱动程序的每个部分,似乎问题出在 ISR 内部的 iomemory 访问中。当我用常量值替换 io 访问时 - 它成功传递给用户级应用程序。
ARM版本:armv7a(Cortex ARM-A8(DM3730))
编译器:CodeSourcery 2014.05
这是来自驱动程序的一些代码,代表已执行的操作:
// Request physical memory region for FPGA address IO
void* uni_PhysMem_request(const unsigned long addr, const unsigned long size) {
// Handle to be returned
void* handle = NULL;
// Check if memory region successfully requested (mapped to module)
if (!request_mem_region(addr, size, moduleName)) {
printk(KERN_ERR "\t\t\t\t%s() failed to request_mem_region(0x%p, %lu)\n", __func__, (void*)addr, size);
}
// Remap physical memory
if (!(handle = ioremap(addr, size))) {
printk(KERN_ERR "\t\t\t\t%s() failed to ioremap(0x%p, %lu)\n", __func__, (void*)addr, size);
}
// Return virtual address;
return handle;
}
// ...
// ISR
static irqreturn_t uni_IRQ_handler(int irq, void *dev_id) {
size_t readed = 0;
if (irq == irqNumber) {
printk(KERN_DEBUG "\t\t\t\tIRQ handling...\n");
printk(KERN_DEBUG "\t\t\t\tGPIO %d pin is %s\n", irqGPIOPin, ((gpio_get_value(irqGPIOPin) == 0) ? "LOW" : "HIGH"));
// gUniAddr is a struct which holds GPMC remapped virtual address (from uni_PhysMem_request), offset and read size
if ((readed = uni_ReadBuffer_IRQ(gUniAddr.gpmc.addr, gUniAddr.gpmc.offset, gUniAddr.size)) < 0) {
printk(KERN_ERR "\t\t\t\tunable to read data\n");
}
else {
printk(KERN_INFO "\t\t\t\tdata readed success (%zu bytes)\n", readed);
}
}
return IRQ_HANDLED;
}
// ...
// Read buffer by IRQ
ssize_t uni_ReadBuffer_IRQ(void* physAddr, unsigned long physOffset, size_t buffSize) {
size_t size = 0;
size_t i;
for (i = 0; i < buffSize; i += 2) {
size += uni_RB_write(readw(physAddr + physOffset)); // Here readed value sent to ring buffer. When "readw" replaced with any constant - everything OK
}
return size;
}
解决方案
看起来问题出在代码优化中。我更改了 uni_RB_write 函数以传递物理地址和数据大小,现在也通过 ioread16_rep 函数执行读取。所以现在一切正常。
推荐阅读
- caching - 地图上的覆盖图未正确绘制,这是缓存问题吗?
- elasticsearch - _msearch api 无法正常工作
- android - 如何在 Flutter 中对整个应用程序进行圆角处理?
- typescript - 类型“{}”对象上不存在属性“条件”
- javascript - 并行执行命令 - nodejs
- javascript - 如何同步 Highcharts?
- regex - reex 匹配多行 - Golang
- bazel - 构建目标后,我可以让 bazel 触发额外的操作吗?
- ios - 通过单一信号的 VOIP 通知不起作用
- ajax - Laravel 中基于 Axios(Ajax)的 Foursquare API 不返回任何数据(500 内部服务器错误)