Sfoglia il codice sorgente

!531 添加rt_driver相关代码
Merge pull request !531 from songchao/rt-smart

bernard 3 anni fa
parent
commit
b4190a5346
6 ha cambiato i file con 246 aggiunte e 2 eliminazioni
  1. 30 1
      include/rtdef.h
  2. 7 1
      include/rtthread.h
  3. 4 0
      src/Kconfig
  4. 3 0
      src/SConscript
  5. 93 0
      src/device.c
  6. 109 0
      src/driver.c

+ 30 - 1
include/rtdef.h

@@ -1093,7 +1093,10 @@ typedef struct rt_wqueue rt_wqueue_t;
 struct rt_device
 {
     struct rt_object          parent;                   /**< inherit from rt_object */
-
+#ifdef RT_USING_DM    
+    const struct rt_driver    *drv;
+    void *dtb_node; 
+#endif    
     enum rt_device_class_type type;                     /**< device type */
     rt_uint16_t               flag;                     /**< device flag */
     rt_uint16_t               open_flag;                /**< device open flag */
@@ -1125,6 +1128,32 @@ struct rt_device
     void                     *user_data;                /**< device private data */
 };
 
+#define RT_DRIVER_MATCH_DTS (1<<0)
+struct rt_device_id 
+{
+    const char *compatible;
+    void *data;
+};
+
+struct rt_driver
+{
+#ifdef RT_USING_DEVICE_OPS    
+    const struct rt_device_ops *dev_ops;
+#endif
+    const struct filesystem_ops *fops;
+    const char *name;
+    enum rt_device_class_type dev_type;
+    int device_priv_data_size;
+    int device_size;
+    int flag;
+    const struct rt_device_id *dev_match;
+    int (*probe)(struct rt_device *dev);
+    int (*probe_init)(struct rt_device *dev);
+    int (*remove)(struct rt_device *dev);
+    const void *ops;    /* driver-specific operations */
+};
+typedef struct rt_driver *rt_driver_t;
+
 /**
  * Notify structure
  */

+ 7 - 1
include/rtthread.h

@@ -24,7 +24,6 @@
 #include <rtdef.h>
 #include <rtservice.h>
 #include <rtm.h>
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -517,7 +516,14 @@ rt_size_t rt_device_write(rt_device_t dev,
                           const void *buffer,
                           rt_size_t   size);
 rt_err_t  rt_device_control(rt_device_t dev, int cmd, void *arg);
+#ifdef RT_USING_DM
+rt_err_t rt_device_bind_driver(rt_device_t device, rt_driver_t driver, void *node);
+rt_device_t rt_device_create_since_driver(rt_driver_t drv,int device_id);
+rt_err_t rt_device_probe_and_init(rt_device_t device);
 
+rt_err_t rt_driver_match_with_id(const rt_driver_t drv,int device_id);
+rt_err_t rt_driver_match_with_dtb(const rt_driver_t drv,void *from_node,int max_dev_num);
+#endif
 /**@}*/
 #endif
 

+ 4 - 0
src/Kconfig

@@ -347,4 +347,8 @@ config RT_VER_NUM
     help
         RT-Thread version number
 
+config RT_USING_DM
+    bool "Enable rt device driver model"
+    default n
+ 
 endmenu

+ 3 - 0
src/SConscript

@@ -29,6 +29,9 @@ if GetDepend('RT_USING_DEVICE') == False:
 if GetDepend('RT_USING_SMP') == False:
     SrcRemove(src, ['cpu.c'])
 
+if GetDepend('RT_USING_DM') == False:
+    SrcRemove(src, ['driver.c'])
+
 group = DefineGroup('Kernel', src, depend = [''], CPPPATH = CPPPATH)
 
 Return('group')

+ 93 - 0
src/device.c

@@ -477,4 +477,97 @@ rt_device_set_tx_complete(rt_device_t dev,
 }
 RTM_EXPORT(rt_device_set_tx_complete);
 
+#ifdef RT_USING_DM
+/**
+ * This function  bind drvier and device
+ *
+ * @param driver the pointer of driver structure
+ * @param device the pointer of device structure
+ * @param node the pointer of fdt node structure
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_device_bind_driver(rt_device_t device, rt_driver_t driver, void *node)
+{
+    if((!driver) || (!device))
+    {
+        return -RT_EINVAL;
+    }
+
+    device->drv = driver;
+#ifdef RT_USING_DEVICE_OPS    
+    device->ops = driver->dev_ops;
+#endif    
+    device->dtb_node = node;
+
+    return RT_EOK;
+} 
+RTM_EXPORT(rt_device_bind_driver);
+
+/**
+ * This function  create rt_device according to driver infomation
+ *
+ * @param drv the pointer of driver structure
+ * @param device_id specify the ID of the rt_device
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_device_t rt_device_create_since_driver(rt_driver_t drv,int device_id)
+{
+    rt_device_t device;
+    if (!drv)
+    {
+        return RT_NULL;
+    }
+
+    device = (rt_device_t)rt_calloc(1,drv->device_size);
+    if(device == RT_NULL)
+    {
+        return RT_NULL;
+    }
+    if(drv->device_priv_data_size != 0)
+    {
+        device->user_data = (void *)(rt_calloc(1,drv->device_priv_data_size));
+        if(device->user_data == RT_NULL)
+        {
+            rt_free(device);
+            return RT_NULL;
+        }   
+    }
+
+    device->device_id = device_id;
+    rt_snprintf(device->parent.name, sizeof(device->parent.name), "%s%d", drv->name, device_id);
+    return device;
+}
+RTM_EXPORT(rt_device_create_since_driver);
+
+/**
+ * This function  rt_device probe and init
+ *
+ * @param device the pointer of rt_device structure
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_device_probe_and_init(rt_device_t device)
+{
+    int ret = -RT_ERROR;
+    if (!device)
+    {
+        return -RT_EINVAL;
+    }
+    if(!device->drv)
+    {
+        return -RT_ERROR;
+    }
+    if(device->drv->probe)
+    {
+        ret = device->drv->probe((rt_device_t)device);
+    }
+    if(device->drv->probe_init)
+    {
+        ret = device->drv->probe_init((rt_device_t)device);
+    }
+    return ret;
+}
+RTM_EXPORT(rt_device_probe_and_init);
+#endif
 #endif

+ 109 - 0
src/driver.c

@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <rtthread.h>
+#ifdef PKG_USING_FDT
+#include <dtb_node.h>
+#endif
+#if defined(RT_USING_POSIX)
+#include <rtdevice.h> /* for wqueue_init */
+#endif
+
+/**
+ * This function driver device match with id
+ *
+ * @param drv the pointer of driver structure
+ * @param device_id the id of the device
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_driver_match_with_id(const rt_driver_t drv,int device_id)
+{
+    rt_device_t device;
+    int ret;
+    if (!drv)
+    {
+        return -RT_EINVAL;
+    }
+    device = rt_device_create_since_driver(drv,device_id);
+    if(!device)
+    {
+        return -RT_ERROR;
+    }
+    ret = rt_device_bind_driver(device,drv,RT_NULL);
+    if(ret != 0)
+    {
+        return -RT_ERROR;
+    }
+    ret = rt_device_probe_and_init(device);
+    if(ret != 0)
+    {
+        return -RT_ERROR;
+    }
+    return ret;
+}
+
+RTM_EXPORT(rt_driver_match_with_id);
+
+#ifdef PKG_USING_FDT
+/**
+ * This function driver device match with dtb_node
+ *
+ * @param drv the pointer of driver structure
+ * @param from_node dtb node entry 
+ * @param max_dev_num the max device support 
+ * 
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_driver_match_with_dtb(const rt_driver_t drv,void *from_node,int max_dev_num)
+{
+    struct dtb_node** node_list; 
+    rt_device_t device;
+    int ret,i;
+    int active_dev_num = 0;
+    if ((!drv)||(!drv->dev_match)||(!drv->dev_match->compatible)||(!from_node))
+    {
+        return -RT_EINVAL;
+    }
+
+    node_list = rt_calloc(max_dev_num,sizeof(void *));
+    if(!node_list)
+    {
+        return -RT_ERROR;
+    }
+
+    ret = dtb_node_find_all_active_compatible_node(from_node,drv->dev_match->compatible,node_list,max_dev_num,&active_dev_num);
+    if((ret != 0) || (!active_dev_num))
+    {
+        return -RT_ERROR;
+    }
+    
+    for(i = 0; i < active_dev_num; i ++)
+    {
+        device = rt_device_create_since_driver(drv,i);
+        if(!device)
+        {
+            return -RT_ERROR;
+        }
+    
+        ret = rt_device_bind_driver(device,drv,node_list[i]);
+        if(ret != 0)
+        {
+            return -RT_ERROR;
+        }
+        ret = rt_device_probe_and_init(device);
+        if(ret != 0)
+        {
+            return -RT_ERROR;
+        }
+    }
+    rt_free(node_list);
+    return ret;
+}
+
+RTM_EXPORT(rt_driver_match_with_dtb);
+#endif  
+