TA的每日心情 | 怒 2019-11-20 15:22 |
|---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
开发板:TQ24405 N! _2 ]' |2 K- J' x* Y2 Y4 A
3 o i7 w! I6 w: A% J! T; e
内核:Linux 2.6.32/ J( I& ~$ S O
( H# t$ y, _/ a K v, ^PC OS:Ubuntu 11.04
j9 G% P5 `9 a' F- j( T
$ Y6 G( u5 l( d5 V z0 x2 | _( N1 z6 R8 [ y3 d
# B/ e( h8 N- P/ F( ~ 本文将对NAND驱动的移植进行简单介绍。其中,将对NAND控制器所需要的参数进行详细说明。
8 L. s8 u& ?8 i& j" e; l4 I l3 m( p
1. 修改分区表3 \' {$ z( B+ Q2 n0 P. j% c, `6 X
' {& T, u6 E0 ?- D0 b* S
打开文件arch/ARM/plat-s3c24xx/common-smdk.c,修改mtd_partition结构体数组。6 d4 P' c" }4 [6 b
, H! S$ g1 Y) H' F. }" a7 }) ]修改后如下:
) h& a& J" h; I" T. a0 f5 [9 J V3 x t
static struct mtd_partition smdk_default_nand_part[] = {
7 H' G1 Y5 n% B2 R2 |9 s) Q [0] = {1 |' [. H3 ?! r( { R* I
.name = "Uboot",2 t/ G, S, T( U i
.size = 0x00040000,. l* s* A" A7 k3 r5 T7 M1 X
.offset = 0x00000000,
6 P% B* F: q1 G },
# q1 U# D9 b# p* D% g4 q& ` [1] = {
5 g6 x# b9 s: A# w ] .name = "Kernel",
; _5 G! j2 D; q- n1 } .offset = 0x00200000,
! A( J+ w+ }% A* _6 d .size = 0x00300000,& @+ J4 N$ Q G0 r* c# f
},
1 ^% W$ S, z( O) ~7 ~7 h [2] = {0 _* }. L; {* j8 I6 ~% h3 C8 v* `+ Z) ]
.name = "filesystem",
3 D4 I5 X- y& M$ {2 r .offset = 0x00500000,0 F9 Y; U9 ?+ n
.size = MTDPART_SIZ_FULL,. l( c' \& g# j) B9 n7 A
}+ z6 }" S2 P8 N H& _' M L
};
: H# \" T% A/ x+ V
! a- e) H0 L7 r4 i6 g4 a v/ X3 q% O8 e; `
TQ2440板上的NAND为256M,请根据你的NAND实际大小分配空间。" D0 _7 O5 R- u0 A5 ?+ E
7 [- A2 ]' B9 X2 L" b4 _5 h2 i
3 r; a- ^. c. @' S; \. q+ u5 q; d
6 o* Q7 P) _# f$ _4 x2. 修改NAND控制器参数
4 `* h2 K! l, X3 }
: |+ ?6 s2 ^5 H, ~$ H! k3 x打开文件arch/arm/plat-s3c24xx/common-smdk.c,修改smdk_nand_info结构体。
& l/ L% W* e& l K4 j P
2 `) ~- h. r9 R# D7 N' `修改后如下:
( q" n. G3 _- W. ]; t+ w. A: |2 ]7 N0 S2 g' b9 x8 d6 W
static struct s3c2410_platform_nand smdk_nand_info = {) S$ X( b* g# a
.tacls = 0, //10,//20,! R5 w) L* G! m8 M
.twrph0 = 21, //25,//60,
7 [# o& P9 g0 r5 I) f. j .twrph1 = 5, //10,//20, `# G" N: ~) @& s1 E$ I
.nr_sets = ARRAY_SIZE(smdk_nand_sets),
I9 }! h1 P$ l! p4 f* } .sets = smdk_nand_sets,
" t2 }) ?' C! z. B" W};
7 A+ S* l4 A0 O. Y. i9 l. N7 S1 u) m% D( Q, R* a6 p
这里的三个参数tacls,twrph0,和twrph1是如何给出的? 我们来分析下。
4 j l( y" s0 g" x6 G l& n
! C6 w# K5 R+ h8 U" P5 |先看下这个结构体的定义,位于arch/arm/mach-s3c2410/include/mach/nand.h:8 n8 X% F [7 l( `
! V- _0 ?$ q) Y, g3 j6 w
struct s3c2410_platform_nand {& ^+ j F6 q# {
/* timing information for controller, all times in nanoseconds */) {( J l: b+ @+ ?/ J4 ~( y% M
: A$ O1 l9 b3 U, { int tacls; /* time for active CLE/ALE to nWE/nOE */6 _& f5 v# r4 w. \* X7 l6 [0 {$ {0 D
int twrph0; /* active time for nWE/nOE */) ?: _) a. T8 H8 b! x# }. J
int twrph1; /* time for release CLE/ALE from nWE/nOE inactive */
( S: j0 v/ U/ ^/ o3 H0 V
: ?8 t$ o$ C* i unsigned int ignore_unset_ecc:1;
( _( G& q- s0 K A8 V: }: y% G7 @- Q. p; s
int nr_sets;$ t0 D2 ^! M7 a* {
struct s3c2410_nand_set *sets;
t2 M/ d& m% x4 e/ L+ c0 [3 F) N* g: S# F
void (*select_chip)(struct s3c2410_nand_set *,( j1 Z+ A6 U) }
int chip);
+ m- H- C' k i }% _+ |: r7 d};
4 e }4 q7 V6 [$ R# I, K# z
5 F5 H$ X4 a& T$ g: r8 H" L看到了对这三个参数的说明,这里提到了这三个参数的单位为纳秒,请注意。
# l6 b s: t0 R/ m
% }) v: r& |. |+ G; x那么这三个参数到底从哪来的呢? 它来自于S3C2440 nand 控制器的NFCONF控制器,如下:
: ]; H: @$ v; N& o8 _+ {2 \8 M+ s( v+ f+ M8 K& P1 m. u* F
% p0 Y* A! l8 l9 [7 y" r! ~2 _, I4 T: O8 O
' j5 |% k2 L2 ?6 N! o; J1 \3 u. p
3 b" f" _. E2 i) `% L 既然找到这三个参数的出处了,那么它们究竟是何含义呢?我们里看下:
" u) X7 R# O9 b7 Y% z+ n& _; Y3 }6 C2 P, A
" O. x" n( L+ r9 K0 w+ g9 u
) w( z* F% G# s0 K4 [( B2 }; V* {
# @- y& M4 E1 Q% U% i' Y! @5 a: _1 D; l; S! P: ^
这幅时序图同样来自S3C2440的datasheet。; R ] p3 Z7 C3 Q- L
! E" R$ z6 H. H0 C4 H通过这幅图和struct s3c2410_platform_nand中的注释,我们可以对这3个参数做出如下定义。* j4 }/ ^- F7 X8 n* A! J- M* o: |
* X. w, B2 C* u. t0 @! WTACLS:表示在CLE/ALE拉高后,多少时间以后才允许将nWE拉低。
& j% z7 v( B3 V; g( ^8 I
' n) _7 h( ~, |% @# H UTWRPH0:表示nWE低电平持续的时间。, e; {, Y: @& s: V& d
$ E* u- l- U- [* A
TWRPH1:表示nWE变为高电平后,多少时间后允许CLE/ALE拉低。' G1 ~, Z# t& o
. {) K6 ~8 E# K( S( [1 B" A8 |知道参数的意义后,我们来看下NAND芯片K9F1208U0C的datasheet来确定这3个参数的值。
x. P$ @& b2 K* H2 p! c8 [; i7 e( x2 G
5 Y1 l0 x. G+ i+ F, F% |* S. {1 v# a8 D" [2 V( t3 ~0 W1 k T
& H# f6 {7 S8 Y& r# n3 T# v, R% H
: P8 T( q8 K( G: c% Z% N7 h
从这个时序图,我们可以直观地看到twp对应着参数twrph0,而tclh对于着参数twrph1。+ v" s+ ~4 w- G% e5 H
1 Y8 {2 p3 z, s9 ]
但是tacls如何得出呢?从图中并不能直接得出该参数的值,需要转个弯,那就是将tcls减去twp,就可以得到tacls了。# e1 B% X& }* r `6 s5 ~
. `7 }" K4 N8 N5 d9 A3 n综上所述,为了得到nand控制器所需的3个参数,我们需要获得该nand芯片的3个时序参数:twp,tcls和tclh。# x9 n( X( S7 J
( ^; \# A9 J4 I& K
通过查找该nand的datasheet,3个时序参数的值如下:- S; g8 z0 Z c$ ~6 S! U
; S1 z) r7 s; q0 w9 v4 ~1 r% N
twp=21, tcls=21, tclh=5。7 d/ O+ v$ T! o; l6 L4 V; Q" }
9 i4 w) j6 N5 _. ^5 h- g, s9 ]4 m
将这3个时序参数转为我们需要的3个参数,单位为纳秒(ns):" k* R! F& ~( k( w0 Y
: X6 k4 E* q' O# ^: |* Q$ f6 h
tacls = tcls-twp = 21 - 21 = 0 ns1 D; A- c2 p# F% H. I6 c( Y
- a+ g9 u. L* Z! w$ u: @twrph0= twp = 21 ns# [: d. [' P: X5 h
. ]1 ?8 [1 O/ x" R7 X; Xtwrph1 = tclh = 5 ns
~9 c$ s' _) i/ a& e7 E/ D: z* b; l0 K* q: C) J$ d
至此,就成功计算出三个参数的值了 。
1 a8 S0 M6 f; j( ]1 @3 W6 @
' j+ d/ M4 R7 G) h3. 配置内核: |, U9 z" n' u/ B) y8 V; A' z
- ]9 C4 z5 ^. ~/ m2 T/ v3 H
8 X7 L4 \& j$ \. i
( n+ p+ V8 _6 F0 ~& E5 B
& w) q" N. X5 l. x+ h3 u9 Q
4 K: d8 r; j" f! ]% C' f% p$ L4. 验证& u" i, G u' v3 n; c/ K
+ K) f% O" _* A, w" j' v; z 在经过上述步骤后,编译内核并将内核少入nand,启动系统。在Linux的启动信息中,会有如下输出:. G$ V" M! o4 A
1 ^3 t, [6 R! V2 |7 F......% V1 l' P, f: ~% N
, G. c$ C6 I6 e3 ^+ P
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
) K% N3 T$ \+ F+ ^5 t* F$ ws3c24xx-nand s3c2440-nand: Tacls=1, 10ns Twrph0=3 30ns, Twrph1=1 10ns
. C, M) L1 \, l3 j. I( m5 ^s3c24xx-nand s3c2440-nand: NAND hardware ECC6 v V: t( Q+ q9 t5 N: ^
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)9 x$ e/ c0 L; P U
Scanning device for bad blocks" q' b$ m1 c: Q0 K
Bad eraseblock 781 at 0x0000061a0000
: F' z W+ J1 Z' Q3 lBad eraseblock 1113 at 0x000008b20000
& j' Q# _- O0 t2 cBad eraseblock 1117 at 0x000008ba0000! E$ U( h( B# L. a& S
Bad eraseblock 1481 at 0x00000b9200000 Z8 m: \8 Z$ {6 P8 E
Bad eraseblock 1566 at 0x00000c3c0000
0 i: q- t7 l/ Y7 ~3 yBad eraseblock 1885 at 0x00000eba0000
7 b N. w# s2 j; v7 J9 bCreating 3 MTD partitions on "NAND 256MiB 3,3V 8-bit":
8 _/ [( T' P+ ^ o9 X5 Z5 |0x000000000000-0x000000040000 : "Uboot"
6 \7 W, c- A5 W( U* L; y* }2 e; z0x000000200000-0x000000500000 : "Kernel"
+ g& ~, `0 S* y2 { g. g0x000000500000-0x000010000000 : "filesystem"- T# v. A" ]& \8 X- `
4 p3 L, I7 I- ?2 Z5 \5 q, c
......6 u: \. \: w! c0 u
9 R2 F# h) l4 ?% {8 N
上述信息表明以成功访问了NAND FLASH。6 l. E. f+ K4 a- {% r3 \
3 `8 J8 v. n" r1 B- X: s9 Q( Q6 U这里,对第二行的输出进行个说明。, J9 i% A" R! s6 t1 S# t( R# P
9 U5 a& {- S. i! i' mUBOOT启动将S3C2440的工作频率 FCLK:HCLK: PCLK = 8:4 :1,7 U7 r0 L. c4 k' ]2 Y
% V. W; w8 B1 U5 H
而FCLK为400Mhz,那么HCLK为100Mhz,根据NFCONF寄存器的说明,寄存器中的这3个参数都跟HCLK有关,必须为1/HCLK的倍数,( `; r9 E+ P- m/ y) K0 l( T$ x
" S; h( [2 p$ n" e. D' [, P8 W
也就是1/100MHz=10ns的倍数。5 S8 n/ k) w! e8 `
) Y7 H( S2 b+ y- A2 B
通过上面第二行的输出信息,Twrph0为 30ns而Twrph1为10ns,这是显而意见的。9 ^& g' j F& ~ i8 ?
0 [" K W' x. n$ p! j
由于参数必须为10ns的倍数,而且必须大于datasheet给出的值,因此向上取到10的倍数,也即5ns取到10ns,21ns取到30ns。6 ^+ @7 y4 m! ^+ N% b( m
, x; [% z/ B4 N0 {, R那么为什么Tacls是10ns呢?明明给出的是0ns,是不是驱动不允许参数为0ns?
& Y/ b& g3 a$ R2 W5 U5 T# Y$ v6 H( v3 d+ o4 ~( y, {
在S3C2440的nand驱动中,参数的值是通过如下函数确定的:
9 P) j8 C- n. W( E2 q, q) g" {8 Y: M
) N- I; X u2 Y2 [static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)! J5 J K1 P. g& W5 b' l- y
{
% h1 r$ C2 u( H/ I3 B int result;
6 g% p V$ M$ {& U$ h! v" N
% Z9 G ?" M7 M0 r result = DIV_ROUND_UP((wanted * clk), NS_IN_KHZ);, y- m0 q- y$ y
' t, z0 A5 B; L: b# W
pr_debug("result %d from %ld, %d\n", result, clk, wanted);' R8 P* G* m6 T0 u" h
/ N/ B7 T& L; \# |, F) w, C
if (result > max) {; j+ ^1 \" x' R B2 Z' `
printk("%d ns is too big for current clock rate %ld\n", wanted, clk);8 d1 Y4 U( j* _( Z Z- o
return -1;$ D8 O, l8 u( m, M8 K" S# X
}- N5 t9 c: X0 ^# R- r2 A
) t. S: U) \/ m2 c4 s if (result < 1)2 ]2 |0 p: d/ d$ j6 O, j$ l5 C8 T
result = 1;
& P. V) v8 I6 }9 C$ G8 ^) M& v& k/ H5 S: j) Z7 q& m) c
return result;
+ z+ X: d7 O; R, L* p" A: M7 c}
3 n9 \' S+ t3 ~% D( S& a j$ |: u4 v& l# D& {) m# p; q
参数wanted就是0(ns),而clk即为HCLK/1000。
+ o; r$ d% b, Y E4 {! |, T9 q2 C5 s' c I
DIV_ROUND_UP宏将返回0,但是if对result进行了限制,也就是不允许小于0,因此将参数值设置为1,并返回给调用函数。; p b t5 H1 y8 @# |7 f
' E8 P. m! e+ r. @7 v4 w2 U' s' {' e j; o/ F) q v, G2 k
/ J6 \! i4 Y, D* d4 j( e. l
5 }# @0 }: O9 n% s
1 s u3 t9 _, n6 w
( J2 \ `4 h8 @, y0 Z
" M$ D0 i1 f" j% O% a8 B# R) V$ P" |& `- {! C# r
) e/ Q/ n( R1 n, A, _
|
|