2009年5月25日星期一

C++中typedef关键字的用法 [zt]

(http://blog.sina.com.cn/u/4862c01601000665   )  
Typedef 声明有助于创建平台无关类型,甚至能隐藏复杂和难以理解的语法。不管怎样,使用 typedef 能为代码带来意想不到的好处,通过本文你可以学习用 typedef 避免缺欠,从而使代码更健壮。
      typedef 声明,简称 typedef,为现有类型创建一个新的名字。比如人们常常使用 typedef 来编写更美观和可读的代码。所谓美观,意指 typedef 能隐藏笨拙的语法构造以及平台相关的数据类型,从而增强可移植性和以及未来的可维护性。本文下面将竭尽全力来揭示 typedef 强大功能以及如何避免一些常见的陷阱。
      如何创建平台无关的数据类型,隐藏笨拙且难以理解的语法?
 
使用 typedefs 为现有类型创建同义字。定义易于记忆的类型名
  typedef 使用最多的地方是创建易于记忆的类型名,用它来归档程序员的意图。类型出现在所声明的变量名字中,位于 ''typedef'' 关键字右边。例如:typedef int size;
  此声明定义了一个 int 的同义字,名字为 size。注意 typedef 并不创建新的类型。它仅仅为现有类型添加一个同义字。你可以在任何需要 int 的上下文中使用
size:void measure(size * psz);
size array[4];
size len = file.getlength();
std::vector <size> vs;
  typedef 还可以掩饰符合类型,如指针和数组。例如,你不用象下面这样重复定义有 81 个字符元素的数组:char line[81];
char text[81];
定义一个 typedef,每当要用到相同类型和大小的数组时,可以这样:
typedef char Line[81];
Line text, secondline;
getline(text);
同样,可以象下面这样隐藏指针语法:
typedef char * pstr;
int mystrcmp(pstr, pstr);
  这里将带我们到达第一个 typedef 陷阱。标准函数 strcmp()有两个'const char *'类型的参数。因此,它可能会误导人们象下面这样声明
mystrcmp():int mystrcmp(const pstr, const pstr);
   这是错误的,按照顺序,'const pstr'被解释为'char * const'(一个指向 char 的常量指针),而不是'const char *'(指向常量 char 的指针)。这个问题很容易解决:typedef const char * cpstr;
int mystrcmp(cpstr, cpstr); // 现在是正确的
记住:不管什么时候,只要为指针声明 typedef,那么都要在最终的 typedef 名称中加一个 const,以使得该指针本身是常量,而不是对象。代码简化
   上面讨论的 typedef 行为有点像 #define 宏,用其实际类型替代同义字。不同点是 typedef 在编译时被解释,因此让编译器来应付超越预处理器能力的文本替换。例如:typedef int (*PF) (const char *, const char *);
  这个声明引入了 PF 类型作为函数指针的同义字,该函数有两个 const char * 类型的参数以及一个 int 类型的返回值。如果要使用下列形式的函数声明,那么上述这个 typedef 是不可或缺的:PF Register(PF pf);
   Register() 的参数是一个 PF 类型的回调函数,返回某个函数的地址,其署名与先前注册的名字相同。做一次深呼吸。下面我展示一下如果不用 typedef,我们是如何实现这个声明的:int (*Register (int (*pf)(const char *, const char *)))
(const char *, const char *);
  很少有程序员理解它是什么意思,更不用说这种费解的代码所带来 的出错风险了。显然,这里使用 typedef 不是一种特权,而是一种必需。持怀疑态度的人可能会问:"OK,有人还会写这样的代码吗?",快速浏览一下揭示 signal()函数的头文件 <csinal>,一个有同样接口的函数。typedef 和存储类关键字(storage class specifier)
   这种说法是不是有点令人惊讶,typedef 就像 auto,extern,mutable,static,和 register 一样,是一个存储类关键字。这并是说 typedef 会真正影响对象的存储特性;它只是说在语句构成上,typedef 声明看起来象 static,extern 等类型的变量声明。下面将带到第二个陷阱:typedef register int FAST_COUNTER; // 错误
  编译通不过。问题出在你不能在声明中有多个存储类关键字。因为符号 typedef 已经占据了存储类关键字的位置,在 typedef 声明中不能用 register(或任何其它存储类关键字)。促进跨平台开发
  typedef 有另外一个重要的用途,那就是定义机器无关的类型,例如,你可以定义一个叫 REAL 的浮点类型,在目标机器上它可以i获得最高的精度:typedef long double REAL;
在不支持 long double 的机器上,该 typedef 看起来会是下面这样:typedef double REAL;
并且,在连 double 都不支持的机器上,该 typedef 看起来会是这样:、typedef float REAL;
   你不用对源代码做任何修改,便可以在每一种平台上编译这个使用 REAL 类型的应用程序。唯一要改的是 typedef 本身。在大多数情况下,甚至这个微小的变动完全都可以通过奇妙的条件编译来自动实现。不是吗? 标准库广泛地使用 typedef 来创建这样的平台无关类型:size_t,ptrdiff 和 fpos_t 就是其中的例子。此外,象 std::string 和 std::ofstream 这样的 typedef 还隐藏了长长的,难以理解的模板特化语法,例如:basic_string<char, char_traits<char>,allocator<char>> 和 basic_ofstream<char, char_traits<char>>。 作者简介
  Danny Kalev 是一名通过认证的系统分析师,专攻 C++ 和形式语言理论的软件工程师。1997 年到 2000 年期间,他是 C++ 标准委员会成员。最近他以优异成绩完成了他在普通语言学研究方面的硕士论文。业余时间他喜欢听古典音乐,阅读维多利亚时期的文学作品,研究 Hittite、Basque 和 Irish Gaelic 这样的自然语言。其它兴趣包括考古和地理。Danny 时常到一些 C++ 论坛并定期为不同的 C++ 网站和杂志撰写文章。他还在教育机构讲授程序设计语言和应用语言课程。来源二:(http://www.ccfans.net/bbs/dispbbs.asp?boardid=30&id=4455)
 C语言中typedef用法
1. 基本解释  typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数 据类型(struct等)。  在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声 明。  至于typedef有什么微妙之处,请你接着看下面对几个问题的具体阐述。
 2. typedef & 结构的问题  当用下面的代码定义一个结构时,编译器报了一个错误,为什么呢?莫非C语言不允许在结构中包含指向它自己的指针吗?请你先猜想一下,然后看下文说明:typedef struct tagNode
{
 char *pItem;
 pNode pNext;
} *pNode;
  答案与分析:  1、typedef的最简单使用typedef long byte_4;
  给已知数据类型long起个新名字,叫byte_4。  2、 typedef与结构结合使用typedef struct tagMyStruct
{
 int iNum;
 long lLength;
} MyStruct;
  这语句实际上完成两个操作:  1) 定义一个新的结构类型struct tagMyStruct
{
 int iNum;
 long lLength;
};
  分析:tagMyStruct称为"tag",即"标签",实际上是一个临时名字,struct 关键字和tagMyStruct一起,构成了这个结构类型,不论是否有typedef,这个结构都存在。
  我们可以用struct tagMyStruct varName来定义变量,但要注意,使用tagMyStruct varName来定义变量是不对的,因为struct 和tagMyStruct合在一起才能表示一个结构类型。
  2) typedef为这个新的结构起了一个名字,叫MyStruct。typedef struct tagMyStruct MyStruct;
  因此,MyStruct实际上相当于struct tagMyStruct,我们可以使用MyStruct varName来定义变量。
  答案与分析
  C语言当然允许在结构中包含指向它自己的指针,我们可以在建立链表等数据结构的实现上看到无数这样的例子,上述代码的根本问题在于typedef的应用。
   根据我们上面的阐述可以知道:新结构建立的过程中遇到了pNext域的声明,类型是pNode,要知道pNode表示的是类型的新名字,那么在类型本身 还没有建立完成的时候,这个类型的新名字也还不存在,也就是说这个时候编译器根本不认识pNode。  解决这个问题的方法有多种:  1)、 typedef struct tagNode
{
 char *pItem;
 struct tagNode *pNext;
} *pNode;   2)、typedef struct tagNode *pNode;
struct tagNode
{
 char *pItem;
 pNode pNext;
};
  注意:在这个例子中,你用typedef给一个还未完全声明的类型起新名字。C语言编译器支持这种做法。  3)、规范做法:struct tagNode
{
 char *pItem;
 struct tagNode *pNext;
};
typedef struct tagNode *pNode;
 3. typedef & #define的问题  有下面两种定义pStr数据类型的方法,两者有什么不同?哪一种更好一点?typedef char *pStr;
#define pStr char *;
  答案与分析:
  通常讲,typedef要比#define要好,特别是在有指针的场合。请看例子:typedef char *pStr1;
#define pStr2 char *;
pStr1 s1, s2;
pStr2 s3, s4;
   在上述的变量定义中,s1、s2、s3都被定义为char *,而s4则定义成了char,不是我们所预期的指针变量,根本原因就在于#define只是简单的字符串替换而typedef则是为一个类型起新名字。   #define用法例子:#define f(x) x*x
main( )
{
 int a=6,b=2,c;
 c=f(a) / f(b);
 printf("%d \\n",c);
}
  以下程序的输出结果是: 36。
  因为如此原因,在许多C语言编程规范中提到使用#define定义时,如果定义中包含表达式,必须使用括号,则上述定义应该如下定义才对:#define f(x) (x*x)   当然,如果你使用typedef就没有这样的问题。
  4. typedef & #define的另一例  下面的代码中编译器会报一个错误,你知道是哪个语句错了吗?
typedef char * pStr;
char string[4] = "abc";
const char *p1 = string;
const pStr p2 = string;
p1++;
p2++;
  答案与分析:
   是p2++出错了。这个问题再一次提醒我们:typedef和#define不同,它不是简单的文本替换。上述代码中const pStr p2并不等于const char * p2。const pStr p2和const long x本质上没有区别,都是对变量进行只读限制,只不过此处变量p2的数据类型是我们自己定义的而不是系统固有类型而已。因此,const pStr p2的含义是:限定数据类型为char *的变量p2为只读,因此p2++错误。  #define与typedef引申谈
  1) #define宏定义有一个特别的长处:可以使用 #ifdef ,#ifndef等来进行逻辑判断,还可以使用#undef来取消定义。
  2) typedef也有一个特别的长处:它符合范围规则,使用typedef定义的变量类型其作用范围限制在所定义的函数或者文件内(取决于此变量定义的位置),而宏定义则没有这种特性。
  5. typedef & 复杂的变量声明
  在编程实践中,尤其是看别人代码的时候,常常会遇到比较复杂的变量声明,使用typedef作简化自有其价值,比如:
  下面是三个变量的声明,我想使用typdef分别给它们定义一个别名,请问该如何做?>1:int *(*a[5])(int, char*);
>2:void (*b[10]) (void (*)());
>3. doube(*)() (*pa)[9];
  答案与分析:  对复杂变量建立一个类型别名的方法很简单,你只要在传统的变量声明表达式里用类型名替代变量名,然后把关键字typedef加在该语句的开头就行了。>1:int *(*a[5])(int, char*);
//pFun是我们建的一个类型别名
typedef int *(*pFun)(int, char*);
//使用定义的新类型来声明对象,等价于int* (*a[5])(int, char*);
pFun a[5];>2:void (*b[10]) (void (*)());
//首先为上面表达式蓝色部分声明一个新类型
typedef void (*pFunParam)();
//整体声明一个新类型
typedef void (*pFun)(pFunParam);
//使用定义的新类型来声明对象,等价于void (*b[10]) (void (*)());
pFun b[10];>3. doube(*)() (*pa)[9];
//首先为上面表达式蓝色部分声明一个新类型
typedef double(*pFun)();
//整体声明一个新类型
typedef pFun (*pFunParam)[9];
//使用定义的新类型来声明对象,等价于doube(*)() (*pa)[9];
pFunParam pa;
体声明一个新类型
typedef pFun (*pFunParam)[9];
//使用定义的新类型来声明对象,等价于doube(*

2009年5月20日星期三

写在‘六四’ 20周年的纪念

蔡老师好!

随着那特殊日子的临近,越来越多的关于‘六四’ 的话题涌到我的眼前,而我却为了下顿饭在越来越忙。

总感觉要写点什么,或者说留下点什么以供回忆,毕竟自己已经不是个小孩,已经过了无忧无虑的年龄。

很奇怪,最近遇到了3个‘六四’ 人。

一个是您,至今仍在异国,并且平静快乐的生活着

一 个是我的老板,可能和您是同时代的北京大学生,出身高干,从小随父母被下方内蒙,大学时目睹了‘六四’ 的惨烈,曾经发誓与共产党不共戴天,努力离开了这个国家,在外多年,感受颇多,就如同老师笔下那另外一只熊,曾经想申请政治避难来着,后来始终不甘心,最 后还是回国了,从此断绝了政治,当了外企高管。前日宴请我们上海的手下,席间有同事痛陈当局之腐败可恶,中国教育制度之荒谬,扬言必推翻之重来。我一言不 发,我的老板就在席间谈了自己的经历,最后说了‘平衡’二字。从他的角度来看,任何事情都没有简单的解决方式,必须要以平衡来协调。商场之道 也......

还有一位是上海的铁杆‘六四’ ,是我们合作伙伴的副总,只某一面,愤世嫉俗的坐在桌子后,近五十多的相貌,我未与其有过交流,只是事后听熟悉其的同事讲他是个至今“比较顽固的”。

我一直想把自己摆在一个旁观者的角度来看问题,但自己却始终在这个社会存在。五月十二日,我就想写点什么,但是始终没有写。都一年了,我家乡的亲人用中国人那种近乎奴性的忍耐去纪念那些枉死的孩子,我只能说愿那些孩子们在天堂都好!

我现在似乎能体会老师当时说看了余杰的文章心会疼的感觉。最近猫眼不大去了,去牛博的时候更多些了。猫眼似乎有猫扑化的倾向,难道说又要沦陷了?以后要追求自由可能只有依靠翻墙术了。

还 有一件心痛的事,有个友人新婚旅行去了趟甘肃的朗木寺,那边的情况真不可想像,听他的描述我感觉象是到了南美的某个军阀小国。路边的沙袋构筑的碉堡,对所 有人的严格盘查,不许拍照,不许摄像。寺庙里已经没有了喇嘛,据说在3.14以后都被抓了。友人还是趁人不备拍了几张寺庙的照片,从照片看来岂能用凄凉来 形容?一个连和尚都怕的政府,还有什么不怕的呢?

‘六四’ 那天我会穿上白衬衣,晚上我会点上一只蜡烛纪念那些为了自由献出生命的所有人。

-------------------------写在烈女怒杀淫官,富家子飙车人行道撞死路人之后

继续沉默么?还是在适当的时候站出来?


祝蔡老师一切都好!祝‘六四’人都好!

2009年5月19日星期二

天堂对话-----狗日的共产党

话说5月7号,谭卓到了天堂报到,然后就一个人在天堂溜达。心想,这天堂确实很漂亮哈,不错不错,等过几十年老爹老娘也能到这里来吧。
  
   走着走着,碰到了一个学生模样的人和一个老头下棋,他就凑过去看,一看,马加爵?
  
   “你咋能在这呢?”谭卓
  
   “哦,我看他其实情有可原的,受了一辈子欺负,真的很不容易了,那几个有钱的孩子实在是欺人太甚了,我就让加爵把他们收拾了,然后把他带我这了”那老头说“我就是耶稣”
  
   “啊,稣哥!”谭卓说。
  
   “小弟,你咋来的啊?”马加爵问
  
   “啊,我是被撞了的”
  
   “这么不小心啊?”
  
   “不怪我,那车太快了。”
  
   “多快?”
  
   “70迈”
  
   “操,玩我呢?”,上帝听不下去了,“你[****]甩出20多米,飞了5米高,是让70迈的车撞的?你们中国人飙车开70迈啊?咋不去跑百米呢!”
  
   “真的,交警就是这么说的”,谭卓辩解说。
  
   “你再瞎胡扯我把你扔地狱去!”上帝火了“你说话的时候问问自己的良心,我可是上帝,啥都知道的!”
  
   “不信你看”说罢给了上帝一个证明,上帝把牛顿找来了。
  
   牛顿听完之后说:“怎么可能是70迈呢?我用三个定理算的都不是这个数啊!他们能做出这么个结果,肯定是站在巨人的肩膀上的!”
  
   上帝又把阿基米德找来了,阿基米德摇了摇头说“:难道,给他一个手机,他能改变车速?”
  
   上帝又找来霍金,霍金用键盘敲出一行字:“他在被撞的那一秒,收到了亿万光年外黑洞的吸引……”
  
   无奈,上帝把爱因斯坦请来了,爱因斯坦看了看,只是平淡的写了一个公式“:E=mc^2”,上帝问,这不是你的质能公式么?
  
   “错,E代表evil,m代表man,c代表cut。这个公式的意思是,面对这样的邪恶的结果,我恨不得把那个人给砍了”
  
   “那平方呢?”
  
   “再砍一刀”
  
   这时候诺贝尔来了,很淡定的对众多物理学家说,基于中国交警在物理学上的重大发现,我决定为那位交警颁发诺贝尔物理学奖。
  
   上帝彻底疯了,然后走来一个拿烟袋的人“鲁迅,这人对中国比较有研究,问问他”
  
   鲁迅说“70迈本无所谓有,也无所谓无,就像这地上的路,其实地上本没有路,交警多了,也便有了路。”,然后对上帝耳语说,“交警么,都想当婊 子,还想给自己立个贞洁牌坊。你再看看他妈,要么为娼,要么当政协委员”
说着说着,人越聚越多,来了个日本人,岩崎弥太郎(三菱公司创始人),听说日本跑车撞死了人,就过来道歉“听说我们的跑车把您带到了这里,我深感遗憾,跑车开70迈,真是辛苦您了!”一边心里想,跑车开七十迈,那司机得用多大劲踩刹车啊!
  
   傅彪过来接话说:”我说啥来着,开一日本车您都不好意思跟人打招呼。你看人家意大利跑车,怎么也得110起,哎,您还别先快,还不减速……“
  
   高秀敏过来了,心疼得看了看孩子,说:”孩子,别难受啊,70迈把你撞成这样,那是你本山大叔忽悠你呢!“
  
  
  
  
  
   上帝彻底无奈了,问了问:“那人是咋处理的啊?”
  
   “扣了三分”
  
   马加爵在心里盘算着,一条人命三分,我那四条人命就是12分,我每次考一百,扣去12分,还剩88分。
  
   上帝跟马加爵说,你别算了,人家有钱……
  
   马加爵问上帝,那以后他们能上天堂么?
  
   当然不能
  
   那就下地狱么?
  
   也不能
  
   为啥?
  
   他们一个个的全是party员,都是无神论的……
    
   上帝跟谭卓说,孩子,你还有什么牵挂的么?
  
   谭卓说:“嗯,我还有父母,还有我相恋了8年的恋人,我想跟他们说,让他们放心,我很好,天堂里,没有车来车往。”

2009年5月14日星期四

大家來學 LaTeX, latex123

大家來學 LaTeX, latex123

Tex 学习

符號 作用 文稿上使用 LaTeX 的替代指令
\ 下排版命令 $\backslash$ \textbackslash
% 註解 \% NA
# 定義巨集 \# NA
~ 產生一個空白 \~{} \textasciitilde
$ 進入(離開)數學模式 \$ \textdollar
_ 數學模式中產生下標字 \_{} \textunderscore
^ 數學模式中產生上標字 \^{} \textasciicircum
{ 標示命令的作用範圍 \{ \textbraceleft
} 標示命令的作用範圍 \} \textbraceright
< 數學模式中的小於符號 $<$ \textless
> 數學模式中的大於符號 $>$ \textgreater
| OT1 編碼,數學模式中才能正確顯示 $|$ \textbar
& 表格中的分隔符號 \& NA

2009年5月10日星期日

Linux patch的用法转自Isaiah

Linux patch的用法: "也许只是我一个人比较笨,每次碰到bug,虽然有人给出补丁(patch),但是却不知道怎么使用。Manual Page ( man patch )也只给出 patch -p(num) <patchfile这样的用法,具体也不知道怎样确定num,如果你也有这样的疑惑,请继续阅读,下面的内容来自这里
建立patch文件:
diff -Naur olddir newdir > new-patch
- or -
diff -Naur oldfile newfile >new-patch
-p0 还是-p1? patch 命令的目录层次:
-p选项可以选择性地截断patchfile的目录层次。例:如果你的patchfile的头象下面这样:

--- old/modules/pcitable Mon Sep 27 11:03:56 1999
+++ new/modules/pcitable Tue Dec 19 20:05:41 2000

使用 -p0 将从你的当前路径下寻找一个“new'的子文件夹,然后在'new'下面寻找“modules”,然后在其下面寻找'pcitable'。

使用 -p1 将截断第一层目录,也就是说patch将直接在当前路径下寻找'modules',然后是'pcitable'

依次类推。

实际上的确很简单。"

2009年5月9日星期六

u-boot移植到mini2440,u-boot版本2008.10 - 转自hugerat的专栏

u-boot移植到mini2440,u-boot版本2008.10: "这篇文章写于2008.12.28日,主要记录了我移植u-boot-2008.10的过程,并附上了移植好的patch文件。移植好的u-boot-2008.10适用友善公司的mini2440和阳初公司的yc2410。其它的开发板,可能要根据相应的电路配置做稍许修改。我的移植是使用非nand-leagcy方法的,移植好的u-boot-2008.10功能除了基本功能外,加上了yaffs1映像的写入功能,加入了从nand flash启动的功能,改善了一些操作感受,往nand写入数据时,可以显示进度。在使用上要注意的是使用nand wirte.yaffs 命令写入yaffs1映像时,文
件长度参数一定要与yaffs1映像的大小完全一致,否则有可能产生假坏块。我的开发环境是vmware,kubuntu8.04。交叉编译是用crosstool0.43编译生成的arm-linux-gcc 4.1.0,libc 2.3.2。
(本人也成功移植了linux2.6.27.9到mini2440开发板上,有需要源码的,可以和我联系。EMAIL:nanjinrat@sohu.com,映像文件在此下载http://blog.chinaunix.net/u2/75270/showart.php?id=1796658)
一直想自已移植一套u-boot,但因为工作忙,一直都没有做,最近时间比较多,买了一套友善之臂的mini2440开发板,此板电路与该公司之前的QQ2440基本一至。而该开发板自带的u-boot的移植的还不很完善,于是下决心自已移植u-boot。要移植就用最新版的u-boot移植,于是决定在u-boot.2008.10版上进行移植,此版是2008年10月的新版,于之前的版本有较大改动,所以版本号也没有延续以前的编号方式,而改为2008.10。我的移植目的,是要能同时持S3C2440,S3C2410(手中还有一块阳初公司出的S3C2410开发板),从nand flash启动u-boot,因为目前大多数应用都是只有nand flash的,所以没打算从nor flash启动。支持tftp的使用,也就说要移植网卡的驱动,mini2440和阳初的s3c2410自带的linux都是使用yaffs文件系统作为根文件系统的,因此,u-boot还要能支持yaffs映像的烧写。在此我将移植过程记录下来,以方便大家在移植此版u-boot时参考。为了方便整个移植过程中的调试,我把移植过程分为0~6共7个阶段。每个阶段完成时,u-boot都是可以正常运行的,因此,你可以根据自已的要求,决定移植工作做到哪一阶段。为了同时支持S3C2440和S3C2410,我在移植时,同时加入两种代码,使用config_s3c2440,config_s3c2410这样的宏定义来决定编译哪种代码。如果你不需要同时支持两个CPU,你可以只加入一种代码。所有代码不在此列出,大家可以看我上传的移植好的u-boot。我在下面给出针对S3C2440移植的详细说明,S3C2410的移植比较简单,参考2440的移植即可,不另说明了。不同阶段的详细代码可以阅读patch文件。
第0阶段:
本阶段任务,是在u-boot系统中,建立起自已的开发板体系。我先建立mini2440板的体系。方法如下。hugerat是我的网名,你可以根据需要更改。
1 打开u-boot主目录下的makefile,找到smdk2410_config,在其下,仿照它的格式加入如下语句
rat2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t rat2440 hugerat s3c24x0
各项的意思如下:
arm: CPU的架构(ARCH)
arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。
rat2440: 开发板的型号(BOARD),对应于board/hugerat/rat2440目录。
hugerat: 开发者/或经销商(vender)。
s3c24x0: 片上系统(SOC)。
此步是为了加入自已的开发板,非必须也可以在现有的开发板基础上修改。
2修改CROSS_COMPILE为自已的arm gcc编译器,我使用的是系统默认的arm-linux-gcc,故不必再修改相应的CROSS_COMPILE项。
3 在/board子目录中建立自己的开发板rat2440目录由于我在上一步板子的开发者/或经销商(vender)中填了 hugerat ,所以开发板rat2440目录一定要建在/board子目录中的hugerat
目录下 ,否则编译会出错。
然后,将smdk2410目录下的文件考入此目录中。
并将其中的smdk2410.c改名为rat2440.c

还要记得修改自己的开发板rat2440目录下的Makefile文件,不然编译时会出错:
COBJS := rat2440.o flash.o
4 在include/configs/中建立配置头文件
将smdk2410的相应头文件复制一份在相同目录下。并改名为rat2440.h
5 回到u-boot主目录,make rat2440_config,再make,编译生成u-boot.bin成功。
建立S3C410板的方法同上,仅将2440改为2410即可。不重复了。
第0阶段完成。
第1阶段
本版u-boot依然没有提供对S3C2440的支持,因此本阶段任务是加入S3C2440相关的代码,使得u-boot可以在s3c2440上正常工作。但
没有增加任何附加功能。
在下列文件中加入标注为/*by hugerat,phase 1---*/的代码。其中,被注释掉的代码为原代码。
/cpu/arm920t/start.s (加入S3C2440的时钟相关的寄存器定义,加入时钟初始化代码,以使S3C2440工作在405MHz)
board/hugerat/rat2440/lowlevel_init.s(加入S3C2440内存控制寄存器的定义)
board/hugerat/rat2440/rat2440.c (修改GPIO,PLL的设置,应注意GPBCON的设置,不要让蜂鸣器响)
include/configs/rat2440.h(设定环境变量)
以下文件主要加入CONFIG_S3C2440宏定义以使得编译一些S3C2410的代码,和加入led灯的控制。以指示u-boot程序进程。
/inlcude/s3c24x0.h
cpu/arm920t/s3c24x0/interrupts.c(这里还要加入CONFIG_rat2440和CONFIG_rat2410)
/cpu/arm920t/s3c24x0/serial.c
cpu/arm920t/s3c24x0/speed.c
cpu/arm920t/s3c24x0/usb_ohci.c
/cpu/arm920t/s3c24x0/usb.c cpu/arm920t/s3c24x0/i2c.c
drivers/usb/usb_ohci.c
drivers/rtc/s3c24x0_rtc.c
/lib_arm/board.c
编译成功。将u-boot.bin烧入nor-flash即可运行。
但是为方便使用,同时,也是方便u-boot的调试。因此,我要将此u-boot代码再做一修改,使其可以在内存中运行。这样,可以用
开发板自带的vivi将其下载到内存中,再在内存中运行u-boot。要想它在内存中运行,方法很简单,将/root/u-boot-
1.3.1/cpu/arm920t中的start.s中
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
此段代码中的bl cpu_init_crit注释掉,即不进行CPU的初始化工作(此工作,当前在板子上运行的vivi已完成,故不能再次进行)
,即改为
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
@bl cpu_init_crit
#endif
修改/board/hugerat/rat2440/config.mk中text_base 值为0x33000000
使用vivi命令load ram 0x33000000 0x17ea8 x将u-boot.bin装入内存。再用go 0x33000000命令,即可。
至此,第1阶段工作完成。
第2阶段
本阶段任务,是给u-boot移植dm9000的网卡驱动。
u-boot自带网卡驱动,所以只要做些设置即可。
在下列文件中加入标志为/*by hugerat,phase 2----*/的代码.
/include/configs/rat2440.h (加入dm9000定义,加入ping命令定义)
此时,编译通过,但ping时,报`ethaddr' not set错误。
研究原代码,发现#define CONFIG_ETHADDR 08:00:3e:26:0a:5b被注释掉,恢复,并改变原来默认的IP地址。重新编译后,可以
ping通网络了。(也可以在u-boot启动后,修改相关参数,但因为现阶段还没有支持nandflash,参数无法保存,故在此改变较为方
便)
又发现,ping是能ping通了,但报could not establish link(不能建立链接)的错。不影响使用。参考网上的资料,发现这是因为
在网卡驱动中,/home/lijin/u-boot-rat/drivers/net/dm9000.c,有一段程序试图连接网卡的MII接口,而实际上MII接口并未使用
,所以有十秒的等待时间,且报错,将此段程序注释掉即可。
到此,本阶段任务完成。
第3阶段
本阶段任务,移植nand-flash驱动,注意此阶段工作仅是让u-boot可以操作读写nand flash。还不能让它从nand flash启动。
首先,要说明一下CFG_NAND_LEGACY的使用。在u-boot的/drivers/mtd/下有两个目录,分别是nand和nand_legacy。在nand目录下的
是nand的初始化函数和nand的操作读写函数,是使用linux的mtd构架的。此目录下的文件,只有在定义了CFG_CMD_NAND宏和没有定
义CFG_NAND_LEGACY宏的情况下才会被编译。在nand_leagcy目录下的文件也是是实现nand相关操作命令,如read,write等命令的功
能,但不是使用linux的mtd构架。此目录下的文件,只有在定义了CFG_CMD_NAND和定义了CFG_NAND_LEGACY宏的情况下才会定义。此
目录下的文件u-boot组织已不推荐使用。事实上,此版中,S3C2410构架已不支持对nand_leagcy,因此,我在移植中,是用的不定
义CFG_NAND_LEGACY的方式,即非nand_leagcy方式。
在/include/configs/rat2440.h中加标注为by hugerat,phase3的代码段,这段代码是让u-boot启用其自带nand flash驱动,并设置
相应的nand flash参数。
此时,试编译一下,通过。要说明的是,此版的u-boot已自带board_nand_init(),此函数在/cpu/arm920t/s3c24x0/nand.c中实现
。并且此版已不支持定义CFG_NAND_LEGACY,如定义此宏,则编译是会报 #error 'U-Boot legacy NAND support not available
for S3C2410'的错误。故此版已不能使用网上流传非nand_leagcy方式的自加nand flash初始化函数的方法,只能用其自带的初始化
函数
下载到内存中运行,报None nand devices!!!,这是当然的。因为S3C2410和S3C2440在FLASH控制器上,差别较大,必须改写代码。
改写主要在/cpu/arm920t/s3c24x0/nand.c中进行。(此文件内是与芯片紧密相关的代码),一是board_nand_init函数,一是
s3c2410_hwcontrol,参照2440的手册,改写相关代码。还要在此文件的开始部分加入S3C2440 nand flash控制器相关寄存器的定义
。改写的代码标注同上。改写完毕后,u-boot可以识别出nand flash芯片是64MB的,但还不能识别是什么芯片。
在/driver/mtd/nand/nand_base.c中的nand_get_flash_type函数结尾,修改MTDDEBUG语句,改为printf,再编译,可以正常显示芯
片了。但nand write功能不正常,即没报错,实际上也没有写进去。
探讨原因后发现,原来是u-boot自带的nand-flash驱动(不定义nand_leagcy),是基于mtd驱动的。在默认情况下,不进行写入正
确与否的校验。要定义CONFIG_MTD_NAND_VERIFY_WRITE宏才能进行写入校验。关于ECC校验,mtd驱动默认是用sotf_ecc的。加入宏
定义后,u-boot报write error了。
在此我卡了很久,最后才发现是u-boot.2008.10自带的S3C2410的s3c2410_hwcontrol函数有错。在此函数中,把chip->IO_ADDR_W值
改写了,导致在写数据时出现错误。将此错误修正后,nand write正常了。修正方法是使用一全局变量替代chip->IO_ADDR_W。
接下来,在rat2440.h中加入#define CONFIG_ENV_IS_IN_NAND 1注掉原来的#define CONFIG_ENV_IS_IN_FLASH 1,加入
#define CONFIG_ENV_OFFSET 0x30000 注掉原来的#define CFG_ENV_OFFSET 0x30000。编译。saveenv功能也正常了。
至此,nand-flash驱动移植完成。
测试,nand write 0x30000000 0x40000 0x40000时,成功。用nand read也成功读出。此处要说明的,如果用vivi烧写信息到nand
中,再用u-boot读取,会报错,应该是ECC校验不是由同一软件产生所至。
此阶段完成。
第4阶段
本阶段任务是将u-boot改写为从nand-flash启动。
首先,将/cpu/arm920t/start.s中第一阶段中为了从内存中启动而屏蔽掉的语句恢复。加入标注为/*by hugerat,phase 4----*/的
语句,为了兼容S3C2410,同时也加入S3C2410 nand boot 相关代码。同时,在/board/hugerat/rat2440/lower_init.s中,根据开
发板电路,对内存相关的几个寄存器定义进行调整。整个启动代码参考了vivi的代码。因此,将vivi的nand_read.c(支持S3C2440
的vivi,此文件中的读nand函数是直接操作nand flash的,与u-boot自带,适合用于启动时用。)考入/board/hugerat/rat2440目
录下。并修改目录下的makefile,使nand_read.c被编译。
编译,成功,将u-boot烧入nand flash,能成功从nand启动了。
第5阶段
本阶段任务是实现u-boot通过nfs引导友善提供的linux2.6.13的内核。
友善的linux并没有提供make uImage命令,需要添加。将u-boot的tools目录下的mkimage拷到开发机linux系统下的/usr/bin目录下
。在linux的/arch/arm/makefile中和/arch/arm/boot/makefile中,可以找到zImage的项目,仿照它添加uImage项目。
这个问题解决后,就是要用u-boot引导linux内核了,我用的是扬创提供的linux2.6.13的内核,扬创提供的内核,loadaddress和
entry都是30008000,我用u-boot1.2中的bootcmd参数,u-boot1.3.1 bootm却不能引导,报bad magic number,看了bootm的相关资
料,得知,如果我们没用mkimage对内核进行处理的话,那直接把内核下载到0x30008000再运行就行,内核会自解压运行(不过内核
运行需要一个tag来传递参数,而这个tag建议是由bootloader提供的,在u-boot下默认是由bootm命令建立的)。

2)如果使用mkimage生成内核镜像文件的话,会在内核的前头加上了64byte的信息,供建立tag之用。bootm命令会首先判断bootm
xxxx 这个指定的地址xxxx是否与-a指定的加载地址相同。
(1)如果不同的话会从这个地址开始提取出这个64byte的头部,对其进行分析,然后把去掉头部的内核复制到-a指定的load地址中去
运行之
(2)如果相同的话那就让其原封不同的放在那,但-e指定的入口地址会推后64byte,以跳过这64byte的头部。
Bootm在没有参数时,是采用rat2440.h中的#define CFG_LOAD_ADDR 的地址的,而我用bootm就是没有使用参数,所以出错了。正确
的做法应该是用nand read命令将内核从nand flash中读到内存的某一地址中(注意不要与其它已分配的内存冲突),然后再用
bootm 加地址参数,即可引导,也可以在上述的文件中,将CFG_LOAD_ADDR的地址定义为此地址,再用bootm就可以了.
我设定bootcmd环境变量为tftp 0x31000000 uImage; bootm 0x31000000,注意地址不能为0x30008000,否则报错.
做完这此,内核可以引导了,但却停在starting kernel不动了,好在我以前做过vivi+linux2.6.22的移植,知道此问题多半是由于
mach_type不同而造成的。在u-boot中,此mach_type是由rat2440.c中的这段代码定义的
#if defined(CONFIG_S3C2440)
/* arch number of S3C2440 -Board */
//gd->bd->bi_arch_number = 5244 ; //改为和内核的MACH_TYPE一至
gd->bd->bi_arch_number = MACH_TYPE_MINI2440 ;
#endif
你可以直接在这里改数字,也可以在include/asm-arm/mach_types.h的文件中,改MACH_TYPE_S3C2440的数值。将数值改为和内核的
mach_type一至。至于内核的mach_type可以在内核linux源代码下的arch/arm/tools中的mach_types文件查看到。
此时,又发现内核不能通过nfs引导。查资料后得知是因为u-boot没有传递参数给内核。原来是rat2440.h中少定义了几个宏。补上

#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
#define CONFIG_SETUP_MEMORY_TAGS 1
#define CONFIG_INITRD_TAG 1
至此,u-boot已能正常引导linux启动了。第5阶段完成。
第6阶段
本阶段任务,是给u-boot加入烧写yaffs映像文件的功能。
网上有很多文章已经有介绍如何加入此功能,方法也不复杂。但我移植的u-boot.2008.10版,在nand flash的操作上与之前的版本
有了很大的区别。这些文章介绍的方法已不能在此版中应用。于是我只好自已根据u-boot的源代码,yaffs映像文件的格式,自已编
修改了u-boot.2008.10的代码,让它可以实现yaffs的烧写,因为我用的开发板的nand flash是k9f1208,只能使用yaffs1,所以我
的修改代码暂时只能支持yaffs1格式的映像。(要支持yaffs2也不难,但因为无法验证,所以就没有做尝试。)
修改方法如下:
在/common/com_nand.c中do_nand函数中,加入三段/*by hugerat,phase6---*/标注的代码,实现对nand write.yaffs命令的支持。
此代码中,要用到mtd_info结构中的两个变量,这两个变量本来是没有的,所以要在include/linux/mtd/mtd.h的mtd_info结构体定
义中加入。
在/drivers/mtd/nand/nand_util.c的nand_write_skip_bad函数中,两段程序,一段是为了计算正常数据的长度,一段是为了在写
入一段数据后,数据指针能正常跳到下一段数据。
在/drivers/mtd/nand/nand_base.c的nand_write函数中,加入一段把正常数据与oob数据分离的代码,再加入页写时的模式设置为
MTD_OOB_RAW,使页写时,不进行ECC的校验和加入。(ECC的校验在yaffs的oob数据中已自带了,不能重写。)此模式下,写入正常
数据后,会把oob数据缓存的数据写入nand的oob区。
至此,u-boot.2008.10的移植工作全部完成。
最后说明一下,关于阳初2410的移植,因为上面的代码中已加入S3C2410相关代码,移植时,只需参考S3C2440,新建一个开发板体
系,新建时,将rat2440目录下的文件拷贝到rat2410下,将重命名S3C2440.c为S3C2410.c,修改makefile,加上s3c2410.o 去掉
s3c2440.o,拷贝rat2440.h为rat2410.h,将其中的CONFIG_S3C2440注掉,加上CONFIG_S3C2410。在u-boot总目录下的makefile中
rat2440_config下添加
rat2410_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t rat2410 hugerat s3c24x0
因为阳初的板用的是cs8900,因此要在rat2410.h中注掉DM9000的定义,添加CS8900的。
再make rat2410_config,再make,即可。
文章最后,为方便网友,我把patch文件附上。patch文件使用方法是下载u-boot-2008.10.tar.bz2,在这里下载ftp://ftp.denx.de/pub/u-boot/,用tar -xvf u-bot-
2008.19.tar.bz2解压到u-boot-2008.10目录,把u-boot-rat.patch文件拷贝到此目录所在同级目录下。执行patch -p0 < u-boot-
rat.patch。完成后,进u-boot-2008.10目录,执行make rat2440_config,再make即可生成u-boot.bin,如是2410,则执行make
rat2410_config即可,我在mini2440,阳初的2410上试过,功能正常。其它开发板的也可一试。
附patch文件:
可以在此下载全部补丁"

u-boot 1.3.1移植,调试心得 - 转自hugerat的专栏

u-boot 1.3.1移植,调试心得: "u-boot 1.3.1移植,调试心得收藏



公司的项目用的是扬创的2440开发板。此板仅有u-boot.bin提供,而没有u-boot的源码,我依照开发板提供的电路图,根据公司项目的要求,对其电路进行了修改,添加,并重新绘制了印制板,用的是扬创的核心板加自已的底板的构架。硬件调试完毕后,问题来了,我需要在硬件一启动时,就要对某些口线进行初始化,可是因为扬创没有提供U-boot的源码,只好自已动手去移植一套源码了。

移植过程主要是根据网上一名为tekkaman(日本动画,宇宙骑士的主角,看来,此兄是一动漫迷)的高手提供的方法进行的,他不仅提供了方法,还把移植好的u-boot 1.3.1放在网上供人下载,真是要感谢他了。移植过程基本顺利。不过还是有一些问题,我将这此记录下来,以供参考。

移植时,tekkaman提供的代码解压,用其中的文件拷贝到原版的u-boot1.3.1目录中,如提示是否覆盖原文件,选覆盖。按照他的方法,对其进行编译配置,这步顺利完成。然后,编译,我用的是arm-linux 3.4.1,编译报错,又试用了3.3.2,2.95.3,均报错。查了资料,知道这是u-boot的浮点数类型引起,于是自已编译了一新的arm-linux 4.1版,是用crosstool0.43编译的。编译过程很顺利。完了,再用新编译的arm-linux4.1版对u-boot1.3.1编译,顺利通过。因为我的板子上是可以正常运行u-boot1.2的(扬创公司提供的u-boot),为了方便u-boot1.3.1调试,我想将u-boot1.3.1用1.2下载到内存中运行。查了网上的相关资料,试了多次,总算可以在内存中运行了,方法很简单,将/root/u-boot-1.3.1/board/tekkaman/tekkaman2440目录下的u-boot.lds文件中的text_base改为0x33000000,再将/root/u-boot-1.3.1/cpu/arm920t中的start.s中

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

bl cpu_init_crit

#endif

此段代码中的bl cpu_init_crit注释掉,即不进行CPU的初始化工作(此工作,当前在板子上运行的u-boot1.2已完成,故不能再次进行),即改为

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

@bl cpu_init_crit

#endif

在下面一段代码中增加一些语句

#ifdef CONFIG_S3C2440_NAND_BOOT





@ reset NAND

mov r1, #NAND_CTL_BASE

ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )

str r2, [r1, #oNFCONF]

ldr r2, [r1, #oNFCONF]



ldr r2, =( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control

str r2, [r1, #oNFCONT]

ldr r2, [r1, #oNFCONT]



ldr r2, =(0x6) @ RnB Clear

str r2, [r1, #oNFSTAT]

ldr r2, [r1, #oNFSTAT]



mov r2, #0xff @ RESET command

strb r2, [r1, #oNFCMD]



mov r3, #0 @ wait

nand1:

add r3, r3, #0x1

cmp r3, #0xa

blt nand1



nand2:

ldr r2, [r1, #oNFSTAT] @ wait ready

tst r2, #0x4

beq nand2





ldr r2, [r1, #oNFCONT]

orr r2, r2, #0x2 @ Flash Memory Chip Disable

str r2, [r1, #oNFCONT]



@ get read to call C functions (for nand_read())

ldr sp, DW_STACK_START @ setup stack pointer

mov fp, #0 @ no previous frame, so fp=0



//增加的语句

adr r0, _start /* r0 <- current position of code */

ldr r1, _TEXT_BASE /* test if we run from flash or RAM */

cmp r0, r1 /* don't reloc during debug */

beq stack_setup

//////////////////////////////

@ copy U-Boot to RAM

ldr r0, =TEXT_BASE

mov r1, #0x0

mov r2, #0x30000

bl nand_read_ll

tst r0, #0x0

beq ok_nand_read

增加的语句是为判断是否是已在内存中运行u-boot,如是,则不进行下面一段将nand flash中的程序拷贝到内存中的操作(此操作在从nand flash中启动时,是必须的,而在内存中运行时,则不能使用,因为此时,nand flash中不一定是要调试的u-boot代码)

编译。完成后,使用tftp将u-boot.bin下载到板子的内存中,注意,内存地址一定是0x33000000,再用u-boot命令go 0x33000000,即可在内存中运行u-boot。解释一下为什么要这么做,u-boot的启动分两个阶段,第一阶段完成一些必须初始工作,此阶段是汇编写的,第二阶段则是进行一些较高级的操作,比如初始化板上的网卡芯片了,引导内核了什么的,这部分是用C写的。第一阶段的汇编程序在编写时,采用的是代码位置无关的方式,即无论代码的开头放在内存的哪一个地址,都可以从这个位置正常运行程序,而不管编译器在编译时认可的代码起始地址是什么。实际上,前面修改的text_base地址,就是编译器所认为的代码起始地址。U-boot中,第一阶段进入第二阶段是直接转入第二阶段的起始地址,而第二阶段的代码编写是与位置有关的,即代码起始地址必须与编译器认可的起始地址一至,才能正常运行。第二阶段的起始地址在编译完成后,即已确定,是相对于text_base的地址。那么我们将代码下载到text_base指定的地址中时,第二阶段代码的头就是在它应该在的位置上了。当我们从此text_base的地址处运行程序时,没有任何问题。而当此代码是从nand flash中运行时,第一阶段的起始地址为0,但因为第一阶段代码是位置无关,所以第一阶段代码可以正常运行,但第二阶段代码的头却不在它应该在的位置了,所以,第二阶段不能正常运行,因为,在第一阶段中,必须将u-boot自身拷贝到text_base的地址处,这样,第二阶段的代码就在它应该在的位置了,此时,第一阶段的程序可以顺利跳转到第二阶段运行了。这个过程,是我看了很资料后总结出来的。

完成此工作后,即可以在内存中运行u-boot了,但因为tekkaman的程序中,用的网卡芯片是DM9000,我用的是CS8900,所以要在tekkaman.h中,将DM9000的宏注释掉,将CS8900的宏开放。在此我犯了个错误,因为我一开始没有修改此处的宏编译的程序,而我在修改过宏以后,没有执行make clean就直接make,结果,网卡不能正常工作,总是报告cs8900 not found,试了多次不能解决,耽搁了一些时间。后来,在make clean后,再make,想不到问题解决了,想来是有些与cs8900想关的文件在修改过宏后没有重新编译所置。真是无语了。

这个问题解决后,就是要用u-boot引导linux内核了,我用的是扬创提供的linux2.6.13的内核,扬创提供的内核,loadaddress和entry都是30008000,我用u-boot1.2中的bootcmd参数,u-boot1.3.1 bootm却不能引导,报bad magic number,看了bootm的相关资料,得知,如果我们没用mkimage对内核进行处理的话,那直接把内核下载到0x30008000再运行就行,内核会自解压运行(不过内核运行需要一个tag来传递参数,而这个tag建议是由bootloader提供的,在u-boot下默认是由bootm命令建立的)。

2)如果使用mkimage生成内核镜像文件的话,会在内核的前头加上了64byte的信息,供建立tag之用。bootm命令会首先判断bootm xxxx 这个指定的地址xxxx是否与-a指定的加载地址相同。
(1)如果不同的话会从这个地址开始提取出这个64byte的头部,对其进行分析,然后把去掉头部的内核复制到-a指定的load地址中去运行之
(2)如果相同的话那就让其原封不同的放在那,但-e指定的入口地址会推后64byte,以跳过这64byte的头部。

Bootm在没有参数时,是采用tekkaman.h中的#define CFG_LOAD_ADDR 的地址的,而我用bootm就是没有使用参数,所以出错了。正确的做法应该是用nand read命令将内核从nand flash中读到内存的某一地址中(注意不要与其它已分配的内存冲突),然后再用bootm 加地址参数,即可引导,也可以在上述的文件中,将CFG_LOAD_ADDR的地址定义为此地址,再用bootm就可以了,我最终就是这么用的。

做完这此,内核可以引导了,但却停在starting kernel不动了,好在我以前做过vivi+linux2.6.22的移植,知道此问题多半是由于mach_type不同而造成的。在u-boot中,此mach_type是由tekkaman.c中的这段代码定义的

#if defined(CONFIG_S3C2440)

/* arch number of S3C2440 -Board */

gd->bd->bi_arch_number = 5244 ; //改为和内核的MACH_TYPE一至

//gd->bd->bi_arch_number = MACH_TYPE_S3C2440 ;

#endif

你可以象我一样直接在这里改数字,也可以在include/asm-arm/mach_types.h的文件中,改MACH_TYPE_S3C2440的数值。将数值改为和内核的mach_type一至。至于内核的mach_type可以在内核linux源代码下的arch/arm/tools中的mach_types文件查看到。

重新编译下载u-boot1.3.1后,内核正常引导了。到此,u-boot1.3.1的移植告一段落。下面,我要做的是移植yaffs,使u-boot1.3.1可以支持yaffs文件的烧写。"

U-boat Watches

U-Boat Watches

Authorized Luxury & Fine Swiss Watches | QUESTIONS (866) 909-8463

Click on the watches below for larger images and more complete descriptions.
U-Boat F-50-CAR-BKGR
U-Boat F-50-CAR-BKGR
U-Boat Flightdeck Mechanical 50mm with Black/Green Dial
Retail Price: $3,050.00

U-Boat C-53-CAR-CF
U-Boat C-53-CAR-CF
U-Boat Classico Automatic 53mm with Carbon Fiber Dial
Retail Price: $2,800.00

U-Boat FC-50-ST-BEBK
U-Boat FC-50-ST-BEBK
U-Boat Flightdeck Automatic Chronograph 50mm
Retail Price: $4,400.00

U-Boat FC-55-CAR-BKWH
U-Boat FC-55-CAR-BKWH
U-Boat Flightdeck Automatic Chronograph 55mm with Carbon Finish
Retail Price: $4,250.00

U-Boat C-53-ST-BK
U-Boat C-53-ST-BK
U-Boat Classico Automatic 53mm with Black Dial
Retail Price: $2,000.00

U-Boat C-45-ST-BE
U-Boat C-45-ST-BE
U-Boat Classico Automatic 45mm with Beige Dial
Retail Price: $1,800.00

U-Boat FC-50-TIT-BKWH
U-Boat FC-50-TIT-BKWH
U-Boat Flightdeck Automatic Chronograph 50mm Titanium
Retail Price: $5,850.00

U-Boat TOF-50-CAR-BK-BG
U-Boat TOF-50-CAR-BK-BG
U-Boat Thousands Of Feet BC Automatic Chronograph 50mm, Carbon Finish with Black Glass
Retail Price: $4,800.00

U-Boat FC-50-CAS-BEBW
U-Boat FC-50-CAS-BEBW
U-Boat Flightdeck Automatic Chronograph 50mm
Retail Price: $4,400.00

U-Boat FC-55-CAR-BKYL
U-Boat FC-55-CAR-BKYL
U-Boat Flightdeck Automatic Chronograph 55mm with Carbon Finish
Retail Price: $4,250.00

U-Boat FC-50-CAR-BKWH
U-Boat FC-50-CAR-BKWH
U-Boat Flightdeck Automatic Chronograph 50mm with Carbon Finish
Retail Price: $3,850.00

U-Boat FC-43-CAR-BKOR
U-Boat FC-43-CAR-BKOR
U-Boat Flightdeck Automatic Chronograph 43mm with Carbon Finish
Retail Price: $3,550.00

U-Boat FC-43-CAR-BKWH
U-Boat FC-43-CAR-BKWH
U-Boat Flightdeck CAB3 Automatic Chronograph 43mm with Carbon Finish
Retail Price: $3,550.00

U-Boat FC-50-ST-BKYL
U-Boat FC-50-ST-BKYL
U-Boat Flightdeck Automatic Chronograph 50mm
Retail Price: $3,400.00

U-Boat FC-50-ST-BKWH
U-Boat FC-50-ST-BKWH
U-Boat Flightdeck Automatic Chronograph 50mm
Retail Price: $3,400.00

U-Boat FC-50-ST-BKOR
U-Boat FC-50-ST-BKOR
U-Boat Flightdeck Automatic Chronograph 50mm
Retail Price: $3,400.00

U-Boat FC-43-ST-BKWH
U-Boat FC-43-ST-BKWH
U-Boat Flightdeck Automatic Chronograph 43mm
Retail Price: $3,350.00

U-Boat F-50-ST-BKGR
U-Boat F-50-ST-BKGR
U-Boat Flightdeck Mechanical 50mm with Black/Green Dial
Retail Price: $2,550.00


Search eWatches.com
Luxury & Fine Swiss Watches

Features & Complications

Zenith
Ebel
Corum