Linux应用层想要操作kernel层的API,比方想操作相关GPIO或寄存器,能够通过写一个字符设备驱动来实现。

1、先在rootfs中的 /dev/ 下生成一个字符设备。注意主设备号 和 从设备号。可用例如以下shell脚本生成:

if [ ! -e audioIN ];then
sudo mknod audioIN c 240 0
fi

生成的设备为 /dev/audioIN ,主设备号240,从设备号0。

2、写audioINdriver.ko ,audioINdriver.c 基本代码框架例如以下:代码中定义了设备名audioIN,设备号240, 0 ,与之前创建的设备一致。

/**************************************************************************\
* audioINdriver.c
*
* kang_liu <liukang325@qq.com>
* 2014-07-15
\**************************************************************************/ #include <asm/uaccess.h>
#include <asm/errno.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <mach/gpio.h>
//#include <mach/at91_rstc.h> /* debug */
//#include <mach/at91_pmc.h>
//#include <mach/at91_rstc.h>
//#include <mach/at91_shdwc.h>
#include <mach/irqs.h>
//#include "generic.h"
//#include "clock.h"
#include <mach/w55fa92_reg.h>
#include <asm/io.h> #define DEV_MAJOR 240
#define DEV_MINOR 0
#define NUM_MINORS 1
#define DEVICE_NAME "audioIN" #define ERR(fmt, args...) printk(KERN_ALERT __FILE__ ": " fmt, ##args)
#define MSG(fmt, args...) printk(KERN_INFO __FILE__ ": " fmt, ##args)
#define DBG(fmt, args...) printk(KERN_DEBUG __FILE__ ": " fmt, ##args) static ssize_t user_gpio_read(struct file *fp, char __user *buff,
size_t count, loff_t *offp)
{
char str[32] = {0};
char out[32] = {0};
int n, err;
// printk("lk~~~~~~~read buff = %s\n",buff);
err = copy_from_user(str, buff, count);
// printk("lk~~~~~~~read str = %s\n",str);
if (err)
return -EFAULT; sprintf(out,"return values");
memset(buff, 0, count);
err = copy_to_user(buff, out, sizeof(out));
if (err)
return -EFAULT; return n;
} static ssize_t user_gpio_write(struct file *fp, const char __user *buff,
size_t count, loff_t *offp)
{
int err;
char tmp[32]; // printk("lk~~~~~~~write buff = %s\n",buff);
err = copy_from_user(tmp, buff, count);
// printk("lk~~~~~~~write tmp = %s\n",tmp); if (err)
return -EFAULT;
if('1' == tmp[0])
{
//LINE IN
printk("line in\n");
}
else if('0' == tmp[0])
{
//MIC IN
printk("mic in\n");
} return count;
} static ssize_t user_gpio_open(struct inode *inode,struct file *fp)
{
// printk("open gpio devices\n"); return 0;
} static struct file_operations user_gpio_file_ops =
{
.owner = THIS_MODULE,
.write = user_gpio_write,
.read = user_gpio_read,
.open = user_gpio_open,
}; static struct cdev *dev; static void __exit user_audioIN_exit(void)
{
printk("exit audioIN\n");
dev_t devno = MKDEV(DEV_MAJOR, DEV_MINOR); unregister_chrdev_region(devno, NUM_MINORS); cdev_del(dev); return;
} static int __init user_audioIN_init(void)
{
printk("init audioIN\n");
int err = 0;
int i;
dev_t devno = MKDEV(DEV_MAJOR, DEV_MINOR); err = register_chrdev_region(devno, NUM_MINORS, DEVICE_NAME); if (err)
goto fail_devno; dev = cdev_alloc();
dev->ops = &user_gpio_file_ops;
dev->owner = THIS_MODULE; err = cdev_add(dev, devno, NUM_MINORS); if (err)
goto fail_cdev; return err;
fail_cdev:
fail_devno:
unregister_chrdev_region(devno, NUM_MINORS);
fail_gpio:
return err;
} module_init(user_audioIN_init);
module_exit(user_audioIN_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("kang_liu <liukang325@qq.com>");
MODULE_DESCRIPTION("Access GSEIO from userspace.");

这里就能够调用kernel层的一些API进行底层的操作。

Makefile:生成audioINdriver.ko

# Comment/uncomment the following line to disable/enable debugging
#DEBUG = y
BUILD_TOOLS_PRE = arm-linux- CC=$(BUILD_TOOLS_PRE)gcc
LD=$(BUILD_TOOLS_PRE)ld
# Add your debugging flag (or not) to CFLAGS
ifeq ($(DEBUG),y)
DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
else
DEBFLAGS = -O2
endif KERNEL_DIR = ../../../linux-2.6.35.4 EXTRA_CFLAGS += $(DEBFLAGS)
EXTRA_CFLAGS += -I$(LDDINC)
EXTRA_CFLAGS +=-I$(KERNEL_DIR)/arch/arm/mach-w55fa92/include
EXTRA_CFLAGS +=-I$(KERNEL_DIR)/arch/arm
EXTRA_CFLAGS +=-I$(KERNEL_DIR)/arch/arm/include
EXTRA_CFLAGS +=-I$(KERNEL_DIR)/arch/arm/include/linux ifneq ($(KERNELRELEASE),)
# call from kernel build system audioIN-objs := audioINdriver.o obj-m := audioINdriver.o else
KERNELDIR ?= $(KERNEL_DIR)
#KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd) modules:
$(MAKE) ARCH=arm CROSS_COMPILE=$(BUILD_TOOLS_PRE) -C $(KERNELDIR) M=$(PWD) LDDINC=$(PWD)/../include modules endif clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers depend .depend dep:
$(CC) $(CFLAGS) -M *.c > .depend ifeq (.depend,$(wildcard .depend))
include .depend
endif

3. 生成好 .ko 以后,就能够在ARM板上,载入驱动。

insmod audioINdriver.ko

4、载入驱动成功后,就能够在应用层直接操作设备 /dev/audioIN,来实现相关功能,将一些參数传到驱动层,运行相关kernel层的代码。

应用层測试程序例如以下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#define BUF_LEN 32
int s_audioInFd = 0; int InitAudioInDevice()
{
s_audioInFd = open("/dev/audioIN",O_RDWR); if (s_audioInFd > 0)
{
return 1;
}
else
{
printf("Can't open the GSE IO device\n");
return 0;
}
} void UninitAudioInDevice()
{
if (s_audioInFd > 0)
close(s_audioInFd);
} int getAudioIn()
{
char buffer[BUF_LEN] = {0};
if (s_audioInFd > 0)
{
memcpy(&buffer[0], "lk_test", 7);
// printf("get buffer = %s\n", buffer);
int len = read(s_audioInFd, buffer, 7);
// printf("get buffer = %s, len = %d\n", buffer, len);
return len;
} return -1;
} int setAudioIn(int micLine)
{
char buffer[BUF_LEN] = {0};
if (s_audioInFd > 0)
{
sprintf(buffer, "%d", micLine);
int len = write(s_audioInFd, buffer, sizeof(buffer));
if (len > 0)
return 1;
} return 0;
}

当中的read 和 write函数,可从驱动中获取一些返回值,也可将字符串传到驱动中。

驱动的入口为:

module_init(user_audioIN_init);

module_exit(user_audioIN_exit);

Linux实现字符设备驱动的基础步骤的更多相关文章

  1. linux学习--字符设备驱动

    目录 1.字符设备驱动抽象结构 2.设备号及设备节点 2.1 设备号分配与管理 2.2 设备节点的生成 3.打开设备文件 linux驱动有基本的接口进行注册和卸载,这里不再做详细说明,本文主要关注li ...

  2. linux driver ------ 字符设备驱动 之 “ 创建设备节点流程 ”

    在字符设备驱动开发的入门教程中,最常见的就是用device_create()函数来创建设备节点了,但是在之后阅读内核源码的过程中却很少见device_create()的踪影了,取而代之的是device ...

  3. Linux高级字符设备驱动

    转载:http://www.linuxidc.com/Linux/2012-05/60469p4.htm 1.什么是Poll方法,功能是什么? 2.Select系统调用(功能)      Select ...

  4. linux 高级字符设备驱动 ioctl操作介绍 例程分析实现【转】

    转自:http://my.oschina.net/u/274829/blog/285014 1,ioctl介绍 ioctl控制设备读写数据以及关闭等. 用户空间函数原型:int ioctl(int f ...

  5. Linux高级字符设备驱动 poll方法(select多路监控原理与实现)

    1.什么是Poll方法,功能是什么? 2.Select系统调用(功能)      Select系统调用用于多路监控,当没有一个文件满足要求时,select将阻塞调用进程.      int selec ...

  6. Linux 字符设备驱动开发基础(二)—— 编写简单 PWM 设备驱动【转】

    本文转载自:https://blog.csdn.net/zqixiao_09/article/details/50858776 版权声明:本文为博主原创文章,未经博主允许不得转载.    https: ...

  7. Linux LED字符设备驱动

    // 申请IO资源 int gpio_request(unsigned gpio, const char *label); // 释放IO资源 void gpio_free(unsigned gpio ...

  8. Linux 简单字符设备驱动

    1.hello_drv.c (1) 初始化和卸载函数的格式是固定的,函数名自定义 (2) printk是内核的打印函数,用法与printf一致 (3) MODULE_LICENSE:模块代码支持开源协 ...

  9. 【转】linux设备驱动程序之简单字符设备驱动

    原文网址:http://www.cnblogs.com/geneil/archive/2011/12/03/2272869.html 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用 ...

随机推荐

  1. c语言,结构体里面的函数

    以linux-3.2内核代码为例,结构体里面的函数的用法: 例,在某驱动文件中,定义了一个平台设备驱动: static struct platform_driver s3c24xx_led_drive ...

  2. 基于visual Studio2013解决C语言竞赛题之1023判断排序

         题目 解决代码及点评 /* 23. 有10个两位整数,把这些数作以下变化,如果它是素数, 则把它乘以2,若它是偶数则除以2,其余的数减1, 请将变化后的10个数按从小到大 ...

  3. hdu 3998 (dp+最大流)

    题意:求最长上升子序列的长度和数量. 分析:用dp求出最长上升子序列m,dp数组存的就是该元素为子序列结尾的长度,源点与长度为1的点建边,长度为m的与汇点连边,然后枚举任意两个元素,ai,aj(ai& ...

  4. hadoop部署、启动全套过程

    Hadoop是Apache基金会的开源项目,为开发者提供了一个分布式系统的基础架构,用户可以在不了解分布式系统的底层细节的情况下开发分布式的应用,充分利用集群的强大功能,实现高速运算和存储.Hadoo ...

  5. Linux下搭建Hadoop具体步骤

    装好虚拟机+Linux.而且主机网络和虚拟机网络互通. 以及Linux上装好JDK 1:在Linux下输入命令vi /etc/profile 加入HADOOP_HOME export JAVA_HOM ...

  6. [置顶] NS2中TCP拥塞控制仿真过程中盲点解析

    最近利用NS2做TCP拥塞控制协议的仿真,发现很多变量的方法含义都是解释的不清楚,给核心模块修改带来很多麻烦,所以决定用最准确的语言解释成员变量.方法,术语等的含义.限于个人水平,若有错误请留言指正! ...

  7. Eclipse用法和技巧十七:覆盖父类方法

    在学校里面学习java,遇到访问权限修饰符一直停留在public是公有的,外面可以访问:protected是对子类可见的,外部不可以访问:private仅在本类中可见.工作之后,接触到了java代码多 ...

  8. office文档转pdf

    这里贴下代码吧,没啥好说的. using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

  9. 重操JS旧业第七弹:面向对象与对象创建

    JS是一种完全面向对象的程序设计语言,在面向对象处理方面,具有多种多样的实现方式,加之对象成员的动态性使得这门语言更加灵活:而js对象成员动态性也是创建和扩展对象的有力方式. 1 对象成员动态性 属性 ...

  10. 10个优秀的 HTML5 &amp; CSS3 下拉菜单制作教程

    下拉菜单是一个非经常见的效果.在站点设计中被广泛使用.通过使用下拉菜单.设计者不仅能够在站点设计中营造出色的视觉吸引力,但也能够为站点提供了一个有效的导航方案.使用 HTML5 和 CSS3 能够更e ...