c# - 使用单声道等待 UIO 中断

标签 c# linux mono driver

我的问题是如何使用单声道等待 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;
}

最佳答案

根据 this documentation , 读取 4 个字节 block 直到中断并为您提供中断计数作为 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 下降到 native 方法。

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

关于c# - 使用单声道等待 UIO 中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36633752/

相关文章:

linux - 查找 -exec cmd {} + vs | xargs

c# - libvideo获取youtube视频可读流

c# - 我如何在我的 ASP.NET 应用程序中为我的 ListView 使用 ItemCommand 事件

c# - Directory.Delete()/.Create() 是同步的吗?

Java - UnixFileSystem - 列表如何对 child 进行排序?

angularjs - yo angular-fullstack 在本地 linux 上安装失败

c# - 附加到 asp.net masterpage 中的默认标题

macos - Mono 完全忽略 app.config

c# - 如何编译单声道源代码

c# - 使用 Mono API 启动新线程和打开对话框时出错