RT-Thread 内核配置项及其源码分析 --- 以ARM64为例

1. 关于 RT-Thread 的内核配置

  • RT-Thread的一个重要特性是它的高度可裁剪性,允许对内核进行微调和灵活地删除组件。

  • 配置主要通过修改项目目录-rtconfig.h下的文件来完成。用户可以通过打开/关闭文件中的宏定义来有条件地编译代码,最终实现系统配置和裁剪的目的,如下所示:

2. 内核配置项目

2.1 RT_NAME_MAX 内核对象名长度

/* Indicates the maximum length of the name of the kernel object. If the maximum length of the name of the object in the code is greater than the length of the macro definition,
 * the extra part will be cut off. */
#define RT_NAME_MAX 8
  • 例如,在 rt_object 中有,
/**
 * Base structure of Kernel object
 */
struct rt_object
{
    char       name[RT_NAME_MAX];                       /**< name of kernel object */
    rt_uint8_t type;                                    /**< type of kernel object */
    rt_uint8_t flag;                                    /**< flag of kernel object */

#ifdef RT_USING_MODULE
    void      *module_id;                               /**< id of application module */
#endif /* RT_USING_MODULE */
    rt_list_t  list;                                    /**< list node of kernel object */
};

2.2 RT_ALIGN_SIZE 内核默认对齐长度

/* Set the number of aligned bytes when bytes are aligned. Usually use ALIGN(RT_ALIGN_SIZE) for byte alignment.*/
#define RT_ALIGN_SIZE 4
  • 例如在 rt_system_heap_init 中,HEAP 的地址会按照 RT_ALIGN_SIZE 对齐
RT_WEAK void rt_system_heap_init(void *begin_addr, void *end_addr)
{
    rt_ubase_t begin_align = RT_ALIGN((rt_ubase_t)begin_addr, RT_ALIGN_SIZE);
    rt_ubase_t end_align   = RT_ALIGN_DOWN((rt_ubase_t)end_addr, RT_ALIGN_SIZE);

    RT_ASSERT(end_align > begin_align);
    ...

2.3 RT_THREAD_PRIORITY_MAX 内核线程优先级数目

/* Define the number of system thread priorities; usually define the priority of idle threads with RT_THREAD_PRIORITY_MAX-1 */
#define RT_THREAD_PRIORITY_MAX 32
  • scheduler.c 中,优先级列表中对应了 RT_THREAD_PRIORITY_MAX 个链表项
rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];

2.4 RT_TICK_PER_SECOND 内核每秒的节拍数

/* Define the clock beat. When it is 100, it means 100 tick per second, and a tick is 10ms. */
#define RT_TICK_PER_SECOND 100
  • gtimer.c 中设置 timer_step = gtimer_freq / RT_TICK_PER_SECOND
static volatile rt_uint64_t timer_step;

void rt_hw_gtimer_local_enable(void)
{
    rt_hw_gtimer_disable();
    rt_hw_set_gtimer_val(timer_step);
    rt_hw_interrupt_umask(EL1_PHY_TIMER_IRQ_NUM);
    rt_hw_gtimer_enable();
}

void rt_hw_gtimer_init(void)
{
    rt_hw_interrupt_install(EL1_PHY_TIMER_IRQ_NUM, rt_hw_timer_isr, RT_NULL, "tick");
    __ISB();
    timer_step = rt_hw_get_gtimer_frq();
    __DSB();
    timer_step /= RT_TICK_PER_SECOND;
    rt_hw_gtimer_local_enable();
}

2.5 RT_USING_OVERFLOW_CHECK 使能堆栈溢出检查

/* Check if the stack overflows, if not defined, close. */
#define RT_USING_OVERFLOW_CHECK
  • 堆栈溢出检查打开都,每次任务调度中,在(1)会进行一次溢出检查,如果发现溢出,会在(2)打印错误信息,让后将系统挂死
static void _scheduler_stack_check(struct rt_thread *thread)
{
    RT_ASSERT(thread != RT_NULL);

    if (*((rt_uint8_t *)thread->stack_addr) != '#' ||
        (rt_ubase_t)thread->sp <= (rt_ubase_t)thread->stack_addr ||
        (rt_ubase_t)thread->sp >
        (rt_ubase_t)thread->stack_addr + (rt_ubase_t)thread->stack_size)
    {
        rt_base_t level;

        rt_kprintf("thread:%s stack overflow\n", thread->name); (2)

        level = rt_hw_interrupt_disable();
        while (level);
    }
}

void rt_schedule(void)
{
    rt_base_t level;
    struct rt_thread *to_thread;
    struct rt_thread *from_thread;

...

#ifdef RT_USING_OVERFLOW_CHECK
                _scheduler_stack_check(to_thread); (1)
#endif /* RT_USING_OVERFLOW_CHECK */

2.6 RT_DEBUG 内核调试功能开关

/* Define this macro to enable debug mode, if not defined, close.  */
#define RT_DEBUG
/* When debug mode is enabled: When the macro is defined as 0, the print component initialization information is turned off. When it is defined as 1, it is enabled. */
#define RT_DEBUG_INIT 0
/* When debug mode is enabled: When the macro is defined as 0, the print thread switching information is turned off. When it is defined as 1, it is enabled. */
#define RT_DEBUG_THREAD 0
  • RT_DEBUG 打开后,会使能一系列功能,具体见 rtdebug.h,同时,如果定义 RT_DEBUG_INIT 为1,会打印组件初始化信息,如果定义 RT_DEBUG_THREAD 为1,会打印线程切换信息

2.7 RT_USING_HOOK 启用内核钩子函数

/* Defining this macro means the use of the hook function is started, if not defined, close. */
#define RT_USING_HOOK
  • 在 interrupt.h 中,使能开关后,可以注册函数在中断进入和离开时调用
#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)

static void (*rt_interrupt_enter_hook)(void);
static void (*rt_interrupt_leave_hook)(void);

void rt_interrupt_enter_sethook(void (*hook)(void))
{
    rt_interrupt_enter_hook = hook;
}

void rt_interrupt_leave_sethook(void (*hook)(void))
{
    rt_interrupt_leave_hook = hook;
}

3. 线程通信配置项

  • 线程间同步和通信部分,此部分将使用的对象是信号量、互斥锁、事件、邮箱、消息队列、信号等。
/* Define this macro to enable the use of semaphores, if not defined, close. */
#define RT_USING_SEMAPHORE

/* Define this macro to enable the use of mutexes, if not defined, close. */
#define RT_USING_MUTEX

/* Define this macro to enable the use of events, if not defined, close. */
#define RT_USING_EVENT

/* Define this macro to enable the use of mailboxes, if not defined, close. */
#define RT_USING_MAILBOX

/* Define this macro to enable the use of message queues, if not defined, close. */
#define RT_USING_MESSAGEQUEUE

/* Define this macro to enable the use of signals, if not defined, close. */
#define RT_USING_SIGNALS
  • 开启 RT_USING_SEMAPHORE 等配置后,相关的功能才能使用,rt_sem_init 等一系列IPC对象相关的函数才能引用

4. 内存管理配置

/* Start the use of static memory pool */
#define RT_USING_MEMPOOL

/* Define this macro to start the concatenation of two or more memory heap , if not defined, close. */
#define RT_USING_MEMHEAP

/* Start algorithm for small memory management */
#define RT_USING_SMALL_MEM

/* Turn off SLAB memory management algorithm */
/* #define RT_USING_SLAB */

/* Start the use of heap */
#define RT_USING_HEAP
  • RT_USING_MEMPOOL 使能静态内存池
  • RT_USING_MEMHEAP 使能内存池堆
  • RT_USING_SMALL_MEM 使能小内存堆
  • RT_USING_HEAP 使能堆,使用 rt_system_heap_init 初始化,用于支持 malloc 、free 等函数
#ifdef RT_USING_HEAP
    /* initialize memory system */
    rt_kprintf("heap: [0x%08x - 0x%08x]\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
    rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
#endif

5. 内核设备对象配置

```c
/* Indicates the start of useing system devices */
#define RT_USING_DEVICE

/* Define this macro to start the use of system console devices, if not defined, close. */
#define RT_USING_CONSOLE
/* Define the buffer size of the console device. */
#define RT_CONSOLEBUF_SIZE 128
/* Name of the console device. */
#define RT_CONSOLE_DEVICE_NAME "uart1"
  • 使能 RT_USING_DEVICE 后,内核能够创建一系列 I/O 设备,方便各类应用调用设备驱动功能
#ifdef RT_USING_DEVICE
static char *const device_type_str[RT_Device_Class_Unknown] =
{
    "Character Device",
    "Block Device",
    "Network Interface",
    "MTD Device",
    "CAN Device",
    "RTC",
    "Sound Device",
    "Graphic Device",
    "I2C Bus",
    "USB Slave Device",
    "USB Host Bus",
    "USB OTG Bus",
    "SPI Bus",
    "SPI Device",
    "SDIO Bus",
    "PM Pseudo Device",
    "Pipe",
    "Portal Device",
    "Timer Device",
    "Miscellaneous Device",
    "Sensor Device",
    "Touch Device",
    "Phy Device",
    "Security Device",
    "WLAN Device",
    "Pin Device",
    "ADC Device",
    "DAC Device",
    "WDT Device",
    "PWM Device",
};
...
  • RT_USING_CONSOLE 使能控制台内核设备,内核可以调用 rt_kprintf 等接口向控制台(比如串口)输出信息
#ifndef RT_USING_CONSOLE
#define rt_kprintf(...)
#define rt_kputs(str)
#else
int rt_kprintf(const char *fmt, ...);
void rt_kputs(const char *str);
#endif
  • RT_CONSOLEBUF_SIZE 指定了控制台 Prompt 支持输入的字符数
  • RT_CONSOLE_DEVICE_NAME 指定了控制台关联设备的字符串,rt_console_set_device 会通过这个字符串找到输入/输出内核设备的控制块,支持输入/输出功能
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
    /* set console device */
    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif

6. 自动初始化配置

/* Define this macro to enable automatic initialization mechanism, if not defined, close. */
#define RT_USING_COMPONENTS_INIT

/* Define this macro to set application entry as main function */
#define RT_USING_USER_MAIN
/* Define the stack size of the main thread */
#define RT_MAIN_THREAD_STACK_SIZE 2048
  • RT_USING_COMPONENTS_INIT 使能组件初始化
  • RT_USING_USER_MAIN 打开后,会在 rtthread_startup 里调用 rt_application_init 和 rt_hw_board_init 等应用代码和板级支持包中实现的初始化函数
  • RT_MAIN_THREAD_STACK_SIZE 指定了 main 线程的堆栈大小
#ifdef RT_USING_USER_MAIN

void rt_application_init(void);
void rt_hw_board_init(void);
int rtthread_startup(void);
...

7. FishSH 配置

/* Define this macro to start the use of the system FinSH debugging tool, if not defined, close. */
#define RT_USING_FINSH

/* While starting the system FinSH: the thread name is defined as tshell */
#define FINSH_THREAD_NAME "tshell"

/* While turning the system FinSH: use history commands. */
#define FINSH_USING_HISTORY
/* While turning the system FinSH: define the number of historical command lines. */
#define FINSH_HISTORY_LINES 5

/* While turning the system FinSH: define this macro to open the Tab key, if not defined, close. */
#define FINSH_USING_SYMTAB

/* While turning the system FinSH: define the priority of the thread. */
#define FINSH_THREAD_PRIORITY 20
/* While turning the system FinSH:define the stack size of the thread. */
#define FINSH_THREAD_STACK_SIZE 4096
/* While turning the system FinSH:define the length of command character. */
#define FINSH_CMD_SIZE 80

/* While turning the system FinSH: define this macro to enable the MSH function. */
#define FINSH_USING_MSH
/* While turning the system FinSH:when MSH function is enabled, macro is defined to use the MSH function by default. */
#define FINSH_USING_MSH_DEFAULT
/* While turning the system FinSH:define this macro to use only the MSH function. */
#define FINSH_USING_MSH_ONLY
  • RT_USING_FINSH 内核使用 FishSH 作为控制台,finish/cmd.c 中的代码都需要先使能这个配置才能使用
  • FINSH_THREAD_NAME 指定了运行 FishSH 的线程,FINSH_THREAD_PRIORITY 指定了 FishSH 线程的优先级,FINSH_THREAD_STACK_SIZE 指定了线程堆栈大小
  • FINSH_USING_HISTORY 是否支持使用历史命令,FINSH_HISTORY_LINES 是 记住历史命令的数目
  • FINSH_USING_SYMTAB 使用 Tab 键显示 Help 信息
  • FINSH_CMD_SIZE 指定了 FinSH 支持命令字符的最大长度
  • FINSH_USING_MSH 关联 Msh 命令风格,具体定义在 fal\fal_rtt.c 中

8. 板级配置

  • 定义板子、Soc的类型,以及其他 BSP 中使用的配置
#define TARGET_E2000D
#define TARGET_E2000
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值