안녕하세요.

 

gpio제어 학습을 해보려고 여기저기 참고해서 소스를 작성했습니다만, 역시 실력이 개발이라 오류가 발생하네요.

전체 소스입니다. 제가 무엇을 잘못했는지.. 조언 부탁드립니다.

 

아래는 s3c2440a 메뉴얼에서 발췌한 GPF 레지스터 정보입니다.

PORT F CONTROL REGISTERS (GPFCON, GPFDAT)
If GPF0–GPF7 will be used for wake-up signals at power down mode, the ports will be set in interrupt mode.
Register        Address            R/W       Description                                       Reset Value
GPFCON     0x56000050     R/W       Configures the pins of port F           0x0
GPFDAT     0x56000054     R/W       The data register for port F               Undef.
GPFUP         0x56000058    R/W       Pull-up disable register for port F     0x000
Reserved       0x5600005c     –            –                                                         –

 

 gpio_dev.c 디바이스 파일입니다.

 

#include <linux/module.h> // 모듈에 관한 정의
#include <linux/init.h>  // init_module()과 cleanup_module()
#include <linux/fs.h>   // file_operations 구조체
#include <asm/uaccess.h> // copy_to_user()
#include <asm/io.h>    // GPIO controller에 관한 정의

 

#define DEV_NAME "gpio"
#define DEV_MAJOR 250

 

#define rGPFCON (*(volatile unsigned *)0x56000050)
#define rGPFDAT (*(volatile unsigned *)0x56000054)
#define rGPFUP  (*(volatile unsigned *)0x56000058)

 

int gpio_open(struct inode *inode, struct file *filp)
{
 printk("gpio driver open\n");
 
 return 0;
}

 

ssize_t gpio_write(struct file *filp, void *buf, size_t count, loff_t *f_pos)
{
  unsigned int buffer;
 
 copy_from_user(buffer,(int *)buf, sizeof(buffer));

 

 rGPFCON = (rGPFCON &~(0x3<<14))|(0x1<<14);     // GPF 7번 핀을 출력으로 설정
 rGPFUP  = rGPFUP|(0x1<<7);             // 출력으로 사용하기 위해 GPF 7번 핀의 풀업제거
 rGPFDAT = (rGPFDAT &~(0x1<<7))|((buffer & 0x1)<<7); // GPF 7번핀에 데이터 쓰기
 
 return 0;
}

 

int gpio_release(struct inode *inode, struct file *filp)
{
 printk("gpio driver close\n");

 return 0;
}

 

struct file_operations gpio_fops =
{
 .owner    = THIS_MODULE,
  .write  = gpio_write,
 .open   = gpio_open,
 .release = gpio_release,
};

 

int gpio_init(void)
{
 int result;
 
 printk("call gpio_init\n");
 
 result = register_chrdev(DEV_MAJOR, DEV_NAME, &gpio_fops);
 if(result < 0) return result;
  
 return 0;
}

 

int gpio_exit(void)
{
 printk("call gpio_exit\n");
 
 unregister_chrdev(DEV_MAJOR, DEV_NAME);
}

 

module_init(gpio_init);
module_exit(gpio_exit);

MODULE_LICENSE("Dual BSD/GPL");

 

gpio_app.c 응용프로그램 파일입니다..

 

#include <stdio.h>
#include <fcntl.h> // open()의 flag 정의
#include <errno.h> // error 값 정의

 

int main(void)
{
 int fd, buf;
 
 printf("device file open\n");
 
 fd=open("/dev/gpio", O_RDWR|O_NDELAY);
 if(fd<0) {
  perror("/dev/gpio open error");
  exit(1);
 }
  
 for(buf=0;buf<10;buf++) {
  write(fd, buf, sizeof(buf));
  sleep(1);
 }


 close(fd);
 return 0;
}


 

make 메시지 입니다.

 

[hdd@hdd-server nfs]$ make
make -C /opt/linux-2.6.21 SUBDIRS=/home/nfs modules
make[1]: Entering directory `/opt/linux-2.6.21'
  CC [M]  /home/nfs/gpio_dev.o
/home/nfs/gpio_dev.c: In function `gpio_write':
/home/nfs/gpio_dev.c:25: warning: passing arg 1 of `copy_from_user' makes pointer from integer without a cast
/home/nfs/gpio_dev.c: At top level:
/home/nfs/gpio_dev.c:44: warning: initialization from incompatible pointer type
/home/nfs/gpio_dev.c: In function `__exittest':
/home/nfs/gpio_dev.c:69: warning: return from incompatible pointer type
/home/nfs/gpio_dev.c: In function `gpio_write':
/home/nfs/gpio_dev.c:23: warning: 'buffer' might be used uninitialized in this function
/home/nfs/gpio_dev.c: In function `gpio_exit':
/home/nfs/gpio_dev.c:66: warning: control reaches end of non-void function
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/nfs/gpio_dev.mod.o
  LD [M]  /home/nfs/gpio_dev.ko
make[1]: Leaving directory `/opt/linux-2.6.21'
arm-linux-gcc -o gpio_app gpio_app.c

 

타켓 시스템으로 옮겨와서 실행

[root@falinux nfs]$ insmod gpio_dev.ko

[root@falinux nfs]$ mknod /dev/gpio c 250 0

[root@falinux nfs]$ lsmod
Module                  Size  Used by    Not tainted
gpio_dev                1888  0

[root@falinux nfs]$ ./gpio_app
device file open
Segmentation fault

 

커널 메시지를 살펴보니...

[root@falinux nfs]$ dmesg

...

call gpio_init
gpio driver open
Unable to handle kernel NULL pointer dereference at virtual address 00000004
pgd = c0df0000
[00000004] *pgd=30dee031, *pte=00000000, *ppte=00000000
Internal error: Oops: 817 [#1]
Modules linked in: gpio_dev
CPU: 0
PC is at __memzero+0x60/0x80
LR is at __lock_text_end+0x638/0x8f0
pc : [<c014aa60>]    lr : [<c02c8718>]    Not tainted
sp : c0d95f38  ip : 0000001c  fp : c0d95f54
r10: 40135f6c  r9 : c0d94000  r8 : 00000000
r7 : c0d95f78  r6 : 00000000  r5 : c05b5520  r4 : 00000004
r3 : 00000000  r2 : 00000000  r1 : 00000004  r0 : 00000004
Flags: nzcv  IRQs on  FIQs on  Mode SVC_32  Segment user
Control: C000717F
Table: 30DF0000  DAC: 00000015
Process gpio_app (pid: 978, stack limit = 0xc0d94250)
Stack: (0xc0d95f38 to 0xc0d96000)
5f20:                                                       00000004 00000004
5f40: bf00005c 00000004 c0d95f74 c0d95f58 c0086450 bf000030 c05b5540 c05b5520
5f60: c0d95f78 00000000 c0d95fa4 c0d95f78 c0086544 c00863a0 00000000 00000000
5f80: 00000000 4001c3bc bed93c84 00008694 00000004 c0028dc4 00000000 c0d95fa8
5fa0: c0028c20 c0086508 4001c3bc bed93c84 00000003 00000000 00000004 00000000
5fc0: 4001c3bc bed93c84 00008694 00000001 401397fc 000085e8 40135f6c bed93c54
5fe0: 00000000 bed93c3c 00003d10 400df400 60000010 00000003 00000000 00000000
Backtrace:
[<bf000020>] (gpio_write+0x0/0x9c [gpio_dev]) from [<c0086450>] (vfs_write+0xc0/0xf4)
 r4 = 00000004
[<c0086390>] (vfs_write+0x0/0xf4) from [<c0086544>] (sys_write+0x4c/0x74)
 r7 = 00000000  r6 = C0D95F78  r5 = C05B5520  r4 = C05B5540
[<c00864f8>] (sys_write+0x0/0x74) from [<c0028c20>] (ret_fast_syscall+0x0/0x2c)
 r8 = C0028DC4  r7 = 00000004  r6 = 00008694  r5 = BED93C84
 r4 = 4001C3BC
Code: e49de004 e3110008 18a0000c e3110004 (14802004)
gpio driver close