arm7(S3C44B0X)键盘中断驱动程序

 1. uClinux-dist/linux-2.4.x/drivers/char/led.h

#define LED_MAGIC 'k'

#define LED1 _IO (LED_MAGIC, 1)
#define LED4 _IO (LED_MAGIC, 4)
#define LED5 _IO (LED_MAGIC, 5)
#define LED6 _IO (LED_MAGIC, 6)
#define LED7 _IO (LED_MAGIC, 7)

#define TURNON  0
#define TURNOFF 1

static int led_open (struct inode *inode, struct file *file);
static int led_release (struct inode *inode, struct file *file);
int led_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
void led_interrupt(int irq, void *dev_id, struct pt_regs *regs);

2. uClinux-dist/linux-2.4.x/drivers/char/led.c

#include <linux/module.h>
#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/fs.h>

#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/mach/irq.h>
#include <asm/arch/irqs.h>
#include <asm/uaccess.h>
#include <asm/irq.h>

#include "led.h"

#define LED_NR 2

MODULE_LICENSE ("GPL");

int led_major = 254;
int state[LED_NR];

struct led_local {
    unsigned long eint;
    void (*interrupt)(int irq, void *dev_id, struct pt_regs *regs);
    unsigned long sa;
    char *device;
};

struct led_local led_local[LED_NR] = {
    {S3C44B0X_INTERRUPT_EINT0, led_interrupt, SA_INTERRUPT, "led4"},
    {S3C44B0X_INTERRUPT_EINT1, led_interrupt, SA_INTERRUPT, "led5"},
//  {S3C44B0X_INTERRUPT_EINT4567, led_interrupt, SA_INTERRUPT, "led6"},
//  {S3C44B0X_INTERRUPT_EINT4567, led_interrupt, SA_INTERRUPT, "led7"}
};

static int led_open (struct inode *inode, struct file *file)
{
    printk (KERN_INFO "Hey! device opened/n");
    return 0;
}

static int led_release (struct inode *inode, struct file *file)
{
    printk (KERN_INFO "Hmmm! device closed/n");
    return 0;
}

void led_manager(int arg, int nr)
{
    if (arg == 0) {
        printk (KERN_INFO "Turn on LED%d/n", nr);
        outb(inb(S3C44B0X_PDATE) & ~(1 << (nr - 1)), S3C44B0X_PDATE);
    } else if (arg == 1) {
        printk (KERN_INFO "Turn off LED%d/n", nr);
        outb(inb(S3C44B0X_PDATE) | (1 << (nr - 1)), S3C44B0X_PDATE);
    } else
        printk (KERN_INFO "Wrong arg/n");
}

int led_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
    int ret = 0;
    int nr = _IOC_NR(cmd);
    led_manager(arg, nr);

    return ret;
}

struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .open    = led_open,
    .release = led_release,
    .ioctl = led_ioctl,
};

void led_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
    printk (KERN_WARNING"led_interrupt device = %s /n", (char*)dev_id);
    if (irq == S3C44B0X_INTERRUPT_EINT0)
        led_manager((++state[0])%2, 4);
    else if (irq == S3C44B0X_INTERRUPT_EINT1)
        led_manager((++state[1])%2, 5);
    else
        printk (KERN_WARNING"wrong irq: %d", irq);
}

static int __init led_init (void)
{
    int result, i;

    request_region(S3C44B0X_PCONE, 12, "led");
    result = register_chrdev(led_major, "led", &led_fops);
    if (result<0) {
        printk (KERN_WARNING "led: can't get major number %d/n", led_major);
        return result;
    }
    outl(0x00025569, S3C44B0X_PCONE);
    outb((inl(S3C44B0X_PDATE) & 0x06), S3C44B0X_PDATE);
    printk (KERN_INFO "led_ioctl driver done/n");


    for (i = 0; i < LED_NR; i ++) {
        result = request_irq(led_local[i].eint, led_local[i].interrupt,
                             led_local[i].sa, led_local[i].device, led_local[i].device);
        if (result) {
            printk(KERN_INFO "led: can't get assigned irq %i/n", led_local[i].eint);
        } else
            printk(KERN_INFO "led: get assigned irq %i/n", led_local[i].eint);
        enable_irq(led_local[i].eint);
    }
    printk(KERN_INFO "S3C44B0X_PCONG=0x%x/n", inw(S3C44B0X_PCONG));
    // 将多功能端口G设置为中断功能
    outw(0xffff, S3C44B0X_PCONG);
    printk(KERN_INFO "S3C44B0X_PCONG=0x%x/n", inw(S3C44B0X_PCONG));

    return 0;
}

static void __exit led_exit (void)
{
    release_region(S3C44B0X_PCONE, 12);
    unregister_chrdev(led_major, "led");
    printk (KERN_INFO "led_ioctl cleaned up/n");
}

module_init (led_init);
module_exit (led_exit);

3. 输出

# more /proc/interrupts
  3:        111   s3c44b0_uart_tx
  7:         20   s3c44b0_uart_rx
  8:        567   timer
 22:          0   ads7843_ts
 23:          1   cs89x0
 24:          0   led5
 25:          0   led4
Err:          0
# led_interrupt device = led5
Turn off LED5
led_interrupt device = led5
Turn on LED5
led_interrupt device = led5
Turn off LED5
# more /proc/interrupts
  3:        152   s3c44b0_uart_tx
  7:         22   s3c44b0_uart_rx
  8:       1365   timer
 22:          0   ads7843_ts
 23:          1   cs89x0
 24:          3   led5
 25:          0   led4
Err:          0
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值