기존 이솝 임베디드 포럼의 지식인 서비스가 게시판 형태로 변경되었습니다.
아래 코드는 제가 테스트중에 있는 드라이버이니다. 그런데 이상하게 이 드라이버를 모듈로 등록해서 테스트 할 때는
정상 동작을 했는데, 커널에 포함 시켜서 리눅스를 부팅하면 커널이 멈추는 현상이 발생했습니다.
그래서 하나 하나..지워 가면서 원인을 찾아보니... 인터럽트 등록함수(아래 빨간줄로 표시함)가 들어가면
커널이 멈추더군요...
i = request_irq(LED_CONT_PIN, &interrupt, 0, DEVICE_NAME, NULL);
이 부분 입니다. 혹시 커널에 모듈을 포함해서 컴파일 할 때는 request_irq()함수 말고 다른 것을 사용해야 하나요?
아니면...혹시 보드 초기 설정 부분에서 인터럽트 관련 처리를 할 텐데 그것과 쫑나는 것인가요?
================================== 드라이버 코드 ========================
#define DEVICE_NAME "dev_mknod"
#define GPIO_MAJOR_DEF 194
#define LED_ON 0
#define LED_OFF 1
#define LED_GPIO_DATA_SET 0xFFFFF830
#define LED_GPIO_DATA_CLR 0xFFFFF834
#define LED_GPIO_DATA 0xFFFFF830
#define LED_CONT_PIN AT91_PIN_PB10
int Device_Open = 0;
int status = 0;
unsigned int* LED_DATA = 0;
int ctrlbox_gpio_open(struct inode* inode, struct file* file);
int gpio_release(struct inode* inode, struct file* file);
int gpio_ioctl(struct inode* indode, struct file* file, unsigned int ioctl_num, unsigned long ioctl_param);
int init_gpio(void);
int ctrlbox_gpio_read(struct file* file, char __user* user, size_t size, loff_t* loff);
struct file_operations gpio_fops = {
.open = ctrlbox_gpio_open,
.release = gpio_release,
};
int ctrlbox_gpio_open(struct inode* inode, struct file* file)
{
if(Device_Open)
return -EBUSY;
Device_Open++;
return 0;
}
int gpio_release(struct inode* inode, struct file* file)
{
Device_Open--;
return 0;
}
irqreturn_t interrupt(int irq, void *dev_id)
{
//int i, j;
status = (char)at91_get_gpio_value(AT91_PIN_PB10);
if(status == 0)
{
*(LED_DATA+1) = 0x00000003;
//at91_set_gpio_value(AT91_PIN_PD0, LED_OFF);
printk("%d\n", status);
}
else if(status == 1)
{
*(LED_DATA) = 0x00000003;
//at91_set_gpio_value(AT91_PIN_PD0, LED_ON);
printk("%d\n", status);
}
return IRQ_HANDLED;
}
int init_gpio(void)
{
ssize_t a = 0;
ssize_t i=0;
printk("%d\n", sizeof(ssize_t));
printk("%d\n", sizeof(a));
printk("ControlBox - GPIO init, Function Called\n");
at91_set_gpio_output(AT91_PIN_PD0, LED_ON); // LED ON
at91_set_gpio_output(AT91_PIN_PD1, LED_ON); // LED ON
at91_set_gpio_input(LED_CONT_PIN, 1);
at91_set_deglitch(LED_CONT_PIN, 1);
at91_set_gpio_output(AT91_PIN_PD0, LED_OFF);
at91_set_gpio_output(AT91_PIN_PD1, LED_OFF);
i = request_irq(LED_CONT_PIN, &interrupt, 0, DEVICE_NAME, NULL);
LED_DATA = (unsigned int*)ioremap(LED_GPIO_DATA, 4);
printk("%x\n", (unsigned int)LED_DATA);
if(i)
{
printk("ControlBox - Can't get IRQ \n");
return i;
}
return 0;
}
static int gpio_init_module(void)
{
int ret;
ret = register_chrdev(GPIO_MAJOR_DEF, DEVICE_NAME, &gpio_fops);
if(ret < 0)
{
printk("Sorry not Register");
return ret;
}
ret = init_gpio();
return 0;
}
static void gpio_cleanup_module(void)
{
iounmap(LED_DATA);
//free_irq(LED_CONT_PIN, NULL);
unregister_chrdev(GPIO_MAJOR_DEF, DEVICE_NAME);
}
module_init(gpio_init_module);
module_exit(gpio_cleanup_module);
MODULE_LICENSE("Proprietary");
MODULE_AUTHOR("Somebody");
MODULE_DESCRIPTION("mknod driver");
gpio_init_module() 함수는 실행도 되지 않아요 ㅠㅠ; 위에 말씀드린 것처럼..
i = request_irq(LED_CONT_PIN, &interrupt, 0, DEVICE_NAME, NULL); 이 부분에서 막혀서요 ㅠㅠ
== 아래는 제 부팅 로고 입니다.====
## Booting kernel from Legacy Image at 22000000 ...
Image Name: Linux-2.6.30
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1763620 Bytes = 1.7 MB
Load Address: 70008000
Entry Point: 70008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux............................................................. ................................................... done, booting the kernel.
Linux version 2.6.30 (root@jongju-desktop) (gcc version 4.3.3 (GCC) ) #17 Fri Ma r 9 13:12:22 KST 2012
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
CPU: VIVT data cache, VIVT instruction cache
Machine: Atmel AT91SAM9M10G45-EK
Memory policy: ECC disabled, Data cache writeback
Clocks: CPU 400 MHz, master 133 MHz, main 12.000 MHz
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 32512
Kernel command line: console=ttyS0,115200 root=/dev/mtdblock0 mtdparts=at91_nand :-(root) rw rootfstype=jffs2
NR_IRQS:192
AT91: 160 gpio irqs in 5 banks
PID hash table entries: 512 (order: 9, 2048 bytes)
Console: colour dummy device 80x30
console [ttyS0] enabled
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 128MB = 128MB total
Memory: 126208KB available (3092K code, 241K data, 116K init, 0K highmem)
Calibrating delay loop... 199.47 BogoMIPS (lpj=997376)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 296 bytes
NET: Registered protocol family 16
atmel_tcb: probe of atmel_tcb.0 failed with error -22
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
cfg80211: Calling CRDA to update world regulatory domain
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 4096 (order: 3, 32768 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
TCP reno registered
NET: Registered protocol family 1
hx170dec: dec/pp kernel module. $Revision: 1.9 $
hx170dec: supports 8170 and 8190 hardware
hx170dec: base_port=0x00900000 irq=30
hx170dec: HW ID=0x81701250
hx170dec: Compatible HW found at 0x00900000
IRQ 30/hx170dec: IRQF_DISABLED is not guaranteed on shared IRQs
hx170dec: module inserted. Major = 253
memalloc: 8190 Linear Memory Allocator, $Revision: 1.1 $
memalloc: linear memory base = 0x74000000
memalloc: allocation method: MEMALLOC_BASIC
memalloc: 117727232 bytes (112MB) configured. Check RAM size!
NetWinder Floating Point Emulator V0.97 (double precision)
JFFS2 version 2.2. (NAND) (SUMMARY) Aⓒ 2001-2006 Red Hat, Inc.
msgmni has been set to 246
alg: No test for stdrng (krng)
io scheduler noop registered
io scheduler anticipatory registered (default)
atmel_lcdfb atmel_lcdfb.0: 255KiB frame buffer at 77940000 (mapped at ffa00000)
atmel_lcdfb atmel_lcdfb.0: fb0: Atmel LCDC at 0x00500000 (mapped at c885c000), irq 23
call_init
4
4
ControlBox - GPIO init, Function Called
<== 이 부분 다음에 문제가 되는 인터럽트 함수가 실행이 되는데요.. 커널이 이 부분 다음부터 이상해지고 있습ㄴ디ㅏ.
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c0004000
[00000000] *pgd=00000000
Internal error: Oops: 805 [#1]
Modules linked in:
CPU: 0 Not tainted (2.6.30 #17)
PC is at interrupt+0x54/0x78
LR is at interrupt+0x10/0x78
pc : [<c014143c>] lr : [<c01413f8>] psr: 60000013
sp : c7817e60 ip : c7817eb0 fp : 00000050
r10: 00000003 r9 : c034ade8 r8 : fefff400
r7 : 0000004a r6 : 00000000 r5 : 00000000 r4 : c792c2e0
r3 : 00000003 r2 : 00000000 r1 : c0374fd4 r0 : c030cf26
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
Control: 0005317f Table: 70004000 DAC: 00000017
Process swapper (pid: 1, stack limit = 0xc7816268)
Stack: (0xc7817e60 to 0xc7818000)
7e60: c7817f54 c005dba4 00000000 c034c418 0000004a c034c418 c03462c8 c005f4d8
7e80: fefff000 0000004a 00000001 c002f7bc c0349194 00000003 00000000 00000003
7ea0: 0000004a 60000013 c02fa7b0 c034c438 00000000 c0025050 00000c32 ffffffff
7ec0: fefff000 c0025a14 00000000 fefff400 00000000 00000000 c792c2e0 c034c418
7ee0: c792c2e0 0000004a 60000013 c02fa7b0 c034c438 00000000 00000000 c7817f10
7f00: c005ee48 c005e36c 60000013 ffffffff 000000c2 000000ff 000000c2 c792c2e0
7f20: 0000004a 00000000 c034c418 c01413e8 00000000 c005e4cc 00000000 00000000
7f40: c00217d4 00000000 c01413a4 00000000 00000000 00000000 00000000 c014133c
7f60: c02fa7b0 00000000 00000000 00000000 c00217d4 c01413d0 c00216e0 c00252d0
7f80: c034e8a8 0000018e c034e8a8 c78363a0 c034e800 000000bf c03715a4 c00b9bbc
7fa0: c005fc64 c7837c80 c7817fb6 c005fc84 c00217d4 39310f60 00000031 00000000
7fc0: 00000000 000000c0 c034acf4 00000000 c00216e0 c00217d4 00000000 00000000
7fe0: 00000000 c00083c0 00000000 00000000 00000000 c003e828 09402a20 8d4ef9ea
[<c014143c>] (interrupt+0x54/0x78) from [<c005dba4>] (handle_IRQ_event+0x40/0x114)
[<c005dba4>] (handle_IRQ_event+0x40/0x114) from [<c005f4d8>] (handle_simple_irq+0x58/0x90)
[<c005f4d8>] (handle_simple_irq+0x58/0x90) from [<c002f7bc>] (gpio_irq_handler+0x98/0xc8)
[<c002f7bc>] (gpio_irq_handler+0x98/0xc8) from [<c0025050>] (_text+0x50/0x78)
[<c0025050>] (_text+0x50/0x78) from [<c0025a14>] (__irq_svc+0x34/0x60)
Exception stack(0xc7817ec8 to 0xc7817f10)
7ec0: 00000000 fefff400 00000000 00000000 c792c2e0 c034c418
7ee0: c792c2e0 0000004a 60000013 c02fa7b0 c034c438 00000000 00000000 c7817f10
7f00: c005ee48 c005e36c 60000013 ffffffff
[<c0025a14>] (__irq_svc+0x34/0x60) from [<c005ee48>] (default_enable+0x24/0x38)
[<c005ee48>] (default_enable+0x24/0x38) from [<c792c2e0>] (0xc792c2e0)
Code: e59f3024 e59f0024 e5932000 e3a03003 (e5823000)
Kernel panic - not syncing: Fatal exception in interrupt
[<c002b628>] (unwind_backtrace+0x0/0xdc) from [<c0273f38>] (panic+0x34/0x110)
[<c0273f38>] (panic+0x34/0x110) from [<c0029bd0>] (die+0x130/0x15c)
[<c0029bd0>] (die+0x130/0x15c) from [<c002c4b0>] (__do_kernel_fault+0x68/0x80)
[<c002c4b0>] (__do_kernel_fault+0x68/0x80) from [<c002c6d0>] (do_page_fault+0x208/0x228)
[<c002c6d0>] (do_page_fault+0x208/0x228) from [<c0025220>] (do_DataAbort+0x30/0x90)
[<c0025220>] (do_DataAbort+0x30/0x90) from [<c00259cc>] (__dabt_svc+0x4c/0x60)
Exception stack(0xc7817e18 to 0xc7817e60)
7e00: c030cf26 c0374fd4
7e20: 00000000 00000003 c792c2e0 00000000 00000000 0000004a fefff400 c034ade8
7e40: 00000003 00000050 c7817eb0 c7817e60 c01413f8 c014143c 60000013 ffffffff
[<c00259cc>] (__dabt_svc+0x4c/0x60) from [<c01413f8>] (interrupt+0x10/0x78)
[<c01413f8>] (interrupt+0x10/0x78) from [<c005dba4>] (handle_IRQ_event+0x40/0x114)
[<c005dba4>] (handle_IRQ_event+0x40/0x114) from [<c005f4d8>] (handle_simple_irq+0x58/0x90)
[<c005f4d8>] (handle_simple_irq+0x58/0x90) from [<c002f7bc>] (gpio_irq_handler+0x98/0xc8)
[<c002f7bc>] (gpio_irq_handler+0x98/0xc8) from [<c0025050>] (_text+0x50/0x78)
[<c0025050>] (_text+0x50/0x78) from [<c0025a14>] (__irq_svc+0x34/0x60)
Exception stack(0xc7817ec8 to 0xc7817f10)
7ec0: 00000000 fefff400 00000000 00000000 c792c2e0 c034c418
7ee0: c792c2e0 0000004a 60000013 c02fa7b0 c034c438 00000000 00000000 c7817f10
7f00: c005ee48 c005e36c 60000013 ffffffff
[<c0025a14>] (__irq_svc+0x34/0x60) from [<c005ee48>] (default_enable+0x24/0x38)
[<c005ee48>] (default_enable+0x24/0x38) from [<c792c2e0>] (0xc792c2e0)
static int __init gpio_init_module(void)
{
int ret;
ret = register_chrdev(GPIO_MAJOR_DEF, DEVICE_NAME, &gpio_fops);
if(ret < 0)
{
printk("Sorry not Register");
return ret;
}
ret = init_gpio();
return 0;
}
static void __exit gpio_cleanup_module(void)
{
iounmap(LED_DATA);
//free_irq(LED_CONT_PIN, NULL);
unregister_chrdev(GPIO_MAJOR_DEF, DEVICE_NAME);
}
이런식으로 지정해 주셔야 합니다.
아래 로그가 찍히는 걸로 봐서 gpio_init_module는 실행되고 있는것 같습니다.
( gpio_init_module 에서 init_gpio를 call 하니까요)
call_init
4
4
ControlBox - GPIO init, Function Called
우선 눈에 보이는 문제는
i = request_irq(LED_CONT_PIN, &interrupt, 0, DEVICE_NAME, NULL);
LED_DATA = (unsigned int*)ioremap(LED_GPIO_DATA, 4);
입니다.
interrupt handler인 interrupt에서 LED_DATA 변수를 사용하기때문에
request_irq 전에 LED_DATA를 ioremap해주어야 합니다.
LED_DATA = (unsigned int*)ioremap(LED_GPIO_DATA, 4);
i = request_irq(LED_CONT_PIN, interrupt, 0, DEVICE_NAME, NULL);
request_irq 실행 후 LED_DATA가 ioremap되기 전에 interrupt에 의해 interrupt hander가 실행되다가
LED_DATA가 NULL이라서 발생한 Oops인것 같습니다.
그럼 수고하세요^^;
혹시나 해서 kernel 2.6.30 을 계속 쓰셔야 하는 것이 아니라면,
ftp://ftp.at91.com/pub/linux/2.6.39-at91/ 를 보시면, linux-2.6.39 관련 patch 가 있고
제 경험상 거의 바로 동작하는 것으로 보입니다.. =-=
그냥 이것은 참고삼아... 공유합니다.
gpio_init_module() 함수가 언제 쯤 호출되는지요???
gpio_init_module() 함수에 로그를 넣은 후.............커널 부팅 로그 부탁드립니다.