S3C2440 LED驱动总结

S3C2440 LED驱动总结1.电路图2.使用说明此驱动实现二种操作模式: 普通操作模式:./LedTest<led1/led2/led3><on/off> 点亮或熄灭某个LED灯 掩码操作模式:./LedTestled_mask led_mask只能是:000、001、010、011….111 可以同时设置三个LED,对应1位置的LED被点亮,对应0位置熄灭…

大家好,又见面了,我是你们的朋友全栈君。

1. 电路图

2. 使用说明

此驱动实现二种操作模式:
		普通操作模式:./LedTest <led1/led2/led3> <on/off>		点亮或熄灭某个LED灯
		掩码操作模式:./LedTest  led_mask
			led_mask只能是:000、001、010、011....111
			可以同时设置三个LED,对应1位置的LED被点亮,对应0位置熄灭
3. 驱动代码
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>

/* Description of LED masks */
typedef enum{ 
   
	LED_MASK_000,
	LED_MASK_001,
	LED_MASK_010,
	LED_MASK_011,
	LED_MASK_100,
	LED_MASK_101,
	LED_MASK_110,
	LED_MASK_111,
	LED_MASK_INIT,
}s3c2440_led_mask;

/* Describe the mode of operating LED */
typedef enum{ 
   
	S3C2440_LED_MODE_MASK=0x11,
	S3C2440_LED_MODE_GENERAL=0x22,
	S3C2440_LED_MODE_INIT=0xff,
}s3c2440_led_mode;

/* Describe the operation of LED */
typedef enum{ 
   
	S3C2440_LED_OP_ON=0x66,
	S3C2440_LED_OP_OFF=0x88,
	S3C2440_LED_OP_INIT=0xff,
}s3c2440_led_op;

/* Describe the position of the operating LED */
typedef enum{ 
   
	S3C2440_LED_POS_GPF4,
	S3C2440_LED_POS_GPF5,
	S3C2440_LED_POS_GPF6,
	S3C2440_LED_POS_INIT,
}s3c2440_led_pos;

/* Description of LED Mask Magic Number */
typedef enum{ 
   
	S3C2440_BIT_MASK8=8,
	S3C2440_BIT_MASK16=16,	
}s3c2440_led_bit_mask;

#define FIRST_DRV_MAJOR 111
static struct class *first_drv_class;
static struct class_device *first_drv_class_dev;

volatile unsigned long *GPFCON = NULL;
volatile unsigned long *GPFDAT = NULL;

static int first_drv_open(struct inode *inode, struct file *file)
{ 
   
	/* 配置 GPF4,5,6为输出 */
	*GPFCON &= ~((0x3<<(4*2)) | (0x3<<(5*2)) | (0x3<<(6*2)));
	*GPFCON |= ((0x1<<(4*2)) | (0x1<<(5*2)) | (0x1<<(6*2)));
	return 0;
}

static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{ 
   
	int val;
	s3c2440_led_mode mode = S3C2440_LED_MODE_INIT;
	s3c2440_led_op op = S3C2440_LED_OP_INIT;
	s3c2440_led_mask mask = LED_MASK_INIT;
	s3c2440_led_pos led_pos = S3C2440_LED_POS_INIT;
	
	copy_from_user(&val, buf, count);	// copy_to_user
	mode =  val&0xff;
	
	if(mode & S3C2440_LED_MODE_GENERAL)
	{ 
   
		led_pos = (val&0xff0000)>>S3C2440_BIT_MASK16;
		op = (val&0xff00)>>S3C2440_BIT_MASK8;
	}
	else if(mode&S3C2440_LED_MODE_MASK)
	{ 
   
		mask = (val&0xff00)>>S3C2440_BIT_MASK8;
	}
	else 
	{ 
   
		printk("[%s][%d]:s3c2440_led_mode is invalid!\n", __FUNCTION__, __LINE__);
		return -1;
	}
	

	if(mode==S3C2440_LED_MODE_MASK)
	{ 
   
		switch(mask)
		{ 
   
			case LED_MASK_000:	*GPFDAT |= (1<<4) | (1<<5) | (1<<6);				break;
			case LED_MASK_001:	*GPFDAT &= ~(1<<4);	*GPFDAT |= (1<<5) | (1<<6);		break;
			case LED_MASK_010:	*GPFDAT &= ~(1<<5);	*GPFDAT |= (1<<4) | (1<<6);		break;
			case LED_MASK_011:	*GPFDAT &= ~((1<<4) | (1<<5));*GPFDAT |= (1<<6);	break;
			case LED_MASK_100:	*GPFDAT &= ~(1<<6);*GPFDAT |= (1<<4) | (1<<5);		break;
			case LED_MASK_101:	*GPFDAT &= ~((1<<4) | (1<<6));*GPFDAT |= (1<<5);	break;
			case LED_MASK_110:	*GPFDAT &= ~((1<<5) | (1<<6));*GPFDAT |= (1<<4);	break;
			case LED_MASK_111:	*GPFDAT &= ~((1<<4) | (1<<5) | (1<<6));				break;
			default:
				printk("[%s][%d]:s3c2440_led_mask is invalid!\n", __FUNCTION__, __LINE__);
				return -1;
		}
	}
	else
	{ 
   
		if(op==S3C2440_LED_OP_ON)
		{ 
   
			switch(led_pos)
			{ 
   
				case S3C2440_LED_POS_GPF4: *GPFDAT &= ~(1<<4); 	break;
				case S3C2440_LED_POS_GPF5: *GPFDAT &= ~(1<<5); 	break;
				case S3C2440_LED_POS_GPF6: *GPFDAT &= ~(1<<6); 	break;
				default:
					printk("[%s][%d]:s3c2440_led_pos is invalid!\n", __FUNCTION__, __LINE__);
					return -1;
			}
		}
		else if(op==S3C2440_LED_OP_OFF)
		{ 
   
			switch(led_pos)
			{ 
   
				case S3C2440_LED_POS_GPF4: *GPFDAT |= (1<<4); break;
				case S3C2440_LED_POS_GPF5: *GPFDAT |= (1<<5); break;
				case S3C2440_LED_POS_GPF6: *GPFDAT |= (1<<6); break;
				default:
					printk("[%s][%d]:s3c2440_led_pos is invalid!\n", __FUNCTION__, __LINE__);
					return -1;
			}
		}
		else
		{ 
   
			printk("[%s][%d]:s3c2440_led_op is invalid!\n", __FUNCTION__, __LINE__);
			return -1;
		}
	}

	return 0;
}

static struct file_operations first_drv_fops = { 
   
	.owner		= THIS_MODULE,
	.open		= first_drv_open,
	.write		= first_drv_write,
};

static int __init first_drv_init(void)
{ 
   
	/* 主设备号, 名字(随便), file_operations结构 如果主设备号写0,就是让系统自动分配设备号 */
	register_chrdev(FIRST_DRV_MAJOR, "first_drv", &first_drv_fops);		/* 注册驱动程序 */

	/* 在系统/sys/class/下创建一个名为first_drv的类 */
	first_drv_class = class_create(THIS_MODULE, "first_drv");
	if(IS_ERR(first_drv_class))
		return PTR_ERR(first_drv_class);

	/* 根据类,设备号,名字在/sys/class/first_drv/下创建名为xxx的设备 */
	first_drv_class_dev = class_device_create(first_drv_class, NULL, 
		MKDEV(FIRST_DRV_MAJOR, 0), NULL, "xxx");
	if(unlikely(IS_ERR(first_drv_class_dev)))
		return PTR_ERR(first_drv_class_dev);

	/* 映射寄存器 */
	GPFCON = (volatile unsigned long *)ioremap(0x56000050, 16);
	GPFDAT = GPFCON + 1;

	return 0;
}

static void __exit first_drv_exit(void)
{ 
   
 	unregister_chrdev(FIRST_DRV_MAJOR, "first_drv");					/* 卸载驱动 */
	class_device_unregister(first_drv_class_dev);
	class_destroy(first_drv_class);
	iounmap(GPFCON);
}

module_init(first_drv_init);
module_exit(first_drv_exit);
MODULE_LICENSE("GPL");

4. 测试代码

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

/* compile: arm-linux-gcc -o FirstDrvTest FirstDrvTest.c */

#define DEV_DEVICE "/dev/xxx"
#define TRUE 1
#define FALSE 0
#define BUF_SIZE_32 32
#define ARRAY_SIZE(array) (sizeof(array)/sizeof((array)[0]))

typedef struct{ 
   
	char input[BUF_SIZE_32];
	unsigned char key;
}s3c2440_turn_key;

typedef enum{ 
   
	LED_MASK_000,
	LED_MASK_001,
	LED_MASK_010,
	LED_MASK_011,
	LED_MASK_100,
	LED_MASK_101,
	LED_MASK_110,
	LED_MASK_111,
	LED_MASK_INIT,
}s3c2440_led_mask;

typedef enum{ 
   
	S3C2440_LED_MODE_MASK=0x11,
	S3C2440_LED_MODE_GENERAL=0x22,
	S3C2440_LED_MODE_INIT=0xff,
}s3c2440_led_mode;

typedef enum{ 
   
	S3C2440_LED_OP_ON=0x66,
	S3C2440_LED_OP_OFF=0x88,
	S3C2440_LED_OP_INIT=0xff,
}s3c2440_led_op;

typedef enum{ 
   
	S3C2440_LED_POS_GPF4,
	S3C2440_LED_POS_GPF5,
	S3C2440_LED_POS_GPF6,
	S3C2440_LED_POS_INIT,
}s3c2440_led_pos;

typedef enum{ 
   
	S3C2440_BIT_MASK8=8,
	S3C2440_BIT_MASK16=16,	
}s3c2440_led_bit_mask;

typedef unsigned int BOOL;

static BOOL check_led_turn_is_legal(s3c2440_turn_key *map, 
	s3c2440_turn_key *map_array, int map_array_len);

int main(int argc, char *argv[])
{ 
   
	int fd, val=0;
	s3c2440_led_mode mode=S3C2440_LED_MODE_INIT;
	s3c2440_led_mask mask=LED_MASK_INIT; 
	s3c2440_led_pos led_pos=S3C2440_LED_POS_INIT;
	s3c2440_led_op op=S3C2440_LED_OP_INIT;
	s3c2440_turn_key input_map, led_map, op_map;

	s3c2440_turn_key s3c2440_key_map[]={ 
   
		{ 
   "000", 0},
		{ 
   "001", 1},
		{ 
   "010", 2},
		{ 
   "011", 3},
		{ 
   "100", 4},
		{ 
   "101", 5},
		{ 
   "110", 6},
		{ 
   "111", 7},
	};
	
	s3c2440_turn_key s3c2440_led_map[]={ 
   
		{ 
   "led1", S3C2440_LED_POS_GPF4},
		{ 
   "led2", S3C2440_LED_POS_GPF5},
		{ 
   "led3", S3C2440_LED_POS_GPF6},
	};

	s3c2440_turn_key s3c2440_op_map[]={ 
   
		{ 
   "on", S3C2440_LED_OP_ON},
		{ 
   "off", S3C2440_LED_OP_OFF},
	};
	
	if(argc==3 || argc==2)
		;
	else
		goto usage_error;
	
	switch(argc)
	{ 
   
		case 2:	mode=S3C2440_LED_MODE_MASK;	break;
		case 3:	mode=S3C2440_LED_MODE_GENERAL;	break;
	}
	
	fd = open(DEV_DEVICE, O_RDWR);
	if(fd<0)
		goto open_error;

	switch(mode)
	{ 
   
		case S3C2440_LED_MODE_MASK:
			val |= S3C2440_LED_MODE_MASK;
			strncpy(input_map.input, argv[1], sizeof(input_map.input));
			if(check_led_turn_is_legal(&input_map, s3c2440_key_map, ARRAY_SIZE(s3c2440_key_map))==TRUE)
				mask=input_map.key;
			else
				goto led_mask_error;

			val |= (mask<<S3C2440_BIT_MASK8);
			break;

		case S3C2440_LED_MODE_GENERAL:
			strncpy(led_map.input, argv[1], sizeof(led_map.input));
			if(check_led_turn_is_legal(&led_map, 
				s3c2440_led_map, ARRAY_SIZE(s3c2440_led_map))==TRUE)
				led_pos = led_map.key;
			else
				goto led_number_error;

			strncpy(op_map.input, argv[2], sizeof(op_map.input));
			if(check_led_turn_is_legal(&op_map, 
				s3c2440_op_map, ARRAY_SIZE(s3c2440_op_map))==TRUE)
				op =  op_map.key;
			else
				goto input_cmd_error;
			
			val |= S3C2440_LED_MODE_GENERAL;
			val |= (op<<S3C2440_BIT_MASK8);
			val |= (led_pos<<S3C2440_BIT_MASK16);
			
			break;
	}

	printf("val=0x%x\n", val);
	write(fd, &val, sizeof(val));

	close(fd);
	return 0;
	
usage_error:
	printf("Usage:%s led_mask\n", argv[0]);
	printf("Usage:%s <led1/led2/led3> <on/off>\n", argv[0]);
	goto ret_error;
	
open_error:
	fprintf(stderr, "open %s fail!\n", DEV_DEVICE);
	goto ret_error;
	
led_mask_error:
	fprintf(stderr, "led mask error!\n");
	close(fd);
	goto ret_error;

led_number_error:
	fprintf(stderr, "led number error!\n");
	close(fd);
	goto ret_error;

input_cmd_error:
	close(fd);
	fprintf(stderr, "input cmd error!\n");
	goto ret_error;
	
ret_error:
	return -1;
}

static BOOL check_led_turn_is_legal(s3c2440_turn_key *map, 
	s3c2440_turn_key *map_array, int map_array_len)
{ 
   
	int i;
	for(i=0; i<map_array_len; i++)
	{ 
   
		if(strcmp(map->input, map_array[i].input)==0)
		{ 
   
			map->key = map_array[i].key;
			return TRUE;
		}	
	}
	return FALSE;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/144980.html原文链接:https://javaforall.net

(0)
上一篇 2022年5月12日 下午7:40
下一篇 2022年5月12日 下午7:40


相关推荐

  • pycharm jinja2_Python django

    pycharm jinja2_Python djangojinja2语法基本语法在jinja2中,存在三种语法:控制结构{%%}变量取值{{}}注释{##}下面是一个简单的jinja2例子{#Thisisjinjacode{%forfileinfilenames%}…{%endfor%}#}可以看到,for循环的使用方式和Python比较类似,但是没有了句尾的冒号,另外需要使用endfor最为结尾,其实在jinja2…

    2025年8月13日
    4
  • 一致性hash面试题_java面试算法

    一致性hash面试题_java面试算法为什么要用一致性hash算法?在学习一致性hash算法之前,首先要考虑下为什么要使用它,使用它能解决什么样的问题。带着问题去学习相信理解起来会更容易。大家都知道我们在使用redis分片技术,mycat对数据库进行分库分表时都会面临数据操作规则的问题;比如我们把一条记录存入redis3服务器,那么我们获取的时候如果不指定规则就会根据key在所有的redis服务器中进行遍历查找,显然这种情况是…

    2022年10月5日
    4
  • FastClick的用法「建议收藏」

    FastClick的用法「建议收藏」为什么要使用FastClick移动设备上的浏览器默认会在用户点击屏幕大约延迟300毫秒后才会触发点击事件,这是为了检查用户是否在做双击。为了能够立即响应用户的点击事件,才有了FastClick。FastClick的使用安装fastclick可以使用npm,Component和Bower。另外也提供了Ruby版的gemfastclick-rails以及.NET提供了NuGetpack…

    2022年6月19日
    42
  • mse均方误差计算公式_视觉SLAM十四讲实践之真实轨迹和估计轨迹均方根误差「建议收藏」

    mse均方误差计算公式_视觉SLAM十四讲实践之真实轨迹和估计轨迹均方根误差「建议收藏」为了理解RMSE首先介绍一些统计学的概念,然后介绍SLAM领域里面的计算精度ATE和RPE的用法。中位数一组数据按大小顺序排列,位于最中间的一个数据(当有偶数个数据时,为最中间两个数据的平均数)叫做这组数据的中位数。用中位数作为一组数据的代表,可靠性不高,但受极端数据影响的可能性小一些,有利于表达这组数据的“集中趋势”。众数几组数据中出现次数最多的那个数据,叫做这批数据的众数。用众…

    2026年4月19日
    5
  • spring的aop思想_图片浏览器的设计与实现原理

    spring的aop思想_图片浏览器的设计与实现原理在上篇文章《Spring设计思想》AOP设计基本原理中阐述了SpringAOP的基本原理以及基本机制,本文将深入源码,详细阐述整个SpringAOP实现的整个过程。读完本文,你将了解到:1、Spring内部创建代理对象的过程2、SpringAOP的核心—ProxyFactoryBean3、基于JDK面向接口的动态代理JdkDynamicAopProxy生成代理对象4、基于Cglib子类继承方式的动态代理CglibAopProxy生成代理对象

    2026年1月16日
    7
  • linux安装svn服务器的两种方式

    linux安装svn服务器的两种方式操作环境:CentOS7.264位==============第一种:采用压缩包安装:比如你们公司服务器上安装软件有自己的规定,一般会采用压缩包安装。==============第一步:SVN服务器端压缩包下载下载地址:http://mirrors.cnnic.cn/apache/subversion/ 我下载的是subversion-1.8.19版本,下载好的压缩包置于目录/usr/loc…

    2022年7月19日
    19

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号