Prologue

참고로, 이 글은 오래전에 쓴 글인데, 실패한 작업이기에 비공개로 놓아 두었다가, 똑같은 작업을 하고 있는 분들에게 조금이라도 도움(?)을 줄 수 있지 않을까라는 생각에 뒤늦게 공개 전환을 합니다.

BBB에 안드로이드 Pre-image를 쉽게 올려서 성공한 글은 바로 밑에 글을 참고하세요~~~!!!

2019/12/02 - [안드로이드 임베디드/Android for the BeagleBone Black] - Beaglebone Black에 Android 이미지 올리기

 

Beaglebone Black에 Android 이미지 올리기

비글본 블랙에 안드로이드 이미지를 올리겠다. 이 이미지는 http://bbbandroid.sourceforge.net/에서 다운 받을 수 있다. 참고로 첨부 파일로 공유한다. BBBAndroid: A custom Android OS for the BeagleBone Blac..

decdream08.tistory.com

 

BeagleBone Black 안드로이드 Pre-image 올리기 (실패...)

안드로이드 소스를 컴파일 하기 전에, 이미 만들어져 있는 안드로이드 Pre-image를 올려보려고 한다.

http://processors.wiki.ti.com/index.php/BeagleBone-Android-DevKit_Guide#Preparation_of_SD_card

 

BeagleBone-Android-DevKit Guide - Texas Instruments Wiki

What is BeagleBone The BeagleBone is a low-cost, high-expansion hardware-hacker focused BeagleBoard. It is a bare-bones BeagleBoard that acts as a USB or Ethernet connected expansion companion for your current BeagleBoard and BeagleBoard-xM or works stand-

processors.wiki.ti.com

위의 문서를 차근 차근 따라서하면 쉽게 이미지를 얻을 수 있다.

BeagleBone Black용 pre-image는 http://software-dl.ti.com/dsps/dsps_public_sw/sdo_tii/TI_Android_DevKit/TI_Android_GingerBread_2_3_4_DevKit_2_1_1/exports/BeagleBone.tar.gz 

를 통해서 얻을 수 있다.

그렇게 받은 압축 파일을 다음과 같이 압축해제 한 후, mkmmc-android.sh 파일을 실행하면 파티션을 3개로 만든 후 

  1. boot - Boot Images (Boot Loaders, Boot Script and Kernel)
  2. rootfs - File system (Android GingerBread 2.3.4)
  3. data - Media Clips (Audio, Video and Images)

위의 3가지 이미지를 각각의 파티션에 복사하는 일을 한다.

그에 대한 명령어는 다음과 같다.

$ tar -xzvf BeagleBone.tar.gz

$ cd BeagleBone

$ sudo ./mkmmc-android.sh /dev/sd<device>

여기서 <device>는 MicroSD 카드를 끼웠다가 뺐을때 "lsblk" 명령어를 써서 다른 부분을 체크하여 MicroSD에 맞는 device 이름을 넣어주면 된다.

참고로, 본인은 MicroSD 카드가 sdb로 인식이 되기 때문에 다음과 같이 명령어를 완성하여 입력하였다.

$ sudo ./mkmmc-android.sh /dev/sd<device>

그런데 mkmmc-android.sh 파일을 실행할때 다음과 같은 문제점이 발생한다는 것이다.

Error의 내용을 보니 파티션이 제대로 나눠지지 않아서 발생하는 문제이다.

참고로, TI 홈페이지에 본인과 동일한 문제점을 갖고 있던 사람이 Q&A를 한 내용이 있어서 발췌를 해본다.

BegleboardXM용 sh 파일을 사용하여 문제가 해결되었다고 하는데, 나는 왜 안될까? 아마도 SD 카드에 따라서 문제가 발생하는거 같다.

https://e2e.ti.com/support/legacy_forums/embedded/android/f/509/t/72783

 

[Resolved] mkmmc-android.sh invoking error to prerare SD card - Android Forum (Read-Only Archived) - Android (Read-Only) - TI E2

 

e2e.ti.com

그래서 해결점은 단 하나. 직접 MicroSD 카드 파티션을 3개로 나누는 것이다.

각 파티션의 용량은 각 파티션에 들어갈 파일 크기 보다 크게만 잡을 것이다.

다운로드 받은 후 압축을 해제했던 준비된 파일의 용량을 다음과 같이 확인했다.

그리고 이미지를 만들때 사용할 mkmmc-android.sh 파일의 아래 내용을 참고하면 각각의 파티션 sdb1/sdb2/sdb3에 어떤 파일이 적재될 것인지를 판단 할 수 있어서, 그것을 참고로 파티션의 크기를 결정한다.

위의 내용을 통해서 $S2가 Boot_Images/MLO, $S3가 Boot_Images/u-boot.... 임을 확인할 수 있다.

이것을 참고로 mkmmc-android.sh 파일의 하기 내용도 파악하기가 쉽다.

mkmmc-android.sh 파일을 분석하여 다음과 같이 정리가 가능하다.

  1. sdb1 - MLO / u-boot.img / uImage / uEnv.txt 그리고 START_HERE가 저장 되며 전체 용량은 4.7MB이다.
  2. sdb2 - $6(Filesystem/rootfs*)이 추가 되는데 tar jxvf로 압축을 풀고 추가가 된다. 압축해제 후 용량은 88.2MB이다.
  3. sdb3 - Media_Clips가 추가되며 전체 용량은 137.1MB이다.

Window에서 DISKPART를 이용하여 MicroSD 카드의 READONLY 속성을 해제하고 기존에 있던 Partition을 모두 지웠다.

그 다음 Ubuntu에서 CParted라는 프로그램을 이용하여 다음과 같이 MicroSD 카드의 파티션을 나누었다.

작업을 마친후 Terminal에서 lsblk 명령어를 이용하여 다시 한번 확인을 해본다.

정상적으로 MicroSD 내부가 sdb1/sdb2/sdb3... 로 파티션이 잘 나눠진것을 확인 할 수 있다.

이제 mkmmc-android.sh 파일에서 파티션을 나누는 부분과 파일 시스템을 만드는 부분을 삭제하고 실행해 본다.

 

다시 경로를 변경한 후에 sh 파일을 다음과 같이 실행을 하면 정상적(?)으로 copy가 되는 것을 확인 할 수 있다.

위의 umount error는 크게 신경쓰지 않아도 될것 같다.

lsblk 명령어를 이용하여 확인을 해보면 sdb1/sdb2/sdb3이 각각 /media/mskim/boot, /media/mskim/rootfs/, /media/mskim/data로 마운트 되어있다.

실제 해당 폴더로 이동하여 파일이 있는지를 다음과 같이 확인했고, 정상적으로 이미지가 다 들어 있는 것을 확인 했다.

자... 이제 운명의 시간이다.

Beaglebone Black에 MicroSD 카드를 삽입하여 확인을 할 것이다.

그 전에, UART 통신을 하기 위해서 케이블을 보드에 삽입하고, 그 다음 Micro HDMI 케이블을 보드와 TV에 연결을 했다.

MicroSD 카드를 삽입하고 나서 보드 전원을 공급하기 위해 Micro USB 케이블을 PC와 보드사이에 연결을 했다.

 

아니 이게 웬걸... 아무리 기다려도 정상적으로 부팅이 되지 않는다. 그동안 이 작업을 위해 많은 시간을 투자 했건만, 한마디로 실패다.

그나마 배운게 있다면 안드로이드 image는 아래와 같이 구성된다는거..

  1. boot - Boot Images (Boot Loaders, Boot Script and Kernel)
  2. rootfs - File system (Android GingerBread 2.3.4)
  3. data - Media Clips (Audio, Video and Images)

2번까지가 유의미한 것이고, 3번은 테스트를 위해 필요한 데이터들이라고 보면 되겠다.

무엇이 잘못된 것인지 시간이 있을 때 다시 한번 일련의 작업들을 찬찬히 들여다 봐야겠다.

이상한 점이 있다면 #1의 Boot쪽에 Kernel 사이즈가 너무 작다는 거...

 

- 끝.

GPIO 코드 컴파일(Build)

이제 실제 앱을 이용하여 BBB의 GPIO를 컨트롤해보자.

이전 글에서 만들었던 안드로이드 프로젝트 대신에 이미 구현이 되어 있는 첨부 파일을 사용할 것이다.

gpio.zip
1.73MB

이 첨부 파일 안에 라이브러리는 이전 글에서 만들었던 것과 동일한 so 파일이 담겨져 있다. 첨부 파일을 다운로드 받고 적당한 위치에 압축을 풀고 Eclipse ADT를 실행한다.

1. 'File' → 'Import'를 선택하고, 

2. 'Android' → 'Existing Android Code Into Workspace'를 선택 한 후, 'Next'를 누른다.

3. 하기 빨간 네모 안 'Browse'를 선택하여, 압축을 해제한 폴더 'gpio'를 클릭 한 후 '폴더선택' 버튼을 누른다.

4. 'Finish' 버튼을 눌러 끝낸다.

이제 프로젝트를 Build 하기 위해서 "gpio에서 오른쪽 클릭" → 'Run As'  'Android Applicaiton' 선택.

하지만, 보기 좋게 Error 발생.

이 Error에 대해서 검색을 해보니 다음과 같이 해결 방안을 찾을 수 있었다.

https://m.blog.naver.com/kkson50/221208277244

 

[문제해결] Unable to build: the file dx.jar was not loaded from the SDK folder

에러현상Eclipse ADT에서 발생한 에러입니다. Failed to load d:\Android\sdk\build-tools\26.0.2\li...

blog.naver.com

그래서 Eclipse에서 'Window → Android SDK Manager'를 실행.

Android SDK Build-tools 25.0.3을 체크하고 'install 1 package'를 실시.

Accept License를 체크하고 Install 버튼을 누른다.

인스톨을 마친 이후에 Eclipse SDK가 위치한 폴더로 이동 후 build-tools\25.0.3\lib\dx.jar 파일을 복사하여 build-tools\29.0.2\lib\dx.jar 파일을 대체 하도록 덮어 씌우기를 한다.

그 다음 다시 build를 실시하면 정상적으로 build가 완료된다.

그러나 Android Virtual Device(ADB)에서 다음과 같이 문제 발생. 우리가 만든 gpio 앱이 정지되었다.

이 문제는 ADB 설정시 Intel CPU로 셋팅을 해서 발생한 문제이다. 그래서 ARM CPU로 변경하였다.

그리고 다시 build 하면 정상적으로 GPIO 앱이 화면에 display 되는 것을 확인할 수 있다.

여기까지 컴파일(build)한 GPIO 코드가 Emulator에서 잘 동작하는 것을 확인했다.

 

GPIO 앱을 BeagleBone Black에 넣기

이제, BBB에 컴파일 하고 만들어진 앱(apk)를 넣는 일만 남았다.

넣는 방법은 이전에 hacktHAL을 BBB에 넣었던 것과 동일하게 ADB를 사용하는 것이다.

참고로, 하기 글을 참고하면 hacktHAL을 BBB에 어떻게 넣었는지 확인 할 수 있다.

2019/12/12 - [안드로이드 임베디드/Android for the BeagleBone Black] - Window10에서 ADB Tool을 이용하여 PacktHAL files을 동작하는 Beaglebone Black(BBB)에 넣기

 

Window10에서 ADB Tool을 이용하여 PacktHAL files을 동작하는 Beaglebone Black(BBB)에 넣기

지난번에 Ubuntu에 ADB를 인스톨했지만, 웬지 아직까지는 Window가 편한지라 Window를 이용해서 진행을 해보았다. Android Debug Bidge를 이용하여 현재 동작 중인 Beaglebone Black(BBB)에 PacktHAL files을 넣을..

decdream08.tistory.com

다음과 같은 순서로 실행을 하면 BBB에 adb 명령어를 이용하여 생성한 앱 즉, .apk 파일을 BBB에 넣을 수 있다.

1. 컴파일 후 생성된 .apk 파일을 확인한다. 안드로이드 프로젝트 안에 \gpio\bin 폴더 안에 있을 것이다. 본인의 경우는 하기 그림과 같이 확인 가능했다.

2. Window에서 CMD 창을 열고 adb.exe가 있는 파일로 경로를 변경 한다.

3. BBB 보드를 USB로 PC와 연결한 후 정상적으로 연결되어 adb 명령어를 사용할 수 있는지 다음과 같이 adb devices 명령어를 입력하여 확인 한다.

4. 정상적으로 BBBANDROID가 확인이 되었다면, adb install -d 명령어를 이용하여 #1의 경로에 있는 gpio.apk 파일을 BBB의 Android system에 install 한다.

adb install -d D:\02_Dev_Tools\01_Android\eclipse_workspace\gpio\bin\gpio.apk

위와 같이 Success가 보여진다면, 앱이 정상적으로 BBB에 install 되었다는 것이다.

실제로 BBB를 HDMI 케이블을 이용하여 모니터에 연결 하였을때 메인 화면에 gpio 앱이 깔려 있음을 확인 할 수 있었다.

그리고 마우스를 BBB에 연결하여 gpio 앱을 실행을 하면 다음과 같이 보여진다.

실제로 마우스로 Turn light on을 클릭하면 GPIO30인 P9의 11번 핀이 High로, Turn light off를 클릭하면 Low로 변경되는 것을 확인할 수 있었다.

- 끝.

Overview

바로 이전 글에서 ADB로 hacktHAL 관련 파일을 BBB에서 구동되는 Android image에 넣고, ADB Shell을 이용하여 GPIO를 컨트롤해보았다.

2019/12/18 - [안드로이드 임베디드/Android for the BeagleBone Black] - BeagleBone Black에서 GPIO Control 하기

 

BeagleBone Black에서 GPIO Control 하기

하기와 같이 지난 번에 Window10에서 ADB를 이용하여 BeagleBone Black(BBB)에 PacktHAL 파일들을 넣었다. 2019/12/12 - [안드로이드 임베디드/Android for the BeagleBone Black] - Window10에서 ADB Tool을 이용..

decdream08.tistory.com

이번에는 제목 그대로 Eclipse ADT를 이용하여 실제 Android App을 만들어 BegaleBone Black(BBB)의 GPIO를 컨트롤 하려고 한다.

지난번과 동일하게 Header P9의 핀11(P9.11)과 핀13(P9.13)을 각각 Mode7 설정으로 GPIO30과 GPIO31로 사용할 예정이다.

GPIO를 Control 하기위해서는 PacktHAL(muxed GPIO)을 안드로이드앱에 포함시키는 작업을 해야한다. 그러기위해서는 PacktHAL은 공유된 라이브러리로 .apk 파일 안에 앱과 함께 넣어져야 하며, 공유된 라이브러리로 PacktHAL을 만들려면  java code와는 별도로 분리하여 build를 실행해야 한다.

즉, PacktHAL code는 C native code로 구현됐기에, Android NDK 내부에 제공된 특정 hardware architecture(ARM) Tool chain을 이용하여 build 된다.

참고로, 이렇게 build된 C native code는 Java Native Interface(JNI)를 통해 앱의 Java code에 의해 호출이된다. JNI는 C 데이터 타입을 Java 데이터 타입으로 또는 그 반대로 번역을 해주는 역할을 한다.

Android NDK 다운로드

PacktHAL code를 컴파일 하기 전에, Android NDK를 다음 링크를 이용하여 Download 받아야 한다.

https://developer.android.com/ndk/downloads?hl=ko

 

NDK 다운로드  |  Android NDK  |  Android Developers

개발 플랫폼에 맞는 NDK 패키지를 선택합니다. NDK 최신 버전 및 이전 버전의 변경사항에 관한 정보는 NDK 업데이트 기록을 참조하세요. 안정적인 최신 버전(r20) 플랫폼 패키지 크기(바이트) SHA1 체크섬 Windows 32비트 android-ndk-r20-windows-x86.zip 814417431 b605f7e2e7585af2fc9d59fe9ddad86b64b2bf03 Windows 64비트 android-ndk-r20-windows-x86

developer.android.com

링크가 걸린 페이지를 열고, 제일 밑으로 가면 이전 Version의 NDK를 다운로드 받을 수 있다. 하기의 빨간 네모 안 참고.

최신 버젼이 아닌 이전 버젼을 다운로드 받으려는 이유는, NDK r17 부터 armeabi(ARM v5) 지원을 중단했기 때문이다.

우리가 사용 할 BBB의 Arm core에 대한 지원이 되지 않기때문에, 이전 버젼을 다운받는 것이다.

여튼, 'NDK 자료실'을 클릭하면 하기와 같이 빨간색 네모 안의 '약관에 동의합니다'를 선택한다.

그러면, 여러가지 버젼을 다운 받을 수 있는 곳으로 이동한다. 여기서 본인은 Window10용 Android NDK, 버전 15c를 다운 받았다.

Download 받은 압축된 파일을 PC의 적당한 곳에 풀어 놓았다.

NDK 압축을 해제한 폴더에 SPI 드라이버에 대한 Header 파일을 넣어 두어야 한다. 해당 Header 파일은 첨부 파일로 넣어 두었으니 참고하면 되겠다.

spi.zip
0.00MB

SPI에 대한 Header 파일을 NDK가 깔려있는 위치에서(본인은 'D:\02_Dev_Tools\01_Android\android-ndk-r15c' 이다) 서브 디렉토리인 다음과 같은 경로로 옮기면 된다.

NDK가 있는 폴더\android-19\arch-arm\usr\include\linux

참고로, android-19를 사용하는 이유는 BBB에 올라가 있는 Android version이 Kitkat이고 그에 대한 API Level이 19이기 때문이고, arch-arm인 이유는 BBB의 CPU core가 ARM이기 때문이다.

정상적으로 잘 따라 했다면, linux 폴더에 spi 폴더가 생성이되고, spi 폴더 안에 spidev.h 파일이 있을 것이다.

 

PacktHAL 컴파일

자, 이제 PacktHAL code를 컴파일 하고, 그리고 나서 라이브러리 형태로 앱에 포함하는 것을 연습해 보겠다.

1. eclipse를 열어 'File → New → Android Application Project'를 선택하여 새로운 프로젝트를 하나 만들고, 그 프로젝트 경로를 잘 숙지한다. 본인은 경우는 그 경로는 'D:\02_Dev_Tools\01_Android\eclipse_workspace\myapp\jni'이다.

2. PacktHAL 폴더 안에 jni 폴더를 복사하여 #1에서 만든 프로젝트 경로에 붙여 넣기 한다. 참고로 jni 폴더는 첨부 파일로 넣어 두었으니 참고하면 되겠다. 또 참고로, jini 폴더 안에 있는 파일은 하드웨어를 access하기 위해 만든 c파일들이다.

jni.zip
0.01MB

3. Window에서 CMD 창을 열고 #1에서의 프로젝트 경로로 이동 한후, #2에서 복사한 jni 폴더로 이동을 한다.

4. 해당 디렉토리에서 Andorid NDK를 이용하여 PacktHAL을 빌드한다. 빌드하는 방법은 Android NDK 경로에 있는 ndk-build를 호출하면 된다. 따라서 본인의 경우는 ndk-build가 있는 경로가 'D:\02_Dev_Tools\01_Android\android-ndk-r15c\ndk-build"이므로, 하기와 같이 입력을 하였다.

이제 컴파일이 제대로 되었는지 확인을 해보자.

안드로이드 프로젝트를 생성한 폴더에서 'libs' 폴더를 들어가 보면 여러 개의 폴더가 생성된 것을 알수가 있다. 눈치가 빠른 사람이라면 우리가 jni를 NDK로 컴파일 할때 나온 메세지들과 관련된 폴더들이라는 것을 알 수 있을 것이다.

우리 Target board인 BBB에 해당 되는 TArget은 'ameabi'이므로, 그 폴더에 들어가서 'libpacktHAL.so' 파일이 하기와 같이 정상적으로 생성되었는지를 확인하면 된다.

이 라이브러리를 Android Project에 넣어 사용하면, 실제 안드로이드 앱에서도 라이브러리 안에 jni 폴더의 c 파일들을 이용하여 하드웨어를 제어 할 수 있게된다.

- 계속...

하기와 같이 지난 번에 Window10에서 ADB를 이용하여 BeagleBone Black(BBB)에 PacktHAL 파일들을 넣었다.

2019/12/12 - [안드로이드 임베디드/Android for the BeagleBone Black] - Window10에서 ADB Tool을 이용하여 PacktHAL files을 동작하는 Beaglebone Black(BBB)에 넣기

 

Window10에서 ADB Tool을 이용하여 PacktHAL files을 동작하는 Beaglebone Black(BBB)에 넣기

지난번에 Ubuntu에 ADB를 인스톨했지만, 웬지 아직까지는 Window가 편한지라 Window를 이용해서 진행을 해보았다. Android Debug Bidge를 이용하여 현재 동작 중인 Beaglebone Black(BBB)에 PacktHAL files을 넣을..

decdream08.tistory.com

정상적으로 PacktHAL을 BBB에 넣었다면, ADB Shell을 이용하여 PacktHAL에 의해 output으로 설정된 GPIO30을 컨트롤 할 수 있다.

아래 BeagleBoard Manual(https://cdn-shop.adafruit.com/datasheets/BBB_SRM.pdf)에서 발췌한 P9 connector에 대한 자료에서 보듯이, GPIO30은 BBB 보드의 P9 connector에서 11번 핀이다(P9.11).

이제, Eclipse에서 사용하는 ADB.exe가 위치한 경로를 파악한다. 본인의 경우는 경로가 D:\02_Dev_Tools\01_Android\eclipse_SDK\platform-tools이다.

윈도우에서 CMD 창을 열고 ADB.exe가 위치한 경로로 이동한 후, BBB를 USB케이블로 PC와 연결한다.

BBB가 정상 부팅이 된 후, 아까 열었던 윈도우 CMD 창에서 하기와 같이 adb devices를 입력하여 현재 연결된 Android 기기를 검색한다.

BBB가 정상적으로 연결되었다면, 위의 그림과 같이 adb devices 명령어로 BBB가 검색이 될 것이다.

이제 준비는 마쳤고, 다음과 같은 순서로 명령어를 입력하면 된다.

   1. adb shell 을 입력한다.

$adb shell

   2. BBB의 gpio30 폴더로 이동한다.


root@beagleboneblack:/ # cd /sys/class/gpio/gpio30

3. echo CMD를 이용하여 강제로 GPIO30을 1(High)로 셋팅 한 후, 0(Low)로 셋팅 한다.

root@beagleboneblack:/ # echo 1 > value

root@beagleboneblack:/ # echo 0 > value

실제로 P9 커넥터의 11번 핀(GPIO30)이 default value인 Low에서 High로 셋팅되고, 그다음 다시 Low로 가는 것을 오실로스코프로 확인할 수 있었다.

참고로, PacktHAL에 의해 GPIO31은 input으로 설정이 되어 있으며, 다음 명령어를 사용하면 GPIO31의 값을 읽을 수 있다.

root@beagleboneblack:/ # cat value

 

- 끝.

참고로, HAL의 다양한 부분들은 전형적으로 C/C++로 만들어졌고 각각의 디바이스 밴더는 HAL을 구현하는데 책임이있다고 한다(?)....

전형적인 완전한 HAL을 생성하는 방법은 다음과 같다.

  1. 하드웨어를 컨트롤하기 위한 Linux kernel device driver를 개발 또는 확인한다.
  2. 그 driver의 환경을 설정하고 예시를 하는 Device Tree Overlay를 만든다.
  3. 그 Kernel device driver와 인터페이스 하는 user space libarary를 개발한다.
  4. userspace library를 위한 JNI binding을 개발한다.
  5. 하드웨어와 인터페이를 위한 JIN binding을 사용하는 Android manager를 개발한다.

Android Kernel Vs Linux Kernel

안드로이드 커널은 전형적인 리눅스 커널에서 찾을 수 없는 몇 가지 추가 기능을 포함하고 있다. 그것은 Binder IPC와 low-memory keller이다. 그러나 이것을 제외하고는 안드로이드 커널은 여전히 리눅스 커널이라고 말할 수 있다.

안드로이드 커널이 위의 몇 가지 기능을 제외하고 리눅스 커널과 같다는 것은 커다란 이점이 있다. 그것은 리눅스 커널에 이미 특정 리눅스 드라이버가 존재 한다면, 안드로이드 드라이버가 있다는 것과 동일한 말이다.

카메라, 오디오, 비디오, 버튼 그리고 터치스크린 등등... 이미 존재하는 리눅스 드라이버들을 가져다 이용하는 것은 안드로이드 지원을 더욱 쉽게 만들어 준다.

그러나 전형적인 리눅스 배포판이 어플리케이션들에 많은 다른 디바이스 파일들(/dev filesystem 안에 직접 파일 열기로) direct access를 허용하는 것과는 다르게, 안드로이드는 하드웨어를 직접 접근하는 것을 제한한다.

예를 들어 서로 다른 안드로이드 앱들이 음악 재생 이나 녹음을 위해 오디오 기능을 사용한다면, 안드로이드 아래에 리눅스 커널은 Advanced Linux Sound Archtecture(ALSA) 오디오 드라이버를 통해 이 오디오 기능을 제공한다. 대부분의 경우 한번에 하나의 프로세스만 ALSA 드라이버 자원을 열고 컨트롤 할 수 있다. 만약 각각의 앱들이 ALSA 드라이버 리소스에 접근을 하고 사용을 한다면, 문제가 발생할 것이다. 그 중 하나의 앱이 쉽게 ALSA 드라이버 리소스를 갖을 수 있다면, 그리고 다른 앱들의 접근을 막는다면... 문제가 커질것이다. 이 문제를 해결하기 위해 안드로이드는 managers를 사용 한다.

 

Android managers

매니져들은 모든 app들을 대신 해서 하드웨어 디바이스들을 컨트롤 하는 시스템의 구성 요소이다. 매니져들은 각각의 오디오/비디오/통신 등등의 리소스들과의 인터페이스와 할당을 책임지고, 앱이 그 리소스를 사용할 권한이 있는지를 정의 한다.

리소스를 사용하기 위해서, 입은 반드시 android.content.Context class의 getSystemService() 매써드를 통해 알맞은 매니져를 참조 생성해야 한다.

// Create a reference to the system "location" manager

LocationManager locationManager = (LocationManager) 

  mContext.getSystemService(LOCATION_SERVICE); 

그리고 나서, 이 매니져 레퍼런스를 통해 정보를 만들고 요청들을 컨트롤한다.

// Query the location manager to determine if GPS is enabled

isGPSEnabled = locationManager.

isProviderEnabled(LocationManager.GPS_PROVIDER);

앱들은 Java Android API를 이용해서 매니져들과 상호작용을 한다.

그리고 매니져들은 이런 Java 매써드에 응답하는 동안에, 하드웨어와 직접적으로 상호작용을 하는 native code를 호출하기 위해 결국은 Java native interface(JNI)를 사용해야만 한다. 여기서, 안드로이드 API와 native code를 호출하는 것 사이의 다리는 hardware abstraction layer(HAL)로 알려져 있다.

아래 글에 대한 원문은 아래 링크임을 먼저 밝혀 둡니다.

https://learn.adafruit.com/introduction-to-the-beaglebone-black-device-tree/overview

 

Introduction to the BeagleBone Black Device Tree

The BeagleBone Black uses the Device Tree to describe the hardware for the system. It also uses it in user-space for accessing GPIO's, PWM, UART, SPI and more in real-time by using device tree overlays.

learn.adafruit.com

위 원문 내용을 간략하게 필요한 부분만 추려서 정리하였습니다.


Overview

Device Tree(DT) 그리고 Device Tree Overlay(DTO)는 하나의 시스템에서 하드웨어를 설명하는 하나의 방법이다. 이에 대한 예는 그 시스템이 UART와 어떻게 인터페이스 하는지, 그 핀들이 어떻게 Mux 되는지, 어떻게 그 디바이스를 enable하는지 그리고 어떻게 그 드라이버를 사용하는지를 설명하는 것이다.

참고로, 원래 BeagleBone은 DT를 사용하지 않았지만, 그 이후 출시된 BeagleBone Black(이하 BBB)이 Linux Kernel 3.8을 사용하면서 DT를 사용하게 되었다.

다음 내용으로 부터 그 개념들을 분석 하려고 시도할 것이고, 어떻게 그리고 왜 우리가 DT를 사용하기 원하는지에 대한 예제들을 보여 줄 것이다.

Device Tree Background

ARM component들을 둘러싼 리눅스 커널 안에서 과거 몇년 동안 리눅스를 사용한 ARM 시스템에서는 많은 혼동과 갈등이 있었고 이는 ARM 보드 파일들을 대체하는 평면 Device Tree를 사용하는 새로운 ARM 보드를 이끌어 냈다.

DT와 관련해 밝혀진 하나의 이슈는 DT가 run-time 동안 그 시스템(muxing pins, enabling devices 등등)을 수정이 필요한 Open embedded system으로 디자인 되지 않았다는 것이다. 그래서 Pantelis Antoniu는 하나의 솔루션을 구현 했는데, 이것은 device tree overlay들과 cape manager를 사용하는 것이다. 그 이후, Grant Likely는 user-space로 부터 run-time 동안 DT의 수정을 허용하는 것 "존재하는 dtb data format으로 부터 직접 확장"이었던 새로운 device tree overlay format에 대해 허용하는 시스템을 제안했다.

이에 대해 더 자세한 역사는 하기를 참고.

https://github.com/jadonk/validation-scripts/tree/master/test-capemgr
https://docs.google.com/document/d/17P54kZkZO_-JtTjrFuVz-Cp_RMMg7GB_8W9JK9sLKfA/pub

 

Beaglebone and the 3.8 Kernel

Beaglebone and the 3.8 Kernel Pantelis Antoniou <panto@antoniou-consulting.com> Additional content by Tom King <ka6sox@gmail.com> Matt Porter <matt.porter@linaro.org> v1.0 Introduction The Beaglebone Black is the new addition to the Linux ARM development b</matt.porter@linaro.org></ka6sox@gmail.com></panto@antoniou-consulting.com>

docs.google.com

 

Device Tree Overlays

아래는 BBB의 UART1 device에 대한 device tree overlay이다. 이것은 P9_24와 P9_26 핀들 위의 UART1을 알맞게 enable하기 위해 필요한 알아야 할 것들 모든것을 kernel에게 말하고 있다.

한 가지 확실히 해둘것은, register offset들과 mux mode들을 밝힐 수 있는 최신 데이터를 사용하고 있는지를 확실히 해둬야 한다. 참고로, 이 링크에서 좋은 reference가 될 수 있는 BoneScript pin reference를 찾을 수 있다. https://github.com/jadonk/bonescript/blob/master/src/bone.js

 

jadonk/bonescript

Scripting tools for BeagleBone and PocketBeagle. Contribute to jadonk/bonescript development by creating an account on GitHub.

github.com

- BBB UART1 Device Tree Overlay

/*
 * Copyright (C) 2013 CircuitCo
 *
 * Virtual cape for UART1 on connector pins P9.24 P9.26
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
/dts-v1/;
/plugin/;
 
/ {
   	compatible = "ti,beaglebone", "ti,beaglebone-black";
 
        /* identification */
        part-number = "BB-UART1";
        version = "00A0";
 
        /* state the resources this cape uses */
        exclusive-use =
                /* the pin header uses */
                "P9.24",        /* uart1_txd */
                "P9.26",        /* uart1_rxd */
                /* the hardware ip uses */
                "uart1";
 
        fragment@0 {
                target = <&am33xx_pinmux>;
                __overlay__ {
                        bb_uart1_pins: pinmux_bb_uart1_pins {
                                pinctrl-single,pins = <
                                        0x184 0x20 /* P9.24 uart1_txd.uart1_txd MODE0 OUTPUT (TX) */
                                        0x180 0x20 /* P9.26 uart1_rxd.uart1_rxd MODE0 INPUT (RX) */
                                >;
                        };
                };
        };
 
	fragment@1 {
                target = <&uart2>;	/* really uart1 */
                __overlay__ {
                        status = "okay";
                        pinctrl-names = "default";
                        pinctrl-0 = <&bb_uart1_pins>;
                };
        };
};

위에 표시된 overlay는 "tree structure of nodes and properties"이다.

이제 위의 oevlay를 하나씩 세분화하여 분석해본다.

첫 번째 섹션은 단지 옵션인 코멘드이지만, 주로 copyright/license 정보에 대한 그리고 이 코드가 무엇을 제안하는지를 이해하기 쉽게 하는 부분이다.

/*
 * Copyright (C) 2013 CircuitCo
 *
 * Virtual cape for UART1 on connector pins P9.24 P9.26
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

그 다음 두개 라인들은 dts 파일의 버젼과 그것을 플러그인을 설명해 준다.

/dts-v1/;
/plugin/;

그 다음 라인은 DT의 root node의 시작을 설명해 준다.

/ {

"compatible" 라인이 설명하는 것은 호환성이 가장 낮은 것 부터 시작하는, 함께 작업하기 위해 디자인된 DT overlay이다. 여기에 언급되지 않은 어떤 플랫폼들은 로드가 실패할 것이기 때문에, 우리가 지원하고 싶은 모든 플랫폼의 이름을 여기에 기입하는 것은 중요하다.

compatible = "ti,beaglebone", "ti,beaglebone-black";

다음 섹션인, part-number와 version은 알맞은 DT overlay가 로드 될 수 있게 보장하는 추가 안전 장치이다.

/* identification */
part-number = "BB-UART1";
version = "00A0";

exclusive-use 속성은 우리가 필요로 하는 자원들과 다른 어떤 overlay들이 그런 자원들을 사용하는 것을 피하기위해 기입을 하는 것이다. 이 경우, 우리는 P9.24과 P9.26을 UART1 디바이스로 사용하고 있다.

/* state the resources this cape uses */
        exclusive-use =
                /* the pin header uses */
                "P9.24",        /* uart1_txd */
                "P9.26",        /* uart1_rxd */
                /* the hardware ip uses */
                "uart1";

그 다음으로는 device tree fragment들이다. 이것들은 overlay할 타겟을 설명하고 그리고 나서 각각의 fragment는 mux pin들 이거나 또는 enable device들로 사용자 지정 할 것이다. 아래 fragment는 복잡해 보이지만 그렇게 나쁘진 않다. 첫 번째는 이 fragment의 Target이 overlay 될 예정이라는 것을 우리가 설정하고 있다는 것이다. 이 경우, pinctrl-single 드라이버와 호환되는 am33x_pinmux 이다. 어떻게 이 드라이버를 사용하지에 대한 예제들은 pinctrl-single documentation page에서 찾을 수 있다.

그 다음 라인은 __overlay__ node 그 자신이다. 해당 노드 내부에 그 첫 번째 속성은 다음 fragment(bb_uart1_pins)에 사용 될 것이고, pinctrl-single 드라이버에 의해 조정되는 그 핀들 muxing에 대한 정의를 포함한다. 우리는 그 documentation page의 설명을 통해 어떻게 설정 할지를 알 수 있다.

  • pinctrl-single에 대한 pin configuration node들은 pinctrl register offset과 pinctrl-single,pins에 사용되는 value 쌍으로서 지정된다. 오직 pinctrl-single,function-mask에 지정된 비트들만이 업데이트 된다. 예를 들어, 디바이스 하나에 대한 핀 한개 설정은 pinctrl-single,pins=<0xdc 0x118>;로 완료될 것이다.여기서 0xdc는 그 디바이스 pinctrl register에 대한 pinctrl register base address로부터의 offset이고, 0x118은 pinctrl register의 희망하는 값을 포함한다.

pinctrl-single, pins 값 블럭 내부에서, 값들의 두 행은 UART1 디바이스를 위해 그 핀들을 설정하고 있다. 이 경우, MODE0로써 P9_24는 OUTPUT(Tx)가 될 것이다. 마찬가지로 MODE0로써 P_26은 INPUT(RX)가 될 것이다. 그 pin reference for BoneScript croos-referencing에 의해 P9_24를 0x184로 설정 할 필요가 있다고 말할 수 있다.

 

fragment@0 {
                target = <&am33xx_pinmux>;
                __overlay__ {
                        bb_uart1_pins: pinmux_bb_uart1_pins {
                                pinctrl-single,pins = <
                                        0x184 0x20 /* P9.24 uart1_txd.uart1_txd MODE0 OUTPUT (TX)  */
                                        0x180 0x20 /* P9.26 uart1_rxd.uart1_rxd MODE0 INPUT (RX)  */
                                >;
                        };
                };
        };

마지막 fragment는 그 uart device를 활성화 한다. overlay에 대한 그 target은 uart2(실제로 uart1으로 주석처리 됨)이다. 또한 이전 프래그먼트 속성 (bb_uart1_pins)을 참조하여 pinctrl 드라이버로 활성화 된 핀을 uart 장치에 매핑합니다.

	fragment@1 {
                target = <&uart2>;	/* really uart1 */
                __overlay__ {
                        status = "okay";
                        pinctrl-names = "default";
                        pinctrl-0 = <&bb_uart1_pins>;
                };
        };

이것은 매우 압도적이며 실제로 모호한 것처럼 보일 수 있다. 원하는 작업에 대한 새 오버레이를 만드는 가장 쉬운 방법은 이미 수행하려는 작업에 가까운 오버레이로 시작하는 것이다. 이것을 찾기 위한 가장 좋은 장소는 /lib/firmware (Angstrom)이며, 사용을 위해 이미 만들어진 오버레이를 잘 살펴보면 된다.

Exporting and Unexporting an Overlay

다음의 예제는 디폴트 Angstrom distribution을 사용한 데모이다.

먼저, 디폴트로 이용 가능한 모든 device tree를 보기위해 /lib/firmware를 확인해라.

root@beaglebone:~# cd /lib/firmware
root@beaglebone:/lib/firmware# ls -ltr
total 888
...

여기서 몇몇의 이용 가능한 overlay들을 볼 수 있다. 그 소스(dts) 그리고 컴파일된 파일(dtbo)는 해당 디렉토릭 안에 있다.

그 내용을 보기 위해 소스파일들 중에 하나를 열어 본다. 그 overlay 그들 자신은 잘 묘사되어 있고 잘 설명되어 있다.

자 이제 이전 페이지를 통해 살펴 봤던 BB-UART1-00A0.dts 파일을 사용한다.

우리는 .dts 파일을 볼 수 있었지만, 우리는 그것이 포함한 것을 이미 알고 있다. 그곳에 우리가 이용 가능한 이미 컴파일된 .dtbo 파일이 있다는 그 사실의 이점을 이용해 보자. 미래 섹션에서 우리가 소유한 것 중 하나를 빌드하고 컴파일 할 것이다.

자, bone cape manager에 의해 활성화 된 overlay들을 볼 수 있는 곳으로 이동하자.

root@beaglebone:/lib/firmware# cd /sys/devices/bone_capemgr.*

우리가 그 숫자가 무엇인지 알 수 없으므로 위의 *가 필요하다. 그 것은 부팅 순서에 의존한다. /sys/devices/bone_capemgr.8/slots뿐만 아니라 /sys/devices/bone_capemgr.9/slots 경로를 본적이 있다. 특정 경로가 무엇인지 확인해야 한다.

다음은 그 슬롯 파일의 그 내용들을 cat 한다.

root@beaglebone:/sys/devices/bone_capemgr.8# cat slots

Anstrong installation을 매우 많이 조작해 본적이 없다면, 이것처럼 보일 것이다.

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

BeagleBone docementaion에 의하면 최초 3 슬롯들은 그 cape들 위에서 EEPROM ID들로 할당되었다. 그 다음 2개는 boot시 로드되는 overlay들이다. 숫자 4는 Angstrom 배포판으로 부터 부팅할 가능성이 높게 빌트된 EMMC memory이다. 그 다섯번째 overlay는 HDMI component 활성화에 대한 것이다.

우리의 선호하는 UART1의 overlay처럼, 이제 또 다른 overlay를 내보낸다면, 숫자 6과 같이 리스트된 새로운 옵션을 볼 수 있을 것이다. 그 UART1 dtbo 파일 내보내기를 시도해 보자.

root@beaglebone:/sys/devices/bone_capemgr.8# echo BB-UART1 > slots

에코 출력인 "BB-UART1"을 취하고 있고, 그것을 slots 파일에 쓰고 있다. 왜냐하면, 그 overlay를 사용한 UART1에 대해 그 드라이버들과 디바이스 활성하기 위해서이다. 이제 그 overlay가 알맞게 로드되었는지 확인해 보자.

root@beaglebone:/sys/devices/bone_capemgr.8# cat slots

이제 UART1 device를 로드 하고, 준비가 됐다.

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,BB-UART1

이제 우리는 UART1 디바이스 사용하기를 완료 했고, 다른 무언가에 대해 그런 핀들이 필요하다고 말해보자.

그 overlay를 제거하기 위한 하나의 방법은 BBB를 재시동 거는 것이다. 다른 방법은 overlay를 내보내는 것을 취소 하는 것이다.

다음 command를 실행하는 것으로 overlay를 내보내기 할 수 있다.

root@beaglebone:/sys/devices/bone_capemgr.8# echo -6 > slots

우리는 6번째로 리스트된 옵션을 가졌고, 그 이전에 '-'를 입력한다. 그리고 그 slots 파일에 쓴다.

한 가지 알아 두어야 할 것은 Angstrom의 6-20-2013 릴리즈에서 다양한 overlay들의 언로딩은 커널 패닉을 야기할 수 있고, capemgr를 예상할 수 없게 만들면서 ssh 세션을 잃는 것을 야기 한다. 이 문제가 해결 될때 까지 overlay들을 unload하기 위해 system을 재시동하는 것을 권장한다. 

이제 우리는 시스템 재시동은 overlay들을 unload하는 것을 야기할 것이라는 걸 알고있다. 시스템이 부트 업될때, 어떻게 하면 우리는 overlay들을 로드할 수 있을까?

이건 정말 간단한 문제이다. 우리가 필요로 하는 모든 작업은 BBB에 작은 FAT 파티션 안에 uEnv.txt에서 overlay들을 참조하는 것이다.

다음 과정은 UART1 overlay에 대해 이것을 어떻게 진행하는지 보여준다.

mkdir /mnt/boot
mount /dev/mmcblk0p1 /mnt/boot
nano /mnt/boot/uEnv.txt
#append this to the end of the single line of uEnv.txt (not on a new line):
capemgr.enable_partno=BB-UART1

 

Compiling an Overlay

이제 우리는 메뉴얼로 하나의 overlay를 활성화했다. SPI0 디바이스와 버스를 활성화하기에 대한 Adafruit BBIO 파이썬 라이브러리 안에 사용된 그리고 생성된 하나의 overlay를 취해보자. the Adafruit Github repository for Adafruit_BBIO에서 이 overlay의 최신 복사본을 찾을 수 있다.

아래는 우리가 컴파일 그리고 활성화에 사용할 SPI0에 대한 overlay 복사본이다.

/dts-v1/;
/plugin/;
 
/ {
    compatible = "ti,beaglebone", "ti,beaglebone-black";
 
    /* identification */
    part-number = "ADAFRUIT-SPI0";
 
    /* version */
    version = "00A0";
 
    fragment@0 {
        target = <&am33xx_pinmux>;
        __overlay__ {
            spi0_pins_s0: spi0_pins_s0 {
                pinctrl-single,pins = <
                  0x150 0x30 /* spi0_sclk, INPUT_PULLUP | MODE0 */
                  0x154 0x30 /* spi0_d0, INPUT_PULLUP | MODE0 */
                  0x158 0x10 /* spi0_d1, OUTPUT_PULLUP | MODE0 */
                  0x15c 0x10 /* spi0_cs0, OUTPUT_PULLUP | MODE0 */
                >;
            };
        };
    };
 
    fragment@1 {
        target = <&spi0>;
        __overlay__ {
             #address-cells = <1>;
             #size-cells = <0>;
 
             status = "okay";
             pinctrl-names = "default";
             pinctrl-0 = <&spi0_pins_s0>;
 
             spidev@0 {
                 spi-max-frequency = <24000000>;
                 reg = <0>;
                 compatible = "spidev";
             };
             spidev@1 {
                 spi-max-frequency = <24000000>;
                 reg = <1>;
                 compatible = "spidev";
             };
        };
    };
};

위의 오버레이를 빠르게 살펴보면, UART1에 대한 오버레이와 같이, 동일한 패턴을 따르는 것을 볼 수 있다. 그곳에는 두 개의 fragment들이 있으며 첫 번째것은 pinctrl-single 드라이버를 사용하여 핀을 mux합니다. 우리는 SPI0 핀 중 4 개를 사용하고 모든 것을 Mode 0으로 설정한다. 그런 다음 fragment@1은 적절한 핀들로 spi0 device를 대상으로하며 그리고 'spi-max-frequency'와 같은 spi device를 사용하는 것에 특수한 다양한 parameter들을 설정한다. spi-bus documentation에서 사용 가능한 옵션을 볼 수 있다.

Home 디렉토리로 이동하고 복사 그리고 새로운 파일을 붙여 넣기 하기 위해 nano를 연다. 아래와 이름과 마찬가지로 정확하게 저장해야 한다.

root@beaglebone:/tmp# cd ~
root@beaglebone:~# nano ADAFRUIT-SPI0-00A0.dts

다음으로, 우리는 device tree overlay 컴파일된 포맷(.dtdo)안에 이 파일을 컴파일 하기 위해 명령어를 실행한다.

dtc -O dtb -o ADAFRUIT-SPI0-00A0.dtbo -b 0 -@ ADAFRUIT-SPI0-00A0.dts

컴파일은 거의 즉각적이어야하며 새롭게 컴파일 된 파일로 끝나야 한다.

root@beaglebone:~# ls -ltr
...
-rw-r--r-- 1 root root 1255 Jul 29 14:33 ADAFRUIT-SPI0-00A0.dts
-rw-r--r-- 1 root root 1042 Jul 29 14:35 ADAFRUIT-SPI0-00A0.dtbo

오버레이를 컴파일하는 데 사용되는 옵션을 분석해 보자.

우선, device tree compiler (dtc)를 사용한다. DT overlay를 컴파일하는 데 요구되는 모든 것이 최신 Angstrom 배포판에 포함되어 있다.

  • -O dtb는 출력 형식이다. device tree binaries를 출력하고 있다.
  • -o는 출력 파일 이름이다.
  • -b 0은 physical boot CPU를 설정한다. (0)
  • -@은 overlay의 동적 DT 로딩의 일부로 하나의 심볼 노드를 생성한다.

컴파일러가 누락 된-@ 플래그에 대해 complain할 경우 충분히 새로운 dtc 버전이 없는지 알 수 있다. 다음을 실행하여 dtc 업그레이드를 시도 할 수 있다 (현재 우분투에서 수행해야 할 수도 있음).

wget -c https://raw.githubusercontent.com/RobertCNelson/tools/master/pkgs/dtc.sh
chmod +x dtc.sh
./dtc.sh

Beaglebone Black(이하 BBB) 회로도는 다음 사이트에 링크가 되어 있다.

https://github.com/beagleboard/beaglebone-black/blob/master/BBB_SCH.pdf

 

beagleboard/beaglebone-black

Design and Document files for the BeagleBone Black from BeagleBoard.org - beagleboard/beaglebone-black

github.com

여기에서 미리보기 및 다운로드가 가능하다.

다운로드는 하기 그림의 빨간색 네모 안에 Download를 입력하면 된다.

 

                             

 

 

+ Recent posts