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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 安卓系统框架介绍(安卓常用框架)

    一、什么是Android?Android是由谷歌公司开发的一种基于Linux的开源的操作系统。——源码地址1:https://android.googlesource.com/——源码地址2:http://androidxref.com/起初专为移动设备开发的一个操作系统,如手机,平板电脑,车载系统,智能电视等。Android第一个版本2008年11月发布,至今有超过…

  • python 正则 括号_js正则匹配0个或多个空格

    python 正则 括号_js正则匹配0个或多个空格\d匹配一个数字\w匹配一个字母或数字.匹配任意字符*表示任意个字符(包括0个),+表示至少一个字符?表示0个或1个字符^表示行的开头$表示行的结束\s匹配一个空格(也包括Tab等空白符)\s+表示至少有一个空格|A|B可以匹配A或B,所以(P|p)ython可以匹配’Pyth…

  • python的zipfile.open_python之zipfile[通俗易懂]

    python的zipfile.open_python之zipfile[通俗易懂]1简述zip文件是一个常用的归档和与压缩标准。zipfile模块提供了创建、读取、写入、添加及列出zip文件的工具。zipfile里有2个非常常用的class,分别是Zipfile和ZipInfo,在绝大多数情况下,我们只需要使用这2个class就可以了。Zipfile是主要的类,用于创建和读取zip文件,而ZipInfo是储存zip文件每个信息的。2Zipfile基本操作1创建一个zip对…

  • PS磨皮滤镜插件:Portraiture 3 for Mac激活成功教程版永久激活方法

    PS磨皮滤镜插件:Portraiture 3 for Mac激活成功教程版永久激活方法为大家推荐Mac上最好用的一款PS磨皮滤镜Portraiture。PortraiturMac主要用于人像图片润色,它可以在保持皮肤的色泽的情况下对图像中的皮肤、头发、眉毛、睫毛等部位进行平滑的疵点处理,功能强大。现为大家带来磨皮滤镜portraituremac激活成功教程版,软件内附激活成功教程补丁,可以助您成功激活成功教程激活portraiture磨皮滤镜。磨皮插件portraiture怎么安装port…

  • 理解的英文(言语理解)

    开篇明义,dropout是指在深度学习网络的训练过程中,对于神经网络单元,按照一定的概率将其暂时从网络中丢弃。注意是暂时,对于随机梯度下降来说,由于是随机丢弃,故而每一个mini-batch都在训练不同的网络。dropout是CNN中防止过拟合提高效果的一个大杀器,但对于其为何有效,却众说纷纭。在下读到两篇代表性的论文,代表两种不同的观点,特此分享给大家。

发表回复

您的电子邮箱地址不会被公开。

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