上一篇介紹了虛擬字符設備的驅動,這篇就深入學習字符驅動的流程,看看字符驅動和應用層是怎么配合使用的!
1、備份原來的驅動

2、修改原來的驅動
在打印輸出時,[BSP]開頭表示驅動,[APP]開頭表示應用,Makefile不用修改;
chrdevbase.c
#include#include #include #include #include #include #define CHRDEVBASE_MAJOR 200 /* 主設備號 */ #define CHRDEVBASE_NAME "chrdevbase" /* 設備名 */ static char readbuf[100]; /* 讀緩沖區 */ static char writebuf[100]; /* 寫緩沖區 */ static char kerneldata[] = {"kernel data!"}; /* * @description : 打開設備 * @param - inode : 傳遞給驅動的inode * @param - filp : 設備文件,file結構體有個叫做private_data的成員變量 * 一般在open的時候將private_data指向設備結構體。 * @return : 0 成功;其他 失敗 */ static int chrdevbase_open(struct inode *inode, struct file *filp) { //printk("chrdevbase open! "); return 0; } /* * @description : 從設備讀取數據 * @param - filp : 要打開的設備文件(文件描述符) * @param - buf : 返回給用戶空間的數據緩沖區 * @param - cnt : 要讀取的數據長度 * @param - offt : 相對于文件首地址的偏移 * @return : 讀取的字節數,如果為負值,表示讀取失敗 */ static ssize_t chrdevbase_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt) { int retvalue = 0; /* 向用戶空間發送數據 */ memcpy(readbuf, kerneldata, sizeof(kerneldata)); retvalue = copy_to_user(buf, readbuf, cnt); if(retvalue == 0){ printk("[BSP]kernel senddata ok! "); }else{ printk("[BSP]kernel senddata failed! "); } //printk("chrdevbase read! "); return 0; } /* * @description : 向設備寫數據 * @param - filp : 設備文件,表示打開的文件描述符 * @param - buf : 要寫給設備寫入的數據 * @param - cnt : 要寫入的數據長度 * @param - offt : 相對于文件首地址的偏移 * @return : 寫入的字節數,如果為負值,表示寫入失敗 */ static ssize_t chrdevbase_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt) { int retvalue = 0; /* 接收用戶空間傳遞給內核的數據并且打印出來 */ retvalue = copy_from_user(writebuf, buf, cnt); if(retvalue == 0){ printk("[BSP]kernel recevdata:%s ", writebuf); }else{ printk("[BSP]kernel recevdata failed! "); } //printk("chrdevbase write! "); return 0; } /* * @description : 關閉/釋放設備 * @param - filp : 要關閉的設備文件(文件描述符) * @return : 0 成功;其他 失敗 */ static int chrdevbase_release(struct inode *inode, struct file *filp) { //printk("chrdevbase release! "); return 0; } /* * 設備操作函數結構體 */ static struct file_operations chrdevbase_fops = { .owner = THIS_MODULE, .open = chrdevbase_open, .read = chrdevbase_read, .write = chrdevbase_write, .release = chrdevbase_release, }; /* * @description : 驅動入口函數 * @param : 無 * @return : 0 成功;其他 失敗 */ static int __init chrdevbase_init(void) { int retvalue = 0; /* 注冊字符設備驅動 */ retvalue = register_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME, &chrdevbase_fops); if(retvalue < 0){ printk("[BSP]chrdevbase driver register failed "); } printk("[BSP]chrdevbase init! "); return 0; } /* * @description : 驅動出口函數 * @param : 無 * @return : 無 */ static void __exit chrdevbase_exit(void) { /* 注銷字符設備驅動 */ unregister_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME); printk("[BSP]chrdevbase exit! "); } /* * 將上面兩個函數指定為驅動的入口和出口函數 */ module_init(chrdevbase_init); module_exit(chrdevbase_exit); /* * LICENSE和作者信息 */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("zuozhongkai");
chrdevbaseApp.c
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
static char usrdata[] = {"usr data!"};
/*
* @description : main主程序
* @param - argc : argv數組元素個數
* @param - argv : 具體參數
* @return : 0 成功;其他 失敗
*/
int main(int argc, char *argv[])
{
int fd, retvalue;
char *filename;
char readbuf[100], writebuf[100];
if(argc != 3){
printf("[APP]Error Usage!
");
return -1;
}
filename = argv[1];
/* 打開驅動文件 */
fd = open(filename, O_RDWR);
if(fd < 0){
printf("[APP]Can't open file %s
", filename);
return -1;
}
if(atoi(argv[2]) == 1){ /* 從驅動文件讀取數據 */
retvalue = read(fd, readbuf, 50);
if(retvalue < 0){
printf("[APP]read file %s failed!
", filename);
}else{
/* 讀取成功,打印出讀取成功的數據 */
printf("[APP]read data:%s
",readbuf);
}
}
if(atoi(argv[2]) == 2){
/* 向設備驅動寫數據 */
memcpy(writebuf, usrdata, sizeof(usrdata));
retvalue = write(fd, writebuf, 50);
if(retvalue < 0){
printf("[APP]write file %s failed!
", filename);
}
}
/* 關閉設備 */
retvalue = close(fd);
if(retvalue < 0){
printf("[APP]Can't close file %s
", filename);
return -1;
}
return 0;
}
3、編譯驅動和應用

4、復制需要的文件到根文件系統中
將 chrdevbase.ko 和 chrdevbaseAPP 復制到 rootfs/lib/modules/4.1.15 目錄中:

5、啟動內核
在uboot界面輸入下面指令啟動系統,
tftp80800000zImage tftp 83000000 imx6ull-14x14-evk.dtb bootz 80800000 - 83000000
6、加載設備驅動
需要進入驅動文件目錄才能加載設備驅動;
//加載驅動 insmod chrdevbase.ko // 查看驅動 lsmod // 指令查看devices 信息 cat /proc/devices
效果如圖:

7、創建設備節點文件
輸入如下命令創建/dev/chrdevbase 這個設備節點文件:
mknod /dev/chrdevbase c 200 0
8、驗證讀寫
// 讀
./chrdevbaseApp /dev/chrdevbase 1
// 寫
./chrdevbaseApp /dev/chrdevbase 2
//可以使用下面這行輸出文件名稱,輸出/dev/chrdevbase
printf("filename:%s
",argv[1]);
//可以使用下面這行輸出參數,輸出1或者 2
printf("dat:%d
",atoi(argv[2]);
讀的流程:

寫的流程:

注意事項
下面這個函數的打印輸出會印象到應用層的輸出,看到應用層輸出異常就把這個函數的輸出給屏蔽就好;

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
字符
+關注
關注
0文章
237瀏覽量
26195 -
設備驅動
+關注
關注
0文章
71瀏覽量
11341
原文標題:i.MX6ULL|字符設備驅動流程深究
文章出處:【微信號:玩轉單片機,微信公眾號:玩轉單片機】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
熱點推薦
使用i.MX6ULL開發板進行Linux根文件系統的完善
上一篇推文講了怎么移植根文件系統,并在i.MX6ULL開發板中運行起來,但是會出現一些提示,現在來進行根文件的完善。
發表于 10-17 11:13
?1242次閱讀
如何在i.MX6ULL睡眠時停止刷新LCD?
為了更好的 EMC,我們需要在 i.MX6ULL 進入睡眠狀態時停止 LCD 刷新。
能否實現 ?
平臺: i.MX6ULL
系統: Linux
發表于 04-03 07:14
i.MX6ULL開發板硬件資源
迅為i.MX6ULL 終結者開發板硬件資源非常豐富,幾乎將 i.MX6ULL 芯片的所有資源都擴展引出到底板上了,底板提供了豐富的外設接口,開發板的尺寸是 190mm*125mm,充分考慮了人性化設計,整體顯得十分大。
發表于 12-29 06:18
初識 i.MX6ULL 寄存器
裸機開發_L1_匯編LED實驗0. 本節目標1. 硬件層電路2. 初識 i.MX6ULL 寄存器2.1 i.MX6ULL 時鐘控制寄存器2.2 i.MX6ULL IO復用寄存器2.3
發表于 12-20 07:13
I.MX6ULL無法枚舉USB2514是為什么?
你好目前,I.MX6ULL開發存在一些問題。其中之一是OTG USB2無法正常掛載USB2514,無法正確枚舉下游設備,只顯示設備id。usb設計要注意什么。
發表于 04-03 06:55
珠海明遠智睿科技聯合NXP強勢推出i.MX6ull核心板
接口,用于連接外圍設備,如WLAN、Bluetooth?、GPS、顯示器和攝像頭傳感器。?為了加速基于NXP i.MX6ULL及i.MX6UL芯片的產品設計,珠海明遠智睿科技聯合恩智浦推出了高質量
發表于 04-24 14:10
?870次閱讀
飛凌i.MX6ULL開發板的評測,再次進階擁有更高的性價比
處理器MCIMX6Y2開發設計,采用先進的ARMCortex-A7內核,運行速度高達800MHz。i.MX6ULL應用處理器包括一個集成的電源管理模塊,降低了外接電源的復雜性,并簡化了上電時序。 i.MX6ULL
發表于 10-27 11:55
?1883次閱讀
基于NXP i.MX6ULL處理器的FETMX6ULL-C核心板
“性價比高,功能接口豐富,資料齊全,穩定性強”這是許多用戶對飛凌FETMX6ULL-S核心板的評價。作為NXP公司一顆經典的MPU,i.MX6ULL的市場認可度無需多言。而作為NXP公司的金牌
發表于 04-11 15:05
?1542次閱讀
基于i.MX6ULL的掉電檢測設計與軟件測試
基于i.MX6ULL的掉電檢測設計與軟件測試基于i.MX6ULL平臺設計實現掉電檢測功能,首先選擇一路IO,利用IO電平變化觸發中斷,在編寫驅動時捕獲該路GPIO的中斷,然后在中斷響應函數中發
i.MX6ULL|字符設備驅動流程深究
評論