OpenVINOTM,给你看得见的未来!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 基于stm32的rt-thread IIC 驱动框架代码阅读

共2条 1/1 1 跳转至

基于stm32的rt-thread IIC 驱动框架代码阅读

工程师
2019-06-30 17:09:20    评分

rt-thread 4.0.1版本已经集成了基于stm32 IIC驱动框架,美中不足的是官方代码的驱动框架是基于模拟IIC的方式实现的,要是集成的是硬件的方式就更棒了,相信不久以后的RTT会有的,主要涉及的文件如下,以下指示个人的一点理解,理解的有不对的地方欢迎各位拍砖。

\rt-thread\components\drivers\i2c\i2c_dev.c
\rt-thread\components\drivers\i2c\i2c_core.c
\rt-thread\components\drivers\i2c\i2c-bit-ops.c
\rt-thread\bsp\stm32\libraries\HAL_Drivers\drv_soft_i2c.c
我们由下而上的了解熟悉各个文件的作用:
①drv_soft_i2c.c:提供BSP相关的硬件操作函数,操作IIC 的SDA,和SCL总线电平,提供上层模拟IIC总线使用完成IIC信号的物理层操作。
向上层提供的操作函数如下:

  1. struct rt_i2c_bit_ops

  2. {

  3.     void *data;            /* private data for lowlevel routines */

  4.     void (*set_sda)(void *data, rt_int32_t state);

  5.     void (*set_scl)(void *data, rt_int32_t state);

  6.     rt_int32_t (*get_sda)(void *data);

  7.     rt_int32_t (*get_scl)(void *data);


  8.     void (*udelay)(rt_uint32_t us);


  9.     rt_uint32_t delay_us;  /* scl and sda line delay */

  10.     rt_uint32_t timeout;   /* in tick */

  11. };

复制代码

上述的void *data;指向如下的内部私有数据,配置设置对应硬件的ID,和向上注册的总线name。rt-thread将引脚的抽象成对应芯片封装的引脚号,具体再次不具体讲述,感兴趣可以查看RTT的gpio框架。如下链接是之前写的自己的认识

  1. /* stm32 config class */

  2. struct stm32_soft_i2c_config

  3. {

  4.     rt_uint8_t scl;

  5.     rt_uint8_t sda;

  6.     const char *bus_name;

  7. };

复制代码

该文件的入口函数如下:该函数会在系统启动完成后自动调用。
stm32_i2c_gpio_init==》设置GPIO默认电平总线空闲状态,SDA,SCL为高电平。
rt_i2c_bit_add_bus==》调用(\rt-thread\components\drivers\i2c\i2c-bit-ops.c)中的函数,向上注册驱动层IO操作函数,注册的结构如下,其中的priv成员指向底层的IO操作函数完成总线设备和底层的IO操作函数的绑定,从而上层使用rt_i2c_bus_device 对应的对象就能完成对总线的操作。

  1. /*for i2c bus driver*/

  2. struct rt_i2c_bus_device

  3. {

  4.     struct rt_device parent;

  5.     const struct rt_i2c_bus_device_ops *ops;

  6.     rt_uint16_t  flags;

  7.     rt_uint16_t  addr;

  8.     struct rt_mutex lock;

  9.     rt_uint32_t  timeout;

  10.     rt_uint32_t  retries;

  11.     void *priv;

  12. };

复制代码


stm32_i2c_bus_unlock==》按照注释是解锁总线,具体的原理现在还没有搞明白什么情况下总线会被锁状态,希望路过有了解的留下脚印讲解下。

  1. /* I2C initialization function */

  2. int rt_hw_i2c_init(void)

  3. {

  4. ......

  5.         stm32_i2c_gpio_init(&i2c_obj[i]);

  6.         result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name);

  7.         RT_ASSERT(result == RT_EOK);

  8.         stm32_i2c_bus_unlock(&soft_i2c_config[i]);

  9. ......

  10. }

  11. INIT_BOARD_EXPORT(rt_hw_i2c_init);

复制代码


②i2c-bit-ops.c:封装底层提供的IO操作函数,实现IIC协议层相关信号操作,提供IIC core核心层对应的操作函数,向IIC core提供的操作方法如下。

  1. struct rt_i2c_bus_device_ops

  2. {

  3.     rt_size_t (*master_xfer)(struct rt_i2c_bus_device *bus,

  4.                              struct rt_i2c_msg msgs[],

  5.                              rt_uint32_t num);

  6.     rt_size_t (*slave_xfer)(struct rt_i2c_bus_device *bus,

  7.                             struct rt_i2c_msg msgs[],

  8.                             rt_uint32_t num);

  9.     rt_err_t (*i2c_bus_control)(struct rt_i2c_bus_device *bus,

  10.                                 rt_uint32_t,

  11.                                 rt_uint32_t);

  12. };

复制代码


该文件中只实现master_xfer函数,另外两个函数指针设置为NULL。

  1. static const struct rt_i2c_bus_device_ops i2c_bit_bus_ops =

  2. {

  3.     i2c_bit_xfer,

  4.     RT_NULL,

  5.     RT_NULL

  6. };

复制代码

i2c_bit_xfer 函数我们可以看出,该函数只是只是对底层提供函数的操作的进一步封住,提供核心层(core)使用,struct rt_i2c_bit_ops *ops = bus->priv 取出底层的函数来按照IIC协议来发送数据

  1. static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus,

  2.                               struct rt_i2c_msg         msgs[],

  3.                               rt_uint32_t               num)

  4. {

  5.     struct rt_i2c_msg *msg;

  6.     struct rt_i2c_bit_ops *ops = bus->priv;

  7. ......

  8.     i2c_start(ops);

  9. ......

  10.     i2c_stop(ops);


  11.     return ret;

  12. }

复制代码

③i2c_core.c:抽象通用的IIC操作函数供应用层使用,调用i2c-bit-ops.c注册的函数指针master_xfer 完成数据的处理

  1. rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus,

  2.                           struct rt_i2c_msg         msgs[],

  3.                           rt_uint32_t               num)

  4. {

  5.     rt_size_t ret;


  6.     if (bus->ops->master_xfer)

  7.     {

  8. #ifdef RT_I2C_DEBUG

  9.         for (ret = 0; ret < num; ret++)

  10.         {

  11.             i2c_dbg("msgs[%d] %c, addr=0x%02x, len=%d\n", ret,

  12.                     (msgs[ret].flags & RT_I2C_RD) ? 'R' : 'W',

  13.                     msgs[ret].addr, msgs[ret].len);

  14.         }

  15. #endif


  16.         rt_mutex_take(&bus->lock, RT_WAITING_FOREVER);

  17.         ret = bus->ops->master_xfer(bus, msgs, num);

  18.         rt_mutex_release(&bus->lock);


  19.         return ret;

  20.     }

  21.     else

  22.     {

  23.         i2c_dbg("I2C bus operation not supported\n");


  24.         return 0;

  25.     }

  26. }

复制代码




专家
2019-07-01 09:37:13    评分
2楼

没有集成硬件IIC驱动 不是因为RT-T的技术没有操作,而是stm32的硬件IIC不是太稳定


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]