6. nRF5x_BSP I2C 移植指南

作者[毛工]

6.1. 目标:使用RT-Thread标准化接口驱动nRF5x的I2C硬件

了解RT-Thread标准化接口 文档

通过示例整理外部接口

6.2. 了解接口封装 通过头文件

ENV 开启 RT_USING_I2C 添加了

#include "drivers/i2c.h"
#include "drivers/i2c_dev.h"

6.2.1. 了解nRF5x的I2C(TWI)驱动层

TWIME

先跑起来示例

examples\peripheral\twi_sensor 

drv_xxx : 历史遗漏层 文档 twi_xxx :被遗弃的外设驱动 主要是为了代码兼容而保留 twim_xxx :EasyDMA

EasyDMA和PPI

IO中断 -》 PPI -》 I2C read

传感器 带FiFo, I2C接口的 FIFO满了 会触发一个IO上升沿

如果没有PPI

接受到IO中断,CPU去触发I2C read 可能是DMA 读取完成再触发读取完成的中断

如果有PPI

接收到IO上升沿 产生了一个io event

PPI 接收到io event后 直接触发 i2c read tasks(固化 发送的内存的地址) 存到固定的位置

读取完成后 再触发read finsh event 这个时候才会有中断 CPU才退出低功耗模式 假设只能省10uA

CR2032 220mAH

DMA CPU不用参与

PPI 主要解决的问题是 外设之间的触发 不涉及内存

  • 底层接口调用流程 以及核心函数

    rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus,
                                        const char               *bus_name)
    
    rt_size_t rt_i2c_transfer()  >>   bus->ops->master_xfer(bus, msgs, num);
    
  • rt_i2c_bus_device 结构体

    /*for i2c bus driver*/
    struct rt_i2c_bus_device
    {
        struct rt_device parent;
        const struct rt_i2c_bus_device_ops *ops;
        rt_uint16_t  flags;
        rt_uint16_t  addr;
        struct rt_mutex lock;
        rt_uint32_t  timeout;
        rt_uint32_t  retries;
        void *priv;
    };
    
  • OPS接口

    struct rt_i2c_bus_device_ops
    {
        rt_size_t (*master_xfer)(struct rt_i2c_bus_device *bus,
                                 struct rt_i2c_msg msgs[],
                                 rt_uint32_t num);
        rt_size_t (*slave_xfer)(struct rt_i2c_bus_device *bus,
                                struct rt_i2c_msg msgs[],
                                rt_uint32_t num);
        rt_err_t (*i2c_bus_control)(struct rt_i2c_bus_device *bus,
                                    rt_uint32_t,
                                    rt_uint32_t);
    };
    

    slave_xfer 和 i2c_bus_control 其实没有任何用处,只能支持Master设备

    在registe之前需要自己初始化硬件,初始化完成后 不能通过标准化接口更改I2C硬件参数

    不支持 rx_indicate 和 tx_complete 回调函数

    在整理下思路 > 仅需要实现 master_xfer 这个底层接口即可

  • /* 查找I2C总线设备,获取I2C总线设备句柄 */
    i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name);
    
    /* 调用I2C设备接口传输数据 */
    (rt_i2c_transfer(bus, &msgs, 1) == 1)
    

    数据流:标准化接口 > 接口封装 > 硬件层