Feedback
Feedback

If you are having issues with the exercises, please create a ticket on DevZone: devzone.nordicsemi.com
Drag & Drop Files, Choose Files to Upload 您最多可以上传 2 个文件。
  • 简体中文
    Eng
    简体中文
  • 练习 2 – 自定义应用程序

    自定义应用程序

    在应用程序开发过程中,为您的特定应用程序自定义 nRF Connect SDK 的各个方面非常有用,且无需修改 SDK 文件本身。

    在本练习中,我们将通过添加自定义文件、配置和修改设备树来自定义我们的应用程序。

    练习步骤

    使用之前的练习作为起点。 将之前完成的练习复制到一个新目录并命名为 l3_e2。请务必删除 build 文件夹。

    添加自定义文件

    1. 创建一个 .c 文件和一个 .h 文件,位置与 main.c 文件相同(在 src 文件夹内),并将它们命名为 myfunction.c 和 myfunction.h.

    2.1 在 myfunction.c 文件中定义函数 sum(),并确保包含头文件。

    #include "myfunction.h"
    
    int sum(int a, int b){
        return a+b;
    }
    C

    2.2 然后在 myfunction.h 头文件中声明该函数。

    #ifndef MY_FUNCTION_H
    #define MY_FUNCTION_H
    
    int sum(int a, int b);
    
    #endif
    C

    前两行和最后几行被称为包含卫士 (include guards)。

    定义

    包含卫士:一种构造(在本例中为宏),用于避免重复包含的问题。如果头文件被包含两次,就会发生重复包含,从而导致内容无效。

    3. 将自定义文件包含在构建中。

    为了将自定义文件包含在构建中,我们使用 CMake 函数 target_sources()。将以下行添加到 CMakeLists.txt

    target_sources(app PRIVATE src/myfunction.c)
    CMake

    4. 包含自定义函数的头文件。

    现在文件已包含在构建中,我们只需要在 main.c 中包含头文件即可运行该函数。

    #include "myfunction.h"
    C

    5. 替换 main() 以运行自定义函数。

    修改 main() 以运行我们定义的函数 sum()。

    int main(void)
    {
    	int a = 3, b = 4;
    	while(1){
    		printk("The sum of %d and %d is %d\n", a, b, sum(a,b));
    		k_msleep(1000);
    	}
    }
    C

    6. 构建应用程序并将其烧录到您的开发板。

    打开终端输出,您应该会看到以下内容。

    *** Booting nRF Connect SDK ***
    *** Using Zephyr OS ***
    The sum of 3 and 4 is 7
    The sum of 3 and 4 is 7
    The sum of 3 and 4 is 7
    The sum of 3 and 4 is 7
    The sum of 3 and 4 is 7
    The sum of 3 and 4 is 7
    Terminal

    通过 target_sources() 包含源代码的问题在于,无论我们是否使用该文件,都会将其包含在构建中。在下一段中,我们将学习如何使用 Kconfig 符号和 target_sources_ifdef() 来控制源代码的包含。

    添加自定义配置

    6. 定义一个用于启用 myfunction 的自定义 Kconfig。

    现在,让我们定义自己的配置,它将决定我们的自定义文件是否被包含在构建中。为此,在应用程序目录(与 CMakeLists.txt 和 prj.conf 相同的位置)中创建一个名为 Kconfig 的文件。

    确保该文件没有文件扩展名。根据您的编辑器,可能会默认添加扩展名,必须手动删除。

    source "Kconfig.zephyr"
    
    config MYFUNCTION
    	bool "Enable my function"
    	default n
    Kconfig

    第一行引入了 Kconfig.zephyr,这在定义新的 Kconfig 文件以引入 Zephyr RTOS 配置时是必需的。接下来的三行将配置 CONFIG_MYFUNCTION 定义为布尔变量,并将其默认值设置为 n。

    如果您有兴趣了解更多关于在 Kconfig 中创建菜单的信息,这里有一个包含更多详情的文档链接。

    7. 使自定义文件的添加取决于 Kconfig 条件。

    在 CMakeLists.txt 中,我们希望自定义文件的添加是可选的。注释掉第 3 步中的行,并使用函数 target_sources_ifdef() 添加以下行,如下所示:

    target_sources_ifdef(CONFIG_MYFUNCTION app PRIVATE src/myfunction.c)
    CMake

    现在,只有在启用 CONFIG_MYFUNCTION 的情况下,构建才会包含自定义文件 myfunction.c。

    注意

    这种策略在 nRF Connect SDK 中被广泛使用,以仅包含您计划在项目中使用的库源代码。

    这是为了限制应用程序的大小。只有当您启用相关配置时,模块和子系统才会包含在构建中,从而允许您根据需要保持应用程序尽可能小。

    8. 为 myfunction 启用 Kconfig。

    通过将以下行添加到 prj.conf 来启用配置:

    CONFIG_MYFUNCTION=y
    Kconfig

    9. 更新您的 main.c 文件,以便它可以检查 Kconfig 符号是否已启用/禁用

    9.1 在包含头文件之前检查 CONFIG_MYFUNCTION 。

    #ifdef CONFIG_MYFUNCTION
    #include "myfunction.h"
    #endif
    C

    9.2 在调用 sum() 之前检查 CONFIG_MYFUNCTION 。

    int main(void)
    {
    
    	while (1) {
    #ifdef CONFIG_MYFUNCTION
    		int a = 3, b = 4;
    		printk("The sum of %d and %d is %d\n", a, b, sum(a, b));
    #else
    		printk("MYFUNCTION not enabled\n");
    		return 0;
    #endif
    		k_msleep(1000);
    	}
    	return 0;
    }
    C

    10. 构建应用程序并将其烧录到您的开发板,您应该会看到以下输出。

    *** Booting nRF Connect SDK ***
    *** Using Zephyr OS ***
    The sum of 3 and 4 is 7
    The sum of 3 and 4 is 7
    The sum of 3 and 4 is 7
    The sum of 3 and 4 is 7
    The sum of 3 and 4 is 7
    The sum of 3 and 4 is 7
    Terminal

    11. 尝试在 prj.conf 中禁用 Kconfig 符号。

    11.1 在 prj.conf 文件中,将第一行更改为 CONFIG_MYFUNCTION=n

    11.2 像之前一样构建并烧录应用程序。

    您应该会看到以下日志输出。

    *** Booting nRF Connect SDK ***
    *** Using Zephyr OS ***
    MYFUNCTION not enabled
    Terminal

    11.3 重新启用 CONFIG_MYFUNCTION 符号 (CONFIG_MYFUNCTION=y),因为我们在下一节“修改设备树”中需要它。

    修改设备树

    在本节中,我们将通过更改向控制台发送信息的波特率(速度),仅针对此应用程序修改设备的设备树。为特定应用程序更改硬件描述(设备树)是使用设备树覆盖文件 (devicetree overlay files)完成的。

    12. 在应用程序目录中创建一个覆盖文件,名称为您正在使用的目标板名称。

    这里我们有两个选项。根据您的喜好选择选项 1 或选项 2。

    选项 1 – 手动创建设备树覆盖文件

    在应用程序目录(与 CMakeLists.txt 和 prj.conf 相同的位置)中,创建一个名为 boards 的目录。在 boards 目录中,创建一个以您正在使用的开发板命名的覆盖文件,在我们的例子中是 nrf52833dk_nrf52833.overlay。主要规则是文件名必须与目标板名称相同,并且文件必须以 .overlay 结尾,例如 <board_target>.overlay。

    请注意,如果您使用的是具有多个目标的设备(例如 nRF54L15 DK、nRF9151 DK),请确保使用目标板名称 (board target),而不是开发板名称 (board name)。例如使用 nrf54l15dk_nrf54l15_cpuapp.overlay,而不是 nrf54l15dk_nrf54l15dk.overlay(后者将不起作用)。

    选项 2 – 使用 nRF Connect for VSCode 扩展创建设备树覆盖文件

    在 nRF Connect for VS Code 中,有一个选项可以创建与构建所用的目标板名称相同的覆盖文件,如下图所示。请务必先选择应用程序上下文 (1)。然后打开 Config files – > Devicetree 以显示 + Create overlay file (2) 选项。此过程在此处有进一步说明。

    13. 更改 UART 节点的波特率。

    我们要更改打印到控制台时使用的 UART 实例的波特率,即 UART0(对于 nRF54L15 和 nRF54LM20 为 UART20)。波特率是 nrf-uart 绑定中的属性 current-speed,其定义和指定在 nrf-uart-common.yaml. 将以下内容添加到覆盖文件(位于应用程序的根目录中)以更改此属性:

    其他开发板 (DK)
    nRF54LC10 DK
    其他 nRF54L 系列 DK
    &uart20 {
    	current-speed = <9600>;
    };
    Devicetree

    设备树中其他常见的修改项包括外设使用的引脚(rx、tx, cts 等)以及状态(okay、disabled)。

    设置设备树覆盖文件有不同的方法。更多详情可以在这里找到:设置设备树覆盖。

    14. 进行全新构建 (pristine build) 并将应用程序烧录到开发板。

    在 Actions 窗口中,选择 Build action 右侧的此图标以进行全新构建。

    如果此图标未出现,您也可以调用 VS Code 的命令面板(Windows 中为 Ctrl + Shift + P)并搜索 Pristine Build 来触发它。

    定义

    全新构建 (Pristine build):创建一个新的构建目录。之前构建的所有副产品都已被移除。

    为了确认设备树已更改,我们可以查看编译后的设备树输出。

    这可以通过调用 VS Code 的命令面板(Windows 中为 Ctrl + Shift + P)并输入命令 nRF DeviceTree: Open Compiled Output 来完成。在编译后的设备树文件中,搜索节点名称 uart0 或 uart20(取决于您的目标板)(1) 并在设备树中找到该节点 (2)。在这里我们可以看到 current-speed 已更改为覆盖文件中设置的值 (3)。

    该文件也可以在以下路径找到: l3_e2/build/l3_e2/zephyr/zephyr.dts

    您也可以打开 Devicetree Visual Editor (请务必先选择应用程序上下文)并导航到 soc-> uart0 (或 uart20)来检查此节点的属性。对于多核 SoC,它将是 soc->peripheral->uart0(或 uart20)。Devicetree Visual Editor 需要编译后的应用程序来处理项目的设备树结构。

    注意

    如果 DeviceTree 窗口在 VS Code 中不可见,这意味着您没有在 VS Code 中安装 nRF DeviceTree 扩展。请务必通过转到“扩展”并搜索 nRF Devicetree 来安装它。nRF DeviceTree 也是 nRF Connect for VS Code Extension Pack 的一部分。

    15. 观察串口终端是否没有任何输出。

    这是因为我们将应用程序中的波特率更改为 9600 baud/sec,而终端仍在使用默认的 115200 baud/sec 波特率。这意味着串口终端正尝试以错误的速度读取日志输出。

    16. 更改串口终端中的波特率。

    1. 关闭并打开一个新终端。

    1. 关闭当前终端
    2. 为同一个 COM 端口打开一个新终端

    2. 将波特率更改为 9600。

    1. 在窗口顶部出现的菜单中,选择右侧的齿轮以“更改端口设置”。
    2. 选择 [Other]
    3. 选择 9600 以更改波特率

    对于其余设置:

    • 输入数据位:8
    • 输入停止位:1
    • 选择校验位:None
    • 选择流控制:RTSCTS

    3. 观察日志输出。

    在 nRF Serial Terminal 中看到的输出

    1. 将波特率更改为 9600。

    1. 选择 Serial Settings 以获取所有可配置选项的下拉列表
    2. 您必须断开与端口的连接 才能配置终端
    3. 选择波特率下的下拉菜单
    4. 选择 9600 以更改速度。

    2. 连接到设备。

    选择“连接到端口”以使用当前设置连接到设备

    3. 观察日志输出。

    在串口终端应用中看到的输出

    17. Devicetree Visual Editor(延伸阅读)。

    一旦我们有了应用程序的设备树覆盖和构建应用程序,我们现在就可以使用 Devicetree Visual Editor,它允许我们使用直观的 GUI 编辑设备树结构。

    通过 DeviceTree 可视化编辑器,我们还可以探索每个节点中的可用属性,并直接使用可视化编辑器修改条目。重要的是要了解 Devicetree 可视化编辑器和设备树文本编辑器方法是可以互换的。因此,它是学习 Devicetree 语法的一个很好的工具。

    我们可以从 Actions 视图访问 Devicetree 可视化编辑器:

    请参阅下面的插图,显示如何使用 Devicetree Visual Editor 设置以下 UART 配置:

    • 硬件流控制:启用 (rtscts: on)
    • 波特率:115200
    • 数据位:8
    • 停止位:1
    • 校验位:none

    请注意,Devicetree 可视化编辑器正在为您填充 Devicetree 覆盖文件,而无需记住 Devicetree 的语法。

    本练习的解决方案可以在 GitHub 存储库 l3/l3_e2_sol 中找到。

    Switch language?

    Progress is tracked separately for each language. Switching will continue from your progress in that language or start fresh if you haven't begun.

    Your current progress is saved, and you can switch back anytime.

    Register an account
    Already have an account? Log in
    (All fields are required unless specified optional)

    • 8 or more characters
    • Upper and lower case letters
    • At least one number or special character

    Forgot your password?
    Enter the email associated with your account, and we will send you a link to reset your password.