S3C2440 LED驱动总结

发布时间:2024-07-15  

1. 电路图

<a href=LED连接">

GPIO口



2. 使用说明

代码语言:javascript


此驱动实现二种操作模式:

普通操作模式:./LedTest 点亮或熄灭某个LED灯

掩码操作模式:./LedTest  led_mask

led_mask只能是:000、001、010、011....111

可以同时设置三个LED,对应1位置的LED被点亮,对应0位置熄灭

3. 驱动代码

代码语言:javascript


#include

#include

#include

#include

#include

#include

#include

#include

#include

#include


/* 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. 测试代码

代码语言:javascript


#include

#include

#include

#include


/* 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<

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<

val |= (led_pos<

break;

}


printf("val=0x%xn", val);

write(fd, &val, sizeof(val));


close(fd);

return 0;

usage_error:

printf("Usage:%s led_maskn", argv[0]);

printf("Usage:%s 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;

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>