S3C6410开发板LED驱动代码分析及测试代码分析
2021-03-23 来源:eefocus
在本文中,我们对S3C6410开发板LED驱动代码的实现过程进行分析,然后通过一个实例对LED进行控制。在本文的资源中包含了设备驱动的源码和测试的源码。
一、设备驱动源码分析
设备驱动主要实现了模块的初始化、模块的卸载、io模块操作的功能。
1、模块初始化
模块的初始化的源码如下所示。
static int __init dev_init(void)
{
int ret;
{
unsigned tmp;
tmp = readl(S3C64XX_GPKCON);
tmp = (tmp & ~(0xffffU<<16))|(0x1111U<<16);
writel(tmp, S3C64XX_GPKCON);
tmp = readl(S3C64XX_GPKDAT);
tmp |= (0xF << 4);
writel(tmp, S3C64XX_GPKDAT);
}
ret = misc_register(&misc);
printk (DEVICE_NAME'tinitializedn');
return ret;
}
在初始化的源码中,主要是对控制LED的GPIO引脚的寄存器进行设置,将GPIO设置为输出,并将GPIO的初始状态设置为高电平,灯是熄灭状态。另外一个功能就是将LED的混杂设备注册到内核中。
2、模块卸载
模块卸载的代码比较简单,如下所示。
static void __exit dev_exit(void)
{
misc_deregister(&misc);
}
模块卸载代码实现的功能是将LED的混杂设备从内核中取消注册。
3、io 操作
io操作的代码如下所示。
static long sbc2440_leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
switch(cmd) {
unsigned tmp;
case 0:
case 1:
if (arg > 4) {
return -EINVAL;
}
tmp = readl(S3C64XX_GPKDAT);
tmp &= ~(1 << (4 + arg));
tmp |= ( (!cmd) << (4 + arg) );
writel(tmp, S3C64XX_GPKDAT);
//printk (DEVICE_NAME': %d %dn', arg, cmd);
return 0;
default:
return -EINVAL;
}
}
这个函数主要使用来对LED进行控制的,其中,cmd是LED的控制命令,1点亮,0熄灭。arg指明控制那个灯,0~3的取值,对应4个LED灯。控制命令最终会被写入到控制GPIO引脚的数据寄存器中。
二、测试代码分析
编写了一个简单的测试代码对led的驱动进行测试,实现led灯的控制。代码如下。
int main(int argc, char **argv)
{
int on;
int led_no;
int fd;
//验证输入
if(argc!=3||sscanf(argv[1],'%d',&led_no)!=1||sscanf(argv[2],'%d',&on)!=1||
on<0||on>1||led_no<0||led_no>3)
{
fprintf(stderr,'Usage: ./led_test 0|1|2|3 0|1n');
return 1;
}
fd = open('/dev/leds',0);
if(fd<0)
{
fprintf(stderr,'can't open leds!n');
return 1;
}
ioctl(fd,on,led_no);
close(fd);
return 0;
}
led的控制命令通过命令行输入,命令输入后先验证命令是否有效,如果有效则打开leds设备文件,并通过ioctl函数对led进行控制。编译代码,并将可执行文件传到开发板中。通过命令行就可以实现对led的控制。比如下面的命令,表示将led3点亮。
./led_test 3 1