Linux驱动开发入门之编译驱动模块-程序员宅基地

Linux驱动开发培训系列教程网址https://edu.csdn.net/course/detail/26814

Linux驱动开发入门之编译驱动模块

调试Linux驱动的基本流程是先把驱动编译成模块,通过insmod命令加载到内核进行调试。调试完成,编译进内核即可。下面的代码基于Linux3.2(AM335X)平台上经过验证。

第一步,在任意位置创建目录gao_driver
第二步,在目录gao_driver中创建文件hello.c makefile
其中hello.c内容:

/*******************************************************************************************
*
*******************************************************************************************/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/spi/spi.h>
#include <linux/bcd.h>
#include <linux/miscdevice.h>  

/*******************************************************************************************
*
*******************************************************************************************/
int my_gpio_open(struct inode *inode, struct file *filp)
{
    
	printk("my_gpio_open \n");
	
	return 0;
}

/*******************************************************************************************
*
*******************************************************************************************/
static ssize_t my_gpio_write(struct file *filp, const char __user *buf,  size_t size, loff_t *ppos)
{
    
	char gao_buf[100];

	printk("my_gpio_write\n");

	memset(gao_buf, 0, 100);

	/*用户空间->内核空间*/
	if (copy_from_user(gao_buf, buf, size))
	{
    
		printk("copy_from_user error\n");
	}
	printk("my_gpio_write=%s\n", gao_buf);
	return size;
}

/*******************************************************************************************
*
*******************************************************************************************/
static ssize_t my_gpio_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
    
	char gao_buf[100];

	printk("my_gpio_read\n");

	memset(gao_buf, 0, 100);

	sprintf(gao_buf, "gaoyanli hello world");

	if(copy_to_user(buf, gao_buf, strlen(gao_buf)))
	{
    
		printk("my_gpio_read error\n");
	}
	return 0;
}

/*******************************************************************************************
*
*******************************************************************************************/
int my_gpio_release(struct inode *inode, struct file *filp)
{
    
	return 0;
}

/*******************************************************************************************
*
*******************************************************************************************/
struct file_operations my_gpio_fops = 
{
    
    .owner = THIS_MODULE,

	.open    =  my_gpio_open,
	.write   =  my_gpio_write,
	.read    =  my_gpio_read, 
	.release =  my_gpio_release,
};

//分配初始化miscdevice
static struct miscdevice my_gpio_dev = 
{
    
    .minor = MISC_DYNAMIC_MINOR,     //自动分配次设备号
    .name = "my_gpio",               //产生设备节点dev/my_gpio
    .fops = &my_gpio_fops
};

/*******************************************************************************************
*
*******************************************************************************************/
int my_gpio_init(void)
{
    
	printk("---------------------------------------------------------------------my_gpio_init\n");

	//注册混杂设备驱动。产生设备节点/dev/my_gpio
	misc_register(&my_gpio_dev); 

	return 0;
}

/*******************************************************************************************
*
*******************************************************************************************/
void my_gpio_remove(void)
{
    
	printk("------------------------------------------------------------------my_gpio_remove\n");


	//卸载混杂设备
	misc_deregister(&my_gpio_dev); 
}

/*******************************************************************************************
*
*******************************************************************************************/
module_init(my_gpio_init);
module_exit(my_gpio_remove);

MODULE_AUTHOR("gaoyanli");
MODULE_LICENSE("GPL");
MODULE_ALIAS("spi:da5304"); 

其中makefile内容:

MOD_FILE=hello

#ifneq ($(KERNELRELEASE),)
	obj-m := $(MOD_FILE).o
#else
	KERNELDIR = /home/forlinx/okxx18-source-android51/kernel
	PWD :=$(shell pwd)
all:	
	$(MAKE) -C $(KERNELDIR)   M=$(PWD) ARCH=arm CROSS_COMPILE=/home/forlinx/okxx18-source-android51/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi- modules  -Wno-error=format-security

clean:
	rm ./*.o
	rm ./*.ko
	rm ./*.mod.c
	rm ./module*
	rm ./Module*
#endif;

第三步,进入目录gao_driver,编译模块,生成hello.ko

#cd ./gao_driver
#make

第四步,把hello.ko下载到开发板,并加载进内核。

#insmod hello.ko
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/gaoyanli1972/article/details/103022681

智能推荐

MFC 笔记(二)属性页和向导的创建-程序员宅基地

基于孙鑫老师讲授的MFC第8讲的视频对属性页和向导的创建而做的一点笔记

从数仓到数据中台,谈技术选型最优解-程序员宅基地

颜博马蜂窝数仓研发总监现任马蜂窝数据仓库团队负责人,曾供职于京东、IBM、亚信等公司。数据行业老兵一名,历经传统数据仓库、大数据平台到数据中台的发展。大家好,今天分享的议题主要包括几大内...

RMAN恢复单实例至RAC 并升级Oracle 版本_rman 升级-程序员宅基地

一、描述:本文主要讲解单实例RMAN异机恢复至RAC集群并升级数据库的相关事宜。本文主要记录的是使用RMAN恢复ORACLE 11.2.0.3 至 11.2.0.4的详细步骤。本文源端环境为Redhat 6.8 + Oracle 11.2.0.3 目标端环境为 Redhat 7.4 RAC + Oracle11.2.0.4。话不多说,进入实战。二、准备环境安装RAC的步骤就不在..._rman 升级

javascript中let和var的区别_js中let和var的区别-程序员宅基地

今天使用laravel-admin中的JS来控制页面的操作部分内容转载于简书:javascript中let和var的区别一、背景$script = <<<JS const iIndexs = "{$iIndexs}"; $('#indexs').on('input', _debounce(ajaxVerifyI..._js中let和var的区别

笔记(十)Java中的标识符与关键字(详解)-程序员宅基地

引言我们在java程序编程中,使用EditPlus工具进行代码编写的时候,有一些单词是蓝色,有的是红色,有的是黑色......在这其中,在java源代码中,在EditPlus工具中显示的高亮颜色为黑色时,这个单词属于标识符。标识符可以标识什么?可以标识:类名 方法名 变量名 接口名 常量名 ......那么,到底什么是标识符呢?一句话:凡是程序员自己有权利命名的单词都是标识符。注意:mian是标识符,但是不可以修改。因为main是SUN公司固定死的...

随便推点

C++ 定时器任务类实现-程序员宅基地

#ifndef __TIMERTASK_H_#define __TIMERTASK_H_/* 定时器任务基类 */#include "asr_taskinterface.h"#include "comontype.h"class BaseTimerTask{public: BaseTimerTask():m_uiTvSec(0),m_uiTvUsec(0){} ..._c++ 实现简单任务调度 select使用

【javm】 -浅谈垃圾收集器(gc)-程序员宅基地

一堆介绍堆主要划分为新生代和老年代;详细划分为Eden,from survivor ,to survivor;二jdk1.8-jvm内存模型要看详细的介绍情看的介绍请看作者发布的"jvm运行时数据区一文",jdk1.8中已经取代了方法区永久带的概念转而的是在方法区中的元空间,有人也称作是直接内存​。二垃圾收集器示意图图中有直线连接的说明是能够相互配合使用的垃圾收集器。​三垃圾收..._javm

java编写九宫格拼图游戏_九宫格拼图游戏_桑夷的博客-程序员宅基地

九宫格拼图游戏设计文档一、综合设计目的、条件、任务和内容要求:1.设计目的《Windows程序设计》是计算机科学与技术专业本科生的一门学科基础课程。Windows程序以图形用户界面(GUI)给用户提供各种功能,在各行各业有着广泛的应用。基于MFC的Windows程序设计是进行Win32程序设计的一种主流方法。本课程主要介绍Windows程序设计的思想和方法,以及MFC的常见应用。本课程综合应用算法..._九格拼图项目描述怎么写

图像直方图均衡化c语言程序,图像增强 直方图均衡化处理C语言实现_杨佶Kulbear的博客-程序员宅基地

1、图像增强 直方图均衡化 处理C 语言实现#ifndef BMP_H_3_INCLUDED#define BMP_H_3_INCLUDED typedef unsigned short WORD;typedef unsigned long DWORD;typedef long LONG;typedef unsigned char BYTE;typedef struct tagBITMAPFILE..._图象增强c语言

QueryPerformanceCounter()查询时钟频率问题-程序员宅基地

QueryPerformanceCounter() 高精度定时器…………查询不正常,在多核的情况下可以用用SetThreadAffinityMask() 解决 WINAPISetThreadAffinityMask( __in HANDLE hThread, __in DWORD_PTR dwThreadAffinityMask );该函数

Android studio启动自带的模拟器,“Error While waiting for device: The emulator process for AVD has terminated“_YSDLAM的博客-程序员宅基地

Android studio启动自带的模拟器,提示"Error While waiting for device: The emulator process for AVD has terminated"。