본문 바로가기

PROJECT/ex347_project

LDD_Part 3. 프로젝트와 디바이스 드라이버

이번 Part에서는 우리가 이번 프로젝트에서 사용할 디바이스 드라이버를 보다 자세히 들여다 볼 것이다.
이 파트를 마치고나면 모두들 우리가 가지고 있는 보드에 원하는 디바이스 드라이버를 짤 수 있으시길 바랍니다.

우선 이번 프로젝트에서 우리가 사용하게될 H/W와 디바이스 드라이버를 짝지어 보았다.

ir모듈  rf모듈  3축 가속도 모듈 
GPIO 드라이버  SPI 드라이버  ADC 드라이버 

위의 내용을 보면 아주 간단함을 알 수 있을 것이다.
그렇다 별거 없다~ ㅋㅋ;

이제 슬슬 시작을 해 봅시다.

우선우리가 사용해야 할 핀의 주소값들은 메뉴얼과 Data Sheet에 잘 설명되어 있다.
    (메뉴얼과 Data Sheet는 보드와 함께 동봉되서 온 CD에 들어있다. )
<file명 : DataSheets\S3C2440.pdf , Manual\ch1_hardware_manual_v1.pdf>

Data Sheet를 열어서 목차를 살펴보면 Chapter9. I/O PORTS 를 볼 수 있을것이다.
우리가 찾아보는 gpio(general purpose input/output))은 이름만 봐도 알겠듯이 I/O PORT이다.

Data Sheet를 읽어보면 gpio레지스터는 GPA0, GPG3 이런 식으로 GP다음에 A~J 까지 아파벳 으로 구분한후 번호를 부여했다.

메뉴얼에서는 우리가 사용하는 mini2440보드에서 사용자가 사용할수 있도록 빼놓은 GPIO 핀을 20페이지에 정리해 놓았다.

이렇게 우리는 Data Sheet와  Manual을 살펴서  우리가 원하는 핀의 주소를 알아보고 사용할 수 있다.
    (보다 자세히 설명한 곳 : 
이제 우리는 이 주소를 사용해서 우리가 원하는 GPIO핀에 LED를 달아서 그녀석이 깜빡이는 것을 확인함으로써 우리가 H/W와 레지스터에 대한 이해를 마무리 지어 보자.

우선 이 작업을 하기 위해서는 우리 kernel source를 알아야 한다.

지금 작업하는 kernel source는 보드 구입시 함께 동봉되어오는 CD에 있는 kernel 2.6.32.2 를 사용하고 있다.

우선 gpio-led는 character device 이다.
그러므로 이녀석이 있는 위치를 유추해서 찾아 볼수 있었다.

linux-2.6.32.2/drivers/char/mini2440-leds.c
이 파일이 바로 보드에 박혀있는 micro-led 4개를 깜빡거리게 하는 녀석이다.

이녀석을 열어보면 다음과 같다.
 
 ==============mini2440-leds.c================
===========================================
  1 #include <linux/miscdevice.h>
  2 #include <linux/delay.h>
  3 #include <asm/irq.h>
  4 #include <mach/regs-gpio.h>
  5 #include <mach/hardware.h>
  6 #include <linux/kernel.h>
  7 #include <linux/module.h>
  8 #include <linux/init.h>
  9 #include <linux/mm.h>
 10 #include <linux/fs.h>
 11 #include <linux/types.h>
 12 #include <linux/delay.h>
 13 #include <linux/moduleparam.h>
 14 #include <linux/slab.h>
 15 #include <linux/errno.h>
 16 #include <linux/ioctl.h>
 17 #include <linux/cdev.h>
 18 #include <linux/string.h>
 19 #include <linux/list.h>
 20 #include <linux/pci.h>
 21 #include <linux/gpio.h>
 22 #include <asm/uaccess.h>
 23 #include <asm/atomic.h>
 24 #include <asm/unistd.h>
 25 
 26 
 27 #define DEVICE_NAME "leds"
 28 
 29 static unsigned long led_table [] = {
 30         S3C2410_GPB(5),
 31         S3C2410_GPB(6),
 32         S3C2410_GPB(7),
 33 //      S3C2410_GPB(8),
 34         S3C2410_GPF(0),
 35 };
 36 
 37 static unsigned int led_cfg_table [] = {
 38         S3C2410_GPIO_OUTPUT,
 39         S3C2410_GPIO_OUTPUT,
 40         S3C2410_GPIO_OUTPUT,
 41       S3C2410_GPIO_OUTPUT,
 42 };
 43 
 44 
 45 static int sbc2440_leds_ioctl(
 46         struct inode *inode,
 47         struct file *file,
 48         unsigned int cmd,
 49         unsigned long arg)
 50 {
 51         switch(cmd) {
 52         case 0:
 53         case 1:
 54                 if (arg > 4) {
 55                         return -EINVAL;
 56                 }
 57                 s3c2410_gpio_setpin(led_table[arg], !cmd);
 58                 return 0;
 59         default:
 60                 return -EINVAL;
 61         }
 62 }
 63 
 64 static struct file_operations dev_fops = {
 65         .owner  =       THIS_MODULE,
 66         .ioctl  =       sbc2440_leds_ioctl,
 67 };
 68 
 69 static struct miscdevice misc = {
 70         .minor = MISC_DYNAMIC_MINOR,
 71         .name = DEVICE_NAME,
 72         .fops = &dev_fops,
 73 };
 74 
 75 static int __init dev_init(void)
 76 {
 77         int ret;
 78 
 79         int i;
 80 
 81         for (i = 0; i < 4; i++) {
 82                 s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
 83                 s3c2410_gpio_setpin(led_table[i], 0);
 84         }
 85 
 86         ret = misc_register(&misc);
 87 
 88         printk (DEVICE_NAME"\tinitialized\n");
 89 
 90         return ret;
 91 }
 92 
 93 static void __exit dev_exit(void)
 94 {
 95         misc_deregister(&misc);
 96 }
 97 
 98 module_init(dev_init);
 99 module_exit(dev_exit);
100 MODULE_LICENSE("GPL");
101 MODULE_AUTHOR("FriendlyARM Inc.");
===========================================
===========================================

이 소스 코드에서 빨간색으로 칠해진 부분이 바로 바꾼 부분이다.
S3C2410_GPB(8) ==> S3C2410_GPF(0) 이렇게 바꿀 것이다.

이렇게 소스코드를 바꿔준 다음에 다시 Kernel Image를 만들기위해 make를 하고서 새로 생긴 zImage를 보드에 올려주면
원래 LED4개가 깜빡이는 것 중에 마지막 녀석 대신에 gpio핀에 달아주는 LED가 깜빡 거릴 것이다.

근데.. 어떤 핀에 LED를 달아주고 왜 하필 이렇게 소스코드를 바꿨는지 궁금할 것이다.

그것은 계속해서 설명하겠다...
 


이 녀석의 소스를 타고 들어가면..

linux-2.6.32.2/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h 파일에 
다음과 같이 정의 되어 있다.
 ================gpio-nrs.h===================
===========================================
 41 
 42 #define S3C2410_GPIO_NEXT(__gpio) \
 43         ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 0)
 44 
 45 #ifndef __ASSEMBLY__
 46 
 47 enum s3c_gpio_number {
 48         S3C2410_GPIO_A_START = 0,
 49         S3C2410_GPIO_B_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_A),
 50         S3C2410_GPIO_C_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_B),
 51         S3C2410_GPIO_D_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_C),
 52         S3C2410_GPIO_E_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_D),
 53         S3C2410_GPIO_F_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_E),
 54         S3C2410_GPIO_G_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_F),
 55         S3C2410_GPIO_H_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_G),
 56 };
 57 
 58 #endif /* __ASSEMBLY__ */
 59 
 60 /* S3C2410 GPIO number definitions. */
 61 
 62 #define S3C2410_GPA(_nr)        (S3C2410_GPIO_A_START + (_nr))
 63 #define S3C2410_GPB(_nr)        (S3C2410_GPIO_B_START + (_nr))
 64 #define S3C2410_GPC(_nr)        (S3C2410_GPIO_C_START + (_nr))
 65 #define S3C2410_GPD(_nr)        (S3C2410_GPIO_D_START + (_nr))
 66 #define S3C2410_GPE(_nr)        (S3C2410_GPIO_E_START + (_nr))
 67 #define S3C2410_GPF(_nr)        (S3C2410_GPIO_F_START + (_nr))
 68 #define S3C2410_GPG(_nr)        (S3C2410_GPIO_G_START + (_nr))
 69 #define S3C2410_GPH(_nr)        (S3C2410_GPIO_H_START + (_nr))
 70 
===========================================
===========================================

S3C2410_GPB(8) 은 GPIO_B 의 8번째 핀을 얘기하고
S3C2410_GPF(0) 은 GPIO_F 의 0번째 핀을 얘기함을 알 수 있다.
 

S3C2410_GPB(8) ===> GPIO_B 의 8번째 핀 ===> GPB8
S3C2410_GPF(0) ===> GPIO_F 의 0번째 핀 ===> GPF0 

이렇게 적고 보니 우리가 만진 레지스터 값이 어떤 녀석을 어떤 녀석으로 바꾼지 알 수 있을 것이다.
눈으로 확실히 보고 싶다면 Manual 에 ch1_hardware_manual_v1.pdf 파일을 열어서 GPB8 과 GPF0을 직접 찾아서 보면 될 것이다. ^^

'PROJECT > ex347_project' 카테고리의 다른 글

LDD_Part 3-2. SPI 디바이스 드라이버  (0) 2011.05.23
LDD_Part 3-1. GPIO 디바이스 드라이버  (0) 2011.05.23
LDD_Part 2. 디바이스 드라이버 도우미  (0) 2011.05.22
5/11  (0) 2011.05.11
spi 보던 사이트  (0) 2011.05.11