head.c
#ifndef __HEAD_H__
#define __HEAD_H__
//封装寄存器结体
typedef struct{
volatile unsigned int MODER;
volatile unsigned int OTYPER;
volatile unsigned int OSPEEDR;
volatile unsigned int PUPDR;
volatile unsigned int IDR;
volatile unsigned int ODR;
volatile unsigned int BSRR;
}gpio_t;
#define PHY_RCC_ADDR 0X50000A28
#define AHB5_RCC_ADDR 0x50000210
#define PHY_LED1_ADDR 0X50006000
#define PHY_LED2_ADDR 0X50007000
#define PHY_LED3_ADDR 0X50006000
#define AHB5_LED_ADDR 0x54004000
//封装LED1开关的功能码
#define LED_ON _IOW('l',1,int)//开灯
#define LED_OFF _IOW('l',0,int)//关灯
#endif
led_dev.c
#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"
int major;
struct class *cls;
struct device *dev;
//定义一些变量接收映射后的虚拟地址
unsigned int *vir_rcc;
unsigned int *AHB5_rcc;
gpio_t *vir_led1;
gpio_t *vir_led2;
gpio_t *vir_led3;
gpio_t *AHB5_LED;
char kbuf[128]={0};
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 *ubuf, size_t size, loff_t *off)
{
int ret;
//判断kbuf的大小,如果<size,把size的数值修改为kbuf的大小
if(size>sizeof(kbuf))
size=sizeof(kbuf);
ret=copy_to_user(ubuf,kbuf,size);
if(ret)
{
printk("copy_to_user filed\n");
return -EIO;//拷贝失败返回错误码
}
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *off)
{
int ret;
if(size>sizeof(kbuf))
size=sizeof(kbuf);
ret=copy_from_user(kbuf,ubuf,size);
if(ret)
{
printk("copy_from_user filed\n");
return -EIO;//拷贝失败返回错误码
}
return 0;
}
//ioctl
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int which,ret;
switch(cmd)
{
case LED_ON:
ret=copy_from_user(&which,(void *)arg,sizeof(int));//把ioctl第三个参数的数值获取到
if(ret)
{
printk("copy_from_user err\n");
return -ENOMEM;
}
switch(which)
{
case 1:
vir_led1->ODR |= (1<<10);
printk("LED1开灯\n");
break;
case 2:
vir_led2->ODR |= (1<<10);
printk("LED2开灯\n");
break;
case 3:
vir_led3->ODR |= (1<<8);
printk("LED3开灯");
break;
case 4:
AHB5_LED->ODR |= (1<<5);
printk("LEDa开灯");
break;
case 5:
AHB5_LED->ODR |= (1<<6);
printk("LEDb开灯");
break;
case 6:
AHB5_LED->ODR |= (1<<7);
printk("LEDc开灯");
break;
}
break;
case LED_OFF:
ret=copy_from_user(&which,(void *)arg,sizeof(int));//把ioctl第三个参数的数值获取到
if(ret)
{
printk("copy_from_user err\n");
return -ENOMEM;
}
switch(which)
{
case 1:
vir_led1->ODR &= (~(1<<10));
printk("LED1关灯\n");
break;
case 2:
vir_led2->ODR &= (~(1<<10));
printk("LED2关灯\n");
break;
case 3:
vir_led3->ODR &= (~(1<<8));
printk("LED3关灯");
break;
case 4:
AHB5_LED->ODR &= (~(1<<5));
printk("LEDa关灯");
break;
case 5:
AHB5_LED->ODR &= (~(1<<6));
printk("LEDb关灯");
break;
case 6:
AHB5_LED->ODR &= (~(1<<7));
printk("LEDc关灯");
break;
}
break;
}
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,
.unlocked_ioctl=mycdev_ioctl,
.release=mycdev_close,
};
void all_led_init(void)
{
//进行物理地址的映射
vir_led1=ioremap(PHY_LED1_ADDR,sizeof(gpio_t));
if(vir_led1==NULL)
{
printk("LED1寄存器映射失败\n");
}
vir_led2=ioremap(PHY_LED2_ADDR,sizeof(gpio_t));
if(vir_led2==NULL)
{
printk("LED2寄存器映射失败\n");
}
vir_led3=ioremap(PHY_LED3_ADDR,sizeof(gpio_t));
if(vir_led3==NULL)
{
printk("LED3寄存器映射失败\n");
}
AHB5_LED=ioremap(AHB5_LED_ADDR,sizeof(gpio_t));
vir_rcc=ioremap(PHY_RCC_ADDR,4);
if(vir_rcc==NULL)
{
printk("vir_rcc寄存器映射失败\n");
}
/*AHB5_rcc=ioremap(AHB5_RCC_ADDR,4);
if(AHB5_rcc==NULL)
{
printk("AHB5_RCC寄存器映射失败\n");
}*/
printk("寄存器物理地址映射成功\n");
//寄存器的初始化
vir_led1->MODER &= (~(3<<20));//设置为输出模式
vir_led1->MODER |= (1<<20);
vir_led1->ODR &= (~(1<<10));//输出低电平
vir_led2->MODER &= (~(3<<20));//设置为输出模式
vir_led2->MODER |= (1<<20);
vir_led2->ODR &= (~(1<<10));//输出低电平
vir_led3->MODER &= (~(3<<16));//设置为输出模式
vir_led3->MODER |= (1<<16);
vir_led3->ODR &= (~(1<<8));//输出低电平
AHB5_LED->MODER &= (~(3<<10));//设置为输出模式
AHB5_LED->MODER |= (1<<10);
AHB5_LED->ODR &= (~(1<<5));//输出低电平
AHB5_LED->MODER &= (~(3<<12));//设置为输出模式
AHB5_LED->MODER |= (1<<12);
AHB5_LED->ODR &= (~(1<<6));//输出低电平
AHB5_LED->MODER &= (~(3<<14));//设置为输出模式
AHB5_LED->MODER |= (1<<14);
AHB5_LED->ODR &= (~(1<<7));//输出低电平
(*vir_rcc) |= (3<<4);//rcc使能
printk("寄存器初始化成功\n");
//(*AHB5_rcc) |=(1);
}
//入口函数
static int __init mycdev_init(void)
{
int i;
//进行字符设备驱动的注册
major=register_chrdev(0,"mycdev",&fops);
if(major<0)
{
printk("字符设备驱动注册失败\n");
return major;
}
printk("字符设备驱动注册成功,major=%d\n",major);
//向上提交目录
cls=class_create(THIS_MODULE,"mycdev");
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,"mycdev%d",i);
if(IS_ERR(dev))//指针指向预留空间,函数调用失败
{
printk("向上提交目录失败\n");
return PTR_ERR(dev);
}
}
printk("设备节点向上提交成功\n");
//led寄存器初始化
all_led_init();
return 0;
}
//出口函数
static void __exit mycdev_exit(void)
{
int i;
//取消物理内存的映射
iounmap(vir_led1);
iounmap(vir_led2);
iounmap(vir_led3);
iounmap(vir_rcc);
iounmap(AHB5_LED);
//iounmap(AHB5_rcc);
//删除节点信息
for(i=0;i<3;i++)
{
device_destroy(cls,MKDEV(major,i));
}
//删除目录信息
class_destroy(cls);
//字符设备驱动的注销
unregister_chrdev(major,"mycdev");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
led.c
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include<string.h>
#include <sys/ioctl.h>
#include"head.h"
int main(int argc, char const *argv[])
{
char buf[128]={0};
int which,a;
int fd=open("/dev/mycdev0",O_RDWR);
if(fd<0)
{
printf("打开设备文件失败\n");
exit(-1);
}
//在终端输入数据
while(1)
{
printf("请输入要进行的操作:1(开灯) 0(关灯)->");
scanf("%d",&a);
if(a==1)
{
printf("请输入要进行操作的灯:1(LED1) 2(LED2) 3(LED3) 4(LEDa) 5(LEDb) 6(LEDc) ->");
scanf("%d",&which);
ioctl(fd,LED_ON,&which);
}
else
{
printf("请输入要进行操作的灯:1(LED1) 2(LED2) 3(LED3) 4(LEDa) 5(LEDb) 6(LEDc) ->");
scanf("%d",&which);
ioctl(fd,LED_OFF,&which);
}
}
close(fd);
return 0;
}
现象:
_____________________________________________________________________________
head.h
#ifndef __HEAD_H__
#define __HEAD_H__
#include "rcc.h"
#include "gpio.h"
//封装LED开关的功能码
#define PWM_ON _IOW('p',1,int)//开
#define PWM_OFF _IOW('p',0,int)//关
#endif
rcc.h
#ifndef __STM32MP1XX_RCC_H__
#define __STM32MP1XX_RCC_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 0x50000000
#endif // __STM32MP1XX_RCC_H__
gpio.h
#ifndef __STM32MP1xx_GPIO_H__
#define __STM32MP1xx_GPIO_H__
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 GPIOB 0x50003000
#define GPIOF 0x50007000
#endif // __STM32MP1xx_GPIO_H__
pwm_dev.c
#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"
int major;
struct class *cls;
struct device *dev;
//定义一些变量接收映射后的虚拟地址
gpio_t* beep_GPIOB;
gpio_t* mada_GPIOF;
rcc_t* pwm_RCC;
char kbuf[128]={0};
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 *ubuf, size_t size, loff_t *off)
{
int ret;
//判断kbuf的大小,如果<size,把size的数值修改为kbuf的大小
if(size>sizeof(kbuf))
size=sizeof(kbuf);
ret=copy_to_user(ubuf,kbuf,size);
if(ret)
{
printk("copy_to_user filed\n");
return -EIO;//拷贝失败返回错误码
}
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *off)
{
int ret;
if(size>sizeof(kbuf))
size=sizeof(kbuf);
ret=copy_from_user(kbuf,ubuf,size);
if(ret)
{
printk("copy_from_user filed\n");
return -EIO;//拷贝失败返回错误码
}
return 0;
}
//ioctl
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int which,ret;
switch(cmd)
{
case PWM_ON:
ret=copy_from_user(&which,(void *)arg,sizeof(int));//把ioctl第三个参数的数值获取到
if(ret)
{
printk("copy_from_user err\n");
return -ENOMEM;
}
switch(which)
{
case 1:
//RCC
pwm_RCC->MP_APB4ENSETR|=(0x1<<1);
pwm_RCC->MP_APB1ENSETR|=(0X1<<2);
//GPIO
beep_GPIOB->MODER&=(~(0x3<<12));
beep_GPIOB->MODER|=(0x1<<13);
beep_GPIOB->AFRL&=(~(0xF<<24));
beep_GPIOB->AFRL|=(0x1<<25);
printk("蜂鸣器开\n");
break;
case 2:
//RCC
pwm_RCC->MP_AHB4ENSETR|=(0x1<<5);
pwm_RCC->MP_APB2ENSETR|=(0x1<<3);
//GPIO
mada_GPIOF->MODER&=(~(0x3<<12));
mada_GPIOF->MODER|=(0x1<<13);
mada_GPIOF->AFRL&=(~(0xF<<24));
mada_GPIOF->AFRL|=(0x1<<24);
printk("马达开\n");
break;
case 3:
printk("\n");
break;
}
break;
case PWM_OFF:
ret=copy_from_user(&which,(void *)arg,sizeof(int));//把ioctl第三个参数的数值获取到
if(ret)
{
printk("copy_from_user err\n");
return -ENOMEM;
}
switch(which)
{
case 1:
printk("\n");
break;
case 2:
printk("\n");
break;
case 3:
printk("\n");
break;
}
break;
}
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,
.unlocked_ioctl=mycdev_ioctl,
.release=mycdev_close,
};
void all_led_init(void)
{
//进行物理地址的映射
beep_GPIOB=ioremap(GPIOB,sizeof(gpio_t));
if(beep_GPIOB==NULL)
{
printk("LED1寄存器映射失败\n");
}
mada_GPIOF=ioremap(GPIOF,sizeof(gpio_t));
if(mada_GPIOF==NULL)
{
printk("LED2寄存器映射失败\n");
}
pwm_RCC=ioremap(RCC,sizeof(rcc_t));
if(mada_GPIOF==NULL)
{
printk("LED2寄存器映射失败\n");
}
printk("寄存器物理地址映射成功\n");
//寄存器的初始化
printk("寄存器初始化成功\n");
}
//入口函数
static int __init mycdev_init(void)
{
int i;
//进行字符设备驱动的注册
major=register_chrdev(0,"mycdev",&fops);
if(major<0)
{
printk("字符设备驱动注册失败\n");
return major;
}
printk("字符设备驱动注册成功,major=%d\n",major);
//向上提交目录
cls=class_create(THIS_MODULE,"mycdev");
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,"mycdev%d",i);
if(IS_ERR(dev))//指针指向预留空间,函数调用失败
{
printk("向上提交目录失败\n");
return PTR_ERR(dev);
}
}
printk("设备节点向上提交成功\n");
//led寄存器初始化
all_led_init();
return 0;
}
//出口函数
static void __exit mycdev_exit(void)
{
int i;
//取消物理内存的映射
iounmap(pwm_RCC);
iounmap(beep_GPIOB);
iounmap(mada_GPIOF);
//删除节点信息
for(i=0;i<3;i++)
{
device_destroy(cls,MKDEV(major,i));
}
//删除目录信息
class_destroy(cls);
//字符设备驱动的注销
unregister_chrdev(major,"mycdev");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
pwm.c
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include<string.h>
#include <sys/ioctl.h>
#include"head.h"
int main(int argc, char const *argv[])
{
char buf[128]={0};
int which,a;
int fd=open("/dev/mycdev0",O_RDWR);
if(fd<0)
{
printf("打开设备文件失败\n");
exit(-1);
}
//在终端输入数据
while(1)
{
printf("请输入要进行的操作:1(开) 0(关)->");
scanf("%d",&a);
if(a==1)
{
printf("请输入要进行操作的设备:1(蜂鸣器) 2(马达) 3(风扇)->");
scanf("%d",&which);
ioctl(fd,PWM_ON,&which);
}
else
{
printf("请输入要进行操作的设备:1(蜂鸣器) 2(马达) 3(风扇)->");
scanf("%d",&which);
ioctl(fd,PWM_OFF,&which);
}
}
close(fd);
return 0;
}