本文主要是以一个早期的移动终端产品案例进行简要地系统移植分析,其中牵涉到多个硬件模块的驱动、framework、app移植与实现。
一.x-loader、u-boot移植
OMAP平台的启动初始化(bootloaders)依次分为了几个的阶段,其启动顺序为:ROM代码、x-loader、u-boot、kernel,如下图所示:
图 1
1. x-loader
a) x-loader代码流程
图 2
b) 编译x-loader
make distclean make ARCH=arm omap44XXpanda_config make ift 2>&1 |tee $MYDROID/logs/x-loader_make.out |
2. u-boot
a) u-boot代码流程
图 3
b) 编译u-boot
make distclean make ARCH=arm omap44XXpanda_config make 2>&1 |tee $MYDROID/logs/u-boot_make.out |
二.eMMC
eMMC ( Embedded Multi Media Card)采用统一的MMC标准接口,文件系统可以在eMMC方式存储。card、core和host这三层的关系如下图:
图 4
驱动程序:
1. u-boot
//board\omap44xxpanda\mmc.c //mmc_read(0)的代码改成mmc_read(mmc_slot); |
2. kernel
//arch\arm\mach-omap2\board-omap4panda.c //添加emmc设备,mmc为2 { .mmc = 2, .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, .gpio_wp = -EINVAL, .gpio_cd = -EINVAL, },
//arch\arm\mach-omap2\board-44xx-power.c //添加设备电源 REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"), |
三.系统分区
Android 系统分为7个区,依次为xloader、bootloader、recovery、boot、system、cache、userdata。使用fastbootoemformat来分区系统,代码位置在uboot
Board\omap44xxpanda\mmc.c
static struct partition partitions[] = { { "-", 128 }, { "xloader", 128 }, { "bootloader", 256 }, { "-", 512 }, { "recovery", 8*1024 }, { "boot", 8*1024 }, { "system", 512*1024 }, { "cache", 256*1024 }, { "userdata", 0}, { 0, 0 }, }; 对应的文件如下: Xloader: MLO Bootloader: u-boot.bin Recovery: recovery.img Boot: boot.img(kernel+ramdisk) System: system.img Cache cache.img Userdata userdata.img
|
四.Busybox
BusyBox可以被自定义化以提供一个超过两百种功能的子集。其属于操作系统上的命令程序。
图 5
BusyBox直接放在Android源码目录下,即可一同编译经android系统内,步骤如下:
1. 获取源码,并编译
wgethttp://busybox.net/downloads/busybox-1.20.2.tar.bz2 ./ tar xvfbusybox-1.20.2.tar.bz2 cd busybox; make; |
2. 拷贝到android系统
cp–a bin android\device\ti\panda |
修改android\device\ti\panda\device.mk
$(shell mkdir out/target/product/panda/system/bin/ -p) $(shellcp device/ti/panda/busybox out/target/product/panda/system/bin/ -R) $(shell cp device/ti/panda/busybox/bin/chat out/target/product/panda/system/bin/ -R) |
3. 修改android环境变量
#修改system\core\rootdir\init.rc export PATH /system/bin/busybox/bin:/system/bin/busybox/sbin:/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin |
五.3G电话模块
通讯模块主要实现底层硬件驱动及RIL框架的支持,RIL在Android体系的位置如下:
图 6
移植3G模块,步骤如下:
a) 移植预编译好的中间层库lib3G-ril-android4.0.4.so到Android系统;
b) 修正ttyUSB的端口权限
#vim ./device/ti/panda/ueventd.omap4pandaboard.rc /dev/ttyUSB* 0777systemsystem |
c) 加入ip-up到etc/ppp/
#vim ./device/ti/panda/device.mk device/ti/panda/ip-up:system/etc/ppp/ip-up \ |
d) 增加message apk
#vim ./device/ti/panda/device.mk PRODUCT_PACKAGES += \ Mms |
e) 添加pppd和chat的权限
#vim ./system/core/include/private/android_filesystem_config.h { 04777, AID_ROOT, AID_RADIO, "system/bin/pppd" }, { 04777, AID_ROOT, AID_RADIO, "system/bin/chat" }, |
六.WIFI模块
图 7
1. WIFI驱动
a) Networking support ---> <*>Generic IEEE 802.11 Networking Stack(mac80211) b) Device Drivers ---> <*>MMC/SD/SDIO card support ---> <*>TI OMAP Multimedia Card Interface support <*>TI OMAP High Speed Multimedia Card Interface support c) [*] Network device support ---> [*] Wireless LAN --- > [*]IEEE 802.11 for Host AP(Prism2/2.5/3 and WEP/TKIP/CCMP) |
2. Android修改
a) 支持WIFI
#vim BoardConfig.mk BOARD_WPA_SUPPLICANT_DRIVER := WEXT |
b) 添加WIFI服务
#vim init.omap4pandboard.rc
Service wpa_supplicant /system/bin/wpa_supplicant–Dwext–imlan0 –dd–c /data/\ Misc/wifi/wpa_supplicant.conf Group system wifiinet Socket wpa_mlan0 dgram 0666 wifiwifi Disabled Oneshot Service dhcpcd_mlan0 /system/bin/dhcpcd–f /system/etc/dhcpcd/dhcpcd.conf–d –B mlan0 Class main Group system dhcpwifi Disabled Oneshot |
在/system/etc/dhcpcd/添加dhcpcd.conf文件,在system/etc/wifi/添加wpa_supplicant.conf文件,内容参考Android/external/wpa_supplicant/下这个两个文件。
c) 修改wifi.c文件,将关于wlan0的替换成mlan0, 将加载的驱动替换我们自己需要替换的驱动名字
d) 将三合一固件拷贝到/system/etc/fireware/mrvl下
七.Bluetooth模块
图 8
1. Bluetooth驱动
[*]Networking support ---> <*> Bluetooth subsystem support ---> <*>Bluetooth subsystem support Bluetooth device drivers ---> <*>HCI SDIO driver <*>HCI VHCI(virtual HCI device)driver |
2. 修改android中间层
a) 在generic.mk增加:
BOARD_HAVE_BLUETOOTH := true |
b) 在init.rc中添加蓝牙服务
Service dbus /system/bin/dbus-daemon –system –nofork Class main Socket dbus stream 0660 bluetoothBluetooth User Bluetooth Group Bluetoothnet_bt_admin Service bluetoothd /system/bin/bluetoothd–n Class main Socket Bluetooth stream 0660 bluetoothBluetooth Socket dbus_bluetooth stream 0660 bluetoothBluetooth |
3. 在init.rc中添加加载驱动
Insmod bt8xxx.ko |
八.FM模块
FM模块是BCM3合一内部集成的一个子模块,FM功能在Android框架中如下图,
图 9
对于FMAPP而言,APP调用JNI接口应同步更新实现。
九.LCD模块
图 10
1. 初始化寄存器。
使用spi接口,修改u-boot,dss驱动。
2. 内核移植
a) 添加lcd设备
//kernel\arch\arm\mach-omap2\board-omap4panda.c static structpanel_generic_dpi_datalcd_panel = { …… }; static structomap_dss_device omap4_panda_lcd_device = { …… }; |
添加lcd时序
//kernel\drivers\video\omap2\displays\panel-generic-dpi.c /* ld070ws2 */ { ……}, |
十.触摸屏
触摸屏设备功能框架图如下:
图 11
3. 触摸屏驱动
a) 硬件
兼容TSC200X驱动电阻触摸屏
b) 驱动程序
添加触摸屏驱动,在kernel中加入tsc驱动。
Device Driver ---> Input device support ---> Touchscreens ---> [*] TSCbased touchscreens |
//添加设备
struct tsc_platform_data tsc_info = {
…..
};
staticstructi2c_board_info ts_i2c_clients []= {
….
};
//for tsctouchScreen
omap_register_i2c_bus(2,400, ts_i2c_clients, ARRAY_SIZE(ts_i2c_clients));
4. 触摸屏校准
a) 算法:
设dx[3]和dy[3]为LCD显示的三点坐标数组, tx[3]和ty[3]为获取的触摸坐标数组。根据采用三点校准算法,求得7个校准参数:
a = (tx[0] - tx[2]) * (ty[1] - ty[2])- (tx[1] - tx[2]) * (ty[0] - ty[2]); b = (dx[0] - dx[2]) * (ty[1] - ty[2])- (dx[1] - dx[2]) * (ty[0] - ty[2]); c = (tx[0] - tx[2]) * (dx[1] - dx[2])- (tx[1] - tx[2]) * (dx[0] - dx[2]); d = dx[0] * (tx[1] * ty[2] - tx[2] * ty[1]) -dx[1] * (tx[0] * ty[2] - tx[2] * ty[0]) +dx[2] * (tx[0] * ty[1] - tx[1] * ty[0]); e = (dy[0] - dy[2]) * (ty[1] - ty[2])- (dy[1] - dy[2]) * (ty[0] - ty[2]); f = (tx[0] - tx[2]) * (dy[1] - dy[2])- (tx[1] - tx[2]) * (dy[0] - dy[2]); g = dy[0] * (tx[1] * ty[2] - tx[2] * ty[1]) -dy[1] * (tx[0] * ty[2] - tx[2] * ty[0]) +dy[2] * (tx[0] * ty[1] - tx[1] * ty[0]); |
校准后的坐标为:设xtmp, ytmp未触摸屏原始坐标,则校准后的坐标为:
x = a * (int) xtmp + b * (int)ytmp+c; x /= g; y = d* (int)xtmp + e* (int)ytmp + f; y /= g; |
b) 处理流程
图 12
十一. GPS
Android GPS架构如下图:
图 13
读取数据的流程图如下:
图 14
降压降频
由于产品受使用环境影响,故需要对cpu温度上限控制。由温度传感器来控制cpu过热降频,对于上层Android没有应用接口,是对于CPU频率控制的一种基本方法,其流程如下图:
图 15
1. 设置CPU默认温度值
drivers\misc\omap_temp_sensor.c,最低和最高电压调为 71/73摄氏度。
2. 降低电压与cpu频率
//line 226 降压如下: #define OMAP4460_VDD_MPU_OPPNITRO_UV 1375000 #define OMAP4460_VDD_MPU_OPPNITROSB_UV 1375000 |
降频如下:
修改arch\arm\mach-omap2\opp4xxx_data.c
//line 322 OPP_INITIALIZER("mpu", "virt_dpll_mpu_ck", "mpu", true, 1200000000, OMAP4460_VDD_MPU_OPPNITRO_UV), /* MPU OPP4 - OPP-Nitro SpeedBin */ //OPP_INITIALIZER("mpu", "virt_dpll_mpu_ck", "mpu", true, 1500000000, OMAP4460_VDD_MPU_OPPNITROSB_UV), |
十三. Camera模块
在Camera系统的各个库中,libui.so对上层的提供的接口主要是Camera类,类libandroid_runtime.so通过调用Camera类提供对JAVA的接口,并且实现了android.hardware.camera类。
图 16
1. 内核移植
使得内核支持UVC(USBvideo device class)驱动及V4L2(Video4Linux 2)驱动。
Symbol: USB_VIDEO_CLASS [=y] Depends on: MEDIA_SUPPORT [=y] && VIDEO_CAPTURE_DRIVERS [=y] && VIDEO_V4L2 [=y] && V4L_USB_DRIVERS [=y] && USB [=y] Location: -> Device Drivers -> Multimedia support (MEDIA_SUPPORT [=y]) -> Video capture adapters (VIDEO_CAPTURE_DRIVERS [=y]) -> V4L USB devices (V4L_USB_DRIVERS [=y]) // Symbol: USB_VIDEO_CLASS_INPUT_EVDEV [=y] Depends on: MEDIA_SUPPORT [=y] && VIDEO_CAPTURE_DRIVERS [=y] && VIDEO_V4L2 [=y] && V4L_USB_DRIVERS [=y] && USB [=y]&& UVC[=y] Location: -> Device Drivers -> Multimedia support (MEDIA_SUPPORT [=y]) -> Video capture adapters (VIDEO_CAPTURE_DRIVERS [=y]) -> V4L USB devices (V4L_USB_DRIVERS [=y]) -> USB Video Class (UVC) (USB_VIDEO_CLASS [=y]) |
2. Android移植
a) HAL
移植camera.panda.so,配置USB Camera分辨率、预览、拍照、录像HAL接口
./hardware/ti/omap4xxx/camera
b) Frameworks
实现JNI接口:
./frameworks/base/core/jni/android_hardware_Camera.cpp;
实现Frameworks的CameraService取景Preview、拍照takePicture以及摄影Recording功能:
./frameworks/base/services/camera
另外实现development:
./development/tools/emulator/system/camera
十四. Omx解码框架
TI的OpenMax 1L层主要包括有:
1. System : OpenMax核心和公共部分;
2. Audio : 音频处理部分的OpenMax1L组件;
3. Video : 视频处理部分的OpenMax1L组件;
4. Image : 图像处理部分的OpenMax1L组件;
图 17
十五. 音频模块
Android的音频子系统集中在Framework层,其中除了MeidaServer外还包括AudioFlinger、AudioTrack、AudioFlinger、AudioPolicyService、AudioPolicyManager等子模块。子系统框架图如下所示:
图 18
音频移植部分集中主要集中在Kernel的SOC驱动和HAL中间件层。根据产品需求定义需要实现多通道输出输出:
输入:3G_phone、Bluetooth_mic、FM、Mic
输出:3G_mic、Bluetooth(hs)、Speaker
1. 内核移植
c) ABE移植,实现多通道输出输出切换、关闭、打开、连接,主要移植的源码有一下几个模块:
./sound/soc/contorl.c
./sound/soc/soc_damp.c
./sound/soc/codecs/twl6040.c
./sound/soc/omap/omap-abe-dsp.c
./sound/soc/omap/omap-abe.c
./sound/soc/omap/abe/
2. HAL:
根据上层的音频策略打开/关闭相应的pcm设备及设置音频输入输出路径,修改以下源码。
./hardware/libhardware_legacy/audio/audio_hw.c
十六. 小键盘模块
小键盘的实现可以采用通用的GPIOButtons驱动实现,对于Android上层Frameworks而言,跟触摸屏差异不大。GPIOButtons在Android体系中如下:
图 19
1. 内核驱动
Symbol: KEYBOARD_GPIO [=y] Depends on: !S390 && INPUT [=y] && INPUT_KEYBOARD [=y] && GENERIC_GPIO [=y] Location: -> Device Drivers -> Input device support -> Generic input layer (needed for keyboard, mouse, ...) (INPUT [=y]) -> Keyboards (INPUT_KEYBOARD [=y]) |
2. 定义键值
在arch/arm/mach-omap2/board-omap4panda.c定义键值并主持设备
static structgpio_keys_buttongpio_buttons[] = { GPIO_BUTTON(GPIO_KEY0,KEY_POWER, 1, "power", 0), GPIO_BUTTON(GPIO_KEY1,KEY_BACK, 1, "back", 0), GPIO_BUTTON(GPIO_KEY2,KEY_HOME, 1, "home", 0), …… }; static structgpio_keys_platform_datagpio_button_data = { .buttons = gpio_buttons, .nbuttons = ARRAY_SIZE(gpio_buttons), }; //注册设备 platform_device_register(&gpio_button_data); |
其次,通过/system/usr/keylayout/gpio-keys.kl文件实现android标准键值映射即可。
十七. PWM背光驱动
Android通过backlight设备节点来控制LCD背光亮度,其大致框架如下图所示:
图 20
1. 内核驱动
Symbol: LEDS_OMAP4430_SDP_DISPLAY [=y] Depends on: NEW_LEDS [=y] && LEDS_CLASS [=y] Location: -> Device Drivers -> LED Support (NEW_LEDS [=y]) Selected by: MACH_OMAP_4430SDP [=n] && ARCH_OMAP2PLUS [=y] && ARCH_OMAP4 [=y] || MACH_OMAP_BLAZE [=n] && ARCH_OMAP2PLUS [=y] && ARCH_OMAP4 [=y] |
2. 注册设备
static struct omap4430_sdp_disp_led_platform_data omap4_panda_disp_led_data = { .flags = LEDS_CTRL_AS_ONE_DISPLAY, .display_led_init = omap4_panda_init_display_led, .primary_display_set = omap4_panda_set_primary_brightness, .secondary_display_set = omap4_panda_set_secondary_brightness, }; static structplatform_device omap4460_backlight_device = { .name = "display_led", .id = -1, .dev = { .platform_data = &omap4_panda_disp_led_data, }, }; //注册设备 platform_device_register(&omap4460_backlight_device); |
3. HAL
修改HAL的设备符 // ./hardware/msm7k/liblights/lights.c /* char const*const LCD_FILE = "/sys/class/backlight/pwm-backlight/brightness"; */
char const*const LCD_FILE = "/sys/class/leds/lcd-backlight/brightness"; |