Browse Source

[add][components][utilities]Add the Var Export component

Signed-off-by: WillianChan <willianchan_lovelife@foxmail.com>
WillianChan 3 years ago
parent
commit
9f543f7065

+ 4 - 0
components/utilities/Kconfig

@@ -205,6 +205,10 @@ config RT_USING_UTEST
             default 20
     endif
 
+config RT_USING_VAR_EXPORT
+    bool "Enable Var Export"
+    default n
+
 source "$RTT_DIR/components/utilities/rt-link/Kconfig"
 
 endmenu

+ 8 - 0
components/utilities/var_export/SConscript

@@ -0,0 +1,8 @@
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c')
+CPPPATH = [cwd]
+group   = DefineGroup('var_export', src, depend = ['RT_USING_VAR_EXPORT'], CPPPATH = CPPPATH)
+
+Return('group')

+ 216 - 0
components/utilities/var_export/var_export.c

@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-06-04     WillianChan  first version
+ * 2021-06-08     WillianChan  support to MS VC++ compiler
+ */
+
+#include <var_export.h>
+
+static const ve_exporter_t *ve_exporter_table = RT_NULL;
+static rt_size_t ve_exporter_num = 0;
+
+/* for IAR compiler */
+#if defined(__ICCARM__) || defined(__ICCRX__)
+#pragma section="VarExpTab"
+#endif
+
+/* for ARM C and IAR Compiler */
+#if defined(__CC_ARM) || defined(__CLANG_ARM) || defined (__ICCARM__) || defined(__ICCRX__)
+static RT_USED const struct ve_exporter __ve_table_start
+RT_SECTION("0.""VarExpTab") = {"ve_start", "ve_start", 0};
+
+static RT_USED const struct ve_exporter __ve_table_end
+RT_SECTION("2.""VarExpTab") = {"ve_end", "ve_end", 2};
+#endif
+
+/* for MS VC++ compiler */
+#if defined(_MSC_VER)
+static ve_exporter_t ve_exporter_tab[2048];
+
+#pragma section("VarExpTab$a", read)
+__declspec(allocate("VarExpTab$a"))
+RT_USED const struct ve_exporter __ve_table_start = { "ve_start", "ve_start", 0};
+
+#pragma section("VarExpTab$z", read)
+__declspec(allocate("VarExpTab$z"))
+RT_USED const struct ve_exporter __ve_table_end = { "ve_end", "ve_end", 2};
+#endif
+
+/* initialize var export */
+int var_export_init(void)
+{
+    /* initialize the var export table.*/
+#if defined(__CC_ARM) || defined(__CLANG_ARM)       /* for ARM C Compiler */
+    ve_exporter_table = &__ve_table_start + 1;
+    ve_exporter_num = &__ve_table_end - &__ve_table_start;
+#elif defined (__GNUC__)                            /* for GCC Compiler */
+    extern const int __ve_table_start;
+    extern const int __ve_table_end;
+    ve_exporter_table = (const ve_exporter_t *)&__ve_table_start;
+    ve_exporter_num = (const ve_exporter_t *)&__ve_table_end - ve_exporter_table;
+#elif defined (__ICCARM__) || defined(__ICCRX__)    /* for IAR Compiler */
+    ve_exporter_table = &__ve_table_start + 1;
+    ve_exporter_num = &__ve_table_end - &__ve_table_start - 1;
+#elif defined (_MSC_VER)                            /* for MS VC++ compiler */
+    unsigned int *ptr_begin = (unsigned int *)&__ve_table_start;
+    unsigned int *ptr_end = (unsigned int *)&__ve_table_end;
+
+    /* past the three members in first ptr_begin */
+    ptr_begin += (sizeof(struct ve_exporter) / sizeof(unsigned int));
+    while (*ptr_begin == 0) ptr_begin++;
+    do ptr_end--; while (*ptr_end == 0);
+
+    ve_exporter_table = (const ve_exporter_t *)ptr_begin;
+    ve_exporter_num = (ptr_end - ptr_begin) / (sizeof(struct ve_exporter) / sizeof(unsigned int)) + 1;
+
+    int index_i, index_j, index_min;
+
+    for (index_i = 0; index_i < ve_exporter_num; index_i++)
+    {
+        ve_exporter_tab[index_i] = ve_exporter_table[index_i];
+    }
+
+    for (index_i = 0; index_i < (ve_exporter_num - 1); index_i++)
+    {
+        index_min = index_i;
+
+        for (index_j = index_i + 1; index_j < ve_exporter_num; index_j++)
+        {
+            if (rt_strcmp(ve_exporter_tab[index_j].module, ve_exporter_tab[index_min].module) < 0)
+            {
+                index_min = index_j;
+                ve_exporter_t ve_exporter_temp[1] = {ve_exporter_tab[index_min]};
+                ve_exporter_tab[index_min] = ve_exporter_tab[index_i];
+                ve_exporter_tab[index_i] = ve_exporter_temp[0];
+            }
+        }
+    }
+#endif
+
+    return ve_exporter_num;
+}
+INIT_PREV_EXPORT(var_export_init);
+
+/* initialize module */
+int ve_module_init(ve_module_t *mod, const char *module)
+{
+#if defined(_MSC_VER)
+    const ve_exporter_t *exporter = ve_exporter_tab;
+#else
+    const ve_exporter_t *exporter = ve_exporter_table;
+#endif
+    rt_bool_t first_exist = RT_FALSE;
+    rt_size_t found_index;
+
+    for (found_index = 0; found_index < ve_exporter_num; found_index++)
+    {
+        if (!rt_strcmp(exporter->module, module))
+        {
+            if (first_exist == RT_FALSE)
+            {
+                mod->begin = exporter;
+                first_exist = RT_TRUE;
+            }
+            mod->end = exporter;
+        }
+        exporter++;
+    }
+
+    if (first_exist == RT_FALSE)
+    {
+        return -RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+
+/* initialize iterator */
+void ve_iter_init(ve_module_t *mod, ve_iterator_t *iter)
+{
+    if (iter)
+    {
+        iter->exp_index = mod->begin;
+        iter->exp_end = mod->end;
+    }
+}
+
+/* iterate backward */
+const ve_exporter_t *ve_iter_next(ve_iterator_t *iter)
+{
+    if (iter->exp_index <= iter->exp_end)
+    {
+        return iter->exp_index++;
+    }
+    else
+    {
+        return RT_NULL;
+    }
+}
+
+/* binary search based on identifier */
+static const ve_exporter_t *ve_binary_search(ve_module_t *mod, const char *identifier)
+{
+#if defined(_MSC_VER)
+    rt_size_t ve_low_num = mod->begin - ve_exporter_tab;
+    rt_size_t ve_high_num = mod->end - ve_exporter_tab;
+#else
+    rt_size_t ve_low_num = mod->begin - ve_exporter_table;
+    rt_size_t ve_high_num = mod->end - ve_exporter_table;
+#endif
+    rt_size_t ve_mid_num;
+    int strcmp_rst;
+
+    while (ve_low_num <= ve_high_num)
+    {
+        ve_mid_num = (ve_high_num - ve_low_num) / 2;
+        strcmp_rst = rt_strcmp(mod->begin[ve_mid_num].identifier, identifier);
+
+        if (strcmp_rst == 0)
+        {
+            return &mod->begin[ve_mid_num];
+        }
+        else if (strcmp_rst > 0)
+        {
+            ve_high_num = ve_mid_num + 1;
+        }
+        else
+        {
+            ve_low_num = ve_mid_num - 1;
+        }
+    }
+
+    return RT_NULL;
+}
+
+/* get the value by identifier */
+rt_base_t ve_value_get(ve_module_t *mod, const char *identifier)
+{
+    const ve_exporter_t *exporter = ve_binary_search(mod, identifier);
+
+    if (exporter)
+    {
+        return exporter->value;
+    }
+    else
+    {
+        return VE_NOT_FOUND;
+    }
+}
+
+/* check if this value exists in the module*/
+rt_bool_t ve_value_exist(ve_module_t *mod, const char *identifier)
+{
+    if (ve_binary_search(mod, identifier))
+    {
+        return RT_TRUE;
+    }
+    else
+    {
+        return RT_FALSE;
+    }
+}

+ 94 - 0
components/utilities/var_export/var_export.h

@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-06-04     WillianChan  first version
+ * 2021-06-08     WillianChan  support to MS VC++ compiler
+ */
+
+#ifndef _VAR_EXPORT_H__
+#define _VAR_EXPORT_H__
+
+#include <rtthread.h>
+
+/* exported object */
+struct ve_exporter
+{
+    const char *module;             /* module name */
+    const char *identifier;         /* module identifier */
+    rt_base_t   value;              /* module value */
+};
+typedef struct ve_exporter ve_exporter_t;
+
+/* module object */
+struct ve_module
+{
+    const ve_exporter_t *begin;     /* the first module of the same name */
+    const ve_exporter_t *end;       /* the last module of the same */
+};
+typedef struct ve_module ve_module_t;
+
+/* iterator object */
+struct ve_iterator
+{
+    const ve_exporter_t *exp_index; /* iterator index */
+    const ve_exporter_t *exp_end;   /* iterate over exporter */
+};
+typedef struct ve_iterator ve_iterator_t;
+
+#define VE_NOT_FOUND (0xFFFFFFFFu)  /* not found */
+
+/* exporter's export command */
+#if defined(__GNUC__)
+#define VAR_EXPORT(module, identi, value)                                       \
+    const char _vexp_##identi##_module[] RT_SECTION(".rodata.vexp") = #module;  \
+    const char _vexp_##identi##_identi[] RT_SECTION(".rodata.vexp") = #identi;  \
+    RT_USED const struct ve_exporter _vexp_##module##identi                     \
+    RT_SECTION("VarExpTab") =                                                   \
+    {                                                                           \
+        _vexp_##identi##_module,                                                \
+        _vexp_##identi##_identi,                                                \
+        value,                                                                  \
+    }
+#elif defined(_MSC_VER)
+#pragma section("VarExpTab$f",read)
+#define VAR_EXPORT(module, identi, value)                                       \
+    const char _vexp_##identi##_module[] RT_SECTION(".rodata.vexp") = #module;  \
+    const char _vexp_##identi##_identi[] RT_SECTION(".rodata.vexp") = #identi;  \
+    __declspec(allocate("VarExpTab$f"))                                         \
+    RT_USED const struct ve_exporter _vexp_##module##identi =                   \
+    {                                                                           \
+        _vexp_##identi##_module,                                                \
+        _vexp_##identi##_identi,                                                \
+        value,                                                                  \
+    }
+#else
+#define VAR_EXPORT(module, identi, value)                                       \
+    const char _vexp_##identi##_module[] RT_SECTION(".rodata.vexp") = #module;  \
+    const char _vexp_##identi##_identi[] RT_SECTION(".rodata.vexp") = #identi;  \
+    RT_USED const struct ve_exporter _vexp_##module##identi                     \
+    RT_SECTION("1."#module".VarExpTab."#identi) =                               \
+    {                                                                           \
+        _vexp_##identi##_module,                                                \
+        _vexp_##identi##_identi,                                                \
+        value,                                                                  \
+    }
+#endif
+
+/* initialize var export */
+int ve_exporter_init(void);
+/* initialize module */
+int ve_module_init(ve_module_t *mod, const char *module);
+/* initialize iterator */
+void ve_iter_init(ve_module_t *mod, ve_iterator_t *iter);
+/* iterate backward */
+const ve_exporter_t *ve_iter_next(ve_iterator_t *iter);
+/* get the value by identifier */
+rt_base_t ve_value_get(ve_module_t *mod, const char *identifier);
+/* check if this value exists in the module*/
+rt_bool_t ve_value_exist(ve_module_t *mod, const char *identifier);
+
+#endif /* _VAR_EXPORT_H__ */

+ 166 - 0
components/utilities/var_export/var_export_cmd.c

@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-06-05     WillianChan  first version
+ */
+
+#include <var_export.h>
+
+static int ve_cmd_help(int argc, char **argv);
+static int ve_find_module(int argc, char **argv);
+static int ve_find_value(int argc, char **argv);
+
+
+struct ve_cmd_des
+{
+    const char *cmd;
+    int (*fun)(int argc, char **argv);
+};
+
+/* dcm cmd table */
+static const struct ve_cmd_des cmd_tab[] =
+{
+    {"module", ve_find_module},
+    {"value", ve_find_value},
+};
+
+static int ve_cmd_help(int argc, char **argv)
+{
+    rt_kprintf("Usage:\n");
+    rt_kprintf("ve_find module <module>                - Find by module name\n");
+    rt_kprintf("ve_find value  <module> <identifier>   - Find accurately\n");
+
+    return RT_EOK;
+}
+
+rt_inline void ve_object_split(int len)
+{
+    while (len--) rt_kprintf("-");
+}
+
+static int ve_find_module(int argc, char **argv)
+{
+    ve_iterator_t iter;
+    const ve_exporter_t *exporter;
+    ve_module_t module;
+    int maxlen = (RT_NAME_MAX * 2);
+    const char *item_title = "ve_module";
+
+    rt_kprintf("%-*.s identifier       value\n", maxlen, item_title); ve_object_split(maxlen);
+    rt_kprintf(" ---------------- -----\n");
+
+    if (!ve_module_init(&module, argv[2]))
+    {
+        ve_iter_init(&module, &iter);
+    }
+    else
+    {
+        return -RT_ERROR;
+    }
+
+    while (1)
+    {
+        exporter = ve_iter_next(&iter);
+        if (exporter == RT_NULL)
+        {
+            return RT_EOK;
+        }
+        else
+        {
+            rt_kprintf("%-*.s %-*.s %d\n",
+                       maxlen, exporter->module,
+                       maxlen, exporter->identifier,
+                       exporter->value);
+        }
+    }
+}
+
+static int ve_find_value(int argc, char **argv)
+{
+    ve_iterator_t iter;
+    const ve_exporter_t *exporter;
+    ve_module_t module;
+    int maxlen = (RT_NAME_MAX * 2);
+    const char *item_title = "ve_module";
+
+    rt_kprintf("%-*.s identifier       value\n", maxlen, item_title); ve_object_split(maxlen);
+    rt_kprintf(" ---------------- -----\n");
+
+    if (!ve_module_init(&module, argv[2]))
+    {
+        ve_iter_init(&module, &iter);
+    }
+    else
+    {
+        return -RT_ERROR;
+    }
+
+    while (1)
+    {
+        exporter = ve_iter_next(&iter);
+        if (exporter == RT_NULL)
+        {
+            return RT_EOK;
+        }
+        else
+        {
+            if (!rt_strcmp(exporter->identifier, argv[3]))
+            {
+                rt_kprintf("%-*.s %-*.s %d\n",
+                           maxlen, exporter->module,
+                           maxlen, exporter->identifier,
+                           exporter->value);
+
+                return RT_EOK;
+            }
+        }
+    }
+}
+
+static int ve_find(int argc, char **argv)
+{
+    int i, resule = RT_EOK;
+    const struct ve_cmd_des *run_cmd = RT_NULL;
+
+    if (argc == 1)
+    {
+        ve_cmd_help(argc, argv);
+        return RT_EOK;
+    }
+
+    /* find command function */
+    for (i = 0; i < sizeof(cmd_tab) / sizeof(cmd_tab[0]); i++)
+    {
+        if (rt_strcmp(cmd_tab[i].cmd, argv[1]) == 0)
+        {
+            run_cmd = &cmd_tab[i];
+            break;
+        }
+    }
+
+    /* not find command function, print help information */
+    if (run_cmd == RT_NULL)
+    {
+        rt_kprintf("There is no command option named %s.\n", argv[1]);
+        ve_cmd_help(argc, argv);
+        return RT_EOK;
+    }
+
+    /* run command function */
+    if (run_cmd->fun != RT_NULL)
+    {
+        resule = run_cmd->fun(argc, argv);
+    }
+
+    if (resule)
+    {
+        ve_cmd_help(argc, argv);
+    }
+
+    return RT_EOK;
+}
+MSH_CMD_EXPORT(ve_find, find the specified export variable);