TA的每日心情 | 怒 2019-11-20 15:22 |
|---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
开发板:TQ2440
+ W" a+ n% U% S) }7 V! [0 a
% j* G7 I" e6 p1 K c) ` f4 t内核:Linux 2.6.32" I- d* U$ B7 v E. ^" D9 i* C
9 d4 K+ J- }; E2 `
PC OS:Ubuntu 11.043 l* c" q5 ]: w- _- {6 H
* s" E3 x# m( R7 n8 h& a
6 J( k% u" A0 o/ {3 K% F" n" Z+ r
3 |; q$ i6 j; c) B0 y5 k0 O, P$ i+ T 本文将对NAND驱动的移植进行简单介绍。其中,将对NAND控制器所需要的参数进行详细说明。: Q" q( b* m' C
) d$ P% H* P. L }2 u" J
1. 修改分区表
/ Z& w: h6 b; g' ?6 Y f o9 X" [& G& v' Y) ~
打开文件arch/ARM/plat-s3c24xx/common-smdk.c,修改mtd_partition结构体数组。
$ c& u+ k, _: P! [7 f2 {. m: _
6 j) k" A- E* A4 S' r8 {+ ?& x' L修改后如下:
0 `; S+ @# {# ~) G6 v% J3 ^/ \- F3 N' Y
static struct mtd_partition smdk_default_nand_part[] = {
9 g9 v1 C! ]3 c. t [0] = {
; ], `# ]7 T7 ?( t* I6 r# O .name = "Uboot",
5 E6 T, X$ C2 ^& e# C1 A8 @ .size = 0x00040000,
' t, G6 J3 F. B7 | .offset = 0x00000000,
8 _; z8 n& t& Y0 b8 e) y3 I },
9 K5 k" S, g0 u9 _5 \ l [1] = {( f Q& v! N* j$ l
.name = "Kernel",
3 Z0 \# L5 k N' R( R- @ .offset = 0x00200000,
! [( v# k. K- K% b .size = 0x00300000,
2 G7 W) r& Y) F% e0 D },
' \& f2 A& m5 s( t [2] = {7 a4 C1 K; o. R% }3 v+ B# p
.name = "filesystem",' e0 d" Q% x% M( F; x4 B; z- R' u. H
.offset = 0x00500000,( M. U# F) t1 X2 n2 G" E0 C; \
.size = MTDPART_SIZ_FULL,
2 X# W5 [" N! x }7 `. k5 _; P- Z- |9 A5 Z* a( M
};' m3 S" u" l4 N9 h. V4 n; ?4 o
7 X3 ?7 @, q* h1 D" e# h$ _, O1 H8 C Z* Y
TQ2440板上的NAND为256M,请根据你的NAND实际大小分配空间。% q: Z4 z; N$ _. x
6 {; h+ ?" F+ ^$ Y# D# ]' J0 K0 K$ k
) U$ p* e9 ~! u0 q: f
+ l9 c! E8 V9 H) M y
2. 修改NAND控制器参数
) [. z8 T! t! \3 D' Y
' H$ t; Y/ }& d {打开文件arch/arm/plat-s3c24xx/common-smdk.c,修改smdk_nand_info结构体。 K) i4 W N& N
+ [ T5 A; I: d1 _* k" P
修改后如下:' u9 ?6 I3 }& P/ J' \3 I1 X& r& T
' [; X$ v& _" K& h
static struct s3c2410_platform_nand smdk_nand_info = {8 \ h5 J* J8 j: d1 }
.tacls = 0, //10,//20,
7 G/ \$ I& C" F* T2 S .twrph0 = 21, //25,//60,
8 Y6 H+ J) k5 X0 n$ L; g$ ~4 U .twrph1 = 5, //10,//20,
2 W9 O$ ]$ u# E- l3 U .nr_sets = ARRAY_SIZE(smdk_nand_sets),
8 K+ b o8 b4 d* b$ _, Y0 k7 K6 P! @ .sets = smdk_nand_sets," ], B( u1 J% W6 S- m+ }6 ]6 R; _
};9 ?: \; V; V. [
$ E2 Z" {1 @! [
这里的三个参数tacls,twrph0,和twrph1是如何给出的? 我们来分析下。1 f: s; D& m" O2 h& u0 y2 B
) z7 J& {, B2 p+ k5 H7 F) x, i o先看下这个结构体的定义,位于arch/arm/mach-s3c2410/include/mach/nand.h:
* ^$ ^' }$ w% x& L7 i d1 N. J* @3 N) S: X
struct s3c2410_platform_nand {: E& w1 W) v9 T& f4 l8 K
/* timing information for controller, all times in nanoseconds */
8 o5 N. Q0 x& Y- |' D/ R1 D4 A/ \! |" P; V% L0 _: M
int tacls; /* time for active CLE/ALE to nWE/nOE */
# k; ~4 G k4 R int twrph0; /* active time for nWE/nOE */0 P. Y# R' q$ o# N: a& l, U
int twrph1; /* time for release CLE/ALE from nWE/nOE inactive */! } X$ d% p2 `$ I: j
2 E/ t& n* Q B) u" D$ Q R; a3 D unsigned int ignore_unset_ecc:1;
; p* q, K8 J/ Q7 v# H# f
- e' |0 X4 i$ V1 { w; M int nr_sets;
, T* \; @) k# i3 `2 e% d struct s3c2410_nand_set *sets;
- v, M! {5 F' X' O, @" T& {/ P1 k" v& _9 P/ N8 g
void (*select_chip)(struct s3c2410_nand_set *,4 @; M+ l/ W, h: G# M% ?0 S
int chip);
0 g3 X! R7 H) o3 h& Z};
/ w6 F/ X* r% W! b: b% W8 P; Y
/ g* A9 x( O, i看到了对这三个参数的说明,这里提到了这三个参数的单位为纳秒,请注意。
) k7 R$ K: ~( }" L9 u J
8 H; E1 T& x( N2 q1 m; e. V3 o那么这三个参数到底从哪来的呢? 它来自于S3C2440 nand 控制器的NFCONF控制器,如下:8 `1 D! t0 r% M
" K' J8 a9 _2 b9 l) F5 Z& L/ p& P
" t- j6 G& ]9 L4 B4 ? f
6 h1 ?8 c' X7 m2 d; x8 o
4 W8 I) e9 j% t C9 U) u2 Q
! G9 T0 f1 ~! g5 ]) G! r3 u& i: v 既然找到这三个参数的出处了,那么它们究竟是何含义呢?我们里看下:
! O. g, C' b* N0 _) L' a! b4 O8 W: o/ F/ n( U3 V* r3 ~
) } z" B8 K6 d2 S4 Y; q$ d- c/ s, z# k- B8 A( O. p7 p4 t
( S* G ^- e* u' Q& U
& {4 O. E: s7 g. `, h这幅时序图同样来自S3C2440的datasheet。% t. \2 w( b# h9 Y. R m) c/ L
' N8 V) r: n8 N8 p4 X5 D! r4 {通过这幅图和struct s3c2410_platform_nand中的注释,我们可以对这3个参数做出如下定义。
3 L+ Q5 @ S0 P6 |$ q9 p! e- N0 e# t5 g* I( d
TACLS:表示在CLE/ALE拉高后,多少时间以后才允许将nWE拉低。
* E& f. E& T4 ?1 h @7 O4 t Y N* u% u! y+ U
TWRPH0:表示nWE低电平持续的时间。
7 P. k$ b i9 d: }- ` p( j. r
, C6 i! }' O1 R/ \TWRPH1:表示nWE变为高电平后,多少时间后允许CLE/ALE拉低。
. z& H$ ^% T1 W4 s8 t5 F, M
' L; O( G: D) ^0 E8 E知道参数的意义后,我们来看下NAND芯片K9F1208U0C的datasheet来确定这3个参数的值。' A r) r8 R1 q" t1 }1 D- f
6 g. ^6 G2 f, M6 d% C: Q" J; d
: B) d$ K, v% O# J( Y; r p- G$ Q
4 O: T6 r6 w6 A5 P
" k$ A2 }+ P. W0 V
" [9 W9 ^0 k* d+ k) v从这个时序图,我们可以直观地看到twp对应着参数twrph0,而tclh对于着参数twrph1。* \' J2 S' f- w3 A$ v I
# r2 O$ A: t. V `" {
但是tacls如何得出呢?从图中并不能直接得出该参数的值,需要转个弯,那就是将tcls减去twp,就可以得到tacls了。
) Q" m6 z' i) a- D( Z% G' |
0 v7 M" ~4 Y F+ b$ p! G综上所述,为了得到nand控制器所需的3个参数,我们需要获得该nand芯片的3个时序参数:twp,tcls和tclh。
5 @! w: @- ^ X7 C* y7 U; a* T/ ?# b2 p# P2 s$ T
通过查找该nand的datasheet,3个时序参数的值如下:
; c/ D: C& `4 ~- }9 t. A( Y! r& m: A
twp=21, tcls=21, tclh=5。$ h: O$ v) y. ?: C: L/ l
+ J* [* t& }2 U
将这3个时序参数转为我们需要的3个参数,单位为纳秒(ns):
) V' K& c$ \1 r; m! z8 v5 `$ ~0 f9 j# q" }
tacls = tcls-twp = 21 - 21 = 0 ns0 b# D# e/ F! E2 c+ [
- O. y$ M7 \- C' Y3 W2 w
twrph0= twp = 21 ns c( @6 ^- p7 L7 [
% e8 R2 ^, q3 a0 F6 Y& Btwrph1 = tclh = 5 ns" o0 j: T1 b8 R0 y# x
6 N# X, C5 ?4 f& S
至此,就成功计算出三个参数的值了 。
8 c9 V& F* c7 D0 B; {) g4 M: O, W- o8 V2 g( q! T( t+ O' O
3. 配置内核/ Z8 y. g% [. B& {- w0 q: p
) r% _( z+ L# T' _
3 ~- P' X6 w. n. ]6 h3 h1 h
2 f) Z( X& M6 B8 n* ` |, s/ c; h. @: q# x
+ r2 P' ]& P+ v6 K+ f9 s2 p4. 验证( Q0 x0 z" \% ~( @! R6 O: {
8 u4 X/ q( R$ K3 D" R5 L4 X 在经过上述步骤后,编译内核并将内核少入nand,启动系统。在Linux的启动信息中,会有如下输出:
2 U: ?- w/ ?/ M7 F. l* Z3 L, L+ X
" R% B& `' \6 h* G8 B F v" Z......' _9 G5 [0 `# k0 s: f8 ]
[( N( K7 I+ G' i! MS3C24XX NAND Driver, (c) 2004 Simtec Electronics
: c* M% \: u) {% r% q1 }( `s3c24xx-nand s3c2440-nand: Tacls=1, 10ns Twrph0=3 30ns, Twrph1=1 10ns
- P3 Q) I' P, |% ^, \0 x+ r Hs3c24xx-nand s3c2440-nand: NAND hardware ECC
7 g. r, C6 n9 }( Q4 ], _5 ^NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
. A# ~, x1 h* C& eScanning device for bad blocks0 T- S/ ~+ ?- Z# c
Bad eraseblock 781 at 0x0000061a0000
4 z* d* M; [7 T8 ^9 S2 XBad eraseblock 1113 at 0x000008b20000" |0 [( Y' X: [0 X
Bad eraseblock 1117 at 0x000008ba00002 Z9 y( h9 Z4 S v1 ^* e
Bad eraseblock 1481 at 0x00000b9200005 l% y2 ?* M! v% M, i5 L( f
Bad eraseblock 1566 at 0x00000c3c0000
* G; I# q4 e. }2 m+ K9 e- t" {Bad eraseblock 1885 at 0x00000eba0000
" g6 T# \% O$ J, Z+ G" e( J! V) ICreating 3 MTD partitions on "NAND 256MiB 3,3V 8-bit":
5 m% f. i6 ]- G" g0x000000000000-0x000000040000 : "Uboot"
( w; |! K+ q' m& u3 a! G0x000000200000-0x000000500000 : "Kernel"
7 ^* \$ E, Z% S+ k0x000000500000-0x000010000000 : "filesystem" \: n$ N8 v( q# O' g7 w! a
8 V { h0 P; z* y
......7 @" q o$ _6 s: F
4 `" t$ J3 f4 r% i
上述信息表明以成功访问了NAND FLASH。
1 }8 D. l0 D t8 K9 F7 p
9 M2 I2 ~& j8 N( |" f. D这里,对第二行的输出进行个说明。2 }/ g7 r+ L+ d. ]: r
E, H! A' k: l! L4 `% b: C8 \UBOOT启动将S3C2440的工作频率 FCLK:HCLK: PCLK = 8:4 :1,
p$ w0 l# _' T" B9 F( v r$ Z0 p/ q4 j P7 ]/ L$ E
而FCLK为400Mhz,那么HCLK为100Mhz,根据NFCONF寄存器的说明,寄存器中的这3个参数都跟HCLK有关,必须为1/HCLK的倍数,# I. @( ^( F) \4 E% {# Q5 M1 f
! `* S' C1 l1 |也就是1/100MHz=10ns的倍数。
- h3 }# Z5 \: U% H! X. j- J/ @- u/ x* l' z7 s" |) z
通过上面第二行的输出信息,Twrph0为 30ns而Twrph1为10ns,这是显而意见的。5 I. ~& N2 _. p( {- o
6 ]. U7 O r/ S) f) U由于参数必须为10ns的倍数,而且必须大于datasheet给出的值,因此向上取到10的倍数,也即5ns取到10ns,21ns取到30ns。3 @* T7 W) ~1 A z7 j4 g/ C7 M
: T0 J) k% I2 o4 c' {" C h5 }那么为什么Tacls是10ns呢?明明给出的是0ns,是不是驱动不允许参数为0ns?& u- R1 r, K4 m% n a* |0 [/ C
( h5 L- A5 m, k
在S3C2440的nand驱动中,参数的值是通过如下函数确定的:
! A. n. \, t, b: \( H% E
( f: d' g$ u3 ~static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
% s, k4 F. y2 z3 F# @5 m' `{, ]& p$ m/ J% }, t/ q
int result;
. U$ I5 ~. [) Z9 s% A8 j3 h: V1 w' ]- y
result = DIV_ROUND_UP((wanted * clk), NS_IN_KHZ);
# N% t/ U D- @3 g0 O. W% s! I1 H4 x& T& J O" G( S8 ?
pr_debug("result %d from %ld, %d\n", result, clk, wanted);$ ?) w1 W; @2 R* K4 q) g0 c
5 E- H/ L5 S) }% [- Z7 g7 n
if (result > max) {
* Y6 v% t. o+ c/ h- ^ printk("%d ns is too big for current clock rate %ld\n", wanted, clk);; s$ F! ^- Z/ |, z
return -1;
, _7 c' j; \9 |) ^) v4 c }
" g" G- Z. a, E
+ b( v" E6 E& e a% d% U1 g' X2 Q2 V if (result < 1)
9 Z% ]6 _# \1 `! A9 g; y result = 1;
; Q- z3 J; o A9 G( o- g9 R/ g/ |1 r( U! a* c H' ?0 E
return result;
- H$ {7 M" K% Z}- T! p, N O4 n: m: ]2 L8 ]. b
% v! }$ H5 f7 f2 d! @& { n
参数wanted就是0(ns),而clk即为HCLK/1000。( c/ M1 z2 Z4 W# x1 s, B
7 Y; T7 T& G. eDIV_ROUND_UP宏将返回0,但是if对result进行了限制,也就是不允许小于0,因此将参数值设置为1,并返回给调用函数。6 A3 ?1 s' L( |, R
]& c( p" [9 T; K9 q. U* \
$ _, ~& n: ~" f5 y4 l; ?
6 l( s9 t1 m# R4 |
3 U C5 _" p: B( [7 Y" p
/ H4 h0 ?0 d" U& O. K% o; v5 j7 n! z) p% _2 |
) q9 o$ Y8 a( ^6 @4 S
( B; n* l7 J9 k: l$ P. @: d, f
" Y; ]+ A! a0 c$ {) W. [ |
|