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闪烁了。
- 一个低级的S3c2416 wince SD eboot汇编错误
- 从sys/power/state分析并实现S3C2416的睡眠和唤醒
- 移植RT2870无线网卡驱动到s3c2416
- 关于《s3c2416裸跑环境配置》一文的一些补充
- s3c2416裸跑环境配置
- S3C2416 Linux2.6.21 驱动移植--添加UART3 及波特率设置bug消除
- s3c2416 sdram初始化各寄存器设置
- [初级知识]s3c2416x时钟配置详细步骤
- [初级教程]samsung s3c2416x 的启动方式
- SylixOS的BSP开发实例之S3C2416 【第五篇】S3C2416 启动模式之 NandFlash