336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
각주1



간단한 임베디드 리눅스 드라이버 만들기

 

q 정의

¦ 장치 파일

       장치를 접근할  있게 하는 파일

       장치에 입출력 하는 것은 장치에 read/write하는것과 동일

¦ 장치번호

       주번호(major number) 부번호(minor number)

       /proc/devices 사용중인 장치번호가 있음

       test 용으로 사용할  있는 major number

      60~63, 120~127, 240~254

¦ 장치 유형(device type)

       문자(character device)

       블록(block device)

       네트워크(network device)

 

q 디바이스 드라이버 읽기 쓰기 구조

q 디바이스 내부 구조

¦ 구성요소

       Initialization/termination interface

      init(), init_module(), exit_module()

       File system interface

      Well-defined interface : file_operations

      Character device : open, release, read, write, ioctl

      Block device : open, release, request, ioctl

      Network device : open, close, transmit, receive, ioctl

       Hardware interface

      inb(), inw(), inl(), insb(), insw(), insl()

      outb(), outw(), outl(), outsb(), outsw(), outsl()

      readb(), readw(), readl()

      writeb(), writew(), writel()

 

q 디바이스 만들기

¦ 순서

        장치를 위한  번호를 할당( 번호를 정하자)

       디바이스 드라이버를 만들기

       Application 프로그램 만들기

       Make 파일 만들기

       장치 파일을 생성함

      mknod /dev/mydrv [b|c] major_number minor_number

       디바이스 드라이버를 컴파일(2가지 방법)

      커널에 직접 포함하여 컴파일

      모듈로서 컴파일하고나중에 모듈 형태로 삽입함

¦  장치를 위한  번호 할당

        예제에서는  번호를 240,  번호를  0으로 정함

¦ 디바이스 드라이버 만들기

       Source code

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/fs.h>

#include <asm/uaccess.h>

#include <asm/io.h>

 

#define DEVICE_NAME "mydrv" //       device name

#define MYDRV_MAJOR 240              //           major number

volatile unsigned int *R_piol;

 

int mydrv_open(struct inode *inode, struct file *flip)

{

             int num = MINOR(inode->i_rdev);

             printk("my drv open : minor number is %d\n",num);

             return 0;

}

ssize_t mydrv_read(struct file *flip, char *buf,size_t count, loff_t *_pos)

{

             unsigned char status;

             printk("my_drvread: buf is %d, countis %d \n",*buf,count);

             return count;

}

 

ssize_t mydrv_write(struct file *flip, char *buf,size_t count, loff_t *_pos)

{

             printk("my_drv_write: buf is %d, countis %d \n",*buf,count);

             *buf=1;

 

             return count;

}

int mydrv_release(struct file *flip, char *buf,size_t count, loff_t *_pos)

{

             printk("my_drv_release: bufis %08X, countis %08X \n",buf,count);

             return count;

}

int mydrv_ioctl(struct inode *inode, struct file *flip, int ioctl_param)

{

             printk("mydrv_ioctl(): ioctl_param %d \n",ioctl_param);

             return 0;

}

 

struct file_operations mydrv_fops ={

             //llseek    :mydrv_llseek,

             read        :mydrv_read,

             write       :mydrv_write,

             ioctl        :mydrv_ioctl,

             open       :mydrv_open,

             release    :mydrv_release

};

 

static int hello_init(void)

{

             int result;

 

             printk("init moudle \n");

 

             result = register_chrdev(MYDRV_MAJOR,DEVICE_NAME,&mydrv_fops);

             if(result<0){

                           printk("mydrv: device driver can't be registered\n");

                           return result;

             }

             return 0;

}

 

static void hello_exit(void)

{

             printk("exit module\n");

}

void hello_cleanup(void)

{

             printk("cleanup module \n");

             unregister_chrdev(MYDRV_MAJOR,DEVICE_NAME);

}

 

module_init(hello_init); //커널을모듈에적재할때호출도리함수지정

module_exit(hello_exit); //커널을모듈에서제거할때호출될함수지정

MODULE_LICENSE("Dual BSD/GPL"); // 커널2.6의라이센스등록

 

¦ Application program 만들기

       Source code

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

#include <stdio.h>

#include <math.h>

 

int main(void)

{

             int fd,ret,select=1;

             int count,temp=0,DIP[8]={0};

             unsigned char buf=0;

             unsigned long flag = 0x01;

             fd = open("/dev/mydrv",O_RDWR);

             if(fd < 0)

             {

                           printf("fd file open fail\n");

                           return -1;

             }

             write(fd,&buf,1);

             read(fd,&buf,1);

             ioctl(fd,1,2);

             close(fd);

}

¦ Makefile 만들기

       Source

obj-m     :=mydrv.o

 

KDIR       :=/home/a/slc100/test_kernel/sl2c100_kernel_2.6.29_20100622

PWD       :=$(shell pwd)

 

default:

             $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

             cp mydrv.ko /nfsroot/RootFS-S5PC100/mydrv.ko

             arm-s3c6410-linux-gnueabi-gcc -o test_app test_app.c

             cp test_app /nfsroot/RootFS-S5PC100/test_app

clean:

             rm -rf *.ko

             rm -rf *.mod.*

             rm -rf *.cmd

             rm -rf *.o

             rm -rf /nfsroot/RootFS-S5PC100/mydrv.ko

rm -rf /nfsroot/RootFS-S5PC100/test_app

 

¦ 장치파일 생성(타켓 보드에서  )

       Mknod /dev/mydrv c 240 0( /dev폴더에 ( 240/ 0 )번호 mydrv 라는 장치파일을 생성)

¦ 모듈 적재

       lnsmod mydrv.ko

       lsmod : 적재된 모듈 출력 / rmmod : 정재된 모듈 삭제

¦ 어플리케션 실행

       ./test_app

¦ 실행화면



Open ->write(buf 0 1 write)->read(buf  1 확인)->ioctl(호출만하였음)->release




블로그 이미지

뚱땡이 우주인

,