s3c44b0的中断(uclinux中断)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chenyefei/article/details/48053359

arm-linux中断驱动程序:                                                             

#include <linux/types.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/string.h>
 
#include <linux/devfs_fs_kernel.h>
 
#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/irq.h>
 
 
//#define S3C44B0X_INTERRUPT_EINT4567   21      //INTPND bit 21
//irq_number defined in arch/riqs.h 这个头文件被arch/irq.h包含
// asm/irq.h头文件中又包含了arch/irq.h头文件
//中断号是指INTPND寄存器对应的各自的位
 
 
#define MY_44B0_EINT    "myextint"
#define MY_44B0_EINT_MAJOR 230
 
 
static char *dev_idledflash=MY_44B0_EINT;
int led_state,timer_state;
 
 
static ssize_t led_flash_read(struct file *filp,char *buf,size_t cout,loff_t *l)
{
        put_user(led_state,buf);
        return 0;
}
 
 
static ssize_t led_flash_write(struct file *filp,const char *buf,size_t count,loff_t *l)
{
        return 0;
}
 
static void led_flash_irq4(int irq,void *dev_idledflash,struct pt_regs *regs)
{
        disable_irq(S3C44B0X_INTERRUPT_EINT4567);
        if(led_state==0)
        {
                printk("led on\n");
                (*(volatile unsigned int *)S3C44B0X_PDATC) |=0xe;
                //S3C44B0X_PDATC and so on register defined in arch/s3c44b0x.h
                led_state=1;
        }else if(led_state==1){
                printk("led off\n");
                (*(volatile unsigned int *)S3C44B0X_PDATC) &=(~0xe);
                led_state=0;
        }
        mdelay(100);
        enable_irq(S3C44B0X_INTERRUPT_EINT4567);
              (*(volatile unsigned int *)S3C44B0X_EXTINPND)=0xf;  //先清零EXTINPND
        (*(volatile unsigned int *)S3C44B0X_I_ISPC) = \           //然后再清零I_ISPC
(1<<S3C44B0X_INTERRUPT_EINT4567);
}
static unsigned long save_pcon;
static unsigned long save_pup;
static unsigned long save_extint;
#define rin_l(a) (*(volatile unsigned int *)a )
static int led_flash_open(struct inode *inode,struct file *filp)
{
        int ret;
        unsigned long flag;
        MOD_INC_USE_COUNT;
if((ret=request_irq(S3C44B0X_INTERRUPT_EINT4567,led_flash_irq4,SA_INTERRUPT,MY_44B0_EINT,dev_idledflash)))
        {
                printk("my_extint led_flash_irq4_init: failed to register IRQ_TIMER1\n");
                free_irq(S3C44B0X_INTERRUPT_EINT4567,dev_idledflash);
                return ret;
        }
        local_irq_save(flag);
        save_pcon=rin_l(S3C44B0X_PCONG);
        (*(volatile unsigned int *)S3C44B0X_PCONG )=save_pcon|(0x3f<<10);
//注意:这里只有567引脚有按键,4没有按键.
        save_pup=rin_l(S3C44B0X_PUPG);
        (*(volatile unsigned int *)S3C44B0X_PUPG )=save_pup&(~(7<<5));//567带上拉
        save_extint=rin_l(S3C44B0X_EXTINT);
        (*(volatile unsigned int *)S3C44B0X_EXTINT )=save_extint&(~(0xff<<20));
//567低电平触发
        local_irq_restore(flag);
        timer_state=1;
        return 0;
}
#define rout_l(a,b) ((*(volatile unsigned int *)a )=b)
static int led_flash_release(struct inode *inode,struct file *filp)
{
        unsigned long flag;
        MOD_DEC_USE_COUNT;
        free_irq(S3C44B0X_INTERRUPT_EINT4567,dev_idledflash);
        local_irq_save(flag);
        rout_l(S3C44B0X_PCONG,save_pcon);
        rout_l(S3C44B0X_PUPG,save_pup);
        rout_l(S3C44B0X_EXTINT,save_extint);
        led_state=0;
        local_irq_restore(flag);
        return 0;
}
static struct file_operations led_flash_fops={
        read:   led_flash_read,
        write:  led_flash_write,
        ioctl:  NULL,
        open:   led_flash_open,
        release: led_flash_release,
};
int __init led_flash_init(void)
{
        int ret;
if((ret=register_chrdev(MY_44B0_EINT_MAJOR,MY_44B0_EINT,&led_flash_fops))!=0){
                printk("registering of" MY_44B0_EINT "is failed\n");
                return ret;
        }
        printk("led_flash driver initialized------------------------OK\n");
        led_state=0;
        return 0;
}
void __exit led_flash_cleanup(void)
{
        free_irq(S3C44B0X_INTERRUPT_EINT4567,dev_idledflash);
        unregister_chrdev(MY_44B0_EINT_MAJOR,MY_44B0_EINT);
        printk("my_extint led_flash driver removed\n");
}
module_init(led_flash_init);
module_exit(led_flash_cleanup);
MODULE_LICENSE("GPL");

驱动测试程序:

#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
 
static int fd =-1;
 
static int stop=0;
static void *comMonitor(void *data)
{
        getchar();
        stop=1;
        return NULL;
}
 
int main(void)
{
        pthread_t th_com;
        void * retval;
        fd=open("/dev/myextint",O_NONBLOCK,0);
        if(fd<0)
        {
                printf("Can't open\n");
                return -1;
        }
        pthread_create(&th_com,NULL,comMonitor,0);
        printf("\nPress Enter key exit!\n");
        while(stop==0)
        {
                 sleep(1);
        }
        pthread_join(th_com,&retval);
        printf("\n");
        close(fd);
}


猜你喜欢

转载自blog.csdn.net/chenyefei/article/details/48053359