驱动开发 day2 (led模块化驱动操控)

head.h

cpp 复制代码
#ifndef __HEAD_H__
#define __HEAD_H__

#define PHY_RCC 0X50000A28

#define PHY_GPIOE 0X50006000
#define PHY_GPIOE_ODR 0X50006014

#define PHY_GPIOF 0X50007000
#define PHY_GPIOF_ODR 0X50007014

#endif // MACRO

fun.c

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char const *argv[])
{
	/* code */
	char buf[128] = {0};
	printf("调用open\n");
	int fd = open ("/dev/mycdev",O_RDWR);
	if(fd < 0)
	{
		printf("打开设备文件失败\n");
		exit(-1);
	}
	while(1)
	{
		printf("请输入要点亮的灯号(1-3)及操作(0[灭]、1[亮])[exit退出程序]:");
		fgets(buf,sizeof(buf),stdin);
		buf[strlen(buf)-1] = '\0';    
		write(fd,buf,sizeof(buf));
		if(!strcmp(buf,"exit")) break;
	}
	printf("调用close\n");
	close (fd);   
	return 0;
}

mycdev.c

cpp 复制代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include "head.h"


unsigned int major;
char kbuf[128] = {0};

unsigned int *vir_moder;
unsigned int *vir_odr;
unsigned int *vir_rcc;

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 *lof)
{
	printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

	if(copy_to_user(ubuf,kbuf,size))
	{
		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 *lof)
{
	unsigned int pin;
	printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

	if(copy_from_user(kbuf,ubuf,size))
	{
		printk("copy_to_user filed\n");
		return -EIO;
	}

	switch(kbuf[0])
	{
	case '1':
		pin = 10;
		vir_odr=ioremap(PHY_GPIOE_ODR,4);
		if(vir_odr==NULL)
		{
			printk("映射物理内存失败%d\n",__LINE__);
			return -EFAULT;
		}
		break;
	case '2':
		pin = 10;
		vir_odr=ioremap(PHY_GPIOF_ODR,4);
		if(vir_odr==NULL)
		{
			printk("映射物理内存失败%d\n",__LINE__);
			return -EFAULT;
		}
		break;
	case '3':
		pin = 8;
		vir_odr=ioremap(PHY_GPIOE_ODR,4);
		if(vir_odr==NULL)
		{
			printk("映射物理内存失败%d\n",__LINE__);
			return -EFAULT;
		}
		break;
	default:
		printk("语法错误,请重新输入>>>");
		return -1;
	}


	if(kbuf[1] == '0')
	{
		//关灯逻辑
		(*vir_odr) &= (~(0X1<<pin));
	}
	else if(kbuf[1]=='1')
	{
		//开灯逻辑
		(*vir_odr) |=(0X1<<pin);
	}
	else
	{
		printk("语法错误,请重新输入>>>");
		return -1;
	}

	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,
	.release = mycdev_close,
	.read = mycdev_read,
	.write = mycdev_write,
};

void GPIO_INIT(unsigned int gpio,unsigned int pin)
{

	//进行寄存器地址的映射
	vir_moder=ioremap(gpio,4);
	if(vir_moder==NULL)
	{
		printk("映射物理内存失败%d\n",__LINE__);
		return;
	}

	vir_rcc=ioremap(PHY_RCC,4);
	if(vir_rcc==NULL)
	{
		printk("映射物理内存失败%d\n",__LINE__);
		return;
	}

	if(gpio == PHY_GPIOE)
	{
		vir_odr=ioremap(PHY_GPIOE_ODR,4);
		if(vir_odr==NULL)
		{
			printk("映射物理内存失败%d\n",__LINE__);
			return;
		}
		(*vir_rcc)|=(0X1<<4);//rcc使能GPIOE组
	}
	else if(gpio == PHY_GPIOF)
	{
		vir_odr=ioremap(PHY_GPIOF_ODR,4);
		if(vir_odr==NULL)
		{
			printk("映射物理内存失败%d\n",__LINE__);
			return;
		}
		(*vir_rcc)|=(0X1<<5);//rcc使能GPIOF组

	}

	printk("映射物理内存成功\n");
	//硬件寄存器的初始化
	(*vir_moder) &= (~(0X3 << pin*2));//设置为输出
	(*vir_moder) |= (0X1 << pin*2);
	(*vir_odr)   &= (~(0X1 << pin));//输出低电平
	printk("硬件寄存器初始化成功\n");

}

static int __init mycdev_init(void)
{
	major = register_chrdev(0,"mycdev",&fops);
	if(major < 0)
	{
		printk("注册失败\n");

	}
	printk("注册成功major = %d\n",major);
	GPIO_INIT(PHY_GPIOE,10);
	GPIO_INIT(PHY_GPIOF,10);
	GPIO_INIT(PHY_GPIOE,8);
	return 0;

}
static void __exit mycdev_exit(void)
{
	unregister_chrdev(major,"mycdev");
	printk("出口函数\n");
}

module_init(mycdev_init);

module_exit(mycdev_exit);

MODULE_LICENSE("GPL");

Makefile

Lisp 复制代码
modname ?= mycdev

arch ?= arm

ifeq ($(arch),arm)
KERNELDIR:= /home/ubuntu/13_UBOOT/linux-stm32mp-5.10.61-stm32mp-r2-r0/linux-5.10.61
else
KERNELDIR:=/lib/modules/$(shell uname -r)/build/
endif


PWD:=$(shell pwd)

all:
	make -C $(KERNELDIR) M=$(PWD) modules

clean:
	make -C $(KERNELDIR) M=$(PWD) clean

obj-m:=$(modname).o
相关推荐
7yewh1 天前
嵌入式硬件杂谈(一)-推挽 开漏 高阻态 上拉电阻
驱动开发·stm32·嵌入式硬件·mcu·物联网·硬件架构·pcb工艺
TeYiToKu1 天前
笔记整理—linux驱动开发部分(8)framebuffer类设备
linux·驱动开发·笔记·嵌入式硬件·arm
三菱-Liu2 天前
三菱MR-J4-B伺服连接器和信号排列
网络·驱动开发·硬件工程·制造·mr
挨踢小明2 天前
arm64架构的linux 配置vm_page_prot方式
驱动开发
lishing63 天前
Linux驱动开发(4):Linux的设备模型
linux·运维·驱动开发
TeYiToKu4 天前
笔记整理—linux驱动开发部分(10)input子系统与相关框架
linux·驱动开发·笔记·嵌入式硬件·arm·1024程序员节
TMC_LAI4 天前
采用 EtherCAT 的磁场定向控制 (FOC) 伺服运动控制器 IC-TMC8670-BI
人工智能·驱动开发·嵌入式硬件
三菱-Liu5 天前
三菱MR-J4伺服绝对位置检测系统
运维·驱动开发·嵌入式硬件·硬件工程·制造·mr
这个菠萝好咸5 天前
内核源码+vscode+bear+clang实现函数任意跳转,无缝跳转,无缝阅读,无缝开发
linux·c语言·驱动开发·后端·arm单片机
TeYiToKu6 天前
笔记整理—linux驱动开发部分(7)misc类设备(杂项设备)
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件