leddevice.c
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <mach/regs-clock.h>
#include <mach/regs-gcr.h>
#include <mach/irqs.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/types.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/irq.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/fcntl.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
/* @description : 释放 flatform 设备模块的时候此函数会执行
* @param - dev : 要释放的设备
* @return : 无
*/
static void nuc977_led_release(struct device *dev)
{
printk("nuc977_led device released!\r\n");
}
/*
* platform 设备结构体
*/
static struct platform_device leddevice = {
.name = "nuc977-led",
.id = -1,
.dev = {
.release = &nuc977_led_release,
},
};
/*
* @description : 设备模块加载
* @param : 无
* @return : 无
*/
static int __init nuc977_leddevice_init(void)
{
return platform_device_register(&leddevice);
}
/*
* @description : 设备模块注销
* @param : 无
* @return : 无
*/
static void __exit nuc977_leddevice_exit(void)
{
platform_device_unregister(&leddevice);
}
module_init(nuc977_leddevice_init);
module_exit(nuc977_leddevice_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("hannux");
leddriver.c
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <mach/regs-clock.h>
#include <mach/regs-gcr.h>
#include <mach/irqs.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/types.h>
#include <linux/ide.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/irq.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/fcntl.h>
#include <linux/platform_device.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define LEDDEV_CNT 1 /* 设备号个数 */
#define LEDDEV_NAME "platled" /* 设备名字 */
#define LEDON 1 /* 开灯*/
#define LEDOFF 0 /* 关灯*/
/* leddev 设备结构体 */
struct leddev_dev{
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct class *class; /* 类 */
struct device *device; /* 设备 */
int major; /* 主设备号 */
};
struct leddev_dev leddev; /* led 设备 */
static int nuc977_led_open(struct inode *ino, struct file *file)
{
file->private_data = &leddev; /* 设置私有数据 */
return 0;
}
static long nuc977_led_unlock_ioctl( struct file *files, unsigned int cmd, unsigned long arg)
{
printk("cmd is %d,arg is %d \n",cmd,(unsigned int)(arg));
struct leddev_dev *dev= (struct leddev_dev *)files->private_data;
switch(cmd)
{
case LEDON:
{
printk(KERN_INFO "LEDON \n");
gpio_set_value(NUC970_PB1, 1);
break;
}
case LEDOFF:
{
printk(KERN_INFO "LEDOFF \n");
gpio_set_value(NUC970_PB1, 0);
break;
}
}
return 0;
}
/* 设备操作函数 */
static struct file_operations nuc977_led_fops = {
.owner = THIS_MODULE,
.open = nuc977_led_open,
.unlocked_ioctl = nuc977_led_unlock_ioctl,
};
/*
* @description : flatform 驱动的 probe 函数,当驱动与设备
* 匹配以后此函数就会执行
* @param - dev : platform 设备
* @return : 0,成功;其他负值,失败
*/
static int nuc977_led_probe(struct platform_device *dev)
{
printk("nuc977 led driver and device has matched!\r\n");
gpio_direction_output(NUC970_PB1,1);
/* 注册字符设备驱动 */
/* 1、创建设备号 */
if (leddev.major) { /* 定义了设备号 */
leddev.devid = MKDEV(leddev.major, 0);
register_chrdev_region(leddev.devid, LEDDEV_CNT,LEDDEV_NAME);
}
else
{ /* 没有定义设备号 */
alloc_chrdev_region(&leddev.devid, 0, LEDDEV_CNT,LEDDEV_NAME); /* 申请设备号 */
leddev.major = MAJOR(leddev.devid); /* 获取主设备号 */
}
printk("leddev major=%d,\r\n",leddev.major);
/* 2、初始化 cdev */
leddev.cdev.owner = THIS_MODULE;
cdev_init(&leddev.cdev, &nuc977_led_fops);
/* 3、添加一个 cdev */
cdev_add(&leddev.cdev, leddev.devid, LEDDEV_CNT);
/* 4、创建类 */
leddev.class = class_create(THIS_MODULE, LEDDEV_NAME);
if (IS_ERR(leddev.class)) {
return PTR_ERR(leddev.class);
}
/* 5、创建设备 */
leddev.device = device_create(leddev.class, NULL,leddev.devid, NULL, LEDDEV_NAME);
if (IS_ERR(leddev.device)) {
return PTR_ERR(leddev.device);
}
printk(KERN_INFO "nuc977_led_probe \n");
return 0;
}
static int nuc977_led_remove(struct platform_device *dev)
{
/* 注销字符设备 */
cdev_del(&leddev.cdev);/* 删除 cdev */
unregister_chrdev_region(leddev.devid, LEDDEV_CNT);
device_destroy(leddev.class, leddev.devid);
class_destroy(leddev.class);
printk(KERN_INFO "nuc977_led_remove \n");
return 0;
}
/* platform 驱动结构体 */
static struct platform_driver led_driver = {
.driver = {
.name = "nuc977-led", /* 驱动名字,用于和设备匹配 */
},
.probe = nuc977_led_probe,
.remove = nuc977_led_remove,
};
/*
* @description : 驱动模块加载函数
* @param : 无
* @return : 无
*/
static int __init nuc977_leddriver_init(void)
{
return platform_driver_register(&led_driver);
}
/*
* @description : 驱动模块卸载函数
* @param : 无
* @return : 无
*/
static void __exit nuc977_leddriver_exit(void)
{
platform_driver_unregister(&led_driver);
}
module_init(nuc977_leddriver_init);
module_exit(nuc977_leddriver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("hannux");
Makefile
obj-m := leddevice.o leddriver.o
PWD := $(shell pwd)
KDIR ?= /home/hbin/nuc977_bsp/nuc970bsp/linux-3.10.x
all:
$(MAKE) -C $(KDIR) M=$(PWD)
clean:
rm -rf .*.cmd *.o *.mod.c *.ko
led_app.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "string.h"
#define IOCTL_LED_ON 1
#define IOCTL_LED_OFF 0
int main(int argc, char **argv)
{
int fd, i;
char *filename;
for(i=0;i<argc;i++)
printf(" argv[%d]= %s \n",i,argv[i]);
if(argc != 3){
printf("Error Usage!\r\n");
return -1;
}
filename = argv[1];
fd = open(filename, O_RDWR);// 打开设备
if (fd < 0) {
printf("file %s open failed!\r\n", argv[1]);
return -1;
}
if (!strcmp(argv[2], "on")) {
ioctl(fd, IOCTL_LED_ON, 0); // 点亮它
} else if (!strcmp(argv[2], "off")) {
ioctl(fd, IOCTL_LED_OFF, 0); // 熄灭它
} else {
printf("argv[2]=%s error \r\n", argv[2]);
}
close(fd);
return 0;
}
secureCRT
1.程序没有判断资源是否可用
2. /mnt/driver/platform_led # cp *.ko /lib/modules/3.10.101/
将leddevice.ko leddriver.ko 复制到 /lib/modules/3.10.101/
3.加载模块驱动,匹配成功
leddevice.ko leddriver.ko modules.dep.bb
/lib/modules/3.10.101 # insmod leddevice.ko
/lib/modules/3.10.101 # lsmod
leddevice 849 0 - Live 0xbf000000 (O)
/lib/modules/3.10.101 # insmod leddriver.ko
nuc977 led driver and device has matched!
4. leddevice.c 中设置 leddevice(platform_device 类型)的
name 字段为“nuc977-led”,也就是设备名字为 nuc977-led, 因此在/sys/bus/platform/devices/目录下有nuc977-led这个文件
5. leddriver.c 中设置led_driver (platform_driver 类型)的 name 字段为“nuc977-led”,因此在/sys/bus/platform/drivers/目录下有nuc977-led这个文件
6./dev目录下有platled这个文件,因为在led_driver定义的设备名字 #define LEDDEV_NAME "platled" /* 设备名字 */
BusyBox v1.22.1 (2016-02-03 14:11:04 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.
~ #
~ #
~ # ifconfig eth0 192.168.0.4 up
nuc970-emac0 nuc970-emac0: eth0 is OPENED
~ # ping 192.168.0.199
PING 192.168.0.199 (192.168.0.199): 56 data bytes
64 bytes from 192.168.0.199: seq=0 ttl=64 time=2.042 ms
64 bytes from 192.168.0.199: seq=1 ttl=64 time=1.317 ms
^C
--- 192.168.0.199 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 1.317/1.679/2.042 ms
~ # mount -o nolock -t nfs 192.168.0.199:/home/hbin/nfs /mnt
~ # ls /mnt
app driver rootfs_hb
~ # cd /mnt/driver/
/mnt/driver # ls
drv_buttons drv_hello drv_led2 drv_timer
drv_buttons2 drv_led drv_newcharled platform_led
/mnt/driver # cd platform_led/
/mnt/driver/platform_led # ls
Makefile led_app.c leddevice.mod.o leddriver.mod.c
Module.symvers leddevice.c leddevice.o leddriver.mod.o
built-in.o leddevice.ko leddriver.c leddriver.o
led_app leddevice.mod.c leddriver.ko modules.order
/mnt/driver/platform_led # ls /lib/modules/
3.10.101 drv_buttons2.ko drv_led.ko drv_newcharled.ko
drv_buttons.ko drv_hello.ko drv_led2.ko drv_timer.ko
/mnt/driver/platform_led # cd /lib/modules/3.10.101/
/lib/modules/3.10.101 # ls
modules.dep.bb
/lib/modules/3.10.101 # cd /sys
/sys # ls
block class devices fs module
bus dev firmware kernel
/sys # cd bus
/sys/bus # ls
clocksource event_source platform usb
cpu mdio_bus scsi workqueue
/sys/bus # cd platform/
/sys/bus/platform # ls
devices drivers_autoprobe uevent
drivers drivers_probe
/sys/bus/platform # cd devices/
/sys/bus/platform/devices # ls
alarmtimer nuc970-gpio.0 nuc970-gpio.4 nuc970-gpio.8 pinctrl-nuc970
nuc970-ehci nuc970-gpio.1 nuc970-gpio.5 nuc970-lcd regulatory.0
nuc970-emac0 nuc970-gpio.2 nuc970-gpio.6 nuc970-ohci
nuc970-fmi nuc970-gpio.3 nuc970-gpio.7 nuc970-uart.0
/sys/bus/platform/devices # cd ..
/sys/bus/platform # cd drivers/
/sys/bus/platform/drivers # ls
alarmtimer nuc970-emac0 nuc970-gpio nuc970-ohci pinctrl-nuc970
nuc970-ehci nuc970-fmi nuc970-lcd nuc970-uart
/sys/bus/platform/drivers # cd /
~ # cd /mnt
/mnt # ls
app driver rootfs_hb
/mnt # cd driver/
/mnt/driver # ls
drv_buttons drv_hello drv_led2 drv_timer
drv_buttons2 drv_led drv_newcharled platform_led
/mnt/driver # cd platform_led/
/mnt/driver/platform_led # ls
Makefile led_app.c leddevice.mod.o leddriver.mod.c
Module.symvers leddevice.c leddevice.o leddriver.mod.o
built-in.o leddevice.ko leddriver.c leddriver.o
led_app leddevice.mod.c leddriver.ko modules.order
/mnt/driver/platform_led # cp *.ko /lib/modules/3.10.101/
/mnt/driver/platform_led # ls /lib/modules/3.10.101/
leddevice.ko leddriver.ko modules.dep.bb
/mnt/driver/platform_led # dpmod
-/bin/sh: dpmod: not found
/mnt/driver/platform_led # cd /lib/modules/3.10.101/
/lib/modules/3.10.101 # ls
leddevice.ko leddriver.ko modules.dep.bb
/lib/modules/3.10.101 # insmod leddevice.ko
/lib/modules/3.10.101 # lsmod
leddevice 849 0 - Live 0xbf000000 (O)
/lib/modules/3.10.101 # insmod leddriver.ko
nuc977 led driver and device has matched!
------------[ cut here ]------------
WARNING: at drivers/gpio/gpiolib.c:160 gpio_ensure_requested+0x6c/0xd8()
autorequest GPIO-33
Modules linked in: leddriver(O+) leddevice(O)
CPU: 0 PID: 432 Comm: insmod Tainted: G O 3.10.101 #7
Backtrace:
[<c0011f24>] (dump_backtrace+0x0/0x10c) from [<c0012138>] (show_stack+0x18/0x1c)
r6:c01ce358 r5:00000009 r4:c3b13c90 r3:00000000
[<c0012120>] (show_stack+0x0/0x1c) from [<c033b430>] (dump_stack+0x20/0x28)
[<c033b410>] (dump_stack+0x0/0x28) from [<c001d178>] (warn_slowpath_common+0x54/0x70)
[<c001d124>] (warn_slowpath_common+0x0/0x70) from [<c001d1cc>] (warn_slowpath_fmt+0x38/0x40)
r8:00000001 r7:60000013 r6:00000021 r5:c045f184 r4:c049a2e8
r3:00000009
[<c001d194>] (warn_slowpath_fmt+0x0/0x40) from [<c01ce358>] (gpio_ensure_requested+0x6c/0xd8)
r3:00000021 r2:c03d90cc
[<c01ce2ec>] (gpio_ensure_requested+0x0/0xd8) from [<c01ceee8>] (gpiod_direction_output+0x80/0x1a4)
r6:c3b12010 r5:c045f184 r4:c049a2e8 r3:c01d0a28
[<c01cee68>] (gpiod_direction_output+0x0/0x1a4) from [<c01cf120>] (gpio_direction_output+0x1c/0x20)
r8:00000001 r7:bf004364 r6:00000000 r5:c049f1f0 r4:00000001
[<c01cf104>] (gpio_direction_output+0x0/0x20) from [<bf004098>] (nuc977_led_probe+0x28/0x114 [leddriver])
r4:bf0044d0 r3:00000000
[<bf004070>] (nuc977_led_probe+0x0/0x114 [leddriver]) from [<c0208858>] (platform_drv_probe+0x1c/0x20)
r7:bf004364 r6:00000000 r5:c049f1f0 r4:bf000098
[<c020883c>] (platform_drv_probe+0x0/0x20) from [<c020752c>] (really_probe+0x84/0x224)
[<c02074a8>] (really_probe+0x0/0x224) from [<c02077c8>] (__driver_attach+0xa0/0xa4)
r8:c04700c0 r7:00000000 r6:bf0000cc r5:bf004364 r4:bf000098
r3:00000007
[<c0207728>] (__driver_attach+0x0/0xa4) from [<c0205904>] (bus_for_each_dev+0x6c/0x9c)
r6:bf004364 r5:c0207728 r4:00000000 r3:00000000
[<c0205898>] (bus_for_each_dev+0x0/0x9c) from [<c02070ac>] (driver_attach+0x20/0x28)
r6:c0462c98 r5:c3ae7180 r4:bf004364
[<c020708c>] (driver_attach+0x0/0x28) from [<c0206d10>] (bus_add_driver+0x1b8/0x250)
[<c0206b58>] (bus_add_driver+0x0/0x250) from [<c0207c60>] (driver_register+0x80/0x148)
r7:00000000 r6:c3b12000 r5:bf0043b0 r4:bf004364
[<c0207be0>] (driver_register+0x0/0x148) from [<c0208dd4>] (platform_driver_register+0x4c/0x60)
r8:c04700c0 r7:00000000 r6:c3b12000 r5:bf0043b0 r4:c3b13f44
r3:00000000
[<c0208d88>] (platform_driver_register+0x0/0x60) from [<bf006014>] (nuc977_leddriver_init+0x14/0x1c [leddriver])
[<bf006000>] (nuc977_leddriver_init+0x0/0x1c [leddriver]) from [<c0008880>] (do_one_initcall+0x104/0x170)
[<c000877c>] (do_one_initcall+0x0/0x170) from [<c005d100>] (load_module+0x1634/0x1d78)
[<c005bacc>] (load_module+0x0/0x1d78) from [<c005d928>] (SyS_init_module+0xe4/0xf8)
[<c005d844>] (SyS_init_module+0x0/0xf8) from [<c000ec60>] (ret_fast_syscall+0x0/0x34)
r6:bedc7e88 r5:00000000 r4:00000000
---[ end trace 8e0753c504ca25ed ]---
leddev major=252,
nuc977_led_probe
/lib/modules/3.10.101 # cd /sys
/sys # ls
block class devices fs module
bus dev firmware kernel
/sys # cd bus
/sys/bus # ls
clocksource event_source platform usb
cpu mdio_bus scsi workqueue
/sys/bus # cd platform/
/sys/bus/platform # ls
devices drivers_autoprobe uevent
drivers drivers_probe
/sys/bus/platform # cd devices/
/sys/bus/platform/devices # ls
alarmtimer nuc970-gpio.0 nuc970-gpio.4 nuc970-gpio.8 nuc977-led
nuc970-ehci nuc970-gpio.1 nuc970-gpio.5 nuc970-lcd pinctrl-nuc970
nuc970-emac0 nuc970-gpio.2 nuc970-gpio.6 nuc970-ohci regulatory.0
nuc970-fmi nuc970-gpio.3 nuc970-gpio.7 nuc970-uart.0
/sys/bus/platform/devices # cd ..
/sys/bus/platform # ls ./drivers
alarmtimer nuc970-emac0 nuc970-gpio nuc970-ohci nuc977-led
nuc970-ehci nuc970-fmi nuc970-lcd nuc970-uart pinctrl-nuc970
/sys/bus/platform # cd /dev
/dev # ls
bus ram14 tty24 tty50
console ram15 tty25 tty51
cpu_dma_latency ram2 tty26 tty52
fb0 ram3 tty27 tty53
full ram4 tty28 tty54
kmem ram5 tty29 tty55
kmsg ram6 tty3 tty56
mdev.seq ram7 tty30 tty57
mem ram8 tty31 tty58
mtd0 ram9 tty32 tty59
mtd0ro random tty33 tty6
mtd1 tty tty34 tty60
mtd1ro tty0 tty35 tty61
mtd2 tty1 tty36 tty62
mtd2ro tty10 tty37 tty63
mtdblock0 tty11 tty38 tty7
mtdblock1 tty12 tty39 tty8
mtdblock2 tty13 tty4 tty9
network_latency tty14 tty40 ttyS0
network_throughput tty15 tty41 ubi0
null tty16 tty42 ubi0_0
platled tty17 tty43 ubi_ctrl
ptmx tty18 tty44 urandom
ram0 tty19 tty45 vcs
ram1 tty2 tty46 vcs1
ram10 tty20 tty47 vcsa
ram11 tty21 tty48 vcsa1
ram12 tty22 tty49 zero
ram13 tty23 tty5
/dev # cd /mnt
/mnt # ls
app driver rootfs_hb
/mnt # cd driver/
/mnt/driver # ls
drv_buttons drv_hello drv_led2 drv_timer
drv_buttons2 drv_led drv_newcharled platform_led
/mnt/driver # cd platform_led/
/mnt/driver/platform_led # ls
Makefile led_app.c leddevice.mod.o leddriver.mod.c
Module.symvers leddevice.c leddevice.o leddriver.mod.o
built-in.o leddevice.ko leddriver.c leddriver.o
led_app leddevice.mod.c leddriver.ko modules.order
/mnt/driver/platform_led # ./led_app /dev/platled off
argv[0]= ./cmd is 0,arg is 0
led_app
aLEDOFF
rgv[1]= /dev/platled
argv[2]= off
/mnt/driver/platform_led # ./led_app /dev/platled on
argv[0]= ./cmd is 1,arg is 0
LEDON
led_app
argv[1]= /dev/platled
argv[2]= on
/mnt/driver/platform_led # ./led_app /dev/platled off
argv[0]= ./cmd is 0,arg is 0
LEDOFF
led_app
argv[1]= /dev/platled
argv[2]= off
/mnt/driver/platform_led #