LINUX学习笔记:(2)编写驱动模块

40 篇文章 2 订阅

LINUX学习笔记:(2)编写驱动模块

宿主机 : 虚拟机 Ubuntu 16.04 LTS / X64
目标板[底板]: Tiny4412SDK - 1506
目标板[核心板]: Tiny4412 - 1412
LINUX内核: 4.12.0
交叉编译器: arm-none-linux-gnueabi-gcc(gcc version 4.8.3 20140320)
日期: 2018-2-28 19:35:35
作者: SY

简介

本章节主要介绍如何编写驱动模块运行在基于 ARMLinux 上。模块可以在运行期间手动安装、卸载,具有即插即用的好处!

APP

led.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>

/* 平台头文件 */
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>

#define DEVICE_NAME                 "LED"

/* 配置IO端口 */
static unsigned int gpio_table[] = {
    EXYNOS4X12_GPM4(0),
    EXYNOS4X12_GPM4(1),
    EXYNOS4X12_GPM4(2),
    EXYNOS4X12_GPM4(3),
}; 
#define LED_NUMS                    ARRAY_SIZE(gpio_table)

/* LED操作方法 */
#define CMD_LED_OPEN                (0)
#define CMD_LED_CLOSE               (1)
static long led_device_ioctl( struct file *filp, unsigned int cmd,
                unsigned long arg )
{   
    if (arg >= LED_NUMS)
    {
        return -EINVAL; 
    }

    switch ( cmd )
    {
        case CMD_LED_OPEN:
            gpio_set_value(gpio_table[arg], CMD_LED_OPEN);
            break;
        case CMD_LED_CLOSE:
            gpio_set_value(gpio_table[arg], CMD_LED_CLOSE);
            break;
        default:
            return -EINVAL;
    }   

    return 0;
}

static struct file_operations led_device_fops = {
    .owner          = THIS_MODULE,
    .unlocked_ioctl = &led_device_ioctl,
};

/**
 *  模块归属为misc设备,所有的misc设备共享同一个主设备号
 *  次设备号为MISC_DYNAMIC_MINOR,表示由系统自动分配
 */
static struct miscdevice led_dev = {
    .minor          = MISC_DYNAMIC_MINOR,
    .name           = DEVICE_NAME,
    .fops           = &led_device_fops,
};

static int __init led_device_init( void )
{
    int ret,i;

    printk("led register!\n");

    for (i=0; i<LED_NUMS; ++i)
    {
        /**
         * 由于开发板已经配置过GPIO,因此不能再请求该端口
         */ 
        /*
        ret = gpio_request(gpio_table[i], "led");
        if (ret)
        {
            printk("请求gpio端口失败!\n");

            return  ret;
        }
        */
        s3c_gpio_cfgpin(gpio_table[i], S3C_GPIO_OUTPUT);
        gpio_set_value(gpio_table[i], CMD_LED_CLOSE);
    }

    ret = misc_register(&led_dev);

    return ret;
}
module_init(led_device_init);

static void __exit led_device_exit( void )
{
    //int i;

    printk("led deregister!\n");
    /*
    for (i=0; i<LED_NUMS; ++i)
    {
        gpio_free(gpio_table[i]);   
    }
    */
    misc_deregister(&led_dev);  
}
module_exit(led_device_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("SY");
MODULE_DESCRIPTION("LED Module");
MODULE_VERSION("1.0.0.0");

Makefile

Makefile

CROSS   := arm-linux-
obj-m   := bsp_led.o
KDIR    := /lib/modules/3.5.0-FriendlyARM/build
PWD     := $(shell pwd)

default:
    $(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
    rm -rf *.o *.ko *.mod.c *.temp_versions *.symvers *.order

编译

在驱动模块当前文件夹中执行:

$ make

即可生成内核模块 led.ko

模块加载

将模块拷贝到开发板中,加载模块:

$ insmod led.ko
$ led register!

列举模块

$ lsmod

删除模块

$ rmmod led.ko
$ led deregister!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值