移植LINUX的外围设备驱动到QNX系统中

花了半年时间在QNX系统上,这是一个RTOS,这个系统是高安全级别的系统,在核物理站/天文空间站/电站/地铁/交通运输(飞机/汽车/地铁)等工业系统领域占有70%以上的市场份额。

背景 :本文将我个人在QNX上移植内核和开发驱动以及应用程序的部分经验记录在此,因公司商业机密,部分源码不便公开。我会框架性的讲解开发思路。为了简化文章复杂性,我只讨论相同板子的平台驱动转移,我手中是at91sam9260-ek的板子。外部设备是公司硬件部单独添加的。
目的 :利用已有的Linux驱动,简化QNX的驱动编写。
大致思路 :Linux的驱动是基于模块的,每个驱动作为内核的扩展放进内存中,QNX的驱动就是一个进程,需要将模块改为一个应用程序。调整内核与驱动的通信机制。

以RTC驱动为例子:
Linux的驱动开发框架为
1.填充read/write/ioctl/probe等驱动回调函数,设置对应的接口。
static  struct file_operations rtc8025_fops = {
    .owner   = THIS_MODULE,
    .open    = rtc_open,
    .release = rtc_release,
    .read    = rtc_read,
    .write   = rtc_write,
    .ioctl   = rtc_ioctl,
};
2.编写每个部分的硬件相关代码。以write为例:
static ssize_t rtc_write( struct file *filp, __user  const  char  *buf,
                         size_t len,loff_t *ppos){
     char buff[16];
    VR_TIME *tm;

    tm = kmalloc( sizeof(VR_TIME),GFP_KERNEL);
     if ( NULL == tm ){
        printk("Memory error!\n");
         return -1;
    }
    
     if ( copy_from_user(buff, buf, len) )
         return -EFAULT;
    buff[len] = '\0';
    
    set_time_value(tm, buff);
    set_sys_time(tm);
    kfree(tm);

     return len;
}
3.注册设备的initial接口函数与exit接口函数。
static __init  int rtc8025_init( void){
     int ret;

    printk("%s Driver Version: %s\n", DRIVER_NAME, VERSION);
    ret = register_chrdev(major,DRIVER_NAME,&rtc8025_fops);
     if ( ret < 0 ){
        printk("unable to register %s\n",DRIVER_NAME);
         return ret;
    }

    init_gpio();
    msleep(10);
    init_rtc();

     return 0;
}

static __exit  void rtc8025_exit( void){
    i2c_stime(0xe0, 0x20);
    i2c_stime(0xf0, 0);
    i2c_stime(0x70, 0x00);
    unregister_chrdev(major, DRIVER_NAME);
    printk("%s unregister!\n", DRIVER_NAME);
}

module_init(rtc8025_init);
module_exit(rtc8025_exit);

其他具体实现就不在这里描述了。
原文参考自web开发网:http://www.software8.co/wzjs/
为了将原有的Linux驱动移植到QNX上,需要改动read/write以及ioctl的函数接口参数。并将与Linux内核相关的函数去掉(通常不会在QNX里面用到)以read函数代码为例:

size_t rtc_read( char *buf, size_t len,  int *ppos){
    VR_TIME *tm = (VR_TIME *)buf;
     static unsigned  char tmp = 0;
    tmp = i2c_rtime(0x00) & 0x7f;     tm->second = BCD2DEC(tmp);
    tmp = i2c_rtime(0x10) & 0x7f;      tm->minute = BCD2DEC(tmp);
    tmp = i2c_rtime(0x20) & 0x3f;      tm->hour   = BCD2DEC(tmp);
    tmp = i2c_rtime(0x40) & 0x3f;      tm->day    = BCD2DEC(tmp);
    tmp = i2c_rtime(0x50) & 0x1f;      tm->month  = BCD2DEC(tmp);
    tmp = i2c_rtime(0x60);             tm->year   = BCD2DEC(tmp)+ 1920;
     return 0;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值