//客户端代码led_app.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
int fd;
fd = open("/dev/led_drv",O_RDWR);
if(fd < 0)
{
perror("open");
exit(1);
}
sleep(2);
close(fd);
return 0;
}
//内核代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/io.h>
struct LED{
volatile unsigned int GPC0_CON;
volatile unsigned int GPC0_DAT;
};
int major;
struct class * clazz;
struct device *dev;
struct LED * fs210_led;
int led_drv_open(struct inode * node, struct file * filp)
{
printk("----------%s----------\n",__FUNCTION__);
//开灯
fs210_led->GPC0_DAT |= (0x03 << 3);
return 0;
}
int led_drv_release(struct inode * node, struct file * filp)
{
printk("----------%s----------\n",__FUNCTION__);
//关闭灯
fs210_led->GPC0_DAT &= ~(0x03 << 3);
return 0;
}
const struct file_operations fops = {
.owner = THIS_MODULE,
.open = led_drv_open,
.release = led_drv_release,
};
#define STATIC_REGISTER
static int __init led_drv_init(void)
{
// 1.申请/注册设备号
// 32位无符号整形
// 高12: 主设备号 --- 哪一类设备
// 低20: 次设备号 --- 该类中的哪一个设备
int ret;
#ifdef STATIC_REGISTER
major = 250;
//注册设备号
//参数1:主设备号
//参数2:描述(自定义)
//参数3:file_operation指针
//返回值:0成功 负数失败
ret = register_chrdev(major, "led_drv", &fops);
if(ret < 0)
{
printk("register_chrdev error\n");
return -EINVAL;
}
#else
//申请设备号
//参数1:0 -- 内核默认分配未使用的
//参数2:描述(自定义)
//参数3:file_operation指针
//返回值:大于0成功 负数失败
major = register_chrdev(0, "led_drv", &fops);
if(major < 0)
{
printk("register_chrdev error\n");
return -EINVAL;
}
#endif
// 2.创建类
// 创建类
//参数1:当前模块
//参数2:类描述(自定义)
clazz = class_create(THIS_MODULE, "led_class");
if(IS_ERR(clazz))
{
printk("register_chrdev error\n");
ret = PTR_ERR(clazz);
goto register_chrdev_err;
}
// 3.创建设备节点
// mknod /dev/xxx c major minor
// 创建设备结点
// 参数1: 类对象
// 参数2: 父类
// 参数3: 设备号
// 参数4: 私有数据
// 参数5: 设备节点名称
dev = device_create(clazz, NULL, MKDEV(major, 0), NULL, "led_drv");
if(IS_ERR(dev))
{
printk("device_create error\n");
ret = PTR_ERR(dev);
goto class_create_err;
}
// 4.硬件初始化
//映射
fs210_led = ioremap(0xE0200060, sizeof(struct LED));
//配置GPIO引脚为输出
fs210_led->GPC0_CON &= ~(0xff << 12);
fs210_led->GPC0_CON |= (0x11 << 12);
//先关闭灯
fs210_led->GPC0_DAT &= ~(0x03 << 3);
return 0;
class_create_err:
class_destroy(clazz);
register_chrdev_err:
unregister_chrdev(major, "led_drv");
return ret;
}
static void __exit led_drv_exit(void)
{
iounmap(fs210_led);
device_destroy(clazz, MKDEV(major, 0));
class_destroy(clazz);
unregister_chrdev(major, "led_drv");
}
module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");
//Makefile
#内核路径
KERNEL_DIR=/home/me/farsight/linux-3.0.8
#驱动程序代码所在的路径
CUR_DIR=$(shell pwd)
#驱动程序的名称
DRV_NAME1 = led_drv
APP_NAME = led_app
all:
make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
arm-none-linux-gnueabi-gcc -o $(APP_NAME) $(APP_NAME).c
clean:
make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
rm -rf $(APP_NAME)
install:
cp -raf *.ko $(APP_NAME) /opt/rootfs/drv_module
#到底要把哪个.c编译成模块
obj-m = $(DRV_NAME1).o