SSP 并口

1. 并口SPP

1.1 历史

最初的并口设计是单向传输数据的,也就是说数据在某一时刻只能实现输入或者输出。后来IBM又开发出了一种被称为SPP(Standard Parallel Port)的双向并口技术,它可以实现数据的同时输入和输出,这样就将原来的半互动并口变成了真正的双方互动并口;IntelXircom Zenith1991年共同推出了EPP(Enhanced Parallel Port增强型并口),允许更大容量数据的传输(5001000byte/s)其主要是针对要求较高数据传输速度的非打印机设备,例如存储设备等;紧接着EPP的推出,1992年微软和惠普联合推出了被称为ECP(Extended Capabilities Port,扩展并行口)的新并口标准,和EPP不同,ECP是专门针对打印机而制订的标准;发布于1994年的IEEE 1284涵盖了EPPECP两个标准,但需要操作系统和硬件都支持该标准,这对现在的硬件而言已不是什么问题了。目前我们所使用的并口都支持EPPECP这两个标准,而且我们可以在BIOS当中自己设置并口的工作模式。

1.2 管脚和寄存器介绍

标准的PC并口有25针和37针两种,分别称为D-subhCentronics,具体管脚定义见表4.14.3

标准的PC并口使用38位的端口寄存器,这些端口寄存器与并行口管脚存在对应关系,我们可以通过这三个端口寄存器去监控并口管脚。这三个端口寄存器依次是数据寄存器、状态寄存器和控制寄存器。

1.2.1 数据寄存器

数据端口或称数据寄存器保存了写入数据输出端口的一字节信息。数据端口可以写入数据,也可以读出数据(即可擦写);写进去的当然是我们希望从数据端口引脚输出的数据,不过读进来的也只是我们上次写进去的数据,或是原来保留在里面的数据,并不是从端口引脚输入PC的数据。

4.1 SPP模式下的信号定义1

数据寄存器(基地址)

引脚:D-sub

信号名

信号源

是否在连接器处倒相

引脚:Centronics

D0

2

数据位0

PC

2

D1

3

数据位1

PC

3

D2

4

数据位2

PC

4

D3

5

数据位3

PC

5

D4

6

数据位4

PC

6

D5

7

数据位5

PC

7

D6

8

数据位6

PC

8

D7

9

数据位7

PC

9

1.2.2 状态寄存器

状态端口或称状态寄存器保存的是5个输入(S3-S7)的逻辑状态。S0-S2位不出现在并口连接器中。除了S0以外,状态寄存器是只读的,读出数据信息是状态端口引脚上的逻辑状态。S0是支持EPP传输并口的超时标志信息,可以用软件方法清零。在许多并口中,状态输入接有上拉电阻。其定义如下:

4.2 SPP模式下的信号定义2

状态寄存器(基地址+1

引脚:D-sub

信号名

信号源

是否在连接器处倒相

引脚:Centronics

S0

Time-Out

S1

未使用

S2

未使用

S3

15

nError

外设

32

S4

13

Select

外设

13

S5

12

Paper Out

外设

12

S6

10

nAck

外设

10

S7

11

Busy

外设

11

注:有些PC上,012位均未定义

1.2.3 控制寄存器

控制端口或称控制寄存器保存了C0-C34位控制信息。一般来说,这些位被用来输出,然而大多数SPP中,控制位为集电极开路/漏极开路模式,也就是说,它们同样可以用作输入。要从控制位上读取外部逻辑信号,首先先向相应位输出写入“1″,然后读取控制寄存器的值即可。但是,为了提高交换速度,大多数支持EPPECP接口中,控制位工作在不能用作输入的推拉模式下。在一些多模式接口中,控制位采用的是改进型的推拉模式,可以用作输入。其定义如下:

4.3 SPP模式下的信号定义3

控制寄存器(基地址+2

引脚:D-sub

信号名

信号源

是否在连接器处倒相

引脚:Centronics

0

1

nStrobe

PC

1

1

14

nAutoLF

PC

14

2

16

nInit

PC

31

3

17

nSelectIn

PC

36

注:连接器中没有提供的附加位有:

4:中断启用:为1时,IRQnAck送往系统的中断控制器;为0时,IRQ不送往中断控制器。

5:双向控制端口的方向控制位:为0时,输出启动;为1时,不能输出;控制端口可以读取外部逻辑电平。

67:未定义。

1.2.4 一些重要说明

1. 对于PC自带的并口(我们称之为原生并口),必须在BIOS中设置为ECPEPP模式;

2. 上面几个表中的基地址一般如下:并口10×378,并口20×278,他们都是计算机自带的标准并口。当我们的PC机没有自带并口时,需要采用一些转换器,此时基地址将由转换器的驱动具体指定。如我的PC上装的PCI转并口设备模拟的并口的基地址为0xC400

3. 数据寄存器对应的引脚属于输入/输出口,状态寄存器对应的引脚属于输入口,控制寄存器对应的引脚属于输出口;

4. 根据模式的不同,并口的信号定义也不同

2.1 linux下对并口的编程

本节主要讨论在Linux如何通过操作前面提到的3个寄存器来达到操作并口管脚的目的。

2.1.1 Linux下如何访问IO端口

Linux下应用程序运行在保护模式下,不能直接对IO端口进行存取,需先通过ioperm取得端口的控制权。Linuxioperm系统调用允许本地读/写访问系统的IO端口,但仅限于00×3FF1024个端口,其它端口的访问级别可通过iopl更改。ioperm系统调用的形式如下:

#include <unistd.h> /* for libc5 */

#include <sys/io.h> /* for glibc */

int ioperm(unsigned long port, unsigned long num, int turn_on);

在这个系统调用中,port指端口的基地址,num是连续的端口数目,turn_on表明是获得控制权(turn_on1),还是释放控制权(turn_on0)。

Jflash源码中,iopermLPT1, 3, 1)即:获取并口1的基地址开始之后连续三个端口(数据寄存器、状态寄存器和控制寄存器)的控制权。

在获取控制权后,即可以通过outbinb等相关函数对IO端口进行写、读操作。

Jflash中相关代码如下:

#define _inp(a) inb(a)

#define _outp(a, d) outb(d, a)

#define OutputPpt(value) _outp((unsigned short)validPpt, value)// value写入validPpt,即写入数据寄存器,最后通过并口输出

#define InputPpt() _inp((unsigned short)(validPpt+0×1))// 读入状态寄存器的数值,实际是读取状态寄存器对应的并口管脚

2.1.2 Jflash源码中并口操作部分分析

上一小节中讨论了Jlash源码中最基础的三条函数,本节继续讨论Jflash中并口操作相关的其它函数。

/********************************************************************

* 功能: 设置port 端口开始之后的3个地址为可访问

* 参数: port: 欲设置访问权限的端口

* 返回值: 成功返回1, 失败返回0

********************************************************************/

static int io_access_on(unsigned long port)

{

if (ioperm (port, 3, 1)) {

perror(”ioperm()”);

return 0;

}

if (ioperm (0×80, 1, 1)) {

perror(”ioperm()”);

return 0;

}

return 1;

}

/********************************************************************

* 功能: 设置port 端口开始之后的3个地址为不可访问

* 参数:port: 欲设置访问权限的端口

* 返回值:

********************************************************************/

static void io_access_off( unsigned long port )

{

ioperm (port, 3, 0);

ioperm (0×80, 1, 0);

}

/********************************************************************

* 功能: 获取有效的端口号

* 参数:

* 返回值: 成功返回LPT1-LPT3中有效的端口, 失败返回0

********************************************************************/

int GetValidPpt(void)

{

if( io_access_on(LPT1) ){// LPT1是否可访问

_outp(LPT1, 0×55);// LPT1可访问,则通过写入0×55再读入对比来确认其是否可操作

if((int)_inp(LPT1) == 0×55)

return LPT1;

io_access_off(LPT1);

}

……// 如上依次检测LPT2LPT3是否可访问

return 0;

}

/********************************************************************

* 功能: 设置并口为兼容模式

* 说明: 由于大部分PC PC 中已设置并口为ECP EPP模式, 故本程序中没必要再设置

********************************************************************/

#define ECP_ECR (0×402)

#define ECR_STANDARD (0×0)

#define ECR_DISnERRORINT (0×10)

#define ECR_DISDMA (0×0)

#define ECR_DISSVCINT (0×4)

void SetPptCompMode(void)

{

//configure the parallel port at the compatibility mode.

//_outp(validPpt+ECP_ECR, ECR_STANDARD | ECR_DISnERRORINT | ECR_DISDMA | ECR_DISSVCINT);

}

2.2 JTAG与并口的硬件连接

关于JTAG引脚与并口的连接,用户可以根据自己的想法进行,只要与软件中设定能对应就ok。目前,有两种所谓”标准”接法:Sdt Wiggler 接法。

下表列出来这两种接法:

4.5 JTAG与并口的硬件连接

JTAG管脚

SDT接法

Wiggler接法

并口管脚

并口管脚号

并口管脚

并口管脚号

TCK

D0

2

D2

4

TMS

D1

3

D1

3

TDI

D6

8

D3

5

TDO

Select/STATUS[4]

13

Busy/STATUS[7]

11

nTRST

D2

4

D0

2

这里有个问题要着重注意下:Wiggler采用Busy脚做为TDO,其管脚在并口硬件上有个反向器。所以我们需要将读入的电平反向;SDT接法则没有这个必要。

3 Window下的JTAG开发

上面讨论的是在linux底下做JTAG开发。本章简单讨论下windows下的JTAG开发。

Jflash源码来看,除了并口操作要用到IO口,是与OS相关的,其它都符合ANSI C,不需要做移植。也就是说,只要解决好windows下的并口编程就ok了。

windows NT架构的操作系统(如XP)底下,应用程序同样不能直接访问IO口,我们同样需要先获取IO端口的控制权,而后使用API去操作他们。

3.1 如何获取IO端口控制权

为了在windows下实现对并口的访问,我们必须安装一些驱动或程序库。可能的手段主要有:

1. winio程序库

WinIO程序库允许在32位的Windows应用程序中通过物理地址直接对I/O端口和物理内存进行存取操作。通过使用一种内核模式的设备驱动器和其它几种底层编程技巧,它绕过了Windows系统的保护机制。

2. GIVEIO驱动

安装该驱动后,应用程序可以直接通过IO的物理地址进行直接访问。

Windows下的SJF烧写程序都使用了该驱动。这也是为什么在用SJF烧写viviBootloader前必须先安装GIVEIO驱动的原因。

关于GIVEIO的源码以及如何使用它,大家可到网上搜索下载,也可参考SJF源码。

3.2 IO端口的操作API

在使用GIVEIO驱动取得访问权后,可使用底下两个接口直接操作IO端口:

#include <conio.h>

int _inp(unsigned short port);

port参数为指定的输入端口号。调用后,它从port参数指定的端口读入并返回一个字节,输入值可以是在0-255范围内的任意无符号整数值。

int _outp(unsigned short port, int databyte);

port 参数为指定的输出端口号,databyte 参数为输出的值。调用后,它将databyte参数指定的值输出到port 参数指定的端口并返回该值。databyte 可以是0-255范围内的任何整数值。

这两个函数都没有错误值返回。在Win98下可以直接用, 但在NT下必须要挂驱动程序。

3.3 关于并口的端口号

当使用转并口设备时,并口端口号会比较特殊。这时,我们只需再定义一个LPT4,并在ppt.cGetValidPpt函数中增加对该并口的支持就ok了。

我的PCI转并口设备的端口号是0xC400,以下是我新增的代码:

#define LPT4 0×0C400

int GetValidPpt(void)

{

……

if( io_access_on(LPT3) ){

_outp(LPT3, 0×55);

if((int)_inp(LPT3) == 0×55)

return LPT3;

io_access_off(LPT3);

}

return 0;

}


Technorati : ,

该日志未加标签。
FPGA BOARD , Altera and Xilinx, News

相关日志

If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.

Leave Comment

(必填)

(必填)