한백전자교육사업부 AndroX Studio 로배우는임베디드프로그래밍 - 한백전자 -
실습용장비 ; SM7-S4412 프로세서와주변장치직접연결 GPIO, 인터럽트, SPI, I2C 인터페이스사용 FPGA 모듈을거치지않음! 마이컴개발을위한아두이노 (Arduino Mega 2560) 탑재 ADK 2011 지원 안드로이드장치와아두이노보드연동가능 2
타깃주요명칭 HBE-SM7-S4412 Tablet 우측 1 전원SM7 Tablet 2 USB 호스트포트1 3 USB 호스트포트2 4 USB-to-Serial 포트 5 HDMI 포트 6 OTG 포트 7 오디오출력포트 8 전원잭 9 전원스위치 3
타깃주요명칭 HBE-SM7-S4412 Tablet 좌측 1 카메라포트 2 리셋키 3 볼륨UP키 4 볼륨DOWN키 5 확장포트 / 블루투스모듈 6 Wi-Fi 모듈 7 T-Flash 슬롯 4
타깃주요명칭 HBE-SM7-S4412 Tablet 뒷면 1 스태킹커넥터 2 카메라 3 배터리 4 NFC모듈 5 확장포트 / 블루투스모듈 6 Wi-Fi 모듈 7 T-Flash 슬롯 5
타깃주요명칭 HBE-SM7-S4412 Tablet 앞면 1 프로세서 2 emmc 3 부팅저장소선택스위치 4 바이브레이터 5 내장스피커 6
타깃주요명칭 HBE-SM7-S4412 베이스보드 베이스보드를이용하면 SM7- 테블릿을다른커스텀모듈과결합가능 오른쪽과왼쪽양끝에는확장커넥터들이위치함 7
타깃주요명칭 HBE-SM7-S4412 베이스보드우측면 1 JTAG 포트 2 전원잭 3 USB 호스트포트 4 버스확장버스 5 이더넷확장포트 8
타깃주요명칭 HBE-SM7-S4412 베이스보드좌측면 1 시리얼포트 2 확장포트 9
ADB 드라이버설치 장비와 PC 가 USB 케이블로연결되면다음과같이내컴퓨터속성의장치관리자내기타장치에서 SM7S4412 를확인할수있음 10
ADB 드라이버설치 SM7S4412 에서마우스오른쪽버튼을클릭하여팝업메뉴를열고, 드라이버소프트웨어업데이트를선택 11
ADB 드라이버설치 드라이버를설치하기위한대화상자가실행되면 C:\AndroXStudio\legacy\sdk\extras\google\usb_driver 폴더를지정 12
안드로이드응용프로그램개발툴 JDK Eclipse for Java ADT(Android Development Tool) Android SDK 13
Android Studio By Google (2013.5) IDE for Java App 14
AndroX Studio By Hanback Elec. IDE for Java App IDE for Embedded Programming ARM Assembly ANSI C Embedded Linux System Programming Linux Device Driver Linux Kernel Programming Java Native Interface(JNI LINUX env. X 15
AndroX Studio - IDE Integrated Development Environment 해당아이콘클릭으로 IDE 실행 16
AndroX Studio - Remote Explorer 17
AndroX Studio - 원격쉘 Remote Shell 18
AndroX Studio - 원격뷰어 Remote Viewer 19
AndroX Studio - Debug Monitor 20
AndroX Studio - Decompile 21
AndroX Studio - 역컴파일러 - Decompile 안드로이드앱 (.apk) 에서자바바이너리파일 à 소스파일로변환 (check!) 코드난독화 22
AndroX Studio - 이미지설치 Image Installer 23
AndroX Studio - 이미지설치 Image Installer System Recovery 기능 (bootloader, kernel, file-system) 공장초기화모드 ; 갤럭시 S2 공장초기화방법은? 24
AndroX Studio - Command 25
ARM 어셈블리실습 ; [step1] IDE 실행 IDE 실행 26
ARM 어셈블리실습 ; [step2] C/C++ Perspective 변경 화면오른쪽상단의 C/C++ Perspective 아이콘클릭 27
ARM 어셈블리실습 ; [step3] 프로젝트생성 [File] >> [New] >> [C Project] 28
ARM 어셈블리실습 ; [step3] 프로젝트생성 프로젝트생성 Project name : asm_hello Project Type : Makefile project >> Empty Project Toolchains : -- Other Toolchain -- 29
ARM 어셈블리실습 ; [step4] 소스코드생성 Project Explorer 에서 asm_hello 프로젝트선택 아이콘선택후, Assembly Executable 항목선택 30
ARM 어셈블리실습 ; [step4] 소스코드생성 OK 버튼선택 결과 asm_hello.s Makefile 31
ARM 어셈블리실습 ; [step5] 파일분석 ; asm_hello.s 001:.syntax unified 002: 003:.global main 004: main: 005: @ The prolog saves the state of the registers r4 through r11 typically 006: @ Push 8 "longs" on the stack and subtracts sp beforehand 007: push {ip, lr} 008: 009: @ Load the argument and perform the call. This is like 'printf()' in C. 010: ldr r0, =message 011: bl printf 012: 013: @ Exit from 'main'. This is like 'return 0' in C. 014: mov r0, #0 @ Return 0. 015: lr @ Pop the dummy ip to reverse our alignment fix, and pop the original 016: @ value directly into pc - the Program Counter - to return. 017: pop {ip, pc} 018: 019: @ Data for the printf calls. The GNU assembler's ".asciz" directive 020: @ automatically adds a NULL character termination. 021: message: 022:.asciz "Hello, ARM!\n" 023: 32
ARM 어셈블리실습 ; [step5] 파일분석 ; Makefile 001:.SILENT: 002: 003: include C:/AndroXStudio/Tools/make_comm 004: 005: all: $(ASM_OBJECTS) 006: $(CC) $(CFLAGS) $(LDFLAGS) -march=armv7-a -o asm_hello $(ASM_OBJECTS) 007: 008: echo 009: echo "**** Install:" /data/local/tmp/asm_hello "****" 010: $(ADB) push asm_hello /data/local/tmp 011: $(ADB) shell chmod 755 /data/local/tmp/asm_hello 012: echo 013: echo "**** Run ****" 014: $(ADB) shell TIMEFORMAT="" time /data/local/tmp/asm_hello 015: 016: clean: 017: rm -f *.o 018: rm -f asm_hello 019: 33
ARM 어셈블리실습 ; [step6] Project Build 아이콘을클릭하면 Project 가빌드된다. 빌드결과 34
ANSI C 실습 ; [step1] 프로젝트생성 프로젝트생성 Project name : c_hello Project Type : Makefile project >> Empty Project Toolchains : -- Other Toolchain -- 35
ANSI C 실습 ; [step2] 소스코드생성 Project Explorer 에서 c_hello 프로젝트선택 아이콘선택후, C Executable 항목선택 OK 버튼선택 36
ANSI C 실습 ; [step2] 소스코드생성 OK 버튼선택 결과 c_hello.c Makefile 37
ANSI C 실습 ; [step3] 파일작성하기 c_hello.c 001: #include <unistd.h> 002: #include <stdlib.h> 003: #include <stdio.h> 004: 005: int main(int argc, char * argv[]) { 006: printf("hello, hanback!\n"); 007: exit(0); 008: } 009: 38
ANSI C 실습 ; [step3] 파일분석하기 Makefile 001:.SILENT: 002: 003: include C:/AndroXStudio/Tools/make_comm 004: 005: all: $(OBJECTS) 006: $(CC) $(CFLAGS) $(LDFLAGS) -save-temps -march=armv7-a -O2 -o c_hello $(OBJECTS) \ 007: $(LLIB)/libgcc.a 008: 009: echo 010: echo "**** Install:" /data/local/tmp/c_hello "****" 011: $(ADB) push c_hello /data/local/tmp 012: $(ADB) shell chmod 755 /data/local/tmp/c_hello 013: echo 014: echo "**** Run ****" 015: $(ADB) shell TIMEFORMAT="" time /data/local/tmp/c_hello 016: 017: clean: 018: rm -f *.o 019: rm -f *.i 020: rm -f *.s 021: rm -f c_hello 022: 39
ANSI C 실습 ; [step4] Project Build 아이콘을클릭하면 Project 가빌드된다. 빌드결과 40
ARM C 공유라이브러리 함수를여러개의프로세스에서동시에사용 Windows 의 DLL 메모리절약 41
ARM C 공유라이브러리 ; [step1] 프로젝트생성 [tree_engine] 42
ARM C 공유라이브러리 ; [step2] 소스파일 (tree_engine.h) [tree_engine] 프로젝트선택후마우스오른쪽버튼 ( 팝업메뉴 ) tree_engine.h 파일생성 43
ARM C 공유라이브러리 ; [step2] 소스파일 (tree_engine.h) 001: #ifndef TREE_ENGINE_H_ 002: #define TREE_ENGINE_H_ 003: 004: #include <sys/stat.h> 005: #include <dirent.h> 006: #include <string.h> 007: 008: typedef void (*callback_search_dir)(char *, int, unsigned int); 009: 010: void search_dir(char * dir, int depth, callback_search_dir csd); 011: 012: #endif /* TREE_ENGINE_H_ */ 013: 44
ARM C 공유라이브러리 ; [step2] 소스파일 (tree_engine.c) 001: #include <unistd.h> 002: #include <stdlib.h> 003: 004: #include "tree_engine.h" 005: 006: void search_dir(char *dir, int depth, callback_search_dir csd) 007: { 008: DIR * ptr_dir; 009: struct dirent *ptr_dirent; 010: struct stat curr_stat; 011: 012: if ((void *)(ptr_dir = opendir(dir)) == NULL) 013: return ; 014: 015: chdir(dir); 016: while ( (void *)(ptr_dirent = readdir(ptr_dir))!= NULL) 017: { 018: lstat(ptr_dirent->d_name, &curr_stat); 019: 45
ARM C 공유라이브러리 ; [step2] 소스파일 (tree_engine.c) 020: if(s_isdir(curr_stat.st_mode)) 021: { 022: if (strncmp(".", ptr_dirent->d_name, 1) == 0 023: strncmp("..", ptr_dirent->d_name, 2) == 0) 024: continue; 025: csd(ptr_dirent->d_name, depth, curr_stat.st_mode & S_IFMT); 026: search_dir(ptr_dirent->d_name, depth + 4, csd); 027: } else { 028: csd(ptr_dirent->d_name, depth, curr_stat.st_mode & S_IFMT); 029: } 030: } 031: chdir(".."); 032: closedir(ptr_dir); 033: } 034: 46
ARM C 공유라이브러리 ; [step2] 소스파일 ; Makefile 001:.SILENT: 002: 003: include C:/AndroXStudio/Tools/make_comm 004: 005: all: 006: $(CC) $(CFLAGS) -save-temps -march=armv7-a -O2 -fpic -c $(wildcard *.c) 007: $(CC) $(LLDFLAGS) -shared -o libtree_engine.so $(wildcard *.o) \ 008: $(LLIB)/libgcc.a 009: 010: echo 011: echo "**** Install:" /system/lib/libtree_engine.so "****" 012: $(ADB) push libtree_engine.so /system/lib/ 013: $(ADB) shell chmod 644 /system/lib/libtree_engine.so 014: echo 015: 016: clean: 017: rm -f *.o 018: rm -f *.i 019: rm -f *.s 020: rm -f libtree_engine.so 021: 47
ARM C 공유라이브러리 ; [step3] 실행파일 tree.c ; main() 001: #include <unistd.h> 002: #include <stdlib.h> 003: #include <stdio.h> 004: 005: #include "../tree_engine/tree_engine.h" 006: 007: void do_search_dir(char *dir, int depth, unsigned int stat) 008: { 009: char *ptr_format; 010: 011: switch (stat) { 012: case S_IFBLK: 013: ptr_format = "%*s<b>%s\n"; 014: break; 015: case S_IFCHR: 016: ptr_format = "%*s<c>%s\n"; 017: break; 018: case S_IFDIR: 019: ptr_format = "%*s%s\n"; 020: break; 48
ARM C 공유라이브러리 ; [step3] 실행파일 tree.c ; main() 021: case S_IFIFO: 022: ptr_format = "%*s<f>%s\n"; 023: break; 024: case S_IFLNK: 025: ptr_format = "%*s<l>%s\n"; 026: break; 027: case S_IFREG: 028: ptr_format = "%*s<s>%s\n"; 029: break; 030: case S_IFSOCK: 031: ptr_format = "%*s<s>%s\n"; 032: break; 033: default: 034: ptr_format = "%*s<?>%s\n"; 035: break; 036: } 037: 038: printf(ptr_format, depth, " ", dir); 039: 040: } 49
ARM C 공유라이브러리 ; [step3] 실행파일 tree.c ; main() 041: 042: int main(int argc, char * argv[]) { 043: char *dir; 044: 045: if (argc == 1) 046: dir = "."; 047: else 048: dir = argv[1]; 049: 050: printf("directory scan of %s\n", dir); 051: search_dir(dir, 0, do_search_dir); 052: exit(0); 053: } 054: 50
ARM C 공유라이브러리 ; [step4] 실행 Makefile 수정 < 기존 > $(CC) $(CFLAGS) $(LDFLAGS) -save-temps -march=armv7-a -O2 -o tree tree.c < 변경 > $(CC) $(CFLAGS) $(LDFLAGS) -save-temps -march=armv7-a -O2 -o tree tree.c -ltree_engine -L../tree_engine 프로젝트를빌드 51
ARM C 공유라이브러리 ; [step4] 실행 Remote Shell / # cd /data/local/tmp /data/local/tmp #./tree /system/etc 52
커널빌드 리눅스커널빌드 컴파일대상을선별하는과정 + 선별된대상들을컴파일 리눅스커널은다양한아키텍쳐와많은디바이스드라이버를지원 자신의타깃에맞는아키텍처와디바이스드라이버선별과정이필요 커널빌드시스템 (Kernel Build System) 53
커널빌드시스템 54
타깃에커널설치 새로컴파일한커널을 SM7 타깃에설치하려면부트로더의 fastboot 서비스를사용 새로운커널을설치하기위해 SM7 태블릿과호스트를 USB 케이블로연결한상태에서안드로엑스스튜디오의런처에서 Image Installer 를실행 SM7 태블릿을부트로드의 fastboot 모드로부팅 전원버튼을누른후빠른시간내에 volume up 키를누른다. 정상부팅으로넘어가버리면, 전원을끄고다시시도 SM7 태블릿이부트로더의 fastboot 모드로부팅되면 Image Installer 는자동으로 fastboot 부팅상태를인식해상태표시줄에는 "Connected..." 가표시되고 [Start] 버튼이활성화됨 55
타깃에커널설치 [KERNEL] 버튼을눌러파일선택대화상자가실행되면다음경로에서커널이미지를불러옴 C:/AndroXStudio/legacy/cygwin/platform/linux/arch/arm/boot/zImage zimage 를 KERNAL 항목에불러왔으면 [Start] 버튼을눌러 SM7 태블릿에설치 56
리눅스커널프로젝트 57
리눅스커널프로젝트 Kernel Configuration 창이실행되면 SM7 태블릿용참조파일을새로적용할지묻는데 [yes + 엔터키 ] 를입력하면새로적용하고 [no + 엔터키 ] 를입력하면기존.config 파일을사용 커널구성편집기 58
이클립스에서커널소스트리작업 이클립스를실행하기위해안드로엑스스튜디오의런처에서 [IDE] 를선택 이클립스가실행되면 [C 퍼시펙티브 ] 를선택한후메인메뉴에서 [File > Makefile Project with Existing Code] 를선택 프로젝트설정대화상자가실행되면 "Project Name" 에 [sm7s4412_kernel] 을입력한후 "Existing Code Location" 에서 [Browse...] 버튼을눌러 SM7 태블릿의커널소스경로를선택하고 [Finish] 버턴을눌러완료 59
이클립스에서커널소스트리작업 정상적으로커널경로를인식하면리눅스커널소스트리전체가표시 60
이클립스에서커널소스트리작업 이클립스의 "Make Target" 창에서 [linux-s4412] 를선택하고 Make Target 의도구모음에서 [New Make Target] 을선택 Makefile 의목표를설정하는대화상자가실행되면 "Target name" 에 [zimage] 를입력한후 [OK] 버튼을눌러완료 61
이클립스에서커널소스트리작업 "Make Target" 창에서 "linux-s4412" 하위폴더를열고새로생성한 [zimage] 목표를더블클릭하거나 [zimage] 목표가선택된상태에서 Make Target 도구모음의 "Build Make Target" 을선택해커널을빌드 62
모듈작성 코드구성은리눅스커널에서제공하는헤더를사용하며다음과같은모듈초기화및해제등록매크로를통해커널영역에삽입되거나제거될때사용자가정의한함수가실행되도록해야함 -module_init(): 매크로함수로모듈이커널에적재될때호출되는 사용자함수를등록한다. -module_exit(): 매크로함수로모듈이커널에서제거될때호출되는사용자함수를등록 -MODULE_LICENSE(): 모듈의라이선스를기술 -MODULE_DESCRIPTION(): 모듈에대한설명을기술 -MODULE_AUTHOR(): 모듈에대한소유권을기술 63
모듈적재및해제 모듈적재및해제 64
모듈구현 [File] [C Project] - khello MISC Device Driver 65
모듈구현 khello.c 001: #include <linux/module.h> 002: #include <linux/kernel.h> 003: #include <linux/init.h> 004: 005: static int khello_init(void){ 006: printk("khello_init, \n"); 007: 008: return 0; 009: } 010: 011: static void khello_exit(void){ 012: printk("khello_exit, \n"); 013: 014: } 015: 016: module_init(khello_init); 017: module_exit(khello_exit); 018: 019: MODULE_LICENSE("GPL"); 020: MODULE_AUTHOR("khello"); 021: 66
모듈구현 Makefile 003: include C:/AndroXStudio/Tools/make_adb 004: 005: export ARCH=arm 006: export CROSS_COMPILE=arm-linux-androideabi- 007: 008: ifneq ($(KERNELRELEASE),) 009: obj-m := khello.o 010: else 011: KDIR := /platform/linux 012: all: 013: $(MAKE) -C $(KDIR) M=$(shell pwd) modules 014: 015: echo 016: echo "**** Install:" /system/lib/modules/khello.ko "****" 017: $(ADB) push khello.ko /system/lib/modules/ 018: $(ADB) shell chmod 644 /system/lib/modules/khello.ko 019: echo 020: echo "**** Load Module:" /system/lib/modules/khello.ko "****" 021: $(ADB) shell toolbox rmmod khello > /dev/null 022: $(ADB) shell insmod /system/lib/modules/khello.ko 023: $(ADB) shell lsmod grep khello 024: echo 025: 026: endif 67
모듈빌드 68
모듈결과확인 결과확인 69