写过了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闪烁了。
上一篇:2416开发记录二:最简单的helloworld驱动
下一篇:2416开发记录四: ioctl与unlocked_ioctl区别
推荐阅读最新更新时间:2024-03-16 16:22
设计资源 培训 开发板 精华推荐
- 直播已结束|浅谈Microchip的FPGA产品与智能嵌入式视觉解决方案
- 沁恒CH579M-R1开发板免费测评,丰富外设等你体验
- 参会领开发板盲盒:2023 RT-Thread开发者大会报名啦!
- 免费体验业界最快编译速度&最好性能 Quartus II v15.0网页版下载有礼!
- ST有奖直播 | 75V降压控制器和隔离降压方案
- 独乐乐不如众乐乐——TI培训“荐课”功能上线公测,邀你提议,参与抢楼!
- 抢鲜体验| 两款GD RISC-V开发板
- 是德科技有奖直播|感恩月开幕式——示波器大讲堂
- 【电源技术需求调查,为2024年蓄力!】活动开始啦~
- 【摸黑抢楼】赢大礼,关于示波器的狂想曲!正式开抢!!!