ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上
2011年5月31日 星期二
htop -- the disk io status
就像 htop 用來 monitor cpu usage, disk io 的使用狀態可以用 iotop 來顯示。
由於現在 cpu 的速度遠大於 disk io 速度,所以很多job 都是 io bound。
所以 iotop 或許比 htop 更能顯示目前 server 的忙碌狀態。
localize android repo -- more detail
抓 code -- 先覆蓋 default.xml 再 sync,這樣減少抓 code 的時間。
follow user guide, 把 kernel 和 uboot 分開 mirror
server 部份先作到這裡,接下來要從 client 來修改 server 的內容 (因為 server 的 repo 是用 --mirror option clone 的)
修改 manifest.git/default.xml
(因為 repo init -u 只能由 -b 選擇 manifest.xml 的 branch,不能選rev,所以要這樣每次都 branch 一次)
OK, 現在 client 可以開始作 repo sync..
為了把每一個 step 都紀錄起來,最好隨著 manifest.xml 的版本變更,增加對應的 project code branch。
現在作一個 branch -- justsync, 要改 source 跟 manifest.xml
先到外面..clone
commit, push 到 serve
接著clone kernel, uboot 到對應位置, follow user guide, checkout v2.6.35.3 出來
到此,所有 git project 都在 justsync 上了。
以後 checkout justsync,就可以回到 repo sync 後的 code 狀態。
上 vendor patch..
同時還會新增一些 folder...
做完 patch ,先把有在 repo manifest管理的 project 都 create imx_r10.1 出來,push 到 server.
kernel, bootloader 也要這樣作,push 回去
做完patch 後,用上次寫的python script : searchcompare.py,找出哪些 folder 不在 manifest.xml 的管轄內。
要手動加回去,還要 mirror 到 server 裡。
到 server 去,su 成 git,到 git-daemon 的 repo 位置, androidrepo 下,到對應的 folder。
以 dispd 為例
--- 現在 server repo 裡有所有 patch 後的 code,在 imx_r10.1 裡。
然後是修改 manifest..
1. 把沒有在 manifest.xml 裡的 project 加進去
2. 把 default rev 改為 imx_r10.1
先 branch 出來
diff:
試著從 predownload 的 working directory 來作,看看能不能減少 localize repo server 的 repo sync 時間。
不行.. 因為 repo 的 project path 和 project name 不一樣,
也就是說 有用 --mirror option 作repo sync 出來的 repo folderstructure 和實際 checkout 出來的不一樣,
所以 manifest.xml 不能用。
$mkdir androidrepo && cd androidrepo
$repo repo init -u git://android.git.kernel.org/platform/manifest.git -b gingerbread --mirror
$cp ....../default.xml ./.repo/manifests/default.xml
$repo sync
為了保險起見,先把他 tar 起來˙˙ ˙
$cd ..
$tar zcvf myandroidrepo.tar.gz myandroidrepo
接著 clone kernel 和 uboot..follow user guide, 把 kernel 和 uboot 分開 mirror
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6.35.y.git --mirrot
還有git clone git://git.denx.de/u-boot.git --mirrot
server 部份先作到這裡,接下來要從 client 來修改 server 的內容 (因為 server 的 repo 是用 --mirror option clone 的)
修改 manifest.git/default.xml
$git clone git://server/androidrepo/platform/manifest.git -b gingerbread
照剛剛server 的作法作一次,好 update default.xml$cp ../code/r10.1/default.xml manifest/default.xml
branch 出來作mark$git checkout -b freescale
$git commit -am 'use freescale default.xml
$git push origin freescale
接著改為local,同樣 branch 一次(因為 repo init -u 只能由 -b 選擇 manifest.xml 的 branch,不能選rev,所以要這樣每次都 branch 一次)
$git checkout -b freescaleLocal
修改 default.xml,把 remote 改為 local: <remote name="korg"
fetch="git://server/androidrepo/"
review="review.source.android.com" /&g
commit & push 回去$git commit -am 'use local server'
$git push origin freescaleLocal
OK, 現在 client 可以開始作 repo sync..
$mkdir myandroid && cd myandroid
$repo init -u git://server/androidrepo/platform/manifest.git -b freescaleLocal
$repo sync
為了把每一個 step 都紀錄起來,最好隨著 manifest.xml 的版本變更,增加對應的 project code branch。
現在作一個 branch -- justsync, 要改 source 跟 manifest.xml
$repo forall -c 'git checkout -b justsync'
update server$repo forall -c 'git push korg justsync
修改 manifest..先到外面..clone
$git clone git://server/androidrepo/platform/manifest.git -b freescaleLocal
新增 justsync , 修改 manifest.xml$cd manifest
$git checkout -b justsync
修改 default.xml,把 default rev 改. <default revision="justsync"
remote="korg" />
並且把下面所有 project 有 revision 的部份刪掉.commit, push 到 serve
$git commit -am 'use justsync as default rev'
$git push origin justsync
接著clone kernel, uboot 到對應位置, follow user guide, checkout v2.6.35.3 出來
$git clone git://serer/linux-2.6.35.y.git kernel_imx
$git checkout v2.6.35.3
cd .....
$git clone git://server/u-boot.git uboot-imx
為求一致,都 branch 一個 justsync ,push 到 server$ git checkout -b justsync
$ git push origin justsync
kernel_imx, uboot-imx 都要作一次。到此,所有 git project 都在 justsync 上了。
以後 checkout justsync,就可以回到 repo sync 後的 code 狀態。
上 vendor patch..
$ c_patch ~/home/myhome/imx-android-r10.1/code/r10.1 imx_r10.1
vendor patch 會 對所有 patch 過的 project 產生 imx_r10.1 這個 branch。同時還會新增一些 folder...
做完 patch ,先把有在 repo manifest管理的 project 都 create imx_r10.1 出來,push 到 server.
$repo forall -c 'git checkout -b imx_r10.1'
$repo forall -c 'git push korg imx_r10.1'
kernel, bootloader 也要這樣作,push 回去
$git push origin imx_r10.1
做完patch 後,用上次寫的python script : searchcompare.py,找出哪些 folder 不在 manifest.xml 的管轄內。
要手動加回去,還要 mirror 到 server 裡。
$python searchcompare.py
./kernel_imx
./system/dispd
./system/wlan/atheros
./packages/apps/fsl_imx_demo
./device/fsl
./hardware/mx5x
./bootable/bootloader/uboot-imx
./external/linux-atheros-wifi
./external/systemtap
./external/linux-firmware-imx
./external/wpa_supplicant_ath
./external/linux-lib
所以除了 kernel_imx, bootable/bootloader/uboot-imx 以外,都要作到 server 去,su 成 git,到 git-daemon 的 repo 位置, androidrepo 下,到對應的 folder。
以 dispd 為例
$cd platform/system
$git clone --mirror /home/myhome/myandroid/system/dispd
10 個都做,這樣 server repo 就做好。--- 現在 server repo 裡有所有 patch 後的 code,在 imx_r10.1 裡。
然後是修改 manifest..
1. 把沒有在 manifest.xml 裡的 project 加進去
2. 把 default rev 改為 imx_r10.1
先 branch 出來
$git checkout -b imx_r10.1
修改 default.xmldiff:
diff --git a/default.xml b/default.xml
index fcdbc50..8670e1e 100644
--- a/default.xml
+++ b/default.xml
@@ -3,7 +3,7 @@
<remote name="korg"
fetch="git://gps1004/myandroid10.1/"
review="review.source.android.com" />
- <default revision="justsync"
+ <default revision="imx_r10.1"
remote="korg" />
<project path="build" name="platform/build">
@@ -174,4 +174,14 @@
<project path="hardware/alsa_sound" name="platform/hardware/alsa_sound" />
<project path="external/alsa-utils" name="platform/external/alsa-utils" />
<project path="external/mtd-utils" name="platform/external/mtd-utils" />
+ <project path="device/fsl" name="device/fsl" />
+ <project path="external/linux-atheros-wifi" name="platform/external/linux-atheros-wifi" />
+ <project path="external/linux-firmware-imx" name="platform/external/linux-firmware-imx" />
+ <project path="external/linux-lib" name="platform/external/linux-lib" />
+ <project path="external/wpa_supplicant_ath" name="platform/external/wpa_supplicant_ath" />
+ <project path="external/systemtap" name="platform/external/systemtap" />
+ <project path="hardware/mx5x" name="platform/hardware/mx5x" />
+ <project path="system/dispd" name="platform/system/dispd" />
+ <project path="system/wlan/atheros" name="platform/system/wlan/atheros" />
+<
</manifest>
commit, push/create 到 server$git commit -am 'use imx_r10.1 as default and add newly added project'
$git push origin imx_r10.1
試著從 predownload 的 working directory 來作,看看能不能減少 localize repo server 的 repo sync 時間。
不行.. 因為 repo 的 project path 和 project name 不一樣,
也就是說 有用 --mirror option 作repo sync 出來的 repo folderstructure 和實際 checkout 出來的不一樣,
所以 manifest.xml 不能用。
2011年5月30日 星期一
read soc register from /dev/mem
就是參考這一篇 : http://blog.richliu.com/2006/10/17/369/
這一篇甚至為 iMX51/3 Android 寫了 register name 轉換功能
http://boundarydevices.com/blogs/i-mx5x-device-register-access
就是利用 /dev/mem,把datasheet 裡面 soc 的 register 位址map 出來存取 (所以要 root 權限).
.. 這個拿來讀 GPIO STATE 應該很方便吧...不知道 overhead 大不大...
就是利用 /dev/mem,把datasheet 裡面 soc 的 register 位址map 出來存取 (所以要 root 權限).
include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#define MAPSIZE 1024
unsigned long *getMappedAddr(unsigned long addr)
{
int fd;
void *map;
unsigned int offset = addr & (MAPSIZE-1);
fd = open("/dev/mem",O_RDWR | O_SYNC);
if(fd<0){
printf("open dev/mem error\n");
return (unsigned long*)-1;
}
map = mmap(0, MAPSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr & ~(MAPSIZE-1));
if(map == MAP_FAILED){
printf("mmap error\n");
return (unsigned long*)-1;
}
return (unsigned long*)((char*)map+offset);
}
int main(int argc, char **argv)
{
unsigned long regaddr;
unsigned long *mapaddr;
char *end;
if(argc<2){
printf("please specify address\n");
return 0;
}
regaddr = strtoul(argv[1],&end,16);
mapaddr = getMappedAddr(regaddr);
if(mapaddr!=(unsigned long*)-1){
printf("%X = %X\n",regaddr,*(mapaddr));
}
return 0;
}
.. 這個拿來讀 GPIO STATE 應該很方便吧...不知道 overhead 大不大...
2011年5月26日 星期四
notes :imx51 ipu
Camera 的相關參數資料,都是用 CameraParameter 這個 class 來儲存。
PreView
Picture
都有Size,Fomat, (FrameRate) 等properties。
CameraHal( ) 生成時,設定
mPictureFormat -- 照相時的 format
mRecordFormat -- Preview 時的 format
camera 的 devicd node 是 /dev/video0
最後把 parameter 用 CameraHal::setParameter( )作檢查,設定到 CameraHal 的內部參數。
啟動的時候, CameraHal create 完,initDefaultParameter 後,setCallbacks( ) 被呼叫,查呼叫 callbacks 的好像只有
接者 ap call startPreview( ):
把所有的 mCaptureBuffers[] 清除好。
=== call cameraPreviewConfig( )
=== call cameraPreviewStart( )..
=== new PreviewCaptureFrameThread(this);
=== new PreviewShowFrameThread(this);
previewCaptureFrameThread()
PreviewShowFrameThread( )
這個好像是最主要 show 畫面的 function,
YUYV --> YUV420
one scanline:
Y,U,Y.U.Y.V.... - 所以 bytes of one scanline = 2 x width.
Camera Interface 的 channel :
0 : 420
1 : 422
這就是用 ioctl input 來設定的。
這是 VDI_C register,上面的field 是 VDI_CH_422,code declairation 是 VDI_C_CH_422。
ap call 的 input channel 應該是指下面的 array index:
要檢查的有
CSI0_SENS_CONF register,相關的 bit 定義是以 CSI_SENS_CONF 開頭。
pimxel format 的定義是用 fourcc: include/linux/ipu.h
CSI_OUT_FRM_CTRL 可以控制drop vertical line 或是 shift horiztal line。
所以要把 525 輸出成 520,大概要設定 drop 5 條 vertical line。
因為 function ipu_csi_set_window_pos( ) 的 argument 是 "start pos..
所以只會丟掉上面的 scan line。
要叫他丟掉下面的 scan line,大概要用CSI_ACT_FRM_SIZE。指定輸出的 image size。
trace 一下 VDI_C (video deinterlace)
找一下 ipu_csi_set_window_size( )
User AP 有 call ioctl,但是傳入的參數是用 g_fmt 拿到的。
g_fmt 會call mxc_v4l2_g_fmt( ):
mxc_v4l2_s_std( ) 有修改
ap 部份
takePicture 時,IPU process 用 pictureWidth x pictureHeight.
preView 時,IPU process 用 recordWidth x recordHeight.
mRecordFormat - set input
PreView
Picture
都有Size,Fomat, (FrameRate) 等properties。
CameraHal( ) 生成時,設定
mPictureFormat -- 照相時的 format
mRecordFormat -- Preview 時的 format
camera 的 devicd node 是 /dev/video0
最後把 parameter 用 CameraHal::setParameter( )作檢查,設定到 CameraHal 的內部參數。
啟動的時候, CameraHal create 完,initDefaultParameter 後,setCallbacks( ) 被呼叫,查呼叫 callbacks 的好像只有
base/camera/libcameraservice/CameraService.cpp
...CameraService::Client::Client(const sp& cameraService,
const sp& cameraClient, pid_t clientPid)
{
int callingPid = getCallingPid();
LOGV("Client::Client E (pid %d)", callingPid);
mCameraService = cameraService;
mCameraClient = cameraClient;
mClientPid = clientPid;
mHardware = openCameraHardware();
mUseOverlay = mHardware->useOverlay();
mHardware->setCallbacks(notifyCallback,
dataCallback,
dataCallbackTimestamp,
mCameraService.get());
接者 ap call startPreview( ):
把所有的 mCaptureBuffers[] 清除好。
=== call cameraPreviewConfig( )
cameraPreviewConfig: openCamera() 準備好 (v4l2_streamparm) -- call ioctl(fd_v4l, VIDIOC_S_PARM, &parm) 準備好 (v4l2_format) -- call ioctl(fd_v4l, VIDIOC_S_FMT, &fmt) 然後再用 ioctl(fd_v4l, VIDIOC_G_FMT, &fmt) 取回參數, (有可能會和剛剛 S_FMT 的內容不一樣?) 一樣再用 ioctl(fd_v4l, VIDIOC_G_PARM, &parm)取回參數。(有可能會和剛剛 S_PARM 不一樣?) 上面的操作,fmt/parm.type 都是 V4L2_BUF_TYPE_VIDEO_CAPTURE
=== call cameraPreviewStart( )..
填好 v4l2_requestbuffers, call ioctl(fd_v4l, VIDIOC_REQBUFS, &req) 再 call ioctl(fd_v4l, VIDIOC_QUERYBUF, &buf), 把一個一個 buffer 的 property 取出來,用mmap 設定為共用. 再 call ioctl (fd_v4l, VIDIOC_QBUF, &buf) 把 buffer 丟到 video capture 的 queue 中。 再 call ioctl (fd_v4l, VIDIOC_STREAMON, &type) 開始傳送資料到 buffer
=== new PreviewCaptureFrameThread(this);
=== new PreviewShowFrameThread(this);
previewCaptureFrameThread()
等待 avaible_dequeue_frame, call ioctl(camera_device, VIDIOC_DQBUF, &cfilledbuffer) 把 captured frame 從 queue 取出。 用 avaiable_show_frame 通知 previewShowFrameThread()
PreviewShowFrameThread( )
int CameraHal::previewShowFrameThread()
{
LOG_FUNCTION_NAME
if (mPreviewRunning && !error_status) {
previewOneFrame();
}
return NO_ERROR;
}
所以是 call previeOneFrame( )這個好像是最主要 show 畫面的 function,
等待 avaiable_show_frame 把 previewCaptureFrameThread 取出的 buffer copy 到 local。 call convertNV12toYUV420SP( ) 把 buffer 轉成 YUV420SP 並且放到 mPreviewBuffers 中。 -create overlay, 設為 push mode。
YUYV --> YUV420
one scanline:
Y,U,Y.U.Y.V.... - 所以 bytes of one scanline = 2 x width.
Camera Interface 的 channel :
0 : 420
1 : 422
這就是用 ioctl input 來設定的。
這是 VDI_C register,上面的field 是 VDI_CH_422,code declairation 是 VDI_C_CH_422。
ap call 的 input channel 應該是指下面的 array index:
tatic struct v4l2_input mxc_capture_inputs[MXC_V4L2_CAPTURE_NUM_INPUTS] = {
{
.index = 0,
.name = "CSI IC MEM",
.type = V4L2_INPUT_TYPE_CAMERA,
.audioset = 0,
.tuner = 0,
.std = V4L2_STD_UNKNOWN,
.status = 0,
},
{
.index = 1,
.name = "CSI MEM",
.type = V4L2_INPUT_TYPE_CAMERA,
.audioset = 0,
.tuner = 0,
.std = V4L2_STD_UNKNOWN,
.status = V4L2_IN_ST_NO_POWER,
},
};
要檢查的有
CSI0_SENS_CONF register,相關的 bit 定義是以 CSI_SENS_CONF 開頭。
pimxel format 的定義是用 fourcc: include/linux/ipu.h
#define fourcc(a, b, c, d)\
(((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
CSI_OUT_FRM_CTRL 可以控制drop vertical line 或是 shift horiztal line。
所以要把 525 輸出成 520,大概要設定 drop 5 條 vertical line。
因為 function ipu_csi_set_window_pos( ) 的 argument 是 "start pos..
所以只會丟掉上面的 scan line。
要叫他丟掉下面的 scan line,大概要用CSI_ACT_FRM_SIZE。指定輸出的 image size。
trace 一下 VDI_C (video deinterlace)
- _ipu_vdi_init( ) 設定 channel type 422, 420
- ipu_init_channel 在 channel 是MEM_VDI_PRP_VF_MEM,MEM_VDI_PRP_VF_MEM_P,MEM_VDI_PRP_VF_MEM_N 時,才會呼叫 ipu_vdi_init。
- 在 capture 的 ipu_csi_enc.c, ipu_still.c, ipu_prp_enc.c, ipu_prp_vf_sdc/_bg.c 都有 call ipu_init_channel。
找一下 ipu_csi_set_window_size( )
- mxc_v4l2_s_param( )
ipu_csi_set_window_size(cam->crop_current.width, cam->crop_current.height, cam->csi);
但是沒看到設 crop_current.X 的code. - mxc_v4l_open () 有設,但是default 是和 image size 一樣 。
- mxc_v4l_do_ioctl( ) 的
case VIDIOC_S_CROP: { ....
- init_camera_struct( ) 設成640x480
User AP 有 call ioctl,但是傳入的參數是用 g_fmt 拿到的。
g_fmt 會call mxc_v4l2_g_fmt( ):
f->fmt.pix = cam->v2f.fmt.pix;
所以就是 cam_data 的內容是 這個
mxc_v4l2_s_std( ) 有修改
ap 部份
takePicture 時,IPU process 用 pictureWidth x pictureHeight.
preView 時,IPU process 用 recordWidth x recordHeight.
mRecordFormat - set input
2011年5月25日 星期三
v4l2 的 capture 取得 camera driver data 的 function :
camera 的 dev node 是在 /dev/video0
capturemode 沒用,是給 camera sensor setting 用的。 adv7180 完全沒有參考到。
static inline void *video_get_drvdata(struct video_device *vdev)
{
return dev_get_drvdata(&vdev->dev);
}
實際上只是call dev_get_drvdata。
沒有 auto detect 的原因:
call ioctl_g_fmt_cap 時,argument 的 format 是 V4L2_BUF_TYPE_VIDEO_CAPTURE,
如果是 V4L2_BUF_TYPE_PRIVATE,就會 call adv7180_get_std 取得 std format。
camera 的 dev node 是在 /dev/video0
capturemode 沒用,是給 camera sensor setting 用的。 adv7180 完全沒有參考到。
2011年5月24日 星期二
kernel : DEBUG - dev_dbg
kernel 中很多地方用 dev_dbg( )。
這個宣告是在include/linux/device.h
原來我以前就寫過: http://r40eubuntu.blogspot.com/2010/11/kernel-driver-dbg.html就可以了
#if defined(DEBUG)
#define dev_dbg(dev, format, arg...) \
dev_printk(KERN_DEBUG , dev , format , ## arg)
#elif defined(CONFIG_DYNAMIC_DEBUG)
#define dev_dbg(dev, format, ...) do { \
dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
} while (0)
#else
#define dev_dbg(dev, format, arg...) \
({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
#endif
所以,要開啟該 .c 的 dev_dbg,就在 source file 的開頭
#define DEBUG
原來我以前就寫過: http://r40eubuntu.blogspot.com/2010/11/kernel-driver-dbg.html就可以了
2011年5月20日 星期五
worklog - Android : add entry into 'About phones'
想要在 About phones 增加一個 entry..
找到好像是在 apps/Settings/src/com/android/settings/DeviceInfoSettings.java
整個 Sett
ing 有關的 Makefile 是在 settings/AndroidManifest.xml,其中和 'About phones' 頁面相關的好像是:
source 在 DeviceInfoSettings.java,onCreate 一開始:
找到:res/xml/device_info_settings.xml
所以在後面copy 一份 把所有 build_number 都改 mcu_version。
在 code 的部份加上
結果 res/***/string.xml 一堆語系都要加上 mcu_version 這個 entry。
另外這些 string.xml的每一個 entry 都有 msgid 屬性,看起來是 unique,但是不知道要怎麼產生新的,所以就不寫了。
都加上後 build 就 OK 了。
測試結果的確在 'About phones' 的最後增加了一個 item : mcu versionm 內容是 1.2.3
找到好像是在 apps/Settings/src/com/android/settings/DeviceInfoSettings.java
整個 Sett
ing 有關的 Makefile 是在 settings/AndroidManifest.xml,其中和 'About phones' 頁面相關的好像是:
<activity android:name="DeviceInfoSettings" androi
d:label="@string/device_info_settings"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.DEVICE_INFO_SETTINGS"
; />
<category android:name="android.intent.category.DEFAULT" />
<category
android:name="android.intent.category.VOICE_LAUNCH" />
;
</intent-filter>
</activity>
所以 activity 是 DeviceInfoSettingssource 在 DeviceInfoSettings.java,onCreate 一開始:
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.device_info_settings);
所以內容是xml 決定 (device_info_settings.xml)。找到:res/xml/device_info_settings.xml
<!-- Device Kernel version -->
<Preference android:key="kernel_version"
style="?android:preferenceInformationStyle"
android:title="@string/kernel_version"
android:summary="@string/device_info_default"/>
<!-- Detailed build version -->
<Preference android:key="build_number"
style="?android:preferenceInformationStyle"
android:title="@string/build_number"
android:summary="@string/device_info_default"/>
所以在後面copy 一份 把所有 build_number 都改 mcu_version。
在 code 的部份加上
setStringSummary("mcu_version","1.2.3");
build 的結果說 string resource 沒有 mcu_version。結果 res/***/string.xml 一堆語系都要加上 mcu_version 這個 entry。
另外這些 string.xml的每一個 entry 都有 msgid 屬性,看起來是 unique,但是不知道要怎麼產生新的,所以就不寫了。
都加上後 build 就 OK 了。
測試結果的確在 'About phones' 的最後增加了一個 item : mcu versionm 內容是 1.2.3
u-boot : accessing the 2nd serial port
follow include/configs/mx51_bbg_android.h 的內容,grep 一下 CONFIG_MXC_UART,找到 driver 是
drivers/serial/serial_mxc.c
要增加的是 uart3.
Worklog : onKeyDown - Android source
都有 source code 真方便
因為更改了 hardware key definition ,所以 onKeyDown 反應的 Key value 也要改。
配合 debug Mode,可以看到每個按鍵的值 (在 TestMode的值)
L1 - No key L2 - 27 - KEYCODE_CAMERA L3 - 24 - KEYCODE_VOLUME_UP L4 - 25 - KEYCODE_VOLUME_DOWN
R1 - X - KEYCODE_A R2 - 82 - KEYCODE_MENU R3 - 4 - KEYCODE_B R4 - 4 - KEYCODE_BACK
onKeyDown 的 keycode 是定義在
framework/base/core/java/android/view/KeyEvent.java
所以知道上面的 value 對應值
eclipse - open existing project
Eclipse 剛安裝完畢,顯示的是 Startup 頁面,先把他關掉,不然一堆 project window 會播蓋住。
開啟現有 project 的方法是
這樣開啟過的 project 就會被放到 package explorer 中。
開啟現有 project 的方法是
File - Import - General - Existing Projects into Workspace
這樣開啟過的 project 就會被放到 package explorer 中。
Syntax error, annotations are only available if source level is 1.5
Import 一個 project 進來,build 後出現
奇怪的是,一旦 OK 後,把這個 option 切回原來 1.6, rebuild 也 OK..
Syntax error, annotations are only available if source level is 1.5
因為我的 jdk 是 1.6。
所以 --Project - properties - Java Compiler - Enable Project Specifig Setting - Compiler Compliance level:
設到 1.5
clean, rebuild 就 OK 了。
奇怪的是,一旦 OK 後,把這個 option 切回原來 1.6, rebuild 也 OK..
2011年5月19日 星期四
datasheet reading .. display port
display 功能由IPU (Image Processing Unit) 提供。
有兩個 DI (Display Interface).
藉由 CS 控制,每個 DI 可以接 3 個 display (CS multiplexing)
DI 支援以下同步模式的輸出 (非同步部份不列出)
TFT
Sharp Display
TV encoder (PAL, NTSC, both with interlace or progressive)
BT 656
BT 1120
IPU 的 bandwith depend on IPU main clock (HSP_CLK) (133MHz as default ?)
DI 輸出信號可以分為兩類
時序信號:VSYNC, HSYNC, pixel clock
資料信號 :
兩組 DI 各有自己的 control register set,內容一樣,base address 不一樣而已
DI0 -- base + 0xE040000
DI1 -- base + 0xE048000
2011年5月18日 星期三
re-enable the splash screen in u-boot
因為原來就有了,只是後來被 disable掉,所以是 "re-enable"
從 commit log 中找出當初disable 的 rev,找出 diff:
然後grep 一下 CONFIG_SPLASH_SCREEN 的code.
function implememt 都在 common/lcd.c
hardware driver 在 drivers/video/mxc_ipuv2.c
另外還有 board specific setting 在 board/freescale/mx51_bbg/mx51_bbg.c
有兩組 DI (display Interface) : DI0, DI1,在 code 中 drivers/video/ipu_common.c 用 data structure clk 宣告一個 array ipu_clk[2] 描述兩個 interface 的 clk setting。
決定 interface 的 argument..
所以要看 di_clk_parent 是否是 1,還有 di 的值。
在 drivers/video/mxc_ipuv3_fb.c
參數 di, di_clk_parent ...
在 board/freescale/mx51_bbg/mx51_bbg.c
di = 1.
所以是用 DI1.
follow kernel 的內容新增一個pvi_2003a_wvga .並且把 di 由 1 改為 0.
從 kernel boot message 可以看到這個設計是以 di0 作 primary。
同時 format 改為 RGB24
檢查一下 gpio 的設定..
DI1_DISP_CLK : No Muxing ..
DI1_PIN2 : ALT0 才是 ipu. 電路作DISP1_HSYNC 用
DI1_PIN3 : ALT0 是 ipu,作 DISP1_VSYNC 用
DI1_PIN15 : No Muxing, ipu, 作 DISP1_DRDY -- 接到 image processor,當 DE 用
DISP1_DAT 0 ~ 5 : No Muxing.
DISP1_DAT 6 ~ 23 : ALT0 是 ipu
看了一下,這些 pin default 都是 ALT0.
在cls command 的 do function 加入填寫螢幕的動作,查各bit 的有效顏色..
修改到此,可以試試看 bmp 的 function 了。因為 option 只有 CONFIG_BMP_8BPP. 所以只有 support 8bpp 的 bmp format.
follow 這一篇 U-Boot display support 產生 8bpp 的 bmp file,叫 u-boot load 進 ram 然後 show出來..
在 boot env 加上 splashimage=0x90800000 後,開機竟然show 一個原廠的畫面...
找了一下,發現在 boared/freescale/common 下有 bmp 的 c arrary source..
只要在 bootargument 有 define splashimage='address' 指定 splash 的 memory location,
就會把 bmp array data 顯示出來。
用 這一篇 的內容,把 splash.bmp 轉成 c array.
output pipe 到 dummy_800x480.c,修改 Makefile。
完成。
從 commit log 中找出當初disable 的 rev,找出 diff:
diff --git a/include/configs/mx51_bbg_android.h b/include/configs/mx51_bbg_android.h
index 7b054e3..a460954 100644
--- a/include/configs/mx51_bbg_android.h
+++ b/include/configs/mx51_bbg_android.h
@@ -349,7 +349,6 @@
#undef CONFIG_JFFS2_CMDLINE
#define CONFIG_JFFS2_DEV "nand0"
-#define CONFIG_SPLASH_SCREEN
#ifdef CONFIG_SPLASH_SCREEN
/*
* Framebuffer and LCD
重新把他加回去。然後grep 一下 CONFIG_SPLASH_SCREEN 的code.
function implememt 都在 common/lcd.c
hardware driver 在 drivers/video/mxc_ipuv2.c
另外還有 board specific setting 在 board/freescale/mx51_bbg/mx51_bbg.c
有兩組 DI (display Interface) : DI0, DI1,在 code 中 drivers/video/ipu_common.c 用 data structure clk 宣告一個 array ipu_clk[2] 描述兩個 interface 的 clk setting。
決定 interface 的 argument..
ipu_common.c : int ipu_probe(int di, ipu_di_clk_parent_t di_clk_parent, int di_clk_val)..
if (di_clk_parent == DI_PCLK_LDB) {
clk_set_parent(g_pixel_clk[di], g_di_clk[di]);
} else {
clk_set_parent(g_pixel_clk[0], g_ipu_clk);
clk_set_parent(g_pixel_clk[1], g_ipu_clk);
}
clk_enable(g_ipu_clk);
所以要看 di_clk_parent 是否是 1,還有 di 的值。
在 drivers/video/mxc_ipuv3_fb.c
int ipuv3_fb_init(struct fb_videomode *mode, int di, int interface_pix_fmt,
ipu_di_clk_parent_t di_clk_parent, int di_clk_val)
{
int ret;
ret = ipu_probe(di, di_clk_parent, di_clk_val);
參數 di, di_clk_parent ...
在 board/freescale/mx51_bbg/mx51_bbg.c
void lcd_enable(void)
{
....
....
gpio config
....
ret = ipuv3_fb_init(&claa_wvga, 1, IPU_PIX_FMT_RGB565, DI_PCLK_PLL3, 0);
di_parent = DI_PCLK_PLL3,di = 1.
所以是用 DI1.
follow kernel 的內容新增一個pvi_2003a_wvga .並且把 di 由 1 改為 0.
從 kernel boot message 可以看到這個設計是以 di0 作 primary。
同時 format 改為 RGB24
檢查一下 gpio 的設定..
DI1_DISP_CLK : No Muxing ..
DI1_PIN2 : ALT0 才是 ipu. 電路作DISP1_HSYNC 用
DI1_PIN3 : ALT0 是 ipu,作 DISP1_VSYNC 用
DI1_PIN15 : No Muxing, ipu, 作 DISP1_DRDY -- 接到 image processor,當 DE 用
DISP1_DAT 0 ~ 5 : No Muxing.
DISP1_DAT 6 ~ 23 : ALT0 是 ipu
看了一下,這些 pin default 都是 ALT0.
在cls command 的 do function 加入填寫螢幕的動作,查各bit 的有效顏色..
0. 1. 2. 3. 4 - green 5. 6. 7. 8. 9.10 - blue 11.12.13.14.15 - red所以是 565沒錯。
修改到此,可以試試看 bmp 的 function 了。因為 option 只有 CONFIG_BMP_8BPP. 所以只有 support 8bpp 的 bmp format.
follow 這一篇 U-Boot display support 產生 8bpp 的 bmp file,叫 u-boot load 進 ram 然後 show出來..
- 先用 gimp create 一個 800x480, backgroupe 是白色,中間隨便的圖案。
如果是用現成的圖,先用 gimp打開,然後 save as,選 windows bmp file,save 時,advance option 選 16bit 565 的格式 - 使用 imagemagick 轉成 8bpp:
$ convert 00.bmp -colors 256 -compress none splash.bmp
- copy splash.bmp 到 boot sd 的 partition 1
- boot,進入 uboot console.
- uboot load spalsh.bmp 進 memory:
fatload mmc 0:1 0x92000000 splash.bmp
- 用 bmp display 顯示出來
bmp display 0x92000000
在 boot env 加上 splashimage=0x90800000 後,開機竟然show 一個原廠的畫面...
找了一下,發現在 boared/freescale/common 下有 bmp 的 c arrary source..
只要在 bootargument 有 define splashimage='address' 指定 splash 的 memory location,
就會把 bmp array data 顯示出來。
用 這一篇 的內容,把 splash.bmp 轉成 c array.
$ hexdump -e '16/1 "0x%02X,"' -e '"\n"' splash.bmp -v
-v option 是要他不要把重複的以 '*' 代替,忠實的顯示出來。output pipe 到 dummy_800x480.c,修改 Makefile。
完成。
2011年5月17日 星期二
touch driver tracing
這個 platform 的 touch 是由 PMIC 的 ADC 負責的。
所以底層 adc reading 的 code 在:
這個 mc13892_adc_convert( )是所有adc 共用。
其中 touch driver 使用的地方在
其中有小小的作一次 2 samples avering.
linux touch driver 的 model driver 在 input/touchscreen/mxc_ts.c
其中的 ts_thread 會呼叫 pmic_adc_get_touch_sample( ).
這邊的 code 好像是用 polling 的方式(msleep(20)).只是 pmic_adc_get_touch_sample( ) 是 interrput driven,所以當沒有 touch adc interrput 時,會 return false。
這個 driver follow linux input driver model,和 keyboard 類似,在 / 下 create 一個 node作為與上層 ap 的 interface。
上層 :
所以底層 adc reading 的 code 在:
drivers/mxc/pmic/mc13892/pmic_adc.c
function : PMIC_STATUS mc13892_adc_convert(t_adc_param *adc_param)
這個 mc13892_adc_convert( )是所有adc 共用。
其中 touch driver 使用的地方在
PMIC_STATUS mc13892_adc_read_ts(t_touch_screen *ts_value, int wait_tsi)
再上層是:PMIC_STATUS pmic_adc_get_touch_sample(t_touch_screen *touch_sample, int wait)
{
if (mc13892_adc_read_ts(touch_sample, wait) != 0)
return PMIC_ERROR;
if (0 == pmic_adc_filter(touch_sample))
return PMIC_SUCCESS;
else
return PMIC_ERROR;
}
pmic_adc_fileter 是算出touch 的壓力大小,決定是不是一個 valid touch。其中有小小的作一次 2 samples avering.
linux touch driver 的 model driver 在 input/touchscreen/mxc_ts.c
其中的 ts_thread 會呼叫 pmic_adc_get_touch_sample( ).
這邊的 code 好像是用 polling 的方式(msleep(20)).只是 pmic_adc_get_touch_sample( ) 是 interrput driven,所以當沒有 touch adc interrput 時,會 return false。
這個 driver follow linux input driver model,和 keyboard 類似,在 / 下 create 一個 node作為與上層 ap 的 interface。
上層 :
2011年5月12日 星期四
pmic -- regulator & init call sequence
pmic 的 driver 寫在driver/regulator/***.c
其中對外的 function interface 寫在 core.c
其他的 driver 要使用 regulator 的話,要 call core.c 的
regulator_get( ) 取得 regulator 的 ops_function_table。
prototype :
driver 中常常用的 :
__define_initcall( ) 是:
regulator driver 跟一般 driver 不一樣,是 core_init,幾乎是所有 init 最開始的部份..
其中對外的 function interface 寫在 core.c
其他的 driver 要使用 regulator 的話,要 call core.c 的
regulator_get( ) 取得 regulator 的 ops_function_table。
prototype :
struct regulator *regulator_get(struct device *dev, const char *id)
其中的 id 是 string。 就是 regulator 的名子。
regulator module 的 init call 是宣告:
core_initcall(regulator_init);
core_initcall 宣告在 include/linux/init.h ,有一堆 initcall 宣告:
#define pure_initcall(fn) __define_initcall("0",fn,0)
#define core_initcall(fn) __define_initcall("1",fn,1)
#define core_initcall_sync(fn) __define_initcall("1s",fn,1s)
#define postcore_initcall(fn) __define_initcall("2",fn,2)
#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)
#define arch_initcall(fn) __define_initcall("3",fn,3)
#define arch_initcall_sync(fn) __define_initcall("3s",fn,3s)
#define subsys_initcall(fn) __define_initcall("4",fn,4)
#define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)
#define fs_initcall(fn) __define_initcall("5",fn,5)
#define fs_initcall_sync(fn) __define_initcall("5s",fn,5s)
#define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)
#define device_initcall(fn) __define_initcall("6",fn,6)
#define device_initcall_sync(fn) __define_initcall("6s",fn,6s)
#define late_initcall(fn) __define_initcall("7",fn,7)
#define late_initcall_sync(fn) __define_initcall("7s",fn,7s)
-- 從這個宣告可以知道 各個 initcall 的執行順序..driver 中常常用的 :
#define __initcall(fn) device_initcall(fn)
還有
#define module_init(x) __initcall(x);
.. 所以一般 driver 的 init 是在 device_initcall 時 執行 ..幾乎是最後了。__define_initcall( ) 是:
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
所以就是安排在 .initcall?.init section 中。
在 loading script 中有指定:
#define INIT_SETUP(initsetup_align) \
. = ALIGN(initsetup_align); \
VMLINUX_SYMBOL(__setup_start) = .; \
*(.init.setup) \
VMLINUX_SYMBOL(__setup_end) = .;
#define INITCALLS \
*(.initcallearly.init) \
VMLINUX_SYMBOL(__early_initcall_end) = .; \
*(.initcall0.init) \
*(.initcall0s.init) \
*(.initcall1.init) \
*(.initcall1s.init) \
*(.initcall2.init) \
*(.initcall2s.init) \
*(.initcall3.init) \
*(.initcall3s.init) \
*(.initcall4.init) \
*(.initcall4s.init) \
*(.initcall5.init) \
*(.initcall5s.init) \
*(.initcallrootfs.init) \
*(.initcall6.init) \
*(.initcall6s.init) \
*(.initcall7.init) \
*(.initcall7s.init)
#define INIT_CALLS \
VMLINUX_SYMBOL(__initcall_start) = .; \
INITCALLS \
VMLINUX_SYMBOL(__initcall_end) = .;
被放在這個 section 的 function pointer ,在 init/main.c 中,會被一一的呼叫:
extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];
static void __init do_initcalls(void)
{
initcall_t *fn;
for (fn = __early_initcall_end; fn < __initcall_end; fn++)
do_one_initcall(*fn);
/* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_work();
}
regulator driver 跟一般 driver 不一樣,是 core_init,幾乎是所有 init 最開始的部份..
2011年5月11日 星期三
key - power key
powerkey 是 hardware gpio 直接對應的。所以有自己專屬的 driver.
linux 的 device - driver 架構。
device 部份:
在 arch . device.c. 其中 pdata 部份,又宣告在 arch 的 board specific init source..
hardware report KEY_F4 後,Android 的部份,就跟 以前寫得 一樣。
static struct power_key_platform_data pwrkey_data = {
.key_value = KEY_F4,
.register_pwrkey = xc_register_powerkey,
.get_key_status = xc_pwrkey_getstatus,
};
driver 的部份,就在 drivers/input/keyboard/xc_pwrkey.c
ref 上一次的內容.set_capability..
xc_pwrkey->value = pdata->key_value;
....
input_set_capability(input, EV_KEY, xc_pwrkey->value);
還有偵測到 key pressed/released, 時 event handler report..
input_report_key(
mxc_pwrkey->input, mxc_pwrkey->value, 1);
所以這個 power-key 真的送出的keycode 就是 KEY_F4.
hardware report KEY_F4 後,Android 的部份,就跟 以前寫得 一樣。
2011年5月9日 星期一
Todo today
- 1. 作一個 delete all /data 的 upgradesys -- OK
- 2. bootloader try 200MHz
- 2.a modify the DDR info parsing code <;i>2.b modify boot parameter for 166MHz
- 2.c if b pass, try 200MHz.
- 3. apply 9.4.1 patch
還是先改 external sd boot 好了,因為 bad ddr parameter may cause un-bootable.
9.4.1
大概就是從 original 9.4 create 一個 branch 出來,依照說明 patch 到 9.4.1.
然後回到目前的工作 branch , rebase 9.4.1
9.4.1 的 patch 是依照 project 來區分,所以要一個一個手動上。
先列出:
find . -type d -name '*.git'
然後只作需要的就可以了,不需要用 repo forall 來作。 ( 也不會比較快 ).2011年5月6日 星期五
Worklog - android suspend - II turn off the peripherial power
上次 pure software 的 suspend/wakeup 已經 OK --- 也就是說外部/週邊電源都不變的情況。
這次配合關閉週邊電源。
結果 : 週邊上電後,會導致 wakeup -- 雖然 CPU_SUSPEND_IN 沒有 set high,但是還是會 wakeup 起來。
所以導致 fail..
當 週邊上電時,wakeup 時,有 "usb wakeup is here" 的 message。
找到,在
把 usb_wakup.o 拿掉, 週邊上電時,改有 exception,並且是 nobody care IRQ 14.
這次配合關閉週邊電源。
結果 : 週邊上電後,會導致 wakeup -- 雖然 CPU_SUSPEND_IN 沒有 set high,但是還是會 wakeup 起來。
所以導致 fail..
當 週邊上電時,wakeup 時,有 "usb wakeup is here" 的 message。
找到,在
./arch/arm/plat-mxc/usb_wakeup.c:80: printk(KERN_INFO "usb wakeup is here\n");
把 usb_wakup.o 拿掉, 週邊上電時,改有 exception,並且是 nobody care IRQ 14.
2011年5月5日 星期四
wakelock in linux kernel
原以為是 linux kernel 功能的 wakelock suspend 機制,結果是從 android port 納入的。
而且當初納入 mainstream 時還有一番修正和討論。
最後的這一篇Android kernel wakelock solution 應該可以算是結束。
follow 這篇的 link 去看:An alternative to suspend blockers 詳細的說明了 suspend wakeup 的需求。機制。優劣。實做。
其中列出的 ref link 更多。
其他的部份,有關 android 的 wakelock 使用方法,在 這個 pdf 檔有簡單說明:
在 kernel 中使用 wakelock:
首先是 wakelock_init( .. ) 參數要給 lock 的 type:
WAKE_LOCK_SUSPEND : 防止 system 進入 suspend
WAKE_LOCK_IDLE: 防止 system 進入 idle.
然後在需要的地方,用:
wake_lock( ) 來 active lock,防止 system 進入 suspend/idle state
wake_unlock( )允許 system suspend/idle.
kernel 的 power driver (inplement wakelock function) 會實做一個 /sys/power/wake_lock, wake_unlock 介面,讓 user 使用。
user 可以用
再用
另外,android pdk 文件也有說明: http://www.netmite.com/android/mydroid/development/pdk/docs/power_management.html
說明的是 android user program access wakelock 的方式,所以內容與 kernel 不一樣。
這篇 http://blog.haozhi.org/dev/?p=668 有說明 android kernel 的 suspend 機制
而且當初納入 mainstream 時還有一番修正和討論。
最後的這一篇Android kernel wakelock solution 應該可以算是結束。
follow 這篇的 link 去看:An alternative to suspend blockers 詳細的說明了 suspend wakeup 的需求。機制。優劣。實做。
其中列出的 ref link 更多。
其他的部份,有關 android 的 wakelock 使用方法,在 這個 pdf 檔有簡單說明:
在 kernel 中使用 wakelock:
首先是 wakelock_init( .. ) 參數要給 lock 的 type:
WAKE_LOCK_SUSPEND : 防止 system 進入 suspend
WAKE_LOCK_IDLE: 防止 system 進入 idle.
然後在需要的地方,用:
wake_lock( ) 來 active lock,防止 system 進入 suspend/idle state
wake_unlock( )允許 system suspend/idle.
kernel 的 power driver (inplement wakelock function) 會實做一個 /sys/power/wake_lock, wake_unlock 介面,讓 user 使用。
user 可以用
echo mylock > /sys/power/wake_lock
防止 system suspend。再用
echo mylock > /sys/power/wake_unlock
釋放另外,android pdk 文件也有說明: http://www.netmite.com/android/mydroid/development/pdk/docs/power_management.html
說明的是 android user program access wakelock 的方式,所以內容與 kernel 不一樣。
這篇 http://blog.haozhi.org/dev/?p=668 有說明 android kernel 的 suspend 機制
2011年5月4日 星期三
Worklog - android suspend
在 driver/input/keyboard/mxc_pwrkey.c 有 powerkey 專用的 keyboard driver。
2.6 的 driver, device architecture.
device 的部份在
arch/arm/mach-mx5/device.c
device 的 data 在
arch/arm/mach-mx5/mx51_babbage.c
大概就是 ..
PM_SUSPEND_XX 定義在: linux/suspend.h:
在 kernel/power/main.c 有 compare, dispatch 的 code:
state_store( )
kernel/power 負責 suspend/wakeup 的流程,提工一組 function,讓其他 driver 能夠register 自己的 handler,在 suspend 前,會被一一呼叫到 : register_early_suspend.
register_late_suspend.
奇怪的是,dmesg的 log 只能看到 early_suspend( ) ,沒有辦法trace 到 early_suspend 之後的 printk message。
在 kernel/printk.c 中有 boot argument : console_suspend_enabled1變數,是用
好像有人鎖住wake_lock,,所以睡不下去...
wake_lock. wake_unlock..
看 log 是
wake_lock : PowerManagerService,
wake_unlock : alarm
印出上面 log 的 code 是在:
kernel/power/wakelock.c - wake_lock_internal()
用 cgrep wake_lock_init 可以找出 alarm 是 driver/rtc/alarm-dev.c。
但是找不出 PowerManagerService 是哪裡來的
"base/services/java/com/android/server/PowerManagerService.java" line 610
有:
那個 acquire 是 PowerManagerService private class UsynchronizedWakeLock( ) 實做的 function.
在 PowerManagerService 中的 WakeLock , Binder 操作,實做了一個 private class WakeLock:
原來 WakeLock 幾乎是 Android 的 PM (power management) 的代名詞。
一些 ref:
所以 cat /proc/wakelock 可以看到所有 wakelock 的統計資料
使用 dumpsys 可以列出 Android System 的狀態 (所有 Service 裡面有實做 dump( ) 的,都會被呼叫).
用
以下是 dumpsys , Battery Service 的部份:
BatteryService.java :469 dump( )
BatteryManager 提供的 isPowered(),是根據以下狀態:
BatteryManager.BATTERY_STATUS_UNKNOWN 的宣告:
=======> 把他 Mark 掉?
但是實際上是 Powered 沒錯,是不應該因為 Powered 就 stayOn,所以應該要改 PowerManagerService..(?)
dumpsys wakeup state 的 PowerManagerService 內容:
ref PowerManagerService.java 610:
繼續看 dumpsys :
還有:
使用者是:
==> 結果一樣,無法 suspend。
用 dumpsys 看, PowerManagerService 的 mLock.size 還是 1.
重新開機.. dumpsys 看.. mLock.size 是 0.
將 CPU_SUSPEND_IN 拉 Low,, 還是無法 suspend,但是 suspend 後的log 變成:
往前看,有
重新開機,usb 不連接, gps default off, 開機後把 CPU_SUSPEND_IN 拉 low.. 進入 suspend:
把 CPU_SUSPEND_IN 拉 High 後,resume.
所以: GPS ON 和 USB connect 會讓 系統無法 suspend.
2.6 的 driver, device architecture.
device 的部份在
arch/arm/mach-mx5/device.c
device 的 data 在
arch/arm/mach-mx5/mx51_babbage.c
大概就是 ..
PM_SUSPEND_XX 定義在: linux/suspend.h:
#define PM_SUSPEND_ON ((__force suspend_state_t) 0)
#define PM_SUSPEND_STANDBY ((__force suspend_state_t) 1)
#define PM_SUSPEND_MEM ((__force suspend_state_t) 3)
#define PM_SUSPEND_MAX ((__force suspend_state_t) 4)
對應的 /sys/power/state 內容字串定義在 kernel/power/suspend.c
const char *const pm_states[PM_SUSPEND_MAX] = {
#ifdef CONFIG_EARLYSUSPEND
[PM_SUSPEND_ON] = "on",
#endif
[PM_SUSPEND_STANDBY] = "standby",
[PM_SUSPEND_MEM] = "mem",
};
在 kernel/power/main.c 有 compare, dispatch 的 code:
state_store( )
for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
printk("state:%d %s\n",state,pm_states[state]);
if (*s && len == strlen(*s) && !strncmp(buf, *s, len)){
printk("matched %d !!\n",state);
break;
}
}
kernel/power 負責 suspend/wakeup 的流程,提工一組 function,讓其他 driver 能夠register 自己的 handler,在 suspend 前,會被一一呼叫到 : register_early_suspend.
register_late_suspend.
奇怪的是,dmesg的 log 只能看到 early_suspend( ) ,沒有辦法trace 到 early_suspend 之後的 printk message。
在 kernel/printk.c 中有 boot argument : console_suspend_enabled1變數,是用
__setup("no_console_suspend", console_suspend_disable);
和 no_console_suspend 關聯在一起。好像有人鎖住wake_lock,,所以睡不下去...
wake_lock. wake_unlock..
看 log 是
wake_lock : PowerManagerService,
wake_unlock : alarm
印出上面 log 的 code 是在:
kernel/power/wakelock.c - wake_lock_internal()
if (debug_mask & DEBUG_WAKE_LOCK)
pr_info("wake_lock: %s, type %d, timeout %ld.%03lu\n",
lock->name, type, timeout / HZ,
(timeout % HZ) * MSEC_PER_SEC / HZ);
lock->expires = jiffies + timeout;
lock->flags |= WAKE_LOCK_AUTO_EXPIRE;
list_add_tail(&lock->link, &active_wake_locks[type]);
} else {
if (debug_mask & DEBUG_WAKE_LOCK)
pr_info("wake_lock: %s, type %d\n", lock->name, type);
lock->expires = LONG_MAX;
lock->flags &= ~WAKE_LOCK_AUTO_EXPIRE;
list_add(&lock->link, &active_wake_locks[type]);
}
所以證明 lock 的人是 alarm 和 PowerMangerService.用 cgrep wake_lock_init 可以找出 alarm 是 driver/rtc/alarm-dev.c。
但是找不出 PowerManagerService 是哪裡來的
"base/services/java/com/android/server/PowerManagerService.java" line 610
有:
private void updateWakeLockLocked() {
if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
// keep the device on if we're plugged in and mStayOnWhilePluggedIn is set.
mStayOnWhilePluggedInScreenDimLock.acquire();
mStayOnWhilePluggedInPartialLock.acquire();
} else {
mStayOnWhilePluggedInScreenDimLock.release();
mStayOnWhilePluggedInPartialLock.release();
}
}
證明 充電時是會保持 wakeup...那個 acquire 是 PowerManagerService private class UsynchronizedWakeLock( ) 實做的 function.
public void acquire() {
if (!mRefCounted || mCount++ == 0) {
long ident = Binder.clearCallingIdentity();
try {
PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken,
MY_UID, mTag);
mHeld = true;
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
所以是用 Binder 作的.在 PowerManagerService 中的 WakeLock , Binder 操作,實做了一個 private class WakeLock:
private class WakeLock implements IBinder.DeathRecipient
{
原來 WakeLock 幾乎是 Android 的 PM (power management) 的代名詞。
一些 ref:
所以 cat /proc/wakelock 可以看到所有 wakelock 的統計資料
使用 dumpsys 可以列出 Android System 的狀態 (所有 Service 裡面有實做 dump( ) 的,都會被呼叫).
用
adb shell dumpsys | less
就可以search "Power Manager State"以下是 dumpsys , Battery Service 的部份:
DUMP OF SERVICE battery:
Current Battery Service state:
AC powered: false
USB powered: false
status: 1
health: 0
present: false
level: 0
scale: 100
voltage:0
temperature: 0
technology: null
對應的 code 是:BatteryService.java :469 dump( )
pw.println("Current Battery Service state:");
pw.println(" AC powered: " + mAcOnline);
pw.println(" USB powered: " + mUsbOnline);
pw.println(" status: " + mBatteryStatus);
pw.println(" health: " + mBatteryHealth);
pw.println(" present: " + mBatteryPresent);
pw.println(" level: " + mBatteryLevel);
pw.println(" scale: " + BATTERY_SCALE);
pw.println(" voltage:" + mBatteryVoltage);
pw.println(" temperature: " + mBatteryTemperature);
pw.println(" technology: " + mBatteryTechnology);
所以 AC powered 就是 mAcOnlineBatteryManager 提供的 isPowered(),是根據以下狀態:
final boolean isPowered() {
// assume we are powered if battery state is unknown so the "stay on while plugged in" option will work.
return (mAcOnline || mUsbOnline || mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN);
}
根據 dumpsys 的內容, mAcOnline = false, mUsbOnline = false, mBatteryStatus = 1.BatteryManager.BATTERY_STATUS_UNKNOWN 的宣告:
/base/core/java/android/os/BatteryManager.java:89: public static final int BATTERY_STATUS_UNKNOWN = 1;
所以上述 isPowered( ) return 1 的原因是 mBatteryStatus.=======> 把他 Mark 掉?
但是實際上是 Powered 沒錯,是不應該因為 Powered 就 stayOn,所以應該要改 PowerManagerService..(?)
dumpsys wakeup state 的 PowerManagerService 內容:
DUMP OF SERVICE power:
Power Manager State:
mIsPowered=true mPowerState=3 mScreenOffTime=327973 ms
mPartialCount=1
mWakeLockState=
mUserState=SCREEN_BRIGHT_BIT SCREEN_ON_BIT
mPowerState=SCREEN_BRIGHT_BIT SCREEN_ON_BIT
mLocks.gather=
mNextTimeout=12961205 now=12948606 12s from now
mDimScreen=true mStayOnConditions=0
mStayOnCondition=0.ref PowerManagerService.java 610:
private void updateWakeLockLocked() {
if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
// keep the device on if we're plugged in and mStayOnWhilePluggedIn is set.
mStayOnWhilePluggedInScreenDimLock.acquire();
mStayOnWhilePluggedInPartialLock.acquire();
} else {
mStayOnWhilePluggedInScreenDimLock.release();
mStayOnWhilePluggedInPartialLock.release();
}
}
所以不是這一段 code lock 住。繼續看 dumpsys :
mBroadcastWakeLock=UnsynchronizedWakeLock(mFlags=0x1 mCount=0 mHeld=false)
mStayOnWhilePluggedInScreenDimLock=UnsynchronizedWakeLock(mFlags=0x6 mCount=0 mHeld=false)
mStayOnWhilePluggedInPartialLock=UnsynchronizedWakeLock(mFlags=0x1 mCount=0 mHeld=false)
mPreventScreenOnPartialLock=UnsynchronizedWakeLock(mFlags=0x1 mCount=0 mHeld=false)
mProximityPartialLock=UnsynchronizedWakeLock(mFlags=0x1 mCount=0 mHeld=false)
mProximityWakeLockCount=0
內部lock 變數都不是在 mHeld 狀態。還有:
mLocks.size=1:
PARTIAL_WAKE_LOCK 'GpsLocationProvider' activated (minState=0, uid=1000, pid=2213)
mPokeLocks.size=0:
有一個 mLock 是 activated..使用者是:
./base/location/java/com/android/internal/location/GpsLocationProvider.java:255:
private final static String WAKELOCK_KEY = "GpsLocationProvider";
查GpsLocationProvider.java..
// Create a wake lock
PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
....
...
// beware, the events can come out of order
if ((mNavigating || mEngineOn) && !mWakeLock.isHeld()) {
if (DEBUG) Log.d(TAG, "Acquiring wakelock");
mWakeLock.acquire();
}
所以到 Setting -- Location & Security ,把 GPS 功能關閉.==> 結果一樣,無法 suspend。
用 dumpsys 看, PowerManagerService 的 mLock.size 還是 1.
重新開機.. dumpsys 看.. mLock.size 是 0.
將 CPU_SUSPEND_IN 拉 Low,, 還是無法 suspend,但是 suspend 後的log 變成:
early_suspend++
early_suspend: call handlers
wake_lock: PowerManagerService, type 0
mxcfb_early_suspend
wake_lock: PowerManagerService, type 0
wake_lock: PowerManagerService, type 0
early_suspend: sync
wake_lock: PowerManagerService, type 0
wake_unlock: PowerManagerService
WAKE_LOCK_SUSPEND has_lock:-1
wake_unlock: main
WAKE_LOCK_SUSPEND has_lock:-1
active wake lock android_usb
wake lock mmc_delayed_work, expired
early_suspend--
wake_lock: alarm, type 0, timeout 5.000
wake_lock: PowerManagerService, type 0
wake_unlock: alarm
WAKE_LOCK_SUSPEND has_lock:-1
wake_unlock: PowerManagerService
WAKE_LOCK_SUSPEND has_lock:-1
wake_lock: alarm, type 0, timeout 5.000
wake_lock: PowerManagerService, type 0
wake_unlock: alarm
WAKE_LOCK_SUSPEND has_lock:-1
wake_unlock: PowerManagerService
WAKE_LOCK_SUSPEND has_lock:-1
wake_lock: alarm, type 0, timeout 5.000
wake_lock: PowerManagerService, type 0
wake_unlock: alarm
WAKE_LOCK_SUSPEND has_lock:-1
最後的 PowerMangerService 有 lock - unlock,所以應該不是 PowerManagerService。往前看,有
active wake lock android_usb
猜是usb 連線,把 usb 斷開後, log 出現suspend++
suspend: enter suspend
然後console 失效,wakeup 拉 high 也無法 wakeup.
重新開機,usb 不連接, gps default off, 開機後把 CPU_SUSPEND_IN 拉 low.. 進入 suspend:
state_store mem
*p (null), len:3
state:0 on
state:1 standby
state:2 (null)
state:3 mem
matched 3 !!
request_suspend_state: 3
request_suspend_state: mem (0->3) at 45862462003 (1970-01-01 00:00:42.936891626 UTC)
put early_suspend_work into suspend_work_queue
early_suspend++
early_suspend: call handlers
mxcfb_early_suspend
wake_lock: PowerManagerService, type 0
wake_lock: PowerManagerService, type 0
wake_lock: PowerManagerService, type 0
early_suspend: sync
wake_lock: PowerManagerService, type 0
wake_unlock: PowerManagerService
WAKE_LOCK_SUSPEND has_lock:-1
wake_unlock: main
expired wake lock mmc_delayed_work
WAKE_LOCK_SUSPEND has_lock:0
early_suspend--
suspend++
suspend: enter suspend
pm_suspend
suspend: enter_state
PM: Syncing filesystems ... done.
suspend_prepare
Freezing user space processes ... (elapsed 0.02 seconds) done.
Freezing remaining freezable tasks ... (elapsed 0.01 seconds) done.
PM: Entering mem sleep
suspend_devices_and_enter
suspend_console++
Suspending console(s) (use no_console_suspend to debug)
電流由 1.2 A 降為 0.75A。把 CPU_SUSPEND_IN 拉 High 後,resume.
suspend_console--
dpm_suspend_start
PM: suspend of devices complete after 1235.924 msecs
suspend_enter
suspend wp cpu=800000000
dpm_suspend_noirq
power_suspend_late return 0
PM: late suspend of devices complete after 0.661 msecs
mx5_suspend_enter
PM: early resume of devices complete after 0.559 msecs
ppwrkey_event_handler_Keydown
pwrkey_event_handler_Keyup
IPU DMFC NORMAL mode: 1(0~1), 5B(4,5), 5F(6,7)
wakeup wake lock: mmc_delayed_work
wake_lock: mmc_delayed_work, type 0
wake_lock: mmc_delayed_work, type 0
ppwrkey_event_handler_Keyup
ppwrkey_event_handler_Keydown
pwrkey_event_handler_Keyup
pwrkey_event_handler_Keydown
wake_lock: mmc_delayed_work, type 0, timeout 0.500
wake_lock: mmc_delayed_work, start expire timer, 50
wake_unlock: mmc_delayed_work
WAKE_LOCK_SUSPEND has_lock:0
wake_unlock: mmc_delayed_work, stop expire timer
PM: resume of devices complete after 188.103 msecs
PM: Finishing wakeup.
suspend_finish
Restarting tasks ...
wake_lock: KeyEvents, type 0
wake_unlock: KeyEvents
WAKE_LOCK_SUSPEND has_lock:0
wake_lock: KeyEvents, type 0
wake_lock: PowerManagerService, type 0
state_store on
*p (null), len:2
state:0 on
matched 0 !!
wake_unlock: KeyEvents
WAKE_LOCK_SUSPEND has_lock:-1
wake_lock: KeyEvents, type 0
done.
suspend: exit suspend, ret = 0 (1970-01-01 00:04:44.101005456 UTC)
suspend++
active wake lock KeyEvents
active wake lock PowerManagerService
request_suspend_state: 0
request_suspend_state: on (3->0) at 124256152052 (1970-01-01 00:04:44.115987198 UTC)
wake_lock: main, type 0
put late_resume_work into suspend_work_queue
wake_lock: PowerManagerService, type 0
suspend: abort suspend
late_resume: call handlers
wake_lock: PowerManagerService, type 0
wake_unlock: KeyEvents
WAKE_LOCK_SUSPEND has_lock:-1
wake_lock: KeyEvents, type 0
mxc_ipu mxc_ipu: Channel already disabled 9
mxc_ipu mxc_ipu: Channel already uninitialized 9
wake_lock: PowerManagerService, type 0
wake_unlock: KeyEvents
WAKE_LOCK_SUSPEND has_lock:-1
late_resume: done
Ending connection
mmc1: Starting deferred resume
Ending connection
mmc1: Deferred resume completed
螢幕出現 mode select,按下 HOME Key, 恢復。所以: GPS ON 和 USB connect 會讓 系統無法 suspend.
2011年5月3日 星期二
check project update - repo
Local Repo 跟 developer 都已經使用 git ok.
所以現在每個禮拜一都作:
repo forall -c 'git fetch kirg'
repo forall -p -c 'git diff korg/rkk'
這樣就知道上禮拜哪些 project 改了哪些東西..
確認後,再作 merge..
標籤
- 3g (19)
- 工作的備worklog (93)
- 自言自語 (36)
- 草稿 (1)
- 亂亂寫 (8)
- 翻譯 (3)
- administration (76)
- alsa (7)
- android (299)
- apple (5)
- application (42)
- archlinux (1)
- audio (3)
- avr (6)
- backup_restore (2)
- bluetooth (5)
- bookmark (38)
- bootloader (21)
- browser (5)
- cellphone (28)
- command (8)
- Configuration (27)
- debug (7)
- django (1)
- driver (15)
- earphone (1)
- editor (1)
- EFL (1)
- ffmpeg (18)
- Filesystem (4)
- GCC (8)
- Gentoo (1)
- google (1)
- Graphic (3)
- hardware (40)
- hero (7)
- hibernation (9)
- iMX51 (38)
- Info (3)
- Install (30)
- java (4)
- Kernel (102)
- language (2)
- life (2)
- make (11)
- MantainLog (38)
- MCU_P (9)
- memo (8)
- microcontroller (3)
- MINGW (7)
- network (19)
- OpenCL (1)
- OS (11)
- package (3)
- pad (1)
- ProblemAndSolve (15)
- programming (8)
- Python (7)
- raspberry_pi (23)
- SDL (2)
- sensation (13)
- setup (3)
- software_package (36)
- SQL (1)
- suspend (2)
- ToDo (5)
- tool (3)
- ubuntu (1)
- VersionControl (45)
- Virtualization (15)
- VLC (5)
- wheezy (1)
- wifi (3)
- Windows (16)
- xiaomi (1)
- xperia (1)
網誌存檔
-
▼
2011
(244)
-
▼
5月
(22)
- htop -- the disk io status
- localize android repo -- more detail
- read soc register from /dev/mem
- notes :imx51 ipu
- v4l2 的 capture 取得 camera driver data 的 function : ...
- kernel : DEBUG - dev_dbg
- worklog - Android : add entry into 'About phones'
- u-boot : accessing the 2nd serial port
- Worklog : onKeyDown - Android source
- eclipse - open existing project
- Syntax error, annotations are only available if so...
- datasheet reading .. display port
- re-enable the splash screen in u-boot
- IOMUX & Pad CONFIG
- touch driver tracing
- pmic -- regulator & init call sequence
- key - power key
- Todo today
- Worklog - android suspend - II turn off the periph...
- wakelock in linux kernel
- Worklog - android suspend
- check project update - repo
-
▼
5月
(22)