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


相关推荐

  • 怎么同时运行两个tomcat?

    怎么同时运行两个tomcat?转载至:http://ask.zol.com.cn/x/4522378.html这几天由于在搞那个jenkins的自动部署项目所以要使用到两个tomcat(因为一个tomcat不能同时开着两个项目),一个作为jenkins服务器,一个作为项目部署服务器,所以找了一些资料看看一台电脑怎么运行两个tomcat。第一步:先下载两个tomcat(不同版本的也行,笔者用的是一个tomcat7,一个…

    2022年6月15日
    38
  • openssl升级后ssh登录失败(无尽升级)

    OpenSSL升级3.0.0openssl官方下载地址:https://www.openssl.org/source/1.编译tarxfopenssl-3.0.0.tar.gzcdopenssl-3.0.0./config–prefix=/usr/local–openssldir=/usr/local/opensslmake&&makeinstall2.1备份原来的opensslmv/usr/bin/openssl/usr/bin/openssl

    2022年4月13日
    427
  • Dirsearch_torrentsearch下载

    Dirsearch_torrentsearch下载dirsearch下载下载网址:https://github.com/maurosoria/dirsearch下图是下载好的文件夹这样就下载好了我在使用的时候出现了下面的这个问题百度了很久也没有找到,kali也不太会用,就继续找继续找,终于????,解决办法找到了!!!是用户权限的问题!依然对dirsearch修改用户权限还是在属性->安全里面选择想要添加的用户,并允许该用户完全控制如下图…

    2022年10月5日
    2
  • linux 安装Jenkins和配置

    linux 安装Jenkins和配置简要介绍Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。语言:Java一句话描述:持续集成工具建议的版本建议使用版本为“jenkins-2.164.x”。环境清单:CentOS7.6配置安装环境安装OpenJDK。 要求Java的OpenJDK为“1.8.0”以上,可以通过以下命令安装…

    2025年7月7日
    7
  • 小谈Compc命令(命令行生成swc文件)

    小谈Compc命令(命令行生成swc文件)

    2021年8月1日
    48
  • win10 wlan wifi 显示 无Internet连接,安全 连不上网;网络连接显示小地球,无Internet连接 但能上网,反正wlan的 各种病症,猛药解决

    win10 wlan wifi 显示 无Internet连接,安全 连不上网;网络连接显示小地球,无Internet连接 但能上网,反正wlan的 各种病症,猛药解决1、暴力重启:直接按电源键强制关机再开机;2、右键小地球,疑难解答并且执行3、360网络修复4、改这里的配置5、计算机管理,服务改这里的配置都改成自动6、win+rregedit\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet这个值改成17、netshwinsockresetcatalognetshinti…

    2022年7月27日
    11

发表回复

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

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