Edit online

Kernel 配置

20 Dec 2024
Read time: 3 minute(s)
如需使用 Dynamic Module 功能,需要在内核中打开以下配置:
  1. 启用 POSIX 文件系统和 I/O
    Rt-Thread options --->
        RT-Thread Components --->
            C/C++ and POSIX layer --->
                POSIX (Portable Operating System Interface) layer --->
                    [*] Enable POSIX file system and I/O
  2. 启用动态模块 API:
    Rt-Thread options --->
        RT-Thread Components --->
            C/C++ and POSIX layer --->
                POSIX (Portable Operating System Interface) layer --->
                    [*] Enable dynamic module APIs, dlopen()/dlsym()/dlclose() etc
  3. 如有需要,可以选择 dm-app 动态加载时使用的内存堆 (heap),否则可跳过此步。

    具体的可选堆会随不同平台的配置有所不同:
    Rt-Thread options  --->
        RT-Thread Components  --->
            C/C++ and POSIX layer  --->
                POSIX (Portable Operating System Interface) layer  --->
                    [*] Enable dynamic module APIs, dlopen()/dlsym()/dlclose() etc
                        Select dynamic module use mem (Prsam CMA heap)  --->
                            (X) Sys Heap
                            ( ) Prsam CMA heap

符号导出

Kernel 中被 dm-app 访问到的符号需要使用 RTM_EXPORT() 宏来进行声明,类似 Linux 中的 EXPORT_SYMBOL() 宏。

  • 对于一些标准的 C 库函数,dm-app 可以直接使用 Kernel 中已经定义好的 RTM_EXPORT() 声明,例如 luban-lite/kernel/rt-thread/components/libc/posix/libdl/dlsyms.c
    RTM_EXPORT(strcpy);
    RTM_EXPORT(strncpy);
    RTM_EXPORT(strlen);
    RTM_EXPORT(strcat);
    RTM_EXPORT(strstr);
    RTM_EXPORT(strchr);
    RTM_EXPORT(strcmp);
    RTM_EXPORT(strtol);
    RTM_EXPORT(strtoul);
    RTM_EXPORT(strncmp);
    ...
  • 对于 RT-Thread API 函数,dm-app 可以直接使用 Kernel 中已经定义好的 RTM_EXPORT() 声明,例如 luban-lite/kernel/rt-thread/src/thread.c
    RTM_EXPORT(rt_thread_create);
    RTM_EXPORT(rt_thread_yield);
    RTM_EXPORT(rt_thread_startup);
    RTM_EXPORT(rt_thread_detach);
    ...
  • 用户可以使用下列命令查看当前系统中使用 RTM_EXPORT() 声明的符号:
    list_symbols
    系统输出结果示例如下:
    rt_critical_level=> 0x40013cc0
    rt_exit_critical=> 0x40014090
    rt_enter_critical=> 0x40013ce0
    rt_device_set_tx_complete=> 0x40014220
    rt_device_set_rx_indicate=> 0x40014200
    rt_device_control=> 0x400141f0
    rt_device_write=> 0x40014370
    rt_device_read=> 0x40014330
    rt_device_close=> 0x400143b0
    重要:

    未使用 RTM_EXPORT() 声明的 Kernel 函数无法在 dm-app 中使用。如需在 dm-app 中使用自定义的 Kernel 函数,必须使用 RTM_EXPORT() 声明。

GCC low-level 函数的符号导出

在加载 dm-app 时,可能会遇到找不到某些 GCC low-level runtime library 中的函数符号的情况,如 __floatdidf __umoddi3__udivdi3__fixdfdi。这些函数是 GCC 基础运算库的一部分,用于实现 CPU 原生硬件指令无法完成的操作。例如,在 32bit 系统中实现 64bit (long long) 类型数据的除法,GCC 就会自动调用软件函数 __umoddi3 来实现。具体原理可以参考The GCC low-level runtime library

执行以下操作步骤,可解决这种问题:

  1. 使用以下命令,在工具链中找出函数的原型声明:
    grep -r -A1 __umoddi3 luban-lite/toolchain/
    toolchain/share/info/gccint.info: -- Runtime Function: unsigned long __umoddi3 (unsigned long A,
    toolchain/share/info/gccint.info-          unsigned long B)
  2. 在 Kernel 中使用 RTM_EXPORT() 给函数加上符号导出声明:
    extern unsigned long __umoddi3 (unsigned long a, unsigned long b);
    RTM_EXPORT(__umoddi3);
    extern unsigned long __udivdi3 (unsigned long a, unsigned long b);
    RTM_EXPORT(__udivdi3);
    extern double __floatdidf (long i);
    RTM_EXPORT(__floatdidf);
    extern long __fixdfdi (double a);
    RTM_EXPORT(__fixdfdi);