【rtthread设备】补充篇:结合源码认识rtthread设备的三层框架

一、rtthread设备三层框架

绝大部分的嵌入式系统都包括一些 I/O(Input/Output,输入 / 输出)设备,例如仪器上的数据显示屏、工业设备上的串口通信、数据采集设备上用于保存数据的 Flash 或 SD 卡,以及网络设备的以太网接口等,都是嵌入式系统中容易找到的 I/O 设备例子。

RT-Thread 提供了一套简单的 I/O 设备模型框架,如下图所示,它位于硬件和应用程序之间,共分成三层,从上到下分别是 I/O 设备管理层、设备驱动框架层、设备驱动层。其中,设备管理层和设备驱动框架层rtthread已经实现,设备驱动框架向设备管理器注册见\rt-thread\components\drivers\spi\spi_dev.c,可见spi驱动框架属于rtthread的组件,rtthread的spi设备驱动框架提供了spi总线注册函数rt_spi_bus_register(struct rt_spi_bus *bus,const char *name, const struct rt_spi_ops *ops)用于将底层的spi操作注册到驱动框架,这样我们就可以调用设备管理api(open,read、write)跟底层硬件寄存器进行数据交换(读写寄存器)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nFewgzWC-1621076760774)(en-resource://database/2585:0)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XSD4o4sN-1621076760782)(en-resource://database/2587:0)]

二、结合源码分析三层之间的注册关系

2.1 设备驱动层向设备驱动框架层注册

wm_spi_ops即为硬件层的操作函数,实现寄存器的读写,如果soc原厂要使用rtthread驱动框架就是要实现spixfer函数。之后rtthread的spi驱动框架就会根据用户的rt_device_write函数去写硬件寄存器,或者通过rt_device_read读取硬件寄存器。

static struct rt_spi_ops wm_spi_ops =
{
    
    
    .configure = spi_configure,
    .xfer = spixfer
};
struct wm_spi spi;
struct rt_spi_bus wm_spi_bus;
int wm_hw_spi_bus_init(void)
{
    
    
    rt_int16_t gpio_pin;
    gpio_pin = wm_get_pin(WM_SPI_CK_PIN);
    if (gpio_pin >= 0)
    {
    
    
        wm_spi_ck_config((enum tls_io_name)gpio_pin);
    }
    gpio_pin = wm_get_pin(WM_SPI_DI_PIN);
    if (gpio_pin >= 0)
    {
    
    
        wm_spi_di_config((enum tls_io_name)gpio_pin);
    }
    gpio_pin = wm_get_pin(WM_SPI_DO_PIN);
    if (gpio_pin >= 0)
    {
    
    
        wm_spi_do_config((enum tls_io_name)gpio_pin);
    }
    wm_spi_bus.parent.user_data = &spi;
#ifdef WM_SPI_BUS_NAME
    rt_spi_bus_register(&wm_spi_bus, WM_SPI_BUS_NAME, &wm_spi_ops);
#else
    rt_spi_bus_register(&wm_spi_bus, "spi0", &wm_spi_ops);
#endif
    return RT_EOK;
}


2.2 设备驱动框架层向设备管理层注册

\rt-thread\components\drivers\spi\spi_dev.c中的rt_spidev_device_init向设备管理层注册一个spi总线驱动。

rt_err_t rt_spidev_device_init(struct rt_spi_device *dev, const char *name)
{
    
    
    struct rt_device *device;
    RT_ASSERT(dev != RT_NULL);

    device = &(dev->parent);

    /* set device type */
    device->type    = RT_Device_Class_SPIDevice;
#ifdef RT_USING_DEVICE_OPS
    device->ops     = &spi_device_ops;
#else
    device->init    = RT_NULL;
    device->open    = RT_NULL;
    device->close   = RT_NULL;
    device->read    = _spidev_device_read;
    device->write   = _spidev_device_write;
    device->control = _spidev_device_control;
#endif

    /* register to device manager */
    return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
}

Guess you like

Origin blog.csdn.net/weixin_43810563/article/details/116859627