#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include "mycdev.h"
#include <linux/io.h>
//
//定义三个指针 指向映射后的虚拟地址
unsigned int *VIR_GPIOE_MODER;
unsigned int *VIR_GPIOE_ODR;
unsigned int *VIR_GPIOF_MODER;
unsigned int *VIR_GPIOF_ODR;
unsigned int *VIR_RCC;
unsigned int major;
char kbuf[2]= {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 *iof)
{
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
int ret = 0;
if (size > sizeof(kbuf))
size = sizeof(kbuf);
ret = copy_to_user(ubuf, kbuf, size);
if (ret)
{
printk("copy to user filed\n");
return -EIO;
}
return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *iof)
{
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
int ret = 0;
if (size > sizeof(kbuf))
size = sizeof(kbuf);
ret = copy_from_user(kbuf, ubuf, size);
if (ret)
{
printk("copy from user filed\n");
return -EIO;
}
switch(kbuf[0])
{
case '1':
{
if (kbuf[1] == '1')
(*VIR_GPIOE_ODR) |= (0x1 << 10);
else
(*VIR_GPIOE_ODR) &= (~(0x1 << 10));
break;
}
case '2':
{
if (kbuf[1] == '1')
(*VIR_GPIOF_ODR) |= (0x1 << 10);
else
(*VIR_GPIOF_ODR) &= (~(0x0 << 10));
break;
}
case '3':
{
if (kbuf[1] == '1')
(*VIR_GPIOE_ODR) |= (0x1 << 8);
else
(*VIR_GPIOE_ODR) &= (~(0x0 << 8));
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,
.release = mycdev_close,
};
//入口
//led_init uart_init lcd_init
//__init:是给编译器使用的, 告诉编译器这个函数放在.init.text段中
static int __init mycdev_init(void)
{
//字符设备驱动的注册
major = register_chrdev(0, "mycdev", &fops);
if (major < 0)
{
printk("字符设备驱动注册失败\n");
}
printk("字符设备驱动注册成功major = %d\n", major);
///
//进行相关寄存器地址映射
VIR_GPIOE_MODER = ioremap(PHY_GPIOE_MODER, 4);
if (NULL == VIR_GPIOE_MODER)
{
printk("1物理地址映射失败\n");
return -EFAULT;
}
VIR_GPIOE_ODR = ioremap(PHY_GPIOE_ODR, 4);
if (NULL == VIR_GPIOE_ODR)
{
printk("2物理地址映射失败\n");
return -EFAULT;
}
VIR_GPIOF_MODER = ioremap(PHY_GPIOF_MODER, 4);
if (NULL == VIR_GPIOF_MODER)
{
printk("3物理地址映射失败\n");
return -EFAULT;
}
VIR_GPIOF_ODR = ioremap(PHY_GPIOF_ODR, 4);
if (NULL == VIR_GPIOF_ODR)
{
printk("4物理地址映射失败\n");
return -EFAULT;
}
VIR_RCC = ioremap(PHY_RCC, 4);
if (NULL == VIR_RCC)
{
printk("5物理地址映射失败\n");
return -EFAULT;
}
//
(*VIR_RCC) |= (0x1 << 4);
(*VIR_RCC) |= (0x1 << 5);
(*VIR_GPIOE_MODER) &= (~(0x3 << 20));
(*VIR_GPIOE_MODER) |= (0x1 << 20);
(*VIR_GPIOF_MODER) &= (~(0x3 << 20));
(*VIR_GPIOF_MODER) |= (0x1 << 20);
(*VIR_GPIOE_MODER) &= (~(0x3 << 16));
(*VIR_GPIOF_MODER) |= (0x1 << 16);
printk("相关寄存器初始化\n");
return 0;
}
//出口
//demo_exit驱动出口的名字
//led_exit uart_exit lcd_exit
//__exit:是给编译器使用的
static void __exit mycdev_exit(void)
{
iounmap(VIR_RCC);
iounmap(VIR_GPIOE_ODR);
iounmap(VIR_GPIOF_ODR);
iounmap(VIR_GPIOF_MODER);
iounmap(VIR_GPIOF_MODER);
unregister_chrdev(major, "mycdev");
printk(KERN_ERR "EXIT\n");
}
//告诉内核入口的地址
module_init(mycdev_init);
//告诉内核出口的地址
module_exit(mycdev_exit);
//许可证
MODULE_LICENSE("GPL");
#ifndef __MYCDEV_H__
#define __MYCDEV_H__
#define PHY_RCC 0X50000A28
#define PHY_GPIOE_MODER 0X50006000
#define PHY_GPIOE_ODR 0X50006014
#define PHY_GPIOF_MODER 0X50007000
#define PHY_GPIOF_ODR 0X50007014
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char protocol[2] = {0};
int fd = open("/dev/mycdev", O_RDWR);
if (fd < 0)
{
perror("open");
exit(1);
}
while (1)
{
printf("控制LED1 (1) LED2(2) LED3(3)\n");
protocol[0] = fgetc(stdin);
printf("控制亮(1) 灭(0)\n");
protocol[1] = fgetc(stdin) ;
write(fd, protocol, sizeof(protocol));
}
close(fd);
return 0;
}