TA的每日心情 | 怒 2019-11-20 15:22 |
|---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
开发板:TQ24408 L, Y& A8 g- ^2 {5 A
; t Z* Y; a/ x, A Z内核:Linux 2.6.32
) @) y2 p+ b" K8 p6 |; G* |9 V: ~5 A; f1 q' e7 F& U/ M; B+ I2 ?
PC OS:Ubuntu 11.04
3 S% J) H4 u3 z% q5 b! d8 Q* B% I6 n. L6 Z1 w
/ |* L# ?& {- G$ q
0 I3 g: Z+ [$ v3 g0 B# d! m2 f9 W 本文将对NAND驱动的移植进行简单介绍。其中,将对NAND控制器所需要的参数进行详细说明。
9 O: a0 K9 \9 p; `
1 h& {/ h) B% l. o5 O1. 修改分区表
/ j; I8 c- j C- J
0 k- ~1 ^; ~# u7 T- x7 Q( g打开文件arch/ARM/plat-s3c24xx/common-smdk.c,修改mtd_partition结构体数组。. g* w: T) D# L: I$ h5 k
& c5 `+ M5 A5 |0 h0 g& Z2 R修改后如下:* x+ K0 S2 j3 Z: i* \* }( Q! H
' t# f+ \ E! {+ R$ q
static struct mtd_partition smdk_default_nand_part[] = {
- G G, d# j* z7 Q8 y: R9 |2 ~ [0] = {
+ w6 V2 Y4 ~8 m9 J .name = "Uboot",8 s" Z7 F3 F: }9 m) q
.size = 0x00040000,$ n% {7 h. S9 m8 L. `4 i
.offset = 0x00000000,
& h: F: _8 b4 {4 s1 w },
1 ?0 n/ }( o+ r4 b" F, D [1] = {
0 r# A; Q; Q) o# l1 L+ q .name = "Kernel",. ]# j* C! C7 X: M3 f; _$ U; K
.offset = 0x00200000,! f* g, ?+ P5 S8 d
.size = 0x00300000,
3 U3 b- L6 E! s W },- F+ Z0 J- y0 u. C/ O2 k, N# T# {
[2] = {3 C! I' }: Y. G
.name = "filesystem",
2 S$ G4 o; \& a# k0 P .offset = 0x00500000,; I9 N5 X3 W1 P0 x' T2 j
.size = MTDPART_SIZ_FULL,6 M& \0 J) N8 a7 Z c# z
}1 y' h5 }* W& i8 x6 [6 k7 _
};; s/ g, |+ i+ u# ?# }
- U- c, U0 f) n, n! ]
4 B+ I- o3 K0 }; aTQ2440板上的NAND为256M,请根据你的NAND实际大小分配空间。! r; f2 x9 |# J- f1 |
1 X" V$ M0 y4 L, R) M; |4 f. ]
; Q' R+ I6 e# W& C1 F0 C- h4 w
( F+ z2 X" L0 x$ N; _3 C2. 修改NAND控制器参数9 |/ z: X6 k3 ^, w
' K) e* u1 |7 b
打开文件arch/arm/plat-s3c24xx/common-smdk.c,修改smdk_nand_info结构体。
2 h6 j; H/ @7 \% m, h
7 ]& ^! n J2 \' H5 w; e: a9 [修改后如下:
" c' t! r4 x/ o2 t
( ?3 u- l& ]% ~# M# g; \% o3 Ostatic struct s3c2410_platform_nand smdk_nand_info = {. p3 k8 D& p+ I- c, A! k5 R5 c# D
.tacls = 0, //10,//20,
) c% v; [/ H7 D .twrph0 = 21, //25,//60,. O# k8 u: ]% q( }6 g
.twrph1 = 5, //10,//20,- K2 w3 W: S: v$ }) ?9 g, B% z
.nr_sets = ARRAY_SIZE(smdk_nand_sets),# p+ U, [0 t6 J$ i
.sets = smdk_nand_sets,: W2 H% N0 |$ s: Y2 z* ?
};
2 `, y$ O/ z. u2 }: B
7 A4 g8 B" \1 e6 n9 A4 ]7 ]# x6 x这里的三个参数tacls,twrph0,和twrph1是如何给出的? 我们来分析下。
, x- w" V7 ~+ h6 q% M* I
( @2 s" p2 q. s- z! ?2 }先看下这个结构体的定义,位于arch/arm/mach-s3c2410/include/mach/nand.h:( {2 [# o9 Y) t8 |3 l% h
; [! ]: x* i) ^% l
struct s3c2410_platform_nand {
5 G8 b% e. I7 s2 a! m: D+ c9 T S /* timing information for controller, all times in nanoseconds */
: o8 o+ y7 F5 v3 U3 k
4 |2 l3 h" I7 g$ Y. Y int tacls; /* time for active CLE/ALE to nWE/nOE */
) a* v; f; l& l5 U& F3 |" J7 K: X int twrph0; /* active time for nWE/nOE */3 A6 e* ]& A' Q" S
int twrph1; /* time for release CLE/ALE from nWE/nOE inactive */
6 G. h8 g0 f/ D, H k4 J7 l: ? a9 Z! \$ Z! T
unsigned int ignore_unset_ecc:1;
1 Y* S% J8 Z8 g0 F$ B# F. e8 ?- S+ l
% d, [- r8 n; f% ^7 W( r int nr_sets;# T9 q$ T$ D8 o7 n
struct s3c2410_nand_set *sets;4 b" e! }# [/ K% E. F
n0 j+ L& u: v' w( A
void (*select_chip)(struct s3c2410_nand_set *,
( _$ s3 q+ k* B& D9 R0 ^( g( m2 W int chip);% J4 }2 _2 H( j+ E- h$ I" X5 ?3 {1 C
};
/ b- j# m/ k/ ]5 Z$ Q: t; v7 g) B( @
6 f/ p) Y$ C& ?) D( h; }看到了对这三个参数的说明,这里提到了这三个参数的单位为纳秒,请注意。
$ {, B S& s; z* i$ U) ~/ G' S! e( }8 ^# W: m
那么这三个参数到底从哪来的呢? 它来自于S3C2440 nand 控制器的NFCONF控制器,如下:& O& N4 L$ @! V
* f+ p6 Q8 b% C" v
3 N5 _2 J1 U/ }% K) |, Q: x- T; D+ t9 e
9 J' z- m- [& s# G( ~
0 b: V" P4 ~: R: O
' l7 y3 T5 x6 W 既然找到这三个参数的出处了,那么它们究竟是何含义呢?我们里看下:
G) k! F- Q' }) o3 q. |4 t. U6 X' I. `+ H t! g
2 A: i: p4 U, n! C$ q( V! C
/ U# F! C7 K1 I* f
& e/ _: @- U% M
6 }! z" e: Y+ T9 d0 Y这幅时序图同样来自S3C2440的datasheet。+ k$ E+ j2 B, P0 k& @% S
; ?- A2 T: X4 a: ]3 o0 e" Q8 i通过这幅图和struct s3c2410_platform_nand中的注释,我们可以对这3个参数做出如下定义。
' Y2 ~9 I& m6 z9 Z7 i4 x
1 n4 k+ c+ J; T' c# c1 i. S( KTACLS:表示在CLE/ALE拉高后,多少时间以后才允许将nWE拉低。
: {+ [7 z: y: v( q! y! ^5 {$ |2 f. ~# b
TWRPH0:表示nWE低电平持续的时间。7 N5 R2 a" I) C
+ t2 ?; \ w! D( O% OTWRPH1:表示nWE变为高电平后,多少时间后允许CLE/ALE拉低。# y* R3 u& ^7 {, e2 P
z( j# A; k v2 p4 N
知道参数的意义后,我们来看下NAND芯片K9F1208U0C的datasheet来确定这3个参数的值。; T; e8 q8 |4 l% J) ~: y N0 A
& ]+ n* v2 O: H+ j$ ^' x
6 L" ]4 p) c6 X4 o
% z( m# j1 ~2 D" b! ^3 \
" v8 K& e+ |& \) {1 s8 O: G# [( G6 a1 _! l
从这个时序图,我们可以直观地看到twp对应着参数twrph0,而tclh对于着参数twrph1。
4 ~: a, M, y2 d3 Q/ e9 ^( {, \
N$ J T9 r6 q% y. A但是tacls如何得出呢?从图中并不能直接得出该参数的值,需要转个弯,那就是将tcls减去twp,就可以得到tacls了。
+ B( n% ^1 K! s# k) n9 S9 n7 w9 J' U+ T1 l
综上所述,为了得到nand控制器所需的3个参数,我们需要获得该nand芯片的3个时序参数:twp,tcls和tclh。
- x' d: W; Z* i: @
/ e. G2 B/ Y. _1 {通过查找该nand的datasheet,3个时序参数的值如下:- g( W3 q. v1 g% O8 m5 ^/ k
' Q2 f8 U/ W9 H3 o' n: R: htwp=21, tcls=21, tclh=5。1 ?3 q! E6 x- N; e% g# E
; y" D2 I6 {+ L% u9 W! T" |
将这3个时序参数转为我们需要的3个参数,单位为纳秒(ns):6 _3 s; t: M+ q. M% J' j2 C
" r' f; l( e& Q; y$ U" h% s' K9 p* [
tacls = tcls-twp = 21 - 21 = 0 ns5 m+ Y) K3 o4 z1 x
! P6 Q: z: H, P5 y$ R
twrph0= twp = 21 ns! G0 t c+ y1 l, U
) y. E2 w" z9 q, v) [. u
twrph1 = tclh = 5 ns4 g2 R% m; Y6 Q) p( K/ l
& T9 M5 r% c8 P5 C4 j8 b" _至此,就成功计算出三个参数的值了 。$ D: h- ?' Q. c8 ^/ [8 ^
9 V- X0 p7 m- ~8 o) f( X3 n$ ^
3. 配置内核6 u I1 q- D' {( `5 G. C3 O
% ^( W) @7 S1 H8 b0 r, \
/ }7 G- z! o$ q; U. ]0 H# [3 c
/ _! _+ d _8 A+ k( u! m$ L+ Z! g7 ]) P& r: P
9 P" D1 e: a: p4. 验证
& |) T; F+ D) M) u
& I! G9 K: L9 T 在经过上述步骤后,编译内核并将内核少入nand,启动系统。在Linux的启动信息中,会有如下输出:5 G) h: d% o9 s* M
8 C4 m9 G$ B [ p* m2 w# {9 c
......
# s& y0 H T/ F: [( N) D1 K! S
3 C9 i8 Q Q# e( u: E0 N/ aS3C24XX NAND Driver, (c) 2004 Simtec Electronics" o7 m" v3 m# U9 G4 r' q# o5 s
s3c24xx-nand s3c2440-nand: Tacls=1, 10ns Twrph0=3 30ns, Twrph1=1 10ns
3 z1 d3 E3 }7 \s3c24xx-nand s3c2440-nand: NAND hardware ECC
9 Y* h6 w4 N$ Z# ONAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
8 X6 C: a# B% f& v, U2 DScanning device for bad blocks
w/ p+ f5 X! i; o0 CBad eraseblock 781 at 0x0000061a0000' v3 `2 |1 ]& J* n0 J, ~
Bad eraseblock 1113 at 0x000008b20000# P( p4 @6 m8 ]' b/ t- H* J/ H
Bad eraseblock 1117 at 0x000008ba0000* L7 [# H) h% W2 U
Bad eraseblock 1481 at 0x00000b920000
7 p) o% w4 z$ Q; p* X' M; \* [Bad eraseblock 1566 at 0x00000c3c0000
4 j; ?- \! X" Y: PBad eraseblock 1885 at 0x00000eba0000
* b3 c" q" j- z0 |Creating 3 MTD partitions on "NAND 256MiB 3,3V 8-bit":
2 K8 M' l: m' X/ ]: C4 D1 ?0x000000000000-0x000000040000 : "Uboot"' E3 P8 C/ }% A: x: }8 J
0x000000200000-0x000000500000 : "Kernel"
' g* ^. K- ]9 v0x000000500000-0x000010000000 : "filesystem" [; t5 n* X2 ~5 o! T1 O4 M$ W0 k
l* j8 l- ^2 l$ I......
& _1 n; g1 L8 W4 | }( A: @( U7 ^9 R# k9 v# c8 s
上述信息表明以成功访问了NAND FLASH。) G. f+ c! n- h, K6 R4 F& _) P' [
! n: i# {6 e" ^% F2 a! m7 ?) ?( X这里,对第二行的输出进行个说明。
0 x$ U- a# K; ^$ W: j# Z& f! |+ s/ F
UBOOT启动将S3C2440的工作频率 FCLK:HCLK: PCLK = 8:4 :1,
' ~2 S1 K% e" o) ^. ], x
) b2 ^+ ^# C9 F4 G+ P4 ~* ]; W: \而FCLK为400Mhz,那么HCLK为100Mhz,根据NFCONF寄存器的说明,寄存器中的这3个参数都跟HCLK有关,必须为1/HCLK的倍数,
) V, E2 @9 u; T, H5 T& b! x
4 Q# Q( U* c- Q也就是1/100MHz=10ns的倍数。
! Q7 E0 Y# A. Q5 p0 {% ~) Z
2 O& g& O- `8 _/ C; k- b8 \通过上面第二行的输出信息,Twrph0为 30ns而Twrph1为10ns,这是显而意见的。6 J+ ], M9 E; ?0 z; U) l* A
8 z. n. x+ N: F! w由于参数必须为10ns的倍数,而且必须大于datasheet给出的值,因此向上取到10的倍数,也即5ns取到10ns,21ns取到30ns。
- _4 `5 b' v: R' s- a; Q P
; V% C" a+ ~3 x7 H那么为什么Tacls是10ns呢?明明给出的是0ns,是不是驱动不允许参数为0ns?$ I( i; h, K8 M* A0 a# u2 i
- r& n: O/ k: G9 F$ h0 J1 F3 P
在S3C2440的nand驱动中,参数的值是通过如下函数确定的:% @8 K8 T, v: Y5 y3 j, b5 |! @
6 w6 u" q2 _4 N5 d3 u' |static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
* p& C7 ?& L/ m( l: I/ J" `9 U7 J{5 n: ]9 n v/ n5 @
int result;* M1 N( [3 X3 M) g8 Y3 t5 o
9 l1 a" J1 R3 r6 T0 r% o" R0 L2 p& @
result = DIV_ROUND_UP((wanted * clk), NS_IN_KHZ);3 w" N0 ]/ J$ |! ~, x! K
+ ~" w$ o+ S6 @$ B5 F pr_debug("result %d from %ld, %d\n", result, clk, wanted);) p1 d2 ?' B0 Q( s; [
3 M- `2 c$ u4 Q6 z! ^
if (result > max) {
. A& T# Q J' M* i7 ]; X0 ~ printk("%d ns is too big for current clock rate %ld\n", wanted, clk);
: ~' \1 Z* \8 ^& N7 n return -1;! H- I- w/ v5 q# h5 z/ Z* v
}
7 L) I9 @; b/ T% F' y
; A# G* v) [0 D9 u% L0 u' n/ S& } if (result < 1)
8 }" o/ H. U, q( C) x9 |; @9 U result = 1;
$ `7 S/ y3 R6 h% J) J' Z. k/ R u' A# t- ~' X# B+ g
return result;
( h. ~- w; T- K! X& T1 x}& A3 v) h' ?8 Q* P$ k! l
. ` D) U6 X; B( R' N参数wanted就是0(ns),而clk即为HCLK/1000。
6 F' g+ e- v; {6 d$ L4 p& ~6 ?" Y3 {2 A- |$ u5 K
DIV_ROUND_UP宏将返回0,但是if对result进行了限制,也就是不允许小于0,因此将参数值设置为1,并返回给调用函数。 p3 x# u! S$ J$ Q; Y% B
" X3 l9 N# y y `2 a4 G
) A/ z7 W6 [8 k! S- p. A( D
+ B3 _! A+ Z; r( p* R4 w
7 d, J3 G8 N/ @% | p( [% n" H2 ?+ y: e2 d+ q# r7 p
4 A: G: Y3 W8 Q5 f3 D% M1 Z0 Q) k# G9 }( f
' Z" J/ L1 R+ T5 Q/ r& O! r
$ g7 l; V$ O& P; c9 V+ q
|
|