使用单声道等待UIO中断

时间:2016-04-14 20:51:44

标签: c# linux mono driver

我的问题是如何使用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;
}

1 个答案:

答案 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);
    }
}