linux i2c dev.h freq,I2C配置及調試流程

一、I2C配置

1.根據原理圖,查找相關的i2c引腳對應的GPIO值,以GPIO10作為I2C_SDA,GPIO11作為I2C_SCL為例。

ZmlsZTovLy9FOi8lRTclQUMlOTQlRTglQUUlQjAvcXFGODM1MURBOTc4NzlFOTc1MDFDMzRENTU5OEFFMTRGNS9kMjBjYzEzMjRhOTA0ZDA2YjEwNTIwNDY5NDI0YWFiMS9jbGlwYm9hcmQucG5n

2.根據MSM8937 DEVICE SPECIFICATION文檔,查找GPIO10與GPIO11對應的BLSP,以及檢查GPIO10與GPIO11是否可以作為I2C來使用。根據文檔,GPIO10對應BLSP3_1,GPIO11對應BLSP3_0。

3.根據80-nu767-1_h_linux_bam_low-speed_peripherals_configuration_and_debug_guide文件,查找I2C部分BLSP3_0與BLSP3_1對應內容,包括其物理地址、reg size、中斷號......

ZmlsZTovLy9FOi8lRTclQUMlOTQlRTglQUUlQjAvcXFGODM1MURBOTc4NzlFOTc1MDFDMzRENTU5OEFFMTRGNS9jN2EwNzk2MGE3MjM0MmJlYjQxOWQ4NDJhM2E5OTI1OC9jbGlwYm9hcmQucG5n

4.進入kernel/msm-3.18/arch/arm/boot/dts/qcom/路徑下修改msm8937-pinctrl.dtsi文件

GPIO配置如下:

i2c_3 {

i2c_3_active: i2c_3_active {

/* active state */

mux {

pins = "gpio10", "gpio11";

function = "blsp_i2c3";

};

config {

pins = "gpio10", "gpio11";

drive-strength = <2>;

bias-disable;

};

};

i2c_3_sleep: i2c_3_sleep {

/* suspended state */

mux {

pins = "gpio10", "gpio11";

function = "gpio";

};

config {

pins = "gpio10", "gpio11";

drive-strength = <2>;

bias-disable;

};

};

};

ZmlsZTovLy9FOi8lRTclQUMlOTQlRTglQUUlQjAvcXFGODM1MURBOTc4NzlFOTc1MDFDMzRENTU5OEFFMTRGNS8zMzEyYzEzZTQyODc0MmI1YjA1MDIyOTE2YjA2MjYzNi9jbGlwYm9hcmQucG5n

5.進入kernel/msm-3.18/arch/arm/boot/dts/qcom/路徑下修改msm8937.dtsi文件

添加一個新的設備樹節點

ZmlsZTovLy9FOi8lRTclQUMlOTQlRTglQUUlQjAvcXFGODM1MURBOTc4NzlFOTc1MDFDMzRENTU5OEFFMTRGNS9jNTEzMGQ1ZmM4MDE0MmU5YjIxMDdkM2ZjMTJjNDYzNC9jbGlwYm9hcmQucG5n

(1)添加i2c_3

aliases {

smd1 = &smdtty_apps_fm;

smd2 = &smdtty_apps_riva_bt_acl;

smd3 = &smdtty_apps_riva_bt_cmd;

smd4 = &smdtty_mbalbridge;

smd5 = &smdtty_apps_riva_ant_cmd;

smd6 = &smdtty_apps_riva_ant_data;

smd7 = &smdtty_data1;

smd8 = &smdtty_data4;

smd11 = &smdtty_data11;

smd21 = &smdtty_data21;

smd36 = &smdtty_loopback;

spi3 = &spi_3;

i2c2 = &i2c_2;

i2c5 = &i2c_5;

i2c3 = &i2c_3;

sdhc1 = &sdhc_1; /* SDC1 eMMC slot */

sdhc2 = &sdhc_2; /* SDC2 for SD card */

};

(2)配置i2c_3

i2c_3: i2c@78b7000 { /* BLSP1 QUP3 */

compatible = "qcom,i2c-msm-v2";

#address-cells = <1>;

#size-cells = <0>;

reg-names = "qup_phys_addr";

reg = <0x78b7000 0x600>;

interrupt-names = "qup_irq";

interrupts = <0 97 0>;

qcom,clk-freq-out = <400000>;

qcom,clk-freq-in  = <19200000>;

clock-names = "iface_clk", "core_clk";

clocks = ,

;

pinctrl-names = "i2c_active", "i2c_sleep";

pinctrl-0 = ;

pinctrl-1 = ;

qcom,noise-rjct-scl = <0>;

qcom,noise-rjct-sda = <0>;

qcom,master-id = <86>;

dmas = ,

;

dma-names = "tx", "rx";

status = "okey";

};

6.進入kernel/msm-3.18/drivers/clk/msm路徑下修改clock-gcc-8952.c文件

添加時鍾節點如下圖所示:

static struct rcg_clk blsp1_qup1_i2c_apps_clk_src = {

.cmd_rcgr_reg = BLSP1_QUP1_I2C_APPS_CMD_RCGR,

.set_rate = set_rate_hid,

.freq_tbl = ftbl_gcc_blsp1_2_qup1_4_i2c_apps_clk,

.current_freq = &rcg_dummy_freq,

.base = &virt_bases[GCC_BASE],

.c = {

.dbg_name = "blsp1_qup1_i2c_apps_clk_src",

.ops = &clk_ops_rcg,

VDD_DIG_FMAX_MAP1(LOWER, 50000000),

CLK_INIT(blsp1_qup1_i2c_apps_clk_src.c),

},

};

ZmlsZTovLy9FOi8lRTclQUMlOTQlRTglQUUlQjAvcXFGODM1MURBOTc4NzlFOTc1MDFDMzRENTU5OEFFMTRGNS83ZWE0ODI4NWQwODA0YWJlYWIzYTkwOGM4MjVmOTM1Mi9jbGlwYm9hcmQucG5n

二、I2C BUS驗證

配置好I2C后,我們需保證I2C BUS被注冊

驗證過程如下:

adb shell //-------> Get adb shell

cd /dev/

ls i2c* //--------> to list all the i2c buses

如果顯示i2c-3,則表示I2C BUS已被注冊

三、I2C調試檢查

1、檢查I2C配置的相關內容,是否存在錯誤,或者漏配。

2、確保SDA和SCL所配置的GPIO沒有被配置,否則會硬件配置出問題或者GPIO設置無效。

3、若I2C配置無誤后,檢查相關硬件問題

使用萬用表測量I2C_SDA以及I2C_SCL的供電電壓,如果與原理圖中所示供電電壓相差無幾,則表示I2C供電電壓沒有問題。反之,則代表供電電壓存在問題。

4、添加從設備

(1)、 通過設備樹來注冊一個從設備

如果I2C總線正常工作,我們就可以創建一個從設備驅動程序並注冊到i2c總線上

我們使用st1663i觸摸屏的驅動注冊作為范例,引用文件:

kernel/drivers/input/touchscreen/st1663i/sitronix_i2c_touch.c.c

(2)、創建一個設備樹節點

文件修改:

/kernel/arch/arm/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dtsi

添加一個新的設備樹節點:

ZmlsZTovLy9FOi8lRTclQUMlOTQlRTglQUUlQjAvcXFGODM1MURBOTc4NzlFOTc1MDFDMzRENTU5OEFFMTRGNS84NWY3YWNlMDcwNGI0NjM5OGVjZTRiMWIyN2JiYTk2OS9jbGlwYm9hcmQucG5n

i2c@78b7000 {

status = "ok";

st1663i@70 {

compatible = "sitronix-tp";

reg = <0x70>;

interrupt-parent = ;

interrupts = <65 0x00>;

reset-gpio = ;

irq-gpio = ;

/*avdd-supply = ;*/

vdd-supply = ;

vcc_i2c-supply = ;

/* pins used by touchscreen */

pinctrl-names = "pmx_ts_active",

"pmx_ts_suspend",

"pmx_ts_release";

pinctrl-0 = ;

pinctrl-1 = ;

pinctrl-2 = ;

st1663i,i2c-pull-up;

st1663i,no-force-update;

st1663i,num_max_touches = <10>;

st1663i,panel-coords = <0 0 480 800>;

st1663i,display-coords = <0 0 480 800>;

st1663i,button-map= <139 172 158>;

st1663i,have-touch-key;

st1663i,driver-send-cfg;

};

};

(3)、編譯完成后,利用示波器測量I2C_SDA以及I2C_SCL波形

測試流程如下

adb root

adb remount

adb push i2c_test system/bin

adb shell

cd system/bin

chmod 777 i2c_test

./i2c_test /dev/i2c-3 0xaddr(從設備物理地址) 0(讀) 0xaddr(寄存器地址)

如果I2C沒有問題,所示I2C_SDA波形應為以下形式

I2C start > 0xE0 (write of 0x70) > 0x1 (reg offset ) > I2C stop > delay > I2C start > 0xE1 (read of 0x70) > > 8 bytes > I2C stop

以下是基于HAL库编写的STM32F103芯片I2C通信程序的.c和.h文件示例: .i2c.h文件 ``` #ifndef __I2C_H #define __I2C_H #ifdef __cplusplus extern "C" { #endif #include "stm32f1xx_hal.h" #define I2C_TIMEOUT 0xFFFF void I2C_Init(I2C_HandleTypeDef *hi2c); HAL_StatusTypeDef I2C_Write(I2C_HandleTypeDef *hi2c, uint8_t dev_addr, uint8_t *data, uint16_t size); HAL_StatusTypeDef I2C_Read(I2C_HandleTypeDef *hi2c, uint8_t dev_addr, uint8_t *data, uint16_t size); #ifdef __cplusplus } #endif #endif /* __I2C_H */ ``` .i2c.c文件 ``` #include "i2c.h" /* I2C initialization function */ void I2C_Init(I2C_HandleTypeDef *hi2c) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* Enable I2C GPIO clocks */ __HAL_RCC_GPIOB_CLK_ENABLE(); /* Configure I2C GPIO pins */ GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* Enable I2C clock */ __HAL_RCC_I2C1_CLK_ENABLE(); /* Configure I2C */ hi2c->Instance = I2C1; hi2c->Init.ClockSpeed = 100000; /* I2C clock frequency */ hi2c->Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c->Init.OwnAddress1 = 0; hi2c->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c->Init.OwnAddress2 = 0; hi2c->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; HAL_I2C_Init(hi2c); } /* I2C write function */ HAL_StatusTypeDef I2C_Write(I2C_HandleTypeDef *hi2c, uint8_t dev_addr, uint8_t *data, uint16_t size) { HAL_StatusTypeDef status; /* Wait until the bus is ready */ while (HAL_I2C_GetState(hi2c) != HAL_I2C_STATE_READY); /* Send device address with write command */ status = HAL_I2C_Master_Transmit(hi2c, dev_addr << 1, data, size, I2C_TIMEOUT); /* Return status */ return status; } /* I2C read function */ HAL_StatusTypeDef I2C_Read(I2C_HandleTypeDef *hi2c, uint8_t dev_addr, uint8_t *data, uint16_t size) { HAL_StatusTypeDef status; /* Wait until the bus is ready */ while (HAL_I2C_GetState(hi2c) != HAL_I2C_STATE_READY); /* Send device address with read command */ status = HAL_I2C_Master_Receive(hi2c, (dev_addr << 1) | 1, data, size, I2C_TIMEOUT); /* Return status */ return status; } ``` 在主函数中,首先需要初始化I2C: ``` I2C_HandleTypeDef hi2c1; int main(void) { /* Initialize HAL Library */ HAL_Init(); /* Initialize I2C */ I2C_Init(&hi2c1); /* ... */ } ``` 之后,可以使用I2C_Write和I2C_Read函数向I2C设备写入和读取数据: ``` #define I2C_DEVICE_ADDR 0x50 uint8_t data[2] = {0xAA, 0x55}; /* Write data */ if (I2C_Write(&hi2c1, I2C_DEVICE_ADDR, data, 2) == HAL_OK) { /* ... */ } /* Read data */ if (I2C_Read(&hi2c1, I2C_DEVICE_ADDR, data, 2) == HAL_OK) { /* ... */ } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值