day2 驱动开发 c语言

通过驱动开发给pcb板子点灯。

u-boot已经提前移植到了emmc中。

灯也是一种字符型设备。

编程流程需要先注册设备,然后创建结点,然后操作电灯相关寄存器

应用层直接调用read write来打开字符设备进行操作。

这样写会造成无法处理内核页面请求的虚拟地址内部错误,没找到解决方法

day2 驱动开发 c语言_第1张图片

head.h

#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)

#endif

mychrdev.c

#include 
#include 
#include 
#include 
#include 
#include "head.h"

unsigned int major; //定义一个变量保存主设备号
char kbuf[128] = {0};//定义一个内核中的buffer
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;
//封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}
ssize_t mycdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *lof)
{
    int res;
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    res = copy_to_user(ubuf, kbuf, size);
    if(res != 0)
    {
        printk("copy_to_user failed\n");
        return -EIO;
    }
    
    return 0;
}

ssize_t mycdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lof)
{
    int res;
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    res = copy_from_user(kbuf, ubuf, size);
    if(res != 0)
    {
        printk("copy_from_user failed\n");
        return -EIO;
    }
    //LED1开灯
    if(kbuf[0] == '1' && kbuf[1] == '1')
    {
        *vir_gpioe_odr |= 0x1 << 10;
    }
    //LED1关灯
    if(kbuf[0] == '1' && kbuf[1] == '0')
    {
        *vir_gpioe_odr &= ~(0x1 << 10);
    }    
    //LED2开灯
    if(kbuf[0] == '2' && kbuf[1] == '1')
    {
        *vir_gpiof_odr |= 0x1 << 10;
    }
    //LED2关灯
    if(kbuf[0] == '2' && kbuf[1] == '0')
    {
        *vir_gpiof_odr &= ~(0x1 << 10);
    }    
    //LED3开灯
    if(kbuf[0] == '3' && kbuf[1] == '1')
    {
        *vir_gpioe_odr |= 0x1 << 8;
    }
    //LED3关灯
    if(kbuf[0] == '3' && kbuf[1] == '0')
    {
        *vir_gpioe_odr &= ~(0x1 << 8);
    }
    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,
    .read = mycdev_read,
    .write = mycdev_write,
    .release = mycdev_close,
};

static int __init mycdev_init(void)
{
    volatile int *tmp = NULL;
    major = register_chrdev(0,"mychrdev",&fops);
    if(major < 0)
    {
        printk("注册字符设备驱动失败\n");
        return major;
    }
    printk("注册字符设备驱动成功\n");
    //初始化几个寄存器,将物理地址映射到虚拟地址,以方便用户空间进行读写操作
    tmp = &GPIOE->MODER;
    vir_gpioe_moder = ioremap(*tmp,4);
    if(vir_gpioe_moder == NULL)
    {
        printk("映射物理内存失败");
        return -EFAULT;
    }
    vir_gpiof_moder = ioremap(GPIOF->MODER,4);
    if(vir_gpioe_moder == NULL)
    {
        printk("映射物理内存失败");
        return -EFAULT;
    }
    vir_gpioe_odr = ioremap(GPIOE->ODR,4);
    if(vir_gpioe_odr == NULL)
    {
        printk("映射物理内存失败");
        return -EFAULT;
    }
    vir_gpiof_odr = ioremap(GPIOF->ODR,4);
    if(vir_gpiof_odr == NULL)
    {
        printk("映射物理内存失败");
        return -EFAULT;
    }
    vir_rcc = ioremap(RCC->MP_AHB4ENSETR,4);
    if(vir_rcc == NULL)
    {
        printk("映射物理内存失败");
        return -EFAULT;
    }
    //初始化几个寄存器的值
    //设置RCC_MP_AHB4ENSETR寄存器第4第5两个引脚为1,使能GPIOE,GPIOF
    *vir_rcc |= (0b11 << 4);
    //设置GPIOE_MODER第20-21位为01
    *vir_gpioe_moder &= ~(0b11 << 20);
    *vir_gpioe_moder |= (0b01 << 20);
    //设置GPIOF_MODER第20-21位为01
    *vir_gpiof_moder &= ~(0b11 << 20);
    *vir_gpiof_moder |= (0b01 << 20);
    //设置GPIOE_MODER第16-17位为01
    *vir_gpioe_moder &= ~(0b11 << 16);
    *vir_gpioe_moder |= (0b01 << 16);
    //设置GPIOE_ODR第10位为0
    *vir_gpioe_odr &= ~(0b1 << 10);
    //设置GPIOF_ODR第10位为0
    *vir_gpiof_odr &= ~(0b1 << 10);
    //设置GPIOE_ODR第8位为0
    *vir_gpiof_odr &= ~(0b1 << 8);
    return 0;
}

static void __exit mycdev_exit(void)
{
    printk("设备卸载\n");
    unregister_chrdev(major,"mychrdev");
}

module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

led.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
    char buf[128] = {0};
    fprintf(stdout,"调用open\n");
    int fd = open("/dev/mychrdev",O_RDWR);
    if( fd < 0)
    {
        perror("");
        exit(-1);
    }
    while(1)
    {
        fprintf(stdout,"请输入开关选项:\n");
        
        fgets(buf,sizeof(buf),stdin);
        buf[strlen(buf) - 1] = '\0';
        fprintf(stdout,"调用write\n");
        write(fd,buf,sizeof(buf));
    }
    close(fd);
    return 0;
}

————————————————————————————————————

后来发现追了一下ioremap函数的参数。第一个参数应该是一个long类型的变量,变量中保存的应该是寄存器的物理地址信息。

所以一开始传参传入的是寄存器的值是不对的。

但又因为如果直接传入取地址的寄存器会造成指针类型和long类型的隐性强转,编译器会报错。

所以得先定义一个long类型的tmp变量,用来保存每一个寄存器的物理地址信息。通过tmp中的值再去映射到虚拟地址。

以下是改版的mychrdev.c

#include 
#include 
#include 
#include 
#include 
#include "head.h"

unsigned int major; //定义一个变量保存主设备号
char kbuf[128] = {0};//定义一个内核中的buffer
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;
//封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}
ssize_t mycdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *lof)
{
    int res;
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    //如果用户请求的buffer不满足用户需求,最大限度的满足用户需求
    if(size > sizeof(kbuf))
    {
        size = sizeof(kbuf);
    }
    res = copy_to_user(ubuf, kbuf, size);
    if(res != 0)
    {
        printk("copy_to_user failed\n");
        return -EIO;
    }
    
    return 0;
}

ssize_t mycdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lof)
{
    int res;
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    //如果用户请求的buffer不满足用户需求,最大限度的满足用户需求
    if(size > sizeof(kbuf))
    {
        size = sizeof(kbuf);
    }
    res = copy_from_user(kbuf, ubuf, size);
    if(res != 0)
    {
        printk("copy_from_user failed\n");
        return -EIO;
    }
    //LED1开灯
    if(kbuf[0] == '1' && kbuf[1] == '1')
    {
        *vir_gpioe_odr |= 0x1 << 10;
    }
    //LED1关灯
    if(kbuf[0] == '1' && kbuf[1] == '0')
    {
        *vir_gpioe_odr &= ~(0x1 << 10);
    }    
    //LED2开灯
    if(kbuf[0] == '2' && kbuf[1] == '1')
    {
        *vir_gpiof_odr |= 0x1 << 10;
    }
    //LED2关灯
    if(kbuf[0] == '2' && kbuf[1] == '0')
    {
        *vir_gpiof_odr &= ~(0x1 << 10);
    }    
    //LED3开灯
    if(kbuf[0] == '3' && kbuf[1] == '1')
    {
        *vir_gpioe_odr |= 0x1 << 8;
    }
    //LED3关灯
    if(kbuf[0] == '3' && kbuf[1] == '0')
    {
        *vir_gpioe_odr &= ~(0x1 << 8);
    }
    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,
    .read = mycdev_read,
    .write = mycdev_write,
    .release = mycdev_close,
};

static int __init mycdev_init(void)
{
    //定义一个long类型(匹配ioremap函数第一个参数),用来保存每个寄存器的地址信息
    volatile unsigned long tmp = 0;
    major = register_chrdev(0,"mychrdev",&fops);
    if(major < 0)
    {
        printk("注册字符设备驱动失败\n");
        return major;
    }
    printk("注册字符设备驱动成功\n");
    //初始化几个寄存器,将物理地址映射到虚拟地址,以方便用户空间进行读写操作

    //将地址信息强转为long类型方便tmp保存
    tmp = (long)&GPIOE->MODER;
    //将寄存器的物理地址映射到虚拟地址并保存
    vir_gpioe_moder = ioremap(tmp,4);
    if(vir_gpioe_moder == NULL)
    {
        printk("映射物理内存失败");
        return -EFAULT;
    }
    //将地址信息强转为long类型方便tmp保存
    tmp = (long)&GPIOF->MODER;
    //将寄存器的物理地址映射到虚拟地址并保存
    vir_gpiof_moder = ioremap(tmp,4);
    if(vir_gpioe_moder == NULL)
    {
        printk("映射物理内存失败");
        return -EFAULT;
    }
    //将地址信息强转为long类型方便tmp保存
    tmp = (long)&GPIOE->ODR;
    //将寄存器的物理地址映射到虚拟地址并保存
    vir_gpioe_odr = ioremap(tmp,4);
    if(vir_gpioe_odr == NULL)
    {
        printk("映射物理内存失败");
        return -EFAULT;
    }
    //将地址信息强转为long类型方便tmp保存
    tmp = (long)&GPIOF->ODR;
    //将寄存器的物理地址映射到虚拟地址并保存
    vir_gpiof_odr = ioremap(tmp,4);
    if(vir_gpiof_odr == NULL)
    {
        printk("映射物理内存失败");
        return -EFAULT;
    }
    //将地址信息强转为long类型方便tmp保存
    tmp = (long)&RCC->MP_AHB4ENSETR;
    //将寄存器的物理地址映射到虚拟地址并保存
    vir_rcc = ioremap(tmp,4);
    if(vir_rcc == NULL)
    {
        printk("映射物理内存失败");
        return -EFAULT;
    }
    //初始化几个寄存器的值
    //设置RCC_MP_AHB4ENSETR寄存器第4第5两个引脚为1,使能GPIOE,GPIOF
    *vir_rcc |= (0b11 << 4);
    //设置GPIOE_MODER第20-21位为01
    *vir_gpioe_moder &= ~(0b11 << 20);
    *vir_gpioe_moder |= (0b01 << 20);
    //设置GPIOF_MODER第20-21位为01
    *vir_gpiof_moder &= ~(0b11 << 20);
    *vir_gpiof_moder |= (0b01 << 20);
    //设置GPIOE_MODER第16-17位为01
    *vir_gpioe_moder &= ~(0b11 << 16);
    *vir_gpioe_moder |= (0b01 << 16);
    //设置GPIOE_ODR第10位为0
    *vir_gpioe_odr &= ~(0b1 << 10);
    //设置GPIOF_ODR第10位为0
    *vir_gpiof_odr &= ~(0b1 << 10);
    //设置GPIOE_ODR第8位为0
    *vir_gpiof_odr &= ~(0b1 << 8);
    return 0;
}

static void __exit mycdev_exit(void)
{
    //取消物理内存映射
    iounmap(vir_gpioe_moder);
    iounmap(vir_gpiof_moder);
    iounmap(vir_gpioe_odr);
    iounmap(vir_gpiof_odr);
    iounmap(vir_rcc);
    printk("设备卸载\n");
    unregister_chrdev(major,"mychrdev");
}

module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

改进的led.c,增加了一点儿注释

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
    char buf[128] = {0};
    fprintf(stdout,"调用open\n");
    int fd = open("/dev/mychrdev",O_RDWR);
    if( fd < 0)
    {
        perror("");
        exit(-1);
    }
    while(1)
    {
        fprintf(stdout,"请输入开关选项:\n");
        fprintf(stdout,"先输入123控制led1,led2,led3,再紧跟输入1开灯,0关灯\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;
        }
        fprintf(stdout,"调用write\n");
        write(fd,buf,sizeof(buf));
    }
    close(fd);
    return 0;
}

你可能感兴趣的:(驱动开发,c语言,开发语言)