BOBO's Note

GPIO 본문

Embedded System

GPIO

bobo_hee 2020. 6. 4. 01:51

임베디드 시스템에서 외부 디바이스와 통신할 때 high bandwidth가 필요하지 않은 경우, 주로 사용하는 인터페이스는 다음과 같다.

  •  I2C
  • SPI
  • UART
  • GPIO

GPIO

GPIO는 General Puprpose Input Output의 약자로, pin의 용도를 정해놓지 않고 사용자가 자유롭게 input 또는 output 핀으로 사용할 수 있다. 

 

한편, 보드에서 하나의 pin이 GPIO 외에 I2C와 같이 미리 정의된 기능에 연결되어 있을 수도 있는데, 이를 alternative functionality라고 한다. 핀의 모드를 설정해줌으로써 GPIO 또는 alternative functionality로 사용할 수 있다. 

 

프로세스에서는 Memory Mapped I/O를 통해 GPIO 핀에 접근한다. 

 

Memory Mapped I/O

메모리 영역에 I/O를 위한 레지스터를 할당해놓아서 메모리 영역에 접근하면 I/O 디바이스에 접근할 수 있게 해준다. 특정 메모리 영역에 데이터를 쓰면 외부 I/O 디바이스에 신호가 전달된다. 반대로 I/O 디바이스의 데이터를 메모리 영역에 접근함으로써 읽어올 수 있다.

 

이 방법은 주소 공간 내에 메모리와 I/O가 연속적인 공간을 차지하므로, I/O가 차지하는 만큼 메모리의 주소 공간 크기가 줄어든다. 대신 CPU 및 프로세스 입장에서는 메모리와 I/O가 동일하게 취급되기 때문에 I/O 디바이스에도 load/store 명령어를 통해 접근할 수 있어 로직이 간단하다.

 

ARM, MIPS 아키텍처에서 사용하는 방식이다.

 

cf) I/O Mapped I/O: 메모리와 I/O가 별개의 주소 공간에 할당된다. 따라서 I/O 디바이스에 접근하기 위해서는 별도의 명령어(예. input/output)를 사용해야 한다. Intel 아키텍처에서 사용하는 방식이다.

 

GPIO 제어

보드마다 GPIO를 제어하기 위한 레지스터들이 존재한다. 각 레지스터들은 앞서 말했듯이 Memory Mapped I/O 방식으로 메모리 주소를 갖는다. 따라서 특정 주소에 접근하여 레지스터를 set해주어 GPIO를 제어할 수 있다.

 

라즈베리파이 B+ 모델의 GPIO 레지스터 스펙 문서

위 문서를 살펴보면 GPSET0, GPSET1이라는 레지스터가 존재한다. GPSETn 레지스터는 각 비트마다 GPIO 핀을 담당하고, 이 비트를 set해주면 GPIO 핀 값이 1이 된다.

 

반대로 GPCLRn 레지스터의 임의의 비트를 set해주면 해당하는 GPIO 핀 값이 0이 된다.

 

GPIO 핀 값을 0 또는 1로 설정하기 위해 하나의 레지스터가 아닌 두개의 레지스터로 나누어 설계한 이유는 access 횟수를 줄이기 위해서이다. 만약 하나의 레지스터의 각 비트 값이 그대로 GPIO 핀 값에 반영된다고 한다면, 원하는 비트만 값을 바꿔주기 위해 load → modify → store 과정을 거쳐야 한다. 반면 두 개의 레지스터로 나누어주면 원하는 값에 따라 레지스터에 write, 즉 store만 해주면 된다.

 

라즈베리파이 B+ 모델의 GPFSELn 레지스터의 스펙 문서

위 문서에서 GPFSELn 레지스터는 GPIO 핀의 모드를 설정하는 레지스터이다. 32비트 레지스터에서 3비트씩 하나의 GPIO 핀을 담당한다. 


이처럼 각 레지스터마다, 레지스터 내의 비트마다 담당하는 제어 기능 및 GPIO 핀 번호가 다르다. 그렇지만 word 단위로 접근할 수 있기 때문에 각 비트에 직접적으로 read/write할 수 없다. 따라서 원하는 위치의 비트만 값을 바꿔주기 위해 비트 마스크 연산을 사용한다.

void set_gpio_output_value void gpio_ctr int gpio_nr int value
int
reg_id gpio_nr 32
int
pos gpio_nr 32
if
value
#define GPIO_SET_OFFSET 0x1c
uint32_t
output_set uint32_t gpio_ctr GPIO_SET_OFFSET 0x4 reg_id
*
output_set 0x1 pos
}
else
#define GPIO_CLR_OFFSET 0x28
uint32_t
output_clr uint32_t gpio_ctr GPIO_CLR_OFFSET 0x4 reg_id
*
output_clr 0x1 pos
}
}

'Embedded System' 카테고리의 다른 글

Linux에서의 전력 관리  (0) 2020.06.17
Bare Metal  (0) 2020.06.16
Interrupt Handler  (0) 2020.06.03
Kernel Module과 Device Driver  (0) 2020.05.29
Android Boot Sequence  (0) 2020.05.26
Comments