三星的S5PV210 GPIO中断--寄存器版

S5PV210 是一款三星的cortex-A8系列的处理器,不知什么原因,听说已经停产了,市面上应该都是以前生产的库存品吧。

程序中使用了7个GPIO作为外部中断,奇怪的是在清除中断标志的位置是在获取值之前,因为这个还调试了很久,在此记录一下吧。

     //奇怪的是这里只能先清除在取值,之前尝试过取值后在清除,却造成了无法进入中断中

        *((unsigned long*)(addr_VIC0_base+VIC0ADDRESS)) = 0;

如下为程序

#include   #include   #include   #include   #include   #include   #include   #include   #include   #include   #include #include #include #include #include #include #include #include #include #include #include //switch cmd define#define    MAGIC                       0x01#define    GET_STATUS                  _IOR(MAGIC,0x60,unsigned char)//physical address(gph1)#define GPH1_REGISTER    0xE0200C20#define GPH1_CON         0x00//physical address(gph2)#define GPH2_REGISTER    0xE0200C40#define GPH2_CON         0x00#define EXT_INT_CON      0xE0200E00#define EXT_INT_1_CON    0x04#define EXT_INT_2_CON    0x08#define EXT_INT_MASK      0xE0200F00#define EXT_INT_1_MASK    0x04#define EXT_INT_2_MASK    0x08#define EXT_INT_PEND      0xE0200F40#define EXT_INT_1_PEND    0x04#define EXT_INT_2_PEND    0x08#define VIC0_base         0xF2000000#define VIC1_base         0xF2100000#define VIC2_base         0xF2200000#define VIC3_base         0xF2300000#define VIC0VECTADDR      0x100#define VIC0ADDRESS       0xf00#define VIC0INTSELECT     0x0c#define VIC0INTENABLE     0x10#define VIC0IRQSTATUS     0x0#define VIC0INTENCLEAR    0x14//virtual adress(gph1)unsigned long addr_gph1 = 0;//virtual adress(gph2)unsigned long addr_gph2 = 0;unsigned long addr_EXT_INT_CON = 0;unsigned long addr_EXT_INT_MASK = 0;unsigned long addr_EXT_INT_PEND = 0;unsigned long addr_VIC0_base = 0;unsigned long addr_Exception_Vector = 0;#define DEVICENAME "switch"#define CLASSNAME  "class"static dev_t devno;  static struct cdev cdev;  static struct class* switch_class;  static struct device* switch_device;  int nprintFlag = 0;int nnowChannel = 0;/*********************************************************************photoelectric switchs:switch 1 :    gph2_4         //position 1switch 2 :    gph2_2         //position 2switch 3 :    gph2_3         //position 3switch 4 :    gph2_1         //position 4switch 5 :    gph1_3         //position 5switch 6 :    gph1_6         //position 1 protect motorswitch 7:     gph1_7         //position 5 protect motor**********************************************************************/void clear_int_pend(void);void intc_init(void);void irq_handler(void);void IRQ_handle(void);void system_initexception( void);//中断初始化static int switch_open(struct inode *inode, struct file *file){  //  system_initexception();  //外部中断对应的GPIO模式设置*((unsigned long*)(addr_gph1+GPH1_CON)) |=(0xff00f<<12); //配置为外部中断模式EXT_INT[11]、EXT_INT[14]、EXT_INT[15]*((unsigned long*)(addr_gph2+GPH2_CON)) |=(0xffff<<4);  //EXT_INT[20]、EXT_INT[18]、EXT_INT[19]、EXT_INT[17]//设置中断触发模式 高电平触发*((unsigned long*)(addr_EXT_INT_CON+EXT_INT_1_CON)) |=(0x001<<12|0x001<<24|0x001<<28);     //EXT_INT_1_CON[3]、EXT_INT_1_CON[6]、EXT_INT_1_CON[7]*((unsigned long*)(addr_EXT_INT_CON+EXT_INT_2_CON)) |=(0x001<<16|0x001<<8|0x001<<12|0x001<<4);  //EXT_INT_2_CON[4]、EXT_INT_2_CON[2]、EXT_INT_2_CON[3]、EXT_INT_2_CON[1]//中断允许*((unsigned long*)(addr_EXT_INT_MASK+EXT_INT_1_MASK)) &= ~ (0x1<<3|0x1<<6|0x1<<7);    //外部中断允许*((unsigned long*)(addr_EXT_INT_MASK+EXT_INT_2_MASK)) &= ~ (0x1<<4|0x1<<2|0x1<<3|0x1<<1);*((unsigned long*)(addr_EXT_INT_PEND+EXT_INT_1_PEND)) |= (0x1<<3|0x1<<6|0x1<<7);*((unsigned long*)(addr_EXT_INT_PEND+EXT_INT_2_PEND)) |= (0x1<<4|0x1<<2|0x1<<3|0x1<<1);intc_init();return 0;}void clear_int_pend(void){//清挂起*((unsigned long*)(addr_EXT_INT_PEND+EXT_INT_1_PEND)) |= (0x1<<3|0x1<<6|0x1<<7);*((unsigned long*)(addr_EXT_INT_PEND+EXT_INT_2_PEND)) |= (0x1<<4|0x1<<2|0x1<<3|0x1<<1);}static int switch_close(struct inode *inode, struct file *file){  *((unsigned long*)(addr_VIC0_base+VIC0INTENCLEAR)) |=(1<<11|1<<14|1<<15|1<<20|1<<18|1<<19|1<<17);// VIC0INTENCLEAR |= (1<<11|1<<14|1<<15|1<<20|1<<18|1<<19|1<<17);return 0;  }  static ssize_t switch_ioctl(struct file *file, unsigned int cmd, unsigned long argc){  unsigned long data=-1;int err;int gph1_3 =0;int gph2_1 =0;int gph2_3 =0;int gph2_2 =0;int gph2_4 =0;int gph1_6 =0;int gph1_7 =0;int reg1;int reg2;if(GET_STATUS != cmd) printk("invalid command id for %s\n",DEVICENAME);else{//奇怪的是这里只能先清除在取值,之前尝试过取值后在清除,却造成了无法进入中断中*((unsigned long*)(addr_VIC0_base+VIC0ADDRESS)) = 0;*((unsigned long*)(addr_EXT_INT_PEND+EXT_INT_1_PEND)) |= (0x1<<3|0x1<<6|0x1<<7);*((unsigned long*)(addr_EXT_INT_PEND+EXT_INT_2_PEND)) |= (0x1<<4|0x1<<2|0x1<<3|0x1<<1);*((unsigned long*)(addr_EXT_INT_PEND+EXT_INT_1_PEND)) |= (0x1<<3|0x1<<6|0x1<<7);*((unsigned long*)(addr_EXT_INT_PEND+EXT_INT_2_PEND)) |= (0x1<<4|0x1<<2|0x1<<3|0x1<<1);reg1=*((unsigned long*)(addr_EXT_INT_PEND+EXT_INT_1_PEND));reg2=*((unsigned long*)(addr_EXT_INT_PEND+EXT_INT_2_PEND));gph1_3 = ((reg1>>3)&0x01);gph2_1 = ((reg2>>1)&0x01);gph2_3 = ((reg2>>3)&0x01);gph2_2 = ((reg2>>2)&0x01);gph2_4 = ((reg2>>4)&0x01);gph1_6 = ((reg1>>6)&0x01);//protect motorgph1_7 = ((reg1>>7)&0x01);//protect motordata = gph1_3 << 0 | gph2_1 << 1 | gph2_3 << 2 | gph2_2 << 3 | gph2_4 << 4 | gph1_6 << 5 |gph1_7 << 6;//add protect motor}err = put_user(data, (int *)argc);return err;}void intc_init(void){*((unsigned long*)(addr_VIC0_base+VIC0ADDRESS)) = 0;*((unsigned long*)(addr_VIC0_base+VIC0INTENCLEAR)) |=(1<<11|1<<14|1<<15|1<<20|1<<18|1<<19|1<<17);*((unsigned long*)(addr_VIC0_base+VIC0INTSELECT)) &= ~(1<<11|1<<14|1<<15|1<<20|1<<18|1<<19|1<<17);  //选择中断类型为IRQ//设置EXT_INT[11]~EXT_INT[20]对应的中断服务程序的入口地址16-20共用一个*((unsigned long*)(addr_VIC0_base+VIC0VECTADDR+4*11))= (unsigned)switch_ioctl;//中断函数入口*((unsigned long*)(addr_VIC0_base+VIC0VECTADDR+4*14))= (unsigned)switch_ioctl;*((unsigned long*)(addr_VIC0_base+VIC0VECTADDR+4*15))= (unsigned)switch_ioctl;*((unsigned long*)(addr_VIC0_base+VIC0VECTADDR+4*16))= (unsigned)switch_ioctl;*((unsigned long*)(addr_VIC0_base+VIC0INTENABLE)) |= (1<<11|1<<14|1<<15|1<<16);}struct file_operations switch_ops = {  .open        =  switch_open,  .release     =  switch_close,  .unlocked_ioctl  =  switch_ioctl,  };  static int __init switch_init(void){  int ret;cdev_init(&cdev,&switch_ops);  cdev.owner = THIS_MODULE;  ret = alloc_chrdev_region(&devno, 0, 1,DEVICENAME);  if(ret){  printk(KERN_ERR "alloc char device region faild!\n");  return ret;  }  ret = cdev_add(&cdev, devno, 1);  if(ret){  printk(KERN_ERR "add char device faild!\n");  goto add_error;  }  // 在sys/class下创建名为switch_class的类switch_class = class_create(THIS_MODULE, CLASSNAME);  if(IS_ERR(switch_class)){  printk(KERN_ERR "create class error!\n");  goto class_error;  }//在 名为switch_class的类创建XP_switch设备switch_device = device_create(switch_class, NULL, devno, NULL, DEVICENAME);  if(IS_ERR(switch_device)){  printk(KERN_ERR "create buttons device error!\n");  goto device_error;  }  //physical adress to virtual adressaddr_gph1 = (unsigned long)ioremap(GPH1_REGISTER,0x10);addr_gph2 = (unsigned long)ioremap(GPH2_REGISTER,0x10);addr_EXT_INT_CON = (unsigned long)ioremap(EXT_INT_CON,0x10);addr_EXT_INT_MASK = (unsigned long)ioremap(EXT_INT_MASK,0x10);addr_EXT_INT_PEND = (unsigned long)ioremap(EXT_INT_PEND,0x10);addr_VIC0_base = (unsigned long)ioremap(VIC0_base,0xFFF);//   addr_Exception_Vector = (unsigned long)ioremap(_Exception_Vector,0x20);printk("%s is installed\n",DEVICENAME);return 0;  device_error:  class_destroy(switch_class);  class_error:  cdev_del(&cdev);  add_error:  unregister_chrdev_region(devno,1);  return -ENODEV;  }  void __exit switch_exit(void){  iounmap((void*)addr_gph2);iounmap((void*)addr_gph1);iounmap((void*)addr_EXT_INT_CON);iounmap((void*)addr_EXT_INT_MASK);iounmap((void*)addr_EXT_INT_PEND);iounmap((void*)addr_VIC0_base);//  iounmap((void*)addr_Exception_Vector);device_destroy(switch_class, devno);  class_destroy(switch_class);  cdev_del(&cdev);  unregister_chrdev_region(devno, 1);  printk("%s is uninstalled\n",DEVICENAME);}  module_init(switch_init);  module_exit(switch_exit);  MODULE_LICENSE("GPL");


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部