1. 程式人生 > >AM335x內核模塊驅動之LED

AM335x內核模塊驅動之LED

author unlock obj magic oct gen sig dev pri

在Ubuntu的任意可操作的文件才建立text目錄

在text中建立zyr-hello.c:

#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/init.h>
#include <linux/miscdevice.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include 
<linux/errno.h> #include <linux/fs.h> #include <linux/init.h> #define CORE_LED (1*32 + 7) //硬件上的一個led燈為goip1_7 #define DEVICE "led_core" #define MAGIC_NUM 0xDB #define MAGIC_SET_LOW _IO(MAGIC_NUM,0) #define MAGIC_SET_HIGH _IO(MAGIC_NUM,1) int led_open(struct inode *inode, struct file *file) {
int ret; ret = gpio_request_one(CORE_LED, (GPIOF_DIR_OUT|GPIOF_OUT_INIT_HIGH),"core_led"); if(ret) { printk("Error: cannot request gpio CORE_LED. \n"); printk("Error ret = %d but still can be manipulated. \n", ret); } gpio_set_value(CORE_LED,
1); return 0; } int led_release(struct inode *inode, struct file *filp) { gpio_free(CORE_LED); printk("GPIO LED dev release. \n"); return 0; } long led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { switch(cmd) { case MAGIC_SET_LOW: printk("GPIO LED set low.\n"); gpio_set_value(CORE_LED,0); break; case MAGIC_SET_HIGH: printk("GPIO LED set high.\n"); gpio_set_value(CORE_LED,1); break; default: printk("ERROR unvalid cmd.\n"); break; } return 0; } struct file_operations led_fops ={ .owner = THIS_MODULE, .open = led_open, .release = led_release, .unlocked_ioctl = led_ioctl, }; struct miscdevice led_dev ={ .minor = MISC_DYNAMIC_MINOR, .name = DEVICE, .fops = &led_fops, }; static int led_init(void) { int ret; ret = misc_register(&led_dev); if (ret) { printk("Error: cannot register misc. \n"); return ret; } printk("misc-register %s\n",DEVICE); return 0; } static void led_exit(void) { misc_deregister(&led_dev); printk("misc-deregister %s\n",DEVICE); } module_init(led_init); module_exit(led_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("zyr<[email protected]>");

在該目錄下建立Makefile文件:

ifneq ($(KERNELRELEASE),)
obj-m := zyr-hello.o
else
KDIR :=/home/zyr/Source_code/linux-3.14.65/
all:
    make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8
clean:
    rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order
endif

其中KDIR為內核的路徑,要想編譯arm可運行的驅動,一定要指定交叉編譯器

在該目錄下執行make,會編譯器出zyr-hello.ko文件,此文件為可加載於內核的.ko模塊的文件。

然後編寫這個led驅動的的測試文件(運行在文件系統中):

同樣在任意的可執行處建立一個目錄放測試文件比如aa:

在該目錄下建立led_test.c:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<string.h>
#include<asm-generic/ioctl.h>

#define DEVICE          "/dev/led_core"
#define MAGIC_NUM       0xDB
#define MAGIC_SET_LOW   _IO(MAGIC_NUM, 0)
#define MAGIC_SET_HIGH  _IO(MAGIC_NUM, 1)

int main(int argc, char *argv[])
{
       int fd;

        printf("Start led test.\n");

        fd = open(DEVICE, O_RDWR);
        if (fd < 2) {
                printf("Cannot open device %s\n", DEVICE);
                return -EFAULT;
        }       
        while (1) {
                ioctl(fd, MAGIC_SET_LOW, 0);
                sleep(1);
                ioctl(fd, MAGIC_SET_HIGH, 0);
                sleep(1);
        }
        return 0;       
}

在該目錄下建立Makefile文件:

#----------------------------
CC    = arm-linux-gnueabihf-gcc 
CFLAGS    =         
main : led_test.c 
    $(CC) $(CFLAGS) led_test.c -o led_test

在該目錄下執行make:生成led_test可執行文件。

將led_test可執行文件和zyr-hello.ko模塊文件copy到建立好的NFS共享文件夾下敲擊命令(在arm板的終端中):

[[email protected] ]#mount -t nfs -o nolock 192.168.200.123:/home/zyr/Source_code/text/nfs /mnt
[[email protected]-am335x ]#cd /mnt
[[email protected]-am335x mnt]#ls
led_test      zyr-hello.ko
[[email protected]-am335x mnt]#insmod zyr-hello.ko
[ 5299.759382] misc-register led_core
[[email protected]-am335x mnt]#./led_test
Start led test.
[ 5309.324907] GPIO LED set low.
[ 5310.338522] GPIO LED set high.
[ 5311.342169] GPIO LED set low.
[ 5312.345413] GPIO LED set high.

參考博客:

http://www.eefocus.com/marianna/blog/15-02/310302_72e75.html

AM335x內核模塊驅動之LED