Busan IT/로봇제어2015. 11. 6. 13:36

==================================Outline====================================

LED 제어 디바이스 드라이버

----------------------------------------------------------------------------

LED 제어 디바이스 드라이버

 

p/558 [smart.c] : 드라이버 소스

p/565 [smart.h] : 헤더 파일

p/566 [led_app.c] : 애플리케이션 소스

 

코드를 간소화 시키기 위해 LED 1개만 이용하고 이에 맞게 코드를 수정하여 작성해보자.

 

핀을 BCM23번을 사용한다.

 

 

 

사용자로부터 명령을 입력받아 LED를 제어할 수 있도록 코드를 작성하자.

 









/*** 소스 ***/


[smart.c]

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/delay.h>

#include <asm/mach/map.h>
#include <asm/io.h>
#include <asm/uaccess.h>

#include "smart.h"

#define SMART_MAJOR   501
#define NAME      "SMART_DRV"

#define GPIO_BASE_PA   0x3F200000
#define GPIO_GPFSEL1   (0x04)
#define GPIO_GPFSEL2   (0x08)
#define GPIO_GPSET0   (0x1C)
#define GPIO_GPCLR0   (0x28)
#define GPIO_GPLEV0   (0x34)

#define GPIO_FSEL23_OUT  (1<<9)

#define GPIO_23      (1<<23)

static void __iomem *gpio_base_va;
volatile unsigned *gpfsel1;
volatile unsigned *gpfsel2;
volatile unsigned *gpset0;
volatile unsigned *gpclr0;
volatile unsigned *gplev0;

unsigned int old_reg;

static void all_led_onoff(void)
{
  *gpset0 |= GPIO_23;
  
  mdelay(500);

  *gpclr0 |= GPIO_23;
}
static void led_on(void)
{
  *gpset0 |= GPIO_23;
}

static void led_off(void)
{
  *gpclr0 |= GPIO_23;
}

int led_open(struct inode *inode, struct file *filp)
{
  printk("RPi LED init=n");

  gpio_base_va = ioremap(GPIO_BASE_PA, 0x60);
  printk("gpio_base: %p\n", gpio_base_va);

  gpfsel1 = (volatile unsigned *)(gpio_base_va + GPIO_GPFSEL1);
  gpfsel2 = (volatile unsigned *)(gpio_base_va + GPIO_GPFSEL2);
  gpset0 = (volatile unsigned *)(gpio_base_va + GPIO_GPSET0);
  gpclr0 = (volatile unsigned *)(gpio_base_va + GPIO_GPCLR0);
  gplev0 = (volatile unsigned *)(gpio_base_va + GPIO_GPLEV0);

  printk("gpfsel2- addr: %p, value: %x\n", gpfsel2, *gpfsel2);
  old_reg = *gpfsel2;
  *gpfsel2 |= (GPIO_FSEL23_OUT);

  all_led_onoff();

  return 0;
}

int led_release(struct inode *inode, struct file *filp)
{
  printk("RPi LED exit\n");

  all_led_onoff();

  *gpfsel2 = old_reg;

  iounmap( (void *)gpio_base_va);

  return 0;
}

ssize_t led_read(struct file *filp, char *user, size_t size, loff_t *pos)
{
  int val;
  unsigned int led_state = 0;

  printk("RPi LED Read\n");

  val = *gplev0;

  if(val & GPIO_23)
    led_state |= 1;

  return led_state;
}

ssize_t led_write(struct file *flip, const char *user, size_t size, loff_t *pos)
{
  unsigned int led_state = 0;

  printk("RPi LED Write\n");

  get_user(led_state, (unsigned int *)user);
  printk("led valude: %d\n", led_state);

  if(led_state & 1)
    led_on();
  else
    led_off();

  return led_state;
}

long led_ioctl(struct file *flip, unsigned int cmd, unsigned long addr)
{
  int size;
  unsigned int led_state = 0;

  printk("RPi LED ioctl\n");

  if(_IOC_TYPE(cmd) != LED_IOCTL_MAGIC)
      return -EINVAL;
    
    
  if(_IOC_NR(cmd) >= LED_IOCTL_MAX)
      return -EINVAL;

  size = _IOC_SIZE(cmd);

  if(size)
  {
    if(_IOC_DIR(cmd) & _IOC_READ)
      if(access_ok(VERITY_WRITE, (void *)addr, size) < 0)
        return -ENOMEM;
    if(_IOC_DIR(cmd) & _IOC_WRITE)
      if(access_ok(VERITY_READ, (void *)addr, size) < 0)
        return -ENOMEM;
  }

  switch(cmd)
  {
    case LED_INIT:
      all_led_onoff();
      break;
    case LED_RED_ON:
      led_on();
      break;
    case LED_RED_OFF:
      led_off();
      break;
    case LED_ON_OFF:
      get_user(led_state, (unsigned int*)addr);
      printk("led_state: %d\n", led_state);

      if(led_state & 1)
        led_on();
      else
        led_off();

      break;
  }
  return 0;
}

struct file_operations led_fops = {
  .open    = led_open,
  .release  = led_release,
  .read    = led_read,
  .write    = led_write,
  .unlocked_ioctl  = led_ioctl
};

static int smart_init(void)
{
  int ret = register_chrdev(SMART_MAJOR, NAME, &led_fops);

  if(ret < 0)
  {
    printk("RPi LED Driver registration failed: %d\n", ret);
  }
  else
  {
    printk("RPi LED Driver registration success");
  }

  return ret;
}

static void smart_exit(void)
{
  unregister_chrdev(SMART_MAJOR, NAME);
  printk("RPi LED Driver unregistered\n");

  return;
}  

module_init(smart_init);
module_exit(smart_exit);

MODULE_LICENSE("GPL");



[led_app.c]


#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

#include "smart.h"

#define SMART_MAJOR   501
#define SMART_MINOR    100
#define NAME      "SMART_DRV"

#define LED_ON      1
#define LED_OFF      0

int main(void)
{
  int iFd;
  int iRtn=0;
  dev_t led_dev;
  unsigned int led_state = 0;
  char * cpBuf = "";
  unsigned char cInput;
  unsigned int uiCnt;
  int iBuf = 0;

  led_dev = makedev(SMART_MAJOR, SMART_MINOR);
  mknod(NAME, S_IFCHR|0666, led_dev);

  iFd = open(NAME, O_RDWR);
  printf("led fd: %d\n", iFd);

  sleep(1);
  printf("ioctl: LED_INIT\n");
  ioctl(iFd, LED_INIT);
  sleep(1);

  while(1)
  {
    if(iRtn == 100)
      break;
    printf("Please input command ::\n");
    printf("0: LED OFF  1: LED ON  2: LED ON/OFF  3: QUIT\n");
    read(0&cInput, sizeof(char));
    switch(cInput)
    {
      default:
        break;
      case '0':
        printf("LED OFF\n");
        ioctl(iFd, LED_RED_OFF);
        iRtn = read(iFd, &iBuf, 4);
        printf("LED state: %X, RTN: %d\n", iBuf, iRtn);
        sleep(1);
        break;

      case '1':
        printf("LED ON\n");
        ioctl(iFd, LED_RED_ON);
        iRtn = read(iFd, &iBuf, 4);
        printf("LED state: %X, RTN: %d\n", iBuf, iRtn);
        sleep(1);        
        break;

      case '2':
        printf("LED ON/OFF\n");
        for(uiCnt = 0; uiCnt < 3; ++uiCnt)
        {
          led_state = LED_ON;
          ioctl(iFd, LED_ON_OFF, &led_state);
          iRtn = read(iFd, &iBuf, 4);
          printf("LED state: %X, RTN: %d\n", iBuf, iRtn);
          sleep(1);

          led_state = LED_OFF;
          ioctl(iFd, LED_ON_OFF, &led_state);
          iRtn = read(iFd, &iBuf, 4);
          printf("LED state: %X, RTN: %d\n", iBuf, iRtn);
          sleep(1);
        }
        break;

      case '3':
        iRtn = 100;
        printf("program terminated\n");
        break;

    }
    if'\n' == getchar() );
    putchar('\n');
  }

  return 0;
}



[smart.h]

#ifndef __SMART_H__
#define __SMART_H__

#define  LED_IOCTL_MAGIC  '1'

#define LED_INIT  _IO(LED_IOCTL_MAGIC, 0)
#define LED_RED_ON  _IO(LED_IOCTL_MAGIC, 1)
#define LED_RED_OFF  _IO(LED_IOCTL_MAGIC, 2)
#define LED_ON_OFF  _IOW(LED_IOCTL_MAGIC, 7int)

#define LED_IOCTL_MAX  8

#endif // __SMART_H__



[Makefile]


obj-m = smart.o

KDIR = /usr/src/linux

PWD = $(shell pwd)

all:
  @clear
  $(MAKE) -C $(KDIR) M=$(PWD) modules
  @ls -al smart.ko

up:
  @clear
  @insmod smart.ko
  @echo ================== dmesg =================
  @dmesg | tail
  @echo ================== dmesg =================

down:
  @clear
  @rmmod smart
  @echo ================== dmesg =================
  @dmesg | tail
  @echo ================== dmesg =================

clean:
  @clear
  @rm -rf *.ko
  @rm -rf *.mod.*
  @rm -rf .*.cmd
  @rm -rf *.o
  @rm -rf modules.order
  @rm -rf Module.symvers
  @rm -rf .tmp_versions
  @ls -al
  @echo Clean :Done.

 

 

반응형
Posted by newind2000
Busan IT/영상처리2015. 11. 5. 22:51

==================================Outline====================================

비트맵 구조체

----------------------------------------------------------------------------

비트맵 구조체

크기가 가로 400픽셀, 세로 400픽셀인 비트맵 파일을 임의로 생성하여 비트맵파일에 대해서 알아보기로 하자.

 

 


각 픽셀이 RGB로 표현되기 때문에 이 비트맵 파일의 용량은 (400 * 400) * 3이고, 54byte는 헤더파일이다헤더 파일은 실제내용을 간추린 정보를 제공하는데 이것을 오버 헤더라고 한다.


 

비트맵 파일은 픽셀 단위로 데이터를 저장한다. 1byte(8bits)에는 한가지 색에 대한 정보를 가지고 있다.  1픽셀은 3byte로 구성되는데,  각 바이트는 빨(Red), 녹(Green), 파(Blue)로 이루어져 있다.

 

**빛의 3원색:  빨강, 녹색, 파랑 

**색의 3원색:  자주, 노랑, 청록

 

 

** 빛은 섞을수록 밝아지고 색은 섞을수록 어두워진다.

위에서 만든 비트맵 파일을 헥사뷰를 사용하여 출력해본다. 54byte가 'FF'가 아닌 값으로 표시되고 있음을 알 수 있다. 

 

54Byte는 비트맵 파일의 헤더부분이며 비트맵 파일에 대한 정보를 담고 있다. 비트맵 파일의 구조체를 살펴보도록 하자. 


 

/* BITMAPFILEHEADER 구조체 */

typedef struct tagBITMAPFILEHEADER{ //bmfh

WORD bfType; // 파일의 형태, 0x42, 0x4d (BM) 이어야함

WORD bfSize; // 비트맵 파일의 크기 (Byte단위)

WORD bfReserved1; // 예약. 0으로 설정

WORD bfReserved2; // 예약2. 0으로설정

DWORD bfOffBits; // 실제 비트맵데이터까지의 오프셋값

// 실제로는 bfOffBits = BITMAPFILEHEADER크기 + BITMAPINFOHEADER크기 + RGBQUAD 구조체배열의크기 이다.

} BITMAPFILEHEADER;

 

/* BITMAPINFOHEADER 구조체 */

typedef struct tagBITMAPINFOHEADER{ //bmfh

DWORD biSize; // 이 구조체의 크기. 구조체 버전확인할수 있다.

LONG biWidth; // 비트맵의 가로 픽셀수

LONG biHeight; // 비트맵의 세로 픽셀수

WORD biPlanes; // 플레인의 갯수 반드시 1이어야함

WORD biBitCount; // 한 픽셀이 구성되는 비트의수

DWORD biCompression; // 압축방법. BI_RGB일땐 비압축 BI_RLE8, BI_RLE4인경우 run length encode방법으로 압축

DWORD biSizeImage; // 이미지의 크기. 압축이 안되어있을때는 0

LONG biXPelsPerMeter; // 가로 해상도

LONG biYPelsPerMeter; // 세로 해상도

DWORD biClrUsed; // 색상테이블을 사용하였을때 실제 사용되는 색상수

DWORD biClrImportant; // 비트맵을 출력하는데 필수 색상수

} BITMAPINFOHEADER;

 

비트맵 파일 구조체를 참고하여 구조체 멤버들을 출력해보자. 

 

400 * 400 크기의 BMP파일의 경우 한 픽셀당 3byte를 차지하고 그 값을 red, greeb, blue의 정도는 8bit(256) 나누어 표시할 수 있다. 파일의 총 크기는 480054byte이고 54byte는 헤더파일임으로 파일의 시작점에서 54byte 떨어진 지점부터의 데이터를 조작함으로써 BMP파일을 변형시킬 수 있다.

BMP파일을 조작하여 여러 가지 색깔로 변형시켜보자.

**BMP이미지를 수정하여 원본에 덮어 쓰도록 하자.

각 색에 대한 출력 정보는 0 ~ FF로 표현된다. '0'이 가장 낮은 단계이며 'FF'가 가장 높은 단계이다. 가로 픽셀이 400, 세로 픽셀이 400인 비트맵 구조체에서 가로 한 줄의 용량은 400 * 3이다. 좌측 상단에서 우측 하단까지 'for문'을 사용하여 데이터의 값을 입력할 값을 설정해주면 된다.

각 픽셀의 첫 번째 바이트는 blue, 두 번째 바이트는 green, 세 번째 바이트는 red이다. 비트맵 파일의 정보를 수정하여 색이 어떻게 바뀌는지 출력해보자.







소스 코드는 아래와 같다.

/*** 소스 ***/ 

#include <stdio.h>
#include <fcntl.h>
#include <windows.h>


int main(int iNum, char * cpArr[])
{
  int iRtn;
  int iFd;
  BITMAPFILEHEADER stBFHead;
  BITMAPINFOHEADER stBIHead;
  char cBuf[16*16];
  unsigned char * ucpBuf;
  
  unsigned int uiCntX;
  unsigned int uiCntY;

  

  iFd = open(cpArr[1], O_RDWR|O_BINARY);  
  if(iFd == 0)
  {
    printf("파일을 열 수 없습니다.\n");
    return -1;
  }

  iRtn = read(iFd, &stBFHead, sizeof(BITMAPFILEHEADER));
  if(iRtn == 0)
  {
    printf("파일을 읽을 수 없습니다.\n");
    close(iFd);            
    return -1;
  }
  if0x4D42 != (stBFHead.bfType) )
  {
    printf("BMP파일이 아닙니다.\n");
    close(iFd);            
    return -1;
  }
  iRtn = lseek(iFd, sizeof(BITMAPFILEHEADER), SEEK_SET);
  if(iRtn != sizeof(BITMAPFILEHEADER) )
  {
    printf("읽어들일 부분이 잘못 지정되었습니다.\n");
    close(iFd);            
    return -1;
  }
  iRtn = read(iFd, &stBIHead, sizeof(BITMAPINFOHEADER));
  if(iRtn == 0)
  {
    printf("INFO헤더가 존재하지 않습니다.\n");
    close(iFd);            
    return -1;
  }

  ucpBuf = (void *)malloc(stBIHead.biSizeImage);
  if(0 == ucpBuf)
  {
    printf("사용 가능한 메모리가 부족합니다.\n");
    close(iFd);
    return -1;
  }
  lseek(iFd, sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER), SEEK_SET);
  iRtn = read(iFd, ucpBuf, stBIHead.biSizeImage);
  

  if(iRtn == 0)
  {
    printf("데이터를 읽을 수 없습니다.\n");
    close(iFd);        
    free(ucpBuf);
    return -1;
  }
  for(uiCntY=0; uiCntY < stBIHead.biHeight; ++uiCntY)
  {
    for(uiCntX=0; uiCntX < stBIHead.biWidth; ++uiCntX)
    {
      ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 0= 0//blue  
      ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 1= 0//green
      ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 2= 0xFF; //red            
    }
  }
  lseek(iFd, 54, SEEK_SET);
  iRtn = write(iFd, ucpBuf, stBIHead.biSizeImage);
  if(iRtn == 0)
  {
    printf("데이터 쓰기에 실패 했습니다.\n");
    close(iFd);        
    free(ucpBuf);
    return -1;
  }

  lseek(iFd, 54, SEEK_SET);
  iRtn = read(iFd, cBuf, 16*16);  

  
  
  
  close(iFd);
  free(ucpBuf);
  
  return 0;

} 

 

 

 

 

반응형
Posted by newind2000
Busan IT/로봇제어2015. 11. 4. 16:26

==================================Outline====================================

라즈베리 파이 커널 빌드와 디바이스 드라이버

----------------------------------------------------------------------------

 

라즈베리 파이 커널 빌드와 디바이스 드라이버

 

p/521

 

교재의 소스를 참고하여 디바이스 드라이버를 작성해 보겠다.

 

p/521 [simple_drv.c - part1] - 디바이스 드라이버 소스

p/528 [simple_drv.c - part2] - 디바이스 드라이버 소스

p/532 [simple_ioctl.h] - 디바이스 드라이버 명령어 정의

p/541 [Makefile] - 컴파일 실행 소스

p/542 [simple_app.c] - 디바이스 드라이버 테스트 코드

 

코딩이 완료되면 컴파일한다.

 

# make

컴파일로부터 생성된 파일들을 확인할 수 있다.

 

# ll

 

 

simple_app 애플리케이션을 컴파일을 위해 작성해놓은 ‘Makefile'을 재사용한다.

 

# make simple_app

실행 파일이 생성된 것을 확인할 수 있다.

 

모듈 명령어를 사용하여 생성한 모듈을 적재한 후 확인한다.

 

# insmod simple_app.ko

# lsmod

/proc/devices 파일을 통해서도 simple_drv정보를 확인할 수 있다.

 

 

애플리케이션을 실행시켜서 결과값을 확인해본다.





/*** 소스 ***/

[simple_drv.c]

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

#include "simple_ioctl.h"

#define SIMPLE_MAJOR    500
#define SIMPLE_MINOR    100

#define SIMPLE_DEV_NAME "/dev/simple"

#define SIMPLE_DEV_ADDR 0x80000000
#define SIMPLE_DEV_SIZE 0x8000

int main()
{
    int fd, ret, rVal = 0, wVal = 200;
    char rBuf[80= "";
    char wBuf[] = "98765432109876543210";
    char *addr;
    struct pollfd pfd[1];
    dev_t simple_dev;
    char tmp[40= "";

    simple_dev = makedev(SIMPLE_MAJOR, SIMPLE_MINOR);
    ret = mknod(SIMPLE_DEV_NAME, S_IFCHR|0666, simple_dev);

    fd = open(SIMPLE_DEV_NAME, O_RDWR);
    printf("open: %d\n", fd);

    ret = read(fd, rBuf, 15);
    rBuf[ret] = '\0';
    printf("read: %s, reg: %d\n", rBuf, ret);

    ret = write(fd, wBuf, 15);
    printf("write ret: %d\n", ret);

    ret = ioctl(fd, SIMPLE_INIT);
    printf("ioctl[SIMPLE_INIT] ret: %d\n", ret);

    ret = ioctl(fd, SIMPLE_READ, &rVal);
    printf("ioctl[SIMPLE_READ] data: %d, ret: %d\n", rVal, ret);

    ret = ioctl(fd, SIMPLE_WRITE, &wVal);
    printf("ioctl[SIMPLE_WRITE] ret: %d\n", ret);

    printf("ioctl[SIMPLE_RDWR] before-> wVal: %d\n", wVal);
    ret = ioctl(fd, SIMPLE_RDWR, &wVal);
    printf("ioctl[SIMPLE_RDWR] after -> wVal : %d, ret: %d\n", wVal, ret);
    printf("--------------before mmap\n");
    sprintf(tmp, "pmap -x %d", getpid() );
    system(tmp);
    addr = (char *)mmap(0, SIMPLE_DEV_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, SIMPLE_DEV_ADDR);
    printf("mmap addr: %p\n", addr);

     printf("--------------after mmap\n");
     system(tmp);

     munmap(addr, SIMPLE_DEV_SIZE);
     printf("--------------after munmap\n");
     system(tmp);

     pfd[0].fd = fd;
     pfd[0].events = POLLIN|POLLOUT|POLLERR;

     while(1)
     {
         ret = poll((struct pollfd *)&pfd, 13000);

         if(pfd[0].revents & POLLIN)
         {
             ret = read(fd, rBuf, 10);
         }
         else if(pfd[0].revents & POLLOUT)
         {
             ret = write(fd, wBuf, 10);
         }
         else if(pfd[0].revents & POLLERR)
         {
             printf("poll error!!\n");
         }

         if(ret == 0)
         {
             printf("poll timeout occured\n");
             break;
         }

     }

     close(fd);
     return 0;
 }

[simple_app.c]
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/mman.h>
 #include <linux/sched.h>

 #include <asm/page.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/poll.h>


 #ifdef ARCH_ARM
 #include <mach/irgs.h>
 #include <mach/reg_gpio.h>
 #endif

 #include "simple_ioctl.h"

 #define DEV_MAJOR   245
 #define DEV_NAME    "Simple Driver"

 #define DEV_ADDR    0x80000000
 #define DEV_SIZE    0x8000
 #define IRQF_DISABLED 0x20

 int simple_major;

 int simple_open(struct inode *inode, struct file *filp)
 {
     int major, minor;
     major = MAJOR(inode->i_rdev);
     major = MINOR(inode->i_rdev);
     printk("Simple Driver : open\n");
     printk("--> major : %d, minor : %d\n", major, minor);
     return 0;
 }

 int simple_release(struct inode *inode, struct file *filp)
 {
     printk("Simple Driver : release\n");
     return 0;
 }

 ssize_t simple_read(struct file *filp, char *buf, size_t size, loff_t *pos)
 {
     char data[] = "12345678901234567890";

     printk("Simple Driver : read\n");

     copy_to_user(buf, data, size);

     return 0x11;
 }

 ssize_t simple_write(struct file *filp, const char *buf, size_t size, loff_t *pos)
 {
    char data[40];

    copy_from_user(data, buf, size);

    printk("Simple Driver : write\n");

    data[size] = '\0';
    printk("--> from user : %s\n", data);

    udelay(100);

    return 0x22;
}

long simple_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    int size;
    int rval = 0;
    int wval = 100;
    int ret;

    printk("Simple Driver: ioctl\n");

    if(_IOC_TYPE(cmd) != SIMPLE_IOCTL_MAGIC) return -EINVAL;
    if(_IOC_NR(cmd) >= SIMPLE_IOCTL_MAX) return -EINVAL;

    size = _IOC_SIZE(cmd);

    if(size)
    {
        if(_IOC_DIR(cmd) & _IOC_READ)
            if(access_ok(VERIFY_WRITE, (void *)arg, size) < 0)
                return -EINVAL;
        if(_IOC_DIR(cmd) & _IOC_WRITE)
            if(access_ok(VERIFY_READ, (void *)arg, size) < 0)
                return -EINVAL;
    }

    switch(cmd)
    {
        case SIMPLE_INIT:
            printk("-->SIMPLE_INIT\n");
            ret = 0x31;
            break;
        case SIMPLE_READ:
            printk("-->SIMPLE_READ\n");
            copy_to_user( (void *)arg, &wval, sizeof(int) );
            ret = 0x32;
            break;
        case SIMPLE_WRITE:
            printk("-->SIMPLE_WRITE\n");
            copy_from_user( &rval, (void *)arg, sizeof(int) );
            printk("----> from user : %d\n", rval);
            ret = 0x33;
            break;
        case SIMPLE_RDWR:
            printk("-->SIMPLE_RDWR\n");
            ret = 0x34;
             break;
     }

     return ret;
 }

 int simple_mmap(struct file *filp, struct vm_area_struct *vma)
 {
     printk("Simple Driver : mmap\n");

     remap_pfn_range(vma, vma->vm_start, DEV_ADDR >> PAGE_SHIFT, DEV_SIZE, vma->vm_page_prot);

     printk("--> start : 0x%x, end: 0x%x\n", (unsigned int)vma->vm_start, (unsigned int)vma->vm_end);
     return 0;
 }

 int readCnt = 0;
 int writeCnt = 0;
 DECLARE_WAIT_QUEUE_HEAD(readQueue);
 DECLARE_WAIT_QUEUE_HEAD(writeQueue);

 int simple_poll(struct file *filp, struct poll_table_struct *pt)
 {
     unsigned int state = 0;

     printk("Simple Driver : poll\n");

     poll_wait(filp, &readQueue, pt);
     poll_wait(filp, &writeQueue, pt);

     if(readCnt > 0)
     {
         state |= POLLIN | POLLRDNORM;
     }
     if(writeCnt > 0)
     {
         state |= POLLIN | POLLWRNORM;
     }

     return state;

 }

 irqreturn_t simple_handler(int irq, void *dev_id)
 {
     printk("Simple Interrupt handler\n");
     printk("--> irq number : %d\n", irq);
     return IRQ_HANDLED;
 }

 struct file_operations simple_fops =
 {
     .open       = simple_open,
     .release    = simple_release,
     .read       = simple_read,
     .write      = simple_write,
     .unlocked_ioctl = simple_ioctl,
     .mmap       = simple_mmap,
     .poll       = simple_poll,
 };

 int simple_drv_init(void)
 {
     simple_major = register_chrdev(DEV_MAJOR, DEV_NAME, &simple_fops);

     printk("Simple Driver : registered\n");
     printk("--> major : %d\n", simple_major);

     if(request_irq(10, simple_handler, IRQF_DISABLED, "Simple Interrupt", NULL) < 0)
         printk("--> request irq failed\n");

     return simple_major;
 }

 void simple_drv_exit(void)
 {
     unregister_chrdev(simple_major, DEV_NAME);
     printk("Simple Driver : unregistered\n");
     return;
 }

 module_init(simple_drv_init);
 module_exit(simple_drv_exit);
 MODULE_LICENSE("Dual BSD/GPL");




[simple_ioctl.h]

 #define SIMPLE_IOCTL_MAGIC  's'

 #define SIMPLE_INIT         _IO(SIMPLE_IOCTL_MAGIC, 0)
 #define SIMPLE_READ         _IOR(SIMPLE_IOCTL_MAGIC, 1int)
 #define SIMPLE_WRITE        _IOW(SIMPLE_IOCTL_MAGIC, 2int)
 #define SIMPLE_RDWR         _IOWR(SIMPLE_IOCTL_MAGIC, 3int)

 #define SIMPLE_IOCTL_MAX    4


[Makefile]
 obj-m := simple_drv.o

 ifeq ($(ARCH), xxx)
 KDIR :=/usr/src/linux
 CROSS_COMPILE :=arm-none-linux-gnueabi-
 CCFLAGS := -static
 else
 KDIR :=/lib/modules/$(shell uname -r)/build
 endif

 TARGET := simple_app
 PWD := $(shell pwd)
 CC := ${CROSS_COMPILE}gcc
 LD := ${CROSS_COMPILE}ld
 AR := ${CROSS_COMPILE}ar

 all:
     $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
 $(TARGET): simple_app.c
     $(CC) $(CCFLAGS) -o $@ $^

 clean:
     $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean
     rm -f $(TARGET)



 

 

 

 

반응형
Posted by newind2000