RaspberryPi U-Boot & GPIO 제어 1 제 12 강 U-Boot + GPIO 제어 부트로더 U-Boot 부트로더 raw GPIO 제어 (LED, BTN) LED, BTN 제어
RaspberryPi U-Boot & GPIO 제어 2 부트로더 * boot loader : 시스템초기화후 OS로부팅 : 부트로더의기능 -시스템초기화 -시스템동작에필요한환경설정 -운영체제부팅 -메모리관리 -시스템모니터링등 * boot loader 종류 : LILO, GRUB, Loadlin, EtherBoot, Blob, PMON, RedBoot, U-Boot 등
부트로더 ( 계속 ) * ARM 의부트로더동작흐름도 RaspberryPi U-Boot & GPIO 제어 3
RaspberryPi U-Boot & GPIO 제어 4 부트로더 ( 계속 ) * 부트로더동작순서 1) 1st stage bootloader(rom에위치 ) : 제조과정에서 SoC에프로그래밍 ( 사용자에의해재프로그래밍불가 ) : SD카드의 FAT32 부트파티션마운트후, 2 nd 부트로더실행 2) 2nd stage bootloader (bootcode.bin) : fixedup.dat 참조하여 SDRAM 파티션및활성화 : 3rd 부트로더 (start.elf) 를 SDRAM에적재후실행 3) 3rd stage bootloader (start.elf) : User code를메모리에적재하고실행 *) User code( 리눅스커널, U-boot, 응용프로그램등 ) : 이진형태의파일 : 통상 kernel.img라명명된커널이미지및부가파일들 : 또다른부트로더 ( 예, U-boot), 혹은응용프로그램일수있음
RaspberryPi U-Boot & GPIO 제어 5 부트로더 ( 계속 ) * /boot 디렉터리의주요파일 pi@raspberrypi:/boot $ ls -al -rwxr-xr-x 1 root root 26108 Jul 10 09:15 bcm2710-rpi-3-b-plus.dtb -rwxr-xr-x 1 root root 52296 Jul 10 09:15 bootcode.bin -rwxr-xr-x 1 root root 142 Jan 21 2019 cmdline.txt -rwxr-xr-x 1 root root 1727 Jul 27 02:03 config.txt -rwxr-xr-x 1 root root 6701 Jul 10 09:15 fixup.dat -rwxr-xr-x 1 root root 5000184 Jul 10 09:15 kernel.img -rwxr-xr-x 1 root root 5281136 Jul 10 09:15 kernel7.img drwxr-xr-x 2 root root 14336 Jul 10 09:15 overlays -rwxr-xr-x 1 root root 2873444 Jul 10 09:14 start.elf
U-Boot 부트로더 ( 계속 ) * U-Boot 로부팅할때조치 RaspberryPi U-Boot & GPIO 제어 6 1) 소스컴파일후생성된 u-boot.bin을 /boot 디렉터리에위치 2) u-boot.bin가실행되도록 /boot/config.txt 편집 * 가상머신에로그인후슈퍼유저로전환 ifc413@ubuntu:~$ sudo su root@ubuntu:/home/ifc413# cd root@ubuntu:~#
U-Boot 부트로더 ( 계속 ) * U-Boot 소스다운로드 ( 방법 1) : git 툴을활용하여다운로드 RaspberryPi U-Boot & GPIO 제어 7 # apt-get update # apt-get upgrade # apt-get install git // git 패키지설치 # git clone git://git.denx.de/u-boot.git // 현작업디렉터리에./u-boot로다운로드됨 # ls./u-boot
U-Boot 부트로더 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 8 * CD 의 /u-boot/u-boot.tar.gz 활용 ( 방법 2) : SAMBA 서비스로공유하는경우 # ls /mnt/hgfs/shared/ # cp /mnt/hgfs/shared/achro-em/u-boot.tar.gz./ # tar xvf u-boot.tar.gz // 풀기 # ls./u-boot
U-Boot 부트로더 ( 계속 ) * 소스구성 : root@ubuntu:~# cd u-boot root@ubuntu:~/u-boot# ls RaspberryPi U-Boot & GPIO 제어 9./configs : 타깃보드용의환경설정파일들위치./arch : 특정아키텍쳐관련소스./examples : 테스트용예제
U-Boot 부트로더 ( 계속 ) * U-Boot 환경설정파일 RaspberryPi U-Boot & GPIO 제어 10 :./configs에타깃보드용환경설정파일들위치 : 라즈베리파이 3B+ 보드용은 rpi_3_32b_defconfig root@ubuntu:~/u-boot# ls./configs/rpi*
U-Boot 부트로더 ( 계속 ) * 라즈베리파이용 U-Boot 환경설정 : U-Boot 홈디렉터리에서 RaspberryPi U-Boot & GPIO 제어 11 # make rpi_3_32b_defconfig // 오류발생참고 ) 오류발생시조치 => bison, flex 패키지설치 # apt install bison # apt install flex # make rpi_3_32b_defconfig // 오류없음 : U-Boot의환경설정내용이.config 히든파일로저장
U-Boot 부트로더 ( 계속 ) * U-Boot 컴파일 # make -j4 : -j4 옵션은코어의개수지정 # ls RaspberryPi U-Boot & GPIO 제어 12 => u-boot.bin 이 U-Boot 의이진파일임 타깃보드의 /boot 디렉터리로복사
U-Boot 부트로더 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 13 * 부트로더포팅 ( 방법 1.. NFS 서비스를통해 ) : NFS 서버측 # cp u-boot.bin /nfs // NFS 서비스디렉터리로복사 # ls /nfs h_hello t_hello u-boot.bin
U-Boot 부트로더 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 14 * 부트로더포팅 ( 방법 1.. NFS 서비스를통해 ) : NFS 클라이언트 ( 라즈베리파이보드 ) 측 -putty 접속하여로그인후 pi@raspberrypi:~ $ sudo su // 슈퍼유저로전환 root@raspberrypi:/home/pi# cd root@raspberrypi:~# ls - 타깃보드의 /boot 파티션으로복사 # mount -t nfs 192.168.0.20:/nfs /share # ls /share h_hello t_hello u-boot.bin # cd /boot # cp /share/u-boot.bin /boot # ls *.bin bootcode.bin u-boot.bin
U-Boot 부트로더 ( 계속 ) * 부트로더포팅 RaspberryPi U-Boot & GPIO 제어 15 : 방법2) SD 카드에관련파일기록 ( 미실습 ) : SD카드를 USB통해연결후, boot 파티션이름확인 # lsblk // boot 파티션 sdb1 주목 ( SD 카드 )!! # mkdir /mnt # mount /dev/sdb1 /mnt // 마운트 # cp u-boot.bin /mnt // 부트로더복사 # nano /mnt/config.txt // 환경파일편집 kernel = u-boot.bin # sync # umount /mnt // 마운트해제 : SD 카드를라즈베리파이보드에장착후부팅
U-Boot 부트로더 ( 계속 ) * /boot 에 u-boot.bin 확인 RaspberryPi U-Boot & GPIO 제어 16 : 어떤방법으로든 /boot 디렉터리에위치해야함 # ls *.bin bootcode.bin u-boot.bin * config.txt 파일편집 : 커널이미지파일대신 U-Boot 이진파일을실행하도록설정 # nano config.txt... # B-boot loader kernel=u-boot.bin # reboot // 재부팅
U-Boot 부트로더 ( 계속 ) * u-boot 통한커널부트 RaspberryPi U-Boot & GPIO 제어 17 : 실습을위해 SBC 구축을권고함 ( 모니터, 키보드연결 ) : 전원인가후즉시키누를것!!! : 다음의부트로더프롬프트가나타남 U-Boot> : 부트로더의내부명령활용
U-Boot 부트로더 ( 계속 ) * U-Boot 내부명령 help.. 내부명령에대한도움말 RaspberryPi U-Boot & GPIO 제어 18 printenv... 환경변수의설정내역출력 setenv... 환경변수에값설정 setenv ipaddr 211.188.17.38 ( ip address 설정 ) setenv serverip 211.188.17.39 ( server address 설정 ) saveenv... 환경변수설정내역저장 ( uboot.env 파일로 FAT 에 ) ${kernel_addr_r}... 내부명령에서환경변수인용시사용형식 gpio... GPIO 제어명령 md... 메모리내용출력 (memory dump) tftpboot... TFTP 클라이언트명령 go.. 메모리내응용프로그램실행 기타등등...
U-Boot 부트로더 ( 계속 ) * TFTP 서버구축 ( 가상머신에 ) RaspberryPi U-Boot & GPIO 제어 19 # apt-get install tftpd-hpa tftp-hpa // 패키지설치 # gedit /etc/default/tftp-hpa // 환경설정파일생성 # /etc/default/tftpd-hpa TFTP_USERNAME="tftp" TFTP_DIRECTORY="/tftpboot" // 서비스디렉터리유의 TFTP_ADDRESS="0.0.0.0:69" TFTP_OPTIONS="--secure # mkdir /tftpboot // 서비스디렉터리생성 # chown nobody /tftpboot # chmod -R 777 /tftpboot # servcie tftpd-hpa restart // 서비스재개
U-Boot 부트로더 ( 계속 ) * TFTP 서버구동확인 : 서비스여부파악명령 # servcie tftpd-hpa status RaspberryPi U-Boot & GPIO 제어 20 : 혹은, 서비스디렉터리에임의파일 (test.txt) 위치시키고다운로드테스트 # tftp localhost > get test.txt > quit # ls test.txt
U-Boot 부트로더 ( 계속 ) * U-Boot 에서 TFTP 서비스받기 : 양측의 IP 주소설정후, : tftpboot 명령사용 RaspberryPi U-Boot & GPIO 제어 21 U-boot> setenv ipaddr 192.168.0.40 // 개발보드의 IP 주소설정 U-boot> setenv serverip 192.168.0.20 // 서버 ( 가상머신 ) 의 IP 주소설정 U-boot> tftpboot 0x0C100000 hello_world.bin
U-Boot 부트로더 ( 계속 ) * 원상복구방법 RaspberryPi U-Boot & GPIO 제어 22 : /boot/config.txt 편집하여관련부분제거 : kernel=u-boot.bin을삭제혹은주석처리, 저장후재부팅 : Windows 환경의경우 -SD 카드내의 config.txt 파일의끝에있는 kernel=u-boot.bin 부분을삭제혹은주석처리후저장하여사용
U-Boot 부트로더 ( 계속 ) [ 실습 1] B-Boot 에서 GPIO 핀제어 RaspberryPi U-Boot & GPIO 제어 23 : LED 회로를 BCM-GPIO #18에연결 : SBC 구축상태를권고함 U-Boot> help // 내부명령목록 U-Boot> gpio // gpio 제어명령 gpio <input set clear toggle> <pin> U-Boot> gpio set 18 // LED ON U-Boot> gpio clear 18 // LED OFF U-Boot> gpio toggle 18 // LED toggle
U-Boot 부트로더 ( 계속 ) [ 실습 2] hello_world.bin 실행 : 다음의파일참조 RaspberryPi U-Boot & GPIO 제어 24./arch/arm/armconfig.mk // standalone 응용의적재될메모리주소확인./examples/standalone/Makefile./examples/standalone/hello_world.c : 위소스는이미컴파일됨 : hello_world.bin을 TFTP 서비스디렉터리로이동후, B-boot> tftpboot 0x0C100000 hello_world.bin B-boot> md 0x0C100000 B-boot> go 0x0C100000
RaspberryPi U-Boot & GPIO 제어 25 $ cat./arch/arm/config.mk # SPDX-License-Identifier: GPL-2.0+ # # (C) Copyright 2000-2002 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. ifndef CONFIG_STANDALONE_LOAD_ADDR ifneq ($(CONFIG_ARCH_OMAP2PLUS),) CONFIG_STANDALONE_LOAD_ADDR = 0x80300000 else CONFIG_STANDALONE_LOAD_ADDR = 0x0c100000 #*) endif endif... $ cat./examples/standalone/makefile # SPDX-License-Identifier: GPL-2.0+ # # (C) Copyright 2000-2006 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. extra-y := hello_world extra-$(config_smc91111)... += smc91111_eeprom
RaspberryPi U-Boot & GPIO 제어 26 $ cat./examples/standalone/hello_world.c // SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. */ #include <common.h> #include <exports.h> int hello_world (int argc, char * const argv[]) { int i; // main() 아님 /* Print the ABI version */ app_startup(argv); printf ("Example expects ABI version %d\n", XF_VERSION); printf ("Actual U-Boot ABI version %d\n", (int)get_version()); printf ("Hello World\n");...
rawgpio 제어 RaspberryPi U-Boot & GPIO 제어 27 * GPIO(General purpose input output) : 입력이나출력을포함한동작이사용자에의해제어되는디지털신호핀 : 하나의입출력핀에여러기능부여로복잡한구조 : 기본적으로입력과출력이가능하며, 하나의핀은 GPIO로혹은다른기능으로도사용가능 : 타깃보드에서총 54 개의 GPIO 핀제공
rawgpio 제어 ( 계속 ) * BCM2835 의메모리맵 RaspberryPi U-Boot & GPIO 제어 28 : BCM2837 의 IO Peripherals Base 주소... 0x3F00_0000
rawgpio 제어 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 29 * GPIO 핀블록도및관련레지스터
rawgpio 제어 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 30 * GPIO 관련레지스터들의베이스주소 : IO Peripherals Base(0x3F00_0000) + 0x0020_0000 : 즉, 0x3F20_0000
rawgpio 제어 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 31 * GPIO 관련레지스터 ( 대략 13 종 ) : 주요레지스터의물리주소및기능 PhysicalAddr Field Name Description Size Read/Write 0x3F20_0000 GPFSEL0 GPIO Function Select 0 32 R/W 0x3F20_0004 GPFSEL1 GPIO Function Select 1 32 R/W 0x3F20_0008 GPFSEL2 GPIO Function Select 2 32 R/W 0x3F20_000C GPFSEL3 GPIO Function Select 3 32 R/W 0x3F20_0010 GPFSEL4 GPIO Function Select 4 32 R/W 0x3F20_0014 GPFSEL5 GPIO Function Select 5 32 R/W 0x3F20_0018 - Reserved - - 0x3F20_001C GPSET0 GPIO Pin Output Set 0 32 W 0x3F20_0020 0x3F20_0024 GPSET1 GPIO Pin Output Set 1 32 W - Reserved - - 0x3F20_0028 GPCLR0 GPIO Pin Output Clear 0 32 W 0x3F20_002C GPCLR1 GPIO Pin Output Clear 1 32 W 0x3F20_0030 0x3F20_0034 - Reserved - - GPLEV0 GPIO Pin Level 0 32 R 0x3F20_0038 GPLEV1 GPIO Pin Level 1 32 R 0x3F20_003C... - Reserved - -
rawgpio 제어 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 32 * GPFSELn(GPIO Function Select Registers) : GPIO 핀의입력용 / 출력용, 다른기능설정입력용 000, 출력용 001, 다른기능 ( 데이터시트참조 ) : 각핀당 3비트씩소요, 각레지스터의상위2비트비사용 : 1개레지스터에 LSB부터할당하여 10개 GPIO핀설정 : 예 ) BCM_GPIO #18 출력용, BCM_GPIO #1 입력용 GPIO_9 GPIO_8... GPIO_2 GPIO_1 GPIO_0 31 30 29 28 27 26 25 24 8 7 6 5 4 3 2 1 0 GPFSEL0 - - 0 0 0 GPFSEL1 - - 0 0 1 GPFSEL2 - - GPFSEL3 - - GPFSEL4 - - GPFSEL5 - - - - - - - -
rawgpio 제어 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 33 * GPSETn(GPIO Pin Output Set Registers) : GPIO 핀에 High 신호를출력할때사용 : 핀번호위치에 1을설정하면, High 신호출력 : 예 ) BCM_GPIO #23 에 High 출력 31 30 29 28 27 26 25 24 23 22 21... 5 4 3 2 1 0 GPSET0 1 GPSET1 - - - - - - - - - -
rawgpio 제어 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 34 * GPCLRn(GPIO Pin Output Clear Registers) : GPIO 핀에 Low 신호를출력할때사용 : 핀번호위치에 1을설정하며, Low 신호출력 : 예 ) BCM_GPIO #23 에 Low 출력 31 30 29 28 27 26 25 24 23 22 21... 5 4 3 2 1 0 GPCLR0 1 GPCLR1 - - - - - - - - - -
rawgpio 제어 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 35 * GPLEVn(GPIO Pin Level Registers) : GPIO 핀에인가된신호를반영하는레지스터 : 입력장치의신호를입력받을때사용 : 예 ) BCM_GPIO #23 의신호 31 30 29 28 27 26 25 24 23 22 21... 5 4 3 2 1 0 GPCLR0 x GPCLR1 - - - - - - - - - -
rawgpio 제어 ( 계속 ) * GPIO 핀관련물리주소 RaspberryPi U-Boot & GPIO 제어 36 : 출력용디바이스 ( 예, LED.. BCM_GPIO#18) : 입력용디바이스 ( 예, BTN.. BCM_GPIO#17) #define GPIO_BASE 0x3F200000 // for BCM2836, BCM2837 // address offset of registers for GPIO #define GPFSEL1 0x04 #define GPSET0 0x1C #define GPCLR0 0x28 #define GPLEV0 0x34 char * gpio; gpio = (char *)GPIO_BASE; // 물리주소
rawgpio 제어 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 37 * 출력용디바이스 ( 예, LED.. BCM_GPIO#18) : 출력용 (001)...GPFSEL1 레지스터 // 19 18 11 10 // GPFSEL1 = 0bxx xxx 001 xxx xxx xxx xxx xxx xxx xxx xxx; gpio[gpfsel1 / 4] &= ~(6 << 24); // #18, output, ~(001)=110(6) : High 출력할때... GPSERT0 레지스터 // 29 20 19 10 9 0 // GPSET0 = 0b00 0000000000 0100000000 0000000000; gpio[gpset0 / 4] = (1 << 18); // LED ON : Low 출력할때... GPCLR0 레지스터 // 29 20 19 10 9 0 // GPCLR0 = 0b00 0000000000 0100000000 0000000000; gpio[gpclr0 / 4] = (1 << 18); // LED OFF
rawgpio 제어 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 38 * 입력용디바이스 ( 예, BTN.. BCM_GPIO#17) : 입력용 (000)...GPFSEL1 레지스터 // 19 18 17 11 10 // GPFSEL1 = 0bxx xxx xxx 000 xxx xxx xxx xxx xxx xxx xxx xxx; gpio[gpfsel1 / 4] &= ~(7 << 21); // #17, input, ~(000)=111(7) : 신호읽기... GPLEV0 레지스터 // 29 20 19 10 9 0 // GPLEV0 = 0bXX XXXXXXXXXX XXXXXXXXXX XXXXXXXXXX; // AND 0b00 0000000000 0010000000 0000000000; ret = (gpio[gplev0 /4] & (1 << 17)) >> 17; // press? // ret는 0, 혹은 1 : 기타레지스터가사용될수있음
rawgpio 제어 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 39 [ 실습 3] LED 제어 ( 부트로더실행방식 ) : LED를 ON/OFF하기를반복하는 standalone app. : GPIO 핀의물리주소로접근하여제어 $ cd./examples/standalone $ nano Makefile... extra-y... := bootledgpio_01 // 작성할파일명으로 $ nano bootledgpio_01.c //======================================= // bootledgpio_01.c // BCM_GPIO #18, LED // to execute like U-boot bootloader //======================================= #include <common.h> // U-boot
RaspberryPi U-Boot & GPIO 제어 40 #include <exports.h> // U-boot #define GPIO_BASE 0x3F200000 // for BCM2836, BCM2837 // address offset of registers for BCM_GPIO #18 #define GPFSEL1 0x04 #define GPSET0 0x1C #define GPCLR0 0x28 int bootledgpio_01(void) { char * gpio_mmap; volatile unsigned int * gpio; printf("[rawgpio testing...led like U-boot]\n"); gpio_mmap = (char *)GPIO_BASE; // 물리주소 gpio = (volatile unsigned int *)gpio_mmap; // 19 18 11 10 // GPFSEL1 = 0bxx xxx 001 xxx xxx xxx xxx xxx xxx xxx xxx; gpio[gpfsel1 / 4] &= ~(6 << 24); // #18, output, ~(001)=110(6) while(1) { // 29 20 19 10 9 0 // GPSET0 = 0b00 0000000000 0100000000 0000000000; gpio[gpset0 / 4] = (1 << 18); // LED ON printf("led ON...\n");
RaspberryPi U-Boot & GPIO 제어 41 mdelay(100); } // 29 20 19 10 9 0 // GPCLR0 = 0b00 0000000000 0100000000 0000000000; gpio[gpclr0 / 4] = (1 << 18); // LED OFF printf("led OFF...\n"); mdelay(100); } return 0; * 컴파일 $ cd../../ $ sudo make clean $ sudo make j4 $ ls
RaspberryPi U-Boot & GPIO 제어 42 * TFTP 서비스디렉터리로 bootledgpio_01..bin 파일복사후, B-boot> tftpboot 0x0C100000 bootledgpio_01.bin B-boot> go 0x0C100000 ==> 운영체제없이부트로더가실행되는방식으로 GPIO 핀에연결된디바이스를 물리주소를이용하여제어가능!!!!
rawgpio 제어 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 43 [ 실습 4] 커널이미지로부팅... 추후시도할것 : TFTP 서비스디렉터리에관련파일위치후, U-boot> setenv ipaddr 192.168.0.40 U-boot> setenv serverip 192.168.0.20 U-boot> tftpboot ${kernel_addr_r} kernel7.img U-boot> tftpboot ${fdt_addr_r} bcm2710-rpi-3-b-plus.dtb U-boot> bootz ${kernel_addr_r} - {fdt_addr_r}
rawgpio 제어 ( 계속 ) RaspberryPi U-Boot & GPIO 제어 44 [ 실습 5] LED 제어용부트로더... 추후, 천천히 : LED 제어전용부트로더형태로구현
응용과제 [ 응용 1] GPIO LED 및 BTN 제어 : U-Boot 부트로더실행방식으로 : LED와 BTN 회로활용 : 수행동작은각자정의할것 RaspberryPi U-Boot & GPIO 제어 45