개발/Xilinx Zynq
axi-gpio uio
slayernoone
2017. 6. 2. 14:29
&axi_gpio_0 {
compatible = "generic-uio";
};
axi_gpio_0: gpio@41200000 {
#gpio-cells = <2>;
compatible = "xlnx,xps-gpio-1.00.a";
gpio-controller ;
reg = <0x41200000 0x10000>;
xlnx,all-inputs = <0x0>;
xlnx,all-inputs-2 = <0x0>;
xlnx,all-outputs = <0x0>;
xlnx,all-outputs-2 = <0x0>;
xlnx,dout-default = <0x00000000>;
xlnx,dout-default-2 = <0x00000000>;
xlnx,gpio-width = <0x18>;
xlnx,gpio2-width = <0x20>;
xlnx,interrupt-present = <0x0>;
xlnx,is-dual = <0x0>;
xlnx,tri-default = <0xFFFFFFFF>;
xlnx,tri-default-2 = <0xFFFFFFFF>;
};
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/mman.h> #include <fcntl.h> #define GPIO_MAP_SIZE 0x10000 #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 volatile int counter; inline void gpio_write(void *gpio_base, unsigned int offset, unsigned int value) { *((volatile unsigned *)(gpio_base + offset)) = value; } inline unsigned int gpio_read(void *gpio_base, unsigned int offset) { return *((volatile unsigned *)(gpio_base + offset)); } unsigned int get_memory_size(char *sysfs_path_file) { FILE *size_fp; unsigned int size; // open the file that describes the memory range size that is based on the // reg property of the node in the device tree size_fp = fopen(sysfs_path_file, "r"); if (!size_fp) { printf("unable to open the uio size file\n"); 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; } void wait_for_interrupt(int fd, void *gpio_ptr) { int pending = 0; int reenable = 1; unsigned int reg; // block on the file waiting for an interrupt */ read(fd, (void *)&pending, sizeof(int)); counter = counter + 1; // the interrupt occurred for the 1st GPIO channel so clear it reg = gpio_read(gpio_ptr, GPIO_IRQ_STATUS); if (reg) gpio_write(gpio_ptr, GPIO_IRQ_STATUS, 1); // // re-enable the interrupt in the interrupt controller thru the // the UIO subsystem now that it's been handled write(fd, (void *)&reenable, sizeof(int)); } int main() { int uio1_fd; void *ptr; int gpio_size; if ((uio1_fd = open("/dev/uio1", O_RDWR)) < 0) { perror("open uio1"); } else{printf("uio1 opened \n");} gpio_size = get_memory_size("/sys/class/uio/uio1/maps/map0/size"); ptr = mmap(NULL, gpio_size, PROT_READ|PROT_WRITE, MAP_SHARED, uio1_fd, 0); if (ptr == MAP_FAILED) { printf("Mmap call failure.\n"); return -1; } gpio_write(ptr, GPIO_TRI_OFFSET, 0xFF); // GPIO Channel 1 input gpio_write(ptr, GPIO_GLOBAL_IRQ, 0x80000000); // GIER, 31. Bit gpio_write(ptr, GPIO_IRQ_CONTROL, 1); // Channel 1 Interrupt enable //wait for interrupt while(1) { wait_for_interrupt(uio1_fd, ptr); printf("Interrupt: %d", counter); puts(""); } munmap(ptr, gpio_size); return 0; }