#夏日挑战赛#【FFH】BearPi_Micro南向开发I2C驱动代码深耕 原创 精华

X丶昕雪
发布于 2022-6-19 11:55
浏览
4收藏

#夏日挑战赛#【FFH】BearPi_Micro南向开发I2C驱动代码深耕
本文正在参加星光计划3.0–夏日挑战赛

I2C

@[toc]

I2C驱动结构概括

接口层将驱动封装起来,用户可直接调用接口层函数进行驱动的使用,用户便可不再需要配置I2C的具体设置
核心层是鸿蒙系统用于操作、控制、管理I2C设备
适配层则为鸿蒙系统用于兼容不同芯片设备,开发新芯片驱动时可以在此设置芯片的驱动相关底层数据
#夏日挑战赛#【FFH】BearPi_Micro南向开发I2C驱动代码深耕-鸿蒙开发者社区

I2C启动的系统结构

启动代码在i2c_if.c,所以使用前需要引用#include "i2c_if.h"

接口层

用户需要使用I2C时,只需要知道I2C控制器的序号,便可通过以下I2C控制器API驱动函数打开I2C

DevHandle I2cOpen(int16_t number);

其中参数number:I2C控制器序号

核心层

在此启动函数中调用到了核心层I2cCntlrGet(number);函数,最终调用到了static struct I2cCntlr *I2cManagerFindCntlr(int16_t number);
此层为核心层,是鸿蒙系统开启I2C的操作,开发时不需要关注这部分

static struct I2cCntlr *I2cManagerFindCntlr(int16_t number)
{
    struct I2cCntlr *cntlr = NULL;
    struct I2cManager *manager = g_i2cManager;
    //检查I2C控制器序号是否合法
    //检查I2C控制器
    //检查I2C锁控制器
    cntlr = manager->cntlrs[number];
    return cntlr;
}

适配层

想要使核心层正确打开芯片的I2C,就需要小熊派芯片的I2C一些重要数值传递给核心层,例如设备号、总线号,IO口位置,寄存器位置等
小熊派的I2C的私人配置数据都放在了i2c_config.hcs
(文件地址:bearpi-hm_micro_small\device\st\bearpi_hm_micro\liteos_a\hdf_config\i2c\i2c_config.hcs)

root {
    platform {
        i2c_config {
            match_attr = "st_stm32mp157_i2c"; /*需要和device_info.hcs中的deviceMatchAttr值一致
            使device_info.hsc可以正确调用私人配置数据*/

            template i2c_controller {
                bus = 1;    
                reg_pbase = 0x40012000; //物理基地址
                reg_size = 0x400;   //寄存器位宽
                timing = 0x10909CEC;
                own_address1 = 0;
                addressing_mode = 0x00000001;
                dual_address_mode = 0x00000000;
                own_address2 = 0;
                own_address_2_masks = 0x00;
                general_call_mode = 0x00000000;
                no_stretch_mode = 0x00000000;
            }

            controller_0x40012000 :: i2c_controller {
                bus = 1;    //i2c控制器序号,用于打开i2c
                reg_pbase = 0x40012000;
                /***********************/
                /* [port,pin]
                    <port> 0:GPIOA 1:GPIOB 3:GPIOC ......GPIOF便是5
                    <pin>  0:PIN0 1:PIN1 2:PIN2 ......
                */                    
                i2cClkIomux = [5, 14];   //PF14,SCL
                i2cDataIomux = [5, 15];  //PF15,SDA
                /***********************/
            }
            controller_0x40013000 :: i2c_controller {
                bus = 2;
                reg_pbase = 0x40013000;

                i2cClkIomux = [7, 4];   //PH4
                i2cDataIomux = [7, 5];  //PH5
            }
             controller_0x40015000 :: i2c_controller {
                bus = 5;
                reg_pbase = 0x40015000;

                i2cClkIomux = [0, 11];   //PA11
                i2cDataIomux = [0, 12];  //PA12
            }
        }
    }
}

通过查询小熊派的E53接口的原理图,可以知道E53接口上的I2C在GPIOF14和GPIOF15
#夏日挑战赛#【FFH】BearPi_Micro南向开发I2C驱动代码深耕-鸿蒙开发者社区
此处对应了小熊派私人配置中的物理基地址配置 i2cClkIomux = [5, 14]; i2cDataIomux = [5, 15];

I2C的结构体

I2cCntlr控制成员在定义驱动入口的对象初始化的时候,就需要被实例化。
调用核心层I2cCntlrAdd函数,使用芯片的私人配置实例化I2cCntlr。

I2cCntlr成员

struct I2cCntlr {
    struct OsalMutex lock;
    void *owner;
    int16_t busId;  
    void *priv;//存储设备属性
    const struct I2cMethod *ops;//I2cMethod的实例化对象的挂载
    const struct I2cLockMethod *lockOps;//I2cLockMethod的实例化对象的挂载
};

I2cCntlr成员I2cMethod和I2cLockMethod

struct I2cMethod {
int32_t (*transfer)(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count);
};
struct I2cLockMethod {//锁机制操作结构体
    int32_t (*lock)(struct I2cCntlr *cntlr);//加锁
    void (*unlock)(struct I2cCntlr *cntlr); //解锁
};

实例化I2cCntlr例子

在stm32mp1_i2c.c定义驱动入口的对象中Init实例化I2cCntlr
#夏日挑战赛#【FFH】BearPi_Micro南向开发I2C驱动代码深耕-鸿蒙开发者社区
Init函数中其中实例化自定义的结构体,实际上也是实例化了I2cCntlr。
#夏日挑战赛#【FFH】BearPi_Micro南向开发I2C驱动代码深耕-鸿蒙开发者社区

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-6-19 19:34:28修改
5
收藏 4
回复
举报
2条回复
按时间正序
/
按时间倒序
FFH杞人
FFH杞人

好,期待作者更多文章

回复
2022-6-19 19:38:59
FFH_magic_H
FFH_magic_H

大佬带带我🥺

回复
2022-6-19 22:01:23
回复
    相关推荐