嵌入式Linux 底层到到应用层 点灯 (基于iTOP4412)

其实这篇博客就是上篇博客https://blog.csdn.net/qq_41495871/article/details/100378690的一个具体例子

先在总线上注册LED这个设备 ,这里我的设备名命名为 MyLED_device

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>


MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("HQU_Orange");

#define DEVICE_NAME	"MyLED_device"

void MyLED_device_release(struct device *dev);

struct platform_device MyLED_device =
{
	.name	=	DEVICE_NAME	, 
	.id		=	-1			,  //-1代表设备数量为1
	.dev	=	 
	{
	.release=	MyLED_device_release ,	
	}
};



static int  Mini_Linux_Device_Module_Init (void)
{ 
	int Device_Status;

	printk(KERN_EMERG "Mini Liunx Device Module Enter ! \r\n");
	Device_Status=platform_device_register(&MyLED_device);
	printk(KERN_EMERG "Module Device Status is %d \n",Device_Status);
	return 0;
}

static void Mini_Linux_Device_Module_Exit (void)
{
	platform_device_unregister(&MyLED_device);
	printk(KERN_EMERG "Mini Linux Device Module Exit ! \r\n");
}



void MyLED_device_release(struct device *dev)
{
	printk(KERN_EMERG DEVICE_NAME "\tdevice release wolk!\r\n");
}

module_init(Mini_Linux_Device_Module_Init);
module_exit(Mini_Linux_Device_Module_Exit);



下面是最重要的部分,LED的驱动编写,我先将代码贴出来

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/gpio.h>
#include <mach/gpio-exynos4.h>


MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("HQU_Orange");

#define DEVICE_NAME		"MyLED_device"
#define DEVICENODE_NAME	"MyLED"

int MyLED_driver_probe(struct platform_device* MyLED_device);
int MyLED_driver_remove(struct platform_device* MyLED_device);
void MyLED_driver_shutdown(struct platform_device* MyLED_device);
int MyLED_driver_suspend(struct platform_device* MyLED_device,pm_message_t state);
int MyLED_driver_resume(struct platform_device* MyLED_device);
int MyLED_driver_fops_open(struct inode* p_inode,struct file* p_file);
int MyLED_driver_fops_release(struct inode* p_inode,struct file* p_file);
long MyLED_driver_fops_unlocked_ioctl(struct file* p_file ,unsigned int ID ,unsigned long cmd);


struct platform_driver MyLED_driver =
{
	.probe	=	MyLED_driver_probe		,
	.remove	=	MyLED_driver_remove		,
	.shutdown=	MyLED_driver_shutdown	,
	.suspend=	MyLED_driver_suspend	,
	.resume	=	MyLED_driver_resume		,
	.driver	=	
	{
	.name	=	DEVICE_NAME	,
	.owner	=	THIS_MODULE	,
	}
};


struct file_operations MyLED_driver_fops =
{
	.owner			=	THIS_MODULE						,
	.open			=	MyLED_driver_fops_open			,
	.release		=	MyLED_driver_fops_release		,
	.unlocked_ioctl	=	MyLED_driver_fops_unlocked_ioctl,
};


struct miscdevice MyLED_misc_device=
{
	.minor	=	MISC_DYNAMIC_MINOR	,
	.name	=	DEVICENODE_NAME		,
	.fops	=	&MyLED_driver_fops	,

};


static int  Mini_Linux_Driver_Init (void)
{ 
	int Driver_Status;

	printk(KERN_EMERG "Mini Liunx Module Enter ! \r\n");
	Driver_Status=platform_driver_register(&MyLED_driver);
	printk(KERN_EMERG "Driver Status is %d \n",Driver_Status);
	return 0;
}

static void Mini_Linux_Driver_Exit (void)
{
	platform_driver_unregister(&MyLED_driver);
	printk(KERN_EMERG "Mini Linux Module Exit ! \r\n");
}


int MyLED_driver_probe(struct platform_device* MyLED_device)
{
	int res;
	printk(KERN_EMERG "device-> name = %s device -> id = %d probe !\r\n",MyLED_device->name,MyLED_device->id);
	
	gpio_free(EXYNOS4_GPL2(0));
	gpio_free(EXYNOS4_GPK1(1));

	res=gpio_request(EXYNOS4_GPL2(0),"MyLED_1");
	if(res==-1) 
	{printk(KERN_EMERG "%s L2(0) gpio request fail !\r\n",MyLED_device->name);return res ;}
	res=gpio_request(EXYNOS4_GPK1(1),"MyLED_2");
	if(res==-1) 
	{printk(KERN_EMERG "%s K1(1) gpio request fail !\r\n",MyLED_device->name);return res ;}

	
	s3c_gpio_cfgpin(EXYNOS4_GPL2(0),S3C_GPIO_OUTPUT);
	gpio_set_value(EXYNOS4_GPL2(0),0);

	s3c_gpio_cfgpin(EXYNOS4_GPK1(1),S3C_GPIO_OUTPUT);
	gpio_set_value(EXYNOS4_GPK1(1),0);

	misc_register(&MyLED_misc_device);
	return 0;
}

int MyLED_driver_remove(struct platform_device* MyLED_device)
{
	printk(KERN_EMERG "device-> name = %s device -> id = %d remove!\r\n",MyLED_device->name,MyLED_device->id);
	misc_deregister(&MyLED_misc_device);
	return 0;
}

void MyLED_driver_shutdown(struct platform_device* MyLED_device)
{
	printk(KERN_EMERG "device-> name = %s device -> id = %d shutdown!\r\n",MyLED_device->name,MyLED_device->id);
}

int MyLED_driver_suspend(struct platform_device* MyLED_device,pm_message_t state)
{
	printk(KERN_EMERG "device-> name = %s device -> id = %d suspend!\r\n",MyLED_device->name,MyLED_device->id);
	return 0;
}

int MyLED_driver_resume(struct platform_device* MyLED_device)
{
	printk(KERN_EMERG "device-> name = %s device -> id = %d resume!\r\n",MyLED_device->name,MyLED_device->id);
	return 0;
}


int MyLED_driver_fops_open(struct inode* p_inode,struct file* p_file)
{			
	printk(KERN_EMERG "MyLED_file_open \r\n");
	return 0;
}

int MyLED_driver_fops_release(struct inode* p_inode,struct file* p_file)
{
	printk(KERN_EMERG "MyLED_file_release \r\n");
	return 0;
}

long MyLED_driver_fops_unlocked_ioctl(struct file* p_file ,unsigned int ID ,unsigned long cmd)
{
	printk(KERN_EMERG "ID is %d  cmd is %d \r\n" ,ID , cmd);
	if(ID>2||cmd>2)
	{
	printk(KERN_EMERG "ID and cmd must are 0 or 1\r\n");
	return 1;
	}
	if(ID)
	gpio_set_value(EXYNOS4_GPL2(0),cmd);
	else
	gpio_set_value(EXYNOS4_GPK1(1),cmd);

	return 0;
}


module_init(Mini_Linux_Driver_Init);
module_exit(Mini_Linux_Driver_Exit);



熟悉单片机的应该知道其实驱动LED其实就是控制一个引脚的电平。

 gpio_free() 其实不是必要的,因为 我之前烧进去的内核已经将这个两个引脚资源先占用了,而现在为了方便调试用了模块加载的方法,故要先释放这两个引脚的资源,才能用我们自己的驱动控制这两个引脚。

gpio_request() 请求 引脚资源

s3c_gpio_cfgpin() 引脚模式设置

gpio_set_value()引脚输出电平设置

ioctl的实现,下面应用会调用到这个函数。

编写应用程序

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdlib.h>

int main(int argc ,char* argv[])
{
	int fd ;
	int res;
	char* file_node = argv[1];
	char id  = atoi(argv[2]);
	char cmd = atoi(argv[3]);
	
	fd=open(file_node,O_RDWR|O_NOCTTY|O_NDELAY);
	if(fd==-1)
	{
	perror(file_node);
	exit(EXIT_FAILURE);
	}

	res=ioctl(fd,id,cmd);
	if(res==-1)
	{
	perror("ioctl");
	close(fd);
	exit(EXIT_FAILURE);
	}
	
	close(fd);
	
	exit(EXIT_SUCCESS);
}


编写Makeflie


obj-m +=MyLED_Device.o
obj-m +=MyLED_Driver.o

KDIR := /home/topeet/zImage/iTop4412_Kernel_3.0

PWD	?= $(shell pwd)

all:
		make -C	$(KDIR) M=$(PWD) modules
clean:
		rm -rf *.o *.mod.c  *.order *.symvers

make编译

 再编译 应用程序 arm-none-linux-gnueabi-gcc -o  linux_file_ioctl linux_file_ioctl.c  -static

将这个三个文件传输到板子上。

先加载设备在加载驱动

此时两个LED灭了,说明在probe函数里面将gpio电平拉低的程序起作用了

查看/dev目录 生成了我们的设备节点

调用应用程序试试看

输入命令  ./linux_file_ioctl  /dev/MyLED  0 1                                                                                                                

发现板子上的靠近蜂鸣器的led亮了

再输入命令  ./linux_file_ioctl /dev/MyLED  1 1            

                                                                              发现靠近按键的另外一个灯也亮了

结合ioctl程序

说明LED驱动工作正常。  

 


其实熟悉了Linux框架后,就是调用厂家提供的库函数进行开发驱动,相信熟悉单片机的都知道,这套流程下来除去与Linux内核

打交道的代码外,其实就是一个gpio模式设置和一个gpio电平变化。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值