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