历史上的今天
今天是:2025年01月17日(星期五)
2019年01月17日 | 2416开发记录三:简单LED驱动及应用程序
2019-01-17 来源:eefocus
写过了helloworld驱动,来点真格的驱动吧,最简单的就是led驱动了。
参考mini2440的led驱动写法。写一个混合驱动(对于第一个简单的驱动来说好处多多)
驱动源码
驱动的源码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "my2416leds"
#define LED_ON 0 //根据原理图,0点亮led,1熄灭led
#define LED_OFF 1
//定义GPIO管脚
static unsigned long led_table [] =
{
S3C2410_GPB(1), //为什么是2410?,使用芯片是2416啊,原来他们的定义几乎是一致的。我在arch/arm/palt-s3c24xx/common-smdk.c文件中发现的。
//S3C2410_GPF(1),
//S3C2410_GPF(2),
//S3C2410_GPF(3),
};
//设置管脚模式
static unsigned int led_cfg_table [] =
{
S3C2410_GPIO_OUTPUT, //随内核版本中定义类型的变化,在arch/arm/mach-sc2410/include/mach/Regs-gpio.h文件中定义
//S3C2410_GPIO_OUTPUT,
//S3C2410_GPIO_OUTPUT,
//S3C2410_GPIO_OUTPUT,
};
//unlocked_ioctl函数实现,注意,这里的函数参数和ioctl是不一样的,否则不会起作用。
//这里虽然是unlocked_ioctl函数,但是在应用程序中依然是调用ioctl函数来控制。
static int my2416_leds_ioctl(struct file* filp, unsigned int cmd,unsigned long arg)
{
switch(cmd)
{
case LED_ON:
s3c2410_gpio_setpin(S3C2410_GPB(1), LED_ON);
break;
case LED_OFF:
//s3c2410_gpio_setpin(led_table[arg], !cmd);
s3c2410_gpio_setpin(S3C2410_GPB(1), LED_OFF);
break;
default:
printk("LED control:no cmd\n");
printk("LED control are LED_ON or LED_OFF\n");
return(-EINVAL);
}
return 0;
}
//dev_fops操作指令集
static struct file_operations my2416Led_fops =
{
.owner =THIS_MODULE,
.unlocked_ioctl =my2416_leds_ioctl,//这里必须是unlocked_ioctl而不是ioctl。
};
//第三步:混杂设备定义
static struct miscdevice my2416Ledmisc =
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &my2416Led_fops,
};
//第二步:gpio模式选择,设定管脚
// 注册混杂设备
static int __init dev_init(void)
{
int ret;
int i;
////这里只定义了一个io口GPB1
for (i = 0; i < 1; i++)
{
s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
s3c2410_gpio_setpin(led_table[i], 0);
}
ret = misc_register(&my2416Ledmisc);
printk (DEVICE_NAME"\tinitialized\n");
return ret;
}
static void __exit dev_exit(void)
{
misc_deregister(&my2416Ledmisc);
}
//第一步:module_init(dev_init);
// module_exit(dev_exit);
module_init(dev_init);
module_exit(dev_exit);
MODULE_AUTHOR("Zhao Yidong
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("A sample 2416 led dev");
MODULE_ALIAS("2416 led dev");
相应的makefile文件如下
#Makefile for .c
ARCH=arm
CROSS_COMPILE=arm-linux-
ifneq ($(KERNELRELEASE),)
obj-m := my2416LedDev.o
else
#bbblack kernel
KERNELDIR ?= /home/zyd/soft/s3c2416/20140409_HELPER2416/Helper2416/source/s3c-linux.jyx
PWD := $(shell pwd)
modules:
make -C $(KERNELDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
modules_install:
make -C $(KERNELDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules_install
app: app.c
$(CROSS_COMPILE)gcc -o app app.c
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
endif
执行命令make modules即可编译出my2416LedDev.ko
使用minicom将驱动下载到板子上,使用insmod命令加载驱动即可。
测试应用程序编写
下面是相应的测试app文件编写。使用的开发环境是codeblocks
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "/dev/my2416leds"
#define LED_ON 0
#define LED_OFF 1
int main()
{
int fd;
int ret;
char *i;
char count=0;
printf("My2416 led dev test!\n");
fd=open(DEVICE_NAME,O_RDWR);
printf("fd=%d\n",fd);
if(fd==-1)
{
printf("open device %s error\n",DEVICE_NAME);
}
else
{
for(count=0;count<10;count++)
{
ioctl(fd,LED_OFF);
sleep(1);
ioctl(fd,LED_ON);
sleep(1);
}
ret=close(fd);
printf("ret =%d\n",ret);
printf("Close ledapp succeed!\n");
}
return 0;
}
编译成功后依然使用minicom下载到板子上。
执行命令./my2416LedAPP即可看到GPB1控制的LED闪烁了。
史海拾趣
|
(完全原创,)黄婆卖瓜要自卖自夸,但今天我就要狠批一下我们自己的“瓜”。 3G网络监控好处很多,能解决很多普通网络监控解决不了的问题,也为网络监控的安装简单了很多,如公交车实时监控,长途客车的实时监控,无线机站的实时监控,轮船的实时 ...… 查看全部问答> |
|
小弟的程序只有一个模式的对话框,没有createwindow主窗口, 想为对话框添加一菜单,就是右下角的“关于”选项, 参考新建程序默认的代码后,复制粘贴,可是没有效果(想了很多办法,并不是简单的复制粘贴)。 请教高手应如何添加,希望高手们能 ...… 查看全部问答> |
|
先来个全家福 这个抽奖工具是不是挺熟悉的~~~ 内部 一个12002模块,一个10501模块,一个12001芯片和一个23610芯片 10501好小! 23610恐怖,该用什么电源给它输入呢?… 查看全部问答> |
|
irqreturn_t int_interrupt(int irq,void * dev_id,struct pt_regs *regs);注册中断函数 extern int __must_check request_irq(unsigned int, irq_handler_t handler,unsigned long, const char *, void *); typedef irqreturn_t (*irq_hand ...… 查看全部问答> |




