2016-04-14 34 views
1

Sorum, bir UIO sürücüsü tarafından oluşturulan bir kesintiyi beklemek için mono nasıl kullanabilirim. Gömülü bir sistem için, bir gpio düğmesine basılana kadar okumayı engelleyen bir UIO sürücüsü oluşturdum, bir C programı ile test ettim ve çalışıyor. Nasıl yapılır, sadece/dev/uioX dosyasını okuyarak ve bir kesinti alındığında engelleme okuması bırakılır. Aynı şeyi yapmak istiyorum ama C# kullanarak birisi bana yardım ederse çok teşekkürler. 4 bayt Bir kesme kadar blokları ve size 32 bitlik tamsayı olarak kesinti sayısı verir okuma this documentation göreUIO interrupt için mono beklemeyi kullanma

#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

Kodunuzu sorgunuza ekleyebilir misiniz? –

+0

K, –

cevap

0

.


Bütün bunlardan sonuç alamazsanız

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

, her zaman Mono.Posix dll kullanarak yerel yöntemlere düşebilmektedir.

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

c kodunu ekledi. Bunu kullanarak endişelendiğim soruna rastladım. Ben system.io.ioexception bir istisna alıyorum: win32 IO 25 döndü. Yol/dev/uio0. Bunun nedeni sıfır bayt dosyası olması ve C# 'nun bunu halledebileceğinden emin değilim. –

+0

@nickrudh Hmm, güncel sürümü deneyin. Yine de aynı sorunu olabilir. – piedar

+0

Aynı hata, bu yüzden bir çeşit pinvoke yapmam gerektiğini tahmin ediyorum? Çok aşina değil, şimdi araştırma yapıyor. Bundan kaçınmayı umuyordum. Başka önerileriniz varsa yardım için teşekkürler. –