2016-04-14 4 views
1

Meine Frage ist, wie könnte ich mono auf einen von einem UIO-Treiber erzeugten Interrupt warten. Ich habe einen UIO-Treiber für ein Embedded-System erstellt, der einen Lesevorgang blockiert, bis eine GPIO-Taste gedrückt wird. Ich habe es mit einem C-Programm getestet und es funktioniert. Wie es gemacht wird, ist durch einfaches Lesen der/dev/uioX-Datei und sobald ein Interrupt empfangen wird, wird das blockierende Lesen freigegeben. Ich möchte das gleiche tun, aber mit C#, wenn mir jemand helfen könnte, wäre das großartig, danke.Mono warten auf UIO-Interrupt

#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

Können Sie Ihren Code zu der Frage hinzufügen? –

+0

K hat den c-Code –

Antwort

0

Nach this documentation, Lesen 4 Byte-Blöcke, bis ein Interrupt und gibt Ihnen die Unterbrechungszähler als 32-Bit-Integer.

using (FileStream f = new FileStream("/dev/uioX", FileMode.Open, FileAccess.Read, FileShare.Read)) 
using (BinaryReader reader = new BinaryReader(f)) 
{ 
    int interruptCount = reader.ReadInt32(); 
} 

Wenn alles andere fehlschlägt, können Sie immer auf die Methoden Drop-Down-nativen die Mono.Posix dll verwenden.

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

hinzugefügt. Also habe ich das Problem, um das ich mir Sorgen gemacht habe, in Erfahrung gebracht. Ich bekomme eine Ausnahme von system.io.ioexception: win32 IO zurückgegeben 25. Pfad/dev/uio0. Der Grund dafür ist, dass es eine Null-Byte-Datei ist, und ich bin mir nicht sicher, ob C# damit umgehen kann. –

+0

@nickrudh Hmm, versuchen Sie die aktualisierte Version. Könnte das gleiche Problem haben. – piedar

+0

Derselbe Fehler, also vermute ich, dass ich irgendeinen Pinvoke machen muss? Nicht sehr vertraut damit und forscht jetzt. Hoffte, das zu vermeiden. Danke für die Hilfe, wenn Sie irgendwelche anderen Vorschläge haben, würde ich es schätzen. –