IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 十二、linux LED初始化 -> 正文阅读

[嵌入式]十二、linux LED初始化

一、硬件原理图 ??

????????我们今天的目标是将itop4412开发板上的两个led灯控制起来。先看一下原理图:

?

二、GPIO需要的接口和定义

1、Linux中申请GPIO的头文件

????????– include/linux/gpio.h

主要提供一些GPIO操作函数:

2、三星平台的GPIO配置函数头文件

????????– arch/arm/plat-samsung/include/plat/gpio-cfg.h

? ? ? ? – 包括三星所有处理器的配置函数

3、三星平台EXYNOS系列平台,GPIO配置参数宏定义头文件

????????– arch/arm/mach-exynos/include/mach/gpio.h
????????– GPIO管脚拉高拉低配置参数等等
????????– 配置参数的宏定义应该在arch/arm/plat-samsung/include/plat/gpio-cfg.h文件中

4、三星平台4412平台,GPIO宏定义头文件(包含在头文件gpio.h中)

????????– arch/arm/mach-exynos/include/mach/gpio-exynos4.h
????????– 包括4412处理器所有的GPIO的宏定义

三、GPIO驱动初始化代码

? linuxGPIO申请函数和赋值函数
????????– gpio_request
????????– gpio_set_value
? 三星平台配置GPIO函数
????????– s3c_gpio_cfgpin
? GPIO配置输出模式的宏变量
????????– S3C_GPIO_OUTPUT

1、leds驱动程序 leds.c :

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

/*驱动注册的头文件,包含驱动的结构体和注册和卸载的函数*/
#include <linux/platform_device.h>
/*注册杂项设备头文件*/
#include <linux/miscdevice.h>
/*注册设备节点的文件结构体*/
#include <linux/fs.h>

/*Linux中申请GPIO的头文件*/
#include <linux/gpio.h>
/*三星平台的GPIO配置函数头文件*/
/*三星平台EXYNOS系列平台,GPIO配置参数宏定义头文件*/
#include <plat/gpio-cfg.h>
#include <mach/gpio.h>
/*三星平台4412平台,GPIO宏定义头文件*/
#include <mach/gpio-exynos4.h>

#define DRIVER_NAME "itop4412_led_ctl"
#define DEVICE_NAME "itop4412_led_ctl"
#define LED_NUM     2

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

static int led_gpios[LED_NUM] = {
	EXYNOS4_GPL2(0),
    EXYNOS4_GPK1(1),
};

static long itop4412_led_ioctl( struct file *files, unsigned int cmd, unsigned long arg){

	printk("cmd is %d,arg is %d\n", cmd, arg);
	
	if(cmd > 1){
		printk("cmd is 0 or 1\n");
	}
	if(arg >= LED_NUM){
		printk("arg is < %d\n",LED_NUM);
	}
	
	gpio_set_value(led_gpios[arg],cmd);
	
	return 0;
}

static int leds_open(struct inode *inode, struct file *file){
	printk(KERN_EMERG "leds open\n");
	return 0;
}

static int leds_release(struct inode *inode, struct file *file){
	printk(KERN_EMERG "leds release\n");
	return 0;
}

static struct file_operations leds_ops = {
	.owner          = THIS_MODULE,
	.open           = leds_open,
	.release        = leds_release,
	.unlocked_ioctl = itop4412_led_ioctl,
};

static  struct miscdevice leds_dev = {
	.minor  = MISC_DYNAMIC_MINOR,
	.name   = DEVICE_NAME,
	.fops   = &leds_ops,
};

static int leds_probe(struct platform_device *pdv){
	int i;
	int ret;
	
	printk(KERN_EMERG "\t leds enter \n");

	for(i = 0; i < LED_NUM; i++)
	{
		ret = gpio_request(led_gpios[i], "LED"); // 请求GPIO
		if (ret) {
			printk("%s: request GPIO %d for LED failed, ret = %d\n", DRIVER_NAME, i, ret);
		}
		else{
			s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT);
			gpio_set_value(led_gpios[i], 1);			
		}
	}

	misc_register(&leds_dev);

	if(ret<0){

		printk("leds:register device failed!\n");
		goto exit;
	}
	return 0;

exit:
	misc_deregister(&leds_dev);
	return ret;
}

static int leds_remove(struct platform_device *pdv){
	
	printk(KERN_EMERG "\t remove\n");
	misc_deregister(&leds_dev);
	return 0;
}

static void leds_shutdown(struct platform_device *pdv){
	
	;
}

static int leds_suspend(struct platform_device *pdv,pm_message_t pmt){
	
	return 0;
}

static int leds_resume(struct platform_device *pdv){
	
	return 0;
}

struct platform_driver leds_driver = {
	.probe      = leds_probe,
	.remove     = leds_remove,
	.shutdown   = leds_shutdown,
	.suspend    = leds_suspend,
	.resume     = leds_resume,
	.driver     = {
		.name   = DRIVER_NAME,
		.owner  = THIS_MODULE,
	}
};

static int leds_init(void)
{
	int DriverState;
	
	printk(KERN_EMERG "leds_init enter!\n");

	DriverState = platform_driver_register(&leds_driver);
	printk(KERN_EMERG "\tDriverState is %d\n",DriverState);
	return 0;
}

static void leds_exit(void)
{
	printk(KERN_EMERG "leds_exit exit!\n");

	platform_driver_unregister(&leds_driver);	
}

module_init(leds_init);
module_exit(leds_exit);

2、驱动配套Makefile,内核源码路径和模块名称记得改成匹配你自己的情况,然后把这1、2放一起,make一下。生成leds.ko

#!/bin/bash
#通知编译器我们要编译模块的哪些源码
#这里是编译itop4412_hello.c这个文件编译成中间文件itop4412_hello.o
obj-m += leds.o 

#源码目录变量,这里用户需要根据实际情况选择路径
#作者是将Linux的源码拷贝到目录/home/topeet/android4.0下并解压的
KDIR := /home/topeet/android4.0/iTop4412_Kernel_3.0

#当前目录变量
PWD ?= $(shell pwd)

#make命名默认寻找第一个目标
#make -C就是指调用执行的路径
#$(KDIR)Linux源码目录,作者这里指的是/home/topeet/android4.0/iTop4412_Kernel_3.0
#$(PWD)当前目录变量
#modules要执行的操作
all:
	make -C $(KDIR) M=$(PWD) modules
		
#make clean执行的操作是删除后缀为o的文件
clean:
	rm -rf *.o

3、调用驱动程序的应用代码 leds_app.c

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

#include <string.h>

#define LEDS 2


int main(int argc, char *argv[]){

	int   fd, i, cmd = 2, led = 2;
	char *led_ctl_node = "/dev/itop4412_led_ctl";
	char *led0 = "0"; 
	char *led1 = "1";
	char *cmd0 = "0"; 
	char *cmd1 = "1";

	if(strcmp(argv[1], led0) == 0){
		led = 0;
		printf("led is 0!\n");
	}
	if(strcmp(argv[1], led1) == 0){
		led = 1;
		printf("led is 1!\n");
	}

	if(strcmp(argv[2], cmd0) == 0){
		cmd = 0;
		printf("cmd is 0!\n");
	}
	if(strcmp(argv[2], cmd1) == 0){
		cmd = 1;
		printf("cmd is 1!\n");
	}

/*O_RDWR只读打开,O_NDELAY非阻塞方式*/	
	if((fd = open(led_ctl_node, O_RDWR | O_NDELAY)) < 0){
		printf("app open %s failed!\n", led_ctl_node);
	}
	else{
		printf("app open %s success!\n", led_ctl_node);
		ioctl(fd, cmd, led);
		printf("app ioctl %s ,led is %d,cmd is %d!\n", led_ctl_node, led, cmd);
	}
	close(fd);
}

通过arm-none-linux-gnueabi-gcc -o leds_app leds_app.c -static编译一下。生成leds_app。

4、在drivers/char/Kconfig添加一个menuconfig选项

????????具体看<linux内核驱动裁剪>。

?5、配置menuconfig

?6、设备注册

?????????在arch/arm/mach-exynos/mach-itop4412.c下,添加如下代码,具体看《linux虚拟平台设备注册

?7、编译内核,重新下载内核文件zImage

?8、挂载leds.ko模块,记得一定要先挂载。

9、运行leds_app。如下:

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-16 11:27:52  更:2021-07-16 11:29:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/28 22:14:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码