User I/Oで割り込み処理

今日はZynq用ドライバを書く?

いや、正確にはUser I/Oで割り込みを使うだな。

#AXIバスを作ろうかなと思ったけど、簡単な方から処理してしまった・・・

DTSは下記のように書く

tgl: tgl@41280000 {

     compatible = "generic-uio";

     reg = <0x41280000 0x10000>;

     interrupt-parent = <&ps7_scugic_0>;

     interrupts = <0 52 0x4>;

};

ここでのinterrupt-parentはxilinxのDevice Tree内のgic名に合わせること。

interruptsの番号はZynqのGICに入っている番号から32を引くこと。

3つめの引数は下記である。

1 = low-to-high edge triggered

2 = high-to-low edge triggered

4 = active high level-sensitive

8 = active low level-sensitive

んで、User I/Oのソースコードが下記になる。

これはaxi_gpioで、Device TreeでUIOを指定しているのデバイスは/dev/uio0になる。

割り込みは

write関数でEnableにして、Readで割り込み待ちをしています。

UIOは割り込みが入るとReadから戻ってくるので特にクリティカルでなければ、UIOで楽ちん割り込み処理ができる。

クリティカルの時はドライバにして、Kernel内で処理をしたほうが良いと思われる。

include

include

include

include

define SIZE 0x1000

define BASE_ADRS 0x41240000

define REG_DATA 0x00

define REG_TRI  0x01

define REG_GIER (0x11C/4)

define REG_IER  (0x128/4)

define REG_ISR  (0x120/4)

void main(){

  int fd;

  unsigned int *buf;

  fd = open("/dev/uio0", O_RDWR),

  if (fd == -1) {

    printf("open "),

    return;

  }

  buf = mmap(NULL, SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0),

  if (buf == MAP_FAILED) {

    printf("mmap "),

    return;

  }

  buf[REG_TRI]  = 0xFF;

//  buf[REG_DATA] = 0xAA;

  buf[REG_GIER] = 0x80000000;

  buf[REG_IER]  = 0x00000001;

//  int data = 0x1;

  write(fd, "1", 4),

  printf("0x%3X: %08x ", REG_GIER, buf[REG_GIER]),

  printf("0x%3X: %08x ", REG_IER, buf[REG_IER]),

  unsigned int ret;

  while(1){

    read(fd, &ret, 4),

    printf("---- "),

    printf("DATA: %08X:%08X(%d) ", buf[REG_DATA], buf[REG_ISR], ret),

    buf[REG_ISR] = 0x1;

    printf("DATA: %08X:%08X(%d) ", buf[REG_DATA], buf[REG_ISR], ret),

    write(fd, "1", 4),

   }

  munmap(buf, SIZE),

  close(fd),

}

write: 2013/10/24/ 02:01:52