- 论坛徽章:
- 0
|
昨天移植了ADC驱动,但内核启动过程中会崩掉。
看内核警告应该是 ioremap处出现了空指针(我是这么判断的。。),但我看不出来。
麻烦高手指点一二~感激不尽~
以下是错误信息:
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c0004000
[00000000] *pgd=00000000
Internal error: Oops: 805 [#1]
last sysfs file:
Modules linked in:
CPU: 0 Not tainted (2.6.32.46 #1
PC is at adc_init+0x78/0xb4
LR is at __arm_ioremap_pfn+0x120/0x138
pc : [<c0019ec0>] lr : [<c00365bc>] psr: a0000013
sp : c3823fb0 ip : 00000000 fp : 00000000
r10: 00000000 r9 : 00000000 r8 : 00000000
r7 : 00000000 r6 : 00000000 r5 : c0022680 r4 : c0443d34
r3 : 00000000 r2 : c486e004 r1 : ffffffe0 r0 : c0400384
Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
Control: c000717f Table: 30004000 DAC: 00000017
Process swapper (pid: 1, stack limit = 0xc3822270)
Stack: (0xc3823fb0 to 0xc3824000)
3fa0: c0019e48 c002f37c c0019e48 00000000
3fc0: c040dbe0 c040dbe0 c00224c4 c0022680 00000000 00000000 00000000 00000000
3fe0: 00000000 c00083fc 00000000 00000000 00000000 c0030868 11cc37dc 33ec33cc
[<c0019ec0>] (adc_init+0x78/0xb4) from [<c002f37c>] (do_one_initcall+0x5c/0x1bc)
[<c002f37c>] (do_one_initcall+0x5c/0x1bc) from [<c00083fc>] (kernel_init+0xa0/0x1)
[<c00083fc>] (kernel_init+0xa0/0x11 from [<c0030868>] (kernel_thread_exit+0x0/0)
Code: ea000007 e2802004 e3a03000 e59f0030 (e5832000)
---[ end trace 0cab6b11a4649c09 ]---
这个是驱动源码:- #include <linux/errno.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/init.h>
- #include <linux/serio.h>
- #include <linux/delay.h>
- #include <linux/miscdevice.h>
- #include <linux/clk.h>
- #include <linux/wait.h>
- #include <linux/irq.h>
- #include <linux/sched.h>
- #include <asm/io.h>
- #include <asm/irq.h>
- #include <asm/uaccess.h>
- #include <plat/regs-adc.h>
- #define DEVICE_NAME "adc"
- static void __iomem *base_addr;
- typedef struct {
- wait_queue_head_t wait;
- int channel;
- int prescale;
- }ADC_DEV;
- DECLARE_MUTEX(ADC_LOCK);
- static ADC_DEV adc_dev;
- static volatile int ev_adc = 0;
- static int adc_finish=0;
- static int owned_adc=0;
- static int adc_data;
- static struct clk *adc_clock;
- #define ADCCON (base_addr + S3C2410_ADCCON) //ADC control
- #define ADCTSC (base_addr + S3C2410_ADCTSC) //ADC touch screen control
- #define ADCDLY (base_addr + S3C2410_ADCDLY) //ADC start or Interval Delay
- #define ADCDAT0 (base_addr + S3C2410_ADCDAT0) //ADC conversion data 0
- #define ADCDAT1 (base_addr + S3C2410_ADCDAT1) //ADC conversion data 1
- #define ADCUPDN (base_addr + 0x14) //Stylus Up/Down interrupt status
- /* ADCCON寄存器设置 */
- #define PRESCALE_DIS (0 << 14) //预分频禁止
- #define PRESCALE_EN (1 << 14) //预分频使能
- #define PRSCVL(x) ((x) << 6) //预分频系数,0~255之间
- #define ADC_INPUT(x) ((x) << 3) //设置模拟信号输入频道
- #define ADC_START (1 << 0) //通过读取启动ADC
- #define ADC_ENDCVT (1 << 15) //转换结束标志
- /* 设置输入频道为ch,预分频系数为prescale,并使能ADC转换 */
- static void start_adc(int ch,int prescale)
- {
- unsigned int tmp;
- tmp = PRESCALE_EN | PRSCVL(prescale) | ADC_INPUT(ch);
- writel(tmp,ADCCON);
- tmp = readl(ADCCON);
- tmp |= ADC_START;
- writel(tmp,ADCCON);
- }
- static irqreturn_t adc_interrupt(int irq,void *dev_id)
- {
- if(owned_adc){
- adc_data = readl(ADCDAT0)& 0x3ff;
- adc_finish = 1 ;
- wake_up_interruptible(&adc_dev.wait);
- }
- return IRQ_HANDLED;
- }
- static ssize_t adc_read(struct file *filp,char *buffer , size_t count ,loff_t *ppos)
- {
- if(down_trylock(&ADC_LOCK)==0){
- owned_adc = 1;
- start_adc(adc_dev.channel,adc_dev.prescale);
- wait_event_interruptible(adc_dev.wait,adc_finish);
-
- adc_finish = 0;
- copy_to_user(buffer,(char *)&adc_data,sizeof(adc_data));
- owned_adc = 0;
- up(&ADC_LOCK);
- return sizeof(adc_data);
- }
- return -EINVAL;
- }
- static int adc_open(struct inode *inode,struct file *filp)
- {
- int ret;
- init_waitqueue_head(&(adc_dev.wait));
- adc_dev.channel = 0;
- adc_dev.prescale = 0xff;
- ret = request_irq(IRQ_ADC,adc_interrupt,IRQF_SHARED,DEVICE_NAME,&adc_dev);
- if(ret){
- free_irq(IRQ_ADC,&adc_dev);
- return ret;
- }
- return 0;
- }
- static int adc_release(struct inode *inode , struct file *filp)
- {
- free_irq(IRQ_ADC,&adc_dev);
- return 0;
- }
- static struct file_operations adc_fops = {
- .owner = THIS_MODULE,
- .open = adc_open,
- .read = adc_read,
- .release= adc_release,
- };
- static struct miscdevice adc_misc ={
- .minor = MISC_DYNAMIC_MINOR,
- .name = DEVICE_NAME,
- .fops = &adc_fops,
- };
- static int __init adc_init(void)
- {
- int ret;
- printk("func:%s",__FUNCTION__);
-
- adc_clock = clk_get(NULL,"adc");
- if(!adc_clock){
- printk(KERN_ERR "failed to get adc clock source \n");
- return -ENOENT;
- }
- clk_enable(adc_clock);
-
- base_addr = ioremap(S3C2410_PA_ADC,0x20);
- if(base_addr == NULL){
- printk(KERN_ERR "Failed to remap register block\n");
- return -ENOMEM;
- }
- writel(ADCTSC,0);
-
- ret = misc_register(&adc_misc);
-
- printk(DEVICE_NAME "\t :initiated!\n");
- return ret;
- }
- static void __exit adc_exit(void)
- {
- free_irq(IRQ_ADC, &adc_dev);
- iounmap(base_addr);
- if (adc_clock) {
- clk_disable(adc_clock);
- clk_put(adc_clock);
- adc_clock = NULL;
- }
- misc_deregister(&adc_misc);
- }
- EXPORT_SYMBOL(ADC_LOCK);
- module_init(adc_init);
- module_exit(adc_exit);
- MODULE_LICENSE("GPL");
- M
复制代码 |
|