对我来说,使用像keil这样的远古开发环境是一种折磨。如今,各大单片机厂商都发布了GCC适配的SDK,使在linux下的开发更为方便快捷。但在智能车竞赛领域,似乎没有人研究Cmake作为单片机构建系统,本篇博客详细地介绍了智能车逐飞开源库的移植使用,发挥其简单易用的优势,同时为各位车友带来更为舒适的开发体验。

0-获取SDK及工具链

SDK

NXP SDK Builder
搜索芯片型号,点击BUILD SDK

选择开发平台及工具链,这里选择Linux和ARM GCC

点击BUILD SDK后,直接下载或去SDK Dashboard下载

工具链

GCC ARM下载此链接为直链下载,若失效请自行搜索arm gcc官网下载即可。

逐飞开源库

命令行下载

1
git clone https://gitee.com/seekfree/RT1064_Library

创建工作空间rt1064,按如下路径解压两个压缩包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
rt1064
├── Car-RT1064 <- 这个目录放项目源码
├── sdk
│   ├── boards
│   ├── CMSIS
│   ├── components
│   ├── COPYING-BSD-3
│   ├── devices
│   ├── docs
│   ├── LA_OPT_NXP_Software_License.txt
│   ├── middleware
│   ├── MIMXRT1064xxxxB_manifest_v3_14.xml
│   ├── rtos
│   ├── SDK_2_16_000_MIMXRT1064xxxxB.tar.gz
│   ├── SW-Content-Register.txt
│   └── tools
├── RT1064_Library
│   ├── Example
│   ├── Example-utf8
│   ├── LICENSE
│   ├── README.md
│   ├── SeekFree_RT1064_Opensource_Library
│   ├── SeekFree-utf8
│   ├── 【封装】核心板整体原理图封装+PCB封装
│   └── 【文档】说明书 芯片手册等
└── toolchain
└── gcc-arm-none-eabi-10.3-2021.10

至此,官方SDK以及编译工具链准备完成。

1-创建项目文件

从示例项目构建工程,复制

1
sdk/boards/evkmimxrt1064/demo_apps/led_blinky

到工作空间,将其重命名为Car-RT1064
删除不需要的文件,保留目录结构如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
led_blinky
├── armgcc <- 重命名为build
│   ├── build_flexspi_nor_debug.sh
│   ├── build_flexspi_nor_release.sh
│   ├── CMakeLists.txt
│   ├── config.cmake
│   ├── flags.cmake
│   ├── MIMXRT1064xxxxx_flexspi_nor.ld
│   ├── MIMXRT1064xxxxx_ram.ld
│   └── MIMXRT1064xxxxx_sdram.ld
├── board.c
├── board.h
├── clock_config.c
├── clock_config.h
├── dcd.c
├── dcd.h
├── led_blinky.c
├── pin_mux.c
└── pin_mux.h

按照个人习惯,build目录常作为编译中间文件临时目录,更改目录结构如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
led_blinky
├── build
├── build_flexspi_nor_debug.sh
├── build_flexspi_nor_release.sh
├── CMakeLists.txt
├── config.cmake
├── flags.cmake
├── include
│   ├── board.h
│   ├── clock_config.h
│   ├── dcd.h
│   └── pin_mux.h
├── MIMXRT1064xxxxx_flexspi_nor.ld
├── MIMXRT1064xxxxx_ram.ld
├── MIMXRT1064xxxxx_sdram.ld
└── src
├── board.c
├── clock_config.c
├── dcd.c
├── led_blinky.c
└── pin_mux.c

依次修改文件:
build_flexspi_nor_debug.sh
1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
# 添加以下两行设置编译器和SDK路径,按需修改
export ARMGCC_DIR=/home/user/rt1064/toolchain/gcc-arm-none-eabi-10.3-2021.10/
export SDK_DIR=/home/user/rt1064/sdk
cd build/
# 注意cmake命令变化,无需修改,build release调用频率较低参照此文件按需修改
cmake -DSdkRootDirPath=${SDK_DIR} -DCMAKE_TOOLCHAIN_FILE=${SDK_DIR}"/tools/cmake_toolchain_files/armgcc.cmake" -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=flexspi_nor_debug ..
make -j 2>&1 | tee build_log.txt
cd -
# 增加flash参数,使用pyocd烧录程序,自行搜索pyocd如何安装
if [[ $# -gt 0 && $1 == "flash" ]];then pyocd flash --erase chip --target mimxrt1064 flexspi_nor_debug/blink.elf; fi

CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 增加此行导出编译命令,供clangd等语言服务器使用
set(CMAKE_EXPORT_COMPILE_COMMANDS on)
# 修改输出固件文件名称,自定义烧录和调试时会用到
set(MCUX_SDK_PROJECT_NAME blink.elf)
add_executable(${MCUX_SDK_PROJECT_NAME}
"${ProjDirPath}/src/led_blinky.c"
"${ProjDirPath}/src/board.c"
"${ProjDirPath}/src/clock_config.c"
"${ProjDirPath}/src/pin_mux.c"
"${ProjDirPath}/src/dcd.c"
)
# 添加包含目录
target_include_directories(${MCUX_SDK_PROJECT_NAME} PRIVATE
${ProjDirPath}/include
$ENV{ARMGCC_DIR}/arm-none-eabi/include
)

执行
1
./build_flexspi_nor_debug.sh flash

稍等片刻,完成后核心板上的led会闪烁。
至此,一个官方库的项目就创建好了。

2-增加逐飞开源库

项目整合

官方代码适配keil且在windows下编写,在linux打开会乱码,因此将其转换为utf-8编码方便查阅注释文档。
转换工具仓库:GBK2UTF8
下载最新Release,解压缩,以绝对路径执行。

1
2
cd RT1064_Library/
~/Downloads/gbk2utf8_v1.0.4_Linux_x86_64/gbk2utf8 --from GBK --to UTF8 --src SeekFree_RT1064_Opensource_Library --dst Seekfree-utf8 --pattern "*.*"

复制RT1064_Library/SeekFree-utf8/libraries下zf_前缀的三个文件夹到之前创建的项目文件夹的lib目录下。
lib中创建files.cmake
1
2
3
4
5
6
7
8
9
10
11
12
set(zfLibDir ${ProjDirPath}/lib/)
target_include_directories(${MCUX_SDK_PROJECT_NAME} PUBLIC
${zfLibDir}/zf_common
${zfLibDir}/zf_components
${zfLibDir}/zf_device
${zfLibDir}/zf_driver
)
file(GLOB_RECURSE ZF_SRCS ${zfLibDir}/*.c)

target_sources(${MCUX_SDK_PROJECT_NAME} PRIVATE
${ZF_SRCS}
)

修改项目目录CMakeLists.txt,在约60行的位置增加
1
include(${ProjDirPath}/lib/files.cmake)

修复编译错误

1、fputc类型冲突

打开zf_common_debug.c,在353行将两个int32_t修改为int
2、找不到DTCM区域对齐宏函数

修改对应行为。但此内容暂时没有深究,因为个人不使用单片机上的摄像头,并且也没有找到GCC编译器下将图像缓冲区放到DTCM区并对齐的办法。这里仅声明对齐,对性能的影响未知。

1
2
uint8 ALIGN(64) mt9v03x_image1[MT9V03X_H][MT9V03X_W];
uint8 ALIGN(64) mt9v03x_image2[MT9V03X_H][MT9V03X_W];

所有有关摄像头的头文件均有类似的报错,请自行修改,修改时注意对齐大小。
3、找不到头文件

在对应文件找到报错这行,大写字母全部改为小写字母即可。
4、找不到头文件x2

基本不用sd卡,删除zf_driver_sdio.c/.h即可。若想使用需自己配置config.cmake,我试过了各种组合均因配置之间的依赖问题无法成功,请自行尝试。
注意: 头文件时请同步删除zf_common_headfile.h中对应行,不然会再次报错。
5、找不到头文件x3

同上,若无法解决,删!!!
放一份自用config.cmake,当遇到可解决的问题后会随时更新。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# config to select component, the format is CONFIG_USE_${component}
# Please refer to cmake files below to get available components:
# ${SdkRootDirPath}/devices/MIMXRT1064/all_lib_device.cmake

set(CONFIG_COMPILER gcc)
set(CONFIG_TOOLCHAIN armgcc)
set(CONFIG_USE_COMPONENT_CONFIGURATION false)
set(CONFIG_USE_driver_igpio true)
set(CONFIG_USE_driver_clock true)
set(CONFIG_USE_driver_common true)
set(CONFIG_USE_driver_gpt true)
set(CONFIG_USE_driver_pwm true)
set(CONFIG_USE_device_MIMXRT1064_CMSIS true)
set(CONFIG_USE_utility_debug_console true)
set(CONFIG_USE_component_lpuart_adapter true)
set(CONFIG_USE_component_serial_manager_uart true)
set(CONFIG_USE_component_serial_manager true)
set(CONFIG_USE_driver_lpuart true)
set(CONFIG_USE_component_lists true)
set(CONFIG_USE_device_MIMXRT1064_startup true)
set(CONFIG_USE_driver_iomuxc true)
set(CONFIG_USE_utility_assert true)
set(CONFIG_USE_driver_xip_device true)
set(CONFIG_USE_driver_xip_board_evkmimxrt1064 true)
set(CONFIG_USE_utilities_misc_utilities true)
set(CONFIG_USE_CMSIS_Include_core_cm true)
set(CONFIG_USE_utility_str true)
set(CONFIG_USE_device_MIMXRT1064_system true)
set(CONFIG_USE_driver_adc_12b1msps_sar true)
set(CONFIG_USE_driver_qtmr_1 true)
# Freertos
set(CONFIG_USE_middleware_freertos-kernel_heap_4 true)
set(CONFIG_USE_middleware_freertos-kernel true)
set(CONFIG_USE_middleware_freertos-kernel_template true)
set(CONFIG_USE_middleware_freertos-kernel_extension true)
set(CONFIG_CORE cm7f)
set(CONFIG_DEVICE MIMXRT1064)
set(CONFIG_BOARD evkmimxrt1064)
set(CONFIG_KIT evkmimxrt1064)
set(CONFIG_DEVICE_ID MIMXRT1064xxxxA)
set(CONFIG_FPU DP_FPU)
set(CONFIG_DSP NO_DSP)

运行逐飞开源库示例

需要删除官方库的两个文件src/dcd.csrc/pin_mux.c,和对应的头文件。同时在CMake add_executable中删除对应行。
替换src/led_blinky.c为逐飞gpio示例,并复制isr.c到src目录下,CMake添加(下文不再强调)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "zf_common_headfile.h"
uint8 gpio_status;
int main(void)
{
clock_init(SYSTEM_CLOCK_600M); // 不可删除
debug_init(); // 调试端口初始化

// 此处编写用户代码 例如外设初始化代码等

// 初始化GPIO B9 为输出 默认输出低电平
gpio_init(B9, GPO, 0, GPO_PUSH_PULL);

// 初始化GPIO D0 D1 为输入引脚
gpio_init(C4, GPI, 0, GPI_PULL_UP);
gpio_init(D1, GPI, 0, GPI_PULL_UP);

// 此处编写用户代码 例如外设初始化代码等

while(1)
{
gpio_set_level(B9, 1); // 设置引脚电平为高电平
system_delay_ms(100);
gpio_set_level(B9, 0); // 设置引脚电平为低电平
system_delay_ms(100);
gpio_toggle_level(B9); // 翻转引脚电平
system_delay_ms(100);

gpio_status = gpio_get_level(C4); // 获取引脚电平
system_delay_ms(100);
}
}

此时就能看见核心板上的led愉快地闪了。

3-使用FreeRTOS

要使用FreeRTOS需要在config.cmake中添加相关配置,这里使用上文的配置即可。
打开lib/zf_common/zf_common_vector.c,注释SVC_HandlerPendSV_HandlerSysTick_Handler。头文件中也要注释。
运行FreeRTOS示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "FreeRTOS.h"
#include "FreeRTOSConfig.h"
#include "queue.h"
#include "task.h"
#include "timers.h"
#include "zf_common_headfile.h"

static void hello_task(void *pv) {
for (;;) {
gpio_set_level(B9, 1);
vTaskDelay(1000 / portTICK_PERIOD_MS);
gpio_set_level(B9, 0);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
int main(void) {
gpio_init(B9, GPO, 1, GPO_PUSH_PULL);
if (pdPASS != xTaskCreate(hello_task, "Hello", configMINIMAL_STACK_SIZE + 100,
NULL, configMAX_PRIORITIES - 1, NULL)) {
while (1) {
printf("Create Task failed");
}
}
vTaskStartScheduler();
}

又能看见led闪烁啦!!!

附:解决clangd无法识别编译选项

在项目根目录创建.clangd文件

1
2
3
CompileFlags:
Add: -Wno-unknown-warning-option
Remove: [-m*, -f*]