2440 개발 보드에서 Linux 시스템의 hello 드라이버 프로그램 작성

  1. 개요 이 문서에서는 실습용으로 실행 가능한 간단한 드라이버 예제를 제공하고, Linux에서 드라이버 템플릿의 요소들을 설명합니다. 또한 Linux에서 애플리케이션에서 드라이버로의 실행 과정을 설명합니다. 이 간단한 드라이버 예제는 개발 보드의 Linux 시스템에서 직접 실행됩니다.

개발 환경: TQ2440 개발 보드 + Linux 2.6.30.4

  1. 드라이버 프로그램 예제
  2. 드라이버 파일 EmbedSky_hello.c 작성
#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>

#define    MY_DEVICE_MAJOR     231
#define    DEVICE_NAME     "MyDevice"

static int my_device_open(struct inode *inode, struct file *file)
{
    printk("<1>MyDevice open.\n");
    return 0;
}

static int my_device_write(struct file *file, const char __user * buf, size_t count, loff_t *ppos)
{
    printk("<1>MyDevice write.\n");
    return 0;
}

static struct file_operations my_flops = {
    .owner  =   THIS_MODULE,
    .open   =   my_device_open,     
    .write  =   my_device_write,
};

static int __init my_device_init(void)
{
    int ret;
    
    ret = register_chrdev(MY_DEVICE_MAJOR, DEVICE_NAME, &my_flops);
    if (ret < 0) 
    {
      printk("<1>%s can't register major number.\n", DEVICE_NAME);
      return ret;
    }
    printk("<1>%s initialized.\n", DEVICE_NAME);

    return 0;
}

static void __exit my_device_exit(void)
{
    unregister_chrdev(MY_DEVICE_MAJOR, DEVICE_NAME);
    printk("<1>%s removed.\n", DEVICE_NAME);
}                                    

module_init(my_device_init);
module_exit(my_device_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("www.embedsky.net");
MODULE_DESCRIPTION("SKY2440/TQ2440 Board First module test");
  1. 드라이버 Makefile 작성
KERN_DIR = /opt/EmbedSky/linux-2.6.30.4

all:
    make -C $(KERN_DIR) M=`pwd` modules 

clean:
    make -C $(KERN_DIR) M=`pwd` modules clean
    rm -rf modules.order

obj-m    += my_device.o
  1. 드라이버 예제 테스트
  2. 드라이버 컴파일 전 주의사항
  • 드라이버 파일이 Linux 커널 소스 트리의 하위 디렉터리가 아닙니다.
  • 드라이버 파일이 "opt/EmbedSky/work/EmbedSky_hello" 디렉터리에 있습니다.
  • Linux 커널 소스가 "opt/EmbedSky/linux-2.6.30.4"에 있습니다.
  1. Ubuntu에서 드라이버 컴파일
# cd /opt/EmbedSky/work/EmbedSky_hello
# make
  1. Ubuntu에서 드라이버를 개발 보드로 복사
# cd /opt/EmbedSky/root_nfs/lib
# cp /opt/EmbedSky/work/EmbedSky_hello/my_device.ko ./
  1. 개발 보드에서 드라이버 설치
# insmode my_device.ko
  1. 드라이버 등록 정보 확인
# cat /proc/devices
  1. 애플리케이션 테스트
  2. 테스트 코드 작성
  • hellotest.c 내용
#include <fcntl.h>
#include <stdio.h>

int main(void)
{
    int fd;
    int val = 1;
    fd = open("/dev/my_device", O_RDWR);
    if(fd < 0){
        printf("can't open!\n");
    }
    write(fd, &val, 4);
    return 0;
}
  1. Ubuntu에서 애플리케이션 컴파일
# arm-linux-gcc hellotest.c -o hellotest
  1. Ubuntu에서 애플리케이션을 개발 보드로 복사
# cd /opt/EmbedSky/root_nfs/usr/bin
# cp /opt/EmbedSky/work/EmbedSky_hello/hellotest ./
  1. 개발 보드에서 장치 파일 생성
# mknod /dev/my_device c 231 0
  1. 테스트 코드 실행
# cd /usr/bin
# ./hellotest
  1. 드라이버 템플릿
  2. 헤더 파일
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
  1. 초기화 함수
static int __init my_device_init(void)
{
    int ret;
    ret = register_chrdev(MY_DEVICE_MAJOR, DEVICE_NAME, &my_flops);
    if (ret < 0) {
        printk(KERN_EMERG DEVICE_NAME " can't register major number.\n");
        return ret;
    }
    printk(KERN_EMERG DEVICE_NAME " initialized.\n");
    return 0;
}
module_init(my_device_init);
  1. 종료 함수
static void __exit my_device_exit(void)
{
    unregister_chrdev(MY_DEVICE_MAJOR, DEVICE_NAME);
    printk(KERN_EMERG DEVICE_NAME " removed.\n");
}
module_exit(my_device_exit);
  1. 라이선스 정보
MODULE_LICENSE("GPL");
  1. 기능 함수
static int my_device_open(struct inode *inode, struct file *file)
{
    printk(KERN_EMERG "my_device open.\n");
    return 0;
}

static int my_device_write(struct file *file, const char __user * buf, size_t count, loff_t *ppos)
{
    printk(KERN_EMERG "my_device write.\n");
    return 0;
}

static struct file_operations my_flops = {
    .owner  =   THIS_MODULE,
    .open   =   my_device_open,     
    .write  =   my_device_write,
};
  1. 애플리케이션에서 드라이버로의 실행 과정
  2. Linux 시스템의 계층 구조
  • 애플리케이션 계층 ---> 라이브러리 ---> 커널 ---> 드라이버 ---> 하드웨어
  1. 애플리케이션에서 드라이버로의 실행 과정
  • "open("/dev/my_device", O_RDWR)" 함수의 실행 과정을 예로 설명
  1. 드라이버 프로그램의 실행 특징
  • 애플리케이션과 달리 드라이버는 주动生成되지 않습니다.
  • 애플리케이션의 요청에 따라 초기화되고, 읽기/쓰기 작업을 수행합니다.
  • 드라이버는 커널 공간에서 실행되고, 시스템의 신뢰할 수 있는 일부분입니다.

태그: linux Embedded Kernel Device Driver Character Device

6월 3일 16:07에 게시됨