RT-Thread 各版本配置项分析
RT-Thread 5.1.0
RT_USING_NANO
一键配置为极简版内核,只保留了以下配置项:
- 内核配置
- Finsh 配置
- 软件包配置
资源对比可参考这篇文章
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_DECLARE
和RT_OBJECT_HOOKLIST_DEFINE
中的name
,即hooklist
节点结构体和操作方法的前缀。hooker_handler
对应RT_OBJECT_HOOKLIST_DECLARE
中handler_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_debug
为rt_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_memset
和 rt_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_HOUR
、RT_LIBC_TZ_DEFAULT_MIN
、RT_LIBC_TZ_DEFAULT_SEC
初始化时间偏移(秒)。可通过
rt_tz_set
和rt_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 */
}