夏天到了,又到了俺的秘制柠檬茶泡制时节,嘿嘿。
所谓的秘制柠檬茶,就是一两片柠檬,一点绿茶,几角薄荷叶,外加一块方糖冲泡出来的。既有绿茶的芬芳,又有柠檬的酸涩,还有薄荷的清凉,以及一点点调和的甘甜。绿茶的香郁就如盛夏里的林荫,柠檬的酸涩似乎是那晃眼的光芒,薄荷的清凉就犹如迎面的清风,让人品味着丝丝甘甜。其实,泡柠檬茶也有一点点学问的,茶叶不能太多,浓茶不适合在炎炎夏日用来解渴;柠檬则只需要少许,如果含有大块的干果肉,一片即可,但又切不能都是柠檬皮子,否则冲出来太涩;薄荷叶只是用来出味,几片叶角就足以让你觉得清凉。一切就绪,冲入开水,待它们上下翻飞,又沉于平静,就正是品味之时。当然,如果条件许可,略微冰镇一下,效果就更好了。
品茶,就如品味生活,既有平凡的宁静,又有偶尔的艰辛,时不时有醍醐灌顶的清醒,透露出一丝丝的甜蜜。当然,你要有平和的心态和好的心情,不急不燥,否则就如大口大口的柠檬茶下肚,酸甜清凉,只得其一,却忽略了其他的味道。
出现在CCTV的屏幕上,对Dian团队而言是莫大的荣幸。这一方面是对团队工作的肯定,另一方面则对我们提出了更高的要求。有一句俗语叫“盛名之下,其实难副”,意思大家都知道。中央台的报道一出来,我们自己知道其中是有一些夸张或者与事实有出入的。当然从新闻和宣传的角度,这也是一定程度上的需求。但对我们自身而言,不能不对此有清醒的认识,也给我们的同学提出了更高的要求:
1、苦练内功。宣传工作为Dian团队创造了良好的声誉,也给团队的发展创造了外部条件。而与此同时,外界对Dian团队的期待也随之提高。这就要求我们团队中的每一位同学随时随地注意自己的道德水平、工作作风和技术功底,无论走到哪里,别人都会拿更高的标准来要求我们。各位同学稍有不慎,就会给自己和团队的声誉带来影响。因此,苦练内功,在道德、作风和技术三方面修身养性,是让自己真真正正名副其实的手段,对大家也是一个鞭策、激励和提高。
2、低调。同样有这么一句话叫做“王婆卖瓜,自卖自夸”。团队现在是名声在外,这是我们每一位队员都会引以为豪的,在这种情况下,大家要牢记“高调做事,低调做人”。以一种合理的心态去对待外界的宣传和挑剔的眼光。除了苦练内功以外,踏踏实实、勤勤恳恳完成自己的任务,不与外部计较、不与外界攀比,才能有一种心如止水的境界,冷静、客观的看待自己所处的位置、团队所处的环境。如果只是因为外界的一点点宣传和光环,就让我们心飘飘然,那只会适得其反,飘得越高摔得越重。
总之,宣传是团队对外的窗口,是对团队过去成绩的肯定。这些都成为了历史,是前人的过去,而我们能改变的只有从现在开始的未来。于是,未来如何决定于现在怎样开始,希望我们的队员能从零开始,再创辉煌。
——写于2007年4月23日
昨天晚上团队例会播放了于丹《论语心得》之后,yeldsd同学提出了几个矛盾之处,其中之一是说论语里云君子视钱财如粪土,又曰“君子爱财取之有道”,这不是很矛盾么?我对此提出的观点是,俗话说“钱不是万能的,但是没有钱是万万不能的”。我想“君子视钱财如粪土”与“君子爱财取之有道”的关系也在于此。
首先,我们不能把钱财作为一种衡量标准,尤其是绝不能作为唯一的衡量标准。一旦我们开始这样去衡量一件事,一个人,那么个人的价值观、价值判断标准就扭曲了。随之而来的就是陷入一种不能自拔的追求钱财的漩涡当中,最终的结果就是整个人的行为方式简单化为以钱财的多少作为判断标准。用一句话概括就是“掉进钱眼里去了”。当这种情况发生以后,你周围的朋友就会渐渐离你远去,因为你不再是一个可以信赖的人,任何托付于你的事,都可能因为钱财不能得到满足或者发生变化而不能得以完成,毕竟钱财是永远赚不完也永远比不出个高下的。于是,在君子的评价标准当中,一定是视钱财如粪土。从以往经济学的观点看,以前钱财乃黄白之物,现在就简单化到纸币了。纸币在经济学上的名词是“一般等价物”,我相信大家都不会把自己和一般等价物的这个“物”画上等号吧。
第二,虽然君子可以视钱财如粪土,但是君子一定不可能离开钱财生存于这个世界之上。于是我们一定要有办法取得在这个世界生存下来所需的钱财,并且是通过合理合法的手段。这就是论语当中所提出的“君子爱财,取之有道”。
这两者其实并不是矛盾的,只是在不同的角度去看“钱财”这一我们生活中无可避免要打交道的东西罢了。
今天走在路上,偶然间想到以前所写的《寄予Dian团队的队员》,其中的第一点:经常问自己“公司为什么要录用我?”这个问题。当中也提到“大家应该想一想自己现在有什么价值,或者俗气一点就是值多少银子”。或许又会有人提出这与上面的解释出现“矛盾”。其实公司与劳动者之间的关系就是赤裸裸的钱财和劳动的关系。站在公司的立场,它所考虑的就是利润,它所要的就是劳动者为它创造价值,它付给劳动者报酬。至于其他的劳保、培训、深造机会等等,都是在各种外界压力和自身需求基础上出现的,本质上公司并不希望提供这些。于是,当我们应聘的时候自然需要站在公司的角度思考,才能知道自己所面临的形势。但从个人的角度去评价其他的人或事的时候,就不能以钱财作为标准了,否则你就成了一个赤裸裸的人。
我说怎么最简单的c代码编译以后链接总是报这个错误呢:
Error – section ’sharebank’ can not fit the absolute section. Section ’sharebank’ start=0×00000070, length=0×00000010
原来sdcc生成.asm代码的时候用udata_ovr来声明全局临时变量了,并固定在0×70开始的位置。从它的字面意义和放置的位置来看,似乎是想把这些变量放置在不分区的内存位置。如果是对PIC12F675这样的片子,首先地址就错了,不可能是0×70开始,因为RAM地址在这个芯片上只有0×20+64B也就是0×60这么多而已,在0×70的位置没有定义。但是在调整以后还是不行。查MPASM的手册,原来udata_ovr在链接的时候使用的是在LKR当中定义的DATABANK区块,不分区(共享)内存在LKR当中用SHAREBANK定义,在.asm当中应该使用udata_shr来声明。
所以要么用udata_ovr定义,但是指定内存地址的时候不要指到SHAREBANK当中。或者改用udata_shr来声明。bug啊bug~~
sdcc(http://sdcc.sourceforge.net)是一款针对微控制器的小型ANSI C编译器。支持MCS 51/Motorlola HC08等系列的单片机。吸引我的地方在于它还支持Microchip的PIC系列的单片机,尤其是PIC14中档单片机。
本以为sdcc可以帮忙搞定一切,从.c一直到.hex的下载文件。用sdcc test.c之后得到的却是一堆的错误
仔细读manual,原来它本意是为MCS 51开发的,对PIC的支持还没有完全做完,不过已经可以把.c翻译成.asm了,至于从.asm到.hex的过程,可以用gputil或者用Microchip的MPLAB解决。而且对于PIC的支持,使用sdcc的时候要用sdcc -S -mpic14 -p12f675 test.c的形式翻译成.asm。只好依葫芦画瓢,果然得到asm的文件。照着manual当中用mpasmwin /o /q再对.asm进行编译,通过后用mplink链接却报share section出错。
反查.asm当中发现声明udata_ovr起始地址是0×70,显然不符合pic12f675只有64字节RAM的情况(加上0×20的SFR,也只到0×60),改为0×40后仍然报错,索性把后面起始地址的0×70去掉,解决。不过test.c只是很简单的例程,不涉及任何的SFR操作。当我加入对TRISIO操作时,mplink就开始抱怨_ANSEL找不到了
又回到manual看到需要将libsdcc.lib链接进来,可是照着命令敲始终不对,而且sdcclib和mplib都认不出libsdcc.lib的格式,怪哉。于是在sdcc的src code里面翻出pic12f675.c,然后把它编译了与test.o一同链接,通过。my god,难道sdcc提供的pic的lib是有问题的?改天把所有的lib重新编一次再说。
嗯,总算用c语言编了一个pic的程序,虽然只是试试看。下次好好把sdcc的环境整一整,最好能集成到MPLAB IDE里面去 ^_^
似乎题目应该写成“第一次与贼的亲密接触”更吸引眼球一些,呵呵。
事情的经过是这样的,昨天晚上回家,在鲁巷的民院路车站等公交车,我站在人行道上远远的看着站台上的人来人往。终于,久等的车来了,于是我穿过整个人行道和站台上的人群,走到了车门口。我依旧站在队伍的末尾,因为我不是一个喜欢去挤的人,就算没有位置坐,站一会儿对于我们这种成天坐在电脑面前的人来说也就是一个锻炼。
终于等到前面的人都上了车,我也准备收起雨伞跨上去,但是我等了一下下,那是因为前面的一位正站在台阶上还没有往里面走,就算我是跨上车,也是在不上不下的位置。于是我不紧不慢的把雨伞放下收起,却瞟见有一人从我的又后侧靠近,更夸张的是他还把手伸向我的腰侧。恐怕是因为我突然放下雨伞,他意识到被发觉了,于是马上转身离开,装作看错车的样子。我则狠狠瞪了他的背影一眼,呵呵。在快下车的时候,司机问了我一句“没有丢东西吧?”,我才知道原来司机也看出来了。司机还说“让你们别挤别挤是有原因的”。
我也不知道那贼的目标是哪里,到底是我上衣口袋,还是我腰间,还是我的裤子口袋。不过上衣口袋从来都是不放东西或者放些无关重要的东西的~~腰间也不会别手机~~除非他的目标是裤子口袋。可惜我穿牛仔,那些口袋都是贴身朝前的,想捞点啥不被发现还真有点困难。不过我从来都是不紧不慢的人,宁可落在最后也不去抢,居然也有贼想浑水摸鱼。
下次准备在腰间别一个老鼠夹子,哼哼~~
2月底就过完了,然后投入了忙碌的工作当中。本来应该是早涂鸦一下的,结果硬是没有闲功夫。
还是要记录一下春节忙过的事情吧,毕竟是一年中难得的假期。总是号称我们还有暑假,其实压根没有功夫休息。看看这个假期都有哪些事情值得记忆:
1、春节里在两边家里都请吃了饭,算是把事情给办了,不张扬,挺合乎我的想法的;
2、在mm的强烈要求下给自己添了一套衣服,按mm的话说就是终于可以见人了;
3、亲眼看到了传说中的J-10,老爸也好这口,呵呵。在它掠过我们头顶的时候,我们都冒出了这个疑问“不会是J-10吧”?可惜太快没能确认。直到它第二次飞过时,我们通过它独一无二的鸭翼确认了;
4、在老爸的怂恿下全家人去了号称四大名楼(阁)之一的真武阁;
5、mm在老爸的鼓励下,又重新抓起了方向盘,似乎是拿驾照以后正儿八经的练了下车,呵呵;
6、全家人去昆仑关踏青,瞻仰了纪念碑。
差不多就是这些事情了吧,呵呵。
by quickmouse <quickmouse@263.net> 2007年1月10日
一直以来,都认为nash仅仅是作为initrd.img当中加载驱动所使用的命令解释器而已,并没有对initrd.img当中的linuxrc脚本作一个深入的了解。例如,Redhat ES3当中的initrd.img内容(各系统略有不同)如下:
#!/bin/nash
echo "Loading scsi_mod.o module"
insmod /lib/scsi_mod.o
echo "Loading sd_mod.o module"
insmod /lib/sd_mod.o
echo "Loading libata.o module"
insmod /lib/libata.o
echo "Loading ata_piix.o module"
insmod /lib/ata_piix.o
echo "Loading jbd.o module"
insmod /lib/jbd.o
echo "Loading ext3.o module"
insmod /lib/ext3.o
echo Mounting /proc filesystem
mount -t proc /proc /proc
echo Creating block devices
mkdevices /dev
echo Creating root device
mkrootdev /dev/root
echo 0×0100 > /proc/sys/kernel/real-root-dev
echo Mounting root filesystem
mount -o defaults –ro -t ext3 /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc
前面是加载驱动部分,而后面是什么用处,就没有深究了。而我自己用的虚拟机里通常会把驱动和文件系统支持编译到内核,也压根用不着initrd.img,所以把这个宝矿放了过去。今天几个学生在Redhat 9的基础上升级内核到2.6.19,并且是驱动、文件系统用模块方式支持,终于出了问题。该来的还是要来的,应了那句话“出来混,迟早都是要还的”。学生们把前面的硬盘驱动、文件系统驱动都替换成2.6的模块,后半部分在我的误导下删除(当然没有删除的也多半没有成功),结果死活不能进入系统,报无法挂载根文件系统的kernel panic错误。查了半天,发现所有的驱动都加载正常,即便是在linuxrc当中加入bash获得一个shell,检查设备和文件系统的状况也都是正常,可就是提示找不到根文件系统。
开始引起我注意的是,通常在硬盘驱动和文件系统支持都完备的情况下它并没有提示说VFS的root=xxxx错误,而直接提示的“VFS: Unable to mount root fs on (0, 0)”。这意味着它并未识别在grub.conf当中传递给kernel的root=/dev/xxx参数,因为Linux的设备主设备号是不会为0的。我曾怀疑root=参数没有被接受,但却注意到“Please append a correct "root=" boot option”的提示。
为了找出问题,我在linuxrc中用bash取得了一个shell,然后挂载proc文件系统后检查/proc/sys/kernel/real_root_dev,发现其值为0。这说明kernel得到的真实root文件系统的设备号不正确(当然有例外,注意后面的解释)。我试着把正确的设备值(例如/dev/sda2用0×802)写入,退出bash之后启动果然正常了。这说明kernel解析参数root=/dev/xxx出现了错误。
经过核对内核代码,发现kernel确实从root=这个参数传递中获得真实的根文件系统的位置,但是这些/dev/xxx会被转换成内核可识别的设备表示形式。转换的过程中内核会试图检查传递进来的/dev/xxx设备是否存在,而这一步是kernel初始化过程中完成的。当我们把硬盘驱动编译为模块时,kernel初始化过程中硬盘尚不能被识别(要等到kernel初始化完,使用initrd.img才能加载硬盘驱动),于是真实根文件系统的设备号就不能被正确转换,使得其保留为初始值0。
那对于使用硬盘驱动的情况下如何解决这个问题呢?那就是initrd.img后半部分的工作。在加载完硬盘驱动后,脚本会用mkrootdev生成设备/dev/root,通过man nash你会发现这个命令的作用是根据内核传递参数当中的root=来创建对应该设备的节点,节点名就是/dev/root。之后它会把这个设备挂载到/sysroot这个位置,然后用pivot_root这个根交换的命令把真正运行的根文件系统切换到/sysroot之下,而运行linuxrc的initrd的文件系统将被挂载到真正的根系统下的initrd目录。至于“echo 0×0100 > /proc/sys/kernel/real-root-dev”这个命令,看起来是告诉内核真正的文件系统是/dev/ram0,其实是利用内核判断使用/dev/ram0为根文件系统时不再mount其他设备作为根文件系统的分支,作了一个小小的技巧骗过内核。
整个脚本的关键在于mkrootdev这个命令。它不仅能够根据root=/dev/xxx来生成对应的设备节点,还能够在碰到root=LABEL=/的情况下探测所有的硬盘分区,以便找到对应着卷标为/的分区。这也解开了我一直没弄清楚的为什么root=LABEL=xxx的参数有些环境可以用而有些却不行的谜团。这个LABEL=/的解析根本不是内核完成的,而是initrd.img当中linuxrc脚本的mkrootdev命令来完成的。脚本的第二个关键在于它负责完成了本是由内核做的挂载真实根文件系统的动作,并对当前根(即initrd使用的内存文件系统)和真实根文件系统进行根切换,又利用欺骗让内核误认为当前使用/dev/ram0作为根文件系统可以不再挂载真实的根文件系统,可谓用心良苦啊 ^_^
当然,如果完全不用initrd.img的机制,你会发现/proc/sys/kernel/real_root_dev的值也是0。这并不是内核也弄错了,而是只有在使用initrd.img机制时,real_root_dev才反映了内核中记录的真实根文件系统的值,虽然它不一定准确。
最后,总结一下:
1、当硬盘驱动以模块形式提供时root=xxx传递给内核的参数可能不会直接起作用,内核在检查这个参数时可能会发现这个设备(因为没有加载驱动而)不存在,因此导致内核没有接受root=xxx的参数。
2、在这种情况下,initrd.img机制的作用不单单是加载驱动这么简单,还肩负着把正确的真实根的设备位置告知内核的艰巨任务。不过实现的方法有两种:
2.1 把正确的根设备号写入/proc/sys/kernel/real_root_dev,或者
2.2 自己挂载真正的根设备,并进行根交换把根系统切换到真实的根系统上,还要阻止内核去挂载它认为的真实根系统
对于2.2,挂载真正的根系统用nash解释器的内置命令mkrootdev完成,它可以根据传递给kernel的参数(估计读了/proc/cmdline)获得/dev/xxx的字符串,或者得到LABEL=xxx的字符串后查询各个分区的卷标来得到对应的真实根设备号。
3、如果没有使用initrd.img的机制,/proc/sys/kernel/real_root_dev的值没有任何处理,因为它只有在调用initrd.img的时候才会被同步于内核中的操作对象。
另外,redhat 9所带的nash解释器(版本3.4.42)在处理mkrootdev的流程上是有bug的。如果传给kernel的参数使用root=/dev/xxx的形式,那么nash会从/proc/sys/kernel/real_root_dev里获取用户想使用的真实根文件系统位置,显然这在我们上面的分析当中是0,也就是错误的;而如果参数传递是root=LABEL=/的形式,那么nash的处理走的另外一个分支,它会通过解析所有分区的卷标来查找所要的真实根文件系统,并不再查询/proc/sys/kernel/real_root_dev,这倒让我们可以得到正确的结果。bug呀bug。
不过FC6所带的nash 5.1.19已经完全不是这个流程了,应当不存在这样的bug。
近日在对PIC12F675编程的时候,写可重定位代码,用udata定义变量。编译是正确的,但是链接的时候出现如下的错误:
Error – section ‘.udata’ can not fit the section. Section ‘.udata’ length=0×00000002
百思不得其解,换用PIC16F688的链接配置文件,则没有出现这样的问题。虽然16F688的内存资源比12F675多很多,但是程序当中使用的内存也只有2个字节,怎么样都不会出现不够的情况。仔细分析16F688和12F675的链接配置文件,涉及内存部分的有:
12F675:
DATABANK NAME=sfr0nobnk START=0×0 END=0×1F PROTECTED
DATABANK NAME=sfr1nobnk START=0×80 END=0×9F PROTECTED
SHAREBANK NAME=gpr0nobnk START=0×20 END=0×5F
SHAREBANK NAME=gpr0nobnk START=0xA0 END=0xDF
16F688:
DATABANK NAME=sfr0 START=0×0 END=0×1F PROTECTED
DATABANK NAME=sfr1 START=0×80 END=0×9F PROTECTED
DATABANK NAME=sfr2 START=0×100 END=0×11F PROTECTED
DATABANK NAME=sfr3 START=0×180 END=0×19F PROTECTED
DATABANK NAME=gpr0 START=0×20 END=0×6F
DATABANK NAME=gpr1 START=0xA0 END=0xEF
DATABANK NAME=gpr2 START=0×120 END=0×16F
SHAREBANK NAME=gprnobnk START=0×70 END=0×7F
SHAREBANK NAME=gprnobnk START=0xF0 END=0xFF
SHAREBANK NAME=gprnobnk START=0×170 END=0×17F
SHAREBANK NAME=gprnobnk START=0×1F0 END=0×1FF
可以发现16F688把内存分成了分区的部分(DATABANK)和不分区的部分(SHAREBANK,即共享区),而12F675只有不分区(SHAREBANK),全部是共享内存,不需要切换访问。于是,试试把12F675程序当中的变量定义到udata_shr当中,问题得到解决。也就是说因为PIC12F675的所有内存都可以不分区的访问,所以Microchip的MPLAB把12F675的内存全部定义成SHAREBANK,导致没有把内存定义到DATABANK。因此,发生了用udata定义变量链接出错的情况。
上次Philip给我打电话说PM有gift要送给Appliance组的人,我就在猜想是什么礼物,嘿嘿,心想不会是iPod吧。不过前几天富士康和第一财经报道打官司的时候,就有爆出富士康这个血汗工厂正是给Apple代工iPod的,当时就觉得不要是iPod的好,正打算抵制呢。不过转念又想,这哪能随心所愿呢?呵呵。
今天早上一到公司,把所有的东西放置妥当,早餐之后就等着Philip来一块商量项目的进展,也顺便等等我的gift ^_^ 上班半个多小时以后,这家伙终于出现了,笑呵呵的拎着他的大包站在我面前,从里面拿出一个深色的盒子,递到我面前说:“其他人的都发过了,就剩下你的了”,定睛一看,iPod Nano。My god,居然真的是iPod,2G版本的黑色Nano。我不知道如果头一天我就到公司的话会不会有颜色挑,不过真的是头天到的话,也一样不知道拣怎样的
我这人对这方面没有什么感觉,还是让其他人帮我决定了的好,呵呵。这样看来,没能早一天到(错过了火车)还真属于好事多磨了。
于是,顺手给美眉挂了个电话,告诉她有个iPod的礼物,结果立刻被她声称收归国有了,呜呜~~
【后记】4天之后我把Nano送到深圳,一下子就把它塞了个半饱,美眉号称半年不需要更新MP3上的歌曲了。可惜Nano设计上需要通过USB来充电,于是打算做一个直接转USB接口的变压器。电话征求美眉的意见,说砖头是不要的,如果能直接借用她那里已有的充电器,就最好了。那只有索爱的充电器满足这个要求,可是索爱充电器的接口太难做了。直到前两天才用回形针和元件引脚搞定~~