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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • postgresql 索引类型[通俗易懂]

    postgresql 索引类型[通俗易懂]postgresql提供了B-tree,R-tree,GiST和hash索引类型。不同的索引类型适合特定的查询类型。绝大多数数据库都支持B-tree索引类型,postgresql默认的createindex语句也是创建B-tree索引。 R-tree:R树是一种用于处理多维数据的数据结构,用来访问二维或者更高维区域对象组成的空间数据.R树是一棵平衡树。树上有两类结点:叶子结点和非

    2022年5月25日
    136
  • 2021年学习Java还有意义吗?

    2021年学习Java还有意义吗?Java编程语言今年已经26岁了,按照软件开发标准来说,这是非常古老的语言了。所以很多编程初学者想知道Java在2021年是否仍然有意义?是否值得学习?在那些还没有决定该专注于哪种语言和技术栈的人看来,Java正面临着来自JavaScript、Python和Kotlin之类语言的挑战。但这是否意味着Java在软件开发领域的受欢迎程度、相关性和实际重要性正在下降,转而学习其他技术将是一个更明智的选择?绝对不是。尽管你偶尔会看到一些观点,预示着Java日渐式微,但事实上,…

    2022年7月8日
    21
  • 01_ElasticSearch学习笔记

    01_ElasticSearch学习笔记

    2021年7月11日
    81
  • CTK 插件框架介绍

    CTK 插件框架介绍CTKPluginFramework:IntroductionTheCTKPluginFrameworkcanshortlybedescribedasadynamiccomponentsystemforC++.CTK插件框架可以简要的描

    2022年6月1日
    136
  • 01 ORA系列:ORA-00904 标识符无效 invalid identifier

    01 ORA系列:ORA-00904 标识符无效 invalid identifier如果希望对常见的 Oracle 异常 ORA 报错解决方案有系统的了解 请看 ORACLE 系列异常总结 ORA nbsp 转载请说明出处 https blog csdn net baidu article details nbsp 1 字段名称与数据库中关键字冲突修改如下 nbsp 2 多层嵌套查询 内层字段别名使用了双引号错误原因 内层查

    2025年7月22日
    2
  • Eclipse 新手使用教程

    Eclipse 新手使用教程Eclipse是Java的集成开发环境,使用Eclipse编写Java代码更加简单和智能,那我们该如何使用Eclipse编写一个Java程序呢?一、需要在Eclipse官网(https://www.eclipse.org)上下载Eclipse,然后在电脑上安装二、打开Eclipse软件(一)选择一个工作空间的目录,建议不要放在C盘,之后创建的项目都会存放在你所选的目录下,然后点击Launch(二)可以通过Window-ShowView-Console调出控制台,方便查看程序编译时的输..

    2022年6月15日
    59

发表回复

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

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