我的问题是如何使用mono来等待UIO驱动程序生成的中断。我为嵌入式系统创建了一个UIO驱动程序,它将阻止读取,直到按下gpio按钮,我已经用C程序测试它并且它可以工作。如何完成只需读取/ dev / uioX文件,一旦收到中断,就会释放阻塞读取。我想做同样的事情但是使用C#如果有人可以帮助我那将是非常感谢。
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
static void *base_address;
#define GPIO_DATA_OFFSET 0x00
#define GPIO_TRI_OFFSET 0x04
#define GPIO_DATA2_OFFSET 0x08
#define GPIO_TRI2_OFFSET 0x0C
#define GPIO_GLOBAL_IRQ 0x11C
#define GPIO_IRQ_CONTROL 0x128
#define GPIO_IRQ_STATUS 0x120
#define GLOBAL_INTERRUPT_ENABLE 0x80000000
#define GLOBAL_INTERRUPT_DISABLE 0x0
#define IP_INTERRUPT_ENABLE 0x1
#define IP_INTERRUPT_DISABLE 0x0
#define INTERRUPT_CLEAR 0x1
/* GLOBAL VATIABLES */
char* uioFile;
char uioNumber;
/* END GLOBALS */
inline void disable_interrupt()
{
*((volatile unsigned *)(base_address + GPIO_GLOBAL_IRQ)) = GLOBAL_INTERRUPT_DISABLE;
*((volatile unsigned *)(base_address + GPIO_IRQ_CONTROL)) = IP_INTERRUPT_DISABLE;
}
inline void enable_interrupt()
{
*((volatile unsigned *)(base_address + GPIO_GLOBAL_IRQ)) = GLOBAL_INTERRUPT_ENABLE;
*((volatile unsigned *)(base_address + GPIO_IRQ_CONTROL)) = IP_INTERRUPT_ENABLE;
}
inline void clear_interrupt()
{
*((volatile unsigned *)(base_address + GPIO_IRQ_STATUS)) = INTERRUPT_CLEAR;
}
unsigned int gpio_read(void *gpio_base, unsigned int offset)
{
return *((unsigned *)(gpio_base + offset));
}
void wait_for_interrupt(int fd)
{
int pending = 0;
int reenable = 1;
unsigned int reg;
/* block on the file waiting for an interrupt */
read(fd, (void *)&pending, sizeof(int));
reg = gpio_read(gpio_ptr, GPIO_IRQ_STATUS);
if (reg)
clear_interrupt();
/* re-enable the interrupt again now that it's been handled */
write(fd, (void *)&reenable, sizeof(int));
}
unsigned int get_memory_size()
{
FILE *size_fp;
unsigned int size;
char* filePath;
/* open the file that describes the memory range needed to map the GPIO into
* this address space, this is the range of the GPIO in the device tree
*/
size_fp = fopen("/sys/class/uio/uio0/maps/map0/size", "r");
if (!size_fp) {
printf("unable to open the %s size file\n", filePath);
exit(-1);
}
/* Get the size which is an ASCII string such as 0xXXXXXXXX and then be stop
* using the file
*/
fscanf(size_fp, "0x%08X", &size);
fclose(size_fp);
return size;
}
int main(int argc, char *argv[])
{
int fd;
unsigned int size;
printf("UIO test\n");
/* open the UIO device file to allow access to control the device */
fd = open("/dev/uio0", O_RDWR);
if (fd < 1) {
printf("Unable to open %s device file", uioFile);
return -1;
}
/* get the size of the memory to be mapped into this process address space
* and then map it in such that the device memory is accessible
*/
size = get_memory_size();
base_address = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
enable_interrupt();
printf("Enabled Interrupt, waiting for the interrupt\n");
wait_for_interrupt(fd);
printf("interrupt complete\n");
munmap(base_address, size);
close(fd);
return 0;
}
答案 0 :(得分:0)
根据this documentation,读取4个字节的块直到中断,并将中断计数作为32位整数。
using (FileStream f = new FileStream("/dev/uioX", FileMode.Open, FileAccess.Read, FileShare.Read))
using (BinaryReader reader = new BinaryReader(f))
{
int interruptCount = reader.ReadInt32();
}
如果所有其他方法都失败了,您始终可以使用Mono.Posix
dll下拉到本机方法。
using System;
using System.Runtime.InteropServices;
using Mono.Unix.Native;
static class Test
{
static int WaitForInterrupt()
{
byte[] buffer = new byte[4];
GCHandle hBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
int fd = Syscall.open("/dev/uioX", OpenFlags.O_RDONLY);
long result = Syscall.read(fd, hBuffer.AddrOfPinnedObject(), Convert.ToUInt64(buffer.Length));
Syscall.close(fd);
hBuffer.Free();
return BitConverter.ToInt32(buffer, 0);
}
}