跳至主要內容

RT-Thread 各版本配置项分析

马龙伟...大约 6 分钟笔记RT-Thread

RT-Thread 5.1.0

RT_USING_NANO

  • 一键配置为极简版内核,只保留了以下配置项:

    • 内核配置
    • Finsh 配置
    • 软件包配置
  • 资源对比可参考这篇文章

    RT-Thread 裁剪分析

RT_USING_HOOK、RT_HOOK_USING_FUNC_PTR

只有同时使能这两项时,RT_OBJECT_HOOK_CALL 才会真正调用回调函数。

#ifndef RT_USING_HOOK
#define RT_OBJECT_HOOK_CALL(func, argv)

#else

/**
 * @brief Add hook point in the routines
 * @note Usage:
 * void foo() {
 *     do_something();
 *
 *     RT_OBJECT_HOOK_CALL(foo);
 *
 *     do_other_things();
 * }
 */
#define _RT_OBJECT_HOOK_CALL(func, argv) __ON_HOOK_ARGS(func, argv)
#define RT_OBJECT_HOOK_CALL(func, argv)  _RT_OBJECT_HOOK_CALL(func, argv)

    #ifdef RT_HOOK_USING_FUNC_PTR
        #define __ON_HOOK_ARGS(__hook, argv)        do {if ((__hook) != RT_NULL) __hook argv; } while (0)
    #else
        #define __ON_HOOK_ARGS(__hook, argv)
    #endif /* RT_HOOK_USING_FUNC_PTR */
#endif /* RT_USING_HOOK */

RT_USING_HOOKLIST

RT_OBJECT_HOOKLIST_DECLARE

  • 定义

    /**
     * @brief Add declaration for hook list types.
     *
     * @note Usage:
     * This is typically used in your header. In foo.h using this like:
     *
     * ```foo.h
     *     typedef void (*bar_hook_proto_t)(arguments...);
     *     RT_OBJECT_HOOKLIST_DECLARE(bar_hook_proto_t, bar_myhook);
     * ```
     */
    #define RT_OBJECT_HOOKLIST_DECLARE(handler_type, name) \
        typedef struct name##_hooklistnode                 \
        {                                                  \
            handler_type handler;                          \
            rt_list_t list_node;                           \
        } *name##_hooklistnode_t;                          \
        extern volatile rt_ubase_t name##_nested;          \
        void name##_sethook(name##_hooklistnode_t node);   \
        void name##_rmhook(name##_hooklistnode_t node)
    
  • 示例

    在头文件中调用,声明了 hooklist 节点和操作方法。

    /**
     * @brief Sets a hook function when RX indicate is called
     *
     * @param thread is the target thread that initializing
     */
    typedef void (*rt_hw_serial_rxind_hookproto_t)(rt_device_t dev, rt_size_t size);
    RT_OBJECT_HOOKLIST_DECLARE(rt_hw_serial_rxind_hookproto_t, rt_hw_serial_rxind);
    =>
    
    typedef struct rt_hw_serial_rxind_hooklistnode {
        rt_hw_serial_rxind_hookproto_t handler;
        rt_list_t list_node;
    } *rt_hw_serial_rxind_hooklistnode_t;
    extern volatile rt_ubase_t rt_hw_serial_rxind_nested;
    void rt_hw_serial_rxind_sethook(rt_hw_serial_rxind_hooklistnode_t node);
    void rt_hw_serial_rxind_rmhook(rt_hw_serial_rxind_hooklistnode_t node)
    

RT_OBJECT_HOOKLIST_DEFINE

  • 定义

    /**
     * @note Usage
     * Add this macro to the source file where your hook point is inserted.
     */
    #define RT_OBJECT_HOOKLIST_DEFINE(name)                                      \
        static rt_list_t name##_hooklist = RT_LIST_OBJECT_INIT(name##_hooklist); \
        static struct rt_spinlock name##lock = RT_SPINLOCK_INIT;                 \
        volatile rt_ubase_t name##_nested = 0;                                   \
        void name##_sethook(name##_hooklistnode_t node)                          \
        {                                                                        \
            rt_ubase_t level = rt_spin_lock_irqsave(&name##lock);                \
            while (name##_nested)                                                \
            {                                                                    \
                rt_spin_unlock_irqrestore(&name##lock, level);                   \
                level = rt_spin_lock_irqsave(&name##lock);                       \
            }                                                                    \
            rt_list_insert_before(&name##_hooklist, &node->list_node);           \
            rt_spin_unlock_irqrestore(&name##lock, level);                       \
        }                                                                        \
        void name##_rmhook(name##_hooklistnode_t node)                           \
        {                                                                        \
            rt_ubase_t level = rt_spin_lock_irqsave(&name##lock);                \
            while (name##_nested)                                                \
            {                                                                    \
                rt_spin_unlock_irqrestore(&name##lock, level);                   \
                level = rt_spin_lock_irqsave(&name##lock);                       \
            }                                                                    \
            rt_list_remove(&node->list_node);                                    \
            rt_spin_unlock_irqrestore(&name##lock, level);                       \
        }
    
  • 示例

    在源文件中调用,定义 hooklist 链表头节点和操作方法。

    RT_OBJECT_HOOKLIST_DEFINE(rt_hw_serial_rxind);
    =>
    
    static rt_list_t rt_hw_serial_rxind_hooklist = RT_LIST_OBJECT_INIT(rt_hw_serial_rxind_hooklist);
    static struct rt_spinlock rt_hw_serial_rxindlock = {0};
    volatile rt_ubase_t rt_hw_serial_rxind_nested = 0;
    
    void rt_hw_serial_rxind_sethook(rt_hw_serial_rxind_hooklistnode_t node) {
        rt_ubase_t level = rt_spin_lock_irqsave(&rt_hw_serial_rxindlock);
        while (rt_hw_serial_rxind_nested) {
            rt_spin_unlock_irqrestore(&rt_hw_serial_rxindlock, level);
            level = rt_spin_lock_irqsave(&rt_hw_serial_rxindlock);
        }
        rt_list_insert_before(&rt_hw_serial_rxind_hooklist, &node->list_node);
        rt_spin_unlock_irqrestore(&rt_hw_serial_rxindlock, level);
    }
    
    void rt_hw_serial_rxind_rmhook(rt_hw_serial_rxind_hooklistnode_t node) {
        rt_ubase_t level = rt_spin_lock_irqsave(&rt_hw_serial_rxindlock);
        while (rt_hw_serial_rxind_nested) {
            rt_spin_unlock_irqrestore(&rt_hw_serial_rxindlock, level);
            level = rt_spin_lock_irqsave(&rt_hw_serial_rxindlock);
        }
        rt_list_remove(&node->list_node);
        rt_spin_unlock_irqrestore(&rt_hw_serial_rxindlock, level);
    }
    

RT_OBJECT_HOOKLIST_DEFINE_NODE

  • 定义

    hookname 对应 RT_OBJECT_HOOKLIST_DECLARERT_OBJECT_HOOKLIST_DEFINE 中的 name,即 hooklist 节点结构体和操作方法的前缀。

    hooker_handler 对应 RT_OBJECT_HOOKLIST_DECLAREhandler_type 类型所定义的方法。

    /**
    * @brief Add declaration for hook list node.
    *
    * @note Usage
    * You can add a hook like this.
    *
    * ```addhook.c
    * void myhook(arguments...) { do_something(); }
    * RT_OBJECT_HOOKLIST_DEFINE_NODE(bar_myhook, myhook_node, myhook);
    *
    * void addhook(void)
    * {
    *      bar_myhook_sethook(myhook);
    * }
    * ```
    *
    * BTW, you can also find examples codes under
    * `examples/utest/testcases/kernel/hooklist_tc.c`.
    */
    #define RT_OBJECT_HOOKLIST_DEFINE_NODE(hookname, nodename, hooker_handler) \
        struct hookname##_hooklistnode nodename = {                            \
            .handler = hooker_handler,                                         \
            .list_node = RT_LIST_OBJECT_INIT(nodename.list_node),              \
        };
    
  • 示例

    在源文件中调用。

    _set_debugrt_hw_serial_rxind_hookproto_t 类型定义的方法。

    之后可通过调用 rt_hw_serial_rxind_sethook 和 rt_hw_serial_rxind_rmhook 将 hooklist 节点 _set_debug_node 注册和移除链表。

    static void _set_debug(rt_device_t dev, rt_size_t size);
    RT_OBJECT_HOOKLIST_DEFINE_NODE(rt_hw_serial_rxind, _set_debug_node, _set_debug);
    

RT_OBJECT_HOOKLIST_CALL

  • 定义

    /**
    * @brief Add hook list point in the routines. Multiple hookers in the list will
    *        be called one by one starting from head node.
    *
    * @note Usage:
    * void foo() {
    *     do_something();
    *
    *     RT_OBJECT_HOOKLIST_CALL(foo);
    *
    *     do_other_things();
    * }
    */
    #define _RT_OBJECT_HOOKLIST_CALL(nodetype, nested, list, lock, argv)  \
        do                                                                \
        {                                                                 \
            nodetype iter, next;                                          \
            rt_ubase_t level = rt_spin_lock_irqsave(&lock);               \
            nested += 1;                                                  \
            rt_spin_unlock_irqrestore(&lock, level);                      \
            if (!rt_list_isempty(&list))                                  \
            {                                                             \
                rt_list_for_each_entry_safe(iter, next, &list, list_node) \
                {                                                         \
                    iter->handler argv;                                   \
                }                                                         \
            }                                                             \
            level = rt_spin_lock_irqsave(&lock);                          \
            nested -= 1;                                                  \
            rt_spin_unlock_irqrestore(&lock, level);                      \
        } while (0)
    #define RT_OBJECT_HOOKLIST_CALL(name, argv)                        \
        _RT_OBJECT_HOOKLIST_CALL(name##_hooklistnode_t, name##_nested, \
                                name##_hooklist, name##lock, argv)
    
  • 示例

    逐个调用链表中的每个节点。

    RT_OBJECT_HOOKLIST_CALL(rt_hw_serial_rxind, (dev, size));
    

RT_KSERVICE_USING_STDLIB、RT_KSERVICE_USING_STDLIB_MEMORY

使能后使用 C 库函数。

/* kstring */

#ifndef RT_KSERVICE_USING_STDLIB_MEMORY
void *rt_memset(void *src, int c, rt_ubase_t n);
void *rt_memcpy(void *dest, const void *src, rt_ubase_t n);
void *rt_memmove(void *dest, const void *src, rt_size_t n);
rt_int32_t rt_memcmp(const void *cs, const void *ct, rt_size_t count);
#endif /* RT_KSERVICE_USING_STDLIB_MEMORY */
char *rt_strdup(const char *s);
rt_size_t rt_strnlen(const char *s, rt_ubase_t maxlen);
#ifndef RT_KSERVICE_USING_STDLIB
char *rt_strstr(const char *str1, const char *str2);
rt_int32_t rt_strcasecmp(const char *a, const char *b);
char *rt_strcpy(char *dst, const char *src);
char *rt_strncpy(char *dest, const char *src, rt_size_t n);
rt_int32_t rt_strncmp(const char *cs, const char *ct, rt_size_t count);
rt_int32_t rt_strcmp(const char *cs, const char *ct);
rt_size_t rt_strlen(const char *src);
#else
#include <string.h>
#ifdef RT_KSERVICE_USING_STDLIB_MEMORY
#define rt_memset(s, c, count)      memset(s, c, count)
#define rt_memcpy(dst, src, count)  memcpy(dst, src, count)
#define rt_memmove(dest, src, n)    memmove(dest, src, n)
#define rt_memcmp(cs, ct, count)    memcmp(cs, ct, count)
#endif /* RT_KSERVICE_USING_STDLIB_MEMORY */
#define rt_strstr(str1, str2)       strstr(str1, str2)
#define rt_strcasecmp(a, b)         strcasecmp(a, b)
#define rt_strcpy(dest, src)        strcpy(dest, src)
#define rt_strncpy(dest, src, n)    strncpy(dest, src, n)
#define rt_strncmp(cs, ct, count)   strncmp(cs, ct, count)
#define rt_strcmp(cs, ct)           strcmp(cs, ct)
#define rt_strlen(src)              strlen(src)
#endif /*RT_KSERVICE_USING_STDLIB*/

RT_KSERVICE_USING_TINY_SIZE

不使能 RT_KSERVICE_USING_STDLIB_MEMORY 时,使能后 rt_memsetrt_memcpy 使用循环方式一个字节一个字节操作,效率低。

RT_USING_TINY_FFS

不使能 RT_USING_CPU_FFS 时,使用查表法查找第一个置位的索引。CPU 提供的方法效率最高。

  • 使能 RT_USING_TINY_FFS

    使用微型表,效率较低。

    const rt_uint8_t __lowest_bit_bitmap[] =
    {
        /*  0 - 7  */  0,  1,  2, 27,  3, 24, 28, 32,
        /*  8 - 15 */  4, 17, 25, 31, 29, 12, 32, 14,
        /* 16 - 23 */  5,  8, 18, 32, 26, 23, 32, 16,
        /* 24 - 31 */ 30, 11, 13,  7, 32, 22, 15, 10,
        /* 32 - 36 */  6, 21,  9, 20, 19
    };
    
    /**
    * @brief This function finds the first bit set (beginning with the least significant bit)
    * in value and return the index of that bit.
    *
    * Bits are numbered starting at 1 (the least significant bit).  A return value of
    * zero from any of these functions means that the argument was zero.
    *
    * @param value is the value to find the first bit set in.
    *
    * @return return the index of the first bit set. If value is 0, then this function
    * shall return 0.
    */
    int __rt_ffs(int value)
    {
        return __lowest_bit_bitmap[(rt_uint32_t)(value & (value - 1) ^ value) % 37];
    }
    
  • 不使能 RT_USING_TINY_FFS

    直接查表

    const rt_uint8_t __lowest_bit_bitmap[] =
    {
        /* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
    };
    
    /**
    * @brief This function finds the first bit set (beginning with the least significant bit)
    * in value and return the index of that bit.
    *
    * Bits are numbered starting at 1 (the least significant bit).  A return value of
    * zero from any of these functions means that the argument was zero.
    *
    * @param value is the value to find the first bit set in.
    *
    * @return Return the index of the first bit set. If value is 0, then this function
    *         shall return 0.
    */
    int __rt_ffs(int value)
    {
        if (value == 0)
        {
            return 0;
        }
    
        if (value & 0xff)
        {
            return __lowest_bit_bitmap[value & 0xff] + 1;
        }
    
        if (value & 0xff00)
        {
            return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9;
        }
    
        if (value & 0xff0000)
        {
            return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17;
        }
    
        return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25;
    }
    

RT_USING_MEMHEAP

使能 memheap 内存管理算法。

RT_USING_MEMHEAP_AS_HEAP

系统内存分配使用 memheap 内存管理算法。

RT_USING_MEMHEAP_AUTO_BINDING

将所有 memheap 对象作为内存分配堆。

RT_USING_LEGACY

支持旧版本的兼容性。

RT_LIBC_USING_FULL_TZ_DST

使用数据库对时区和夏令时进行全面版本。

会选中 PKG_USING_TZ_DATABASE 软件包。

RT_LIBC_USING_LIGHT_TZ_DST

  • 启用轻量级时区和夏令时。与 RT_LIBC_USING_FULL_TZ_DST 互斥。

  • 根据 RT_LIBC_TZ_DEFAULT_HOURRT_LIBC_TZ_DEFAULT_MINRT_LIBC_TZ_DEFAULT_SEC 初始化时间偏移(秒)。

  • 可通过 rt_tz_setrt_tz_get 设置和获取时间偏移(秒)。

static volatile int32_t _current_tz_offset_sec = \
    RT_LIBC_TZ_DEFAULT_HOUR * 3600U + RT_LIBC_TZ_DEFAULT_MIN * 60U + RT_LIBC_TZ_DEFAULT_SEC;

/* return current timezone offset in seconds */
void rt_tz_set(int32_t offset_sec)
{
    _current_tz_offset_sec = offset_sec;
}

int32_t rt_tz_get(void)
{
    return _current_tz_offset_sec;
}

int8_t rt_tz_is_dst(void)
{
    return 0U; /* TODO */
}
你认为这篇文章怎么样?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.5