通过ioctl(内核+应用层)
控制led灯三盏,风扇,蜂鸣器,小马达
头文件head.h
cpp
#ifndef __LED_H__
#define __LED_H__
typedef struct {
volatile unsigned int TZCR; // 0x000
volatile unsigned int res1[2]; // 0x004-0x008
volatile unsigned int OCENSETR; // 0x00C
volatile unsigned int OCENCLRR; // 0x010
volatile unsigned int res2[1]; // 0x014
volatile unsigned int HSICFGR; // 0x018
volatile unsigned int CSICFGR; // 0x01C
volatile unsigned int MPCKSELR; // 0x020
volatile unsigned int ASSCKSELR; // 0x024
volatile unsigned int PCK12SELR; // 0x028
volatile unsigned int MPCKDIVR; // 0x02C
volatile unsigned int AXIDIVR; // 0x030
volatile unsigned int res3[2];
volatile unsigned int APB4DIVR; // 0x03C
volatile unsigned int APB5DIVR; // 0x040
volatile unsigned int RTCDIVR; // 0x044
volatile unsigned int MSSCKSELR; // 0x048
volatile unsigned int res4[13];
volatile unsigned int PLL1CR; // 0x080
volatile unsigned int PLL1CFGR1; // 0x084
volatile unsigned int PLL1CFGR2; // 0x088
volatile unsigned int PLL1FRACR; // 0x08C
volatile unsigned int PLL1CSGR; // 0x090
volatile unsigned int PLL2CR; // 0x094
volatile unsigned int PLL2CFGR1; // 0x098
volatile unsigned int PLL2CFGR2; // 0x09C
volatile unsigned int PLL2FRACR; // 0x0A0
volatile unsigned int PLL2CSGR; // 0x0A4
volatile unsigned int res5[6];
volatile unsigned int I2C46CKSELR; // 0x0C0
volatile unsigned int SPI6CKSELR; // 0x0C4
volatile unsigned int UART1CKSELR; // 0x0C8
volatile unsigned int RNG1CKSELR; // 0x0CC
volatile unsigned int CPERCKSELR; // 0x0D0
volatile unsigned int STGENCKSELR; // 0x0D4
volatile unsigned int DDRITFCR; // 0x0D8
volatile unsigned int res6[9];
volatile unsigned int MP_BOOTCR; // 0x100
volatile unsigned int MP_SREQSETR; // 0x104
volatile unsigned int MP_SREQCLRR; // 0x108
volatile unsigned int MP_GCR; // 0x10C
volatile unsigned int MP_APRSTCR; // 0x110
volatile unsigned int MP_APRSTSR; // 0x114
volatile unsigned int res7[10];
volatile unsigned int BDCR; // 0x140
volatile unsigned int RDLSICR; // 0x144
volatile unsigned int res8[14];
volatile unsigned int APB4RSTSETR; // 0x180
volatile unsigned int APB4RSTCLRR; // 0x184
volatile unsigned int APB5RSTSETR; // 0x188
volatile unsigned int APB5RSTCLRR; // 0x18C
volatile unsigned int AHB5RSTSETR; // 0x190
volatile unsigned int AHB5RSTCLRR; // 0x194
volatile unsigned int AHB6RSTSETR; // 0x198
volatile unsigned int AHB6RSTCLRR; // 0x19C
volatile unsigned int TZAHB6RSTSELR;// 0x1A0
volatile unsigned int TZAHB6RSTCLRR;// 0x1A4
volatile unsigned int res9[22];
volatile unsigned int MP_APB4ENSETR;// 0x200
volatile unsigned int MP_APB4ENCLRR;// 0x204
volatile unsigned int MP_APB5ENSETR;// 0x208
volatile unsigned int MP_APB5ENCLRR;// 0x20C
volatile unsigned int MP_AHB5ENSETR;// 0x210
volatile unsigned int MP_AHB5ENCLRR;// 0x214
volatile unsigned int MP_AHB6ENSETR;// 0x218
volatile unsigned int MP_AHB6ENCLRR;// 0x21C
volatile unsigned int MP_TZAHB6ENSELR;// 0x220
volatile unsigned int MP_TZAHB6ENCLRR;// 0x224
volatile unsigned int res10[22];
volatile unsigned int MC_APB4ENSETR; // 0x280
volatile unsigned int MC_APB4ENCLRR; // 0x284
volatile unsigned int MC_APB5ENSETR; // 0x288
volatile unsigned int MC_APB5ENCLRR; // 0x28C
volatile unsigned int MC_AHB5ENSETR; // 0x290
volatile unsigned int MC_AHB5ENCLRR; // 0x294
volatile unsigned int MC_AHB6ENSETR; // 0x298
volatile unsigned int MC_AHB6ENCLRR; // 0x29C
volatile unsigned int res11[24];
volatile unsigned int MP_APB4LPENSETR; // 0x300
volatile unsigned int MP_APB4LPENCLRR; // 0x304
volatile unsigned int MP_APB5LPENSETR; // 0x308
volatile unsigned int MP_APB5LPENCLRR; // 0x30C
volatile unsigned int MP_AHB5LPENSETR; // 0x310
volatile unsigned int MP_AHB5LPENCLRR; // 0x314
volatile unsigned int MP_AHB6LPENSETR; // 0x318
volatile unsigned int MP_AHB6LPENCLRR; // 0x31C
volatile unsigned int MP_TZAHB6LPENSETR; // 0x320
volatile unsigned int MP_TZAHB6LPENCLRR; // 0x324
volatile unsigned int res12[22];
volatile unsigned int MC_APB4LPENSETR; // 0x380
volatile unsigned int MC_APB4LPENCLRR; // 0x384
volatile unsigned int MC_APB5LPENSETR; // 0x388
volatile unsigned int MC_APB5LPENCLRR; // 0x38C
volatile unsigned int MC_AHB5LPENSETR; // 0x390
volatile unsigned int MC_AHB5LPENCLRR; // 0x394
volatile unsigned int MC_AHB6LPENSETR; // 0x398
volatile unsigned int MC_AHB6LPENCLRR; // 0x39C
volatile unsigned int res13[24];
volatile unsigned int BR_RSTSCLRR; // 0x400
volatile unsigned int MP_GRSTCSETR; // 0x404
volatile unsigned int MP_RSTSR; // 0x408
volatile unsigned int MP_IWDGFZSETR; // 0x40C
volatile unsigned int MP_IWDGFZCLRR; // 0x410
volatile unsigned int MP_CIER; // 0x414
volatile unsigned int MP_CIFR; // 0x418
volatile unsigned int PWRLPDLYCR; // 0x41C
volatile unsigned int MP_RSTSS; // 0x420
volatile unsigned int res14[247];
volatile unsigned int MCO1CFGR; // 0x800
volatile unsigned int MCO2CFGR; // 0x804
volatile unsigned int OCRDYR; // 0x808
volatile unsigned int DBGCFGR; // 0x80C
volatile unsigned int res15[4];
volatile unsigned int RCK3SELR; // 0x820
volatile unsigned int RCK4SELR; // 0x824
volatile unsigned int TIMG1PRER; // 0x828
volatile unsigned int TIMG2PRER; // 0x82C
volatile unsigned int MCUDIVR; // 0x830
volatile unsigned int APB1DIVR; // 0x834
volatile unsigned int APB2DIVR; // 0x838
volatile unsigned int APB3DIVR; // 0x83C
volatile unsigned int res16[16];
volatile unsigned int PLL3CR; // 0x880
volatile unsigned int PLL3CFGR1; // 0x884
volatile unsigned int PLL3CFGR2; // 0x888
volatile unsigned int PLL3FRACR; // 0x88C
volatile unsigned int PLL3CSGR; // 0x890
volatile unsigned int PLL4CR; // 0x894
volatile unsigned int PLL4CFGR1; // 0x898
volatile unsigned int PLL4CFGR2; // 0x89C
volatile unsigned int PLL4FRACR; // 0x8A0
volatile unsigned int PLL4CSGR; // 0x8A4
volatile unsigned int res17[6];
volatile unsigned int I2C12CKSELR; // 0x8C0
volatile unsigned int I2C35CKSELR; // 0x8C4
volatile unsigned int SAI1CKSELR; // 0x8C8
volatile unsigned int SAI2CKSELR; // 0x8CC
volatile unsigned int SAI3CKSELR; // 0x8D0
volatile unsigned int SAI4CKSELR; // 0x8D4
volatile unsigned int SPI2S1CKSELR; // 0x8D8
volatile unsigned int SPI2S23CKSELR; // 0x8DC
volatile unsigned int SPI45CKSELR; // 0x8E0
volatile unsigned int UART6CKSELR; // 0x8E4
volatile unsigned int UART24CKSELR; // 0x8E8
volatile unsigned int UART35CKSELR; // 0x8EC
volatile unsigned int UART78CKSELR; // 0x8F0
volatile unsigned int SDMMC12CKSELR; // 0x8F4
volatile unsigned int SDMMC3CKSELR; // 0x8F8
volatile unsigned int ETHCKSELR; // 0x8FC
volatile unsigned int QSPICKSELR; // 0x900
volatile unsigned int FMCCKSELR; // 0x904
volatile unsigned int res18[1];
volatile unsigned int FDCANCKSELR; // 0x90C
volatile unsigned int res19[1];
volatile unsigned int SPDIFCKSELR; // 0x914
volatile unsigned int CECCKSELR; // 0x918
volatile unsigned int USBCKSELR; // 0x91C
volatile unsigned int RNG2CKSELR; // 0x920
volatile unsigned int DSICKSELR; // 0x924
volatile unsigned int ADCCKSELR; // 0x928
volatile unsigned int LPTIM45CKSELR; // 0x92C
volatile unsigned int LPTIM23CKSELR; // 0x930
volatile unsigned int LPTIM1CKSELR; // 0x934
volatile unsigned int res20[18];
volatile unsigned int APB1RSTSETR; // 0x980
volatile unsigned int APB1RSTCLRR; // 0x984
volatile unsigned int APB2RSTSETR; // 0x988
volatile unsigned int APB2RSTCLRR; // 0x98C
volatile unsigned int APB3RSTSETR; // 0x990
volatile unsigned int APB3RSTCLRR; // 0x994
volatile unsigned int AHB2RSTSETR; // 0x998
volatile unsigned int AHB2RSTCLRR; // 0x99C
volatile unsigned int AHB3RSTSETR; // 0x9A0
volatile unsigned int AHB3RSTCLRR; // 0x9A4
volatile unsigned int AHB4RSTSETR; // 0x9A8
volatile unsigned int AHB4RSTCLRR; // 0x9AC
volatile unsigned int res21[20];
volatile unsigned int MP_APB1ENSETR; // 0xA00
volatile unsigned int MP_APB1ENCLRR; // 0xA04
volatile unsigned int MP_APB2ENSETR; // 0xA08
volatile unsigned int MP_APB2ENCLRR; // 0xA0C
volatile unsigned int MP_APB3ENSETR; // 0xA10
volatile unsigned int MP_APB3ENCLRR; // 0xA14
volatile unsigned int MP_AHB2ENSETR; // 0xA18
volatile unsigned int MP_AHB2ENCLRR; // 0xA1C
volatile unsigned int MP_AHB3ENSETR; // 0xA20
volatile unsigned int MP_AHB3ENCLRR; // 0xA24
volatile unsigned int MP_AHB4ENSETR; // 0xA28
volatile unsigned int MP_AHB4ENCLRR; // 0xA2C
volatile unsigned int res22[2];
volatile unsigned int MP_MLAHBENSETR; // 0xA38
volatile unsigned int MP_MLAHBENCLRR; // 0xA3C
volatile unsigned int res23[16];
volatile unsigned int MC_APB1ENSETR; // 0xA80
volatile unsigned int MC_APB1ENCLRR; // 0xA84
volatile unsigned int MC_APB2ENSETR; // 0xA88
volatile unsigned int MC_APB2ENCLRR; // 0xA8C
volatile unsigned int MC_APB3ENSETR; // 0xA90
volatile unsigned int MC_APB3ENCLRR; // 0xA94
volatile unsigned int MC_AHB2ENSETR; // 0xA98
volatile unsigned int MC_AHB2ENCLRR; // 0xA9C
volatile unsigned int MC_AHB3ENSETR; // 0xAA0
volatile unsigned int MC_AHB3ENCLRR; // 0xAA4
volatile unsigned int MC_AHB4ENSETR; // 0xAA8
volatile unsigned int MC_AHB4ENCLRR; // 0xAAC
volatile unsigned int MC_AXIMENSETR; // 0xAB0
volatile unsigned int MC_AXIMENCLRR; // 0xAB4
volatile unsigned int MC_MLAHBENSETR; // 0xAB8
volatile unsigned int MC_MLAHBENCLRR; // 0xABC
volatile unsigned int res24[16];
volatile unsigned int MP_APB1LPENSETR; // 0xB00
volatile unsigned int MP_APB1LPENCLRR; // 0xB04
volatile unsigned int MP_APB2LPENSETR; // 0xB08
volatile unsigned int MP_APB2LPENCLRR; // 0xB0C
volatile unsigned int MP_APB3LPENSETR; // 0xB10
volatile unsigned int MP_APB3LPENCLRR; // 0xB14
volatile unsigned int MP_AHB2LPENSETR; // 0xB18
volatile unsigned int MP_AHB2LPENCLRR; // 0xB1C
volatile unsigned int MP_AHB3LPENSETR; // 0xB20
volatile unsigned int MP_AHB3LPENCLRR; // 0xB24
volatile unsigned int MP_AHB4LPENSETR; // 0xB28
volatile unsigned int MP_AHB4LPENCLRR; // 0xB2C
volatile unsigned int MP_AXIMLPENSETR; // 0xB30
volatile unsigned int MP_AXIMLPENCLRR; // 0xB34
volatile unsigned int MP_MLAHBLPENSETR; // 0xB38
volatile unsigned int MP_MLAHBLPENCLRR; // 0xB3C
volatile unsigned int res25[16];
volatile unsigned int MC_APB1LPENSETR; // 0xB80
volatile unsigned int MC_APB1LPENCLRR; // 0xB84
volatile unsigned int MC_APB2LPENSETR; // 0xB88
volatile unsigned int MC_APB2LPENCLRR; // 0xB8C
volatile unsigned int MC_APB3LPENSETR; // 0xB90
volatile unsigned int MC_APB3LPENCLRR; // 0xB94
volatile unsigned int MC_AHB2LPENSETR; // 0xB98
volatile unsigned int MC_AHB2LPENCLRR; // 0xB9C
volatile unsigned int MC_AHB3LPENSETR; // 0xBA0
volatile unsigned int MC_AHB3LPENCLRR; // 0xBA4
volatile unsigned int MC_AHB4LPENSETR; // 0xBA8
volatile unsigned int MC_AHB4LPENCLRR; // 0xBAC
volatile unsigned int MC_AXIMLPENSETR; // 0xBB0
volatile unsigned int MC_AXIMLPENCLRR; // 0xBB4
volatile unsigned int MC_MLAHBLPENSETR; // 0xBB8
volatile unsigned int MC_MLAHBLPENCLRR; // 0xBBC
volatile unsigned int res26[16];
volatile unsigned int MC_RSTSCLRR; // 0xC00
volatile unsigned int res27[4];
volatile unsigned int MC_CIER; // 0xC14
volatile unsigned int MC_CIFR; // 0xC18
volatile unsigned int res28[246];
volatile unsigned int VERR; // 0xFF4
volatile unsigned int IDR; // 0xFF8
volatile unsigned int SIDR; // 0xFFC
}rcc_t;
#define RCC ((rcc_t *)0x50000000)
typedef struct {
volatile unsigned int MODER; // 0x00
volatile unsigned int OTYPER; // 0x04
volatile unsigned int OSPEEDR; // 0x08
volatile unsigned int PUPDR; // 0x0C
volatile unsigned int IDR; // 0x10
volatile unsigned int ODR; // 0x14
volatile unsigned int BSRR; // 0x18
volatile unsigned int LCKR; // 0x1C
volatile unsigned int AFRL; // 0x20
volatile unsigned int AFRH; // 0x24
volatile unsigned int BRR; // 0x28
volatile unsigned int res;
volatile unsigned int SECCFGR; // 0x30
}gpio_t;
#define GPIOA ((gpio_t *)0x50002000)
#define GPIOB ((gpio_t *)0x50003000)
#define GPIOC ((gpio_t *)0x50004000)
#define GPIOD ((gpio_t *)0x50005000)
#define GPIOE ((gpio_t *)0x50006000)
#define GPIOF ((gpio_t *)0x50007000)
#define GPIOG ((gpio_t *)0x50008000)
#define GPIOH ((gpio_t *)0x50009000)
#define GPIOI ((gpio_t *)0x5000A000)
#define GPIOJ ((gpio_t *)0x5000B000)
#define GPIOK ((gpio_t *)0x5000C000)
#define GPIOZ ((gpio_t *)0x54004000)
#define LED1_ON _IOW('l',11,int)
#define LED1_OFF _IOW('l',10,int)
#define LED2_ON _IOW('l',21,int)
#define LED2_OFF _IOW('l',20,int)
#define LED3_ON _IOW('l',31,int)
#define LED3_OFF _IOW('l',30,int)
#define FAN_ON _IOW('f',1,int)
#define FAN_OFF _IOW('f',0,int)
#define BUZ_ON _IOW('b',1,int)
#define BUZ_OFF _IOW('b',0,int)
#define MOT_ON _IOW('m',1,int)
#define MOT_OFF _IOW('m',0,int)
#endif
内核代码
ioctldev.c
cpp
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/device.h>
#include "head.h"
//定义四个变量保存主设备号
unsigned int major_led;
unsigned int major_fan;
unsigned int major_buz;
unsigned int major_mot;
//定义多个寄存器的虚拟地址
unsigned int *vir_gpiob_moder = NULL;
unsigned int *vir_gpiob_odr = NULL;
unsigned int *vir_gpioe_moder = NULL;
unsigned int *vir_gpioe_odr = NULL;
unsigned int *vir_gpiof_moder = NULL;
unsigned int *vir_gpiof_odr = NULL;
unsigned int *vir_rcc = NULL;
//定义四个向上提交目录的信息struct class
struct class *cls_led;
struct class *cls_fan;
struct class *cls_buz;
struct class *cls_mot;
//定义四个向上提交设备节点信息struct device
struct device *dev_led;
struct device *dev_fan;
struct device *dev_buz;
struct device *dev_mot;
//封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
return 0;
}
long mycdev_ioctl(struct file *file, unsigned int request, unsigned long args)
{
//args == 0 时,表示操作灯
if(args == 0)
{
//开led1
if(request == LED1_ON)
{
*vir_gpioe_odr |= 0x1 << 10;
}
//关led1
else if(request == LED1_OFF)
{
*vir_gpioe_odr &= ~(0x1 << 10);
}
//开led2
else if(request == LED2_ON)
{
*vir_gpiof_odr |= 0x1 << 10;
}
//关led2
else if(request == LED2_OFF)
{
*vir_gpiof_odr &= ~(0x1 << 10);
}
//开led3
else if(request == LED3_ON)
{
*vir_gpioe_odr |= 0x1 << 8;
}
//关led3
else if(request == LED3_OFF)
{
*vir_gpioe_odr &= ~(0x1 << 8);
}
}
//操作风扇
else if(args == 1)
{
//打开风扇
if(request == FAN_ON)
{
*vir_gpioe_odr |= 0x1 << 9;
}
//关闭风扇
else if(request == FAN_OFF)
{
*vir_gpioe_odr &= ~(0x1 << 9);
}
}
//操作蜂鸣器
else if(args == 2)
{
//打开蜂鸣器
if(request == BUZ_ON)
{
*vir_gpiob_odr |= 0x1 << 6;
}
//关闭蜂鸣器
else if(request == BUZ_OFF)
{
*vir_gpiob_odr &= ~(0x1 << 6);
}
}
else if(args == 3)
{
if(request == MOT_ON)
{
*vir_gpiof_odr |= 0x1 << 6;
}
else if(request == MOT_OFF)
{
*vir_gpiof_odr &= ~(0x1 << 6);
}
}
return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
return 0;
}
struct file_operations fops = {
.open = mycdev_open,
.unlocked_ioctl = mycdev_ioctl,
.release = mycdev_close,
};
static int __init mycdev_init(void)
{
//定义一个long类型(匹配ioremap函数第一个参数),用来保存每个寄存器的地址信息
volatile unsigned long tmp = 0;
//定义一个led设备数量变量
int led_num = 0;
//注册设备,获得主设备号
major_led = register_chrdev(0, "led", &fops);
if (major_led < 0) {
printk("注册字符设备驱动失败\n");
return major_led;
}
printk("注册字符设备led驱动成功\n");
major_fan = register_chrdev(0, "fan", &fops);
if (major_fan < 0) {
printk("注册字符设备fan驱动失败\n");
return major_fan;
}
printk("注册字符设备驱动成功\n");
major_buz = register_chrdev(0, "buz", &fops);
if (major_buz < 0) {
printk("注册字符设备驱动失败\n");
return major_buz;
}
printk("注册字符设备buz驱动成功\n");
major_mot = register_chrdev(0, "mot", &fops);
if (major_mot < 0) {
printk("注册字符设备驱动失败\n");
return major_mot;
}
printk("注册字符设备mot驱动成功\n");
//初始化几个寄存器,将物理地址映射到虚拟地址,以方便用户空间进行读写操作
//将地址信息强转为long类型方便tmp保存
tmp = (long)&GPIOB->MODER;
//将寄存器的物理地址映射到虚拟地址并保存
vir_gpiob_moder = ioremap(tmp, 4);
if (vir_gpiob_moder == NULL) {
printk("映射物理内存失败\n");
return -EFAULT;
}
//将地址信息强转为long类型方便tmp保存
tmp = (long)&GPIOE->MODER;
//将寄存器的物理地址映射到虚拟地址并保存
vir_gpioe_moder = ioremap(tmp, 4);
if (vir_gpioe_moder == NULL) {
printk("映射物理内存失败\n");
return -EFAULT;
}
//将地址信息强转为long类型方便tmp保存
tmp = (long)&GPIOF->MODER;
//将寄存器的物理地址映射到虚拟地址并保存
vir_gpiof_moder = ioremap(tmp, 4);
if (vir_gpioe_moder == NULL) {
printk("映射物理内存失败\n");
return -EFAULT;
}
//将地址信息强转为long类型方便tmp保存
tmp = (long)&GPIOB->ODR;
//将寄存器的物理地址映射到虚拟地址并保存
vir_gpiob_odr = ioremap(tmp, 4);
if (vir_gpiob_odr == NULL) {
printk("映射物理内存失败\n");
return -EFAULT;
}
//将地址信息强转为long类型方便tmp保存
tmp = (long)&GPIOE->ODR;
//将寄存器的物理地址映射到虚拟地址并保存
vir_gpioe_odr = ioremap(tmp, 4);
if (vir_gpioe_odr == NULL) {
printk("映射物理内存失败\n");
return -EFAULT;
}
//将地址信息强转为long类型方便tmp保存
tmp = (long)&GPIOF->ODR;
//将寄存器的物理地址映射到虚拟地址并保存
vir_gpiof_odr = ioremap(tmp, 4);
if (vir_gpiof_odr == NULL) {
printk("映射物理内存失败\n");
return -EFAULT;
}
//将地址信息强转为long类型方便tmp保存
tmp = (long)&RCC->MP_AHB4ENSETR;
//将寄存器的物理地址映射到虚拟地址并保存
vir_rcc = ioremap(tmp, 4);
if (vir_rcc == NULL) {
printk("映射物理内存失败\n");
return -EFAULT;
}
printk("映射物理内存成功\n");
//初始化几个寄存器的值
//设置RCC_MP_AHB4ENSETR寄存器第1第4第5两个引脚为1,使能GPIOB,GPIOE,GPIOF
*vir_rcc |= (0b11001 << 1);
//设置GPIOB_MODER第12-13位为01(TIM4)
*vir_gpiob_moder &= ~(0b11 << 12);
*vir_gpiob_moder |= (0b01 << 12);
//设置GPIOE_MODER第20-21位为01(LED1),第18-19位为01(TIM1),第16-17位为01(LED3输出)
*vir_gpioe_moder &= ~(0b111111 << 16);
*vir_gpioe_moder |= (0b010101 << 16);
//设置GPIOF_MODER第20-21位为01(LED2),第12-13位为01(TIM16)
*vir_gpiof_moder &= ~(0b11 << 20);
*vir_gpiof_moder |= (0b01 << 20);
*vir_gpiof_moder &= ~(0b11 << 12);
*vir_gpiof_moder |= (0b01 << 12);
//设置GPIOB_ODR第6位为0(TIM4)
*vir_gpiob_odr &= ~(0b1 << 6);
//设置GPIOE_ODR第10位为0(LED1),第9位为0(TIM1),第8位为0(LED3)
*vir_gpioe_odr &= ~(0b111 << 8);
//设置GPIOF_ODR第10位为0(LED2),第6位为0(TIM16)
*vir_gpiof_odr &= ~(0b1 << 10);
*vir_gpiof_odr &= ~(0b1 << 6);
printk("寄存器初始化成功\n");
//向上提交struct class设备目录信息
cls_led = class_create(THIS_MODULE, "my_led");
if (IS_ERR_VALUE(cls_led)) {
printk("向上提交目录失败\n");
return -PTR_ERR(cls_led);
}
//向上提交struct device设备节点信息
for (led_num = 0; led_num < 3; led_num++) {
dev_led =
device_create(cls_led, NULL, MKDEV(major_led, led_num),
NULL, "LED%d", led_num);
if (IS_ERR(dev_led)) {
printk("向上提交设备节点信息失败\n");
return -PTR_ERR(dev_led);
}
}
printk("向上提交设备节点信息成功\n");
//向上提交struct class设备目录信息
cls_fan = class_create(THIS_MODULE, "my_fan");
if (IS_ERR_VALUE(cls_fan)) {
printk("向上提交目录失败\n");
return -PTR_ERR(cls_fan);
}
//向上提交struct device设备节点信息
dev_fan = device_create(cls_fan, NULL, MKDEV(major_fan, 0), NULL,"FAN");
if (IS_ERR(dev_fan)) {
printk("向上提交设备节点信息失败\n");
return -PTR_ERR(dev_fan);
}
printk("向上提交设备节点信息成功\n");
//向上提交struct class设备目录信息
cls_buz = class_create(THIS_MODULE, "my_buz");
if (IS_ERR_VALUE(cls_buz)) {
printk("向上提交目录失败\n");
return -PTR_ERR(cls_buz);
}
//向上提交struct device设备节点信息
dev_buz = device_create(cls_buz, NULL, MKDEV(major_buz, 0), NULL,"BUZ");
if (IS_ERR(dev_buz)) {
printk("向上提交设备节点信息失败\n");
return -PTR_ERR(dev_buz);
}
//向上提交struct class设备目录信息
cls_mot = class_create(THIS_MODULE, "my_mot");
if (IS_ERR_VALUE(cls_mot)) {
printk("向上提交目录失败\n");
return -PTR_ERR(cls_mot);
}
//向上提交struct device设备节点信息
dev_mot = device_create(cls_mot, NULL, MKDEV(major_mot, 0), NULL,"MOT");
if (IS_ERR(dev_mot)) {
printk("向上提交设备节点信息失败\n");
return -PTR_ERR(dev_mot);
}
return 0;
}
static void __exit mycdev_exit(void)
{
//定义一个led设备数量变量
int led_num = 0;
//销毁设备节点信息
for (led_num = 0; led_num < 3; led_num++) {
device_destroy(cls_led, MKDEV(major_led, led_num));
}
device_destroy(cls_fan, MKDEV(major_fan, 0));
device_destroy(cls_buz, MKDEV(major_buz, 0));
device_destroy(cls_mot, MKDEV(major_mot, 0));
//销毁设备目录
class_destroy(cls_led);
class_destroy(cls_fan);
class_destroy(cls_buz);
class_destroy(cls_mot);
//取消物理内存映射
iounmap(vir_gpiob_moder);
iounmap(vir_gpioe_moder);
iounmap(vir_gpiof_moder);
iounmap(vir_gpiob_odr);
iounmap(vir_gpioe_odr);
iounmap(vir_gpiof_odr);
iounmap(vir_rcc);
printk("设备卸载\n");
//取消注册设备信息
unregister_chrdev(major_led, "led");
unregister_chrdev(major_fan, "fan");
unregister_chrdev(major_buz, "buz");
unregister_chrdev(major_mot, "mot");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
应用层代码
ioctl.c
cpp
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include "head.h"
int main()
{
int dev = 0;
char buf[128] = {0};
fprintf(stdout,"调用open\n");
int fd_led = open("/dev/LED0",O_RDWR);
if( fd_led < 0)
{
perror("");
exit(-1);
}
int fd_fan = open("/dev/FAN",O_RDWR);
if( fd_fan < 0)
{
perror("");
exit(-1);
}
int fd_buz = open("/dev/BUZ",O_RDWR);
if( fd_buz < 0)
{
perror("");
exit(-1);
}
int fd_mot = open("/dev/MOT",O_RDWR);
if( fd_mot < 0)
{
perror("");
exit(-1);
}
while(1)
{
fprintf(stdout,"请输入开关选项:\n");
fprintf(stdout,"先输入0123控制器件,再紧跟输入1开,0关\n");
fprintf(stdout,"11开1号灯,10关1号灯以此类推\n");
fprintf(stdout,"输入q来结束\n");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf) - 1] = '\0';
//如果输入的是q或Q,结束循环
if(buf[0] == 'q' || buf[0] == 'Q')
{
break;
}
else if(buf[0] == '0')
{
dev = 0;
if(buf[1] == '1' && buf[2] == '0')
{
ioctl(fd_led, LED1_OFF, dev);
}
else if(buf[1] == '1' && buf[2] == '1')
{
ioctl(fd_led, LED1_ON, dev);
}
else if(buf[1] == '2' && buf[2] == '0')
{
ioctl(fd_led, LED2_OFF, dev);
}
else if(buf[1] == '2' && buf[2] == '1')
{
ioctl(fd_led, LED2_ON, dev);
}
else if(buf[1] == '3' && buf[2] == '0')
{
ioctl(fd_led, LED3_OFF, dev);
}
else if(buf[1] == '3' && buf[2] == '1')
{
ioctl(fd_led, LED3_ON, dev);
}
}
else if(buf[0] == '1')
{
dev = 1;
if(buf[1] == '0')
{
ioctl(fd_fan, FAN_OFF, dev);
}
else if(buf[1] == '1')
{
ioctl(fd_fan, FAN_ON, dev);
}
}
else if(buf[0] == '2')
{
dev = 2;
if(buf[1] == '0')
{
ioctl(fd_buz, BUZ_OFF, dev);
}
else if(buf[1] == '1')
{
ioctl(fd_buz, BUZ_ON, dev);
}
}
else if(buf[0] == '3')
{
dev = 3;
if(buf[1] == '0')
{
ioctl(fd_mot, MOT_OFF, dev);
}
else if(buf[1] == '1')
{
ioctl(fd_mot, MOT_ON, dev);
}
}
}
close(fd_led);
close(fd_fan);
close(fd_buz);
close(fd_mot);
return 0;
}