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


相关推荐

  • 用域代码任何带圈字符都能做出来

    用域代码任何带圈字符都能做出来在文档中按下“Ctrl+F9”组合键输入域记号(一对大括号{},不能用键盘直接输入),在域记号中输入如下域代码:eq/o/ac(○,11B)。设置好字体、字号等。  选中上述域代码,按“Alt+F9”组合键看一下效果。如果不满意,再按一次“Alt+F9”组合键切换回域代码状态,分别选中域代码中的“○”或“11B”,执行“格式→字体”命令,打开“字体”对话框,在“字体”和“字符间距”标签中,通

    2022年5月26日
    36
  • 格雷码与二进制的转换[通俗易懂]

    格雷码与二进制的转换[通俗易懂]一、什么是格雷码?格雷码,又叫循环二进制码或反射二进制码,格雷码是我们在工程中常会遇到的一种编码方式,它的基本的特点就是任意两个相邻的代码只有一位二进制数不同,这点在下面会详细讲解到。格雷码的基本特点就是任意两个相邻的代码只有一位二进制数不同,这点很重要。常用的二进制数与格雷码间的转换关系如下表:二、二进制格雷码与自然二进制码的互换1、二进制码转换成二进制格雷码  二进制码转换成二进制格雷码,

    2022年10月17日
    0
  • 联想开天 N7 评测

    联想开天 N7 评测开天N7系列笔记本电脑基于兆芯开先KX-6640MA处理器平台,搭配16GB双通道内存和512GBNVMe高速SSD,辅以国产BIOS、OS定制调优;1.29kg超轻单机重量,14.6mm极致纤薄全金属机身;14英寸2.2k16:10显示屏,91%屏占比;支持单手极限180度开盖;率先在国产笔记本引入WiFi6和蓝牙5.0;搭配联想专用芯片的创新智能控制方案,具备光感自动化、开盖即开机、快速充电、充电宝模式等多重独有功能;双风扇双热管散热系统,搭配61Wh

    2022年5月10日
    62
  • 大白菜运行ghost备份恢复工具_大白菜备份的系统被隐藏了

    大白菜运行ghost备份恢复工具_大白菜备份的系统被隐藏了不是经常换系统,容易换机,简单记录下先在u盘做一个系统,我用的大白菜电脑启动的时候进入u盘系统根据自己电脑型号查询如果启动的时候可以选择启动菜单是最方面的,直接通过启动菜单启动u盘系统如果启动的时候没有启动菜单,需要去bios里面调整顺序进入大白菜系统后,我选择的ghost备份还原…

    2022年9月4日
    3
  • ubuntu安装wget命令_linux bash命令

    ubuntu安装wget命令_linux bash命令我们先安装linux系统比如centos7.1里面有的就没有wget下载工具。wget这个命令就不可以使用。我们使用yum-yinstallwgetyuminstallperl会出现:[root@localhost~]#yum-yinstallwgetLoadedplugins:fastestmirrorRepodataisoverweeksold.Instal…

    2022年10月16日
    0
  • 负采样方式

    负采样方式一、随机负采样二、曝光未点击三、混合负采样四、重要性采样五、有偏采样六、NCE采样参考:[mixednegativesampling]MixedNegativeSamplingforLearningTwo-towerNeuralNetworksinRecommendations(2020) [Youtube]Sampling-Bias-CorrectedNeuralModelingforLargeCorpusItemRecomme

    2022年6月29日
    23

发表回复

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

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