IT/리눅스마스터1급

GPIO

알콩달콩아빠 2022. 5. 3. 18:31
728x90
반응형

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





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에 걸거나 혹은 깨어나기 위하여 인터럽트제어기를 프로그램할 수 있음
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



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





 

#define IRQ_SSP3    PXA_IRQ(0)    /* SSP3 service request */
#define IRQ_MSL    PXA_IRQ(1)    /* MSL Interface interrupt */
#define IRQ_USBH2    PXA_IRQ(2)    /* USB Host interrupt 1 (OHCI) */
#define IRQ_USBH1    PXA_IRQ(3)    /* USB Host interrupt 2 (non-OHCI) */
#define IRQ_KEYPAD    PXA_IRQ(4)    /* Key pad controller */
#define IRQ_MEMSTK    PXA_IRQ(5)    /* Memory Stick interrupt */
#define IRQ_PWRI2C    PXA_IRQ(6)    /* Power I2C interrupt */
#define IRQ_HWUART    PXA_IRQ(7) /* HWUART Transmit/Receive/Error(PXA26x) */
#define IRQ_OST_4_11    PXA_IRQ(7)    /* OS timer 4-11 matches (PXA27x) */
#define IRQ_GPIO0    PXA_IRQ(8)    /* GPIO0 Edge Detect */
#define IRQ_GPIO1    PXA_IRQ(9)    /* GPIO1 Edge Detect */
#define IRQ_GPIO_2_x    PXA_IRQ(10)    /* GPIO[2-x] Edge Detect */
#define IRQ_USB    PXA_IRQ(11)    /* USB Service */

인터럽트 등록과 해제
#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);

대기큐(wait queue) 정의

DECLARE_WAIT_QUEUE_HEAD(wq)
인터럽트 허가와 금지
#include <asm/irq.h>
void disable_irq(int irq);   // 인터럽트 금지
void enable_irq(int irq);   // 인터럽트 해제


기타 인터럽트 관련 함수
set_GPIO_IRQ_edge(): GPIO 단자를 사용해 인터럽트 실행 시 감지할 상태를 설정
set_irq_type(): 인터럽트 종류를 설정
pxa_gpio_mode(): GPIO 모드 설정


set_trap_gate(): 소프트웨어 인터럽트인 트랩을 설정
set_system_gate(), set_intr_gate(): 여러 인터럽트를 설정  

타겟 시스템 X-HYPER270-TKU에는 GPIO 35, 41, 36, 37번  

단자를 사용하는 4개의 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 }
……


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

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 }

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);


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 }  

 

출처 : http://www.google.co.kr/url?sa=t&rct=j&q=GPIO&source=web&cd=4&ved=0CE4QFjAD&url=http%3A%2F%2Fweb.donga.ac.kr%2Fjwjo%2FLectures%2FEmbedded%2F8.GPIO%25ED%2594%2584%25EB%25A1%259C%25EA%25B7%25B8%25EB%259E%2598%25EB%25B0%258D.ppt&ei=9ybqUNC8M-30iwLhxYGACA&usg=AFQjCNF06KwmS21R4T53fGz9D_JUH8-lUg&bvm=bv.1355534169,d.cGE&cad=rjt 

728x90
반응형

'IT > 리눅스마스터1급' 카테고리의 다른 글

SPI  (0) 2022.05.04
I2C  (0) 2022.05.04
Streams  (0) 2022.05.03
Memo Management Unit  (0) 2022.05.03
opengl 1.1 2.0 비교  (0) 2022.05.03