一片冰心在玉壶

那时我们有梦,关于文学,关于爱情,关于穿越世界的旅行, 如今我们深夜饮酒,杯子碰到一起,都是梦破碎的声音. 交往都是初逢,爱情都在心里,往事都在梦中, 希望都带着注释,信仰都带着呻吟. 总有善意的光逃避现世的繁琐而寻找片刻的安宁, 也许,就是你凝视这里的眼睛

博客园 首页 联系 订阅 管理

第一次在X86下写LINUX驱动,具体来说应该是IO驱动。X86的IO是独立编址的。所以用OUTB和INB直接操作IO地址就可以。这点跟ARM等其它CPU不一样。。

数据采集采用DMA的传输方式。。

2.4下可调的调式代码如下:

 

#ifndef __KERNEL__ 
        
#define __KERNEL__ 
#endif 
#ifndef MODULE 
        
#define MODULE 
#endif 
#include 
<linux/init.h> 
#include 
<linux/module.h> 
#include 
<linux/kernel.h> 
#include 
<linux/types.h>   /* size_t */
#include 
<linux/fs.h>      /* file_operation */
#include 
<asm/uaccess.h>   /* copy_to_user, copy_from_user */
#include
<asm/io.h>
#include
<asm/dma.h>
#define DRIVER_NAME "myPump"
#define DMA_BUFFER_SIZE 1024
#define PUMP_ADDRESS 0x308
#define ADBase       0x300     /*ADT采集板基地址*/
static unsigned char IO =0xFF;
static char status[20]="abcdefg ni hao";
static int myPump_Major = 0/* Driver Major Number */
static unsigned char IT[3]={0xFF,0xFF,0xFF};
static short DA[4]={0,0,0,0};
static void DASentOut();
static short *dma_buffer;
static int     Add[16];
static short      ADC[16];
static short      ADM;
static short      AD[10][16],ADSS[10][16];
static short      ADFast[16];
static short  st=0;//测10组数。DMA读1024*2个字节读10次
static unsigned int AD_IRQ=0x77;
static void int_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
{
  register 
int  i;
  st
++;

  
if(st>9)
    {
    memcpy(ADSS,AD,
320);
    st 
= 0;
    }
  memset(Add,
0,64);
  memset(ADC,
0,32);
  
for(i=0;i<DMA_BUFFER_SIZE;i++)
     { ADM
=(dma_buffer[i]>>12)&0x0f;
       Add[ADM]
+=dma_buffer[i]&0x0fff;
       ADC[ADM]
++;
     }
  
for(i=0;i<16;i++)
  
if(ADC[i]>0)
    {  ADFast[i]
=(int)(Add[i]/ADC[i]);
       AD[st][i]
=ADFast[i];
    }
  
else
    { AD[st][i]
=0;
    }
  outb(inb(ADBase
+5)&0xfd,ADBase+5);
  outb(
0x20,0xa0);
  outb(
0x20,0x20);
}

static ad_dma_start(int channel,int mode,unsigned char *dma_buffer,unsigned int count)
{
    unsigned 
long flags;
    flags 
= claim_dma_lock();
    disable_dma(channel);
    clear_dma_ff(channel);
    set_dma_mode(channel,mode);
    set_dma_addr(channel,virt_to_bus(dma_buffer));
    set_dma_count(channel,count);
    outb(
0xf0,ADBase+3);
    outb(inb(ADBase
+4)|0x70,ADBase+4);
    outb((((inb(ADBase
+6))&0xC0)|0x0C),ADBase+6);
    enable_dma(channel);

}
static int myPump_open(struct inode *inode, struct file *filp)
{
    MOD_INC_USE_COUNT;
    
  
//  dma_buffer = (short*)__get_dma_pages(GFP_KERNEL,get_order(DMA_BUFFER_SIZE*2));
    
//request_irq(AD_IRQ,int_interrupt,0,DRIVER_NAME,myPump_Major);    
    
//request_dma(3,DRIVER_NAME);
  
//  ad_dma_start(3,DMA_MODE_READ,dma_buffer,1024*2);
    return 0;
}
static int myPump_release(struct inode *inode, struct file *filp)
{
       MOD_DEC_USE_COUNT;
       free_dma(
3);
       free_irq(AD_IRQ,myPump_Major);    
       
if(dma_buffer)
       {
           free_pages((unsigned 
long)dma_buffer,get_order(DMA_BUFFER_SIZE));
       }
       
return 0;
}
static ssize_t myPump_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
    
   
// status = inb(PUMP_ADDRESS);
// printk(KERN_ALERT "Rd, The fucking Rt\n"); 
    
//outb(0xFE,ADBase+8);
//    TestShow();
    copy_to_user(buf,ADSS,count);
    
    
return 0;
}
static ssize_t myPump_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
   
// unsigned char status;
//    get_user(status,(char *)buf)
    char strt;
    
int lsb=0,msb=0;
     
int i;
    copy_from_user(status,buf,count);
    memcpy(DA,
&status[1],8);
    
switch(status[0])
    {
        
case 0x01://SendPump
            outb(status[1],PUMP_ADDRESS);
            
break;
        
case 0x02://SendDa;        
         outb(inb(ADBase+4)|0x80,ADBase+4);
         
for(i=0;i<4;i++)
         {   lsb
=DA[i]&0xff;
             msb
=(DA[i]/256)&0x0f;
             outb(msb
+(i)*16,ADBase+2);
             outb(lsb,ADBase
+1);
         }
         inb(ADBase
+2);
            
break;
    }
/*    int lsb=0,msb=0;
     int i;
    
    if(IT[0]&0x08)  
   {  IT[0]=IT[0]&0xf7;
      outb(IT[0],0x308);
   }
    outb(0xfb,PUMP_ADDRESS);

    short DA[4]={4000,4000,4000,4000};
     outb(inb(ADBase+4)|0x80,ADBase+4);
         for(i=1;i<5;i++)
         {   lsb=DA[i]&0xff;
             msb=(DA[i]/256)&0x0f;
             outb(msb+(i-1)*16,ADBase+2);
             outb(lsb,ADBase+1);
         }
         inb(ADBase+2);
*/
    
//     outb(0xFF,ADBase+8);
         return 0;
}
static int myPump_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
  printk(KERN_ALERT 
"Hello,CTRIO init open \n"); 
  DA[
0]=cmd;DA[1]=cmd;DA[2]=cmd;DA[3]=cmd;
  DASentOut();
  
return 1;
}
static struct file_operations myPump_fops = {
       owner: THIS_MODULE,
       write: myPump_write,
       read: myPump_read,
       ioctl: myPump_ioctl,
       open: myPump_open,
       release: myPump_release,
};
static int myPump_init(void

        printk(KERN_ALERT 
"Hello, The fucking crazy world\n"); 
        myPump_Major 
= register_chrdev(240, DRIVER_NAME, &myPump_fops);
    
//    request_region(ADBase, 16, DRIVER_NAME);
     outb(0x88,ADBase+11);
     DASentOut();
     outb(
0xff,ADBase+8);
     outb(
0xff,ADBase+9);
     outb(
0xF0,ADBase+10);
 
// IO[2]=inportb(ADBase+10);
        return 0


static void myPump_exit(void

        printk(KERN_ALERT 
"Bye, The fucking crazy world!\n"); 

static void DASentOut()
{
    
int lsb=0,msb=0;
    
int i;
    outb(inb(ADBase
+4)|0x80,ADBase+4);
    
for(i=0;i<4;i++)
    {   lsb
=DA[i]&0xff;
        msb
=(DA[i]/256)&0x0f;
        outb(msb
+(i)*16,ADBase+2);
        outb(lsb,ADBase
+1);
    }
    inb(ADBase
+2);
}
module_init(myPump_init); 
module_exit(myPump_exit); 

MODULE_LICENSE(
"GPL"); 
MODULE_AUTHOR(
"albcamus <sankye@163.com>");

功能:控制泵的运行,数据采集。。。。

还有点问题:DMA传完后处理的中断1S才发生一次。。不是设置好的100MS一次。。

 

posted on 2011-07-06 08:54  Sankye  阅读(421)  评论(0编辑  收藏  举报