zcyhansen 发表于 2013-05-03 14:57

加载驱动程序出错Unknown symbol

我在主机编译一个驱动。编译过程没有出错。代码如下:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <asm/gptimers.h>
#include <asm/irq.h>
#include <asm/bfin_simple_timer.h>
#include <asm/bfin-global.h>

#define AUTHOR "Axel Weiss (awe@aglaia-gmbh.de)"
#define DESCRIPTION "simple timer char-device interface for the bf5xx_timers driver"
#define LICENSE "GPL"
#define TIMER_MAJOR 238

#define DPRINTK(fmt, args...) printk(KERN_NOTICE "%s: " fmt, __FUNCTION__ , ## args)
#define DRV_NAME            "bfin_simple_timer"

MODULE_AUTHOR   (AUTHOR);
MODULE_DESCRIPTION(DESCRIPTION);
MODULE_LICENSE    (LICENSE);

#if defined(BF533_FAMILY) || defined(BF537_FAMILY)
#define IRQ_TIMER0    IRQ_TMR0         /*Timer 0 */
#define IRQ_TIMER1    IRQ_TMR1         /*Timer 1 */
#define IRQ_TIMER2    IRQ_TMR2         /*Timer 2 */
#if (MAX_BLACKFIN_GPTIMERS > 3)
#define IRQ_TIMER3    IRQ_TMR3         /*Timer 3 */
#define IRQ_TIMER4    IRQ_TMR4         /*Timer 4 */
#define IRQ_TIMER5    IRQ_TMR5         /*Timer 5 */
#define IRQ_TIMER6    IRQ_TMR6         /*Timer 6 */
#define IRQ_TIMER7    IRQ_TMR7         /*Timer 7 */
#endif
#endif

static unsigned long sysclk = 0;
module_param(sysclk, long, 0);
MODULE_PARM_DESC(sysclk, "actual SYSCLK frequency in Hz. Default: 120000000 = 120 MHz.");

static volatile unsigned long isr_count;
static const struct {
        unsigned short id, bit;
        unsigned long irqbit;
        int irq;
} timer_code = {
        {TIMER0_id,TIMER0bit,TIMER_STATUS_TIMIL0,IRQ_TIMER0},
        {TIMER1_id,TIMER1bit,TIMER_STATUS_TIMIL1,IRQ_TIMER1},
        {TIMER2_id,TIMER2bit,TIMER_STATUS_TIMIL2,IRQ_TIMER2},
#if (MAX_BLACKFIN_GPTIMERS > 3)
        {TIMER3_id,TIMER3bit,TIMER_STATUS_TIMIL3,IRQ_TIMER3},
        {TIMER4_id,TIMER4bit,TIMER_STATUS_TIMIL4,IRQ_TIMER4},
        {TIMER5_id,TIMER5bit,TIMER_STATUS_TIMIL5,IRQ_TIMER5},
        {TIMER6_id,TIMER6bit,TIMER_STATUS_TIMIL6,IRQ_TIMER6},
        {TIMER7_id,TIMER7bit,TIMER_STATUS_TIMIL7,IRQ_TIMER7},
#endif
#if (MAX_BLACKFIN_GPTIMERS > 8)
        {TIMER8_id,TIMER8bit,TIMER_STATUS_TIMIL8,IRQ_TIMER8},
        {TIMER9_id,TIMER9bit,TIMER_STATUS_TIMIL9,IRQ_TIMER9},
        {TIMER10_id, TIMER10bit, TIMER_STATUS_TIMIL10, IRQ_TIMER10},
        {TIMER11_id, TIMER11bit, TIMER_STATUS_TIMIL11, IRQ_TIMER11},
#endif
};

static int timer_ioctl(struct inode *inode, struct file *filp, uint cmd, unsigned long arg){
        int minor = MINOR(inode->i_rdev);
        unsigned long n;
        switch (cmd){
        case BFIN_SIMPLE_TIMER_SET_PERIOD:
                if (arg < 2) return -EFAULT;
                n = ((sysclk / 1000) * arg) / 1000;
                if (n > 0xFFFF) n = 0xFFFF;
                set_gptimer_period(timer_code.id, n);
                set_gptimer_pwidth(timer_code.id, n >> 1);
                printk("timer_ioctl TIMER_SET_PERIOD: arg=%lu, period=%lu, width=%lu\n",
                        arg, n, n>>1);
                break;
        case BFIN_SIMPLE_TIMER_START:
                enable_gptimers(timer_code.bit);
                break;
        case BFIN_SIMPLE_TIMER_STOP:
                disable_gptimers(timer_code.bit);
                break;
        case BFIN_SIMPLE_TIMER_READ:
                *((unsigned long*)arg) = isr_count;
                break;
        default:
                return -EINVAL;
        }
        return 0;
}

static irqreturn_t timer_isr(int irq, void *dev_id)
{
        int minor = (int)dev_id;
#if (MAX_BLACKFIN_GPTIMERS > 8)
        int octet = BFIN_TIMER_OCTET(minor);
        unsigned long state = get_gptimer_status(octet);
        if (state & timer_code.irqbit){
                set_gptimer_status(octet, timer_code.irqbit);
                ++isr_count;
        }
#else
        unsigned long state = get_gptimer_status(0);
        if (state & timer_code.irqbit){
                set_gptimer_status(0,timer_code.irqbit);
                ++isr_count;
        }
#endif
        return IRQ_HANDLED;
}

static int timer_open(struct inode *inode, struct file *filp){
        int minor = MINOR(inode->i_rdev);
        int err = 0;
        if(!sysclk)
          sysclk = get_sclk();
        if (minor >= MAX_BLACKFIN_GPTIMERS) return -ENODEV;
        err = request_irq(timer_code.irq, timer_isr, IRQF_DISABLED, DRV_NAME, (void *)minor);
        if (err < 0){
                printk(KERN_ERR "request_irq(%d) failed\n", timer_code.irq);
                return err;
        }
        set_gptimer_config(timer_code.id, OUT_DIS | PWM_OUT | PERIOD_CNT | IRQ_ENA);
        DPRINTK("device(%d) opened\n", minor);
        return 0;
}

static int timer_close(struct inode *inode, struct file *filp){
        int minor = MINOR(inode->i_rdev);
        disable_gptimers(timer_code.bit);
        free_irq(timer_code.irq, (void*)minor);
        DPRINTK("device(%d) closed\n", minor);
        return 0;
}

int timer_read_proc(char *buf, char **start, off_t offset, int cnt, int *eof, void *data){
        int ret = 0, i;
        for (i=0; i<MAX_BLACKFIN_GPTIMERS; ++i){
                ret += sprintf(buf + ret, "timer %2d isr count: %lu\n", i, isr_count);
        }
        return ret;
}

static ssize_t timer_status_show(struct class *timer_class, char *buf)
{
        char *p;
        unsigned short i;
        p = buf;

        for (i=0; i<MAX_BLACKFIN_GPTIMERS; ++i){
                p += sprintf(p, "timer %2d isr count: %lu\n", i, isr_count);
        }

        return p - buf;
}

static struct proc_dir_entry *timer_dir_entry;
static struct file_operations fops = {
   .owner   = THIS_MODULE,
   .ioctl   = timer_ioctl,
   .open    = timer_open,
   .release = timer_close,
};

static struct class *timer_class;

static CLASS_ATTR(status, S_IRUGO, &timer_status_show, NULL);

int __init timer_initialize(void){
        int minor;
        char minor_name;
        int err;
        err = register_chrdev(TIMER_MAJOR, DRV_NAME, &fops);
        if (err < 0){
                DPRINTK("could not register device %s\n", DRV_NAME);
                return err;
        }
        timer_dir_entry = create_proc_entry(DRV_NAME, 0444, &proc_root);
        if (timer_dir_entry) timer_dir_entry->read_proc = &timer_read_proc;

      timer_class = class_create(THIS_MODULE, "timer");
        if ((err = class_create_file(timer_class, &class_attr_status)) != 0) {
                remove_proc_entry(DRV_NAME, &proc_root);
                unregister_chrdev(TIMER_MAJOR, DRV_NAME);
                return err;
        }
        for (minor = 0; minor < MAX_BLACKFIN_GPTIMERS; minor++) {
                sprintf(minor_name, "timer%d", minor);
                device_create(timer_class, NULL,
                              MKDEV(TIMER_MAJOR, minor), minor_name);
        }
       
        DPRINTK("module loaded\n");
        return 0;
}

void __exit timer_cleanup(void){
        remove_proc_entry(DRV_NAME, &proc_root);
        unregister_chrdev(TIMER_MAJOR, DRV_NAME);
        DPRINTK("module unloaded\n");
}

module_init(timer_initialize);
module_exit(timer_cleanup);


但是当在目标板加载的时候就出现错误了:insmod: cannot insert 'drive.ko': Unknown symbol in module (-1): No such file or directory
通过查找log ,我看到如下的提示:
Jan1 04:15:31 lean user.warn kernel: pwm: Unknown symbol _enable_gptimers
Jan1 04:15:31 lean user.warn kernel: pwm: Unknown symbol _get_gptimer_status
Jan1 04:15:31 lean user.warn kernel: pwm: Unknown symbol _disable_gptimers
Jan1 04:15:31 lean user.warn kernel: pwm: Unknown symbol _set_gptimer_pwidth
Jan1 04:15:31 lean user.warn kernel: pwm: Unknown symbol _set_gptimer_config
Jan1 04:15:31 lean user.warn kernel: pwm: Unknown symbol _set_gptimer_status
Jan1 04:15:31 lean user.warn kernel: pwm: Unknown symbol _set_gptimer_period

请教是什么原因呢》
页: [1]
查看完整版本: 加载驱动程序出错Unknown symbol