1 / 21

GPIO 프로그래밍

GPIO 프로그래밍. PXA270의 GPIO GPIO 동작과 GPIO 레지스터 기능 PXA270과 인터럽트 인터럽트 처리 함수 GPIO를 이용한 디바이스 드라이버 . PXA270 의 GPIO. PXA270 의 GPIO 개요 GPIO(General Purpose Input Output) 는 하나의 연결 단자를 입력이나 출력으로 고정시키지 않고 선택적으로 사용할 수 있게 융통성을 높인 범용 입출력 단자 PXA270 은 121 개의 GPIO 단자를 제공하고 이 중 119 개만 사용 .

wentworth
Télécharger la présentation

GPIO 프로그래밍

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. GPIO 프로그래밍 • PXA270의 GPIO • GPIO 동작과 GPIO 레지스터 기능 • PXA270과 인터럽트 • 인터럽트 처리 함수 • GPIO를 이용한 디바이스 드라이버

  2. PXA270의 GPIO • PXA270의 GPIO 개요 • GPIO(General Purpose Input Output)는 하나의 연결 단자를 입력이나 출력으로 고정시키지 않고 선택적으로 사용할 수 있게 융통성을 높인 범용 입출력 단자 • PXA270은 121개의 GPIO 단자를 제공하고 이 중 119개만 사용. • 각 단자는 입력 혹은 출력으로 설정하거나 부가 기능을 위해 양방향으로 설정. 32비트 레지스터 36개를 사용하여 설정. • GPIO 단자를 입력으로 프로그램하면 인터럽트 소스로 사용 가능 • 일부 GPIO 단자는 프로세서를 휴면 상태에서 깨우는 사건(event)를 생성

  3. GPIO 레지스터 36개

  4. GPIO 단자와 GPIO 레지스터의 관계

  5. GPIO의 전형적인 동작 과정

  6. GPIO 레지스터의 기능 • 입출력 방향 설정 레지스터(GPDR, GPIO Pin Direction Register) • GPIO port pins의 각각에 대한 방향 제어 비트로 구성 • 해당 비트가 0이면 입력, 1이면 출력 • 하드웨어 리셋 후에는 모든 비트가 0로 설정 • 출력 설정 레지스터(GPSR, GPIO Pin Set Register) 및 출력 제거 레지스터(GPCR, GPIO Pin Clear Register) • GPDR에 의하여 출력으로 설정된 경우에만 동작 • 만약 GPDR의 해당 비트가 0으로 설정되어 있을 경우 무영향 • GPSR 혹은 GPCR의 임의 비트에 1을 쓰면 해당 output pin이 set 혹은 clear • GPSR 혹은 GPCR의 임의의 비트에 0을 쓰는 것은 무영향 • write-only register • 상승 에지 검출 허가 레지스터(GRER, GPIO Rising Edge Detect Enable Register) 및 하강 에지 검출 허가 레지스터(GFER, GPIO Falling Edge Detect Enable Register) • 각 GPIO port는 상승천이(rising edge) 혹은 하강천이(falling edge)로 입력을 감지할 수 있도록 프로그램 가능 • GPIO 핀의 천이(transition) 방식을 설정 • edge가 발생하면 status bit가 set • status bits 중 하나가 set될 때 인터럽트를 CPU에 걸거나 혹은 깨어나기 위하여 인터럽트제어기를 프로그램할 수 있음

  7. GPIO 레지스터의 기능(계속) • 에지 입력 검출 레지스터(GEDR, GPIO Edge Detect Status Register) • GRER 혹은 GFER이 설정되었을 때 동작 • 해당 비트가 1이면 GRER 혹은 GFER에 따라 상승천이 혹은 하강천이된 입력이 발생했음을 의미 • 부가 기능 사용 허가 레지스터(GAFR, GPIO Alternate Function Register) • 해당 비트가 0이면 대응하는 pin을 일반적인 I/O, 1이면 특수목적 • 특수 목적에 관련된 기능은 Intel, PXA27x Processor Family Developer’s Manual, 2004 참조 • 단자 상태 검출 레지스터(GPLR, GPIO Pin Level Register) • 각각의 GPIO port pin에 대한 현재 상태를 제공, 즉 현재 pin의 상태가 low 혹은 high인지 표현 • read-only register

  8. 일반적인 인터럽트 처리 과정 • 일반적인 인터럽트 처리 과정

  9. PXA270의 인터럽트 처리 • PXA270의 인터럽트 처리

  10. ICCR이 기본 상태이고 프로세서가 IDLE 상태인지 점검. 혹은 ICMR의 해당 비트가 인터럽트를 금지하는지 점검. 즉, 인터럽트 제어기가 인터럽트 마스크의 상태를 점검하는 것. • 인터럽트가 발생하면 ICPR의 한 비트가 설정됨. 설정되는 비트는 인터럽트를 야기한 입출력 디바이스에 해당. • 발생한 인터럽트와 ①의 결과를 논리적으로 AND 연산을 수행. 즉, 발생한 인터럽트가 ①에 의해 금지되지 않아야 함. • ICLR을 사용해 발생한 인터럽트가 IRQ 혹은 FIQ인지 선택. • 발생한 인터럽트가 IRQ 모드이면 ICIP, FIQ 모드이면 ICFP의 해당 비트를 설정. 따라서 ICIP와 ICFP를 읽으면 발생한 인터럽트의 종류를 알 수 있음. • 주변장치 우선순위 처리기(peripheral priority processor)는 IPR을 참조하여 모든 인터럽트의 우선순위를 결정하며 인터럽트 제어기는 우선순위에 따라 ICHP를 갱신. • 프로세서 코어는 ICHP를 참조하여 가장 높은 우선순위의 인터럽트를 처리

  11. 프로그램 상태 레지스터(CPSR, Current Program Status Register) • IRQ 인터럽트 서비스 준비를 위한 유사 코드

  12. 리눅스 커널의 IRQ 인터럽트 처리

  13. ICPR 레지스터와 IRQ 헤더 파일(<linux>/include/asm-arm/arch-pxa/irqs.h)

  14. 인터럽트처리 함수 • 인터럽트 등록과 해제 • 인터럽트 대기 및 깨우기 #include <linux/interrupt.h> int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *device, void *dev_id); void free_irq(unsigned int irq, void *dev_id); #include <linux/sched.h> // 대기 상태로 만드는 함수 void interruptible_sleep_on(struct wait_queue **q); void sleep_on(struct wait_queue **q); // 대기 상태의 프로세스를 깨우는 함수 void wake_up_interruptible(struct wait_queue **q); void wake_up(struct wait_queue **q);

  15. 대기큐(wait queue) 정의 • 인터럽트 허가와 금지 • 기타 인터럽트 관련 함수 • set_GPIO_IRQ_edge(): GPIO 단자를 사용해 인터럽트 실행 시 감지할 상태를 설정 • set_irq_type(): 인터럽트 종류를 설정 • pxa_gpio_mode(): GPIO 모드 설정 • set_trap_gate(): 소프트웨어 인터럽트인 트랩을 설정 • set_system_gate(), set_intr_gate(): 여러 인터럽트를 설정 DECLARE_WAIT_QUEUE_HEAD(wq)

  16. 타겟 시스템 X-HYPER270-TKU에는 GPIO 35, 41, 36, 37번 단자를 사용하는 4개의 GPIO 버튼을 테스트용으로 제공

  17. 실습 GPIO 디바이스 드라이버 및 테스트 프로그램 작성 001 #include <linux/module.h> …… 016 #define IRQ_KEY1 IRQ_GPIO(35) 017 #define IRQ_KEY2 IRQ_GPIO(41) 018 #define IRQ_KEY3 IRQ_GPIO(36) 019 #define IRQ_KEY4 IRQ_GPIO(37) 020 021 #define LED_PHYS 0x12400000 022 023 static void *mem_base; 024 unsigned long mem_addr, mem_len; 025 026 #define GPIO_MAJOR 241 027 #define GPIO_NAME "GPIO" 028 029 #define GPIO_KEY_READ 0x1000 030 031 #define GPIO_LED1_ON 0x2000 032 #define GPIO_LED2_ON 0x2100 033 #define GPIO_LED3_ON 0x2200 034 #define GPIO_LED4_ON 0x2300 …… 038 char key_buf; 039 char led_on=0xff; 040 041 DECLARE_WAIT_QUEUE_HEAD(key_queue); 042 043 int gpio_open(struct inode *inode, struct file *filp) 044 { 045 printk("%s\n", __func__); 046 return 0; 047 } 048 049 int gpio_release(struct inode *inode, struct file *filp) 050 { 051 printk("%s\n", __func__); 052 return 0; 053 } ……

  18. 실습 GPIO 디바이스 드라이버 및 테스트 프로그램 작성 060 ssize_t gpio_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) 061 { 062 interruptible_sleep_on ( &key_queue); 063 copy_to_user( buf, &key_buf, sizeof(key_buf)); 064 return 0; 065 } 066 067 int gpio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) 068 { 069 int data = 0; 070 071 switch (cmd) { 072 case GPIO_LED1_ON: 073 copy_from_user(&data, (void *)arg, sizeof(data)); 074 if( data == 0) 075 { led_on |= 0x01; 076 (*((volatile unsigned char *)(mem_base))) = led_on;} 077 else 078 { led_on &= 0xfe; 079 (*((volatile unsigned char *)(mem_base))) = led_on;} 080 break; 081 case GPIO_LED2_ON: …… 110 } 111 return 0; 112 } 113 114 static irqreturn_t key_interrupt(int irq, void *dev_id, struct pt_regs *regs) 115 { 116 if(GPLR1 & GPIO_bit(35)) 117 key_buf = 1; 118 if(GPLR1 & GPIO_bit(41)) 119 key_buf = 2; 120 if(GPLR1 & GPIO_bit(36)) 121 key_buf = 3; 122 if(GPLR1 & GPIO_bit(37)) 123 key_buf = 4; 124 wake_up_interruptible(&key_queue); 125 return IRQ_HANDLED; 126 } 127

  19. 실습 GPIO 디바이스 드라이버 및 테스트 프로그램 작성 128 struct file_operations gpio_fops = { 129 .owner = THIS_MODULE, 130 .open = gpio_open, 131 .read = gpio_read, 132 .write = gpio_write, 133 .ioctl = gpio_ioctl, 134 .release = gpio_release, 135 }; 136 137 static int __init gpio_init(void) 138 { 139 int result, ret; 140 141 result = register_chrdev(GPIO_MAJOR, GPIO_NAME, &gpio_fops); 142 mem_addr = LED_PHYS; 143 mem_len = 0x1000; 144 mem_base = ioremap_nocache ( mem_addr, mem_len); 145 if( !mem_base) { 146 printk("Error mapping OHCI memery\n"); 147 release_mem_region(mem_addr, mem_len); 148 return -EBUSY; } 149 (*((volatile unsigned char *)(mem_base))) = (0xFF); 150 set_irq_type(IRQ_KEY1, IRQT_RISING); …… 153 set_irq_type(IRQ_KEY4, IRQT_RISING); 154 if ((ret = request_irq(IRQ_KEY1, key_interrupt, SA_INTERRUPT, "GPIO35_KEY1", NULL))) { 155 printk("failed to register IRQ KEY1\n"); 156 return ret; 157 } …… 166 if ((ret = request_irq(IRQ_KEY4, key_interrupt, SA_INTERRUPT, "GPIO37_KEY4", NULL))) { …… 169 } 170 key_buf = 0; 171 printk("%s MAJOR %d\n", GPIO_NAME, GPIO_MAJOR); 172 173 return 0; 174 }

  20. 실습 GPIO 디바이스 드라이버 및 테스트 프로그램 작성 176 static void __exit gpio_exit(void) 177 { 178 disable_irq(IRQ_KEY1); 179 free_irq(IRQ_KEY1, NULL); …… 184 disable_irq(IRQ_KEY4); 185 free_irq(IRQ_KEY4, NULL); 186 unregister_chrdev(GPIO_MAJOR, GPIO_NAME); 187 } 188 MODULE_LICENSE("GPL"); 189 module_init(gpio_init); 190 module_exit(gpio_exit);

  21. 실습 GPIO 디바이스 드라이버 테스트 프로그램 작성 01 #include <stdio.h> …… 06 #define GPIO_KEY_READ 0x1000 07 #define GPIO_LED1_ON 0x2000 08 #define GPIO_LED2_ON 0x2100 09 #define GPIO_LED3_ON 0x2200 10 #define GPIO_LED4_ON 0x2300 11 12 static char gpio_testDev[] = "/dev/GPIO"; 13 static int gpio_testFd = -1; 14 int ON = 1; …… 17 int main() 18 { 19 char buf; 20 21 if((gpio_testFd = open(gpio_testDev, O_RDWR )) < 0) { 22 perror("open failed /dev/GPIO_TEST\n"); 23 exit(-1); 24 } 25 26 while(1) { 27 read(gpio_testFd , &buf, sizeof(buf)); 28 printf("KEY %x PUSH \n",buf); 29 ON ^= 0x0001; 30 switch(buf) { 31 case 1: 32 ioctl(gpio_testFd , GPIO_LED1_ON, &ON); 33 break; 34 case 2: …… 43 default: break; 44 } 45 } 46 return 0; 47 }

More Related