Chinaunix首页 | 论坛 | 博客
  • 博客访问: 135327
  • 博文数量: 17
  • 博客积分: 1420
  • 博客等级: 上尉
  • 技术积分: 210
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-18 14:29
文章分类
文章存档

2011年(1)

2009年(12)

2008年(4)

我的朋友

分类:

2009-05-25 20:27:38

下对并口的编程

经过前面一节的处理后,在虚拟机底下的Linux与独立的Linux下的并口编程是一样的了。本节主要讨论在Linux如何通过操作前面提到的3个寄存器来达到操作并口管脚的目的。

下如何访问IO端口

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

#include /* for libc5 */

#include /* 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+0x1))// 读入状态寄存器的数值,实际是读取状态寄存器对应的并口管脚

源码中并口操作部分分析

上一小节中讨论了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 (0x80, 1, 1)) {

              perror("ioperm()");

              return 0;

       }

       return 1;

}

 

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

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

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

* 返回值:  

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

static void io_access_off( unsigned long port )

{

       ioperm (port, 3, 0);

       ioperm (0x80, 1, 0);

}

 

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

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

* 参数:     

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

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

int GetValidPpt(void)

{

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

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

              if((int)_inp(LPT1) == 0x55)

                     return LPT1;

              io_access_off(LPT1);

       }

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

       return 0; 

}

 

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

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

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

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

#define ECP_ECR                       (0x402)

#define ECR_STANDARD           (0x0)

#define ECR_DISnERRORINT     (0x10)

#define ECR_DISDMA                (0x0)

#define ECR_DISSVCINT           (0x4)

void SetPptCompMode(void)

{

       //configure the parallel port at the compatibility mode.

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

}

与并口的硬件连接

关于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接法则没有这个必要。

下的JTAG开发

上面讨论的是在linux底下做JTAG开发。本章简单讨论下windows下的JTAG开发。有兴趣者可查看我的源码。

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

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

IO端口控制权

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

1.       winio程序库

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

2.       GIVEIO驱动

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

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

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

端口的操作API

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

#include

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下必须要挂驱动程序。

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

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

#define LPT4  0x0C400

 

int GetValidPpt(void)

{

   ……

       if( io_access_on(LPT3) ){

              _outp(LPT3, 0x55);

              if((int)_inp(LPT3) == 0x55)

                     return LPT3;

              io_access_off(LPT3);

       }    

       return 0; 

}

阅读(4330) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~