S3C6410板子移植 Android2.2

一:Android简介

1.什么是Android

Android是一种基于linux的自由及开放源代码的操作系统,主要适用于移动设备,如智能手机和平板电脑,是由google公司和开放手机联盟领导和开发;

Android的系统架构和其操作系统一样,采用了分层的架构从架构图看,Android分为四个层:从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和Linux内核层。如下图所示:

1应用程序层所有安装在手机上的应用程序都是属于这一层的就是一些应用程序(apk

2应用程序框架层这一层主要提供了构建应用时可能用到的APIAndroid自带的一些核心应用程序就是使用这些API完成的,开发者可以通过使用这些API构建自己的应用程序。比如有活动管理器、View系统。内容提供器、通知管理器等

3系统运行库层这这一层主要包含的是C/C++库来为Android系统提供了主要的特性支持,比如SQLite库提供了数据库的支持,同时还它提供了一些核心库,能允许开发者使用Java来编写Android应用,关键是Dalvik虚拟机,它使得我们每一个Android应用都能运行在独立的进程当中,并且拥有一个自己的Dalvik拟机实例,相比Java虚拟机(JVM)Dalvik是专门为移动设备定制的,它对手机内存、CPU性能有限等情况做了优化处理;

4Linux内核层:s3c6410板子上面跑的是Android2.2+linux-2.6.35;

Tiny4412:Android4.2.2 + linux-3.5; 这一层为Android设备的各种硬件提供了底层的驱动,如显示驱动、音频驱动、照相机驱动、蓝牙驱动、WiFi驱动、电源管理;

 

二、Android手机的移植

 

1、编译Android源码

  1. 在编译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

  1. 设置sd卡启动,烧写bootloadersd

  2. 在板子上选择sd卡启动

  3. 安装minicom软件(配置Minicom -s

  4. pc机上运行命令 minicom -s 选择第三个(配置如下图)

  5. 安装设置好tftp

yum install xinetd

yum install tftp

yum install-sever

配置tftp服务:

vim vi /etc/xinetd.d/tftp
    disable = no

重启服务:

service xinetd restart

   6.烧写bootloadernandflash

将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文件系统构建完毕

 

  1. 设置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系统简单的应用程序及驱动的编写

  1. Android触摸屏矫正(内核、Android源码)

  1. 首先我们需要在Android上面移植tslibTslib是一个开源的程序,能够为触摸屏驱动获得的采样提供诸如滤波、去抖、校准等功能,通常作为触摸屏驱动的适配层,为上层的应用提供了一个统一的接口;

  2. 下载 tslib, ./configure mmm 编
  3. 配置编译tslib 拷贝到nfsroot目录下 ts.conf

  4. 重新启动Android ts_calibrate

在android内核中运行ts_calibrate

利用ts_calibrate得到7个数值,填充到内核中的数组中,作为计算xy的坐标的系数

矫正数据在.. nfsroot/system/etc/pointercal

 

至此触摸屏就可以工作了

  1. LED内核驱动的编写

接下来的工作就是在应用写一个apk程序,调用Java的动态库jarjar在通过jni调用内核中的C库,实现led的亮、灭

  1. 编写apkjarjnikernel_module

  2. 编译的一个顺序

.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 }

 

  1. Android ALSA声卡驱动的移植

 

    1. 下载ALSA源码包

    2. git clone git://android.git.kernel.org/platform/external/alsa-lib.git

    3. git clone git://android.git.kernel.org/platform/external/alsa-utils.git

    4. git clone git://android.git.kernel.org/platform/hardware/alsa_sound.git

  1. mmm单独编译

  2. alsa-libalsa-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

  1. 需要用静态链接编译busybox

  2. 将整个nfsroot目录拷贝到nandfalsh的第三个分区中

  busybox mount -t yasff2 /dev/mtdblock3 /mnt

  更改权限:chmod 777 /mnt * - R

  nand erase nand writenand 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系统移植完毕:

posted @ 2015-10-25 12:58  zhangwju  阅读(429)  评论(0编辑  收藏  举报