이 매뉴얼은 JK전자(JK Electronics) 에 의해서 번역, 수정, 작성 되었고 소유권 또한
JK전자(JK Electronics)
의 것입니다. 소유권자의 허가를 받지 않고 무단으로 수정, 삭제하거나 배포 할 수 없습니다.

 

S3C6410 Start Kit Linux 디바이스 드라이버 Developer Guide


 
* Update history

- 2011.1.13 : 초기 Release


 



1. Environment Setup

1.1 Installation Fedora9

S3C6410 Startkit 의 모든 예제와 컴파일 과정은 VMWare에 설치된 Fedora9 머신에서 실행 하였습니다. 다른 리눅스 환경에서는 테스트 되지 않았습니다. 폐도라 리눅스의 전체 설치 과정은 여기 Installation Fedora9 을 참조하시기 바랍니다.


1.2 Install cross-build compiler

AM용 임베디드 리눅스의 어플리케이션을 개발하기 위해서는 컴파일러로 개발용 Linux PC에 ARM용 크로스 컴파일러를 설치 해야 합니다. 이 개발보드를 위해서는 arm-linux-gcc-4.5.1 컴파일러를 설치 해야 합니다. 이 컴파일러는 armv6 Instruction set and support hardware floating-point operations 등을 지원 합니다. 자세한 설치 방법은 리눅스 개발자 가이드를 참조하시기 바랍니다.

1. Linux 개발자 가이드(커널 컴파일, 파일시스템, Qt 포팅 등)

2. Device Driver Programming

1.12 절에서는 리눅스 User mode 에서의 예제들에 대해서 살펴 보았습니다. 이번 절에서는 커널 모드에서의 리눅스 디바이스 작성 예제들을 살펴 보도록 합니다.

2.1 Hello, Module-simple Device Driver Example

드라이버 소스 디렉토리 /opt/FriendlyARM/mini6410/linux/linux-2.6.36/drivers/char
드라이버 소스 파일 이름 Mini6410_hello_module.c
The driver will not load any device in the dev node

#include <linux/kernel.h>
#include <linux/module.h>

static int __init mini6410_hello_module_init(void)
{
printk("Hello, Mini6410 module is installed !\n");
return 0;
}

static void __exit mini6410_hello_module_cleanup(void)
{
printk("Good-bye, Mini6410 module was removed!\n");
}

module_init(mini6410_hello_module_init);
module_exit(mini6410_hello_module_cleanup);
MODULE_LICENSE("GPL");



(1) "Hello, Module" 을 커널 소스 트리에 넣어서 컴파일 하는 방법(added to the kernel source tree, and compile)

General compile the driver module version 2.6 driver code need to be added to the kernel source tree, and make the appropriate configuration. make menuconfig 명령에 의해서 선택 할 수 있도록 합니다.


Step1 : Kconfig 파일을 열어 다음과 같이 수정 합니다. Open "linux-2.6.36/drivers/char/Kconfig" file

s3c6410

linux-2.6.36 커널이 있는 디렉토리에서 "make menuconfig" 명령을 실행 합니다.

s3c6410


Device
Drivers -> Character devices -> "Mini6410 module sample" 에서 <M> 을 선택하면 모듈로 컴파일 된다는 의미이고 "*" 를 선택하면 커널에 포함해서 컴파일 한다는 의미 입니다. 여기에서는 <M> 으로 선택합니다.

Step2: Step1에서의 설정은 커널 컨피규레이션상의 설정이고 실제로는 이번 단계에서 Makefile을 수정 한것이 컴파일시 반영이 됩니다. "linux-2.6.36/drivers/char/Makefile" 파일을 Open 합니다.

s3c6410

Step3: 이번 단계에서는 실제로 모듈로 소스 파일을 컴파일 하는 단계 입니다.

s3c6410

(2) "Hello, Module download and install it using the development board

FTP를 이용해서 타겟 개발보드의 "/lib/modules/2.6.36-FriendlyARM" 위치에 "mini6410_hello_module.ko" 파일을 다운로드 합니다. 그리고 나서 "modprobe" 명령을 위해서 모듈을 커널에 Load 합니다 modprobe 명령시 "ko" 확장자는 붙이지 않습니다.

# modprobe mini6410_hello_module

다음 명령은 모듈은 Unload 하는 명령 입니다.

# rmmod mini6410_hello_module

s3c6410

2.2 LED Driver

LED1 ~ LED4까지를 컨트롤 하는 디바이스 드라이버 예제 입니다. 각 LED들의 6410 CPU에 할당된 리소스 입니다.

LED IO 포트 이름 CPU Pin name
LED1 GPK4 R23
LED2 GPK5 R22
LED3 GPK6 R24
LED4 GPK7 R25



드라이버 소스 디렉토리 /opt/FriendlyARM/mini6410/linux/linux-2.6.36/drivers/char
드라이버 소스 파일 이름 Mini6410_leds.c
Device Type misc
Device Name /dev/leds
예제 소스 디렉토리 위치 /opt/FriendlyARM/mini6410/linux/examples/leds
드라이버 소스 파일 이름 led.c
드라이버 파일 이름 led
The driver will not load any device in the dev node

#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
//#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <mach/map.h>
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/gpio-bank-e.h>
#include <mach/gpio-bank-k.h>

#define DEVICE_NAME "leds"

static long sbc2440_leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
switch(cmd) {
unsigned tmp;
case 0:
case 1:
if (arg > 4) {
return -EINVAL;
}
tmp = readl(S3C64XX_GPKDAT);
tmp &= ~(1 << (4 + arg));
tmp |= ( (!cmd) << (4 + arg) );
writel(tmp, S3C64XX_GPKDAT);
//printk (DEVICE_NAME": %d %d\n", arg, cmd);
return 0;
default:
return -EINVAL;
}
}
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = sbc2440_leds_ioctl,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
static int __init dev_init(void)
{
int ret;
{
unsigned tmp;
(tmp & ~(0xffffU<<16))|(0x1111U<<16);
writel(tmp, S3C64XX_GPKCON);
tmp = readl(S3C64XX_GPKDAT);
tmp |= (0xF << 4);
writel(tmp, S3C64XX_GPKDAT);
}
ret = misc_register(&misc);
printk (DEVICE_NAME"\tinitialized\n");
return ret;
}
static void __exit dev_exit(void)
{
misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("FriendlyARM Inc.");