内核代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "myled.h"
#define CNAME "myled"
int major;//1.定义一个变量,保存字符设备创建成功之后,得到的主设备号
struct class *cls;
struct device *dev;
char kbuf[128]={0};
volatile gpio_t* virt_gpioe;
volatile gpio_t* virt_gpiof;
volatile gpio_t* virt_gpioz;
volatile gpio_t* virt_gpiob;
volatile unsigned int* virt_rcc_gpioe;
volatile unsigned int* virt_rcc_gpioz;
int mycdev_open(struct inode *inode, struct file *file)
{
printk("open:%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int flag,ret;
switch(cmd)
{
//开灯
case LED_ON:
//从用户空间获取数据
ret = copy_from_user(&flag,(void*)arg, sizeof(int));
if(ret)
{
printk("copy_from_user error\n");
return -ENOMEM;
}
//选择那一盏灯
switch (flag)
{
case 1:
virt_gpioe->ODR |= (1 << 10);
break;
case 2:
virt_gpiof->ODR |= (1 << 10);
break;
case 3:
virt_gpioe->ODR |= (1 << 8);
break;
default:
break;
}
break;
//关灯
case LED_OFF:
ret = copy_from_user(&flag,(void*)arg, sizeof(int));
if(ret)
{
printk("copy_from_user failed\n");
return -ENOMEM;
}
switch (flag)
{
case 1:
virt_gpioe->ODR &= (~(1 << 10));
break;
case 2:
virt_gpiof->ODR &= (~(1 << 10));
break;
case 3:
virt_gpioe->ODR &= (~(1 << 8));
break;
default:
break;
}
break;
case LED_ZB_ON:
ret = copy_from_user(&flag,(void*)arg, sizeof(int));
if(ret)
{
printk("copy_from_user failed\n");
return -ENOMEM;
}
switch (flag)
{
case 1:
virt_gpioz->ODR |= (1 << 5);
break;
case 2:
virt_gpioz->ODR |= (1 << 6);
break;
case 3:
virt_gpioz->ODR |= (1 << 7);
break;
default:
break;
}
break;
case LED_ZB_OFF:
ret = copy_from_user(&flag,(void*)arg, sizeof(int));
if(ret)
{
printk("copy_from_user failed\n");
return -ENOMEM;
}
switch (flag)
{
case 1:
virt_gpioz->ODR &= (~(1 << 5));
break;
case 2:
virt_gpioz->ODR &= (~(1 << 6));
break;
case 3:
virt_gpioz->ODR &= (~(1 << 7));
break;
default:
break;
}
break;
case BEE_ON:
virt_gpiob->ODR |= (1 << 6);
break;
case BEE_OFF:
virt_gpiob->ODR &= (~(1 << 6));
break;
case MON_ON:
virt_gpiof->ODR |= (1 << 6);
break;
case MON_OFF:
virt_gpiof->ODR &= (~(1 << 6));
break;
}
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;
}
int mycdev_close(struct inode *inode, struct file *file)
{
printk("close:%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
const struct file_operations fops ={
.open=mycdev_open,
.read=mycdev_read,
.write=mycdev_write,
.release=mycdev_close,
.unlocked_ioctl=mycdev_ioctl,
};
static int __init mycdev_init(void)
{
major = register_chrdev(0,CNAME,&fops);
if(major < 0)
{
printk("register chrdev is error\n");
}
printk("register chrdev major=%d\n",major);
virt_gpioe = ioremap(PHY_GPIOE_MODER,sizeof(gpio_t));
if(NULL == virt_gpioe)
{
printk("virt_gpioe ioremap is error\n");
return -EIO;
}
virt_gpiob = ioremap(PHY_GPIOb_MODER,sizeof(gpio_t));
if(NULL == virt_gpiob)
{
printk("virt_gpiob ioremap is error\n");
return -EIO;
}virt_gpioz = ioremap(PHY_GPIOZ_MODER,sizeof(gpio_t));
if(NULL == virt_gpioz)
{
printk("virt_gpioz ioremap is error\n");
return -EIO;
}virt_gpiof = ioremap(PHY_GPIOF_MODER,sizeof(gpio_t));
if(NULL == virt_gpiof)
{
printk("virt_gpiof ioremap is error\n");
return -EIO;
}
virt_rcc_gpioe = ioremap(PHY_RCC_GPIOE,4);
if(NULL == virt_rcc_gpioe)
{
printk("gpioe rcc ioremap is error\n");
return -EIO;
}
virt_rcc_gpioz = ioremap(PHY_RCC_GPIOZ,4);
if(NULL == virt_rcc_gpioz)
{
printk("gpioz rcc ioremap is error\n");
return -EIO;
}
//PE10
*virt_rcc_gpioe |= (0x1 << 4);
virt_gpioe->MODER &= (~(0x3 << 20));
virt_gpioe->MODER |= (0x1 << 20);
virt_gpioe->ODR &= (~(0x1 << 10));
//PF10
*virt_rcc_gpioe |= (0x1 << 5);
virt_gpiof->MODER &= (~(0x3 << 20));
virt_gpiof->MODER |= (0x1 << 20);
virt_gpiof->ODR &= (~(0x1 << 10));
//PE8
virt_gpioe->MODER &= (~(0x3 << 16));
virt_gpioe->MODER |= (0x1 << 16);
virt_gpioe->ODR &= (~(0x1 << 8));
//PZ5-7
*virt_rcc_gpioz |= (1 << 0);
(virt_gpioz->MODER) &= (~(3 << 10));
(virt_gpioz->MODER) |= (1 << 10);
(virt_gpioz->ODR) &= (~(1<<5));
(virt_gpioz->MODER) &= (~(3 << 12));
(virt_gpioz->MODER) |= (1 << 12);
(virt_gpioz->ODR) &= (~(1<<6));
(virt_gpioz->MODER) &= (~(3 << 14));
(virt_gpioz->MODER) |= (1 << 14);
(virt_gpioz->ODR) &= (~(1<<7));
//蜂鸣器
(virt_gpiob->MODER) &= (~(3 << 12));
(virt_gpiob->MODER) |= (1 << 12);
(virt_gpiob->ODR) &= (~(1<<6));
//马达
(virt_gpiof->MODER) &= (~(3 << 12));
(virt_gpiof->MODER) |= (1 << 12);
(virt_gpiof->ODR) &= (~(1<<6));
printf("register init successful!!!\n");
return 0;
}
static void __exit mycdev_exit(void)
{
iounmap(virt_rcc_gpioe);
iounmap(virt_rcc_gpioz);
iounmap(virt_gpiof);
iounmap(virt_gpioe);
iounmap(virt_gpiob);
iounmap(virt_gpioz);
unregister_chrdev(major,CNAME);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
应用层代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include "myled.h"
char buf[128] = "0";
int main(int argc, char const *argv[])
{
int fd = -1;
int whitch;
int num, flag;
fd = open("/dev/myled",O_RDWR);
if(-1 == fd)
{
perror("open is error");
exit(1);
}
while(1)
{
//先给一个无效的值
whitch = -1;
printf("1、辅助版LED亮灭\n");
printf("2、主板LED亮灭\n");
printf("3、蜂鸣器控制\n");
printf("4、马达控制\n");
printf("请选择一个操作>>>");
scanf("%d", &whitch);
switch (whitch)
{
case LED_FZ:
num = -1;
printf("1、LED1\n2、LED1\n3、LED1\n");
printf("请选择一个操作>>>");
scanf("%d", &num);
printf("1、亮\n2、灭");
printf("请选择一个操作>>>");
scanf("%d", &flag);
if(flag)
{
ioctl(fd,LED_ON,&flag);
}else if(!flag)
{
ioctl(fd,LED_OFF,&flag);
}
break;
case LED_ZB:
num = -1;
printf("1、LED1\n2、LED1\n3、LED1\n");
printf("请选择一个操作>>>");
scanf("%d", &num);
printf("1、亮\n2、灭");
printf("请选择一个操作>>>");
scanf("%d", &flag);
if(flag)
{
ioctl(fd,LED_ZB_ON,&flag);
}else if(!flag)
{
ioctl(fd,LED_ZB_OFF,&flag);
}
break;
case BEE:
printf("1、工作\n2、不工作");
printf("请选择一个操作>>>");
scanf("%d", &flag);
if(flag)
{
ioctl(fd,BEE_ON,&flag);
}else if(!flag)
{
ioctl(fd,BEE_OFF,&flag);
}
break;
case MON:
printf("1、工作\n2、不工作");
printf("请选择一个操作>>>");
scanf("%d", &flag);
if(flag)
{
ioctl(fd,MON_ON,&flag);
}else if(!flag)
{
ioctl(fd,MON_OFF,&flag);
}
break;
default:
printf("输入有误,请重新输入!!!\n");
break;
}
}
close(fd);
return 0;
}
头文件
#ifndef __LED_H__
#define __LED_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;
}gpio_t;
typedef enum{
LED1 = 0,
LED2,
LED3
}led_t;
enum{
LED_FZ = 1,
LED_ZB,
BEE,
MON
};
#define PHY_GPIOZ_MODER 0X54004000
#define PHY_GPIOb_MODER 0X50003000
#define PHY_GPIOE_MODER 0x50006000
#define PHY_GPIOF_MODER 0x50007000
#define PHY_RCC_GPIOE 0x50000A28
#define PHY_RCC_GPIOZ 0X50000210
//辅助板LED亮灭
#define LED_ON _IOW('a',1,int)
#define LED_OFF _IOW('a',0,int)
//主板LED亮灭
#define LED_ZB_ON _IOW('a',1,int)
#define LED_ZB_OFF _IOW('a',0,int)
//蜂鸣器工作/不工作
#define BEE_ON _IOW('a',1,int)
#define BEE_OFF _IOW('a',0,int)
//马达工作/不工作
#define MON_ON _IOW('a',1,int)
#define MON_OFF _IOW('a',0,int)
#endif