星期六, 5月 12, 2007

字元類型驅動程式

V1.1

copyright@2006

email: mesmerli@hotmail.com

什麼是字元類型驅動程式

Linux 的驅動程式可區分為以下三種類型:

  1. 字元類型驅動程式-> I/O 驅動程式 -> 磁碟與網路驅動程式之外的驅動程式
  2. 區塊類型驅動程式-> 磁碟驅動程式
  3. 網路類型驅動程式-> 網路驅動程式

LED 驅動程式實驗步驟

Host 端

  1. root file system 組態設定。

    1. 建構新的 root file system (RAMDISK)

      1. dd if=/dev/zero of=ext2new bs=1k count=8192
      2. mke2fs -F -m0 -i 2000 ext2new
      3. mount -w -o loop ext2new /mnt/loop
      4. mount -w -o loop ext2_2418_Creator2410 /mnt/looporg
      5. cp -dpR /mnt/looporg/. /mnt/loop/.
      6. cd /mnt/loop/dev (/dev 檔案夾下,建立 裝置節點)
      7. mknod -m 777 led0 c 44 0
      8. cd /
      9. umount -l /mnt/loop
      10. gzip -9 ext2new
    2. 重新燒錄 root file system。
  2. 建構 LED 驅動程式

    1. 進入 led-demo 目錄
    2. make

Taget 端

  1. 使用 NFS 的方式,mount host 端的目錄,以存取剛剛建立的 LED 驅動程式。

    1. mount 192.168.0.200:/usr/src/creator/nfs /mnt
  1. 安裝驅動程式

    1. cd /dev
    2. mknod -m 777 led0 c 44 0
    3. cd /mnt/Day3/char-driver/led-demo
    4. insmod led-creator.o
  2. 執行應用程式

    1. ./led-demo.exe

led-creator.c

// --------------------------------------------------------------------
//
// Title : led-creator.c
// :
// Library :
// :
// Developers: MICROTIME MDS group (V1.0)
// : mesmerli@gmail.com (V1.1)
// :
// Purpose : Driver for LED of Creator
// :
// Limitation:
// :
// Note :
// :
// --------------------------------------------------------------------
// modification history :
// --------------------------------------------------------------------
// Version| mod. date: |
// V1.0 | 03/05/2004 | First release
// V1.1 | 11/15/2004 | LED by mesmerli
// --------------------------------------------------------------------
//
// Note:
//
// MICROTIME COMPUTER INC.
//
//

#include <linux/config.h>
#include <linux/kernel.h> // 必要的 Header files
#include <linux/module.h>

#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <asm/irq.h>
#include <asm/param.h>
#include <asm/uaccess.h>
#include "asm/arch/irqs.h"

#if LINUX_VERSION_CODE < 0x020100
#define GET_USER(a,b) a = get_user(b)
#else
#include <asm/uaccess.h>
#define GET_USER(a,b) get_user(a,b)
#endif

#include "asm/arch/lib/creator_s3c2410_addr.h" // 硬體暫存器定義
#include "asm/arch/lib/genfont8_8.h"

#include "led-creator.h"

/*
* Define driver major number.
*/
#define MAJOR_NUM LED_MAJOR_NUM
#define MODULE_VERSION "1.10"
#define MODULE_NAME "LED_CREATOR"
#define COPYRIGHT "Copyright (C) 2003-2004, Microtime Computer Inc."
#define MODULE_AUTHOR_STRING "Microtime Computer Inc."
#define MODULE_DESCRIPTION_STRING "Creator led module"

// 硬體控制

#define KEYPAD_SCAN_PERIOD (HZ/5) // 200ms

static UI scan_led=0x5500;

int Creator_led_cmd (int cmd, unsigned char led)
{
int rc = 0;
unsigned char bit ;

switch (cmd){
case LED_IOCTL_SET : {
/*
led value : 1 : 亮, 0 : 不亮
H/W : 0 : 亮, 1 : 不亮
*/
scan_led = ((~led) << 8);

break;
}
case LED_IOCTL_BIT_SET : {
int i ;

if (led >= 8)
return(-EINVAL);

bit = 1;
for (i=0; i < led; i++)
bit <<= 1;

scan_led &= ((~bit) << 8);
break;
}
case LED_IOCTL_BIT_CLEAR : {
int i ;

if (led >= 8)
return(-EINVAL);

bit = 1;
for (i=0; i < led; i++)
bit <<= 1;

scan_led |= (bit << 8);
break;
}
default :
return(-ENOTTY);
}
if (rc == 0)
IO_REG2 = scan_led | 0xfe;

return (rc);
}

/*****************************************************************************/

static int drv_led_open(struct inode *inode, struct file *filp)
{
MOD_INC_USE_COUNT;
return(0);
}
/*****************************************************************************/


static int drv_led_release(struct inode *inode, struct file *filp)
{
MOD_DEC_USE_COUNT;
return 0;
}

int drv_led_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
int rc = 0;

/*
分離type如果遇到錯誤的cmd, 就直接傳回ENOTTY
*/
if (_IOC_TYPE(cmd) != LED_IOCTL_MAGIC) return (-ENOTTY);

switch (cmd) {
case LED_IOCTL_SET :
case LED_IOCTL_BIT_SET :
case LED_IOCTL_BIT_CLEAR : {
unsigned short led;


if (copy_from_user(&led, (unsigned short*)arg, sizeof(unsigned short)))
return (-EINVAL);

if (Creator_led_cmd(cmd, led) < -EFAULT)
return (-EINVAL);
break;
}
default:
rc = -ENOTTY;
break;
}

return(rc);
}

/*
* Exported file operations structure for driver...
*/

struct file_operations drv_led_fops =
{
ioctl: drv_led_ioctl,
open: drv_led_open,
release: drv_led_release,
};

/*****************************************************************************/
static int __init init_module_drv_led(void)
{
int rc;

SET_MODULE_OWNER(&drv_led_fops);

/* Register lcdtxt as character device */
if ((rc = register_chrdev(MAJOR_NUM, MODULE_NAME, &drv_led_fops)) < 0) {
printk("<1>%s: can't get major %dn", MODULE_NAME, MAJOR_NUM);

return (-EBUSY);
}
printk("<1>%s: Version : %s %sn", MODULE_NAME, MODULE_VERSION, COPYRIGHT);

/* Hardware specific initialization */
return 0;
}

static void __exit cleanup_module_drv_led(void)
{
unregister_chrdev(MAJOR_NUM, MODULE_NAME);
printk("<1>%s: removedn", MODULE_NAME);
}

/* here are the compiler macro for module operation */
module_init(init_module_drv_led);
module_exit(cleanup_module_drv_led);

MODULE_AUTHOR(MODULE_AUTHOR_STRING);
MODULE_DESCRIPTION(MODULE_DESCRIPTION_STRING);

EXPORT_NO_SYMBOLS;

/*****************************************************************************/

led-creator.h

//=============================================================================
// File Name : led-creator.h
// Function : LED device drvier definition
// Program :
// Date : 11/15/2004
// Version : 1.10
// History
// 1.0.0 : Programming start (03/05/2004) -> SOP
// 1.1.0 : LED version
//=============================================================================
#ifndef LED_CREATOR_H_
#define LED_CREATOR_H_

#include <linux/config.h>
#if defined(__linux__)
#include <asm/ioctl.h> /* For _IO* macros */
#define LED_IOCTL_NR(n) _IOC_NR(n)
#elif defined(__FreeBSD__)
#include <sys/ioccom.h>
#define LED_IOCTL_NR(n) ((n) & 0xff)
#endif

#define LED_MAJOR_NUM 44
#define LED_IOCTL_MAGIC LED_MAJOR_NUM
#define LED_IO(nr) _IO(LED_IOCTL_MAGIC,nr)
#define LED_IOR(nr,size) _IOR(LED_IOCTL_MAGIC,nr,size)
#define LED_IOW(nr,size) _IOW(LED_IOCTL_MAGIC,nr,size)
#define LED_IOWR(nr,size) _IOWR(LED_IOCTL_MAGIC,nr,size)

/* LED specific ioctls */
/* 設定8個LED Lamps, Low byte 值為有效 */
#define LED_IOCTL_SET LED_IOW( 0x40, unsigned short)
/* 點亮單一個LED lamp */
#define LED_IOCTL_BIT_SET LED_IOW( 0x41, unsigned short)
/* 熄滅單一個LED lamp*/
#define LED_IOCTL_BIT_CLEAR LED_IOW( 0x42, unsigned short)

/* LED define */
#define LED_ALL_ON 0xFF /* 點亮LED Lamp */
#define LED_ALL_OFF 0x00 /* 熄滅LED Lamp */
#define LED_D9_INDEX 0 /* LED 編號D9 (1) */
#define LED_D10_INDEX 1 /* LED 編號D10(2) */
#define LED_D11_INDEX 2 /* LED 編號D11(3) */
#define LED_D12_INDEX 3 /* LED 編號D12(4) */
#define LED_D13_INDEX 4 /* LED 編號D13(5) */
#define LED_D14_INDEX 5 /* LED 編號D14(6) */
#define LED_D15_INDEX 6 /* LED 編號D15(7) */
#define LED_D16_INDEX 7 /* LED 編號D16(8) */

#endif // LED_CREATOR_H_

led-demo.c

#include <signal.h>
#include <stdio.h>
#include <strings.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ioctl.h>

#include "led-creator.h"

int main()
{
int fd;

unsigned int data = 0x0;

int ret;

fd = open("/dev/led0", O_RDWR);
if (fd < 0)
{
printf("open /dev/led0 errorn");
return (-1);
}


while(1)
{
ioctl(fd, LED_IOCTL_SET, &data);

sleep(1);

data++;
if(data >= 0xff)
{
data = 0x0;
}

}

printf("Led Demo!!!n");

return 0;
}

Makefile

CROSS_COMPILE = arm-linux-

LINUXDIR = /usr/src/creator/s3c2410/linux
INCLUDE = $(LINUXDIR)/include
export LINUXDIR

#
# Include the make variables (CC, etc...)
#

AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar

export AS LD CC CPP AR

CFLAGS= -O2 -DMODULE -D__KERNEL__ -DEXPORT_SYMTBL -Wall -I/usr/src/creator/s3c2410/linux/include -Wstrict-prototypes -Wno-trigraphs -Os -mapcs
-fno-strict-aliasing -fno-common -gdwarf-2 -D__linux__ -fno-common -pipe -g -mapcs-32 -march=armv4 -mtune=arm9tdmi
-mshort-load-bytes -msoft-float -DKBUILD_BASENAME=creator_s3c2410_lcd

#CFLAGS= -O0 -Wall -DHAVE_CONFIG_H -D__KERNEL__ -I$(INCLUDE) -DMODULE -DFPM_DEFAULT -Dlinux -Dunix -DNDEBUG -D_REENTRANT -I.
CFLAGS_AP= -O0 -gdwarf-2 -DHAVE_CONFIG_H -DFPM_DEFAULT -Dlinux -Dunix -DNDEBUG -D_REENTRANT -I.

.c.o:
$(CC) $(CFLAGS) -c -o $@ $<

.S.o:
$(CC) $(AFLAGS) -c -o $@ $<

ALL = led-creator.o led-demo.exe

all: $(ALL)

led-creator.o: led-creator.c
$(CC) $(CFLAGS)-c -o $@ $<
led-demo.exe: led-demo.c
$(CC) $(LDFLAGS_AP) -o $@ $^ $(LDLIBS) -L/usr/local/arm/2.95.3/arm-linux/lib /usr/local/arm/2.95.3/arm-linux/lib/libpthread.a
clean:
rm -f *.o *.exe *~ core $(ALL)

0 意見: