今日は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内で処理をしたほうが良いと思われる。
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),
}