驱动Driver-LED驱动

地址映射


ioremap



iounmap


IO内存访问函数

读操作

写操作

Kernel代码

Code
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define LED_MAJOR 200
#define LED_NAME  "led"
#define OFF 0
#define ON  1
// 寄存器物理地址
#define CCM_CCGR1_BASE				(0X020C406C)
#define SW_MUX_GPIO1_IO03_BASE		(0X020E0068)
#define SW_PAD_GPIO1_IO03_BASE		(0X020E02F4)
#define GPIO1_DR_BASE				(0X0209C000)
#define GPIO1_GDIR_BASE				(0X0209C004)
// 映射后寄存器地址
static void __iomem * CCM_CCGR1;
static void __iomem * SW_MUX_GPIO1_IO03;
static void __iomem * SW_PAD_GPIO1_IO03;
static void __iomem * GPIO1_DR;
static void __iomem * GPIO1_GDIR;
void led_switch(u8 sw)
{
	u32 val = 0;
	if (sw == OFF)
	{
		val = readl(GPIO1_DR);
		val &= ~(1 << 3);
		writel(val, GPIO1_DR);
	}
	else
	{
		val = readl(GPIO1_DR);
		val = (1 << 3);
		writel(val, GPIO1_DR);
	}
}
static void led_open(struct inode *inode, struct file *filp)
{
	return 0;
}
static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
	return 0;
}
static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
	int retVal = 0;
	unsigned char dataBuf[1];
	unsigned char ledstat;
	retVal = copy_from_user(dataBuf, buf, cnt);
	if (retVal < 0)
	{
		printk("kernel write failed!\r\n");
		return -EFAULT;
	}
	ledstat = dataBuf[0];
	if (ledstat == OFF)
	{
		led_switch(OFF);
	}
	else
	{
		led_switch(ON);
	}
}
static int led_release(struct inode *inode, struct file *filp)
{
	return 0;
}
static struct file_operations led_fops = {
	.owner = THIS_MODULE,
	.open = led_open,
	.write = led_write,
	.release = led_release,
};
static int __init led_init(void)
{
	u32 val = 0;
	int retValue = 0;
	// 1 寄存器地址映射
	CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);
	SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);
	SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4);
	GPIO1_DR = ioremap(GPIO1_DR_BASE, 4);
	GPIO1_GDIR = ioremap(GPIO1_GDIR_BASE, 4);
	// 2 使能GPIO1时钟
	val = readl(CCM_CCGR1);
	val &= ~(3 << 26);	
	val |= (3 << 26);	
	writel(val, CCM_CCGR1);
	// 3 使能GPIO1时钟,设置IO属性
	writel(5, SW_MUX_GPIO1_IO03);
	writel(0x10B0, SW_PAD_GPIO1_IO03);
	// 4 设置GPIO1_IO03为输出功能
	val = readl(GPIO1_GDIR);
	val &= &(1 << 3);	// 清零
	val |= (1 << 3);	// 设置
	writel(val, GPIO1_GDIR);
	// 5 默认关闭LED
	val = readl(GPIO1_DR);
	val |= (1 << 3);
	writel(val, GPIO1_DR);
	// 6 注册字符设备驱动
	retValue = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);
	if (retValue < 0)
	{	
		printk("register chrdev failed!\r\n");
		return -EIO;
	}
	return 0;
}
static void __exit led_exit(void)
{
	iounmap(CCM_CCGR1_BASE);
	iounmap(SW_MUX_GPIO1_IO03_BASE);
	iounmap(SW_PAD_GPIO1_IO03_BASE);
	iounmap(GPIO1_DR_BASE);
	iounmap(GPIO1_GDIR_BASE);
	unregister_chrdev(LED_MAJOR, LED_NAME);
}
module_init(led_init);
module_exit(led_exit);
MODULE_AUTHOR("starc");
MODULE_LICENSE("GPT");

User代码

Code
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#define LEDOFF 	0
#define LEDON 	1
int main(int argc, char *argv[])
{
	int fd, retvalue;
	char *filename;
	unsigned char databuf[1];
	if(argc != 3){
		printf("Error Usage!\r\n");
		return -1;
	}
	filename = argv[1];
	/* 打开led驱动 */
	fd = open(filename, O_RDWR);
	if(fd < 0){
		printf("file %s open failed!\r\n", argv[1]);
		return -1;
	}
	databuf[0] = atoi(argv[2]);	/* 要执行的操作:打开或关闭 */
	/* 向/dev/led文件写入数据 */
	retvalue = write(fd, databuf, sizeof(databuf));
	if(retvalue < 0){
		printf("LED Control Failed!\r\n");
		close(fd);
		return -1;
	}
	retvalue = close(fd); /* 关闭文件 */
	if(retvalue < 0){
		printf("file %s close failed!\r\n", argv[1]);
		return -1;
	}
	return 0;
}
posted @ 2024-02-28 15:47  starc再起航  阅读(2)  评论(0编辑  收藏  举报