1700 字
9 分钟
在Nordic nRF52项目中使用CMake

转载自外网,原文链接:https://www.nrbtech.io/blog/2020/1/4/using-cmake-for-nordic-nrf52-projects

CMake 是一款流行的 C/C++ 构建系统(根据其官网描述,它是一个“开源的、跨平台的工具家族,旨在构建、测试和打包软件”),我们在 NRB Tech 将其用于固件项目和跨平台库​。CMake 也可与优秀的 C/C++ ​集成开发环境(IDE)CLion​ 配合使用。Nordic 官方推荐并支持 Segger Embedded Studio 作为其首选 IDE,然而 CMake 能使依赖管理和单元测试变得更为简便。

例如,NRB Tech 常用的一种开发架构是:在固件、实用工具和应用程序之间共享一个或多个 C 语言库,以减少代码重复和错误,并确保关键代码得到充分的单元测试。使用 CMake 可以轻松管理此类库,根据需要生成 ​Makefile​ 或 ​Xcode 项目,并将其作为依赖项集成到其他 CMake 项目中。

Nordic 在其 ​SDK​ 中并未直接提供对 CMake 的支持,但它们的 ​Mesh SDK​ 使用了 CMake,这就让基于 Nordic SDK 的非 Mesh 项目使用CMake成为可能。

nRF5 CMake 脚本#

Nordic的Mesh SDK并非为构建外部的、自定义的非Mesh项目而设计,但通过一些外部支持,它可以用于此目的——这正是我们的 nRF5-cmake-scripts 项目所实现的:尽可能复用Mesh SDK的脚本,同时为其他所有功能定义自己的函数,包括添加Nordic Mesh SDK不具备的特性(例如添加引导加载程序目标和创建DFU软件包)。该项目还定义了可轻松集成Nordic SDK中众多库的函数。现在让我们尝试从头开始创建一个新项目。

环境搭建#

如果你使用的是Mac系统,你可以使用homebrew:

Terminal window
brew tap ArmMbed/homebrew-formulae
brew install arm-none-eabi-gcc

创建基于CMake的Nordic固件项目#

最终的项目可在 此处查看

首先,在终端/命令窗口中克隆 基础项目 以设置项目结构:

Terminal window
git clone --recurse-submodules https://github.com/NRB-Tech/nRF5-cmake-scripts-example-base.git .

运行一个脚本来清理项目,以便您自己使用(在Windows上,通过右键单击目录 > “Git Bash here”来在Git Bash中运行):

Terminal window
# 确保文件有可执行权限
chmod +x ./cleanup.sh
./cleanup.sh

执行下面命令,它会拷贝示例项目中的CMakeLists.txt到当前目录:

Terminal window
cmake -E copy nRF5-cmake-scripts/example/CMakeLists.txt .

请注意:您可能还需要根据您的平台编辑此文件中的某些变量,假如 NRFJPROG、MERGEHEX、NRFUTIL 和 PATCH_EXECUTABLE 这些工具未配置在系统的 PATH 环境变量中,则需要手动指定它们的完整路径。

然后我们可以用脚本来下载依赖:

Terminal window
cmake -B cmake-build-download -G "Unix Makefiles" .
# Windows上使用:
# cmake -B cmake-build-download -G "MinGW Makefiles" .
cmake --build cmake-build-download/ --target download

从 SDK 示例项目中复制一些文件(对于 nRF52840 DK 开发板,请将 pca10040/s132 替换为 pca10056/s140):

Terminal window
cmake -E copy toolchains/nRF5/nRF5_SDK_16.0.0_98a08e2/examples/ble_peripheral/ble_app_template/pca10040/s132/armgcc/ble_app_template_gcc_nrf52.ld src/gcc_nrf52.ld
cmake -E copy toolchains/nRF5/nRF5_SDK_16.0.0_98a08e2/examples/ble_peripheral/ble_app_template/pca10040/s132/config/sdk_config.h src/

此时,您可以在 CLion 或您选择的任意编辑器中打开项目并进行文件编辑、添加文件并编写源代码。

这里我们在 src/main.c 中添加一段简单的日志输出代码:

#include "nrf_log_default_backends.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
int main(void) {
ret_code_t err_code = NRF_LOG_INIT(NULL);
APP_ERROR_CHECK(err_code);
NRF_LOG_DEFAULT_BACKENDS_INIT();
NRF_LOG_INFO("Hello world");
while(true) {
// do nothing
}
}

创建一个 src/app_config.h 文件,用于覆盖 sdk_config.h 中的部分默认配置:

#define NRF_LOG_BACKEND_RTT_ENABLED 1 // 开启RTT
#define NRF_LOG_BACKEND_UART_ENABLED 0 // 关闭UART
#define NRF_LOG_DEFERRED 0 // 立即刷新日志
#define NRF_LOG_ALLOW_OVERFLOW 0 // 不打印溢出日志
#define SEGGER_RTT_CONFIG_DEFAULT_MODE 2 // 阻塞直到处理完成

我们还需要集成 DFU 引导加载程序,因此需要生成密钥。请在终端/命令提示符中执行以下操作:

Terminal window
nrfutil keys generate keys/dfu_private.key
nrfutil keys display --key pk --format code keys/dfu_private.key --out_file keys/dfu_public_key.c

现在我们需要创建 src/CMakeLists.txt 文件来构建我们的目标项目。

Terminal window
set(NRF5_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/gcc_${NRF_FAMILY})
# DFU 配置
# 列出之前使用过的softdevice版本,若没有,则使用“FALSE”
set(PREVIOUS_SOFTDEVICES FALSE)
# 设置DFU密钥位置
set(PRIVATE_KEY ${CMAKE_CURRENT_SOURCE_DIR}/../keys/dfu_private.key)
set(PUBLIC_KEY ${CMAKE_CURRENT_SOURCE_DIR}/../keys/dfu_public_key.c)
# 设置应用验证类型 [NO_VALIDATION|VALIDATE_GENERATED_CRC|VALIDATE_GENERATED_SHA256|VALIDATE_ECDSA_P256_SHA256]
set(APP_VALIDATION_TYPE NO_VALIDATION)
# 设置SoftDevice验证类型. [NO_VALIDATION|VALIDATE_GENERATED_CRC|VALIDATE_GENERATED_SHA256|VALIDATE_ECDSA_P256_SHA256]
set(SD_VALIDATION_TYPE NO_VALIDATION)
# 引导加载程序版本(用户定义)
set(BOOTLOADER_VERSION 1)
# DFU 版本 (固件版本) 字符串
set(DFU_VERSION_STRING "${VERSION_STRING}")
# 设置Target名称
set(target example)
# 添加此示例所需的库
nRF5_addLog()
nRF5_addSeggerRTT()
nRF5_addAppError()
# include files
list(APPEND SOURCE_FILES
main.c
)
list(APPEND INCLUDE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}"
)
nRF5_addExecutable(${target} "${SOURCE_FILES}" "${INCLUDE_DIRS}" "${NRF5_LINKER_SCRIPT}")
# sdk_config.h 导入 app_config.h
target_compile_definitions(${target} PRIVATE USE_APP_CONFIG)
# 处理BootLoader中的用户预定义变量
set(bootloader_vars "")
# add the secure bootloader build target
nRF5_addSecureBootloader(${target} "${PUBLIC_KEY}" "${bootloader_vars}")
# add the bootloader merge target
nRF5_addBootloaderMergeTarget(${target} ${DFU_VERSION_STRING} ${PRIVATE_KEY} ${PREVIOUS_SOFTDEVICES} ${APP_VALIDATION_TYPE} ${SD_VALIDATION_TYPE} ${BOOTLOADER_VERSION})
# add the bootloader merged flash target
nRF5_addFlashTarget(bl_merge_${target} "${CMAKE_CURRENT_BINARY_DIR}/${target}_bl_merged.hex")
# Add the Bootloader + SoftDevice + App package target
nRF5_addDFU_BL_SD_APP_PkgTarget(${target} ${DFU_VERSION_STRING} ${PRIVATE_KEY} ${PREVIOUS_SOFTDEVICES} ${APP_VALIDATION_TYPE} ${SD_VALIDATION_TYPE} ${BOOTLOADER_VERSION})
# Add the App package target
nRF5_addDFU_APP_PkgTarget(${target} ${DFU_VERSION_STRING} ${PRIVATE_KEY} ${PREVIOUS_SOFTDEVICES} ${APP_VALIDATION_TYPE})
# print the size of consumed RAM and flash - does not yet work on Windows
if(NOT ${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows")
nRF5_print_size(${target} ${NRF5_LINKER_SCRIPT} TRUE)
endif()

至此,我们已经准备好构建并运行示例项目。首先,请运行 JLink 工具以获取 RTT 输出:

Terminal window
cmake -Bcmake-build-debug -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug .
# Windows,使用:
# cmake -B cmake-build-debug -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Debug .
# 如果报编译器未找到的错误,请确保环境变量配置正确 (运行 `arm-none-eabi-gcc` 来检查是否已配置正确)
cmake --build cmake-build-debug/ --target START_JLINK_RTT

接下来,构建并烧录目标固件:

Terminal window
cmake --build cmake-build-debug/ --target flash_bl_merge_example

您现在应该能在 RTT 控制台中看到 “Hello world” 日志输出了!至此,您可以通过 nRF5-cmake-scripts/includes/libraries.cmake 文件中提供的宏来添加源代码并集成 SDK 库。

NRB Tech 运用 CMake 构建经过充分测试的产品,并充分利用跨平台代码的优势。如果您正在规划新产品开发,或希望参与多样化的跨平台产品研发,欢迎 与我们联系

一些关联的项目#

你可以将以下代码另存为nrf5-sdk-to-clion.sh,然后放在nRF5 SDK根目录执行。

它会为所有SDK中的实例项目创建好CMakeList.txt文件:

#!/usr/bin/env bash
#Copyright 2017 Jumper Labs Ltd.
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
set -e
tmp_makefile="/tmp/CMakeLists-generator.mk"
\cat << 'EOF' > ${tmp_makefile}
include Makefile
generate:
$(foreach var, PROJECT_NAME SDK_ROOT PROJ_DIR SRC_FILES INC_FOLDERS CFLAGS CXXFLAGS, \
echo "set($(var) $($(var)))" ; \
echo ; \
)
@echo 'cmake_minimum_required(VERSION 2.4.0)'
@echo 'project($$$ {PROJECT_NAME})'
@echo 'list(APPEND CFLAGS "-undef" "-D__GNUC__")'
@echo 'list(FILTER CFLAGS EXCLUDE REGEX mcpu)'
@echo 'string(REPLACE ";" " " CFLAGS "$$$ {CFLAGS}")'
@echo 'set(CMAKE_C_FLAGS $$$ {CFLAGS})'
@echo 'include_directories($$$ {INC_FOLDERS})'
@echo 'add_executable($$$ {PROJECT_NAME} $$$ {SRC_FILES})'
EOF
\echo "cmake_minimum_required(VERSION 2.8.9)" > CMakeLists.txt
for makefile in `\find ./examples -name Makefile` ; do
dir=`\dirname ${makefile}`
\echo "Creating CMakeLists.txt for ${makefile}"
\pushd ${dir} > /dev/null
\make -s -f ${tmp_makefile} generate > CMakeLists.txt
\popd > /dev/null
\echo "#add_subdirectory(${dir})" >> CMakeLists.txt
done
\rm ${tmp_makefile}
echo '************************************'
echo 'Enjoy using CLION with the NRF5-SDK!'
echo '************************************'
在Nordic nRF52项目中使用CMake
https://martinlevine.vercel.app/posts/using-cmake-for-nrf52-projects/
作者
404 Not Found.
发布于
2025-09-04
许可协议
CC BY-NC-SA 4.0