TA的每日心情 | 开心 2019-11-20 15:05 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
4 d3 ^8 l$ N5 E8 x: b4 l: O
# `6 }( J6 z1 L2 H
3 i3 E( \; F0 n) j4 \* L& ? 引言
3 g" F& X" ?. [& I* \4 }' u, ]
) t/ N; o. H* P& r 8位单片机在嵌入式系统中应用广泛,然而让它直接与PCI总线设备打交道却有其固有缺陷。8位单片机只有16位地址线,8位数据端口,而PCI总线2.0规范中,除了有32位地址数据复用AD[3~0]外,还有FRAME、IRDY、TRDY等重要的信号线。让单片机有限的I/O端口来直接控制如此众多的信号线是不可能的。一种可行的方案就是利用CPLD作为沟通单片机与PCI设备间的桥梁,充分利用CPLD中I/O资源丰富、用户可自定制逻辑的优势,来帮助单片机完成与PCI设备间的通信任务。, R) c% h- x& t5 m+ Z6 X# t
$ G& d* {2 `$ Z4 ~6 e
1 PCI接口设计原理
2 V# r4 J6 E3 e5 G) U4 M& K- T( A c+ q: K0 n
1.1 PCI总线协议简介
5 ]* Q$ e+ T6 u4 w( ?) n) V* ]/ A% c: x4 ~: C/ b
这里只讨论PCI总线2.0协议,其它协议仅仅是在2.0的基础上作了一些扩展,仅就单片机与PCI设备间的通信来说,意义不大。PCI总线是高性能局部总线,工作频率0~33MHz,可同时支持多组外围设备。在这里,我们只关心单片机与一个PCI设备间通信的情况,而且是以单片机与CPLD一方作为主控方,另一方作为PCI从设备。这样做的目的是为了简化问题,降低系统造价。
& b3 l* v/ z8 p( l
, v+ v2 S" L, R PCI总线上信号线虽然多,但并不是每个信号都要用到。实际上PCI设备也并不会支持所有的信号线,比如错误报告信号PERR与SERR在网卡中就不支持。我们可以针对具体的应用选择支持其中部分信号线,还有一些信号线可以直接连电源或接地。下面简单介绍一下常用信号线的功能。9 J! y" H$ d2 N% T! M \1 B
5 M' z7 O' I0 h3 v AD[31~0]:地址数据多路复用信号。在FRAME有效的第一个周期为地址,在IRDY与TRDY同时有效的时候为数据。" h# J* L; e% j+ M6 U/ q* ^
- T( R9 }2 h V. k C/BE[3~0]:总线命令与字节使能控制信号。在地址中传输的是总线命令;在数据期内是字节使能控制信号,表示AD[31~0]中哪些字节是有效数据。以下是总线命令编码的说明:% q5 E9 Q9 K) e
7 A% r7 M: m+ V2 `1 E$ q
C/BE[30]# 命令类型说明C/BE[30]# 命令类型说明
/ B5 M' N. f/ q! u; d2 f# n$ v* d5 g0 F. J7 ?1 b
0 0 0 0 中断应答 1 0 0 0 保留% d3 F4 j) N5 ]# u
* ]. b, T {0 Y4 {& E3 q, ]! w 0 0 0 1 特殊周期 1 0 0 1 保留
$ a; [% ~9 x: S) k- W3 f6 a7 a" Q$ l/ K, H5 G9 _% u: m- r1 b
0 0 1 0 I/O读 1 0 1 0 配置读
1 Q8 z/ a; |0 ?" V; [* E9 K
9 G( d+ m+ b) l' K7 f$ K6 T 0 0 1 1 I/O写 1 0 1 1 配置写
! g; A0 B: S/ y) r
1 ?, e% `$ I% {2 E9 q& ^ 0 1 0 0 保留 1 1 0 0 存储器多行读* q! W* ^, j% R. y
3 f5 \2 ?3 g# U% Q5 v: a9 v 0 1 0 1 保留 1 1 0 1 双地址周期
* T% ?2 o$ x& B. B# k6 z
" g8 j8 g1 i$ I( i. z 0 1 1 0 存储器读 1 1 1 0 存储器一行读
6 h9 t1 }' _0 g0 o
# s# P' c# J1 R* ^: p 0 1 1 1 存储器写 1 1 1 1 存储器写并无效6 Q2 J; c* J- D5 l. e. f; C
# q9 W6 z) ^. j( P* h
PCI总线上所有的数据传输基本上都由以下三条信号线控制。1 t, x# l; N: f) [6 p* {' |1 N# q
% t* ~$ x$ e3 K
FRAME:帧周期信号。由主设备驱动,表示一次访问的开始和持续时间,FRAME有效时(0为有效,下同),表示数据传输进行中,失效后,为数据传输最后一个周期。( W; l. {* ^. |; q3 ]8 I# ~5 Y, D
- h4 }$ a: D0 g! i5 g
IRD:主设备准备好信号。由主设备驱动,表示主设备已经准备好进行数据传输。1 A; `; x9 g4 \, |4 S
/ @% q8 j. {. H
TRDY:从设备准备好信号。由从设备驱动,表示从设备已经准备好进行数据传输。当IRDY与TRDY同时有效时,数据传输才会真正发生.% `) ]% W$ ?0 L9 @
7 h8 A; f1 L: v4 }另外,还有IDSEL信号用来在配置空间读写期间作为片选信号。对于只有一个PCI从设备的情况,它总可以接高电平。IDSEL信号由从设备驱动,表示该设备已成为当前访问的从设备,可以不理会。
6 B6 o% n9 k y) z1 l, X I9 v6 z
在PCI总线上进行读写操作时,PCI总线上的各种信号除了RST、IRQ、IRQC、IRQ之外,只有时钟的下降沿信号会发生变化,而在时钟上升沿信号必须保持稳定。: Z8 i- \: g4 k U {
9 N( k B7 x1 }! I8 T9 d: N 1.2 CPLD设计规划
" J& p3 w/ {7 f7 u, A/ a/ N* j1 p s! D m) D7 ?
出于对单片机和CPLD处理能力和系统成本的考虑,下面的规划不支持PCI总线的线性突传输等需要连续几个数据周期的读写方式,而仅支持一个址周期加一个数据周期的读写方式。对于大部分应用而言,这种方式已经足够了。图1是经过简化后的PCI总线读写操作时序。
' e& @) a5 @: x" S( o' ?1 N0 t6 D
: p p6 M; \4 J Q 在CPLD内设有13个8位寄存器用来保存进行一次PCI总线读写时所需要的数据,其中pci_address0~pci_address3是读写时的地址数据;: ]. b3 _3 j5 [! a# j! h* i
5 O1 Z# U6 Z0 K; V
# c7 T O% P; k
7 ?6 B4 n9 o/ Z4 c# p0 n5 X图1 简化的PCI写操作时序 . `# E) o8 j7 D
* D& m" ^# g8 S6 J- k, z0 i8 } pcidatas0~pci_datas3是要往PCI设备写的数据;pci_cbe[3~0]保存地址周期时的总线命令;pci_cbe[7~4]保存数据周期时的字节使能命令;pci_data0~pci_data3保存从PCI设备返回的数据;pci_request是PCI总线读写操作状态寄存器,用于向单片机返回一些信息。当单片机往pci_cbe寄存器写入一个字节的时候,会复位CPLD中的状态机,触发CPLD进行PCI总线的读写操作;单片机则通过查询pci_request寄存器得知读写操作完成,再从pci_data寄存器读出PCI设备返回的数据。* k/ f3 a o& z2 L+ w
2 J3 I1 c# {' B6 ^/ E) ^. G* f
CPLD中状态机的状态转移图如图2所示。每一个状态对应FRAME与IRD信号的一种输出,而其它输入输出信号线可由这两个信号线和pci_cbe的值及TRDY的状态决定。当FRAME为有效时,AD[31~0]由pci_address驱动,而C/BE[3~0]由pci_cbe低4位驱动;当IRDY有效时,C/BE[3~0]视总线命令,要么由pci_cbe高4位驱动,要么设为高阻态,而AD[31~0]在pci_cbe[0]为“0” (PCI读命令)时,设为高阻态,而在pci_cbe[0]为“1” (PCI写命令)时由pci_datas驱动。另外一方面,一旦TRDY信号线变为低电平,AD[31~0]线上的数据被送入pci_data寄存器,而C/BE[3~0]线上的数据被送入pci_request寄存器的低4位。 # Q* f( {$ b" P) N1 q5 h
2 h5 U6 s! G0 @1 y, x! p0 y( ?* U, d: i& J5 p5 z
3 y$ Q: b8 U7 J- U
图2 状态转移图 1 h3 W' p# D3 K8 A, U' D
" G" m3 |! j! l& X) |
考虑到在不正常情况下,PCI设备不会对PCI总线作出响应,即TRDY不会有效,为了不使状态机陷入状态S2的僵持局面,另外增设了一个移位计数器mycounter。当IRD信号有效时,计数器开始计数。计数溢出之后,不论PCI总线操作是否完成,状态机都会从状态S2转移到状态S3,即结束PCI总线操作。当TRDY有效时,会立即置位mycounter.cout。8 R; t$ A) f) q# ^
" y0 x, f0 j9 M3 i
PCI总线操作是否正确完成,可查询pci_request的最高位是否为“1”,而IRDY与FRAME的值可分别查询pci_request的第4位和第5位。这两位反映了PCI总线操作所处的状态,两位都为“1”时可以认为PCI总线操作已经完成。在实践中,如果单片机的速度不是足够快的话,可以认为PCI总线操作总是即时完成的。
) j/ }) L9 N& F. V+ w' N( v( f) e/ X" ?; Z
2 PCI设计接口实现+ F! `9 ~" Z/ W5 V
$ T5 v5 y' ~6 y' [, r
2.1 CPLD VHDL程序设计
& _) l& v* {( R5 i$ [5 X& t% S* g) j" k3 T3 m$ r! l: _+ }& [9 d. o
我们针对8位单片机控制PCI以太网卡进行了程序设计,CPLD器件选用Xilinx的XC95216系列。针对以太网卡的特点在逻辑上进行了再次简化,最终程序将适配进XC95261芯片中,并在实践中检验通过。
( j. G: R H- r7 S* N) S, G( W
# P4 i+ S& w7 g% _8 r' l8 U 以太网卡仅支持对配置空间和I/O空间的读写操作,而且这两个空间的地址都可以设置在0xFF以内,所以可以只用一个pci_address0寄存器,其它地址都直接设为“0”;如果再限制,每次只往网卡写入一个字节数据,则可以只用一个pci_datas0寄存器,其它数值在具体操作时设成与pci_datas0寄存器的一样即可.
& T4 r8 n& ]: [7 x& \4 {- t, ^
6 e; s8 M7 ^% k8 O3 P: |2.2 单片机PCI读写C语言程序设计
) k6 g3 g0 v. k( O/ Y, C2 p' D, d3 a. Y. Z2 o7 L% [9 c
在CPLD在帮助下,单片机读写PCI设备就变得相当简单。首先,将pci_cbe等寄存器都声明为外部存储器变量,并根据CPLD的设计指定地址。然后,传递适当的参数给以下两个读写子函数,即可完成对PCI设备配置空间、I/O空间、存储器空间的读写操作。从PCI设备的返回数据存放在全局变量savEDAta中。1 P5 M" ?+ U; \
% [( |+ O( c- S% Q: |$ p& }& }
实际上在写PCI设备时,也可以从pci_data中得到返回数据。这个数据必须等于往PCI设备写的数据。利用这一点可以进行差错检验和故障判断,视具体应用而定。
3 X) S6 v; L- ~" p+ n; r
+ H; `) S i5 J0 [4 W& |* `8 r bdate unigned char request;
8 M4 H v" r+ o. N! }$ h! a- Y! w- V
sbit IRDY0=request^4;
- h" i$ @9 c, L
! C! W+ m$ }# F* l; z sbit FRAME0=request^5; O f. \/ L& A5 x+ r2 ?1 L" X$ P
& z3 M6 k1 e8 h4 Z( b
sbit VALID=request^7;: C' Z# N# d& G. P& c" h
+ L) _5 m8 L' S) X! H. w8 n
void readpci(unsigned char addr,unsigned char cbe){
" q @! j0 J; C5 c
, i7 w. r# N {1 s+ k3 S pci_address0=addr;, B' p% B6 }9 z" j! R X
, d. [+ e" f1 ` Q8 X# T pci_cbe=cbe;* R" ]' Q; P. a/ v e. o; P
7 \+ O$ g# J: j8 ~+ }; s `0 r% {+ @ request=pci_request;3 k5 t e6 M5 P. X2 q
, T+ T, P* J8 M7 h% J while(!IRDY0 & FRAME0)) request=pci_request;' w2 `) R6 c1 [) N2 y+ q: T# g) I
' d; u! q2 y! H c9 B* P( Q0 A savedata0=pci_data0;, H+ Q; ~8 j4 ]/ N3 j) `& Y
A1 H& v0 \9 }1 L savedata1=pci_data1;) Z/ i, h( [* K# P4 W& }
2 g4 }2 J- H: o- p savedata2=pci_data2;
0 `7 R5 Y2 `; U R! p2 M3 I9 _) ^( E2 g/ U- N% |* t/ h
savedata3=pci_data3;4 a- i7 c0 {$ l" S6 q1 l
" o9 Z# q3 \8 d# Z if(!VALID)printf("Data read is invalid! ");
+ Q5 t8 S- Q1 D6 z& T( |9 ^1 x4 F9 D% d! C. d. ?
}* \( z* n0 ]- ]$ H R3 _3 h# z1 J
9 B+ s! V) d6 x- p# U" ?' x0 f void writepci(uchar addr,uchar value0,uchar cbe){
B) [; T1 r$ c& |6 _/ y: B+ h1 H
+ h6 W1 b2 }& k: P0 Y8 k* q data uchar temp;
$ t b F/ G" y. ?) G/ M# w( o& J. t, H) N9 o
pci_address0=addr;3 I1 R" G& M" V ~9 s5 O: t
* h& y2 S) P+ x% @
pci_datas0=value0;& G+ |5 g: [. Y
6 L( F1 p5 _) |. {3 t3 K# K0 W% f pci_cbe=cbe;
8 D7 c6 _) D. k1 P0 K! M, H0 B* [8 A, \! Z4 t& V0 A$ Z& E6 N
request=pci_request;
& ?! i. K5 \6 W, u7 X
8 @% s7 o. e; \9 M! ~$ [* t- H while(!(IRDY0 & FRAME0)) request=pci_request;1 n* E+ k6 E0 `7 O/ m: B& Y/ i
6 _$ O! P* m8 S* K' x if(!VALID)printf("Data write is invalid!"); ]9 p2 L* q8 v+ E3 ^6 o
: R7 x* _) j; U* K% o# H
} " I6 {! {( q4 K' g2 h
3 z+ W+ E: r1 B W' L7 ~ v
3 结论; d5 D3 Y% f. G4 o8 }4 Q
e+ w P3 q9 N' g- B
用CPLD实现单片机与PCI总线接口的并行通信,电路结构简单、体积小,1片CPLD芯片足够,并且控制方便,实时性强,通信效率高。本设计方法已成功地应用于作者开发的各种数据采集系统中,用作单片机与PC104之间的并行数据通信,效果非常理想.
) n" B z; A) u0 _0 t# `7 Y
! R' Y {5 ^7 i
$ C1 ?/ _& t2 r0 D# O- Q1 | |
|