Beckhoff Driver-开源

  • Y9_149285
    了解作者
  • 10.4KB
    文件大小
  • gz
    文件格式
  • 0
    收藏次数
  • VIP专享
    资源类型
  • 0
    下载次数
  • 2022-04-03 19:07
    上传日期
Linux内核级驱动程序,用于访问与Beckhoff CX-1000嵌入式PC一起使用的Beckhoff CX-1100电源的I / O。 这样就可以访问Beckhoff系统的K-Bus和IP-Bus。
beckhoff.tar.gz
  • beckhoff
  • driver
  • bhkldrv.c
    14.3KB
  • Makefile
    608B
  • bhkldrv.h
    5.3KB
  • beckhoff.h
    4KB
  • beckhoff.cpp
    17.1KB
  • Makefile
    213B
内容介绍
/** Beckhoff CX1000 Kernel level driver Copyright (C) 2005 Thermo Electron Corporation This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA http://www.gnu.org/copyleft/lesser.html \file This driver maps the dual port I/O ram to user space. It is not that clever it just grabs the whole block every update. This is a reasonable performance hit and it would be better to modify the driver to deal with only the bits of memory you are interested in. The better solution would be to allow reads of the data directly from the user code with a good spinlock on the update. \author Richard Lemon \date 12/08/04 */ #include <linux/module.h> #include <linux/config.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/ioport.h> #include <linux/reboot.h> #include <asm/io.h rel='nofollow' onclick='return false;'> #include <asm/errno.h rel='nofollow' onclick='return false;'> #include <asm/uaccess.h rel='nofollow' onclick='return false;'> #include <asm/page.h rel='nofollow' onclick='return false;'> #include <asm/atomic.h rel='nofollow' onclick='return false;'> #include <linux/delay.h> #include <linux/slab.h> #include <linux/interrupt.h> #include "bhkldrv.h" // module level defines MODULE_AUTHOR("Richard Lemon"); static int bhkldrv_major = 250; module_param(bhkldrv_major, int, 0); MODULE_DESCRIPTION("Support for Beckhoff CX1000 embedded PC"); MODULE_SUPPORTED_DEVICE("/dev/bhio"); MODULE_LICENSE("Dual BSD/GPL"); // global variables /** Used as a bitmask to signal between kernel timer interrupt and read / write operations bit0 = signals to stop the driver (stop scheduling the tasklet) bit1 = signals that the driver is stopped bit2 = mutex locks the IO memory between tasklet and user IO bit3 = Set if the watchdog is active bit4 = signals new data after write (dirty bit) */ unsigned long io_poll = 0; const unsigned long io_used = 0x1000; //!< Used block length for IO unsigned char* io_new = NULL; //!< User space buffer for Beckhoff data unsigned char* io_old = NULL; //!< Temporary buffer for Beckhoff data void* io_base = NULL; //!< Base address of remapped memory area int bh_interrupt_count = 0; //!< Interrupt count of missed interrupts for tasklet atomic_t bh_watchdog_count; //!< Counter for watchdog timeouts atomic_t bh_watchdog_timeout; //!< Counter for watchdog timeouts //! board map variable initialised with KBus available BH_IO_BOARD_MAP bh_boardmap = {0x01,0x200,0x200,0x00,0x00,0x00}; //! declare work structure void bhkldrv_timedout(void *ptr); DECLARE_WORK(bh_work, bhkldrv_timedout , NULL); //! Tasklet function to handle bottom half processing for timer interrupt void bh_do_tasklet(unsigned long); DECLARE_TASKLET(bh_tasklet, bh_do_tasklet, 0); //! Wait queue to signal when data is ready to be read. DECLARE_WAIT_QUEUE_HEAD(read_wait_queue); // forward function declarations int bhkldrv_open(struct inode *inode, struct file *filp); int bhkldrv_release(struct inode *inode, struct file *filp); int bhkldrv_ioctl(struct inode *node, struct file *filep, unsigned int cmd, unsigned long arg); ssize_t bhkldrv_read(struct file *filp, char *buf, size_t count, loff_t *f_pos); ssize_t bhkldrv_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos); //! Structure to map the available interfaces to the kernel struct file_operations bhkldrv_remap_ops = { open: bhkldrv_open, release: bhkldrv_release, ioctl: bhkldrv_ioctl, read: bhkldrv_read, write: bhkldrv_write, }; /** \brief Runs the device IO loop, called every jiffy \author RDL \date 17/08/04 */ void bhkldrv_timedout(void *ptr) { if (test_bit(0,&io_poll)) // check if we are meant to end { tasklet_schedule(&bh_tasklet); bh_interrupt_count++; // record the interrupt schedule_delayed_work(&bh_work, 2);// add ourselves back into the timer queue } else clear_bit(1, &io_poll); // signal back that we are finished } /** \brief Does the actual read, bottom half style processing so we don't lockup the kernel. \author RDL \date 23/08/04 \bug Need to copy like this */ void bh_do_tasklet(unsigned long something) { if (test_bit(3,&io_poll)) { // watchdog is active atomic_inc( &bh_watchdog_count ); if ( atomic_read(&bh_watchdog_count) > atomic_read(&bh_watchdog_timeout ) ) { //printk("watchdog timed out - reboot in progress\n"); kernel_restart(NULL); return; } } // if the read request is finished then lets get the data if (readb(io_base + GCB_OFFSET + 0x0D) == readb(io_base + GCB_OFFSET + 0x0E)) { if (test_and_set_bit(2,&io_poll) != 0) return; // copy data from IO memcpy_fromio(io_old + GCB_OFFSET, io_base + GCB_OFFSET, sizeof(GCB)); // from io to swap buffer if (bh_boardmap.bUseKBus) { memcpy_fromio(io_old + KBCB_OFFSET, io_base + KBCB_OFFSET, sizeof(BUSCB)); // from io to swap buffer if ( bh_boardmap.nKBusInputBytes ) memcpy_fromio(io_old + KBIP_OFFSET, io_base + KBIP_OFFSET, bh_boardmap.nKBusInputBytes ); // from io to swap buffer if ( bh_boardmap.nKBusOutputBytes ) memcpy_fromio(io_old + KBOP_OFFSET, io_base + KBOP_OFFSET, bh_boardmap.nKBusOutputBytes); // from io to swap buffer } if (bh_boardmap.bUseIPBus) { memcpy_fromio(io_old + IPCB_OFFSET, io_base + IPCB_OFFSET, sizeof(BUSCB)); // from io to swap buffer if ( bh_boardmap.nIPBusInputBytes ) memcpy_fromio(io_old + IPIP_OFFSET, io_base + IPIP_OFFSET, bh_boardmap.nIPBusInputBytes ); // from io to swap buffer if ( bh_boardmap.nIPBusOutputBytes ) memcpy_fromio(io_old + IPOP_OFFSET, io_base + IPOP_OFFSET, bh_boardmap.nIPBusOutputBytes); // from io to swap buffer } if ( test_bit(4,&io_poll) )// buffer dirty copy data to IO { if ((bh_boardmap.bUseKBus) && ( bh_boardmap.nKBusOutputBytes )) memcpy_toio(io_base + KBOP_OFFSET, io_new + KBOP_OFFSET, bh_boardmap.nKBusOutputBytes); // from user to dp ram if ((bh_boardmap.bUseIPBus) && ( bh_boardmap.nIPBusOutputBytes )) memcpy_toio(io_base + IPOP_OFFSET, io_new + IPOP_OFFSET, bh_boardmap.nIPBusOutputBytes); // from user to dp ram } else { // buffer clean, let's sync the output buffer if ( (bh_boardmap.bUseKBus) && ( bh_boardmap.nKBusOutputBytes ) ) memcpy(io_new + KBOP_OFFSET, io_old + KBOP_OFFSET, bh_boardmap.nKBusOutputBytes); // from user to dp ram if ( (bh_boardmap.bUseIPBus) && ( bh_boardmap.nIPBusOutputBytes ) ) memcpy(io_new + IPOP_OFFSET, io_old + IPOP_OFFSET, bh_boardmap.nIPBusOutputBytes); // from user to dp ram // signal that the buffer is ready wake_up_interruptible(&read_wait_queue); } // signal that the buffer is clean clear_bit(4,&io_poll); // ready for user IO again clear_bit(2,&io_poll); //start another run writeb(readb(io_base + GCB_OFFSET + 0x0D) + 1, io_base + GCB_OFFSET + 0x0E); } } /** \brief Open the device; all we have to do here is to up the usage count and set the right fops. \author RDL \date 13/08/04 */ int bhkldrv_open(struct inode *inode, struct file *filp) { unsigned int dev = MINOR(inode->i_rdev); if (dev >= 1) return -ENODEV; filp->f_op = &bhkldrv_remap_ops; // MOD_INC_USE_COUNT; return 0; } /** \brief Close the device; all we have to do here is to decrement the usage count. \author RDL \date 13/08/04 */ int bhkldrv_release(struct inode *inode, struct fi
评论
    相关推荐
    • 嵌入式linux嵌入式linux嵌入式linux嵌入式linux嵌入式linux
      嵌入式linux嵌入式linux嵌入式linux嵌入式linux嵌入式linux
    • 嵌入式linux 基础
      从最初的linux的安装到深入,这本书从基础开始,让我们慢慢的让识linux。对于我们用贯了window,而用linux是不习惯的,而这本书可以让我们慢慢的习惯linux
    • 嵌入式linux 学习
      嵌入式linux 开发学习,linux下的uboot,文件系统,驱动介绍。
    • 嵌入式LINUX教程
      嵌入式LINUX教程,作为初学者教程很受欢迎
    • 嵌入式linux文档
      15份关于嵌入式linux内核和移植的文档。
    • 嵌入式linux
      本光盘为《嵌入式Linux应用开发详解》一书的配套光盘.本软件系统包括本书部分例子程序的源代码和3个实际的样例程序。 本光盘目录结构及说明如下: /demo **本书各章部分例子程序源代码 /examples **样例程序的...
    • 嵌入式linux
      介绍嵌入式linux系统的应用 基础教程
    • 嵌入式linux试验
      嵌入式linux试验,有需要的下吧,呵呵
    • 嵌入式Linux开发
      嵌入式系统概述; Linux系统编程简介; Linux应用程序设计; 嵌入式Linux环境构建; 嵌入式Linux应用开发;
    • 嵌入式linux教程
      嵌入式linux教程, 很不错的教材,配套辅助使用的。