RT-Thread 各版本配置项分析

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_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

#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 */

}

相关推荐

如何在美图秀秀中添加水印?详尽步骤与小技巧全解析
365体育平台bet下载入口

如何在美图秀秀中添加水印?详尽步骤与小技巧全解析

📅 10-15 👁️ 1888
《上古卷轴5》配置要求介绍 老滚5配置要求高吗
365bet网址开户

《上古卷轴5》配置要求介绍 老滚5配置要求高吗

📅 06-24 👁️ 8387
房产客源管理软件哪个好
365bet网址开户

房产客源管理软件哪个好

📅 07-09 👁️ 4628