TA的每日心情 | 怒 2019-11-20 15:22 |
|---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
开发板:TQ2440/ s l5 w3 ?. |& [% p, H( u+ i
1 s) F a( E" h; y
内核:Linux 2.6.324 B' v- E/ ^% g, x3 Q5 ?# f( N
# J6 b1 a, O. g4 Q
PC OS:Ubuntu 11.047 G5 t+ n# |" O4 D
2 U s, c$ q) V/ R% _
}0 w' G Q( d) i
) O, A$ o5 W; l! k 本文将对NAND驱动的移植进行简单介绍。其中,将对NAND控制器所需要的参数进行详细说明。
$ t& a4 \$ T9 }/ x4 r6 U5 k9 o3 U
9 }" g( v* s+ p( T: S1. 修改分区表
0 X, P X* ^ A5 w3 {+ ]* G6 D. R o1 q0 a! F
打开文件arch/ARM/plat-s3c24xx/common-smdk.c,修改mtd_partition结构体数组。
0 C9 M; K* b3 f1 I* Z: w: m% g; T" _' _: H: R
修改后如下:$ ?; e5 ~, b: B% l& K, d$ f" ~+ ?
+ C" o1 l9 b: j8 K2 K) N1 D. G
static struct mtd_partition smdk_default_nand_part[] = {, `0 s5 H# P# B# V1 y
[0] = {/ Y: N# |0 k, I* ?) f
.name = "Uboot",
+ B- O2 f# J8 W. V, l4 f0 d8 d' V) w .size = 0x00040000,
6 {4 T v2 N2 b. c6 o .offset = 0x00000000,
) l5 S$ X+ H; e6 i E+ W },+ }+ e# ]' h6 y# G
[1] = {
N$ V' c: U8 C; p- k7 { Q .name = "Kernel",3 R! Q% U0 z2 I/ g/ a9 a5 @! A
.offset = 0x00200000,
" D8 n* v6 g4 q: `; `$ Y5 } .size = 0x00300000,
6 M0 B5 @. \3 t9 f! Y' c },
7 @2 K% I( s5 G [2] = {7 V [) A$ |9 P( `; s! b/ u: U7 C
.name = "filesystem",
2 t2 N2 m1 \4 a. f' ]: B6 c4 ` .offset = 0x00500000,
6 u7 A, O5 h( `0 S% X2 z .size = MTDPART_SIZ_FULL,
. _- ?$ O4 j6 Z6 |0 ~ }# j- @ \. j4 k# h9 V. M: M% g
};2 o' z" I3 T5 |/ |/ @( n: K! F; e3 R
: T+ w- |4 E) O4 G
- l0 ]% |3 c( E- bTQ2440板上的NAND为256M,请根据你的NAND实际大小分配空间。
9 p/ Z6 n$ n3 d$ p7 `% w/ K) G) F( R- j; K( X; l4 @( Z
( g2 M. C0 J" G* k3 R5 B4 f' w8 |0 m
! s& a4 b& Q+ W" I* ~2. 修改NAND控制器参数
2 a. _9 m' V, w P, q: m6 A* o
打开文件arch/arm/plat-s3c24xx/common-smdk.c,修改smdk_nand_info结构体。
' R5 r6 A; g: }+ g7 L# A7 k' c `: p" B; w3 u; q
修改后如下:
3 b) @0 n) H5 v6 z! w2 T
, U& T$ x3 o4 h _. x' t2 Dstatic struct s3c2410_platform_nand smdk_nand_info = {
+ W7 Y+ {. |3 @! D5 q .tacls = 0, //10,//20,
% g$ [8 }2 Y2 S+ g .twrph0 = 21, //25,//60,0 Q6 c4 A5 \# M; Y. H2 S5 \
.twrph1 = 5, //10,//20,# I$ t) q0 d& j2 |0 r
.nr_sets = ARRAY_SIZE(smdk_nand_sets),
$ @/ a) |( @" ?% b$ d( I, i ^ .sets = smdk_nand_sets,
; O* g' P8 r4 t% G: B5 f7 f9 d};1 n1 a: N( ?7 W, r3 h. c6 e/ ]
& l9 p( G! L0 ^, n: R' I
这里的三个参数tacls,twrph0,和twrph1是如何给出的? 我们来分析下。2 w9 ?# ?4 @' d1 p* T: K" I5 t6 L6 S
& K7 P/ [, \! M2 X4 b3 r: G! h
先看下这个结构体的定义,位于arch/arm/mach-s3c2410/include/mach/nand.h:
. q9 V) w# M' P; r0 F" S
. c# y; n# k$ L0 ostruct s3c2410_platform_nand {
' a4 W3 X# U6 \! l& @9 s /* timing information for controller, all times in nanoseconds */! H$ ^3 t( N+ n- i0 r
& n/ ^3 i4 {# q; W, v4 ? int tacls; /* time for active CLE/ALE to nWE/nOE */
6 O: ]! N. {! u- ]! W int twrph0; /* active time for nWE/nOE */
3 _- \; ?2 p" J5 j; Z* [4 E int twrph1; /* time for release CLE/ALE from nWE/nOE inactive */
8 v7 Y0 m$ Y" Z1 o+ Y: W+ r1 D8 m. X
unsigned int ignore_unset_ecc:1;
0 G! _/ b, R; K: ~" R: t2 ~- }& I1 t
int nr_sets;& |4 {8 J6 h1 r9 k" a! r
struct s3c2410_nand_set *sets;
1 U( w! R/ [- O0 L6 E1 \
/ ]' m5 W& ]0 | void (*select_chip)(struct s3c2410_nand_set *,) ?) B* }( c7 P P# F
int chip);$ s$ z& p& j3 x; N1 b' G( ]0 l
};8 V' S5 N6 N# f7 z
) h- u; U( A2 M* q/ k6 R
看到了对这三个参数的说明,这里提到了这三个参数的单位为纳秒,请注意。; s; |) S- L/ p( T: f* f P
6 ^2 Q. n2 T8 c. n8 s- Q4 d$ m
那么这三个参数到底从哪来的呢? 它来自于S3C2440 nand 控制器的NFCONF控制器,如下:
8 j! `' L$ l+ S
% g+ T; h" B" H z: t
7 L: w; n4 V. C: k
8 z! m( @1 @; @+ ]
3 C8 e1 \7 c; n# |& [4 f2 M9 S' U# L2 r, }! {9 P
既然找到这三个参数的出处了,那么它们究竟是何含义呢?我们里看下:8 w5 ~. k( l: J; k2 w' P
, Y) `( n/ Z* d' g$ n' i7 R! j" Z
0 s0 G! W) r/ e6 x _$ y' _
/ V( u- v# W5 i2 x0 j( L; D2 o2 ?6 w! j; g7 e4 g' w ~0 U6 O
% E& Z* g- _; d2 D, X
这幅时序图同样来自S3C2440的datasheet。
& r0 W; E: W r# s2 _& g" }
5 ]7 ~ n- M& S通过这幅图和struct s3c2410_platform_nand中的注释,我们可以对这3个参数做出如下定义。
0 v2 j; v2 I! f: k+ f
* A& B# |0 ~, l( K8 s% t# LTACLS:表示在CLE/ALE拉高后,多少时间以后才允许将nWE拉低。* A/ Z8 {& J _% f
! L- U% T( \: i( i/ ]! i5 w' KTWRPH0:表示nWE低电平持续的时间。
, N8 d. i$ f1 g! ^9 |& x2 o# Q/ J: w8 E# D) @7 }3 N0 }6 O
TWRPH1:表示nWE变为高电平后,多少时间后允许CLE/ALE拉低。( Q& A3 L/ S9 w' d7 ]
2 d9 O: v" d$ U: a0 N- {知道参数的意义后,我们来看下NAND芯片K9F1208U0C的datasheet来确定这3个参数的值。3 b; K0 d7 Z6 h* i, ^* v
1 a* @+ Q) w2 Z, q: [/ [3 G
8 O# \3 v2 ~7 l5 ~; b. n/ Q3 n
1 G+ S6 Z. k" `$ q, }3 _' L# a
* c/ x$ Q) P$ I+ i/ j- ~
+ S. R3 x( m8 I从这个时序图,我们可以直观地看到twp对应着参数twrph0,而tclh对于着参数twrph1。
, Z" s' ^0 @% n/ V: N, `8 W3 W1 F5 N
但是tacls如何得出呢?从图中并不能直接得出该参数的值,需要转个弯,那就是将tcls减去twp,就可以得到tacls了。
6 P; i/ \1 T' w4 O$ ^* i/ V ^2 W
, _% b* S0 P4 f0 Y7 r% x综上所述,为了得到nand控制器所需的3个参数,我们需要获得该nand芯片的3个时序参数:twp,tcls和tclh。
, o' P1 z& b, M8 X( X, Q. n
9 i. A A ^4 \% e1 M* b# U9 ~$ ^通过查找该nand的datasheet,3个时序参数的值如下:
& K9 @- ^: k# c+ L- D5 B' y* o' j& @6 ^, h
twp=21, tcls=21, tclh=5。" h* Q5 k/ G [( R b+ U
9 `, t5 J2 w$ V: F! C" ]
将这3个时序参数转为我们需要的3个参数,单位为纳秒(ns):
8 b" t" V+ W/ p" o" S9 L n6 w& ^3 D5 ^1 q
tacls = tcls-twp = 21 - 21 = 0 ns% Q5 b% R6 d- `3 k1 `
, t8 K2 K+ f+ E' X5 X H6 n% c
twrph0= twp = 21 ns
! @4 ]0 t$ X* w- v" v# f! q. I# s+ X8 J5 ~3 J% J. z3 H) O0 r
twrph1 = tclh = 5 ns# K3 |4 I9 a6 l& C# _" q) }, o! e
3 U, d0 g7 P2 C! V* q0 x8 L$ O4 c
至此,就成功计算出三个参数的值了 。9 \, E& r& Y3 q5 H7 h% g/ b% b
2 V0 N0 Z& c( O. @
3. 配置内核
/ y$ T# ^+ |7 v& r5 X6 H
) F: w& z8 Z2 z- q
0 Y8 P- a( I: k+ Z# E/ D7 Y' h
- @$ J# F# ~2 `# k$ c/ v7 ?0 P
+ U8 f+ M4 j$ D* d) E5 ~! V: {% n; p- @/ l
4. 验证2 s0 M/ u$ {+ E% T! i- Y: T
& u; s- E+ H/ t6 w& x. K" c 在经过上述步骤后,编译内核并将内核少入nand,启动系统。在Linux的启动信息中,会有如下输出:) Z H" u2 ~ i/ l" Y- S' @4 z9 X
( v) f: z& l B) c0 x0 v3 s5 n
....../ m( L+ ^8 N5 i7 i3 E1 ]4 o
& f" p$ ~4 h& |. |$ qS3C24XX NAND Driver, (c) 2004 Simtec Electronics
' [! k O# e8 k6 |9 \8 m& ?; bs3c24xx-nand s3c2440-nand: Tacls=1, 10ns Twrph0=3 30ns, Twrph1=1 10ns& r- \6 E5 t* J8 W* }* T
s3c24xx-nand s3c2440-nand: NAND hardware ECC' i- `* J2 J2 c# D' Y
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)3 B5 J L) R5 G) A! L, S5 }. U
Scanning device for bad blocks6 }9 e( I* q0 \$ S2 s* @& c
Bad eraseblock 781 at 0x0000061a0000
2 y }6 ^6 h1 Z# s" i% ZBad eraseblock 1113 at 0x000008b20000
% j" e" h3 F. _7 ^. mBad eraseblock 1117 at 0x000008ba00008 N8 r- p: s* j# L+ A( {
Bad eraseblock 1481 at 0x00000b920000
8 F9 ]& h9 e5 a# JBad eraseblock 1566 at 0x00000c3c0000
+ U9 A" b4 f0 r cBad eraseblock 1885 at 0x00000eba0000
# R# w5 y* I4 m4 @8 b2 q V1 L' bCreating 3 MTD partitions on "NAND 256MiB 3,3V 8-bit":+ L7 Q$ j/ {# T: j* c+ }
0x000000000000-0x000000040000 : "Uboot"
! n3 }( T, H3 Z! k8 m+ U5 x0x000000200000-0x000000500000 : "Kernel"% a8 u" k' e2 n0 v
0x000000500000-0x000010000000 : "filesystem"
* S1 [4 i; {: h p& l- {6 C: s; f, R
2 d5 b `" B; s: N9 D @! q......! o+ T9 t8 j' k! q5 C
/ N+ h( g. S; s/ X0 \
上述信息表明以成功访问了NAND FLASH。% d1 ~/ X: K& F4 B" l8 c6 ^
1 y4 e( v; t; {( H$ o; W
这里,对第二行的输出进行个说明。
9 z. c) h* j. ?( |6 ^# V6 G! }. u, H. x# L# `- c
UBOOT启动将S3C2440的工作频率 FCLK:HCLK: PCLK = 8:4 :1,
4 K- |8 F$ D$ }
2 y4 w9 M! V* V而FCLK为400Mhz,那么HCLK为100Mhz,根据NFCONF寄存器的说明,寄存器中的这3个参数都跟HCLK有关,必须为1/HCLK的倍数,
* ~; U6 D# w" J8 j. F! z6 S! {6 Z9 l
也就是1/100MHz=10ns的倍数。7 ^9 I4 h) l1 r8 t, u8 b% K# w
# }( p9 \+ m/ t; b( F" t2 R7 n& P# _
通过上面第二行的输出信息,Twrph0为 30ns而Twrph1为10ns,这是显而意见的。
6 r% H6 r9 b `7 S
9 I0 S8 n* f6 m, t" |由于参数必须为10ns的倍数,而且必须大于datasheet给出的值,因此向上取到10的倍数,也即5ns取到10ns,21ns取到30ns。# k/ T* t5 _7 P) f
% s! L! f) A7 Y那么为什么Tacls是10ns呢?明明给出的是0ns,是不是驱动不允许参数为0ns?
$ I) F6 N' Q/ U* O
9 B& Q, r3 M A d2 l8 q在S3C2440的nand驱动中,参数的值是通过如下函数确定的:0 @$ J+ k; S3 H
C' ]. h) a9 Wstatic int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
$ D* h* M/ d5 t7 Q3 u{! ]8 g" I H% i5 a/ `# B
int result; |: S# O2 C1 L w
/ }/ ^5 o5 E4 h6 ^' g1 n8 W
result = DIV_ROUND_UP((wanted * clk), NS_IN_KHZ);! u) ^5 i# o' m; G
* X5 V9 ]0 h) [ k( Z1 `9 F6 h- @
pr_debug("result %d from %ld, %d\n", result, clk, wanted);# O' w7 y1 n3 N6 {! m
4 j, S" I- w& D; x if (result > max) {3 u$ T6 [' @3 T$ u( E0 Q- x" {6 _
printk("%d ns is too big for current clock rate %ld\n", wanted, clk);0 w" t) I0 ]$ R, Z2 W" @9 R
return -1;
1 s7 e# p% g3 r% ^! F+ X: N }' `3 L w7 |6 O
2 G( I1 ]# _& C: ]' H Y
if (result < 1) p6 e" ]$ H/ s$ m
result = 1;" `3 Q; S0 H3 v; U* k5 }
; }( r1 p/ C. ?7 b return result;
0 T1 S' t* M8 }& O$ ?' M}
; }' ~1 k9 X7 D* G! G$ t% x V$ |$ x2 d9 _2 J# o
参数wanted就是0(ns),而clk即为HCLK/1000。: m! ~2 U' Y! |1 W
& m% K( H& y7 k/ E7 _7 A7 N4 k0 U
DIV_ROUND_UP宏将返回0,但是if对result进行了限制,也就是不允许小于0,因此将参数值设置为1,并返回给调用函数。
1 F4 i4 b l& x9 ^! ~4 z7 @7 t* o7 `1 f( O9 m
' [9 Y& u: Q1 c. o$ Y
2 s. `' c, H, a$ q3 x$ l! s4 Y1 `
' S1 z+ n+ M7 k0 T5 e, L4 i1 z. w6 o- Q) C3 i/ F
2 ~4 n$ ~% _0 }6 C+ |
3 \5 `: [& c" `4 W7 q6 W
0 Y! N' Z" K4 e( W9 \
: ]- {' H; R; U+ b# C3 w) M- h0 k |
|