0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于实时操作系统QNX4.25进行设备驱动程序的编写研究

电子设计 来源:单片机与嵌入式系统应用 作者:曹园 , 吴勇 , 傅鹏 2020-10-09 10:15 次阅读

介绍实时操作系统QNX4.25下编写设备驱动程序的大体框架、底层细节以及诸多注意点。针对使用较为普遍的PCI设备作为较为详细的描述。

QNX是一个多任务、多用户、分布式、可嵌入式符合POSIX标准的微内核的主流实时操作系统,广泛用于实时性能、开发灵活性、网络灵活性要求较高的场合,如电信系统、医疗仪器、航空航天、工业自动化、交通运输、POS机、信息家电等。

QNX是一个适合软件/硬件定制的实时操作系统。如果你曾经试图在传统的UNIX或Windows平台下开发设备驱动程序,那么,QNX下开发驱动程序一定会让你受宠若惊。由于QNX的微内核结构,QNX下的系统进程和用户所写的进程没有什么不同,甚至没有私有的隐藏起来的以至用户不能使用的界面。正是这种结构给QNX带来了无与伦比的可扩展性,使得在QNX下写驱动程序如同写其它程序一般方便。设备驱动程序能够获取普通程序所能获得的任务服务。在QNX中增加一个新的驱动程序不会影响操作系统其它程序的任何部分,QNX环境所需的唯一改变是实现地启动新的驱动程序。

当然,我们会遇到形形色色的硬件设备,某些驱动程序可能将以特殊方式控制设备的存在和配置。本文只想集中讨论QNX下如何进入、控制设备级的通用硬件,对所有驱动程序来讲这是一个共性问题。其中,将对使用较多的PCI设备作较为详细的叙述。以下是硬件驱动程序的编写。

1 探测硬件

首先,需要判断设备是否存在,然后查询该设备的配置(例如,设备基地址、中断号等)。对于某类设备,一般会有一大相应的标准机制来判断其配置。每块设备的基地址、中断号等是编程必须的资源,例如,常用的ISA及PCI硬件设备。对于ISA设备,一般由板上手工跳线设定,不言自明;对于常用的PCI设备,这些资源会由系统自动分配,特别是添减设备,可能会发生变化。因此,在驱动程序中能够动态查找这些资源显得比较重要。对于诸如A/D、D/A、定时卡、I/O板卡这类设备,对照硬件手册编写一些简单的驱动程序并不困难。如果有DOS下驱动程序的C源码,移值应该更容易一些。

为了实现对PCI总线设备的控制和管理,必须访问PCI设备的配置空间。配置空间是一容量为256字节并具特定纪录结构的地址空间。该地址空间的结构如图1所示。NQX4.25pp sys/pci.h中对应的结构体定义。

基于实时操作系统QNX4.25进行设备驱动程序的编写研究

每个PCI设备具有唯一的厂商标识(vendorid)和设备标识(device id),这些信息由硬件手册提供或系统启动时可以看到。下面一段代码展示了于一个给定的PCI设备如何调用QNX相关的函数、侦测设备的存在以及系统分配的资源。其中,标识(index)用来支持和区分具有同样厂商标识和设备标识的几块同样的设备。Index从0开始,如果指定为1,将标识第二块同型号的设备。

本例中,YOUR_PCI_DEVICE_ID、YOUR_PCI)CENDOR)OD值是研华的PCL-1713采集卡,可以根据所使用的硬件填以合适的值。

以根据所使用的硬件填以合适的值。

#include

#include

#include

#include

#include

#include

#include

#include

#define YOUR_PCI_DEVICE_ID0x1713 //根据具体设备提供对应的厂商标识及设备标识

#define YOUR_PCI_VENDOR_ID 0x13fe

int main(void){

unsigned busnum,devfuncnum; //总线号(PC仅有一条)及设备功能号

longaddress;

long io_base; //I/O基地址

unsigned char irq; //中断号

int pci_index=0 //标识为零标识第一块此种型号设备

if(_CA_PCI_Fin

d_Device(YOUR_PCI_DEVICE_ID,

YOUR_PCI_VENDOR_ID,pci_index,%26;amp;busnum,%26;amp;devfuncnum)!=PCI_SUCCESS){

printf(“Cannot find device”);

exit(EXIT_FAILURE);

}

//侦测设备中断

if(_CA_PCI_Read_Config_Byte(busnum,devfuncnum,offsetof(struct_pci_config_regs,Interrupt_Line),

1,%26;amp;irq)!=PCI_SUCCESS){

printf(“Error reading interrupt”);

exit(EXIT_FAILURE);

}

//侦测设备I/O基地址

if_CA_PCI_Read_Config_DWord(busnum,devfuncnum,offsetof(struct_pci_config_regs,Base_),

1,(char *)%26;amp;address)!=PCI_SUCCESS){

printf(“Error reading address”);

exit(EXIT_FAILURE);

}

io_base=PCI_IO_ADDR(adress);

printf(“IO address:%x”,io_base);

printf(“IRQ:”%x“,irq);

exit(EXIT_SUCCESS);

}

注意:各种设备的Base_Address_Regs[x],x可能不尽相同,需要查看具体的硬件手册决定。

2 进入硬件

一旦获得了系统分配给某个硬件设备的资源信息,就可以同这个设备进行通信了。至于如何做取决于需要访问的硬件资源。

2.1 I/O资源

一个进程试图进行I/O操作,必须具有正确的权限等级。你必须是超及用户(root),在编译的时候加上适当参数T1,以确何该进程拥有访问I/O口的权限。若忽视这一点,该运行进程将获得一个口的权限。若忽视这一点,该运行进行将获得一个SIGSEGV信号,表示一个非法的内存引用,并结束进程运行。

现在就可以利用inp()、inpd()、inpw(),outp(),inpd(),inpw(0等函数,对I/O基地址(I/O base address)加上寄存器偏移量(offset)处的I/O进行操作了。例如:

outpw(baseaddress+offset_reg,0xdeadbeef);

此外,对于一些设备,其I/O口是固定、众所皆知的,例如,一块VGA兼容的设备,并无上述所谓基地址。通过0x3c0、0x3d4、0x3d5,可以直接进入这些VGA的控制器。例如:

outp(0x3d4,0x11);

outp(0x3d5,inp(0x3d5)%26;amp; ~0x80);

2.2 存储映射资源

某些设备,可以通过一般的内存操作进入寄存器,这就需要获得内存基地址(memory base address)。为了能够获进入此类设备的寄存器,需要将其映射到驱动程序虚拟地址空间。QNX下的技术资料/etc/readme/technotes/shmem.txt描述了如何创建一个共享内存对象,然后将这个内存对象的一段内存映射到PCI卡中,以便能够进入这个PCI设备。(接着上面的代码)可以利用mmap():

char *mem_base;

if(PCI_IS_MEM(address)){ //判断内存基地址

int fd;

char *page_ptr;

fd=shm_open(”Physical“,O_RDWR,0777);//创建一个共享内存对象

if(fd= =-1){

perror(”Error shm_open:“);

exit(EXIT_FAILURE);

}

page_ptr=mmap(0,4096,PROT_READ|PROT_WRITE,

MAP_SHARED,fd,PCI_MEM_ADDR(address)%26;amp;~0xfff);//将内存基地址映射

if(page_ptr= =(char *)

perror(”Error mmap:“);

exit(EXIT_FAILURE);

}

mem_base=page_ptr+(PCI_MEM_ADDR(address)%26;amp;0xfff);

close(fd);

}

printf(”MEM“ address:%lx”,PCI_MEM_ADDR(address));

if(PCI_IS_MEM(address))

printf(“mapped at : %lx”,mem_base);

现在可以使用指针mem_base来进入设备寄存器了。例如:

mem_base[SHUTDOWN_REGISTER]=0x0xdeadbeef;

2.3 中断资源

超级用户(root)可以调用qnx_hint_attach()将一个中断处理程序绑定到一个设备上。中断处理程序作为一个远程调用(far),在进程空间(Localdescriptor Table set)运行。该函数最后一个参数设置数据段。寄存器SS为一个特别的内核栈,这不同于数据段(DS)。因此,需要在中断处理程序及其调用的函数中关断栈检查。大部分系统库中的函数在编译的时候都关断了栈检查,然而,对于需要使用大量内存的函数可能并非如此。后者即是那些在中断处理程序中不可调用的函数,如printf()、open()。通过QNX具体函数在线资源的Safety→Interrupt handler项进行判断该函数是否可以调用。如果函数中包括任何自动(auto)变量,强烈建议将中断函数放在自身文件中,然后利用参数-zu选项编译之。这样能够告知编译器,使得SS!=DS。

任何被中断处理程序修改的变量需要指定为volatile关键字。中断处理程序的返回值必须为0;或某个有效的代码号(proxypid),以此来触发一个代码从而发送一则消息。

下面总结一个中断处理程序编写时的注意点:

①只能和自己的硬件对话(如,清除设备的中断状态位),千万不要对8259中断控制器编程!

②使中断处理程序尽可能的短小。如果有很多的工作需要做,必须触发一个代理,并且它唤醒一个进程完成这些工作,以保证其它进程及低优先级的中断正常运行,提高系统的实时响应能力。

③中断处理程序不能调用含有内核调用的例程。

④中断处理程序必须是一个远程(far)调用函数。

⑤中断处理程序必须在自己的模块中。

⑥无论程序中其它模块是如何编译的,包含中断处理程序的模块必须是利用-zu和-s选项编译。(利用cc-zu-Wc-s)这些选项能够保证SS!=DS,并且关断栈检查。当然,也可使用:

#pragma off(check_stack);

pid_t far handler_xxx(){

return(proxy_xxx);

}

#pragma on(check_stack);

在试图编写执行一个中断处理程序前,务必仔细阅读在线文档。现在,可以参照硬件手册自由地对您的设备寄存器进行操作了。

结语

在HT-7U极向场电源控制系统中,我们在QNX4.25下开发了多种设备的驱动程序。这些程序工作稳定、性能优异、工作量小且易于控制。此外,QSSL公司的新版本QNX6.x下开发驱动更为方便,其原理同QNX4.25相似或者是对应的。

责任编辑:gt

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 操作系统
    +关注

    关注

    37

    文章

    6506

    浏览量

    122644
  • PCI
    PCI
    +关注

    关注

    4

    文章

    634

    浏览量

    129896
  • 自动化
    +关注

    关注

    28

    文章

    5355

    浏览量

    78512
收藏 人收藏

    评论

    相关推荐

    vmware虚拟机内运行qnx4.25系统

    ,型号是cif104。 现在由于计算机不再生产,我想将该 qnx4.25 系统放入windows10虚拟机内运行,暂时测试运行无问题。 我现在急需解决的问题是,后面带的输入输出该如何处理,cif104通讯该如何处理。 请各位大神指教!!!
    发表于12-12 15:42

    实时系统VxWorks下设备驱动程序编写详解

    实时 系统VxWorks下 设备 驱动程序编写详解
    发表于03-29 12:26 15次下载

    实时操作系统VxWorks下电子盘驱动程序的开发

    实时 操作系统VxWorks下电子盘 驱动程序的开发
    发表于03-29 12:26 28次下载

    基于VxWorks实时嵌入式操作系统设备驱动程序设计

    基于VxWorks 实时嵌入式 操作系统设备 驱动程序设计
    发表于03-29 12:28 28次下载

    QNX4.25设备驱动程序编写

    介绍 实时 操作系统 QNX4.25编写 设备 驱动程序的大体框架、底层细节以及诸多注意点。针对使用较为
    发表于04-16 10:25 40次下载

    QNX操作系统及网络设备驱动模块

    介绍嵌入式 操作系统 QNX的微内核结构、基于io-net 的网络子 系统、网络 设备 驱动程序的组成;给出以以太网
    发表于04-16 10:50 27次下载

    QNX操作系统及网络设备驱动模块

    介绍嵌入式 操作系统 QNX的微内核结构、基于io-net 的网络子 系统、网络 设备 驱动程序的组成;给出以以太网
    发表于05-14 16:26 19次下载

    实时系统VxWorks下设备驱动程序编写

    近年来, 实时 系统得到了越来越广泛的应用,VxWorks 是较受欢迎的一种。在嵌入式 实时 系统进行软硬件开发的关键是
    发表于06-12 11:38 9次下载

    基于Linux操作系统设备驱动程序开发

    本文介绍了Linux 系统的特点,阐述了在Linux 操作系统下,对 系统硬件的访问和开发 驱动程序的方法,说明了 设备
    发表于09-02 17:11 20次下载

    Linux字符设备驱动程序编写框架

    一、Linux device driver 的概念 系统调用是 操作系统内核和应用 程序之间的接口, 设备 驱动程序
    发表于12-25 10:54 796次阅读

    嵌入式操作系统VxWorks设备驱动程序的设计

    在嵌入式 实时 系统进行软硬件开发的关键是 编写高效可靠的 设备 驱动程序,而VxWorks下END网口
    发表于03-21 15:38 33次下载

    QNX操作系统下的Modbus串口通信设计

    在分析 QNX 设备 驱动程序体系结构和Modbus 协议的基础上,提出 QNX 操作系统串行接口 设备
    发表于12-13 17:11 33次下载

    QNX实时操作系统及应用分析

    QNX 实时 操作系统的发展历程、主要特点、最新技术和应用领域 进行了概括性描述,对于 QNX嵌入式用户界面和
    发表于12-13 17:12 34次下载
    <b class='flag-5'>QNX</b><b class='flag-5'>实时</b><b class='flag-5'>操作系统</b>及应用分析

    基于QNX实时操作系统及应用分析

    基于 QNX 实时 操作系统及应用分析
    发表于10-30 14:53 12次下载
    基于<b class='flag-5'>QNX</b><b class='flag-5'>实时</b><b class='flag-5'>操作系统</b>及应用分析

    Linux系统网络驱动程序编写

    驱动程序 编写一.Linux 系统 设备 驱动程序概述 1.1 Linux 设备
    发表于11-07 10:40 0次下载