開發板上驅動程式模組的實現
一、在同一個資料夾中,寫一個驅動模組程式(file.c檔案)和一個Makefile
如:驅動模組程式:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <plat/regs-gpio.h>
#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/regs-timer.h>
#include <linux/device.h>
#define DEVICE_NAME "ledtest"
static struct class *led_class;
static int ledtest_open(struct inode *inode, struct file *file)
{
unsigned int tmp;
tmp = readl(S3C64XX_GPKCON);
tmp =(tmp&~(0xffffU<<4)) | (0x1111U<<4);
//(tmp & ~(0xffffU<<0)) | (0x1111U<<0);
writel(tmp, S3C64XX_GPKCON);
tmp = readl(S3C64XX_GPKDAT);
tmp |= (0x0F << 4);
writel(tmp, S3C64XX_GPKDAT);
return 0;
}
static int ledtest_close(struct inode *inode, struct file *file)
{
unsigned int tmp;
tmp = readl(S3C64XX_GPKCON);
tmp = (tmp & ~(0xffffU<<4)); //input function
writel(tmp, S3C64XX_GPKCON);
return 0;
}
static int ledtest_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
unsigned tmp;
unsigned char num;
num = *(unsigned char *)arg;
//printk (DEVICE_NAME": %d %d\n", num, cmd);
switch(cmd) {
case 0: //on
if (num > 4) {
return -EINVAL;
}
tmp = readl(S3C64XX_GPKDAT);
tmp &= ~(1 << (4 + num));
//tmp |= ( cmd << (0 + num) );
writel(tmp, S3C64XX_GPKDAT);
return 0;
case 1: //off
if (num > 4) {
return -EINVAL;
}
tmp = readl(S3C64XX_GPKDAT);
tmp &= ~(1 << (4+ num));
tmp |= ( cmd << (4 + num) );
writel(tmp, S3C64XX_GPKDAT);
return 0;
default:
return -EINVAL;
}
return 0;
}
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = ledtest_open,
.ioctl = ledtest_ioctl,
.release = ledtest_close,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
static int __init dev_init(void)
{
int ret;
ret = misc_register(&misc);
printk ("led driver initialized.\n");
return ret;
}
static void __exit dev_exit(void)
{
misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
如Makefile:
ifneq ($(KERNELRELEASE),)
obj-m := s3c6410_leds.o
else
PWD := $(shell pwd)
KERNEL_DIR :=/home/ghh/linux-2.6.28.6
all:
cd $(KERNEL_DIR); make SUBDIRS=$(PWD) modules
arm-linux-gcc -o leds_tese leds_test.c
clean:
rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions *.order *.symvers
endif
二、然後執行make命令(make -C /核心路徑/ SUBDIRS=$(pwd) modules),執行該命令後會生成幾個檔案,其中有一個是.KO檔案,這個檔案是用來做載入驅動模組用的
三、在同一檔案中,寫一個應用程式和一個Makefile
如:應用程式
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#define PATH "/dev/ledtest" //device file
#define LED_ON 0
#define LED_OFF 1
int main(void)
{
int fd, count;
unsigned char num;
unsigned char led_num[4] = {0, 1, 2, 3};
fd = open("/dev/ledtest", 0);
if (fd < 0) {
printf("Failed to open leds driver\n");
exit(1);
}
count = 4;
while(1) {
ioctl(fd, LED_ON, &led_num[count%4]);
ioctl(fd, LED_OFF, &led_num[(count - 1)%4]);
usleep(500000);
count++;
ioctl(fd, LED_ON, &led_num[count%4]);
ioctl(fd, LED_OFF, &led_num[(count - 1)%4]);
usleep(500000);
}
close(fd);
return 0;
}
Makefile:
CROSS_COMPILE = /opt/FriendlyARM/toolschain/4.5.1/bin/arm-linux-
CC = $(CROSS_COMPILE)gcc
AR = $(CROSS_COMPILE)ar
ALL : leds_test
leds_test: leds_test.c
$(CC) -o leds_test leds_test.c
clean :
rm -rf leds_test *~
四、然後執行make命令,就會生成一個可執行檔案
五、啟動NFS在宿主機上,並把前面生成的.KO檔案和可執行檔案拷壩到共享目錄下
六、開啟開發板的終端,然後掛載共享檔案目錄,而掛載共享檔案有兩種方式:例如:
1、mount -o nolock 192.168.3.150:/home/share /mnt
2、mount -t nfs -o intr,nolock,wsize=1024,rsize=1024 192.168/3/150:/home/share /mnt
七、掛載成功後,就進入/mnt進行載入.KO檔案
#cd /mnt
#insmod file.ko
#lsmod //檢視是否載入成功
#lsmod | head -引數 //可檢視前面的模組
#dmesg | tail -引數 //檢視尾的模組,並顯示模組內容
八、在開發板上載入模組成功後,就執行應用程式生成的可執行檔案 ,如:
# ./led_test on或off
注:
在執行make 的命令之前,記得要更新環境變數,即
#soure /etc/profile