国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

嵌入式Linux驅(qū)動開發(fā) 02:將驅(qū)動程序添加到內(nèi)核中

這篇具有很好參考價值的文章主要介紹了嵌入式Linux驅(qū)動開發(fā) 02:將驅(qū)動程序添加到內(nèi)核中。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目的

在上一篇文章 《嵌入式Linux驅(qū)動開發(fā) 01:基礎(chǔ)開發(fā)與使用》 中我們已經(jīng)實現(xiàn)了最基礎(chǔ)的驅(qū)動功能。在那篇文章中我們的驅(qū)動代碼是獨立于內(nèi)核代碼存放的,并且我們的驅(qū)動編譯后也是一個獨立的模塊。在實際使用中將驅(qū)動代碼放在內(nèi)核代碼中,并將驅(qū)動編譯到內(nèi)核中也是比較常見的選擇,這篇文章將此進行介紹。

這篇文章中內(nèi)容均在下面的開發(fā)板上進行測試:
《新唐NUC980使用記錄:自制開發(fā)板(基于NUC980DK61YC)》

這篇文章主要是在下面文章基礎(chǔ)上進行的:
《新唐NUC980使用記錄:訪問以太網(wǎng)(LAN8720A) & 啟用SSH》

基礎(chǔ)說明

將驅(qū)動程序添加到內(nèi)核中可以分為兩層含義來理解:

  1. 將驅(qū)動程序源碼等放到 Linux Kernel 源碼目錄下
    Linux Kernel 源碼中通常將驅(qū)動放到 drivers/ 下,本文中也將驅(qū)動源碼放到這個目錄下;
  2. 在 Linux Kernel 配置管理工具中統(tǒng)一管理與編譯
    這條主要指可以在 menuconfig 中進行配置管理來選擇編譯(這里先不討論使用設(shè)備樹的情況);
    menuconfig 界面中各個菜單和選項都是由 Kconfig 文件定義的,所以我們需要修改和編寫相關(guān)文件;
    menuconfig 中配置最終改變的是 make 時 Makefile 文件中各個變量,我們的自己的驅(qū)動也需要 Makefile 文件來指定編譯規(guī)則,并結(jié)合 Kconfig 文件中定義的變量來控制編譯過程;

添加到內(nèi)核中

本文中演示中涉及目錄與文件結(jié)構(gòu)組織如下:
嵌入式Linux驅(qū)動開發(fā) 02:將驅(qū)動程序添加到內(nèi)核中
其中 char_dev 就是本文中要添加的驅(qū)動。 user/ 目錄用于統(tǒng)一存放自己編寫的驅(qū)動,如果沒有這個需求這一層可以去掉,這樣結(jié)構(gòu)上會更簡單些,當(dāng)然推薦還是留著。各目錄下的 Kconfig 是一層層應(yīng)用的, Makefile 同理。

進入源碼目錄并建立相關(guān)目錄和文件:

cd ~/nuc980-sdk/NUC980-linux-4.4.y/

mkdir -p drivers/user
touch drivers/user/Kconfig
touch drivers/user/Makefile

mkdir -p drivers/user/char_dev
touch drivers/user/char_dev/char_dev.c
touch drivers/user/char_dev/Kconfig
touch drivers/user/char_dev/Makefile

Kconfig

首先修改drivers目錄下Kconfig文件:

gedit drivers/Kconfig

在其中添加下面一行,用來引用drivers/user目錄下的Kconfig文件:

source "drivers/user/Kconfig"

接著編輯drivers/user目錄下的Kconfig文件:

gedit drivers/user/Kconfig

寫入下面內(nèi)容,用來引用drivers/user/char_dev目錄下的Kconfig文件:

menu "User drivers"

source "drivers/user/char_dev/Kconfig"

endmenu

最后編輯drivers/user/char_dev目錄下的Kconfig文件:

gedit drivers/user/char_dev/Kconfig

寫入下面內(nèi)容:

config USER_CHAR_DEV
	tristate "char_dev"
	default n
	help
	char_dev driver test.

上面內(nèi)容中 config USER_CHAR_DEV 表示設(shè)置一個可配置的變量,名稱為 USER_CHAR_DEV (保存后實際的變量名會在頭部添加 CONFIG_CONFIG_USER_CHAR_DEV ,這個變量可以在Makefile中使用)。 tristate 表示該變量可取值為 n/y/m ,后面的字符串為該條目在 menuconfig 中顯示的文本。 default n 表示該變量默認值。 help 表示其下面的內(nèi)容是可在 menuconfig 中查看幫助信息。

經(jīng)過上面處理后就可以在 menuconfig 中看到相關(guān)選項并進行操作了:
嵌入式Linux驅(qū)動開發(fā) 02:將驅(qū)動程序添加到內(nèi)核中

Makefile

首先修改drivers目錄下Makefile文件:

gedit drivers/Makefile

在其中添加下面一行,這樣編譯時會進入drivers/user目錄下:

obj-y				+= user/

接著編輯drivers/user目錄下的Makefile文件:

gedit drivers/user/Makefile

寫入下面內(nèi)容,這樣編譯時會進入drivers/user/char_dev目錄下:

obj-y				+= char_dev/

最后編輯drivers/user/char_dev目錄下的Makefile文件:

gedit drivers/user/char_dev/Makefile

寫入下面內(nèi)容:

obj-$(CONFIG_USER_CHAR_DEV) += char_dev.o

上面就是最終編譯驅(qū)動程序過程了,這里的 CONFIG_USER_CHAR_DEV 變量就是由前面配置來產(chǎn)生的。根據(jù)變量的值,其最終可能產(chǎn)生 obj-nobj-y 、 obj-m 幾個結(jié)果,這幾個是 Linux Kernel 源碼總的Makefile中定義的變量,添加到 obj-y 的內(nèi)容會編譯到內(nèi)核中,添加到 obj-m 的內(nèi)容會編譯成單獨的模塊。

驅(qū)動程序

最后編輯下進行測試用的驅(qū)動程序:

gedit drivers/user/char_dev/char_dev.c

直接使用上一篇文章的程序即可:

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/device.h>

static int major = 0;
static const char *char_dev_name = "char_dev";
static struct class *char_dev_class;
static struct device *char_dev_device;

static char dev_buf[4096];

#define MIN(a, b) ((a) < (b) ? (a) : (b))

static int char_dev_open(struct inode *node, struct file *file)
{
	return 0;
}

static int char_dev_close(struct inode *node, struct file *file)
{
	return 0;
}

static ssize_t char_dev_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	int ret;
	ret = copy_to_user(buf, dev_buf, MIN(size, 4096)); // 從內(nèi)核空間拷貝數(shù)據(jù)到用戶空間
	return ret;
}

static ssize_t char_dev_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
	int ret;
	ret = copy_from_user(dev_buf, buf, MIN(size, 4096)); // 從用戶空間拷貝數(shù)據(jù)到內(nèi)核空間
	return ret;
}

static const struct file_operations char_dev_fops = {
	.owner = THIS_MODULE,
	.open = char_dev_open,
	.release = char_dev_close,
	.read = char_dev_read,
	.write = char_dev_write,
};

static int __init char_dev_init(void)
{
	printk("modlog: func %s, line %d.\n", __FUNCTION__, __LINE__);
	major = register_chrdev(0, char_dev_name, &char_dev_fops); // 注冊字符設(shè)備,第一個參數(shù)0表示讓內(nèi)核自動分配主設(shè)備號

	char_dev_class = class_create(THIS_MODULE, "char_dev_class"); // 
	if (IS_ERR(char_dev_class))
	{
		unregister_chrdev(major, char_dev_name);
		return -1;
	}
	char_dev_device = device_create(char_dev_class, NULL, MKDEV(major, 0), NULL, char_dev_name); // 創(chuàng)建設(shè)備節(jié)點創(chuàng)建設(shè)備節(jié)點,成功后就會出現(xiàn)/dev/char_dev_name的設(shè)備文件
	if (IS_ERR(char_dev_device))
	{
		device_destroy(char_dev_class, MKDEV(major, 0));
		unregister_chrdev(major, char_dev_name);
		return -1;
	}

	return 0;
}

static void __exit char_dev_exit(void)
{
	printk("modlog: func %s, line %d.\n", __FUNCTION__, __LINE__);

	device_destroy(char_dev_class, MKDEV(major, 0)); // 銷毀設(shè)備節(jié)點,銷毀后/dev/下設(shè)備節(jié)點文件就會刪除
	class_destroy(char_dev_class);

	unregister_chrdev(major, char_dev_name); // 注銷字符設(shè)備
}

module_init(char_dev_init); // 模塊入口
module_exit(char_dev_exit); // 模塊出口

MODULE_LICENSE("GPL"); // 模塊許可

這個驅(qū)動程序在安裝和卸載時打印了一些消息,可以通過此判斷驅(qū)動程序是否工作。

編譯與測試

模塊方式

menuconfig 將控制驅(qū)動的選項選擇為模塊后進行編譯:

# make menuconfig
export PATH=$PATH:/home/nx/nuc980-sdk/arm_linux_4.8/bin
# 可以使用make整體編譯或使用make modules編譯單獨模塊
# make 
make modules

嵌入式Linux驅(qū)動開發(fā) 02:將驅(qū)動程序添加到內(nèi)核中
最后編譯生成的模塊默認在模塊源碼目錄下,可以拷貝到開發(fā)板中進行測試:

# scp drivers/user/char_dev/char_dev.ko root@192.168.31.142:/root/

嵌入式Linux驅(qū)動開發(fā) 02:將驅(qū)動程序添加到內(nèi)核中

編譯到內(nèi)核中

menuconfig 將控制驅(qū)動的選項選擇為y后進行編譯:

# make menuconfig
# export PATH=$PATH:/home/nx/nuc980-sdk/arm_linux_4.8/bin
make uImage

嵌入式Linux驅(qū)動開發(fā) 02:將驅(qū)動程序添加到內(nèi)核中

編譯完成后拷貝內(nèi)核文件到開發(fā)板boot分區(qū):

# 在開發(fā)板中掛載啟動分區(qū)
# mount /dev/mmcblk0p1 /mnt/

# 在虛擬機中拷貝編譯生成的內(nèi)核到開發(fā)板
# scp ../image/980uimage root@192.168.31.142:/mnt/

嵌入式Linux驅(qū)動開發(fā) 02:將驅(qū)動程序添加到內(nèi)核中
開發(fā)板重啟后可以看到驅(qū)動程序在內(nèi)核啟動時自動啟動了,可以看到打印的信息以及 /dev/ 下的設(shè)備文件。

總結(jié)

將驅(qū)動程序添加到內(nèi)核中還是比較簡單的,按照內(nèi)核源碼本身的組織方式來進行就行了。更多的示例可以參考內(nèi)核源碼 drivers/ 目錄下各個驅(qū)動。文章來源地址http://www.zghlxwxcb.cn/news/detail-408227.html

到了這里,關(guān)于嵌入式Linux驅(qū)動開發(fā) 02:將驅(qū)動程序添加到內(nèi)核中的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 嵌入式Linux驅(qū)動開發(fā)——常見框架梳理

    嵌入式Linux驅(qū)動開發(fā)——常見框架梳理

    本文主要介紹了Linux驅(qū)動開發(fā)中一些常用的驅(qū)動框架,platform、input、iic、spi等,硬件平臺使用的是正點原子的imx6ull開發(fā)板。 不管什么框架最后都是要追溯到配置IO的電氣屬性和復(fù)用功能 如果要使用外部中斷,設(shè)備樹節(jié)點中還需添加相關(guān)信息,什么邊沿觸發(fā) 1:module_init和mod

    2024年02月15日
    瀏覽(31)
  • 嵌入式Linux驅(qū)動開發(fā) 04:基于設(shè)備樹的驅(qū)動開發(fā)

    嵌入式Linux驅(qū)動開發(fā) 04:基于設(shè)備樹的驅(qū)動開發(fā)

    前面文章 《嵌入式Linux驅(qū)動開發(fā) 03:平臺(platform)總線驅(qū)動模型》 引入了資源和驅(qū)動分離的概念,這篇文章將在前面基礎(chǔ)上更進一步,引入設(shè)備樹的概念。 在平臺總線驅(qū)動模型中資源和驅(qū)動已經(jīng)從邏輯上和代碼組織上進行了分離,但每次調(diào)整資源還是會涉及到內(nèi)核,所以現(xiàn)

    2024年02月16日
    瀏覽(26)
  • 正點原子嵌入式linux驅(qū)動開發(fā)——Linux 網(wǎng)絡(luò)設(shè)備驅(qū)動

    正點原子嵌入式linux驅(qū)動開發(fā)——Linux 網(wǎng)絡(luò)設(shè)備驅(qū)動

    網(wǎng)絡(luò)驅(qū)動是linux里面驅(qū)動三巨頭之一 ,linux下的網(wǎng)絡(luò)功能非常強大,嵌入式linux中也常常用到網(wǎng)絡(luò)功能。前面已經(jīng)講過了字符設(shè)備驅(qū)動和塊設(shè)備驅(qū)動,本章就來學(xué)習(xí)一下linux里面的 網(wǎng)絡(luò)設(shè)備驅(qū)動 。 本次筆記中討論的都是有線網(wǎng)絡(luò)! 提起網(wǎng)絡(luò),一般想到的硬件就是“網(wǎng)卡”。在

    2024年01月17日
    瀏覽(24)
  • 【嵌入式Linux驅(qū)動】驅(qū)動開發(fā)調(diào)試相關(guān)的關(guān)系記錄

    【嵌入式Linux驅(qū)動】驅(qū)動開發(fā)調(diào)試相關(guān)的關(guān)系記錄

    https://www.processon.com/mindmap/64537772b546c76a2f37bd2f

    2024年02月02日
    瀏覽(25)
  • 嵌入式Linux驅(qū)動開發(fā)系列六:Makefile

    嵌入式Linux驅(qū)動開發(fā)系列六:Makefile

    Makefile是什么? gcc hello.c -o hello gcc aa.c bb.c cc.c dd.c ... make工具和Makefile make和Makefile是什么關(guān)系? make工具:找出修改過的文件,根據(jù)依賴關(guān)系,找出受影響的相關(guān)文件,最后按照規(guī)則單獨編譯這些文件。 Makefile文件:記錄依賴關(guān)系和編譯規(guī)則。 必須要學(xué)精Makefile嗎? 怎么學(xué)習(xí)Makefi

    2024年02月13日
    瀏覽(20)
  • 嵌入式Linux驅(qū)動開發(fā)(LCD屏幕專題)(一)

    嵌入式Linux驅(qū)動開發(fā)(LCD屏幕專題)(一)

    總的分辨率是 yres*xres。 以下三種方式表示顏色 每個屏幕都有一個內(nèi)存(framebuffer)如下圖,內(nèi)存中每塊數(shù)據(jù)對用屏幕上的一個像素點,設(shè)置好LCD后,只需把顏色數(shù)據(jù)寫入framebuffer即可。 Framebuffer驅(qū)動屬于字符設(shè)備驅(qū)動,我們先說字符設(shè)備驅(qū)動框架如下圖: 驅(qū)動主設(shè)備號 構(gòu)造

    2024年02月09日
    瀏覽(29)
  • 嵌入式Linux驅(qū)動開發(fā)(LCD屏幕專題)(三)

    嵌入式Linux驅(qū)動開發(fā)(LCD屏幕專題)(三)

    1. 硬件相關(guān)的操作 LCD驅(qū)動程序的核心就是: 分配fb_info 設(shè)置fb_info 注冊fb_info 硬件相關(guān)的設(shè)置 硬件相關(guān)的設(shè)置又可以分為3部分: 引腳設(shè)置 時鐘設(shè)置 LCD控制器設(shè)置 2. 在設(shè)備樹里指定LCD參數(shù) 3. 編程 3.1 從設(shè)備樹獲得參數(shù) 時序參數(shù)、引腳極性等信息,都被保存在一個display_timi

    2024年02月09日
    瀏覽(33)
  • 嵌入式linux驅(qū)動開發(fā)篇之設(shè)備樹

    嵌入式linux驅(qū)動開發(fā)篇之設(shè)備樹

    設(shè)備樹(Device Tree)是一種用于描述嵌入式系統(tǒng)硬件組件及其連接關(guān)系的數(shù)據(jù)結(jié)構(gòu)。它被廣泛用于嵌入式 Linux 系統(tǒng),尤其是針對使用多種不同架構(gòu)和平臺的嵌入式系統(tǒng)。它是一種與硬件描述相關(guān)的中間表示形式,將硬件信息抽象成一種可移植的格式,使得操作系統(tǒng)和引導(dǎo)加載

    2024年02月22日
    瀏覽(23)
  • 嵌入式Linux驅(qū)動開發(fā)系列五:Linux系統(tǒng)和HelloWorld

    嵌入式Linux驅(qū)動開發(fā)系列五:Linux系統(tǒng)和HelloWorld

    三個問題 了解Hello World程序的執(zhí)行過程有什么用? 編譯和執(zhí)行:Hello World程序的執(zhí)行分為兩個主要步驟:編譯和執(zhí)行。編譯器將源代碼轉(zhuǎn)換為可執(zhí)行文件,然后計算機執(zhí)行該文件并輸出相應(yīng)的結(jié)果。了解這個過程可以幫助我們理解如何將代碼轉(zhuǎn)化為可運行的程序。 語法和語義

    2024年02月13日
    瀏覽(24)
  • 嵌入式linux驅(qū)動開發(fā)之移遠4G模塊EC800驅(qū)動移植指南

    嵌入式linux驅(qū)動開發(fā)之移遠4G模塊EC800驅(qū)動移植指南

    回顧下移遠4G模塊移植過程, 還是蠻簡單的。一通百通,無論是其他4G模塊都是一樣的。這里記錄下過程,分享給有需要的人。環(huán)境使用正點原子的imax6ul開發(fā)板,板子默認支持中興和移遠EC20的驅(qū)動,這里要移植使用的是移遠4G模塊EC800。 imax6ul開發(fā)板 虛擬機(Ubuntu18.04) 交叉編譯

    2024年02月17日
    瀏覽(51)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包