linux下編寫I2C驅動與stm32通訊(一)

2021-08-13 14:56:50 字數 3000 閱讀 4342

由於i2c對時序的嚴格要求,而linux是乙個多工作業系統,在應用層無法滿足嚴格的時序要求,只得在驅動層做。

1.將暫存器做相應的巨集定義,包含相應的標頭檔案,定義使用者的資料結構體

[html]

view plain

copy

#include 

<

linux

/module.h

>

#include <

linux

/errno.h

>

#include <

linux

/miscdevice.h

>

#include <

linux

/fcntl.h

>

#include <

linux

/init.h

>

#include <

linux

/delay.h

>

#include <

linux

/proc_fs.h

>

#include <

linux

/workqueue.h

>

#include <

asm/uaccess.h

>

#include <

asm/system.h

>

#include <

asm/io.h

>

[html]

view plain

copy

typedef struct i2c_data_s  

i2c_data_s;  

[html]

view plain

copy

#define gpio_0_base 0x20180000  

#define scl                 (1 <

<

6)    /* gpio 4_6 */  

#define sda                 (1 <

<

7)    /* gpio 4_7 */  

#define gpio_i2c_scl_reg    io_address(gpio_0_base + 0x400)  

#define gpio_i2c_sda_reg    io_address(gpio_0_base + 0x200  

#define gpio_i2c_sclsda_reg   io_address(gpio_0_base + 0x600)<

strong

>

strong

>

2.按照linux miscdevice驅動開發的一般流程:定義相應的資料結構

[html]

view plain

copy

static struct file_operations 

gpioi2c_fops

= ;  

static struct miscdevice gpioi2c_dev

= ;  

3.編寫模組的入口函式(init)和出口函式(exit)

[csharp]

view plain

copy

static

int__init gpio_i2c_init(

void

)    

static

void

__exit gpio_i2c_exit(

void

)    

[csharp]

view plain

copy

module_init(gpio_i2c_init); 

//宣告入口函式,模組被insmod時會自動呼叫gpio_i2c_init

module_exit(gpio_i2c_exit); //宣告出口函式,模組被rmmod時會自動呼叫gpio_i2c_exit

4.編寫unlock_ioctl,open,close函式

[cpp]

view plain

copy

long

gpioi2c_ioctl(

struct

file *file, unsigned 

intcmd, unsigned 

long

arg)  

return

0;  

}  int

gpioi2c_open(

struct

inode * inode, 

struct

file * file)  

intgpioi2c_close(

struct

inode * inode, 

struct

file * file)    

至此,大概框架就搭好了,接下來就是按照i2c的時序要求編寫相應的**,在此就不全貼了,說說遇到的問題吧。

首先遇到的第乙個問題就是驅動編寫完成載入後,scl和sda的引腳均為低電平,而我在模組入口函式處將sda和scl均拉高了,通過在其中加printk語句,確認函式確實執行到了,但是就是沒有起作用,對照datasheet檢查了各種暫存器的位址和配置都沒有問題,後來通過示波器發現兩個引腳的電平都為0,但是不是很平穩,更像是乙個未被控制的引腳,類似於三態的感覺,於是懷疑方向控制暫存器配置不對,於是在gpio_i2c_init函式中將這個暫存器的值列印出來發現是對的。排除了其他的暫存器配置後,只剩下乙個管腳復用暫存器,由於復位後這個暫存器的值為0x00,即為gpio模式,就沒有對其進行配置。如下圖所示:

結果將這個暫存器的值列印出來發現是0x01,不是預設的gpio模式,於是在入口函式中重新配置該暫存器,i2c時序正常。 hi3518e這邊的工作算是完成了,接下來就是完成stm32的i2c從機配置和兩者之間的通訊協議。

I2C裝置驅動的編寫

前面我們說了如何i2c使用者模式驅動,這種驅動基於i2c子系統,但是他對於應用程式開發人員的要求較高,需要應用程式開發人員了解硬體的一些東西,比如時序,位址等等,而多數時候應用程式開發人員是按照操作檔案的方法操作裝置,所以我們更希望用一些更簡單的介面去訪問。也就是我們今天的內容 基於i2c子系統的字...

linux下的I2C驅動記錄

現在做的是rk平台的i2c驅動,不是說linux每個外設對應乙個裝置檔案嗎?可是找了一下一直沒找到,今天特別搞了一下。i2c裝置是註冊為platform平台驅動的。下面是我用adb命令檢視的 linux的裝置檔案不一定只在dev 這個目錄下面,像sys 目錄下面也會有一些裝置檔案的 mid下面的i2...

Linux驅動 I2C匯流排

這裡以rk3288為例子,使用的是linux4.14,根據裝置樹節點i2c 與rk3x i2c driver,match之後,就會呼叫對應的probe rk3x i2c probe 這裡主要就是註冊乙個adapt i2c add adapter 也就是i2c控制器,或者說是i2c主裝置,既然是主裝置...