Search This Blog

Apr 15, 2011

Mfgtools mkfs.vfat format fat parittion smaller than 1GB

vfat partition file system reports size is 0.99GB

We met problem when using Mfgtools to update android image to 4GB SD card on MX53 SMD board.I got Mfgtools-Rel-11.03.00_ER_MX53_UPDATER.tar.gz, extract it and select "MX53SMD-Android-SD" config to burn Android image to SD card. Mfgtools use "Profiles\MX53 Linux Update\OS Firmware\ucl.xml" to control burning operation. It will fdisk 5 partitions on SD card. First partition is vfat, and others are EXT4. We can look at part of the code:
"push" body="$ mkfs.vfat /dev/mmcblk0p1">Formatting sd partition
  "push" body="$ mkfs.ext4 /dev/mmcblk0p2">Formatting system partition
  "push" body="$ mkfs.ext4 -O^extent /dev/mmcblk0p4">Formatting recovery partition
  "push" body="$ mkfs.ext4 /dev/mmcblk0p5">Formatting data partition
  "push" body="$ mkfs.ext4 -O^extent /dev/mmcblk0p6">Formatting cache partition
My SD card is 4GB, in this case, vfat partition assigned 3.3GB. But after burn image complete, I found fat partition file system only 0.99GB. I checked update log message, found vfat partition information is correct, 3.3GB size. and format that partition with tool "mkfs.vfat", the problem should comes from this tool. Normally, it should be such as word length issue,32 bits variable has limitation to access GB space size. And from the log, it shows that "mkfs.vfat" version is 2.11, date is 2005. It is six years old.

Found patch via google.

find a bug report in debian, it is known issue that mkfs.vfat 2.11 has bug that will limit fat format size smaller than 1GB. Got the patch, it is very simple, Just add specific CFLAGS in debian/rules.
ifeq ($(ARCH),alpha)
-OPTFLAGS="-fomit-frame-pointer -fno-strict-aliasing"
+OPTFLAGS="-fomit-frame-pointer -fno-strict-aliasing $(shell getconf LFS_CFLAGS)"
else
-OPTFLAGS="-O2 -fomit-frame-pointer"
+OPTFLAGS="-O2 -fomit-frame-pointer $(shell getconf LFS_CFLAGS)"
endif
What is LFS_CFLAGS?
$ getconf LFS_CFLAGS
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
OK, that is key point, it tells mkfs.vfat to support LARGEFILE_SOURCE and FILE_OFFSET_BITS is 64, that make sense.
Get LTIB1101, extract dosfstools package
$./ltib -m prep -p dosfstools
It extract source code in directory rpm/BUILD/dosfstools-2.11/, check debian/rules, but it already contains that patch. Oh, now we suppose that Mfstools default mkfs.vfat has problem, I need generate new mkfs.vfat to replace it.

Generate new Mfgtools ram rootfs.

Mfgtool use initramfs.cpio.gz.uboot as it rootfs when burning image.
execute ./ltib --selectype, select Mfgtools profile, and also select dosfstools and util-linux in package list, mkfs.vfat in dosfstools, sfdisk in util-linux. After building done, copy initramfs.cpio.gz.uboot to Mfgtools directory "Profiles\MX53 Linux Update\OS Firmware". Run Mfgtools to burn image into SD card, but unfortunately, vfat partitin file system report 0.99GB! Why?

Get latest dosfstools_3.0.11.orig.tar.gz

Just suppose this fix doesn't work at all, get latest dosfstools from http://ftp.debian.org/debian/pool/main/d/dosfstools/dosfstools_3.0.11.orig.tar.gz. Put it in /opt/freescale/pkgs/. Modify "ltib/dist/lfs-5.1/dosfstools/dosfstools.spec" to support this new package. Regenerate initramfs.cpio.gz.uboot, testing. Oh, the vfat partition size changed, it change to 2GB size! Oh, that is not my desire... 2GB size normally is FAT16 limitation, but it shows that is FAT32.Must something wrong. I doubt SD card driver has problem to access 2GB size, something like SDHC issue. I want to use "mkfs.ext4 /dev/mmcblk0p1" it shows 3.3GB. SD card driver has no problem, problem comes from mkfs.vfat.

Debug dosfstools_3.0.11 mkdosfs.

I choose ltib environment for debuging, use mx53 SMD board with NFS. Extract dosfstool package.
$./ltib -m prep -p dosfstools
$ cd rpm/BUILD/dosfstools_3.0.11
$ make -j2
We got mkfsdos, it link to mkfs.vfat. Copy it to /tftpboot/sbin. In mx53 smd console, excute "mkfs.vfat", but it report error and cannot run. And then I want to try use ltib to build.
$./ltib -m scbuild -p dosfstools
Copy mkdosfs to /tftpboot/sbin, it can run, but vfat partition size still not correct. What is the difference between LTIB scbuild and directly make under dosfstools directory? Compare the build process message, found when use ltib scbuild it will pass CFLAGS in it, that is to say, CFLAG in mkdosfs Makefile will has no use. Here is the command line when execute ltib scbuild.
arm-none-linux-gnueabi-gcc -c -Dllseek=lseek64 -D_LARGEFILE64_SOURCE mkdosfs
I think that is the root cause, the CFLAG definition for ltib scbuild in "dist/lfs-5.1/dosfstools.spec", modified it:
%Build
-make CC="${TOOLCHAIN_PREFIX}gcc" CFLAGS="-Dllseek=lseek64 -D_LARGEFILE64_SOURCE"
+make CC="${TOOLCHAIN_PREFIX}gcc" 
Build mkdosfs, copy it to /tftpboot/sbin, in mx53 SMD console
$ mkfs.vfat /dev/mmcblk0p1
$ mount -t vfat /dev/mmcblk0p1 /mnt
$ df
It shows 3.3GB.
We locate the root cause!

LTIB default dosfstools 2.11 also works

Turn back to LTIB default dosfstools 2.11, with same modification, mkfs.vfat make format the whole partition to correct size 3.3GB. Now, we known, the CFLAG in "dist/lfs-5.1/dosfstools.spec" cause the problem.

Apr 13, 2011

[ZAKER分享] 纽约时报书评:甘地是怎样炼成的

几年前,英国作家帕特里克•弗兰奇(Patrick French)造访了位于印度古吉拉特邦艾哈迈达巴德市郊的甘地纪念馆(Sabarmati ashram)。1930年,圣雄甘地(Mahatma Gandhi)领导的"食盐长征"正是从这里出发,向大海前进。让弗兰奇大为震惊的是,纪念馆的公共厕所竟然秽气熏天,于是他就去质问纪念馆秘书由谁负责打扫厕所。
图为1906年左右的甘地。
莫罕达斯•K.甘地(Mohandas K. Gandhi)曾留学英国攻读法律,并取得了律师资格。1893年,年轻的甘地以律师的身份来到南非。
  
这位负责人解释说,有一位清洁女工每天都会过来打扫一个小时,但她走后,厕所不可避免地又会变脏。
然而,难道在圣雄对追随者的谆谆教导中,把自己造成的脏乱清理干净不是其中的一项基本原则吗?
"我们都是集中打扫厕所,在甘地诞辰日那一天,"这位秘书回答道,"我们把这当成一种象征性的活动,表明我们领会了他的信息所传达出的意思。"
甘地曾经向世人发出过许多信息,有些被人们忽略了,有些遭到了误解,还有一些信息,即便是时至今日,仍然和第一次从他口中说出时一样至关重要。大多数美国人,其实还包括许多印度中产阶级在内,对圣雄甘地的了解都仅限于于本•金斯利(Ben Kingsley)在那部奥斯卡获奖影片中塑造的银幕形象。他在影片中的表演令人倾倒,但是电影剧本却差强人意,几乎没有触及现实世界中的甘地那种令人困惑的复杂性。彼时,他既是一位虔诚的朝圣者,同时也是一位狡猾的政治家,他是禁欲主义的拥护者、非暴力不合作主义(satyagraha,真理的力量)的缔造者、宗教复兴运动的领导者、革命者以及社会改革家。
而最令约瑟夫•莱利维尔德(Joseph Lelyveld)感兴趣的却是甘地的最后一重身份。用他自己的话来说,他的新作——《伟大的灵魂》一书专注讨论甘地"逐步形成的选民观和社会观"以及他随之而来的行动——竭力要将这种观念强加在其时正"虔诚而又执迷不悟"的印度之上。想要找出一位能够为甘地立传的作者,就印度洋两岸来说,莱利维尔德尤其有资格。他曾为《纽约时报》报道南非新闻(1986年,他以种族隔离为主题的著作——《走出阴霾》(Move Your Shadow)荣获普利策奖),在上世纪60年代末,他又在印度度过了多年的记者生涯。莱利维尔德的这本新书体现了一名记者健康的怀疑精神,也展现了一位"印度通"对印度次大陆及其人民显得有些偏执的强烈兴趣。
这本书并不是一本百科全书式的传记,也并非是为那些对甘地知之甚少的初级读者们预备的。莱利维尔德假设他的读者们对甘地的生平已经有所了解,心中已经能够勾勒出其大致框架。尽管这本书也给出了一份极其简单的年表,并将其划分为南非和印度两大部分来帮助读者做到心中有数,但是其内容却频繁跳跃。读者想要跟上甘地的思想变迁过程或许本身就非易事,在某些时候,他的这种写作风格又平添了几分难度。
尽管如此,《伟大的灵魂》仍是一本值得注意的佳作,笔触生动、描写细腻、目光敏锐。大多数时候,甘地在南非度过的二十余载都仅仅被人们看作是其一生的序曲。莱利维尔德却对这段岁月给予了应有的重视。在一次反对等级制度的运动中,甘地写道,"我隐隐约约地相信,人生而平等,在南非,我曾一步一步地和这种优越论进行抗争。
莱利维尔德提醒我们,事实上,将这种朦胧的信念转化成明确的行动,甘地也经历了很长的一段时期。1893年,23岁的莫罕达斯•卡拉姆昌德•甘地(Mohandas Karamchand Gandhi)从印度孟买来到南非德班,这位机敏的年轻律师在英国接受了专业教育。一位富有的印度穆斯林商人聘请他来到此地为其代理一桩枯燥沉闷的民事诉讼。最开始,甘地对南非的兴趣仅停留在当地的宗教和饮食方面,而并非政治。在早期的一则宣传广告中,他声称自己是"密宗基督教联盟和伦敦素食协会的代理人"。但是,莱利维尔德又写道,"南非……从一开始就对他提出了挑战——他不清楚如何去解释,有着褐色皮肤的他,是如何看待自己在南非的所作所为的。"
起初,甘地仅仅只是有意去触犯那些歧视性法律和那些根深蒂固的地方习俗,对于像他一样受过良好教育、生活富足的印度人和那些"苦力"——贫困的矿场、种植园、铁路工人,他都一视同仁,同等对待。在当时的南非,这些"苦力"是主要的印度移民人口。这之后的二十年里,他所领导的旨在实现印度人和白人平等的非暴力运动,将会促使他去提倡人人平等,首先跨越种姓制度和宗教的界限,然后又打破穷富的屏障。这种过程是缓慢和不稳定的,但其趋势不可阻挡。(而他对于黑人渴望的权利所产生的认同感,一直到他离开非洲很久以后才逐渐形成。)
正如莱利维尔德告诉我们的那样,甘地在南非领导的运动所取得的成果既不明显,也不持久。在一次运动之后,他自己的支持者们将他打得鲜血淋漓,因为他们认为他太快就对政府妥协了。然而,他们也教会了他如何去调动群众——不仅是身为中产阶级的印度教徒和穆斯林移民,还有那些赤贫的底层百姓。正如他自己所说的,他已经找到了他"毕生的使命"。
1915年,甘地回到了印度,不久以后他就提出了印度独立的四项原则,用他的话说就是"独立大厦的四根支柱将会永远挺立"——印度教徒和穆斯林结成不可撼动的同盟;一致认同非暴力主义,将此作为原则,而非战略;通过纺纱以及其他一些自给自足的手工艺品改造印度总共约65万个村庄;废除印度罪孽深重的贱民制度。甘地为了实现这些目标,展开了多次尽管崇高,却注定要失败的斗争。莱利维尔德仔细审视了这些斗争,并作出了敏锐的判断。
 一路走来,他树敌众多——那些认为他过于同情穆斯林的正统印度教徒,那些将他宗教团结的要求看成是印度教的一种阴谋的穆斯林,那些认为他只不过是一个冒充内行的激进革命分子的英国人等等。但是在所有的敌人中,才华横溢、脾气暴躁的贱民领袖比姆拉奥•拉姆吉•安培多伽尔(Bhimrao Ramji Ambedkar)却是最难以对付的。直到如今,西方社会对安培多伽尔还知之甚少。他认为甘地那些旨在铲除贱民制度的非暴力运动充其量只是一种杂耍表演。他甚至还反对甘地为他领导的贱民们杜撰的新名称——"神的子民"(Harijans),认为这词显得有些屈尊俯就;他更喜欢"达利"(Dalits)一词,在印度梵文中的意思是"压碎的"、"破碎的"。
上世纪20年代,甘地在印度。
  
有时,甘地说除非印度废除贱民制度,印度的独立将永远不会到来;而有时他又声称贱民制度只有等印度获得独立以后才能消除。对于这种前后不一的说法,他却不愿道歉。"我无法将全身心都投入到贱民身上,而且还说,'忽略印度教教徒和穆斯林的团结或者是印度独立事业',"他告诉自己的一位友人,"所有这些彼此之间都互相交织,相互依赖。你会发现,在我的一生中,这一次我会强调这件事情,而下一次我又会强调另外一件事情。不过,这就好像是钢琴家弹钢琴,这次加重这个音符,下次又是另外一个音符。"这也正如他对自己的定位那样——他曾说自己是一名政治家,总是小心翼翼地平衡着一个选民群体和其他选民群体之间的要求。
莱利维尔德曾在《走出阴霾》一书中这样写道,"甘地曾希望在千千万万印度人民在道德上取得进步的同时,实现印度的独立,在这样的一次社会革命中,人民对独立和经济平等的追求才是主要的,而异族统治的崩溃只不过是革命成果的副产品。"最终,外国人的统治的确被推翻了,"但是冲突和不平等仍然存在于印度人中间,甚至更甚了。"
如今的印度仍然习惯将甘地称之为"国父",然而在莱利维尔德所说的他的"光轮"之外,我们很难再看到他的余辉。他那些有关性、纺纱、简单生活的理念已被遗忘已久。在并不安稳的表面之下,印度教和穆斯林的不和仍然在酝酿郁积着。贱民制度也依然存在。现在,不管在哪一个达利人的居住区,安培多伽尔那穿着双排扣铁青色西装、系着红色领带的标准版彩色雕像都要多于衣不遮体的圣雄像。
甘地早已预料到以上大多数情况的发生,有些也会陷于绝望。莱利维尔德认为,甘地一生最大的悲剧,并"不在于他遭到了暗杀,也不是因为他高贵的品质激起了暗杀者心中的仇恨。他的悲剧在于,尽管不情愿,但最终他还是看到自己改造世界的雄心也存在着一定的局限,正如李尔王(Lear)一样。"
不管怎样,莱利维尔德同时还写道,尽管甘地也许"一直到自己的弥留之际,都在与怀疑和自我做斗争,"但他"给千千万万的同胞们带来了困境,无论他们之间存在怎样的紧张关系,因为没有哪位近代的领导人曾这样做过。"再者,尽管他前后矛盾,但在他的一生中,他的印度梦想却从来未曾改变过。"如今,"在被自己的追随者暗杀之前不到三周的时候,他写道,"不管我们是印度教教徒、锡克教徒、穆斯林,还是拜火教徒,我们都必须忘记这种身份……在我们的家园,我们以何种方式呼唤神并不重要。"
在19、20世纪之交来临前夕,他在南非第一次敦促当地的印度人团结起来和压迫者抗争的时候,这是一种革命性的观念。当他在第一次世界大战之际回到祖国的时候,这是一种革命性的观念。而到了1947年,印度在取得独立的同时又因宗教仇恨而分裂时,这仍然是一种革命性观念。他曾屡次冒着生命危险,想要平息这种仇恨,然而令人悲哀的是,至今这仍是极具颠覆性的观念——在印度乃至更广阔的世界范围来说都是如此。
杰弗里•C.沃德(Geoffrey C. Ward)是一名传记作家和纪录片编剧,他少年时期曾在印度度过数年,目前正在撰写一本有关印度分裂的著作。



Sent from my iPad

Apr 12, 2011

Android graphics benchmark

   We need to know graphics benchmark in Android.
1. Get Android benchmark apk and console application. List them all
apk files:
    ApiDemos.apk
    com.qualcomm.qx.neocore.apk
    DrawTest_16_16.apk
    kr.co.ocosmos.cube.apk
    Quadrant_Standard_v1.1.2.apk
    se.nena.nenamark1.apk
    SkiaTest.apk
    SpeedTest.apk

console files:
    console_cube/
    3DMark/

2. Install them into Android system via adb.
$ ./adb install ApiDemoes.apk
$ ./adb install com.qualcomm.qx.neocore.apk
...
# Install all apk into Android devices.
# And then we push console test files into /system/bin directory, this directory is read-only in default, remount it as read-write.
$ mount -o remount rw /system
$ ./adb push console_cube/ /system/bin/console_cube
$ ./adb push 3DMark/ /system/bin/3DMark

3. Run APPS in Android UI and get performance test result.

3D benchmark
Neocore
25.8fps
NenaMark1
18.3fps
Cube
25ms/frame
Intro (3DMark)
61.57fps
Samurai (3DMark)
43.86fps
Proxycon (3DMark)
21.89fps
2D benchmark

ApiDemo (Graphics/OpenGL ES/Sprite Text)
15ms/frame
Concole_cube
70.9fps
SpeedTest (1024*600)
Landscape (Nop=0,GL=0)
30.50fps
Portrait (Nop=0,GL=0)
33.34fps
Landscape (Nop=2,GL=0)
71.74fps
Portrait (Nop=2,GL=0)
70.52fps
DrawTest
bmp 16bit, sur 16bit, landscape
71.61fps
bmp 16bit, sur 16bit, portrait
71.57fps
bmp 32bit, sur 32bit, landscape
70.91fps
bmp 32bit, sur 32bit, portrait
46.16fps
bmp 32bit, sur 16bit, landscape
71.11fps
bmp 32bit, sur 16bit, portrait
68.15fps
bmp 16bit, sur 32bit, landscape
51.10fps
bmp 16bit, sur 32bit, portrait
42.60fps
SkiaTest
Fill Rectangle (Test 1)
40381
Stretch blit with Dither (Test 2.1)
1641
Stretch blit without Dither (Test 2.2)
4475

Dimming (Test 3)
8574

256 color pallet blit (Test 4.1)
4078

Stretch blit (Test 4.2)
2542

Draw line (Test 5)
476665
2D/3D benchmark
Quadrant_Standard_v1.1.2.apk
1098 (Total)
218 (2D)
262 (3D)

Mar 9, 2011

Set Linux power state as "mem" not working

1.客户反馈执行命令 “echo mem > /sys/power/state” 不起作用。

2. 重现和比较:

2.1 我拿客户的板子和程序,编译后跑,可以重现客户说的问题。串口显示
PM: Syncing filesystems ... done.
Freezing user space processes ... (elapsed 0.01 seconds) done.
Freezing remaining freezable tasks ... (elapsed 0.01 seconds) done.
Suspending console(s) (use no_console_suspend to debug)
就不再往下跑了,不过按键盘串口仍然有回显。
2.2 在Linux PC上执行了下“echo mem > /sys/power/state”,PC立即屏幕变黑,按键和鼠标都无反应,按机箱上的Power开关,Linux苏醒过来。
2.3 拿MX53 EVK跑标准程序,执行“echo mem > /sys/power/state”,立即进入suspend,串口无回显,按板子上的Power on键,Linux苏醒过来。

3. 定位最后显示的错误代码

从“Suspending console(s) (use no_console_suspend to debug)”,找到其在文件kernel/printk.c中函数void suspend_console()里面。
void suspend_console(void)
{
 if (!console_suspend_enabled)
  return;
 printk("Suspending console(s) (use no_console_suspend to debug)\n");
 acquire_console_sem();
 console_suspended = 1;
 up(&console_sem);
}
看到一个变量console_suspend_enabled来控制是否使串口进入suspend,往上看一下,这个变量在函数console_suspend_disable()做了赋值,
static int __init console_suspend_disable(char *str)
{
 console_suspend_enabled = 0;
 return 1;
}
__setup("no_console_suspend", console_suspend_disable);
console_suspend_disable()是 _setup()执行的函数,也就是根据u-boot传递过来的启动参数里查看是否定义了“no_console_suspend”,有定义就执行console_suspend_disable()。所有的_setup()圈定的函数会在init/main.c里面的static int __init obsolete_checksetup(char *line)集中执行。
对于调试来说,在函数里面修改比在u-boot参数休改要快捷,于是添加了一行代码在suspend_console()函数里面。
void suspend_console(void)
{
        console_suspend_enabled = 0;
 if (!console_suspend_enabled)
  return;
 printk("Suspending console(s) (use no_console_suspend to debug)\n");
 acquire_console_sem();
 console_suspended = 1;
 up(&console_sem);
}
编译运行后,执行“echo mem > /sys/power/state”打出了大量信息,一个空指针导致kernel崩溃。
root@freescale ~$ echo mem >/sys/power/state
PM: Syncing filesystems ... done.
Freezing user space processes ... (elapsed 0.01 seconds) done.
Freezing remaining freezable tasks ... (elapsed 0.01 seconds) done.
suspend_devices_and_enter
da9052_tsi_suspend: called
PM: suspend of devices complete after 7.109 msecs
mx5_suspend_prepare
suspend wp cpu=400000000
Unable to handle kernel NULL pointer dereference at virtual address 00000008
pgd = 9537c000
[00000008] *pgd=85366031, *pte=00000000, *ppte=00000000
Internal error: Oops: 17 [#1] PREEMPT
last sysfs file: /sys/power/state
Modules linked in:
CPU: 0    Not tainted  (2.6.35.3-744-g27fdf7b-g4ab9a2c-dirty #154)
PC is at set_cpu_freq+0x38/0xe8
LR is at _clk_arm_get_rate+0x20/0x28
pc : [<800541bc>]    lr : [<8003fb74>]    psr: 80000013
sp : 954d7eb8  ip : 00000100  fp : 00000002
r10: 8076fd4a  r9 : 80419028  r8 : 80401bfc
r7 : 00000001  r6 : 3b9aca00  r5 : 17d78400  r4 : 00000000
r3 : 00000001  r2 : 00000000  r1 : 00000004  r0 : 3b9aca00
Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: 10c5387d  Table: 8537c019  DAC: 00000015
Process sh (pid: 2142, stack limit = 0x954d62e8)
Stack: (0x954d7eb8 to 0x954d8000)
7ea0:                                                       954d7ed0 00000000
7ec0: 8080dde8 00000001 80401bfc 8003c94c 00000000 000f4240 00061a80 003fff00
7ee0: 00000004 00000003 00000000 003fffff 00000004 8008d704 8076fd4a 00000003
7f00: 00000000 8008d930 95364000 00000003 00000003 8008cfd0 950195a0 95454718
7f20: 954d7f80 00000004 95454700 80419028 95002840 801e54d4 950195a0 8010b06c
7f40: 00000004 95404900 2aac9000 954d7f80 00000004 954d6000 0009a26c 800c0ea0
7f60: 95404900 2aac9000 95404900 2aac9000 00000000 00000000 00000004 800c0ff4
7f80: 00000000 00000000 00000004 00000000 00000004 2abf65c8 00000004 00000004
7fa0: 80033104 80032f80 00000004 2abf65c8 00000001 2aac9000 00000004 00000000
7fc0: 00000004 2abf65c8 00000004 00000004 2aac9000 00000000 0009a26c 00000002
7fe0: 00000000 7ed065e0 2ab33c48 2ab8624c 60000010 00000001 70b4a021 70b4a421
[<800541bc>] (set_cpu_freq+0x38/0xe8) from [<8003c94c>] (mx5_suspend_prepare+0xfc/0x13c)
[<8003c94c>] (mx5_suspend_prepare+0xfc/0x13c) from [<8008d704>] (suspend_devices_and_enter+0x94/0x200)
[<8008d704>] (suspend_devices_and_enter+0x94/0x200) from [<8008d930>] (enter_state+0xc0/0x124)
[<8008d930>] (enter_state+0xc0/0x124) from [<8008cfd0>] (state_store+0xa0/0xbc)
[<8008cfd0>] (state_store+0xa0/0xbc) from [<801e54d4>] (kobj_attr_store+0x18/0x1c)
[<801e54d4>] (kobj_attr_store+0x18/0x1c) from [<8010b06c>] (sysfs_write_file+0x108/0x13c)
[<8010b06c>] (sysfs_write_file+0x108/0x13c) from [<800c0ea0>] (vfs_write+0xac/0x154)
[<800c0ea0>] (vfs_write+0xac/0x154) from [<800c0ff4>] (sys_write+0x3c/0x68)
[<800c0ff4>] (sys_write+0x3c/0x68) from [<80032f80>] (ret_fast_syscall+0x0/0x30)
Code: e594203c e1a04003 e5911000 ea000003 (e5920008)
---[ end trace 53b6c4297f475235 ]---

4. 定位空指针

从上面的信息看崩溃的地址在“set_cpu_freq+0x38/0xe8”,本想用工具辅助定位在vmlinux中的具体位置,不过命令都忘了...花了五分钟回忆没有任何结果就改用printk()来定位了,set_cpu_freq这个函数也不大,应该会比较快。函数在arch/arm/plat-mxc/cpufreq.c里面。里面的各个变量,函数都看起来都老实本分,不像是NULL指针应该具有的样子。通常这些冷僻函数久经考验,基本发布后就不会有人修改的。然而现实和理想总是有一定的差距,经过定位cpu_wp_tbl的地址竟然是“0”!
int set_cpu_freq(int freq)
{
...
 pr_info("cpu_wp_tbl addr = 0x%x\n",(unsigned int)cpu_wp_tbl);
 for (i = 0; i < cpu_wp_nr; i++) {
  if (freq == cpu_wp_tbl[i].cpu_rate)
   gp_volt = cpu_wp_tbl[i].cpu_voltage;
 }
...
 return ret;
}

5. 查找cpu_wp_tbl为何为0.

cpu_wp_tbl是什么?经查证,是指CPU working points,保存cpu频率,电压等信息。在cpufreq.c里面函数有对其赋值。
static int __init mxc_cpufreq_driver_init(struct cpufreq_policy *policy)
{
...
  cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
 cpu_freq_khz_min = cpu_wp_tbl[0].cpu_rate / 1000;
 cpu_freq_khz_max = cpu_wp_tbl[0].cpu_rate / 1000;
...
}
而get_cpu_wp()是一个指针函数struct cpu_wp *(*get_cpu_wp)(int *wp),在arch/arm/mach-mx5/mx53_wp.c我们找到其赋值的地方.
void mx53_set_cpu_part_number(enum mx53_cpu_part_number part_num)
{
 get_cpu_wp = mx53_get_cpu_wp;
 set_num_cpu_wp = mx53_set_num_cpu_wp;
 switch (part_num) {
 case IMX53_CEC_1_2G:
  cpu_wp_table = cpu_wp_ces_1_2g;
  num_cpu_wp = ARRAY_SIZE(cpu_wp_ces_1_2g);
  break;
 case IMX53_CEC:
  cpu_wp_table = cpu_wp_ces;
  num_cpu_wp = ARRAY_SIZE(cpu_wp_ces);
  break;
 case IMX53_AEC:
 default:
  cpu_wp_table = cpu_wp_aec;
  num_cpu_wp = ARRAY_SIZE(cpu_wp_aec);
  break;
 }
}
那么mx53_get_cpu_wp又做了什么?原来只是返回一个结构数组指针。
struct cpu_wp *mx53_get_cpu_wp(int *wp)
{
 *wp = num_cpu_wp;
 return cpu_wp_table;
}
根据mx53_set_cpu_part_number()函数的内容,cpu_wp_table只能是cpu_wp_ces_1_2g,cpu_wp_ces,cpu_wp_aec。经确认,我们目前跑1GHz,也就是说cpu_wp_table = cpu_wp_ces.看起来逻辑清楚,cpu_wp_tbl怎么会为“0”呢?还是回到cpufreq.c里面的cpu_wp_tbl的赋值部分,看看它拿到一个有效的地址没有。在函数里面加上打印代码:
static int __init mxc_cpufreq_driver_init(struct cpufreq_policy *policy)
{
 int ret;
 int i;

 printk(KERN_INFO "i.MXC CPU frequency driver\n");

 if (policy->cpu != 0)
  return -EINVAL;

 cpu_clk = clk_get(NULL, "cpu_clk");
 if (IS_ERR(cpu_clk)) {
  printk(KERN_ERR "%s: failed to get cpu clock\n", __func__);
  return PTR_ERR(cpu_clk);
 }

 gp_regulator = regulator_get(NULL, gp_reg_id);
 if (IS_ERR(gp_regulator)) {
  clk_put(cpu_clk);
  printk(KERN_ERR "%s: failed to get gp regulator\n", __func__);
  return PTR_ERR(gp_regulator);
 }

 /* Set the current working point. */
 if(get_cpu_wp)
  printk(KERN_INFO"We have get_cpu_wp define!!!!!!!!!!!!!!!!!!!!!!!!!\n");
 else
  printk(KERN_INFO"We have not get_cpu_wp define!!!!!!!!!!!!!!!!!!!!!!!!!\n");
 cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
  printk(KERN_INFO"cpu_wp_tbl adddddr= 0x%x\n",(unsigned int)cpu_wp_tbl);

  cpu_freq_khz_min = cpu_wp_tbl[0].cpu_rate / 1000;
 cpu_freq_khz_max = cpu_wp_tbl[0].cpu_rate / 1000;
...
}
编译运行没有跑到加的输出信息那里,也就是说cpu_wp_tbl没有赋值!
仔细查看了启动的输出信息后发现有这样的输出信息:
i.MXC CPU frequency driver
regulator: get() with no identifier
mxc_cpufreq_driver_init: failed to get gp regulator
哦,在cpu_wp_tbl前面出错返回了,没有赋值,所以cpu_wp_tbl为NULL。

6. 为何regulator_get(NULL, gp_reg_id)出错?

这也是一段忠厚老实的代码,为什么总在忠厚老实的代码里面打转?不想质疑regulator_get()可靠性,直接查gp_reg_id。发现其在arch/arm/mach-mx5/bus_freq.c里面定义的,赋值也是在函数busfreq_probe()里面实现的。这里再次强调,一个好的IDE会使查找过程变得非常快速,并有效防止个人在漫长查找过程中思想溜号跑去上网等影响效率的事情发生。
static int __devinit busfreq_probe(struct platform_device *pdev)
{
...
 gp_reg_id = p_bus_freq_data->gp_reg_id;
...
}
恩,再找p_bus_freq_data->gp_reg_id,在arch/arm/mach-mx5/mx53_smd.c发现了定义。
static struct mxc_bus_freq_platform_data bus_freq_data = {
 .gp_reg_id = "DA9052_BUCK_CORE",
 .lp_reg_id = "DA9052_BUCK_PRO",
};
再看发现其竟然没有注册...
// mxc_register_device(&busfreq_device, &bus_freq_data);
迅速打开编译,运行,启动后串口输出没有再打印“mxc_cpufreq_driver_init: failed to get gp regulator”。

7. 验证

在串口键入“echo mem > /sys/power/state”,板子迅速进入suspend,按power on key,板子苏醒。OK,All done!

Mar 3, 2011

存理克欲(四)

孟子見梁惠王。王曰:「叟,不遠千里而來,亦將有以利吾國乎?」
孟子對曰:「王何必曰利?亦有仁義而已矣。」「王曰:『何以利吾國?』大夫曰:『何以利吾家?』士庶人曰:『何以利吾身?』上下交征利,而國危矣!萬乘之國,弒其君者,必千乘之家;千乘之國,弒其君者,必百乘之家。萬取千焉,千取百焉,不為不多矣;茍為後義而先利,不奪不饜。」
「未有仁而遺其親者也,未有義而後其君者也。」
「王亦曰:仁義而已矣,何必曰利?」


语译:
  孟子见梁惠王。梁惠王说:“老先生,您不远千里来到我国,将有些策略来使我国获利吧?”孟子答道:“大王何必说利呢?也只有讲仁义就是了。大王说:如何使我国获利?大夫说:如何是我家获利?士,庶人说:如何使我个人获利?假使上上下下的人都相互夺取利益,那么邦国就危险了。拥有万乘兵车的邦国,弑杀他的国君的,必是拥有千乘兵车的大夫之家;拥有千乘兵车的邦国,弑杀他的国君的,必是拥有百乘兵车的大夫之家。在万乘之国中拥有千乘兵车,在千乘之国中拥有百乘兵车,不能说不多了。假使把义放在后面,却把利放在前头,那么不全部夺走是不会满足的。没有一个有仁德的人却遗弃他的父母啊!没有一个讲道义的人却把他的国君阁在脑后啊!大王也只有讲仁义就是了,何必说利呢?

析论
   颇有感触“苟为后义而先利,不夺不餍(yan)”凡事利字当前,真是欲壑难填,无所不为。私利是祸乱相寻的源头。董仲舒说:凡事只要合乎仁义,以仁德和天地万物相感通,以道义节制其轻重厚薄,使其和于中庸之道,自然无需先考虑是否得利,而天下之大利自然就在之中了。行中道,去私利,无需瞻前顾后,处事自然顺畅无滞。

存理克欲(三)

「齊人有一妻一妾而處室者。其良人出,則必饜酒肉而後反。其妻問所與飲食者,則盡富貴也。其妻告其妾曰:『良人出,則必饜酒肉而後反,問其所與飲食者,盡富貴也,而未嘗有顯者來。將瞷良人之所之也。』蚤起,施從良人之所之,〔彳扁〕國中無與立談者,卒之東郭墦間之祭者,乞其餘,不足,又顧而之他,此其為饜足之道也。
其妻歸,告其妾曰:『良人者,所仰望而終身也。今若此!』與其妾訕其良人,而相泣於中庭。而良人未之知也,施施從外來,驕其妻妾。
由君子觀之,則人之所以求富貴利達者,其妻妾不羞也,而不相泣者,幾希矣!


语译
  齐国有一妻一妾住在一起的家庭,这户人家的丈夫一出门,就必定酒足饭饱才回家。他妻子问和他一起吃喝的是什么人,他就说都是些富贵的人。他妻子跟他的妾说:“丈夫一出门,就必定喝足酒,吃饱肉才回家。问他一起吃喝的是什么人,他就说都是些富贵的人,可是却不曾有富贵的人来家里。我打算暗中查看他是往哪儿去的。”翌日,她起了个大早,躲躲藏藏的跟踪丈夫走过的地方,走遍城中,竟没有一个人停下来跟他说话。最后走到东门外的坟地间,向上坟的人乞讨祭坟剩余的食物来吃,吃不够,又转而向另一处乞食。这就是他吃饱喝足的方法。他妻子回家,对他的妾说:“做丈夫的人是我们指望依靠他过一辈子的人,现在竟然如此!”两人埋怨责骂她们的丈夫,并且在庭中相向哭泣。然而这个做丈夫的还不知道,仍然喜滋滋的从外面回来,又向妻妾夸耀骄傲一番。
  用君子的眼光来看此事,那么世人追求富贵利达的奸邪行径,他们的妻妾不感觉羞耻,并且不相向哭泣的,恐怕是很少的。

析论:
   良人不良,自欺欺人,无耻之尤。孟子正是以冷隽的反讽,痛斥那些谄媚阿谀,巧取豪夺,以求富贵利达的无耻败德之徒。顾炎武说“博学于文”,“行己有耻”,这应该是每个人的自我要求。
   

存理克欲(二)

孟子曰:「魚,我所欲也;熊掌,亦我所欲也,二者不可得兼,舍魚而取熊掌者也。生,亦我所欲也;義,亦我所欲也,二者不可得兼,舍生而取義者也。生亦我所欲,所欲有甚於生者,故不為苟得也;死亦我所惡,所惡有甚於死者,故患有所不辟也。如使人之所欲莫甚於生,則凡可以得生者,何不用也?使人之所惡莫甚於死者,則凡可以辟患者,何不為也?由是則生而有不用也,由是則可以辟患而有不為也。是故所欲有甚於生者,所惡有甚於死者,非獨賢者有是心也,人皆有之,賢者能勿喪耳。」
「一簞食,一豆羹,得之則生,弗得則死。嘑爾而與之,行道之人弗受;蹴爾而與之,乞人不屑也。萬鍾則不辨禮義而受之。萬鍾於我何加焉?為宮室之美、妻妾之奉、所識窮乏者得我與?鄉為身死而不受,今為宮室之美為之;鄉為身死而不受,今為妻妾之奉為之;鄉為身死而不受,今為所識窮乏者得我而為之,是亦不可以已乎?此之謂失其本心。」

语译:
  孟子说:鱼是我喜欢的;熊掌也是我所喜欢的,假如这两者不能兼得,我情愿舍弃鱼而选择熊掌。生命是我所爱惜的;道义也是我所爱惜的,假如这两者只能取其一,我情愿舍弃生命而成全道义。生命是我所爱惜的,然而我所爱惜的有比生命还要贵重时,就不会苟且求生了;死亡时我所憎恶的,然而我所憎恶的有比死亡还要可厌,就不会苟且避开祸患了。假如一个人所爱惜的没有比生命更贵重了,那么凡是足以维持生命的手段,还有什么使不出来的呢?假如一个人所憎恶的没有比死亡更可厌的了,那么凡是足以避免死亡灾祸的事情,还有什么做不出来的呢?照这样做,就能生存下去,可是却有人不这样做,照这样做,就可以避免祸患,可是却有人不这样做。由此可知,人所爱惜的有比生命更珍贵的,人所憎恶的有比死亡更可厌。不只是贤德的人有这样崇尚道义的羞恶之心,每一个人都有啊!只是贤德的人能够存养本心而不丧失罢了。
  譬如有一小竹篮的饭,有一碗羹汤,饿极了的人得到了就能活命,得不到就要饿死。然而大声吆喝的给他吃,即使是一般的路人也不肯接受;假如是用脚拨给他,就连乞丐也不屑一顾了。然而一旦万钟厚禄当前,许多人就不去分辨是否合乎礼义而接受了。那万钟厚禄对我有什么助益呢?是为了住宅的华美,妻妾的奉侍,以及那些困穷的朋友可以得到我的好处而对我感激吗?从前情愿饿死也不愿意接受不礼貌的施舍,现在却为了华美的住宅就接受了;从前情愿饿死也不愿接受不礼貌的施舍,现在却为了妻妾的奉侍就接受了;从前情愿饿死也不愿意接受不礼貌的施舍,现在却为了要使那些困穷的朋友对自己感激就接受了,这种行为难道不可以停止吗?这种情形就叫做失去本有的良心。


析论:
   这篇文章在学校是背的烂熟,今天读来仍是回味无穷。人往往为私利所困,趋利避患,不择手段,无所不为。孟子点出“所欲有甚于生者”,“所恶有甚于死者”。须得秉承良知行事,方能自由。