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)


相关推荐

  • cleanwipe使用方法_清空qq缓存数据会怎样

    cleanwipe使用方法_清空qq缓存数据会怎样glassfish清空缓存rm-rf$GLASSFISH_HOME/glassfish/domains/domain1/generated/*rm-rf$GLASSFISH_HOME/glassfish/domains/domain1/osgi-cache/*rm-rf $GLASSFISH_HOME/glassfish/domains/domain1/applicat

  • sql smallint与int_datetime数据类型

    sql smallint与int_datetime数据类型使用整数数据的精确数字数据类型。bigint数值范围从-2^63(-9223372036854775808)到2^63-1(9223372036854775807)的整型数据(所有数字)。存储大小为8个字节。int数值范围从-2^31(-2,147,483,648)到2^31-1(2,147,483,647)的整型数据(所有数字)。存储大小为4个字节。int的SQL-92同义字为integer。smallint数值范围从-2^15(-32,76

  • 增长黑客手册——03

    增长黑客手册——03ToB,ToC案例;增长团队的组建;用数据驱动增长的方法(三个过程、五步搭建方法)

  • mysql timestampdiff datediff_「timestampdiff」datediff()函数 与 timestampdiff()函数的区别 及使用。 – seo实验室…

    mysql timestampdiff datediff_「timestampdiff」datediff()函数 与 timestampdiff()函数的区别 及使用。 – seo实验室…timestampdiff在操作数据库时,经常会使用到“时间范围取值、取时间差”的情况。今天就学习了一个这两个求时间差的函数。1.先从名字上来区分这两个函数的区别。datediff()//看名字“直译”过来的意思是《日期差异》(胡乱翻译的不是很正确哦!)timestampdiff()//这个也“值译”过来《时间戳差异》从名字就能大概区分他们的租作用,一个比较时间戳的,一个是比较日期的。…

  • autodock分子对接结果分析_分子对接公司

    autodock分子对接结果分析_分子对接公司分子对接#一、题目要求自己寻找一个受体+药物分子复合物体系(不同配体结合3-4个),然后拿复合物结构作为起始,做对接实验。软件自选,Dock,AutoDock…二、操作过程记录及结果1、软件下载与安装AutoDock下载安装进入AutoDock官网下载安装http://autodock.scripps.edu/downloads/autodock-r…

  • 局部变量和全局变量,以及作用范围的区别_外部变量和全局变量区别

    局部变量和全局变量,以及作用范围的区别_外部变量和全局变量区别    在写工程文件的时候,犯了一个基础性的错误,基础不牢,地动山摇。所以通过查阅资料回顾了一些相关知识,并记录下来。防止以后再发生这种惨案。变量按存储区域分:全局变量、静态全局变量和静态局部变量都存放在内存的静态存储区域,局部变量存放在内存的栈区。变量按作用域分:  全局变量:在整个工程文件内都有效;“在函数外定义的变量”,即从定义变量的位置到本源文件结束都有效。由于同一文…

    2022年10月28日

发表回复

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

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