嵌入式学习——硬件(Linux内核驱动编程LED、蜂鸣器、按键)——day59

  1. 编写LED驱动(初始化所有子设备号)
cpp 复制代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#define GPBCON  (0x56000010)
#define GPBDAT  (0x56000014)
static unsigned int *regGPBCON;
static unsigned int *regGPBDAT;

int led_driver_open(struct inode *p_node, struct file *fp)
{
	printk("open\n");
	return 0;
}

ssize_t led_driver_read(struct file *fp, char __user *user_buffer, size_t n, loff_t * offset)
{
	printk("read\n");
	return 0;
}

void ledOn(unsigned int n)
{
	*regGPBDAT |= (0x0F << 5);
	if(n < 1 || n > 4)
	{
		return;
	}
	*regGPBDAT &= ~(1 << (n + 4));
}

ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t *offset)
{
	char s[10];
	
	copy_from_user(s, user_buffer, n);
	ledOn(s[0]);

	printk("write\n");
	return n;
}

int led_driver_close(struct inode *p_node, struct file *fp)
{
	printk("close\n");
	return 0;
}

struct file_operations fops =
{	
	.owner = THIS_MODULE,
	.release = led_driver_close,
	.open = led_driver_open,
	.read = led_driver_read,
	.write = led_driver_write,
};

static int __init led_driver_init(void)
{	
	int ret;
	printk("init\n");
	ret = register_chrdev(200, "first driver", &fops);
	if(ret != 0)
	{
		return ret;
	}

	regGPBCON = ioremap(GPBCON, 4);
	regGPBDAT = ioremap(GPBDAT, 4);

	*regGPBCON &= ~((3 << 10) | (3 << 12) | (3 << 14) | (3 << 16));
	*regGPBCON |= (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);

	*regGPBDAT |= (0x0F << 5);
	return 0;
}

static void __exit led_driver_exit(void)
{
	iounmap(regGPBDAT);
	iounmap(regGPBCON);

	unregister_chrdev(200, "first driver");
	printk("exit\n");
}

module_init(led_driver_init);
module_exit(led_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("PuTe");
  1. 编写LED驱动(初始化一个子设备号)
cpp 复制代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#define GPBCON  (0x56000010)
#define GPBDAT  (0x56000014)
static unsigned int *regGPBCON;
static unsigned int *regGPBDAT;
static dev_t dev_num;
struct cdev led_dev;

int led_driver_open(struct inode *p_node, struct file *fp)
{
	printk("open\n");
	return 0;
}

ssize_t led_driver_read(struct file *fp, char __user *user_buffer, size_t n, loff_t * offset)
{
	printk("read\n");
	return 0;
}

void ledOn(unsigned int n)
{
	*regGPBDAT |= (0x0F << 5);

	if(n < 1 || n > 4)
	{
		return;
	}

	*regGPBDAT &= ~(1 << (n + 4));
}

ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t *offset)
{
	char s[10];
	
	copy_from_user(s, user_buffer, n);
	ledOn(s[0]);
	printk("write\n");

	return n;
}

int led_driver_close(struct inode *p_node, struct file *fp)
{
	printk("close\n");
	return 0;
}

struct file_operations fops =
{	
	.owner = THIS_MODULE,
	.release = led_driver_close,
	.open = led_driver_open,
	.read = led_driver_read,
	.write = led_driver_write,
};

static int __init led_driver_init(void)
{	
	int ret;

	ret = alloc_chrdev_region(&dev_num, 0, 1, "first device");
	if(ret)
	{
		printk("alloc_chrdev_region is error\n");
		return ret;
	}
	
	printk("major = %u, minior = %u\n", MAJOR(dev_num), MINOR(dev_num));

	cdev_init(&led_dev, &fops);
	ret = cdev_add(&led_dev, dev_num, 1);
	if(ret)
	{
		unregister_chrdev_region(dev_num, 1);
		printk("cdev_add is error\n");
		return ret;
	}

	regGPBCON = ioremap(GPBCON, 4);
	regGPBDAT = ioremap(GPBDAT, 4);

	*regGPBCON &= ~((3 << 10) | (3 << 12) | (3 << 14) | (3 << 16));
	*regGPBCON |= (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);
	*regGPBDAT |= (0x0F << 5);

	return 0;
}

static void __exit led_driver_exit(void)
{
	iounmap(regGPBDAT);
	iounmap(regGPBCON);

	cdev_del(&led_dev);
	unregister_chrdev_region(dev_num, 1);
	printk("exot\n");
}

module_init(led_driver_init);
module_exit(led_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("PuTe");
  1. LED标准字符设备驱动(省去在linux终端mknod的过程,直接insmod的即可运行程序)
cpp 复制代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#define GPBCON  (0x56000010)
#define GPBDAT  (0x56000014)
static unsigned int *regGPBCON;
static unsigned int *regGPBDAT;
static dev_t dev_num;
struct cdev led_dev;
static struct class *p_class;
static struct device *p_device;

int led_driver_open(struct inode *p_node, struct file *fp)
{
	printk("open\n");
	return 0;
}

ssize_t led_driver_read(struct file *fp, char __user *user_buffer, size_t n, loff_t * offset)
{
	printk("read\n");
	return 0;
}

void ledOn(unsigned int n)
{
	*regGPBDAT |= (0x0F << 5);

	if(n < 1 || n > 4)
	{
		return;
	}

	*regGPBDAT &= ~(1 << (n + 4));
}

ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t *offset)
{
	char s[10];
	
	copy_from_user(s, user_buffer, n);
	ledOn(s[0]);
	printk("write\n");

	return n;
}

int led_driver_close(struct inode *p_node, struct file *fp)
{
	printk("close\n");
	return 0;
}

struct file_operations fops =
{	
	.owner = THIS_MODULE,
	.release = led_driver_close,
	.open = led_driver_open,
	.read = led_driver_read,
	.write = led_driver_write,
};

static int __init led_driver_init(void)
{	
	int ret;

	ret = alloc_chrdev_region(&dev_num, 0, 1, "first device");
	if(ret)
	{
		printk("alloc_chrdev_region is error\n");
		goto alloc_chrdev_region_err;
	}
	
	printk("major = %u, minior = %u\n", MAJOR(dev_num), MINOR(dev_num));

	cdev_init(&led_dev, &fops);
	ret = cdev_add(&led_dev, dev_num, 1);
	if(ret)
	{
		printk("cdev_add is error\n");
		goto cdev_add_err;
	}

	p_class = class_create(THIS_MODULE, "Led class");
	if(IS_ERR(p_class))
	{
		printk("class_create is error!");
		goto class_create_err;
	}

	p_device = device_create(p_class, NULL, dev_num, NULL, "led");
	if(p_device == NULL)
	{
		printk("device_create is error\n");
		goto device_create_err;
	}

	regGPBCON = ioremap(GPBCON, 4);
	regGPBDAT = ioremap(GPBDAT, 4);

	*regGPBCON &= ~((3 << 10) | (3 << 12) | (3 << 14) | (3 << 16));
	*regGPBCON |= (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);
	*regGPBDAT |= (0x0F << 5);

	return 0;

device_create_err:
	class_destroy(p_class);
class_create_err:
	cdev_del(&led_dev);
cdev_add_err:
	unregister_chrdev_region(dev_num, 1);
alloc_chrdev_region_err:
	return ret;
}

static void __exit led_driver_exit(void)
{
	iounmap(regGPBDAT);
	iounmap(regGPBCON);

	device_destroy(p_class, dev_num);
	class_destroy(p_class);
	cdev_del(&led_dev);
	unregister_chrdev_region(dev_num, 1);
	printk("exit\n");
}

module_init(led_driver_init);
module_exit(led_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("PuTe");
  1. 蜂鸣器------混杂设备驱动
cpp 复制代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#define GPBCON (0x56000010)
#define GPBDAT (0x56000014)
static unsigned int *regGPBCON;
static unsigned int *regGPBDAT;

int beep_open(struct inode *p_node, struct file *fp)
{
	return 0;
}

int beep_release(struct inode *p_node, struct file *fp)
{
	return 0;
}

ssize_t beep_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t * offset)
{
	int ret;

	copy_from_user(&ret, user_buffer, 4);
	printk("kernel : %d",ret);
	if(ret)
	{
		*regGPBDAT |= (1 << 0);
	}
	else
	{
		*regGPBDAT &= ~(1 << 0);
	}

	return 4;
}

static struct file_operations fops =
{
	.owner = THIS_MODULE,
	.open = beep_open,
	.release = beep_release,
	.write = beep_write
};

static struct miscdevice beep_device =
{
	.minor = MISC_DYNAMIC_MINOR,
	.name = "beep",
	.fops = &fops,
};

static int __init beep_init(void)
{
	int ret;

	ret = misc_register(&beep_device);
	if(ret)
	{
		printk("misc_register is error");
		return ret;
	}
	
	regGPBCON = ioremap(GPBCON, 4);
	regGPBDAT = ioremap(GPBDAT, 4);

	*regGPBCON &= ~(3 << 0);
	*regGPBCON |= (1 << 0);

	return 0;
}

static void __exit beep_exit(void)
{
	iounmap(regGPBCON);
	iounmap(regGPBDAT);
	misc_deregister(&beep_device);
}

module_init(beep_init);
module_exit(beep_exit);

MODULE_LICENSE("GPL");
  1. 按键(轮询查看按键)------混杂设备驱动
cpp 复制代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#define GPGCON (0x56000060)
#define GPGDAT (0x56000064)
#define GPGUP (0x56000068)

static unsigned int *regGPGCON;
static unsigned int *regGPGDAT;
static unsigned int *regGPGUP;

int key_open(struct inode *p_node, struct file *fp)
{
	return 0;
}

int key_release(struct inode *p_node, struct file *fp)
{
	return 0;
}

ssize_t key_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t * offset)
{
	return 0;
}

ssize_t key_read(struct file *fp, char __user *user_buffer, size_t n, loff_t *offset)
{
	int ret = -1;

	if (0 == (*regGPGDAT & (1 << 0)))
	{
		ret = 1;
	}
	else if (0 == (*regGPGDAT & (1 << 3)))
	{
		ret = 2;
	}
	else if (0 == (*regGPGDAT & (1 << 5)))
	{
		ret = 3;
	}
	else if (0 == (*regGPGDAT & (1 << 6)))
	{
		ret = 4;
	}
	else if (0 == (*regGPGDAT & (1 << 7)))
	{
		ret = 5;
	}
	else if (0 == (*regGPGDAT & (1 << 11)))
	{
		ret = 6;
	}
	
	if (ret != (-1))
	{
		copy_to_user(user_buffer, &ret, 4);
	}

	return 0;
}

static struct file_operations fops =
{
	.owner = THIS_MODULE,
	.open = key_open,
	.release = key_release,
	.write = key_write,
	.read = key_read,
};

static struct miscdevice key_device =
{
	.minor = MISC_DYNAMIC_MINOR,
	.name = "key",
	.fops = &fops,
};

static int __init key_init(void)
{
	int ret;
	ret = misc_register(&key_device);
	if(ret)
	{
		printk("misc_register is error");
		return ret;
	}
	
	regGPGCON = ioremap(GPGCON, 4);
	regGPGDAT = ioremap(GPGDAT, 4);
	regGPGUP = ioremap(GPGUP, 4);

	*regGPGCON &= ~((3 << 0) | (3 << 6) | (3 << 10) | (3 << 12) | (3 << 14) | (3 << 22));	
	*regGPGDAT |= ((1 << 0) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 11));
	*regGPGUP |= ((1 << 0) | (1 << 11));
	*regGPGUP &= ~((1 << 3) | (1 << 5) | (1 << 6) | (1 << 7));

	return 0;
}

static void __exit key_exit(void)
{
	iounmap(regGPGCON);
	iounmap(regGPGDAT);
	iounmap(regGPGUP);
	misc_deregister(&key_device);
}


module_init(key_init);
module_exit(key_exit);

MODULE_LICENSE("GPL");
相关推荐
ltl2 小时前
大多数「无锁」代码其实不是无锁的
linux
ltl2 小时前
Linux 内核的内存屏障:一个让我调了三天的 bug
linux
paopaokaka_luck3 小时前
基于springboot3+vue3的企业考勤管理系统(部门树递归、Echarts图形化分析)
开发语言·spring boot·学习·echarts·mybatis·需求分析·代码规范
minglie13 小时前
zynq高频小数据量PS闭环 抖动时间的测量
学习
long3163 小时前
MySQL 学习练习(配套 01 入门资料)
数据库·学习·mysql
Lonely 净土4 小时前
Rocky Linux 安装教程
linux·运维·服务器
梦雨生生4 小时前
java开发工具(学习第一天)
java·开发语言·学习
李白你好8 小时前
Windows 离线 Linux 提权辅助查询工具
linux
Lust Dusk9 小时前
记一次Linux应急响应题目解析
linux·运维·服务器·网络·安全·网络安全
ShineWinsu9 小时前
对于Linux:五种IO模型以及非阻塞IO的详细解析
linux·c++·面试·io·阻塞·非阻塞·fcntl