day3 驱动开发 c语言编程

通过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;
}
相关推荐
lulu_gh_yu18 分钟前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
AAA 建材批发王哥(天道酬勤)2 小时前
JVM 由多个模块组成,每个模块负责特定的功能
jvm
~yY…s<#>2 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
EricWang13584 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
我是谁??4 小时前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
希言JY5 小时前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
午言若5 小时前
C语言比较两个字符串是否相同
c语言
TeYiToKu6 小时前
笔记整理—linux驱动开发部分(9)framebuffer驱动框架
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件·arm
互联网打工人no17 小时前
每日一题——第一百二十四题
c语言