2019-11-29(openwrt系統(tǒng)驅(qū)動(dòng)開(kāi)發(fā)B)

在/package/kernel目錄下新建一個(gè)目錄mydrv骂租,下面有一個(gè)Makefile和一個(gè)src目錄

在src目下下有三個(gè)文件道逗,Kconfig致份,Makefile逻族,mydrv.c?

下面分別介紹每一個(gè)文件

1. 第一個(gè)Makefile

include $(TOPDIR)/rules.mk

include $(INCLUDE_DIR)/kernel.mk

PKG_NAME:=mydrv

PKG_RELEASE:=1

include $(INCLUDE_DIR)/package.mk

define KernelPackage/mydrv

? SUBMENU:=Other modules

? TITLE:=mydrv

? FILES:=$(PKG_BUILD_DIR)/mydrv.ko

? KCONFIG:=

endef

define KernelPackage/mydrv/description

? This is a mydrv drivers

endef

MAKE_OPTS:= \

?? ?ARCH="$(LINUX_KARCH)" \

?? ?CROSS_COMPILE="$(TARGET_CROSS)" \

?? ?SUBDIRS="$(PKG_BUILD_DIR)"

define Build/Prepare

?? ?mkdir -p $(PKG_BUILD_DIR)

?? ?$(CP) ./src/* $(PKG_BUILD_DIR)/

endef

define Build/Compile

?? ?$(MAKE) -C "$(LINUX_DIR)" \

?? ?$(MAKE_OPTS) modules

endef

$(eval $(call KernelPackage,mydrv))

2. src下的Kconfig

config MYDRV

? ? tristate "Just a mydrv"

? ? help

? ? This is a example, for debugging kernel model.

? ? If unsure, say N.

3. src下的Makefile

?obj-m += mydrv.o

4. src下的源碼文件mydrv.c

/*****************************?

*

* ? 驅(qū)動(dòng)程序模板

* ? 版本:V1

* ? 使用方法(末行模式下):

* ? :%s/mydrv/"你的驅(qū)動(dòng)名稱(chēng)"/g

*

*******************************/

#include <linux/mm.h>

#include <linux/miscdevice.h>

#include <linux/slab.h>

#include <linux/vmalloc.h>

#include <linux/mman.h>

#include <linux/random.h>

#include <linux/init.h>

#include <linux/raw.h>

#include <linux/tty.h>

#include <linux/capability.h>

#include <linux/ptrace.h>

#include <linux/device.h>

#include <linux/highmem.h>

#include <linux/crash_dump.h>

#include <linux/backing-dev.h>

#include <linux/bootmem.h>

#include <linux/splice.h>

#include <linux/pfn.h>

#include <linux/export.h>

#include <linux/io.h>

#include <linux/aio.h>

#include <linux/kernel.h>

#include <linux/module.h>

#include <asm/uaccess.h>

#include <linux/ioctl.h>

#define MYLEDS_LED1_ON ?0

#define MYLEDS_LED1_OFF 1

volatile unsigned long *GPIOMODE;

volatile unsigned long *GPIO11_DIR;

volatile unsigned long *GPIO11_SETDATA;

volatile unsigned long *GPIO11_RESETDATA;

/**************** ?基本定義 **********************/

//內(nèi)核空間緩沖區(qū)定義

#if 0

?? ?#define KB_MAX_SIZE 20

?? ?#define kbuf[KB_MAX_SIZE];

#endif

//加密函數(shù)參數(shù)內(nèi)容: _IOW(IOW_CHAR , IOW_NUMn , IOW_TYPE)

//加密函數(shù)用于mydrv_ioctl函數(shù)中

//使用舉例:ioctl(fd , _IOW('L',0x80,long) , 0x1);

//#define NUMn mydrv , if you need!

#define IOW_CHAR 'L'

#define IOW_TYPE ?long

#define IOW_NUM1 ?0x80

//初始化函數(shù)必要資源定義

//用于初始化函數(shù)當(dāng)中

//device number;

?? ?dev_t dev_num;

//struct dev

?? ?struct cdev mydrv_cdev;

//auto "mknode /dev/mydrv c dev_num minor_num"

struct class *mydrv_class = NULL;

struct device *mydrv_device = NULL;

/**************** 結(jié)構(gòu)體 file_operations 成員函數(shù) *****************/

/*======================================================================

======================================================================*/

//open

static int mydrv_open(struct inode *inode, struct file *file)

{

?? ?printk("mydrv drive open...\n");

?? ?*GPIO11_RESETDATA |=(1u<<11);

?? ?return 0;

}

/*======================================================================

======================================================================*/

//close

static int mydrv_close(struct inode *inode , struct file *file)

{

?? ?printk("mydrv drive close...\n");

?? ?return 0;

}

/*======================================================================

======================================================================*/

//read

static ssize_t mydrv_read(struct file *file, char __user *buffer,

?? ??? ??? ?size_t len, loff_t *pos)

{

?? ?int ret_v = 0;

?? ?printk("mydrv drive read...\n");

?? ?return ret_v;

}

/*======================================================================

======================================================================*/

//write

static ssize_t mydrv_write( struct file *file , const char __user *buffer,

?? ??? ??? ? ? size_t len , loff_t *offset )

{

?? ?int ret_v = 0;

?? ?printk("mydrv drive write...\n");

?? ?return ret_v;

}

/*======================================================================

======================================================================*/

//unlocked_ioctl

static int mydrv_ioctl (struct file *filp , unsigned int cmd , unsigned long arg)

{

?? ?int ret_v = 0;

?? ?printk("mydrv drive ioctl...\n");

?? ?switch(cmd)

?? ?{

?? ??? ?//常規(guī):

?? ??? ?//cmd值自行進(jìn)行修改

?? ??? ? case MYLEDS_LED1_ON:

?? ??? ? ? ? ?*GPIO11_RESETDATA |= (1u<<11);

?? ??? ? break;

?? ??? ? case MYLEDS_LED1_OFF:

? ? ? ? ? ? ?*GPIO11_SETDATA |= (1u<<11);

?? ??? ? break;

?? ??? ?//帶密碼保護(hù):

?? ??? ?//請(qǐng)?jiān)?基本定義"進(jìn)行必要的定義

?? ??? ?case _IOW(IOW_CHAR,IOW_NUM1,IOW_TYPE):

?? ??? ?{

?? ??? ??? ?if(arg == 0x1) //第二條件

?? ??? ??? ?{


?? ??? ??? ?}

?? ??? ?}

?? ??? ?break;

?? ??? ?default:

?? ??? ??? ?break;

?? ?}

?? ?return ret_v;

}

/***************** 結(jié)構(gòu)體: file_operations ************************/

/*======================================================================

//struct

======================================================================*/

static const struct file_operations mydrv_fops = {

?? ?.owner ? = THIS_MODULE,

?? ?.open?? ? = mydrv_open,

?? ?.release = mydrv_close,?? ?

?? ?.read?? ? = mydrv_read,

?? ?.write ? = mydrv_write,

?? ?.unlocked_ioctl?? ?= mydrv_ioctl,

};

/************* ?functions: init , exit*******************/

//條件值變量,用于指示資源是否正常使用

unsigned char init_flag = 0;

unsigned char add_code_flag = 0;

/*======================================================================

//init

======================================================================*/

static __init int mydrv_init(void)

{

?? ?int ret_v = 0;

?? ?printk("mydrv drive init...\n");

?? ?//函數(shù)alloc_chrdev_region主要參數(shù)說(shuō)明:

?? ?//參數(shù)2: 次設(shè)備號(hào)

?? ?//參數(shù)3: 創(chuàng)建多少個(gè)設(shè)備

?? ?if( ( ret_v = alloc_chrdev_region(&dev_num,0,1,"mydrv") ) < 0 )

?? ?{

?? ??? ?goto dev_reg_error;

?? ?}

?? ?init_flag = 1; //標(biāo)示設(shè)備創(chuàng)建成功束昵;

?? ?printk("The drive info of mydrv:\nmajor: %d\nminor: %d\n",

?? ??? ?MAJOR(dev_num),MINOR(dev_num));

?? ?cdev_init(&mydrv_cdev,&mydrv_fops);

?? ?if( (ret_v = cdev_add(&mydrv_cdev,dev_num,1)) != 0 )

?? ?{

?? ??? ?goto cdev_add_error;

?? ?}

?? ?mydrv_class = class_create(THIS_MODULE,"mydrv");

?? ?if( IS_ERR(mydrv_class) )

?? ?{

?? ??? ?goto class_c_error;

?? ?}

?? ?mydrv_device = device_create(mydrv_class,NULL,dev_num,NULL,"mydrv");

?? ?if( IS_ERR(mydrv_device) )

?? ?{

?? ??? ?goto device_c_error;

?? ?}

?? ?printk("auto mknod success!\n");

?? ?//------------ ? 請(qǐng)?jiān)诖颂砑幽某跏蓟绦??--------------//??

?? ?//GPIOMODE=(volatile unsigned long *)ioremap(0x10000060,4);//gpio 復(fù)用時(shí)需要配置

? ? GPIO11_DIR=(volatile unsigned long *)ioremap(0x10000600,4);

?? ?GPIO11_SETDATA=(volatile unsigned long *)ioremap(0x10000630,4);

? ? GPIO11_RESETDATA=(volatile unsigned long *)ioremap(0x10000640,4);? ?

?? ?//*GPIOMODE |= (1u<<11);

?? ?*GPIO11_DIR |= (1u<<11);

? ? ? ? //如果需要做錯(cuò)誤處理拔稳,請(qǐng):goto mydrv_error;?? ?

?? ? add_code_flag = 1;

?? ?//---------------------- ?END ?---------------------------//?

?? ?goto init_success;

dev_reg_error:

?? ?printk("alloc_chrdev_region failed\n");?? ?

?? ?return ret_v;

cdev_add_error:

?? ?printk("cdev_add failed\n");

??? ?unregister_chrdev_region(dev_num, 1);

?? ?init_flag = 0;

?? ?return ret_v;

class_c_error:

?? ?printk("class_create failed\n");

?? ?cdev_del(&mydrv_cdev);

??? ?unregister_chrdev_region(dev_num, 1);

?? ?init_flag = 0;

?? ?return PTR_ERR(mydrv_class);

device_c_error:

?? ?printk("device_create failed\n");

?? ?cdev_del(&mydrv_cdev);

??? ?unregister_chrdev_region(dev_num, 1);

?? ?class_destroy(mydrv_class);

?? ?init_flag = 0;

?? ?return PTR_ERR(mydrv_device);

//------------------ 請(qǐng)?jiān)诖颂砑幽腻e(cuò)誤處理內(nèi)容 ----------------//

mydrv_error:

?? ?printk("mydrv drive close...\n");

?? ?add_code_flag = 0;

?? ?return -1;

//-------------------- ? ? ? ? ?END ? ? ? ? -------------------//?

init_success:

?? ?printk("mydrv init success!\n");

?? ?return 0;

}

/*======================================================================

//exit

======================================================================*/

static __exit void mydrv_exit(void)

{

?? ?printk("mydrv drive exit...\n");?? ?

?? ?if(add_code_flag == 1)

??? ?{ ??

? ? ? ? ? ?//---------- ? 請(qǐng)?jiān)谶@里釋放您的程序占有的資源 ? ---------//

?? ? ? ?printk("free your resources...\n");?? ? ? ? ? ? ? ? ??

?? ? ?? ? //iounmap(GPIOMODE);

?? ??? ? iounmap(GPIO11_DIR);

?? ??? ? iounmap(GPIO11_SETDATA);

?? ??? ? iounmap(GPIO11_RESETDATA);

?? ? ? ?printk("free finish\n");?? ??? ? ? ? ? ? ? ? ??

?? ? ? ?//---------------------- ? ? END ? ? ?-------------------//

?? ?}?? ??? ??? ??? ??? ? ? ? ? ? ? ?

?? ?if(init_flag == 1)

?? ?{

?? ??? ?//釋放初始化使用到的資源;

?? ??? ?cdev_del(&mydrv_cdev);

??? ??? ?unregister_chrdev_region(dev_num, 1);

?? ??? ?device_unregister(mydrv_device);

?? ??? ?class_destroy(mydrv_class);

?? ?}

}

/**************** module operations**********************/

//module loading

module_init(mydrv_init);

module_exit(mydrv_exit);

//some infomation

MODULE_LICENSE("GPL v2");

MODULE_AUTHOR("from Jafy");

MODULE_DESCRIPTION("mydrv drive");

/********************* ?The End ***************************/


make menuconfig 下kernel 選擇Other ,選擇mydrv

保存锹雏,

make? package/kernel/mydrv/compile V=s

或者直接

make -j1 V=s 編譯巴比,然后把mydrv.ko 文件copy到開(kāi)發(fā)板/tmp目錄下,運(yùn)行

insmod mydrv.ko?

顯示驅(qū)動(dòng)注冊(cè)成功礁遵,類(lèi)注冊(cè)成功

可以在/dev 以及/sys/class 目錄下查看

————————————————

版權(quán)聲明:本文為CSDN博主「forAllforMe」的原創(chuàng)文章轻绞,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明佣耐。

原文鏈接:https://blog.csdn.net/cym_anhui/article/details/87915841

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末政勃,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子兼砖,更是在濱河造成了極大的恐慌奸远,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,002評(píng)論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件讽挟,死亡現(xiàn)場(chǎng)離奇詭異懒叛,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)耽梅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門(mén)薛窥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人眼姐,你說(shuō)我怎么就攤上這事诅迷。” “怎么了妥凳?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,787評(píng)論 0 365
  • 文/不壞的土叔 我叫張陵竟贯,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我逝钥,道長(zhǎng)屑那,這世上最難降的妖魔是什么拱镐? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,237評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮持际,結(jié)果婚禮上沃琅,老公的妹妹穿的比我還像新娘。我一直安慰自己蜘欲,他們只是感情好益眉,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,237評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著姥份,像睡著了一般郭脂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上澈歉,一...
    開(kāi)封第一講書(shū)人閱讀 52,821評(píng)論 1 314
  • 那天展鸡,我揣著相機(jī)與錄音,去河邊找鬼埃难。 笑死莹弊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的涡尘。 我是一名探鬼主播忍弛,決...
    沈念sama閱讀 41,236評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼考抄!你這毒婦竟也來(lái)了细疚?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,196評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤川梅,失蹤者是張志新(化名)和其女友劉穎惠昔,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體挑势,經(jīng)...
    沈念sama閱讀 46,716評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,794評(píng)論 3 343
  • 正文 我和宋清朗相戀三年啦鸣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了潮饱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,928評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诫给,死狀恐怖香拉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情中狂,我是刑警寧澤凫碌,帶...
    沈念sama閱讀 36,583評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站胃榕,受9級(jí)特大地震影響盛险,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,264評(píng)論 3 336
  • 文/蒙蒙 一苦掘、第九天 我趴在偏房一處隱蔽的房頂上張望换帜。 院中可真熱鬧,春花似錦鹤啡、人聲如沸惯驼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,755評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)祟牲。三九已至,卻和暖如春抖部,著一層夾襖步出監(jiān)牢的瞬間说贝,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,869評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工您朽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留狂丝,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,378評(píng)論 3 379
  • 正文 我出身青樓哗总,卻偏偏與公主長(zhǎng)得像几颜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子讯屈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,937評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容