0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

嵌入式Linux的驅(qū)動(dòng)編寫入門資料詳細(xì)說(shuō)明

Wildesbeast ? 來(lái)源:今日頭條 ? 作者:TopSemic ? 2020-02-20 15:06 ? 次閱讀

1.引言

很早之前就有網(wǎng)友建議寫一篇關(guān)于Linux驅(qū)動(dòng)的文章。之所以拖到現(xiàn)在才寫,原因之一是我之前沒有在工作中遇到需要自己手動(dòng)去寫驅(qū)動(dòng)的需求,主要是現(xiàn)在Linux內(nèi)核驅(qū)動(dòng)的支持已經(jīng)比較完善了,另外一個(gè)原因是自己水平實(shí)在有限,不敢寫驅(qū)動(dòng)這個(gè)話題,Linux驅(qū)動(dòng)里涉及到的東西太多了,很多年前專門買過驅(qū)動(dòng)相關(guān)的書籍,厚厚的,看的云里霧里。借此機(jī)會(huì),在這里給大家做個(gè)非常非常入門級(jí)的介紹,希望對(duì)大家有所幫助。

2.環(huán)境介紹

2.1.硬件

網(wǎng)上的一個(gè)第三方做的NUC972開發(fā)板,這里會(huì)用到板子上的MPU6050傳感器芯片,相關(guān)部分原理圖如下:

2.2.軟件

1) Uboot不需要改動(dòng)

2) Kernel不需要改動(dòng)

3) Rootfs不需要重新編譯

3.最簡(jiǎn)單的驅(qū)動(dòng)例子

第1步:編寫hello.c

#include #include static int __init hello_init(void) { printk(KERN_INFO "module init success\n"); return 0;} static void __exit hello_exit(void) { printk(KERN_INFO "module exit success\n");} module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("wuya");MODULE_DESCRIPTION("driver example");

這是一個(gè)簡(jiǎn)單的內(nèi)核模塊程序,可以動(dòng)態(tài)加載和卸載。模塊加載的時(shí)候系統(tǒng)會(huì)打印module init success,模塊卸載的時(shí)候系統(tǒng)會(huì)打印module exit success。

開頭的兩個(gè)頭文件,init.h 定義了驅(qū)動(dòng)的初始化和退出相關(guān)的函數(shù),module.h 定義了內(nèi)核模塊相關(guān)的函數(shù)、變量及宏。然后module_init和module_exit是模組加載和卸載相關(guān)的兩個(gè)函數(shù),

第2步:編寫Makefile

obj-m := hello.oPWD := $(shell pwd)KDIR :=/home/topsemic/nuc972/kernel/NUC970_Linux_Kernel-master/all: $(MAKE) -C $(KDIR) M=$(PWD)clean: rm -rf *.o *.mod.c *.mod.o *.ko *.symvers *.order *.a

注意:KDIR 取決于你自己Linux內(nèi)核安裝的位置,一定要設(shè)置正確,否則編譯會(huì)報(bào)錯(cuò)。

第3步:編譯

將hello.c和Makefile放在同一路徑下進(jìn)行編譯,輸入make即可。編譯成功后,會(huì)在當(dāng)前路徑下生成hello.ko,這就是我們將要加載到內(nèi)核的模塊。

第4步:將生成的hello.ko放到板子上,然后登錄板子輸入:

insmod hello.ko

如果模塊加載成功的話,可以查看模塊加載情況,使用lsmod命令

并且可以查看內(nèi)核打印的消息,使用dmesg命令,

rmmod hello.ko,用來(lái)卸載模塊,使用dmesg命令可以看到相關(guān)輸出信息

4.MPU6050驅(qū)動(dòng)

本章以板子上的MPU6050 傳感器為例,來(lái)介紹驅(qū)動(dòng)的編寫。由于板子上使用的是PE10和PE11,它們不是真正的I2C引腳,所以這里我們使用GPIO來(lái)模擬I2C時(shí)序。編寫驅(qū)動(dòng)前,首先需要下載控制器件的datasheet,在官網(wǎng) 可以下載。

第1步:寫驅(qū)動(dòng)文件,我們這里在驅(qū)動(dòng)文件里放了三個(gè)文件,分別為mpu6050.c、mpu6050bsp.c和mpu6050bsp.h

其中mpu6050.c代碼如下:

#include"mpu6050bsp.h"int MPU6050_MAJOR = 0;int MPU6050_MINOR = 0;int NUMBER_OF_DEVICES = 2; struct class *my_class;struct cdev cdev;dev_t devno;/*************************************************************************************/ #define DRIVER_NAME "mpu6050"int mpu6050_open(struct inode *inode,struct file *filp){u8 reg;reg=InitMPU6050();printk("mpu6050:%d\n",reg);return nonseekable_open(inode,filp);}long mpu6050_ioctl(struct file *filp,unsigned int cmd,unsigned long arg){switch(cmd){default:return -2;}return 0;}int mpu6050_read(struct file *filp, char *buffer,size_t count, loff_t *ppos){mpu_get_data();return copy_to_user(buffer, mpu_data, 14);}int mpu6050_write(struct file *filp, char *buffer, size_t count, loff_t *ppos){return 0;}struct file_operations mpu6050_fops = {.owner = THIS_MODULE,.read = mpu6050_read,.write = mpu6050_write,.open = mpu6050_open,.unlocked_ioctl = mpu6050_ioctl,};/**************************************************************************************/static int __init mpu6050_init(void){ int result; devno = MKDEV(MPU6050_MAJOR, MPU6050_MINOR); if (MPU6050_MAJOR) result = register_chrdev_region(devno, 2, "mpu6050"); else { result = alloc_chrdev_region(&devno, 0, 2, "mpu6050"); MPU6050_MAJOR = MAJOR(devno); } printk("MAJOR IS %d\n",MPU6050_MAJOR); my_class = class_create(THIS_MODULE,"mpu6050_class"); //類名為 if(IS_ERR(my_class)) { printk("Err: failed in creating class.\n"); return -1; } device_create(my_class,NULL,devno,NULL,"mpu6050"); //設(shè)備名為mpu6050 if (result<0) { printk (KERN_WARNING "hello: can't get major number %d\n", MPU6050_MAJOR); return result; } cdev_init(&cdev, &mpu6050_fops); cdev.owner = THIS_MODULE; cdev_add(&cdev, devno, NUMBER_OF_DEVICES); printk (KERN_INFO "mpu6050 driver Registered\n"); return 0;} static void __exit mpu6050_exit (void){ cdev_del (&cdev); device_destroy(my_class, devno); //delete device node under /dev//必須先刪除設(shè)備,再刪除class類 class_destroy(my_class); //delete class created by us unregister_chrdev_region (devno,NUMBER_OF_DEVICES); printk (KERN_INFO "char driver cleaned up\n");} module_init (mpu6050_init );module_exit (mpu6050_exit ); MODULE_LICENSE ("GPL");

上述代碼整體結(jié)構(gòu)和第3章介紹的hello.c類似,不過為了支持對(duì)字符設(shè)備的操作,多了open/write/read的幾個(gè)函數(shù)實(shí)現(xiàn)。

mpu6050bsp.c由于內(nèi)容較多,不把代碼貼到這里了,大家一看就明白了,它就是用gpio來(lái)模擬i2c功能,實(shí)現(xiàn)寄存器操作功能。mpu6050bsp.h主要是相關(guān)寄存器定義。

第2步:編譯,然后把ko文件放到板子,insmod mpu6050d.ko 。模塊如果加載成功,在/dev目錄下可以看到mpu6050的設(shè)備名出現(xiàn)。

第3步:寫個(gè)應(yīng)用程序mpu6050app.c,

#include #include #include #include short x_accel, y_accel, z_accel;short x_gyro, y_gyro, z_gyro;short temp;int main(){ char buffer[128]; short *value; int in, out; int nread; in = open("/dev/mpu6050", O_RDONLY); if (!in) { printf("ERROR: %d, Open /dev/mpu6050 failed.\n", -1); return -1; } nread = read(in, buffer, 12); close(in); if (nread < 0) { printf("ERROR: %d, A read error has occurred\n", nread); return -1; } value = (short*)buffer; x_accel = *(value); y_accel = *(value + 1); z_accel = *(value + 2); temp = *(value + 3); x_gyro = *(value + 4); y_gyro = *(value + 5); z_gyro = *(value + 6); printf("x accel is: %d \n", x_accel); printf("y accel is: %d \n", y_accel); printf("z accel is: %d \n", z_accel); printf("x gyro is: %d \n", x_gyro); printf("y gyro is: %d \n", y_gyro); printf("z gyro is: %d \n", z_gyro);printf("temperature is: %d \n", temp); exit(0);}

編譯arm-linux-gcc mpu6050app.c -o mpu6050app

第4步:將板子水平擺放朝上,運(yùn)行例子結(jié)果如下,

我們來(lái)計(jì)算下z軸加速度和溫度的實(shí)際數(shù)值。

因?yàn)轵?qū)動(dòng)里AFS_SEL寄存器設(shè)置的值是2,所以對(duì)應(yīng)量程8g。數(shù)字-32767對(duì)應(yīng)-8g,32767對(duì)應(yīng)8g。把32767除以8,就可以得到4096,即1g對(duì)應(yīng)的數(shù)值。把從加速度計(jì)讀出的數(shù)字除以4096,就可以換算成加速度的數(shù)值。上面我們從加速度計(jì)z軸讀到的數(shù)字是3723,那么對(duì)應(yīng)的加速度數(shù)據(jù)是3723/4096≈0.91g。g為加速度的單位,重力加速度定義為1g, 等于9.8米每平方秒。由于桌上不是很平,加上傳感器自身誤差,所以這個(gè)值是合理的。

再看看溫度計(jì)算,從手冊(cè)中可以看到如下的計(jì)算公式

上述的-2352計(jì)算后得到溫度為29.6℃,注意這個(gè)溫度不是環(huán)境溫度,是芯片內(nèi)部的溫度,環(huán)境溫度會(huì)比這個(gè)值略低。

由于我是在北京,冬天屋里有暖氣,所以這個(gè)值也是合理的。

5.結(jié)束語(yǔ)

本期給大家介紹關(guān)于Linux驅(qū)動(dòng)最簡(jiǎn)單的使用,可以看到驅(qū)動(dòng)開發(fā)和應(yīng)用開發(fā)還是有很大的差異,驅(qū)動(dòng)需要關(guān)注底層,需要深入的閱讀芯片的數(shù)據(jù)手冊(cè),同時(shí)也得具備內(nèi)核的相關(guān)知識(shí)。市場(chǎng)上Linux應(yīng)用開發(fā)人員相對(duì)更多,真正懂驅(qū)動(dòng)的人相對(duì)較少,大部分集中在芯片原廠公司。推薦大家在實(shí)際做產(chǎn)品時(shí)盡量選擇官方推薦的元器件,或者選擇可以提供Linux驅(qū)動(dòng)的元器件,以降低開發(fā)難度。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 傳感器
    +關(guān)注

    關(guān)注

    2551

    文章

    51106

    瀏覽量

    753652
  • 嵌入式
    +關(guān)注

    關(guān)注

    5082

    文章

    19126

    瀏覽量

    305293
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11304

    瀏覽量

    209535
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    詳細(xì)說(shuō)明如何配置嵌入式linux 的nfs開發(fā)環(huán)境

    對(duì)于嵌入式開發(fā)者而言開發(fā)效率非常重要,nfs的是嵌入式linux 開發(fā)的一個(gè)重要的組成部分,本部分內(nèi)容將詳細(xì)說(shuō)明如何配置嵌入式
    發(fā)表于 07-28 16:14 ?2345次閱讀

    嵌入式Linux設(shè)備驅(qū)動(dòng)開發(fā)

    嵌入式Linux設(shè)備驅(qū)動(dòng)開發(fā) Linux 設(shè)備驅(qū)動(dòng)的基本概念Linux 設(shè)備
    發(fā)表于 09-10 13:10 ?82次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b>開發(fā)

    嵌入式Linux嵌入式Linux開發(fā)環(huán)境說(shuō)明

    嵌入式Linux嵌入式Linux開發(fā)環(huán)境說(shuō)明
    發(fā)表于 03-28 09:49 ?30次下載

    嵌入式Linux系統(tǒng)的移植研究

    介紹嵌入式系統(tǒng)和嵌入式系統(tǒng)中的GUI , 詳細(xì)說(shuō)明三種常見的嵌入式GUI (Microwindows、MiniGUI 和QT)的設(shè)計(jì)結(jié)構(gòu)和使用上的優(yōu)缺點(diǎn), 描述Microwindows
    發(fā)表于 04-24 10:43 ?23次下載

    嵌入式linux 入門教材

    嵌入式linux 入門教材 1、什么是嵌入式Linux   嵌入式
    發(fā)表于 03-02 16:03 ?127次下載

    嵌入式linux開發(fā)詳細(xì)資料

    本文主要介紹了嵌入式linux開發(fā)詳細(xì)資料。
    發(fā)表于 06-05 08:00 ?3次下載

    嵌入式教程之Linux的基礎(chǔ)命令詳細(xì)資料說(shuō)明

    本文檔的主要內(nèi)容詳細(xì)介紹的是嵌入式教程之Linux的基礎(chǔ)命令詳細(xì)資料說(shuō)明主要內(nèi)容包括了:1.Linux
    發(fā)表于 12-06 17:31 ?8次下載
    <b class='flag-5'>嵌入式</b>教程之<b class='flag-5'>Linux</b>的基礎(chǔ)命令<b class='flag-5'>詳細(xì)資料</b><b class='flag-5'>說(shuō)明</b>

    如何吧Mysql數(shù)據(jù)庫(kù)移植到嵌入式Linux詳細(xì)資料說(shuō)明

    本文檔的主要內(nèi)容詳細(xì)介紹的是如何吧Mysql數(shù)據(jù)庫(kù)移植到嵌入式Linux詳細(xì)資料說(shuō)明。
    發(fā)表于 01-18 08:00 ?4次下載
    如何吧Mysql數(shù)據(jù)庫(kù)移植到<b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>的<b class='flag-5'>詳細(xì)資料</b><b class='flag-5'>說(shuō)明</b>

    如何吧SQLite移植到嵌入式Linux系統(tǒng)的詳細(xì)資料說(shuō)明

    本文檔的主要內(nèi)容詳細(xì)介紹的是如何吧SQLite移植到嵌入式Linux系統(tǒng)的詳細(xì)資料說(shuō)明。
    發(fā)表于 01-18 08:00 ?8次下載
    如何吧SQLite移植到<b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>系統(tǒng)的<b class='flag-5'>詳細(xì)資料</b><b class='flag-5'>說(shuō)明</b>

    使用嵌入式Linux設(shè)計(jì)的矩陣鍵盤程序和資料說(shuō)明

    本文檔的主要內(nèi)容詳細(xì)介紹的是使用嵌入式Linux設(shè)計(jì)的矩陣鍵盤程序和資料說(shuō)明。
    發(fā)表于 03-20 08:00 ?1次下載
    使用<b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>設(shè)計(jì)的矩陣鍵盤程序和<b class='flag-5'>資料</b><b class='flag-5'>說(shuō)明</b>

    2020年嵌入式汽車技術(shù)的重大變革詳細(xì)說(shuō)明

    電子發(fā)燒友網(wǎng)站提供《2020年嵌入式汽車技術(shù)的重大變革詳細(xì)說(shuō)明.pdf》資料免費(fèi)下載
    發(fā)表于 11-26 04:17 ?10次下載

    嵌入式LINUX的Qt開發(fā)入門教程

    嵌入式LINUX的Qt開發(fā)入門教程(最好的嵌入式開發(fā)板)-該文檔為嵌入式LINUX的Qt開發(fā)
    發(fā)表于 08-04 11:01 ?30次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>LINUX</b>的Qt開發(fā)<b class='flag-5'>入門</b>教程

    小白入門嵌入式Linux開發(fā)板,嵌入式linux驅(qū)動(dòng)如何學(xué)?小白入門必看

    嵌入式發(fā)展這么快,很多人都躋身在嵌入式行業(yè),對(duì)于新手小白來(lái)說(shuō),學(xué)習(xí)嵌入式還是會(huì)遇到一些問題,就比如說(shuō)嵌入式linux
    發(fā)表于 11-01 16:32 ?11次下載
    小白<b class='flag-5'>入門</b><b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>開發(fā)板,<b class='flag-5'>嵌入式</b><b class='flag-5'>linux</b><b class='flag-5'>驅(qū)動(dòng)</b>如何學(xué)?小白<b class='flag-5'>入門</b>必看

    嵌入式linux報(bào)警,嵌入式Linux下LED報(bào)警燈驅(qū)動(dòng)設(shè)計(jì)及編程.doc

    設(shè)計(jì)及編程一.實(shí)驗(yàn)?zāi)康睦斫?b class='flag-5'>驅(qū)動(dòng)本質(zhì),掌握嵌入式Linux系統(tǒng)下驅(qū)動(dòng)開發(fā)相關(guān)知識(shí),包括端口寄存器訪問、接口函數(shù)編寫、和文件系統(tǒng)掛接、注冊(cè)及相關(guān)
    發(fā)表于 11-01 17:21 ?6次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>linux</b>報(bào)警,<b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>下LED報(bào)警燈<b class='flag-5'>驅(qū)動(dòng)</b>設(shè)計(jì)及編程.doc

    視頻教程-嵌入式Linux系統(tǒng)基礎(chǔ)入門-Linux

    嵌入式Linux系統(tǒng)基礎(chǔ)入門 嵌入式開發(fā)工程師,有超過8年的
    發(fā)表于 11-02 14:21 ?14次下載
    視頻教程-<b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>系統(tǒng)基礎(chǔ)<b class='flag-5'>入門</b>-<b class='flag-5'>Linux</b>