gpio 디바이스드라이버이해artoa.hanbat.ac.kr/lecture_data/embedded_sw/05_old.pdf · hanbat...
TRANSCRIPT
Hanbat National University Prof. Lee Jaeheung
GPIO 디바이스 드라이버 이해
Hanbat National University Prof. Lee Jaeheung
목차
? GPIO( General-Purpose I/O )
– GPIO 특성
– GPIO 레지스터
– GPIO모듈 프로그램 작성
– TEST 프로그램 작성
– Interrupt의 처리과정
– GPIO를 이용한 Interrupt의 구현
Hanbat National University Prof. Lee Jaeheung
GPIO 특성? GPIO Block Diagram
- SA1110은 28개의 GPIO제공
Hanbat National University Prof. Lee Jaeheung
GPIO 레지스터 정리
에지 검출 레지스터GPIO edge detect status register 읽기/쓰기GEDR0x 9004 0018
하강 에지 검출 허가
레지스터
GPIO falling-edge detect register 읽기/쓰기GFER0x 9004 0014
상승 에지 검출 허가
레지스터
GPIO rising-edge detect register 읽기/쓰기GRER0x 9004 0010
출력 clear 레지스터GPIO pin output clear register 쓰기 전용GPCR0x 9004 000C
출력 set 레지스터GPIO pin output set register 쓰기 전용GPSR0x 9004 0008
입출력 방향 설정
레지스터
GPIO pin direction register 읽기/쓰기GPDR0x 9004 0008
핀 상태 검출 레지스터GPIO pin-level register 읽기 전용GPLR0x 9004 0000
설명핀 설명접근이름레지스터 주소
Hanbat National University Prof. Lee Jaeheung
GPLR(GPIO Pin-Level Register)
reserved
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
PL27
PL26
PL25
PL24
PL23
PL22
PL21
PL20
PL19
PL18
PL17
PL16
PL15
PL14
PL13
PL12
PL11
PL10
PL 9
PL 8
PL 7
PL 6
PL 5
PL 4
PL 3
PL 2
PL 1
PL 0
? GPLR - 핀상태 검출 레지스터
?GPIO의 핀에 인가된 전압 레벨 값
?LOW로 인가되면 GPIO 핀에 해당되는 비트가 0
?HIGH로 인가되면 GPIO 핀에 해당되는 비트가 1
?다른 설정 레지스터에 영향을 받지 않음
?RESET시에 어떤 값이 인가 될지 알 수 없음
0 0 0 0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
0h 9004 0000 GPLR Read-Only
Hanbat National University Prof. Lee Jaeheung
GPDR(GPIO Pin Direction Register)
reserved
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
PD27
PD26
PD25
PD24
PD23
PD22
PD21
PD20
PD19
PD18
PD17
PD16
PD15
PD14
PD13
PD12
PD11
PD10
PD 9
PD 8
PD 7
PD 6
PD 5
PD 4
PD 3
PD 2
PD 1
PD 0
? GPDR - 입출력 방향 설정 레지스터
?입/출력을 설정하는 레지스터
?0 이면 입력 전용으로 설정
?1 이면 출력 전용으로 설정
?RESET시에는 클리어
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0h 9004 0004 GPDR Read/Write
Hanbat National University Prof. Lee Jaeheung
GPSR/GPCR(GPIO Pin Set/Clear Register)
reserved
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
PS27
PS26
PS25
PS24
PS23
PS22
PS21
PS20
PS19
PS18
PS17
PS16
PS15
PS14
PS13
PS12
PS11
PS10
PS 9
PS 8
PS 7
PS 6
PS 5
PS 4
PS 3
PS 2
PS 1
PS 0
? GPSR/GPCR - 출력 Set/Clear 레지스터
?GPDR이 출력(‘1’)으로 설정 되어 있을 경우
?0으로 설정한 비트는 이전 상태를 유지
?GPSR : 값을 1로 설정하면 HIGH출력
?GPCR : 값을 1로 설정하면 LOW출력
0h 9004 0008 GPSR Write-Only
reserved
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
PC27
PC26
PC25
PC24
PC23
PC22
PC21
PC20
PC19
PC18
PC17
PC16
PC15
PC14
PC13
PC12
PC11
PC10
PC 9
PC 8
PC 7
PC 6
PC 5
PC 4
PC 3
PC 2
PC 1
PC 0
0h 9004 000C GPCR Write-Only
Hanbat National University Prof. Lee Jaeheung
GRER/GFER(GPIO Rising-Edge/Falling-Edge Detect Register)
reserved
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
RE2
7RE2
6RE2
5RE2
4RE2
3RE2
2RE2
1RE2
0RE1
9RE1
8RE1
7RE1
6RE1
5RE1
4RE1
3RE1
2RE1
1RE1
0RE
9RE
8RE
7RE
6RE
5RE
4RE
3RE
2RE
1RE
0
? GRER/GFER 상승/하강 에지 검출 허가 레지스터?GRER : 입력 핀의 상태가 Low에서 High로 변했을 때
에지 검출 레지스터를 1 로 설정?GFER : 입력 핀의 상태가 High 에서 Low 로 변했을 때
에지 검출 레지스터를 1 로 설정?RESET시에 값이 지정되지 않음
0h 9004 0010 GRER Read/Write
reserved
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
FE27
FE26
FE25
FE24
FE23
FE22
FE21
FE20
FE19
FE18
FE17
FE16
FE15
FE14
FE13
FE12
FE11
FE10
FE 9
FE 8
FE 7
FE 6
FE 5
FE 4
FE 3
FE 2
FE 1
FE 0
0h 9004 0014 GFER Read/Write
0 0 0 0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1 1
0 0 0 0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1 1
Hanbat National University Prof. Lee Jaeheung
GEDR(GPIO Edge Detect Status Register)
reserved
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
ED27
ED26
ED25
ED24
ED23
ED22
ED21
ED20
ED19
ED18
ED17
ED16
ED15
ED14
ED13
ED12
ED11
ED10
ED 9
ED 8
ED 7
ED 6
ED 5
ED 4
ED 3
ED 2
ED 1
ED 0
? GEDR - 에지 검출 레지스터
?레지스터는 GRER이나 GFER의 허가 비트가 설정되어 있을 경우
해당 에지가 발생하면 ‘1’로 설정하여 에지 발생을 표시
?에지가 발생하지 않으면 이전 상태를 유지
?RESET시에 값이 지정되지 않음
0h 9004 0018 GEDR Read/Write
0 0 0 0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Hanbat National University Prof. Lee Jaeheung
GPIO모듈 프로그램#include <linux/module.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#include <linux/kernel.h> /* printk() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <asm/ioctl.h>
#include <asm/segment.h>
#define GPIO_MAJOR 0
int gpio_major=GPIO_MAJOR;
unsigned char data;
int gpio_open (struct inode *inode, struct file *filp
)
{
printk("<1>gpio opened.\n");
MOD_INC_USE_COUNT; // 모듈을 관리하는 변수값수의
증가
return 0;
}
int gpio_release (struct inode *inode, struct file *filp){
MOD_DEC_USE_COUNT; // 모듈을 관리하는 변수값의 감소printk("<1>gpio closed.\n");return 0;
}
ssize_t gpio_read (struct file *filp, char *buf, size_t count,loff_t *f_pos)
{u_int16_t data =0;GPDR = 0x00; // GPIO DIRECTION 설정 : 입력으로 설정data = ((~GPLR & 0x800) >> 8); // GPIO LEVEL 체크 - : copy_to_user(buf,&data,count);
// read 한 데이터를 사용자 영역의 buffer 공간에 저장return count;
}
ssize_t gpio_write (struct file *filp, const char *buf, size_tcount, loff_t *f_pos)
{// unsigned char data;
copy_from_user(&data,buf,1);GPDR = 0xff000;
Hanbat National University Prof. Lee Jaeheung
GPIO모듈 프로그램switch(data)
{
case '1' :GPCR = GPIO_GPIO12;
break;
case '2' :
GPCR = GPIO_GPIO13;
break;
case '3' :
GPCR = GPIO_GPIO14;
break;
case '4' :
GPCR = GPIO_GPIO15;
break;
case '5' :
GPCR = GPIO_GPIO16;
break;
case '6' :
GPCR = GPIO_GPIO17;
break;
case '7' :
GPCR = GPIO_GPIO18;
break;
case '8' :
GPCR = GPIO_GPIO19;
break;
case '0' :GPCR = 0xff000;break;
case 'z' :GPSR = 0xff000;break;
case 'a' :GPSR = GPIO_GPIO19;break;
case 'b' :GPSR = GPIO_GPIO18;break;
case 'c' :GPSR = GPIO_GPIO17;break;
case 'd' :GPSR = GPIO_GPIO16;break;
case 'e' :GPSR = GPIO_GPIO15;break;
case 'f' :GPSR = GPIO_GPIO14;break;
default :GPSR =0xff000; break;
}return 1;
}
Hanbat National University Prof. Lee Jaeheung
GPIO모듈 프로그램struct file_operations gpio_fops = { // 파일 구조체 정의
read: gpio_read,
write: gpio_write,
open: gpio_open,
release: gpio_release,
};
int init_module(void)
{
int result;
result = register_chrdev(gpio_major, "GPIO", &gpio_fops);
// major number 등록 - 동적 major number할당
if (result < 0) {
printk(KERN_WARNING "gpio: can't get major %d\n",gpio_major);
return result;
}
if (gpio_major == 0) gpio_major = result; /* dynamic */
printk("<1> init module, major number : %d\n", result);
return 0;
}
void cleanup_module(void)
{
unregister_chrdev(gpio_major, "GPIO");
// 모듈 등록
}
Hanbat National University Prof. Lee Jaeheung
test program#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
void delay (int timer){
int i,j;
for(i=0;i<timer;i++)
for(j=0; j<1000;j++);
}
int main(int argc, char **argv)
{
int dev,i;
unsigned char data[1];
dev=open("/dev/GPIO",O_RDWR);
if( dev >=0 )
{
printf("\n\nLED를 점등하려면 버튼을 누르세요.....\n");
while(1){
read(dev, data,2);if(data[0] == 0)break;}data[0] = '0';for(i=0; i<18;i++){
data[0]+=1;write( dev, data, 1 );if (data[0] == '9') data[0] = '0';printf("data = %c\n",data[0]); delay(10000);
} close( dev ); } else
{ fprintf(stderr,"open() failed\n"); exit(-1); }
return 0;}
Hanbat National University Prof. Lee Jaeheung
Interrupt 처리 과정
인터럽트발생
PC
0x18
Vector_IRQ
Vector Tablevector IRQ(){
… …“번호” 추출do_IRQ(번호, … … )… …ret_with_reschedule()
}
do IRQ(int irq, struct pt_regs *regs){
struct irqdesc *descstruct irqaction *action… …desc = irq_desc + irqaction = desc -> actiondo{
action -> handler(irq, action -> dev_id, regs)
action = action->next}while(action)
… …}
xxx_isr(){
인터럽트 서비스 루틴}
request_irq(irq, xxx_isr, *regs){
… …}
… …handler() : xxx_isrnext… … … …
Handler()next
irqaction
irqaction… …
action
irqdesc… …
… …
irq_desc[]
0
1
irq
NR_IRQS
desc
Hanbat National University Prof. Lee Jaeheung
Interrupt 주요 함수? int request_irq(unsigned int irq, void (*handler)(int, void *, struct
pt_regs *), unsigned long flags, const char *device, void *dev_id);
? void free_irq(unsigned int irq, void *dev_id);
– unsigned int irq : 인터럽트 번호
– void (*handler)(int, void *, struct pt_regs *) : 인스톨되는 함수의 포인터
– unsigned long flags : 인터럽트 관리에 관련된 옵션의 비트 마스크
? SA_INTERRUPT : 세트되면 빠른 인터럽트 핸들러 표시, 현대 컴퓨터에서는 별 차이가없기 때문에 구별할 필요는 없음
? SA_SHIRQ : 인터럽트 디바이스 사이에 인터럽트 공유될 수 있다는 신호 표시
? SA_SAMPLE_RANDOM : 세트되면 디바이스가 읽힐 때 난수를 반환하므로 임의의 시점에서 인터럽트 발생
– const char *device : 인터럽트의 소유자를 표시(/proc/interrupt)
– void *dev_id : 공유 인터럽트 라인을 위해 사용 ClientData같은 고유의 식별자
Hanbat National University Prof. Lee Jaeheung
Interrupt program#include <linux/config.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#define INT IRQ_GPIO10
static void interrupt_service_rt(int irq, void * dev_id, struct pt_regs * regs)
{
// interrupt button 이 눌러 졌을 때 처리하는
인터럽트 서비스 루틴
int i=10;
printk("\nInterrpt Service Routine Start..\n");
while(i--){
GPCR |= 0xff000;mdelay(500);GPSR |= 0xff000;mdelay(500);
}printk("\nInterrpt Service Routine END..\n");
}int init_module(void){
int retval;retval = request_irq(INT, &interrupt_service_rt, SA_INTERRUPT,
"Button_IN", NULL);// 인터럽트넘버 , 인터럽트 네임 , 인터럽트플래그, 인터럽트 핸들러 함수 등을 등록
if(retval < 0)printk( KERN_ERR "%s: Request for IRQ %d failed\n", __FUNCTION__,INT );
else {set_GPIO_IRQ_edge (1 << INT, GPIO_RISING_EDGE);enable_irq(INT);
}
return 0;}
void cleanup_module(void){
free_irq(INT, NULL);disable_irq(INT);
}
Hanbat National University Prof. Lee Jaeheung
test program<1> 모든 LED를 점등<2> 모든 LED를 소등
<3> 차례대로 LED를 점등<4> 역순으로 LED를 점등<5> 차례대로 LED를 소등
<6> 역순으로 LED를 소등<q> 종료\n