一:Android簡介
1.什麼是Android:
Android是一種基于linux的自由及開放源代碼的作業系統,主要适用于移動裝置,如智能手機和平闆電腦,是由google公司和開放手機聯盟上司和開發;
Android的系統架構和其作業系統一樣,采用了分層的架構從架構圖看,Android分為四個層:從高層到低層分别是應用程式層、應用程式架構層、系統運作庫層和Linux核心層。如下圖所示:
(1)應用程式層:所有安裝在手機上的應用程式都是屬于這一層的,就是一些應用程式(apk)
(2)應用程式架構層:這一層主要提供了建構應用時可能用到的API,Android自帶的一些核心應用程式就是使用這些API完成的,開發者可以通過使用這些API建構自己的應用程式。比如有活動管理器、View系統。内容提供器、通知管理器等。
(3)系統運作庫層:這這一層主要包含的是C/C++庫來為Android系統提供了主要的特性支援,比如SQLite庫提供了資料庫的支援,同時還它提供了一些核心庫,能允許開發者使用Java來編寫Android應用,關鍵是Dalvik虛拟機,它使得我們每一個Android應用都能運作在獨立的程序當中,并且擁有一個自己的Dalvik虛拟機執行個體,相比Java虛拟機(JVM),Dalvik是專門為移動裝置定制的,它對手機記憶體、CPU性能有限等情況做了優化處理;
(4)Linux核心層:s3c6410闆子上面跑的是Android2.2+linux-2.6.35;
Tiny4412:Android4.2.2 + linux-3.5; 這一層為Android裝置的各種硬體提供了底層的驅動,如顯示驅動、音頻驅動、照相機驅動、藍牙驅動、WiFi驅動、電源管理;
二、Android手機的移植
1、編譯Android源碼
- 在編譯android原代碼之前要解除安裝系統原有的openjdk,安裝sun公司的jdk 1.5 (為了支援以後的Android上層的應用開發;)
yum remove openjdk*
yum remove gcc-java
安裝jdk-1.5
rpm -ivh jdk-1.x-xxx.rpm
在此之前還需要配置yum 源(一般為163源,更新比較快)
2、設定環境變量
vim /etc/profile
加入:
PATH=$PATH:/usr/local/arm/4.5.1/bin
export JAVA_HOME=/usr/java/jdk1.5.0_22
export JRE_HOME=${JAVA_HOME}/jre
exportCLASS_PATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib:$CLASS_PATH
export JAVA_PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin
export PATH=${JAVA_PATH}:$PATH
現在就可以進入android2.2源碼寶包進行編譯了
cd .../android2.2
make
在編譯android的過程中可能會遇到 :
gperf : command not found
gperf指令沒有,于是乎就要安裝,需要下載下傳gperf包:
tar xf gperf *. tar.gz
./configure
make
make install
至此就靜等android編譯完畢(這個過程大概要4個小時左右)
3.編譯Android核心(Linux-2.6.35)
在編譯整個android結束後,就可以開始核心的編譯了
vim Makefile
配置相應的編譯平台及編譯器
ARCH ?= arm
CROSS_COMPILE ?=/home/android/android1/android-2.2_froyo/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-
make
4.燒寫bootloader
- 設定sd卡啟動,燒寫bootloader到sd卡
- 在闆子上選擇sd卡啟動
- 安裝minicom軟體(配置Minicom -s)
- pc機上運作指令 minicom -s 選擇第三個(配置如下圖)
- 安裝設定好tftp
yum install xinetd
yum install tftp
yum install-sever
配置tftp服務:
vim vi /etc/xinetd.d/tftp
disable = no
重新開機服務:
service xinetd restart
6.燒寫bootloader到nandflash
将u-boot-nand.bin拷貝到 /var/lib/tftp目錄下:
進入minicom
闆子上面:tftp 52000000 u-boot-nand.bin
nand erase clean
nand write 52000000 0 3000
重新開機闆子設定為nand falsh啟動
5.搭建Android nfs 網絡檔案系統到開發闆
安裝nfs服務:
yum install nfs
在pc 機建立根檔案系統目錄
mkdir /work/android/nfsroot
配置nfs
vim /etc/export
/work/android/nfsroot *(rw,no_root_squash)
重新開機 nfs 服務
service nfs restart
将編譯生成的Android源碼的一下檔案拷貝到nfsroot下面
cp root/* /work/android/nfsroot -rf
cp system/ /work/android/nfsroot/system -rf
cp data/ /work/android/nfsroot/data -rf
至此android nfs檔案系統建構完畢
- 設定arm闆的啟動參數
setenv bootargs console=ttySAC0 init=/init root=/dev/nfs nfsroot=192.168.1.10:/work/android/nfsroot ip=192.168.1.20
Saveenv
将編譯生成的核心鏡像copy到/var/lib/tftp
啟動闆子
tftp 50008000 zImage
bootm 50008000
至此整個Android系統就可以在闆子上面跑起來了
三、Android系統簡單的應用程式及驅動的編寫
- Android觸摸屏矯正(核心、Android源碼)
- 首先我們需要在Android上面移植tslib:Tslib是一個開源的程式,能夠為觸摸屏驅動獲得的采樣提供諸如濾波、去抖、校準等功能,通常作為觸摸屏驅動的适配層,為上層的應用提供了一個統一的接口;
- 下載下傳 tslib, ./configure mmm 編
- 配置編譯tslib 拷貝到nfsroot目錄下 ts.conf
- 重新啟動Android (ts_calibrate)
在android核心中運作ts_calibrate
利用ts_calibrate得到7個數值,填充到核心中的數組中,作為計算x,y的坐标的系數
矯正資料在.. nfsroot/system/etc/pointercal
至此觸摸屏就可以工作了
- LED核心驅動的編寫
接下來的工作就是在應用寫一個apk程式,調用Java的動态庫jar,jar在通過jni調用核心中的C庫,實作led的亮、滅
- 編寫apk,jar,jni,kernel_module
- 編譯的一個順序
.so --> jni --> jar -->apk
Android.mk
include $(BUILD_PACKAGE) -->編譯生成apk檔案
include $(BUILD_JAVA_LIBRARY) -->編譯生成動态jar庫
include $(BUILD_STATIC_JAVA_LIBRARY) -->編譯生成靜态jar庫
include $(BUILD_SHARED_LIBRARY) -->編譯生成動态C庫
開發闆
insmod led.ko
chmod 777 /dev/s3c6410_led
代碼如下:
首先了解下如何編譯生成apk,jar,jni檔案
1 #-------------- 1. APK ---------------
2 LOCAL_PATH := $(call my-dir)
3 LOCAL_SRC_FILES := $(call all-subdir-java-files)
4 LOCAL_PACKAGE_NAME := TestEvent
5
6 LOCAL_JAVA_LIBRARIES := cat
7 # in AndroidManifest.xml
8 # <application android:label="@string/app_name" android:icon="@drawable/icon">
9 # <uses-library android:name="cat" />
10 # <activity android:name="TestEvent"
11
12 LOCAL_STATIC_JAVA_LIBRARIES :=
13
14 include $(BUILD_PACKAGE)
15
16 #-------------- 2. static JAR --------
17 LOCAL_PATH := $(call my-dir)
18 LOCAL_SRC_FILES := $(call all-java-files-under, src)
19 LOCAL_MODULE := dog
20
21 LOCAL_JAVA_LIBRARIES :=
22 LOCAL_STATIC_JAVA_LIBRARIES :=
23
24 include $(BUILD_STATIC_JAVA_LIBRARY)
25
26
27 #-------------- 3. shared JAR ----------
28 LOCAL_PATH := $(call my-dir)
29 LOCAL_SRC_FILES := $(call all-java-files-under, src)
30 LOCAL_MODULE := dog
31
32 LOCAL_JAVA_LIBRARIES :=
33 LOCAL_STATIC_JAVA_LIBRARIES :=
34 # in system/etc/permissions/platform.xml
35 # <library name="cat"
36 # file="/system/framework/cat.jar"/>
37
38 include $(BUILD_JAVA_LIBRARY)
39
40 #-------------- 4. static c library -------
41 LOCAL_PATH := $(call my-dir)
42
43 LOCAL_SRC_FILES := test-jni.c
44 LOCAL_MODULE := libtest-jni
45
46 LOCAL_SHARED_LIBRARIES := libc
47 LOCAL_STATIC_LIBRARIES :=
48
49 include $(BUILD_STATIC_LIBRARY)
50
51 #-------------- 5. shared c library -------
52 LOCAL_PATH := $(call my-dir)
53
54 LOCAL_SRC_FILES := test-jni.c
55 LOCAL_MODULE := libtest-jni
56 LOCAL_PRELINK_MODULE := false
57
58 LOCAL_SHARED_LIBRARIES := libc
59 LOCAL_STATIC_LIBRARIES :=
60
61 include $(BUILD_SHARED_LIBRARY)
62
63 #-------------- 6. exectutable ---------------
64 LOCAL_PATH := $(call my-dir)
65
66 LOCAL_SRC_FILES := test.c
67 LOCAL_MODULE := test
68 LOCAL_SHARED_LIBRARIES := libc
69 LOCAL_STATIC_LIBRARIES :=
70
71 include $(BUILD_EXECUTABLE)
led的檔案内容:
apk中的内容:
如下打開main.xml 我們可以制作apk的界面,我這個apk是實作的是兩個按鈕,btn_off, btn_on, 用來控制燈亮/滅 一個textview顯示欄
vim /home/DREAM/src/8nd_led/apk/res/layout/main.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent"
6 >
7 <TextView
8 android:layout_width="fill_parent"
9 android:layout_height="80dp"
10 android:id="@+id/txt"
11 android:textSize="30dp"
12 />
13 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
14 android:orientation="horizontal"
15 android:layout_width="fill_parent"
16 android:layout_height="fill_parent"
17 >
18 <Button
19 android:layout_width="60px"
20 android:layout_height="40px"
21 android:layout_weight="1"
22 android:id="@+id/but_on"
23 />
24 <Button
25 android:layout_width="60px"
26 android:layout_height="40px"
27 android:layout_weight="1"
28 android:id="@+id/but_off"
29 />
30 </LinearLayout>
31 </LinearLayout>
vim /home/DREAM/src/8nd_led/apk/src/bunfly/pratice/Bunfly.java
1 package bunfly.pratice;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.widget.TextView;
6 import android.widget.Button;
7 import android.view.View.OnClickListener;
8 import android.view.View;
9 import com.device.led;
10
11 public class Bunfly extends Activity
12 {
13 TextView txt;
14 Button but_on, but_off;
15 OnClickListener listener; //監聽
16
17 /** Called when the activity is first created. */
18 @Override
19 public void onCreate(Bundle savedInstanceState)
20 {
21 super.onCreate(savedInstanceState);
22 setContentView(R.layout.main);
23 txt = (TextView)findViewById(R.id.txt);
24 but_on =(Button)findViewById(R.id.but_on);
25 but_off = (Button)findViewById(R.id.but_off);
26 txt.setText("Please Click Button");
27 but_on.setText("ON");
28 but_off.setText("OFF");
29
30 listener = new OnClickListener() {
31 public void onClick(View v) {
32 led l;
33 String str;
34 l = new led();
35 if(v == but_on) {
36 str = l.jar_led_on(); //調用jar中的jar_led_on()
37 txt.setText(str);
38 //txt.setText(String.valueOf(ret));
39 }else if (v == but_off) {
40 str = l.jar_led_off();////調用jar中的jar_led_off()
41 txt.setText(str);
42 //txt.setText(String.valueOf(ret));
43 }
44 }
45 };
46 but_on.setOnClickListener(listener);//設定監聽
47 but_off.setOnClickListener(listener);
48
49 }
50 }
JAR程式編寫:
1 package com.device;
2
3 public class led {
4 native String on();
5 native String off();
6
7 static {
8 System.loadLibrary("s3c6410_led");
9 }
10
11 public String jar_led_on() {
12 return on();
13 }
14
15 public String jar_led_off() {
16 return off();
17 }
18 };
JNI程式編寫
1 #include <jni.h>
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include <sys/ioctl.h>
5 #include <string.h>
6
7 #define LED_ON (('Z' << 24) | 1)
8 #define LED_OFF (('Z' << 24) | 2)
9
10 jstring Java_com_device_led_on(JNIEnv *env,
11 jobject thiz)
12 {
13 int fd = open("/dev/s3c6410_led", O_RDWR); //打開led裝置檔案
14 if(fd < 0) {
15 return (*env)->NewStringUTF(env, "open failed");
16 }
17 ioctl(fd, LED_ON); //控制led
18 close(fd);
19 return (*env)->NewStringUTF(env, "led on"); //傳回給jar
20 }
21
22 jstring Java_com_device_led_off(JNIEnv *env,
23 jobject thiz)
24 {
25 int fd = open("/dev/s3c6410_led", O_RDWR);
26 if(fd < 0) {
27 return (*env)->NewStringUTF(env, "open failed");
28 }
29 ioctl(fd, LED_OFF);
30 close(fd);
31 return (*env)->NewStringUTF(env, "led off");
32 }
核心子產品驅動編寫
1 #include <linux/init.h>
2 #include <linux/module.h>
3 #include <linux/io.h>
4 #include <linux/platform_device.h>
5 #include <linux/device.h>
6 #include <linux/miscdevice.h>
7 #include <linux/fs.h>
8 #include <linux/cdev.h>
9
10 MODULE_LICENSE("GPL");
11 MODULE_AUTHOR("bunfly");
12
13 struct led_class {
14 char *name;
15 unsigned long phys;
16 unsigned long gpio_virt;
17 unsigned *gpmcon, *gpmdat;
18 void (*led_on)(struct led_class *);
19 void (*led_off)(struct led_class *);
20 };
21
22 int led_probe(struct platform_device *led_dev);
23 int led_remove(struct platform_device *led_dev);
24 int led_ioctl(struct inode *no, struct file *fp, unsigned int cmd, unsigned long arg);
25 int led_open(struct inode *no, struct file *fp);
26 int led_release(struct inode *no, struct file *fp);
27 void led_dev_release(struct device *dev);
28
29 //led_on
30 void s3c6410_led_on(struct led_class *l)
31 {
32 *(l->gpmcon) &= ~0xffff;
33 *(l->gpmcon) |= 0x1;
34 *(l->gpmdat) = 0x0;
35 }
36
37 //led_off
38 void s3c6410_led_off(struct led_class *l)
39 {
40 *(l->gpmcon) &= ~0xffff;
41 *(l->gpmcon) |= 0x1;
42 *(l->gpmdat) = 0x1;
43
44 }
45
46
47 void init_led_class(struct led_class *l)
48 {
49 l->name = "s3c6410_led"; //裝置檔案名
50 l->phys = 0x7f008000;
51 l->gpio_virt = ioremap(l->phys, SZ_4K); //将實體位址映射為虛拟位址,以4k對齊
52 l->gpmcon = l->gpio_virt + 0x820;
53 l->gpmdat = l->gpio_virt + 0x824;
54 l->led_on = s3c6410_led_on;
55 l->led_off = s3c6410_led_off;
56 }
57
58 struct led_class s3c6410_led;
59 int led_open(struct inode *no, struct file *fp)
60 {
61 return 0;
62 }
63
64 int led_release(struct inode *no, struct file *fp)
65 {
66 return 0;
67 }
68
69 int led_ioctl(struct inode *no, struct file *fp, unsigned int cmd, unsigned long arg)
70 {
71 int ret = 0;
72 #define LED_ON (('Z' << 24) | 1)
73 #define LED_OFF (('Z' << 24) | 2)
74
75 switch(cmd) {
76 case LED_ON:
77 s3c6410_led.led_on(&s3c6410_led);
78 break;
79 case LED_OFF:
80 s3c6410_led.led_off(&s3c6410_led);
81 break;
82 }
83
84 return ret;
85 }
86
87 void destroy_led_class(struct led_class *l)
88 {
89 iounmap(l->gpio_virt); //取消映射
90 }
91
92 /*初始化file_operations*/
93 struct file_operations led_ops = {
94 .open = led_open,
95 .ioctl = led_ioctl,
96 .release = led_release,
97 };
98
99 /*将s3c6410_led注冊到misc類下*/
100 struct miscdevice led_misc = {
101 .minor = 99,
102 .name = "s3c6410_led",
103 .fops = &led_ops, //關聯fangfa
104 };
105
106
107 int led_probe(struct platform_device *led_dev)
108 {
109 int ret = 0;
110 init_led_class(&s3c6410_led);
111 ret = misc_register(&led_misc);//登出led
112 if(ret < 0) {
113 printk("misc_register device failed");
114 }
115
116 return ret;
117 }
118
119 int led_remove(struct platform_device *led_dev)
120 {
121 misc_deregister(&led_misc);
122 destroy_led_class(&s3c6410_led);
123
124 return 0;
125 }
126
127 void led_dev_release(struct device *dev)
128 {
129 printk("device release\n");
130 }
131
132 struct platform_device led_dev = { //在platform總線上注冊名為led的裝置
133 .name = "led",
134 .id = 0,
135 .dev = {
136 .release = led_dev_release,
137 },
138 };
139
140 struct platform_driver led_drv = {//在platform總線上注冊名為led的裝置驅動
141 .driver = {
142 .name = "led",
143 },
144 .probe = led_probe,
145 .remove = led_remove,
146 };
147
148 int bunfly_init()
149 {
150 int ret = 0;
151 printk("bunfly_init");
152 platform_device_register(&led_dev);//注冊裝置
153 platform_driver_register(&led_drv);//注冊裝置驅動
154
155 return ret;
156 }
157
158 void bunfly_exit()
159 {
160 s3c6410_led.led_off(&s3c6410_led);
161 platform_device_unregister(&led_dev);//登出裝置
162 platform_driver_unregister(&led_drv);//登出裝置驅動
163 }
164
165 module_init(bunfly_init);
166 module_exit(bunfly_exit);
本地可執行程式測試led:
1 #include <stdio.h>
2 #include <fcntl.h>
3 #include <sys/ioctl.h>
4 #include <sys/types.h>
5
6 int main(int argc, char **argv)
7 {
8 #define LED_ON (('Z' << 24) | 1)
9 #define LED_OFF (('Z' << 24) | 2)
10 int fd;
11 fd = open("/dev/s3c6410_led", O_RDWR); //打開裝置檔案
12 ioctl(fd, LED_ON); //用ioctl控制燈
13 close(fd); //關閉檔案
14
15 return 0;
16 }
- Android ALSA聲霸卡驅動的移植
-
- 下載下傳ALSA源碼包
- git clone git://android.git.kernel.org/platform/external/alsa-lib.git
- git clone git://android.git.kernel.org/platform/external/alsa-utils.git
- git clone git://android.git.kernel.org/platform/hardware/alsa_sound.git
- 用mmm單獨編譯
- 将alsa-lib、alsa-utils 、alsa_sound 分别拷貝到Android下的external 及hardware 目錄下
播放聲樂沒有聲音
(4)編輯build/target/gerneric/Board/Config.mk
注釋原來的兩行,添加新的,如下:
#HAVE_HTC_AUDIO_DRIVER := true
#BOARD_USES_GENERIC_AUDIO := true
BOARD_USES_ALSA_AUDIO := true
BUILD_WITH_ALSA_UTILS := true
編譯 make clean
make
重新編譯Android源碼:再次啟動Android就可以播放音樂了;
四、将Android系統燒錄到nandflash 中
- 需要用靜态連結編譯busybox
- 将整個nfsroot目錄拷貝到nandfalsh的第三個分區中
busybox mount -t yasff2 /dev/mtdblock3 /mnt
更改權限:chmod 777 /mnt * - R
nand erase 、nand write、nand read
設定闆子啟動參數:
Setenv bootargs console=ttySAC0 root=/dev/block/mtdblock3 init=/init
31:3
Setenv bootcmd nand read 50008000 10000 400000\; bootm 50008000
Setenv bootdelay 3
Saveenv
至此整個Android系統移植完畢:
轉載于:https://www.cnblogs.com/wenqiang/p/4908599.html