Beaglebone Black GPIO 다루기

출처 : http://blog.aiui.com/13


1. 개요


이번 글에서는 BBB에서 GPIO를 다루는 방법을 정리해 두려고 합니다.
BBB에서 GPIO를 다루는 방법은 여러가지가 있으나 본 글에서는 디바이스 트리 오버레이와 sys 가상 디렉토리를 이용해 원하는 핀을 GPIO용으로 설정하고 테스트 하는 가장 기본적인 방법을 설명합니다.

이 글의 내용들은 제가 완전히 이해하고 자신있게 강좌의 개념으로 정리했다기 보다는 '이렇게 사용해 봤습니다' 라는 정도의 수준이고, 제 자신의 정리로써의 의미가 더 강하므로 그저 참고만 하시기 바랍니다.

1) GPIO란?


이 글을 보시려는 대부분의 분들이 GPIO에 대해 잘 아시겠으나 혹여라도 생소한 분들을 위해 간단하게만 언급을 하면, 설정에 따라 입력/출력으로 사용할 수 있도록 구성된 IO를 말합니다. 그리고 출력의 경우는 마지막 값을 계속 유지(latch)하고 입력으로 설정하는 경우는 밖으로 부터 주어진 값을 그대로 받아들이기 위해 하이임피던스 상태가 된다고 합니다.

모든 GPIO가 만족하는 것인지는 모르겠으나, BBB의 경우 게다가 각 IO에 Pullup/Pulldown의 종류와 사용 여부도 설정할 수 있습니다.

한마디로 말해서 외부의 센서에서 값을 읽거나 장치를 제어하기 위해 다목적으로 설계된 IO를 말합니다.

좀 더 쉽고 정확한 설명을 위해 참고자료에 링크를 추가했습니다.

2) BBB에서의 GPIO


GPIO의 개념은 차이가 있을 수 없겠으나, BBB에서는 한 가지 언급하고 넘어가야 하는 문제가 있습니다.
BBB의 보드 위에는 세로로 좌우에 46핀 구성의 확장용 핀 헤더 들이 있습니다. 이 헤더들을 보통 P8(우측), P9(좌측)라고 부릅니다. 각 핀은 설정에 따라 8가지 기능을 가지는 구조입니다. 모드0 부터 모드7까지 8가지 모드에 따라 그 기능이 다릅니다. 모든 핀이 GPIO에 사용될 수 있는 것은 아니며 가능한 핀들의 경우도 모드7에서 GPIO로 사용할 수 있습니다. 각 핀이 기본으로 어떤 모드로 설정되어 있는지는 모르겠으나 원하는 핀을 GPIO로 사용하려면 해당 핀을 모드7로 변경해 주어야 합니다.

다음 표는 모드7로 설정했을 때의 P8 헤더의 핀 기능 중 일부입니다.

P8 헤더
Mode7    OffsetName    Pin Pin Name     OffsetMode7
               DGND     1  2  DGND            
gpio1[6] 6  0x018 GPIO1_6  3  4  GPIO1_7  0x01c 7  gpio1[7]
gpio1[2] 2  0x008 GPIO1_2  5  6  GPIO1_3  0x00c 3  gpio1[3]
gpio2[2] 66 0x090 TIMER4   7  8  TIMER7   0x094 67 gpio2[3]
gpio2[5] 69 0x09c TIMER5   9  10 TIMER6   0x098 68 gpio2[4]
gpio1[13]45 0x034 GPIO1_13 11 12 GPIO1_12 0x030 44 gpio1[12]
gpio0[23]23 0x024 EHRPWM2B 13 14 GPIO0_26 0x028 26 gpio0[26]
gpio1[15]47 0x03c GPIO1_15 15 16 GPIO1_14 0x038 46 gpio1[14]
...   .........   .........   ... ......


(완전한 테이블은 글 마지막에 [부록]을 참고 하세요)

이 글에서는, 위의 표에서 초록색으로 표시한 11번 핀을 사용해서 GPIO 테스트를 합니다.

그런데 최근의 리눅스 커널에서 그 '모드 변경'이라는 일을 하기가 간단하지 않아졌습니다. 커널 버전 2.6에선가 부터 등장한 디바이스 트리(Device Tree)라는 개념 때문입니다. 원하는 핀의 모드 변경을 하려면 디바이스 트리 오버레이(Device Tree Overlay)라는 작업을 해야 합니다. 그래서 이 글에서는 디바이스 트리의 개념과 다루는 방법도 간략하게나마 설명합니다.

3) BBB의 GPIO 신호 전압 레벨


최근의 소형 하드웨어 플랫폼들이 고성능화 되면서 I/O에 3.3V의 전압 레벨을 사용하는 방향으로 변하고 있는 것 같습니다. 아마도 메인 칩의 저전력 설계로 동작 전압이 낮아진 것이 이유라고 생각합니다. BBB의 경우도 3.3V I/O 신호 레벨을 사용합니다. GPIO로 제어하는 장치가 3.3V 로 동작 가능하면 상관 없지만 5V를 필요로 하면 중간에 레벨 컨버터(3.3V <=> 5V 변환기)를 사용해야 합니다.

제가 테스트 한 경우도 5V 장치라 레벨 컨버터를 사용했습니다. 저는 Rorze 사의 2상 스테퍼 모터 드라이버를 사용해야 했기에 불가피한 경우가 되겠습니다.
몇 개월 전에 구입해 두었던 'NS-LS4' 라는 모델명의 4채널 양방향 레벨 컨버터 모듈을 이용했습니다.

잘못된 전압 레벨을 사용하는 경우, 출력의 경우엔 장치가 제대로 동작하지 않는 정도로 끝날 수 있으나, 입력의 경우는 BBB의 메인 칩이 손상될 수도 있다는 경고가 있으므로 절대 주의해야 합니다.


2. 디바이스 트리


내용이 방대해서 완전한 이해에 이르기까지는 상당한 시간이 필요하고 이런 단편적인 글 하나로 불가능할지도 모르겠습니다.
따라서 여기서는 대략적인 개념과 다음 진행을 위해 필요한 구조만 설명하고 넘어 가려 합니다.

1) 개념


공통적으로 하고있는 설명들을 토대로 정리해 보면 다양한 장치들에 대한 정보을 명시하기 위한 자료 구조라고 합니다.
분위기를 보아하니 임베디드 장치들이 늘어나면서 각 장치들을 운영체제에서 지원하도록 하기 위한 드라이버 제작이 점점 부담스러워졌고 이를 해결하기 위한 방안으로 자연스레 채택을 하게 된 것 같습니다.
예전에는 특정 장치를 지원하기 위한 드라이버를 각 운영체제에 맞게 제작해서 장치와 같이 배포하는 구조였다면, 디바이스 트리 구조에서는 프로그램 코드를 제공하지 않고 장치를 잘 설명하는 자료 구조를 작성해서 이를 지원(이해)하는 운영체제에 전달해 운영체제 기동 시 이를 읽어 설정하는 구조로 바꾸려는 것으로 이해했습니다.
결국 운영체제에 범용적인 코드를 작성해 놓고 장치의 정보에 대해 일반화를 잘해서 체계화 된 자료 구조를 전달하는 것으로 보입니다.

2) 구조


먼저, 앞서 말씀드린 것 처럼 운영체제가 장치를 지원하도록 하기 위해 텍스트 문서(.dts)를 사용해 장치에 대한 정보를 기술합니다.
그리고 이 파일을 디바이스 트리 컴파일러(dtc)라고 부르는 툴로 컴파일을 해서 바이너리 파일(.dtb)로 변환합니다.
그렇게 준비된 바이너리 파일을 운영체제에 전달합니다.

     스크립트 작성(.dts)  =>  컴파일(dtc)  =>  바이너리 파일(.dtb)

.dtb 파일을 운영체제에 알려주면 부팅 시 적용하는 개념이지만, Linux에서는 .dtbo 파일로 만들어 /lib/firmware 디렉토리에 모아 놓고 운영중에 아무 때나 적용 및 해제가 가능한 구조입니다.

자세한 방법은 아래 설명합니다.


3) DTS 구조


디바이스 트리는 장치를 설명하는 자료구조라고 했습니다. 실제로 어떻게 설명을 하는 것일까요?
'디바이스 트리 스크립트(Device Tree Script)' 또는 '디바이스 트리 소스(Device Tree Source)' 라고 일컫는 텍스트 형식의 문서에 정해진 문법으로 기술합니다. 일반적으로 .dts 라는 확장자의 파일로 저장합니다.

문법 구조나 명칭들이 상당히 방대해서 규격을 다 봐야 알겠지만, 우선은 BBB의 GPIO를 다루는 데 필수적인 내용만으로 작성된 DTS를 예로 보입니다.

p8_11_out.dts
/dts-v1/;
/plugin/;
 
/{
        compatible = "ti,beaglebone""ti,beaglebone-black";
        part-number = "p8_11_out";
        version = "00A0";
 
        fragment@0 {
                target = <&am33xx_pinmux>;
 
                __overlay__ {
                        pinctrl_test: p8_11_pins {
                                pinctrl-single,pins = <
 
                                        0x034 0x37  /* GPIO1_13, SLEWCTRL_FAST | OUTPUT_PULLUP | MODE7 [gpio45] */
                                >;
                        };
                };
        };
 
        fragment@1 {
                target = <&ocp>;
                __overlay__ {
                        test_helper: helper {
                                compatible = "bone-pinmux-helper";
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_test>;
                                status = "okay";
                        };
                };
        };
 
};


.dts 문법에 대해서는 본인도 잘 모르므로 질문하셔도 답변 못 드릴 겁니다. 보다 깊은 내용은 마지막 부분의 참고자료를 보시기 바랍니다.ㅠㅠ

다만, 중요한 내용은 중간 부분의 0x034 0x37 가 되겠습니다.
Linux kernel 내부에서 am33xx_pinmux가 0x44e10800 값을 가지기 때문에 P8_11을 지정하기 위해 그 offset 주소인 0x034를 사용해야 하며,
저 두 숫자가 핀헤더 P8의 11번 핀을 GPIO로 사용하겠다라는 의미를 가지고 있습니다.


3. DTS 컴파일 및 적용


1) 컴파일


Super-user로 전환

컴파일은 super user가 아니어도 되긴 합니다만, 나머지 과정이 모두 권한을 요구하므로 미리 super user로 전환해 둡니다.

슈퍼 유저 전환
ubuntu@arm:~$ sudo su
root@arm:/home/ubuntu#


컴파일러 준비
root@arm:/home/ubuntu# wget -c https://raw.github.com/RobertCNelson/tools/master/pkgs/dtc.sh
root@arm:/home/ubuntu# chmod +x dtc.sh
root@arm:/home/ubuntu# ./dtc.sh


주의
단순히 apt-get install device-tree-compiler 로 설치를 해도 dtc 가 준비는 됩니다.
이 경우는 일반 ubuntu 버전이 설치되어 BBB용 dts 를 컴파일 할 때 오류가 납니다. 따라서 위의 방법으로 설치를 하셔야 합니다.


컴파일

.dts 를 컴파일해서 .dtbo로 만드는 과정은 다음과 같습니다.

컴파일
root@arm:/home/ubuntu# dtc -I dts -O dtb -o p8_11_out-00A0.dtbo -@ p8_11_out.dts


간단하니 별다른 설명은 필요 없을 것 같지만, 위 예를 보면 .dts와 .dtbo 파일의 이름이 다르게 지정되어 있습니다.
"-00A0" 을 더 붙여서 결과 파일을 만듭니다만, 버전 관리 차원에서 하는 것으로 이해하면 되겠습니다.

주의: .dtbo 파일에 버전(00A0)을 붙일 때 반드시 '-'로 붙여야 합니다. '_' 같은 글자로 붙이면 슬롯에 올릴 때 오류 납니다.

운영체제에 복사

컴파일된 .dtbo 는 운영체제의 특별한 위치로 복사해 줍니다.

DTB 복사
root@arm:/home/ubuntu# cp p8_11_out-00A0.dtbo /lib/firmware


자, 그럼 이제 준비는 끝났습니다. 앞으로는 다음 단계부터 진행해 주면 됩니다.


2) 디바이스 트리 오버레이


준비된 .dtbo 를 적용시키는 과정을 디바이스 트리 오버레이(Device Tree Overlay) 라고 하는 데, 이름에서 알 수 있듯이 커널 내부의 기존 디바이스 트리 위에 새로운 .dtbo를 중첩시켜서 새로운 하드웨어를 추가하거나 기능을 변경하는 것이 아닌가 싶습니다. 정확한 메커니즘은 커널 내부를 확인해야 알 것 같습니다. 여기서는 동작하는 데 의의를 두고 그냥 넘어갑니다.

아무튼, 이 동작을 마치 케이프를 올렸다 내렸다 하는 것에 대응해서 추상화 해 놓았더군요. 위에서 만든 p8_11 핀을 출력용 gpio 핀으로 동작시키는 가상 케이프를 BBB에 장착 시키는 것 같은 개념입니다.

케이프란?
케이프는 비글본 시리즈 보드에 추가로 장착해서 원하는 특정 기능을 하는 보드를 말합니다.
아두이노의 쉴드에 대응한다고 볼 수 있습니다. 아직은 아두이노 만큼 풍부한 기능의 케이프 들이 있지는 않지만 점점 새로운 케이프들이 개발되고 있더군요.


슬롯에 장착

준비된 .dtbo 파일을 운영체제에 적용하도록 해 줍니다.

슬롯에 장착
root@arm:/home/ubuntu# echo p8_11_out > /sys/devices/bone_capemgr.*/slots


리눅스에서는 /proc 과 마찬가지로 /sys 뒤의 파일들은 디스크 상의 실제 파일이 아니라 커널 내부의 자료 구조를 파일로 가상화 한 것으로 보입니다. 그 중 /sys/devices/bone_capemgr.*/slots 부분이 이름처럼 케이프 매니저의 슬롯 개념으로 보이는데, 물리적으로 케이프를 장착시켜 주는 것처럼 .dtbo 파일을 비슷하게 다룰 수 있게 되어 있습니다.

위의 'echo' 명령 1줄은 'p8_11_out 이란 가상 케이프를 BBB에 장착하라'라는 의미로 이해하면 될 듯 합니다.

장착 상태의 확인

잘 장착(?) 되었는지 확인하는 방법은

슬롯 상황 확인
root@arm:/home/ubuntu# cat /sys/devices/bone_capemgr.*/slots
 0: 54:PF---
 1: 55:PF---
 2: 56:PF---
 3: 57:PF---
 4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
 5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
 6: ff:P-O-L Override Board Name,00A0,Override Manuf,p8_11_out


마지막 줄에 보이는 것처럼 슬롯 6에 p8_11_out 이 장착되어 있습니다.

여기까지 하면 P8_11 을 접근할 수 있는 상태가 됩니다.
그러면 실제로 P8_11 을 설정해 줘야 GPIO로 다룰 수 있습니다.

3) GPIO핀 설정


GPIO 상황 확인

현재의 GPIO 핀 설정이 어떻게 되어 있는 지 확인을 해 봅니다.

GPIO 상황 확인
root@arm:/home/ubuntu# ls /sys/class/gpio/
export  gpiochip0  gpiochip32  gpiochip64  gpiochip96  unexport


위에 보시는 것처럼 기존에 사용하고 있는 핀 목록이 나타납니다.
각자 사용하시는 상황에 따라 조금씩 달라질 수 있을 겁니다.

위에서 export 와 unexport 는 특별한 의미가 있는 파일입니다. 바로 아래 설명이 나옵니다.

P8_11 핀 활성화

P8_11핀을 GPIO로 사용하겠다고 설정하려면 다음과 같이 합니다.

핀 활성화
root@arm:/home/ubuntu# echo 45 > /sys/class/gpio/export


위에서 언급한 'export'라는 특별한 파일에 gpio번호를 출력해 주면 됩니다.

GPIO 상황 재 확인


GPIO 상황 확인
root@arm:/home/ubuntu# ls /sys/class/gpio/
export  gpio45  gpiochip0  gpiochip32  gpiochip64  gpiochip96  unexport


자 위의 결과처럼 'gpio45' 가 추가되어 있음을 확인할 수 있습니다. gpio45는 파일이 아니라 폴더처럼 동작합니다.
그 내부에는 다음과 같은 파일들이 있습니다.

GPIO 폴더 내부
root@arm:/home/ubuntu# ls /sys/class/gpio/gpio45/
active_low  direction  edge  power  subsystem  uevent  value


역시 실제 파일은 아니며, 저 중에서 'direction'과 'value'를 사용해서 출력으로의 설정과 실제 데이터 출력을 하게 됩니다.

P8_11핀을 출력용으로 설정


gpio의 입/출력 설정은 gpio45/direction 파일에 'out' 을 출력해 주면 됩니다.

핀의 출력 설정
root@arm:/home/ubuntu# echo out > /sys/class/gpio/gpio45/direction


이제 gpio45를 출력용으로 사용할 수 있게 준비되었습니다.

P8_11에 High 신호 출력


핀에 출력
root@arm:/home/ubuntu# echo 1 > /sys/class/gpio/gpio45/value


P8_11의 비활성화


사용이 끝나면 gpio를 다음과 같이 비활성화 해 줄 수 있습니다.

gpio #45를 비활성하는 예
root@arm:/home/ubuntu# echo 45 > /sys/class/gpio/unexport


P8_11을 슬롯에서 제거


슬롯에서 제거하기 위해서는

슬롯에서 제거하는 예
$ echo -6 > /sys/devices/bone_capemgr.*/slots


'echo' 명령으로 '-'가 붙은 슬롯 번호를 슬롯에 보내면 됩니다.
예에서는 슬롯 번호가 6이지만 실제 슬롯 번호는  cat /sys/devices/bone_capemgr.*/slots  명령을 사용해서 확인해야 합니다.


이상으로 gpio 사용 설명을 정리합니다만, 최대한 짧게 설명한다고 했는데도 장황해진 것 같아 다시 한번 요약합니다.

구분           명령 예)
슬롯 장착      echo p8_11_out > /sys/devices/bone_capemgr.*/slots
슬롯 상황 확인 cat /sys/devices/bone_capemgr.*/slots
핀 활성화      echo 45 > /sys/class/gpio/export
핀 상황 확인   ls /sys/class/gpio/
핀 출력 설정   echo out > /sys/class/gpio/gpio45/direction
데이터(High) 출력    echo 1 > /sys/class/gpio/gpio45/value
핀 비활성화    echo 45 > /sys/class/gpio/unexport
슬롯 제거      

echo -6 > /sys/devices/bone_capemgr.*/slots



3. 회로 구성


다음 사진에 이 글에서 사용하는 핀들을 표시해 봤습니다.

0009_BBB_GPIO_test.PNG






그리고 다음 사진에서는 레벨 컨버터(NS-LS4)를 사용하기 위한 선 연결을 보였습니다.
0009_BBB_5V_Converted_GPIO.PNG





위 사진의 우측 하단의 5V Circuit 에 원하는 5V 회로를 구성해 주면 됩니다.


4. 테스트


그럼 실제 테스트를 하기 위해 선 연결한 모습을 보시죠.
0013_BBB_Stepper_Motor_Wiring0.PNG



 


BBB와 레벨 컨버터 부분만 확대한 모습입니다.
0013_BBB_Stepper_Motor_Wiring1.PNG



 

워낙 간단한 것이라 별 달리 설명할 만한 건 없네요.
(가능하면 위의 그림과 같은 색의 점퍼 선을 사용하려고 노력했습니다.)


자, 그리고는 테스트를 위한 프로그램을 간단하게 C언어로 작성했습니다.
다음 프로그램은 단순히 스테퍼 모터를 1회전(Revolution, 360도) 시키는 코드가 되겠습니다.

for문에서 200*50 번 반복하면서 gpio45에 '1'과 '0'을 출력하는 것입니다.
200*50에서 200은 360도 회전하기 위한 모터 자체의 스텝 수 이고, 50은 마이크로스텝 설정 값 입니다.

c_stepper.c
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
 
int main(void)
{
        int fd = open("/sys/class/gpio/gpio45/value", O_WRONLY, S_IWRITE);
 
        if (fd>0) {
                int i;
                for (i=0; i<200*50; i++) {
                        write(fd, "1", 1);
                        //usleep(1);
                        write(fd, "0", 1);
                        //usleep(1);
                }
                close(fd);
        }
 
        return 0;
}


root@arm:/home/ubuntu# gcc -o c_stepper c_stepper.c
root@arm:/home/ubuntu# ./c_stepper
root@arm:/home/ubuntu#


위 코드의 실행으로 모터가 회전하는 것을 확인 했으며, 테스트 자체는 워낙 단순한 것이라 동영상 같은 것이 의미가 없다고 판단하고 생략합니다.


5. 결론


사실 알고 나면 너무나 간단한 것일테지만, 제가 원하는 전체 과정이 일목 요연하게 정리된 정보를 찾을 수가 없었기에 나름 많은 곳을 방문해서 읽어보고 시행착오도 많았습니다.

저 스스로의 정리도 하고, 또 저와 같은 목적의 정보를 원하시는 분께 조금이라도 도움이 될까 싶어서 정리를 해 봤습니다만, 부족한 부분이 많을 것이라고 생각됩니다. 조금씩 더 제대로 알아가면서 수정 보완하려고 합니다.


이 글에서 설명한 테스트는 사실 문제가 있습니다. 전반적인 개념과 구조가 이렇다라는 것을 보이기 위해 이런 예를 들어 정리했지만, 실제로 스테퍼 모터를 제어하는 데 사용하기에는 부족한 점이 있다는 것이죠.

1) 효율적인 제어가 어렵다.
2) 실시간 제어를 만족 못할 수도 있다.

위와 같은 문제점을 해결하기 위해 다음 단계로 넘어가야 합니다. 스테퍼 모터의 핵심 제어를 메인 프로세서에서 하지 않고 AM335x 내부에 탑재된 PRU 라는 보조 프로세서(?) 를 사용해서 어셈블리로 제어하는 방법인 PRUSS 라는 기술을 사용해야 합니다. 이 기술을 사용하면 고효율과 실시간 처리 두 가지를 모두 얻을 수 있을 것 같습니다. 제가 여러 고성능 오픈 하드웨어 플랫폼을 찾다가 BBB를 본격적으로 보게 된 이유가 PRUSS 라는 기술 때문이었습니다.

언제가 될 지 모르겠으나 조만간 PRUSS 에 대해서도 정리를 해 볼 예정입니다.


6. 참고 자료


관련 링크들
자료 링크
BeagleBone Black
System Reference Manual       
(BBB_SRM)
http://www.farnell.com/datasheets/1701090.pdf
AM335x Technical Reference Manual     
(AM335x TRM,SPRUH73I) 
http://www.ti.com/lit/ug/spruh73i/spruh73i.pdf
BBB Pins http://robotic-controls.com/node/68
Using BeagleBone Black GPIOs http://www.armhf.com/index.php/using-beaglebone-black-gpios/
A Tutorial on the Device Tree http://xillybus.com/tutorials/device-tree-zynq-1
Device Tree Usage http://devicetree.org/Device_Tree_Usage
GPIO가 뭔가요? http://forum.falinux.com/zbxe/index.php?document_srl=438015&mid=hardware



7.[부록] BBB 확장 헤더 핀 목록


P8 헤더
Mode7    OffsetName    Pin Pin Name     OffsetMode7
               DGND     1  2  DGND            
gpio1[6] 6  0x018 GPIO1_6  3  4  GPIO1_7  0x01c 7  gpio1[7]
gpio1[2] 2  0x008 GPIO1_2  5  6  GPIO1_3  0x00c 3  gpio1[3]
gpio2[2] 66 0x090 TIMER4   7  8  TIMER7   0x094 67 gpio2[3]
gpio2[5] 69 0x09c TIMER5   9  10 TIMER6   0x098 68 gpio2[4]
gpio1[13]45 0x034 GPIO1_13 11 12 GPIO1_12 0x030 44 gpio1[12]
gpio0[23]23 0x024 EHRPWM2B 13 14 GPIO0_26 0x028 26 gpio0[26]
gpio1[15]47 0x03c GPIO1_15 15 16 GPIO1_14 0x038 46 gpio1[14]
gpio0[27]27 0x02c GPIO0_27 17 18 GPIO2_1  0x08c 65 gpio2[1]
gpio0[22]22 0x020 EHRPWM2A 19 20 GPIO2_31 0x084 63 gpio1[31]
gpio1[30]62 0x080 GPIO1_30 21 22 GPIO1_5  0x014 37 gpio1[5]
gpio1[4] 36 0x010 GPIO1_4  23 24 GPIO1_1  0x004 33 gpio1[1]
gpio1[0] 1  0x000 GPIO1_0  25 26 GPIO1_29 0x07c 61 gpio1[29]
gpio2[22]86 0x0e0 GPIO2_22 27 28 GPIO2_24 0x0e8 88 gpio2[24]
gpio2[23]87 0x0e4 GPIO2_23 29 30 GPIO2_25 0x0ec 89 gpio2[25]
gpio0[10]10 0x0d8UART5_CTSN31 32 UART5_RTSN0x0dc11 gpio0[11]
gpio0[9] 0x0d4 UART4_RTSN33 34 UART3_RTSN0x0cc81 gpio2[17]
gpio0[8] 8  0x0d0UART4_CTSN35 36 UART3_CTSN0x0c880 gpio2[16]
gpio2[14]78 0x0c0 UART5_TXD37 38 UART5_RXD0x0c4 79 gpio2[15]
gpio2[12]76 0x0b8 GPIO2_12 39 40 GPIO2_13 0x0bc 77 gpio2[13]
gpio2[10]74 0x0b0 GPIO2_10 41 42 GPIO2_11 0x0b4 75 gpio2[11]
gpio2[8] 72 0x0a8 GPIO2_8  43 44 GPIO2_9  0x0ac 73 gpio2[9]
gpio2[6] 70 0x0a0 GPIO2_6  45 46 GPIO2_7  0x0a4 71 gpio2[7]



P9 헤더
Mode7    OffsetName    Pin Pin Name     OffsetMode7
               GND      1  2  GND             
               DC_3.3V  3  4  DC_3.3V         
               VDD_5V   5  6  VDD_5V          
               SYS_5V   7  8  SYS_5V          
               PWR_BUT  9  10 SYS_RSTn        
gpio0[30]30 0x070 UART4_RXD11 12 GPIO1_28 0x078 60 gpio1[28]
gpio0[31]31 0x074 UART4_TXD13 14 EHRPWM1A 0x048 50 gpio1[18]
gpio1[16]48 0x040 GPIO1_16 15 16 EHRPWM1B 0x04c 51 gpio1[19]
gpio0[5] 5  0x15c I2C1_SCL 17 18 I2C1_SDA 0x158 4  gpio0[4]
gpio0[13]13 0x17c I2C2_SCL 19 20 I2C2_SDA 0x178 12 gpio0[12]
gpio0[3] 3  0x154 UART2_TXD21 22 UART2_RXD0x150 2  gpio0[2]
gpio1[17]49 0x044 GPIO1_17 23 24 UART1_TXD0x184 15 gpio0[15]
gpio3[21]1170x1ac GPIO3_21 25 26 UART1_RXD0x180 14 gpio0[14]
gpio3[19]1150x1a4 GPIO3_19 27 28 SPI1_CS0 0x19c 113gpio3[17]
gpio3[15]1110x194 SPI1_D0  29 30 SPI1_D1  0x198 112gpio3[16]
gpio3[14]1100x190 SPI1_SCLK31 32 VADC            
               AIN4     33 34 AGND            
               AIN6     35 36 AIN5            
               AIN2     37 38 AIN3            
               AIN0     39 40 AIN1            
gpio0[20]20 0x1b4 CLKOUT2  41A42AGPIO0_7  0x164 7  gpio0[7]
gpio3[20]1160x1a8 GPIO3_20 41B42BGPIO3_18 0x1a0 114gpio3[18]
               GND      43 44 GND             
               GND      45 46 GND             
위로 스크롤