head.h
#ifndef __HEAD_H__
#define __HEAD_H__
typedef struct{
unsigned int moder;
unsigned int otyper;
unsigned int ospeedr;
unsigned int pupdr;
unsigned int idr;
unsigned int odr;
}gpio_t;
#define RCC 0x50000A28
#define GPIOB 0x50003000
#define GPIOE 0x50006000
#define GPIOF 0x50007000
#define ON _IOW('l',1,int*)
#define OFF _IOW('l',0,int*)
#endif
led.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/io.h>
#include "head.h"
// 存储主设备号
int major;
// 存放class_create与device_create函数创建的空间首地址
struct class *cls;
struct device *dev;
// 存储虚拟空间地址
gpio_t *vir_led1;
gpio_t *vir_led2;
gpio_t *vir_led3;
int *vir_rcc;
// 封装操作方法函数
int led_open(struct inode *inode, struct file *file)
{
return 0;
}
long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
// 存放从用户空间传过来的数据
int buf;
int ret = copy_from_user(&buf, (void *)arg, 4);
if (ret)
{
printk("拷贝用户空间传过来的数据失败\n");
return -EIO;
}
switch (cmd)
{
case OFF: // 关灯
switch (buf)
{
case 1: // led1
vir_led1->odr &= (~(0x1 << 10));
break;
case 2: // led2
vir_led2->odr &= (~(0x1 << 10));
break;
case 3: // led3
vir_led3->odr &= (~(0x1 << 8));
break;
}
break;
case ON: // 开灯
switch (buf)
{
case 1: // led1
vir_led1->odr |= (0x1 << 10);
break;
case 2: // led2
vir_led2->odr |= (0x1 << 10);
break;
case 3: // led3
vir_led3->odr |= (0x1 << 8);
break;
}
break;
default:
break;
}
return 0;
}
int led_close(struct inode *inode, struct file *file)
{
return 0;
}
// 声明操作方法结构体变量并初始化
struct file_operations fops =
{
.open = led_open,
.unlocked_ioctl = led_ioctl,
.release = led_close,
};
static int __init led_init(void)
{
int i;
// 注册字符设备驱动
major = register_chrdev(0, "led", &fops);
if (major < 0)
{
printk("注册字符设备驱动失败\n");
return -EIO;
}
printk("注册字符设备驱动成功\n");
// 自动生成设备节点
// 向上提交目录
cls = class_create(THIS_MODULE, "led");
if (IS_ERR(cls))
{
printk("向上提交目录失败\n");
return -PTR_ERR(cls);
}
printk("向上提交目录成功\n");
// 向上提交设备信息
for (i = 0; i < 3; i++)
{
dev = device_create(cls, NULL, MKDEV(major, i), NULL, "led%d", i);
if (IS_ERR(dev))
{
printk("向上提交设备信息失败\n");
return -PTR_ERR(dev);
}
}
printk("向上提交设备信息成功\n");
// 物理地址映射
vir_led1 = ioremap(GPIOE, sizeof(gpio_t));
if (vir_led1 == NULL)
{
printk("led1相关寄存器物理地址映射失败\n");
return -EIO;
}
vir_led2 = ioremap(GPIOF, sizeof(gpio_t));
if (vir_led2 == NULL)
{
printk("led2相关寄存器物理地址映射失败\n");
return -EIO;
}
vir_led3 = vir_led1;
vir_rcc = ioremap(RCC, 4);
if (vir_rcc == NULL)
{
printk("rcc相关寄存器物理地址映射失败\n");
return -EIO;
}
printk("寄存器物理地址映射成功\n");
// 寄存器初始化
// rcc寄存器使能
(*vir_rcc) |= (0x3 << 4);
// 设置为输出
// led1
vir_led1->moder &= (~(0x3 << 20));
vir_led1->moder |= (0x1 << 20);
// led2
vir_led2->moder &= (~(0x3 << 20));
vir_led2->moder |= (0x1 << 20);
// led3
vir_led3->moder &= (~(0x3 << 16));
vir_led3->moder |= (0x1 << 16);
// 默认为灯灭
vir_led1->odr &= (~(0x1 << 10)); // led1
vir_led2->odr &= (~(0x1 << 10)); // led2
vir_led3->odr &= (~(0x1 << 8)); // led3
printk("寄存器初始化成功\n");
printk("LED灯设备安装成功\n");
return 0;
}
static void __exit led_exit(void)
{
int i;
// 字符设备驱动注销
unregister_chrdev(major, "led");
// 销毁设备节点信息
for (i = 0; i < 3; i++)
{
device_destroy(cls, MKDEV(major, i));
}
// 销毁目录
class_destroy(cls);
// 取消物理地址映射
iounmap(vir_led1);
iounmap(vir_led2);
iounmap(vir_rcc);
printk("取消地址映射成功\n");
printk("LED灯设备安装成功\n");
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
breeze.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/io.h>
#include "head.h"
// 存储主设备号
int major;
// 存放class_create与device_create函数创建的空间首地址
struct class *cls;
struct device *dev;
// 存储虚拟空间地址
gpio_t *vir_breeze;
int *vir_rcc;
// 封装操作方法函数
int breeze_open(struct inode *inode, struct file *file)
{
return 0;
}
long breeze_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
case OFF:
vir_breeze->odr &= (~(0x1 << 6));
break;
case ON:
vir_breeze->odr |= (0x1 << 6);
break;
}
return 0;
}
int breeze_close(struct inode *inode, struct file *file)
{
return 0;
}
// 声明操作方法结构体变量并初始化
struct file_operations fops =
{
.open = breeze_open,
.unlocked_ioctl = breeze_ioctl,
.release = breeze_close,
};
static int __init breeze_init(void)
{
// 注册字符设备驱动
major = register_chrdev(0, "breeze", &fops);
if (major < 0)
{
printk("注册字符设备驱动失败\n");
return -EIO;
}
printk("注册字符设备驱动成功\n");
// 自动生成设备节点
// 向上提交目录
cls = class_create(THIS_MODULE, "breeze");
if (IS_ERR(cls))
{
printk("向上提交目录失败\n");
return -PTR_ERR(cls);
}
printk("向上提交目录成功\n");
// 向上提交设备信息
dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "breeze0");
if (IS_ERR(dev))
{
printk("向上提交设备信息失败\n");
return -PTR_ERR(dev);
}
printk("向上提交设备信息成功\n");
// 物理地址映射
vir_breeze = ioremap(GPIOB, sizeof(gpio_t));
if (vir_breeze == NULL)
{
printk("breeze相关寄存器物理地址映射失败\n");
return -EIO;
}
vir_rcc = ioremap(RCC, 4);
if (vir_rcc == NULL)
{
printk("rcc相关寄存器物理地址映射失败\n");
return -EIO;
}
printk("寄存器物理地址映射成功\n");
// 寄存器初始化
// rcc寄存器使能
(*vir_rcc) |= (0x1 << 1);
// 设置为输出
vir_breeze->moder &= (~(0x3 << 12));
vir_breeze->moder |= (0x1 << 12);
// 默认蜂鸣器不响
vir_breeze->odr &= (~(0x1 << 6));
printk("寄存器初始化成功\n");
printk("蜂鸣器设备安装成功\n");
return 0;
}
static void __exit breeze_exit(void)
{
// 字符设备驱动注销
unregister_chrdev(major, "breeze");
// 销毁设备节点信息
device_destroy(cls, MKDEV(major, 0));
// 销毁目录
class_destroy(cls);
// 取消物理地址映射
iounmap(vir_breeze);
iounmap(vir_rcc);
printk("取消地址映射成功\n");
printk("蜂鸣器设备安装成功\n");
}
module_init(breeze_init);
module_exit(breeze_exit);
MODULE_LICENSE("GPL");
fan.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/io.h>
#include "head.h"
// 存储主设备号
int major;
// 存放class_create与device_create函数创建的空间首地址
struct class *cls;
struct device *dev;
// 存储虚拟空间地址
gpio_t *vir_fan;
int *vir_rcc;
// 封装操作方法函数
int fan_open(struct inode *inode, struct file *file)
{
return 0;
}
long fan_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
case OFF:
vir_fan->odr &= (~(0x1 << 9));
break;
case ON:
vir_fan->odr |= (0x1 << 9);
break;
}
return 0;
}
int fan_close(struct inode *inode, struct file *file)
{
return 0;
}
// 声明操作方法结构体变量并初始化
struct file_operations fops =
{
.open = fan_open,
.unlocked_ioctl = fan_ioctl,
.release = fan_close,
};
static int __init fan_init(void)
{
// 注册字符设备驱动
major = register_chrdev(0, "fan", &fops);
if (major < 0)
{
printk("注册字符设备驱动失败\n");
return -EIO;
}
printk("注册字符设备驱动成功\n");
// 自动生成设备节点
// 向上提交目录
cls = class_create(THIS_MODULE, "fan");
if (IS_ERR(cls))
{
printk("向上提交目录失败\n");
return -PTR_ERR(cls);
}
printk("向上提交目录成功\n");
// 向上提交设备信息
dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "fan0");
if (IS_ERR(dev))
{
printk("向上提交设备信息失败\n");
return -PTR_ERR(dev);
}
printk("向上提交设备信息成功\n");
// 物理地址映射
vir_fan = ioremap(GPIOE, sizeof(gpio_t));
if (vir_fan == NULL)
{
printk("fan相关寄存器物理地址映射失败\n");
return -EIO;
}
vir_rcc = ioremap(RCC, 4);
if (vir_rcc == NULL)
{
printk("rcc相关寄存器物理地址映射失败\n");
return -EIO;
}
printk("寄存器物理地址映射成功\n");
// 寄存器初始化
// rcc寄存器使能
(*vir_rcc) |= (0x1 << 4);
// 设置为输出
vir_fan->moder &= (~(0x3 << 18));
vir_fan->moder |= (0x1 << 18);
// 默认蜂鸣器不响
vir_fan->odr &= (~(0x1 << 9));
printk("寄存器初始化成功\n");
printk("风扇设备安装成功\n");
return 0;
}
static void __exit fan_exit(void)
{
// 字符设备驱动注销
unregister_chrdev(major, "fan");
// 销毁设备节点信息
device_destroy(cls, MKDEV(major, 0));
// 销毁目录
class_destroy(cls);
// 取消物理地址映射
iounmap(vir_fan);
iounmap(vir_rcc);
printk("取消地址映射成功\n");
printk("风扇设备卸载成功\n");
}
module_init(fan_init);
module_exit(fan_exit);
MODULE_LICENSE("GPL");
motor.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/io.h>
#include "head.h"
// 存储主设备号
int major;
// 存放class_create与device_create函数创建的空间首地址
struct class *cls;
struct device *dev;
// 存储虚拟空间地址
gpio_t *vir_motor;
int *vir_rcc;
// 封装操作方法函数
int motor_open(struct inode *inode, struct file *file)
{
return 0;
}
long motor_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
case OFF:
vir_motor->odr &= (~(0x1 << 6));
break;
case ON:
vir_motor->odr |= (0x1 << 6);
break;
}
return 0;
}
int motor_close(struct inode *inode, struct file *file)
{
return 0;
}
// 声明操作方法结构体变量并初始化
struct file_operations fops =
{
.open = motor_open,
.unlocked_ioctl = motor_ioctl,
.release = motor_close,
};
static int __init motor_init(void)
{
// 注册字符设备驱动
major = register_chrdev(0, "motor", &fops);
if (major < 0)
{
printk("注册字符设备驱动失败\n");
return -EIO;
}
printk("注册字符设备驱动成功\n");
// 自动生成设备节点
// 向上提交目录
cls = class_create(THIS_MODULE, "motor");
if (IS_ERR(cls))
{
printk("向上提交目录失败\n");
return -PTR_ERR(cls);
}
printk("向上提交目录成功\n");
// 向上提交设备信息
dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "motor0");
if (IS_ERR(dev))
{
printk("向上提交设备信息失败\n");
return -PTR_ERR(dev);
}
printk("向上提交设备信息成功\n");
// 物理地址映射
vir_motor = ioremap(GPIOF, sizeof(gpio_t));
if (vir_motor == NULL)
{
printk("motor相关寄存器物理地址映射失败\n");
return -EIO;
}
vir_rcc = ioremap(RCC, 4);
if (vir_rcc == NULL)
{
printk("rcc相关寄存器物理地址映射失败\n");
return -EIO;
}
printk("寄存器物理地址映射成功\n");
// 寄存器初始化
// rcc寄存器使能
(*vir_rcc) |= (0x1 << 5);
// 设置为输出
vir_motor->moder &= (~(0x3 << 12));
vir_motor->moder |= (0x1 << 12);
// 默认蜂鸣器不响
vir_motor->odr &= (~(0x1 << 6));
printk("寄存器初始化成功\n");
printk("马达设备安装成功\n");
return 0;
}
static void __exit motor_exit(void)
{
// 字符设备驱动注销
unregister_chrdev(major, "motor");
// 销毁设备节点信息
device_destroy(cls, MKDEV(major, 0));
// 销毁目录
class_destroy(cls);
// 取消物理地址映射
iounmap(vir_motor);
iounmap(vir_rcc);
printk("马达设备卸载成功\n");
}
module_init(motor_init);
module_exit(motor_exit);
MODULE_LICENSE("GPL");
test.c
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "head.h"
// LED灯控制函数
void led_func(void)
{
int num, l;
int fd = open("/dev/led0", O_RDWR);
if (fd < 0)
{
printf("打开文件失败\n");
return;
}
printf("控制第几盏灯,1(led1) 2(led2) 3(led3) >");
scanf("%d", &num);
printf("0(关灯) 1(开灯) >");
scanf("%d", &l);
if (l == 0)
{
ioctl(fd, OFF, &num);
}
else if (l == 1)
{
ioctl(fd, ON, &num);
}
close(fd);
}
// 蜂鸣器控制函数
void breeze_func(void)
{
int l;
int fd = open("/dev/breeze0", O_RDWR);
if (fd < 0)
{
printf("打开文件失败\n");
return;
}
printf("0(关闭) 1(启动) >");
scanf("%d", &l);
if (l == 0)
{
ioctl(fd, OFF);
}
else if (l == 1)
{
ioctl(fd, ON);
}
close(fd);
}
// 风扇控制函数
void fan_func(void)
{
int l;
int fd = open("/dev/fan0", O_RDWR);
if (fd < 0)
{
printf("打开文件失败\n");
return;
}
printf("0(关闭) 1(启动) >");
scanf("%d", &l);
if (l == 0)
{
ioctl(fd, OFF);
}
else if (l == 1)
{
ioctl(fd, ON);
}
close(fd);
}
// 马达控制函数
void motor_func(void)
{
int l;
int fd = open("/dev/motor0", O_RDWR);
if (fd < 0)
{
printf("打开文件失败\n");
return;
}
printf("0(关闭) 1(启动) >");
scanf("%d", &l);
if (l == 0)
{
ioctl(fd, OFF);
}
else if (l == 1)
{
ioctl(fd, ON);
}
close(fd);
}
int main(int argc, const char *argv[])
{
int dev;
while (1)
{
printf("请输入要控制的设备 1(LED灯) 2(蜂鸣器) 3(风扇) 4(马达) >");
scanf("%d", &dev);
switch (dev)
{
case 1:
led_func();
break;
case 2:
breeze_func();
break;
case 3:
fan_func();
break;
case 4:
motor_func();
break;
default:
printf("输入错误\n");
}
}
return 0;
}