小麦克

  • 2024-09-14
  • 回复了主题帖: 《CMake构建实战》CMake构建初探

  • 发表了主题帖: 《CMake构建实战》CMake构建初探

    # CMake构建初探 《CMake构建实战》第3章,第4章详细讲解了CMake这门语言,由于之前有过一点点CMake开发经验。先跳到第六章 `CMake构建初探` 来试试,有不懂的再回头找对应的知识点学习。否则真怕第三第四章没看完就把书扔一边了~ ## CMake项目生命周期 ### 配置阶段和生成阶段 CMake本身并不实际调用编译器和链接器,而是根据整个构建流程,生成Makefile或者其他构建工具的配置文件。 常用的构建系统生成器 `Unix Makefiles` `Ninja` 等 ```bash The following generators are available on this platform (* marks default):   Green Hills MULTI            = Generates Green Hills MULTI files                                  (experimental, work-in-progress). * Unix Makefiles               = Generates standard UNIX makefiles.   Ninja                        = Generates build.ninja files.   Ninja Multi-Config           = Generates build-.ninja files.   Watcom WMake                 = Generates Watcom WMake makefiles. ``` ### 实例 下面通过一个静态库实例来演示CMake的配置和生成阶段。 新建`mylib`文件夹,创建`CMakeLists.txt` 和 `lib.c` ```bash tree . └── mylib     ├── CMakeLists.txt     └── lib.c 2 directories, 2 files ``` `CMakeLists.txt ` ```cmake cmake_minimum_required(VERSION 3.20) project(mylib VERSION 1.0.0) add_library(mylib STATIC lib.c) install(TARGETS mylib) set(CPACK_PACKAGE_NAME "mylib") include(CPack) ``` `lib.c` ```c int add(int a, int b) {         return a + b; } ``` 测试,新建`build`文件夹,用来存放生成的文件,防止污染源代码目录。进入`build`目录执行 `cmake ..` ```bash mkdir build cd build cmake .. -- The C compiler identification is GNU 13.2.0 -- The CXX compiler identification is GNU 13.2.0 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /usr/bin/cc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /usr/bin/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done (0.3s) -- Generating done (0.0s) -- Build files have been written to: /home/bruce/Documents/study/cmake/6/001/mylib/build ``` 执行成功后就生成了我们需要的Makefile文件,其实从这个角度讲,`CMake`就是帮助我们生成Makefile的工具,这样我们就不需要手动写复杂的`Makefile` 文件了。 下一步执行make即可生成最终目标文件 ```bash $ make [ 50%] Building C object CMakeFiles/mylib.dir/lib.c.o [100%] Linking C static library libmylib.a [100%] Built target mylib ``` ### 安装打包发布阶段 其实大部分情况下,上面的步骤已经完成日常开发了。CMake还能够打包发布,将需要的二进制文件打包,以便分发。这里不作过多介绍,需要时再详细了解。

  • 2024-09-13
  • 回复了主题帖: 《CMake构建实战》 - 引入CMake

  • 发表了主题帖: 《CMake构建实战》 - 引入CMake

    # CMake引入 ### 为什么使用CMake 从之前的介绍中可知Linux平台中的Makefile和Windows不能做到很好的兼容。而CMake很好的解决了跨平台问题。CMake能做到一次编写,到处编译 CMake是高效的,写CMakeLists.txt比写Makefile高效,能帮助开发者将精力都放在写代码上 CMake是强大的,支持在同一项目中使用多种开发环境和编译器,支持多种编程语言,适合团队开发,几乎是构建C和C++项目的业界标准工具 ### 安装CMake 在Ubuntu中安装,我安装的版本是`3.28.3` ```bash bruce@ubuntu:~$ sudo apt install cmake bruce@ubuntu:~$ cmake --version cmake version 3.28.3 CMake suite maintained and supported by Kitware (kitware.com/cmake). ``` ### 基础语法 `CMakeLists.txt` 项目顶层目录下的CMake入口文件 `.cmake` 指定`-P`参数执行脚本类型的CMake程序,这种CMake程序不会配置生成任何构建系统 `.cmake` 模块,通过`include`等命令引用模块程序 CMake程序几乎完全由命令调用构成,命令不区分大小写,一般使用小写 新建 `005`,创建`cmake.cmake` ```cmake message(hello, CMake!) ``` 执行 ```bash bruce@ubuntu:~/Documents/study/cmake/005$ cmake -P cmake.cmake hello,CMake! ``` #### 命令参数 * 引号参数(quoted argument) * 非引号参数(unquoted argument) * 括号参数(bracket argument) ##### 引号参数(quoted argument) ```cmake message("CMake 您好!") ``` ```bash bruce@ubuntu:~/Documents/study/cmake/005$ cmake -P 1.cmake CMake 您好! ``` 可以看到双引号`""`包裹的参数会原样的显示出来 ##### 非引号参数(unquoted argument) ```cmake message("x;y;z") message(x y z) message(x;y;z) ``` 执行`cmake -P 2.cmake` ```bash bruce@ubuntu:~/Documents/study/cmake/005$ cmake -P 2.cmake x;y;z xyz xyz ``` ##### 变量引用(variable reference) 创建`3.cmake` ```cmake set(var_a 您好) set(var_b a) message(${var_${var_b}}) ``` 执行 `cmake -P 3.cmake` ```bash bruce@ubuntu:~/Documents/study/cmake/005$ cmake -P 3.cmake 您好 ```

  • 2024-09-09
  • 回复了主题帖: 《CMake构建实战》 - 构建之旅

    13620203064 发表于 2024-9-6 17:20 有没有pdf文档,或者电子书的内容,发个链接。 上面内容的pdf文档,没有这本书的电子版  

  • 2024-09-06
  • 发表了主题帖: 《CMake构建实战》 - 构建之旅

    # 构建之旅 收到《CMake构建实战》有两天了,开始学习。 平时工作中也零零散散接触到CMake开发,比如QT6开始推荐使用CMake的方式进行构建。也做了几个QT CMake相关项目,但是项目模板都是工具自动生成的,项目改动不大。对CMake内部原理似懂非懂,遇到问题也不知道如何下手。 非常感谢论坛能给我提供这个机会,后面我会和坛友们一起学习,一起进步。 ### 构建之旅 第一章先从构建基础讲起,让我们了解构建原理。书中对Windows和Linux分别做了讲解,但是原理差不多。由于我最近在学习Linux,比较熟悉Linux开发环境,后面都在Linux环境下进行测试,Windows和macOS环境了解即可。 #### 一、静态库 静态库(static library),也称静态链接库(statically-linked library)。在静态库中包含了所有目标文件,还有一些符号索引。在我们程序链接静态库时,会将需要的函数、变量等目标代码会全部拷贝到我们的程序中,发布程序时不再需要带上这些静态库。好处是程序运行时没有依赖问题,坏处是我们的程序体积会变大。 按照书上的示例,新建下面几个文件 ```bash bruce@ubuntu:~/Documents/study/cmake/001$ tree . ├── a.c ├── b.c ├── libab.h ├── main.c └── Makefile 1 directory, 5 files ``` 为了方便测试,`Makefile`中添加了`clean`目标 ```makefile main: main.o libab.a         gcc main.o -o main -L. -lab main.o: main.c         gcc -c main.c -o main.o libab.a: a.o b.o         ar rcs libab.a a.o b.o a.o: a.c         gcc -c a.c -o a.o b.o: b.c         gcc -c b.c -o b.o .PHONY: clean clean:         rm -rf *.o *.a main ``` 测试,可以看到生成了静态库文件`libab.a` ```bash bruce@ubuntu:~/Documents/study/cmake/001$ make gcc -c main.c -o main.o gcc -c a.c -o a.o gcc -c b.c -o b.o ar rcs libab.a a.o b.o gcc main.o -o main -L. -lab bruce@ubuntu:~/Documents/study/cmake/001$ tree . ├── a.c ├── a.o ├── b.c ├── b.o ├── libab.a ├── libab.h ├── main ├── main.c ├── main.o └── Makefile 1 directory, 10 files bruce@ubuntu:~/Documents/study/cmake/001$ ls -alh 总计 60K drwxrwxr-x 2 bruce bruce 4.0K Sep  6 11:33 . drwxrwxr-x 3 bruce bruce 4.0K Sep  6 11:30 .. -rw-rw-r-- 1 bruce bruce   54 Sep  6 11:12 a.c -rw-rw-r-- 1 bruce bruce 1.5K Sep  6 11:33 a.o -rw-rw-r-- 1 bruce bruce   54 Sep  6 11:13 b.c -rw-rw-r-- 1 bruce bruce 1.5K Sep  6 11:33 b.o -rw-rw-r-- 1 bruce bruce 3.1K Sep  6 11:33 libab.a -rw-rw-r-- 1 bruce bruce   81 Sep  6 11:15 libab.h -rwxrwxr-x 1 bruce bruce  16K Sep  6 11:33 main -rw-rw-r-- 1 bruce bruce   82 Sep  6 11:16 main.c -rw-rw-r-- 1 bruce bruce 1.4K Sep  6 11:33 main.o -rw-rw-r-- 1 bruce bruce  236 Sep  6 11:28 Makefile bruce@ubuntu:~/Documents/study/cmake/001$ ./main a b bruce@ubuntu:~/Documents/study/cmake/001$ ``` 将main单独拷贝到其他目录也能执行,不需要带上`libab.a` #### 二、动态库 动态库(dynamic library),也称动态链接库(Dynamically-Linked Library, DLL)或共享库(shared library)。与静态库不同,动态库的目标代码在程序转载时或运行时被动态链接。 好处是和程序解耦,可以单独更新,我们的应用程序体积不会增大。坏处是随着时间的推移,应用程序可能和动态库出现不兼容的情况,这种情况对最终目标客户是个灾难。 拷贝之前的001文件夹为002,修改`Makefile` ```bash main: main.o libab.so         gcc main.o -o main -L. '-Wl,-R$$ORIGIN' -lab main.o: main.c         gcc -c main.c -o main.o libab.so: a.o b.o         gcc -shared a.o b.o -o libab.so a.o: a.c         gcc -c a.c -o a.o b.o: b.c         gcc -c b.c -o b.o .PHONY: clean clean:         rm -rf *.o *.so main ``` 主要改动了`libab.so`生成方法:`gcc -shared a.o b.o -o libab.so` 注意,生成`main`需要添加 `'-Wl,-R$$ORIGIN'`,否则会出现错误 `./main: error while loading shared libraries: libab.so: cannot open shared object file: No such file or directory` #### 三、引用第三方库 C和C++编程的一大优势是丰富的生态,让我们站在巨人的肩膀上。学习一下引用第三方 `Boost` 库。 下载boost库,解压到`~/boost` ```bash cd ~ wget https://archives.boost.io/release/1.86.0/source/boost_1_86_0.tar.gz tar -xf boost_1_86_0.tar.gz boost ``` 创建`main.cpp`和`Makefile`,编译测试 ```bash bruce@ubuntu:~/Documents/study/cmake/003$ tree . ├── main ├── main.cpp └── Makefile 1 directory, 3 files bruce@ubuntu:~/Documents/study/cmake/003$ cat Makefile main: main.cpp         g++ main.cpp -I ~/boost -o main clean:         rm main bruce@ubuntu:~/Documents/study/cmake/003$ cat main.cpp #include #include using namespace std; using namespace boost; int main(void) {         string str = "  hello world!";         cout

  • 2024-08-31
  • 回复了主题帖: 读书入围名单: 《CMake构建实战:项目开发卷》

    个人信息无误,确认可以完成阅读分享计划

  • 2024-08-28
  • 回复了主题帖: 【米尔 NXP i.MX93 开发板评测】搭建QT交叉编译环境

    Jacktang 发表于 2024-8-28 07:27 i.MX93没有GPU,不支持opengl,开发的时候有点不方便的 和定位有关,工业应用。普通的QT UI应用没问题的,适配了DRM,也能高清显示,最高可达1080p60,一般场景足够了。

  • 2024-08-27
  • 发表了主题帖: 【米尔 NXP i.MX93 开发板评测】搭建QT交叉编译环境

    本帖最后由 小麦克 于 2024-8-27 10:14 编辑 ## QT交叉编译环境 需要提前安装好cmake和ninja ```bash sudo apt install cmake sudo apt install ninja-build ``` ## 基于Yocto编译环境 关于Yocto环境,米尔专门提供了一篇教程《MYD-LMX9X+QT开发指南.pdf》,里面写的很详细了,我这里就不重复了,有两个地方需要注意一下。 ### Sysroot配置问题 教程中的`Sysroot`有点问题,应该为 `/opt/fsl-imx-xwayland/6.1-mickledore/sysroots/armv8a-poky-linux` 而不是 `/opt/fsl-imx-xwayland/6.1-mickledore/sysroots/x86_64-pokysdk-linux` ### CMake构建失败 上面配置都成功了,开始创建QT应用,如果使用`qmake`方式构建应用一切正常。但是如果使用`CMake`方式构建,配置阶段为提示错误:`To use a cross-compiled Qt, please set the QT_HOST_PATH cache variable to the location of your host Qt installation.` 解决方法:需要在`CMakeLists.txt` 中设置 `QT_HOST_PATH`为主机QT的gcc目录,我安装的目录是 `/home/bruce/Qt/6.5.3/gcc_64` ```cmake set(QT_HOST_PATH /home/bruce/Qt/6.5.3/gcc_64) ``` 重新配置后成功了 编译上传测试程序到开发板测试。 ## buildroot环境 由于我们之前的根文件系统都是基于`buildroot`,下面来看看怎么在`buildroot`构建的系统上面配置QT的交叉编译环境。 ### 构建SDK 确保配置的`buildroot`构建成功,能成功打包成文件系统。下面是我的配置文件(基于当前最新的buildroot仓库-2024-08-27) ```bash BR2_aarch64=y BR2_cortex_a55=y BR2_ARM_FPU_VFPV4D16=y BR2_KERNEL_HEADERS_6_1=y BR2_PACKAGE_GLIBC_UTILS=y BR2_TOOLCHAIN_BUILDROOT_CXX=y BR2_PACKAGE_HOST_GDB=y BR2_ENABLE_DEBUG=y BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_MDEV=y BR2_ROOTFS_MERGED_USR=y BR2_SYSTEM_DHCP="eth0" BR2_SYSTEM_DEFAULT_PATH="/bin:/sbin:/usr/bin:/usr/sbin" BR2_ENABLE_LOCALE_WHITELIST="en_US.UTF-8" BR2_GENERATE_LOCALE="en_US.UTF-8" BR2_SYSTEM_ENABLE_NLS=y BR2_TARGET_TZ_INFO=y BR2_PACKAGE_ALSA_UTILS=y BR2_PACKAGE_ALSA_UTILS_ALSACONF=y BR2_PACKAGE_ALSA_UTILS_ACONNECT=y BR2_PACKAGE_ALSA_UTILS_ALSALOOP=y BR2_PACKAGE_ALSA_UTILS_ALSAUCM=y BR2_PACKAGE_ALSA_UTILS_ALSATPLG=y BR2_PACKAGE_ALSA_UTILS_AMIDI=y BR2_PACKAGE_ALSA_UTILS_AMIXER=y BR2_PACKAGE_ALSA_UTILS_APLAY=y BR2_PACKAGE_ALSA_UTILS_APLAYMIDI=y BR2_PACKAGE_ALSA_UTILS_ARECORDMIDI=y BR2_PACKAGE_ALSA_UTILS_ASEQDUMP=y BR2_PACKAGE_ALSA_UTILS_ASEQNET=y BR2_PACKAGE_ALSA_UTILS_BAT=y BR2_PACKAGE_ALSA_UTILS_IECSET=y BR2_PACKAGE_ALSA_UTILS_SPEAKER_TEST=y BR2_PACKAGE_FFMPEG_GPL=y BR2_PACKAGE_FFMPEG_NONFREE=y BR2_PACKAGE_FFMPEG_FFPLAY=y BR2_PACKAGE_FFMPEG_FFPROBE=y BR2_PACKAGE_FFMPEG_POSTPROC=y BR2_PACKAGE_FLAC=y BR2_PACKAGE_GSTREAMER1=y BR2_PACKAGE_GSTREAMER1_CHECK=y BR2_PACKAGE_GST1_PLUGINS_BASE_PLUGIN_APP=y BR2_PACKAGE_GST1_PLUGINS_BAYER2RGB_NEON=y BR2_PACKAGE_GST1_PLUGINS_GOOD=y BR2_PACKAGE_GST1_PLUGINS_BAD=y BR2_PACKAGE_GST1_LIBAV=y BR2_PACKAGE_GDB=y BR2_PACKAGE_GDB_SERVER=y BR2_PACKAGE_GDB_DEBUGGER=y BR2_PACKAGE_GDB_TUI=y BR2_PACKAGE_BINUTILS=y BR2_PACKAGE_BINUTILS_TARGET=y BR2_PACKAGE_LIBTOOL=y BR2_PACKAGE_MAKE=y BR2_PACKAGE_PKGCONF=y BR2_PACKAGE_TREE=y BR2_PACKAGE_MMC_UTILS=y BR2_PACKAGE_BITSTREAM_VERA=y BR2_PACKAGE_CANTARELL=y BR2_PACKAGE_DEJAVU=y BR2_PACKAGE_FONT_AWESOME=y BR2_PACKAGE_GHOSTSCRIPT_FONTS=y BR2_PACKAGE_INCONSOLATA=y BR2_PACKAGE_LIBERATION=y BR2_PACKAGE_WQY_ZENHEI=y BR2_PACKAGE_DIRECTFB=y BR2_PACKAGE_SDL=y BR2_PACKAGE_SDL_GFX=y BR2_PACKAGE_SDL_IMAGE=y BR2_PACKAGE_SDL_IMAGE_GIF=y BR2_PACKAGE_SDL_IMAGE_JPEG=y BR2_PACKAGE_SDL_IMAGE_LBM=y BR2_PACKAGE_SDL_IMAGE_PCX=y BR2_PACKAGE_SDL_IMAGE_PNG=y BR2_PACKAGE_SDL_IMAGE_PNM=y BR2_PACKAGE_SDL_IMAGE_TARGA=y BR2_PACKAGE_SDL_IMAGE_TIFF=y BR2_PACKAGE_SDL_IMAGE_WEBP=y BR2_PACKAGE_SDL_IMAGE_XCF=y BR2_PACKAGE_SDL_IMAGE_XPM=y BR2_PACKAGE_SDL_IMAGE_XV=y BR2_PACKAGE_SDL_MIXER=y BR2_PACKAGE_SDL_MIXER_MIDI_TIMIDITY=y BR2_PACKAGE_SDL_NET=y BR2_PACKAGE_SDL_TTF=y BR2_PACKAGE_QT6=y BR2_PACKAGE_QT6BASE_CONCURRENT=y BR2_PACKAGE_QT6BASE_DBUS=y BR2_PACKAGE_QT6BASE_VULKAN=y BR2_PACKAGE_QT6BASE_FONTCONFIG=y BR2_PACKAGE_QT6BASE_HARFBUZZ=y BR2_PACKAGE_QT6BASE_GIF=y BR2_PACKAGE_QT6BASE_JPEG=y BR2_PACKAGE_QT6BASE_PNG=y BR2_PACKAGE_QT6BASE_WIDGETS=y BR2_PACKAGE_QT6BASE_PRINTSUPPORT=y BR2_PACKAGE_QT6BASE_SYSLOG=y BR2_PACKAGE_QT6BASE_TEST=y BR2_PACKAGE_QT6BASE_TSLIB=y BR2_PACKAGE_QT6CORE5COMPAT=y BR2_PACKAGE_QT6SERIALBUS=y BR2_PACKAGE_QT6SVG=y BR2_PACKAGE_EVEMU=y BR2_PACKAGE_EVTEST=y BR2_PACKAGE_KBD=y BR2_PACKAGE_SYSSTAT=y BR2_PACKAGE_LIBG7221=y BR2_PACKAGE_LIBGSM=y BR2_PACKAGE_LIBILBC=y BR2_PACKAGE_LIBSAMPLERATE=y BR2_PACKAGE_OPENCORE_AMR=y BR2_PACKAGE_PORTAUDIO=y BR2_PACKAGE_WEBRTC_AUDIO_PROCESSING=y BR2_PACKAGE_SQLITE_ENABLE_COLUMN_METADATA=y BR2_PACKAGE_IMLIB2=y BR2_PACKAGE_IMLIB2_JPEG=y BR2_PACKAGE_IMLIB2_PNG=y BR2_PACKAGE_IMLIB2_GIF=y BR2_PACKAGE_IMLIB2_TIFF=y BR2_PACKAGE_IMLIB2_ID3=y BR2_PACKAGE_LIBJPEG=y BR2_PACKAGE_LIBDRM_INSTALL_TESTS=y BR2_PACKAGE_LIBFREEIMAGE=y BR2_PACKAGE_LIBVA=y BR2_PACKAGE_WAYLAND=y BR2_PACKAGE_WAYLAND_UTILS=y BR2_PACKAGE_LIBAIO=y BR2_PACKAGE_LIBV4L=y BR2_PACKAGE_LIBV4L_UTILS=y BR2_PACKAGE_LIBOPENH264=y BR2_PACKAGE_LIBYUV=y BR2_PACKAGE_X264=y BR2_PACKAGE_X264_CLI=y BR2_PACKAGE_LIBPJSIP=y BR2_PACKAGE_LIBRSYNC=y BR2_PACKAGE_LIBUPNP=y BR2_PACKAGE_LIBCAP=y BR2_PACKAGE_FMT=y BR2_PACKAGE_PCRE2_32=y BR2_PACKAGE_DHCPCD=y BR2_PACKAGE_FREESWITCH=y BR2_PACKAGE_FREESWITCH_MOD_BCG729=y BR2_PACKAGE_OPENSSH=y BR2_PACKAGE_TCPDUMP=y BR2_PACKAGE_VSFTPD=y BR2_PACKAGE_ZSH=y BR2_PACKAGE_KMOD=y BR2_PACKAGE_UTIL_LINUX_LIBFDISK=y BR2_PACKAGE_UTIL_LINUX_AGETTY=y BR2_PACKAGE_UTIL_LINUX_FSCK=y BR2_PACKAGE_UTIL_LINUX_HWCLOCK=y BR2_PACKAGE_UTIL_LINUX_KILL=y BR2_PACKAGE_UTIL_LINUX_LSFD=y BR2_PACKAGE_UTIL_LINUX_MORE=y BR2_PACKAGE_UTIL_LINUX_MOUNT=y BR2_PACKAGE_UTIL_LINUX_SULOGIN=y BR2_TARGET_ROOTFS_EXT2=y BR2_TARGET_ROOTFS_EXT2_SIZE="512M" BR2_TARGET_ROOTFS_TAR_GZIP=y BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y ``` 构建SDK,构建成功后,在`output/images`文件夹下会生成 `aarch64-buildroot-linux-gnu_sdk-buildroot.tar.gz`SDK,这个SDK可以拷贝到其他电脑或者其他目录,进行应用开发。 ```bash make sdk ``` 我这里拷贝到`/home/bruce/Documents`文件夹下,解压,重定位 ```bash # 解压 tar -xf aarch64-buildroot-linux-gnu_sdk-buildroot.tar.gz # 重定位(只需要执行一次) cd aarch64-buildroot-linux-gnu_sdk-buildroot/ ./relocate-sdk.sh ``` 生成新的QT配置,C和C++编译器配置 QT Versions配置,有红色的错误,不用管。 Devices配置 上面都配置好后,最后配置一下Kits,添加一个imx93的配置项。注意`Sysroot`的位置 新建一个CMake QT测试程序,配置为`imx93`,编译,成功! 如果不使用`Qt Creator`,`buildroot`还为我们准备了`environment-setup`脚本,需要交叉编译的时候直接`source`一下,一切就准备就绪了。看下面的示例 ```bash source ~/Documents/aarch64-buildroot-linux-gnu_sdk-buildroot/environment-setup # 进入qt app目录编译 bruce@ubuntu:~/Documents/qt/qt-apps/test-app/build$ cmake .. -- The CXX compiler identification is GNU 13.3.0 -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /home/bruce/Documents/aarch64-buildroot-linux-gnu_sdk-buildroot/bin/aarch64-buildroot-linux-gnu-g++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Performing Test CMAKE_HAVE_LIBC_PTHREAD -- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success -- Found Threads: TRUE   -- Performing Test HAVE_STDATOMIC -- Performing Test HAVE_STDATOMIC - Success -- Found WrapAtomic: TRUE   -- Configuring done (1.2s) -- Generating done (0.0s) -- Build files have been written to: /home/bruce/Documents/qt/qt-apps/test-app/build bruce@ubuntu:~/Documents/qt/qt-apps/test-app/build$ make [  0%] Built target test-app_autogen_timestamp_deps [ 16%] Automatic MOC and UIC for target test-app [ 16%] Built target test-app_autogen [ 33%] Building CXX object CMakeFiles/test-app.dir/test-app_autogen/mocs_compilation.cpp.o [ 50%] Building CXX object CMakeFiles/test-app.dir/main.cpp.o [ 66%] Building CXX object CMakeFiles/test-app.dir/mainwindow.cpp.o [ 83%] Linking CXX executable test-app [100%] Built target test-app bruce@ubuntu:~/Documents/qt/qt-apps/test-app/build$ ls CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile  test-app  test-app_autogen bruce@ubuntu:~/Documents/qt/qt-apps/test-app/build$ file test-app test-app: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 6.1.0, with debug_info, not stripped ``` 可以看到生成的`test-app`就是`ARM aarch64`。 这种方式适合自动化,对项目组提交的代码进行自动编译打包或者测试。 ## 树莓派 最近搞了一台8GB的树莓派5,测试下来性能还不错,前提必须上PCI-E固态硬盘,SD卡相对于固态硬盘太慢了。 因为和IMX93使用了同样的`aarch64`架构,接上显示器,用来开发原生QT更简单,不需要配置复杂的交叉编译环境。 我这里通过VNC连接到了树莓派5,安装Qt Creator IDE,编译出的程序可以直接放到开发板运行。需要注意的是i.MX93没有GPU,不支持opengl,因此开发的时候不能调用这些库。否则在开发板加载程序会失败。 ## 结论 本篇将QT开发的几种方式都做了测试,欢迎大家指正补充~

  • 2024-08-23
  • 发表了主题帖: 【米尔 NXP i.MX93 开发板评测】嵌入式QT开发

    # 嵌入式QT测试 iMX93支持`drm`。之前在IMX93上测试了一下`LVGL`,发现`LVGL`对`Linux`的优化不太好,有些场景有卡顿,LVGL还是比较适合单片机的应用场景。对比研究下来感觉还是QT更加适合嵌入式Linux UI应用。毕竟QT功能更加强大,如果QT用熟悉了,QT不仅仅可以开发UI程序,还能写一些复杂的服务。 ## Linux显示子DRM Linux DRM是Linux下比较新的显示子系统,相比之前的framebuffer功能更加强大。 配置`buildroot`,添加 test programs 查看当前`drm`驱动信息 ```bash modetest ``` 测试,显示器会有彩色条纹抖动。 ```bash modetest -M imx-drm -s 35@33:720x1280 -v ``` ## 事件测试 触摸屏触摸测试,从后面的说明可以看出`/dev/input/event1`为触摸屏,输入1,触摸屏幕看到有新事件。 ```bash # evtest No device specified, trying to scan all of /dev/input/event* Available devices: /dev/input/event0:      44440000.bbnsm:pwrkey /dev/input/event1:      Goodix Capacitive TouchScreen /dev/input/event2:      gpio_keys@0 /dev/input/event3:      Logitech Inc. Logi USB Headset H340 Consumer Control /dev/input/event4:      Logitech Inc. Logi USB Headset H340 Select the device event number [0-4]: 1 Input driver version is 1.0.1 Input device ID: bus 0x18 vendor 0x416 product 0x38f version 0x1060 Input device name: "Goodix Capacitive TouchScreen" ``` ## QT开发 从github同步最新的buildroot编译QT6.7,配置常用的库。 这是我当前的buildroot配置信息 ```bash BR2_aarch64=y BR2_cortex_a55=y BR2_ARM_FPU_VFPV4D16=y BR2_KERNEL_HEADERS_6_1=y BR2_PACKAGE_GLIBC_UTILS=y BR2_TOOLCHAIN_BUILDROOT_CXX=y BR2_PACKAGE_HOST_GDB=y BR2_ENABLE_DEBUG=y BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_MDEV=y BR2_ROOTFS_MERGED_USR=y BR2_SYSTEM_DHCP="eth0" BR2_SYSTEM_DEFAULT_PATH="/bin:/sbin:/usr/bin:/usr/sbin" BR2_ENABLE_LOCALE_WHITELIST="en_US.UTF-8" BR2_GENERATE_LOCALE="en_US.UTF-8" BR2_SYSTEM_ENABLE_NLS=y BR2_TARGET_TZ_INFO=y BR2_PACKAGE_ALSA_UTILS=y BR2_PACKAGE_ALSA_UTILS_ALSACONF=y BR2_PACKAGE_ALSA_UTILS_ACONNECT=y BR2_PACKAGE_ALSA_UTILS_ALSALOOP=y BR2_PACKAGE_ALSA_UTILS_ALSAUCM=y BR2_PACKAGE_ALSA_UTILS_ALSATPLG=y BR2_PACKAGE_ALSA_UTILS_AMIDI=y BR2_PACKAGE_ALSA_UTILS_AMIXER=y BR2_PACKAGE_ALSA_UTILS_APLAY=y BR2_PACKAGE_ALSA_UTILS_APLAYMIDI=y BR2_PACKAGE_ALSA_UTILS_ARECORDMIDI=y BR2_PACKAGE_ALSA_UTILS_ASEQDUMP=y BR2_PACKAGE_ALSA_UTILS_ASEQNET=y BR2_PACKAGE_ALSA_UTILS_BAT=y BR2_PACKAGE_ALSA_UTILS_IECSET=y BR2_PACKAGE_ALSA_UTILS_SPEAKER_TEST=y BR2_PACKAGE_FFMPEG_GPL=y BR2_PACKAGE_FFMPEG_NONFREE=y BR2_PACKAGE_FFMPEG_FFPLAY=y BR2_PACKAGE_FFMPEG_FFPROBE=y BR2_PACKAGE_FFMPEG_POSTPROC=y BR2_PACKAGE_FLAC=y BR2_PACKAGE_GSTREAMER1=y BR2_PACKAGE_GSTREAMER1_CHECK=y BR2_PACKAGE_GST1_PLUGINS_BASE_PLUGIN_APP=y BR2_PACKAGE_GST1_PLUGINS_BAYER2RGB_NEON=y BR2_PACKAGE_GST1_PLUGINS_GOOD=y BR2_PACKAGE_GST1_PLUGINS_BAD=y BR2_PACKAGE_GST1_LIBAV=y BR2_PACKAGE_GDB=y BR2_PACKAGE_GDB_SERVER=y BR2_PACKAGE_GDB_DEBUGGER=y BR2_PACKAGE_GDB_TUI=y BR2_PACKAGE_BINUTILS=y BR2_PACKAGE_BINUTILS_TARGET=y BR2_PACKAGE_LIBTOOL=y BR2_PACKAGE_MAKE=y BR2_PACKAGE_PKGCONF=y BR2_PACKAGE_TREE=y BR2_PACKAGE_MMC_UTILS=y BR2_PACKAGE_BITSTREAM_VERA=y BR2_PACKAGE_CANTARELL=y BR2_PACKAGE_DEJAVU=y BR2_PACKAGE_FONT_AWESOME=y BR2_PACKAGE_GHOSTSCRIPT_FONTS=y BR2_PACKAGE_INCONSOLATA=y BR2_PACKAGE_LIBERATION=y BR2_PACKAGE_WQY_ZENHEI=y BR2_PACKAGE_DIRECTFB=y BR2_PACKAGE_SDL=y BR2_PACKAGE_SDL_GFX=y BR2_PACKAGE_SDL_IMAGE=y BR2_PACKAGE_SDL_IMAGE_GIF=y BR2_PACKAGE_SDL_IMAGE_JPEG=y BR2_PACKAGE_SDL_IMAGE_LBM=y BR2_PACKAGE_SDL_IMAGE_PCX=y BR2_PACKAGE_SDL_IMAGE_PNG=y BR2_PACKAGE_SDL_IMAGE_PNM=y BR2_PACKAGE_SDL_IMAGE_TARGA=y BR2_PACKAGE_SDL_IMAGE_TIFF=y BR2_PACKAGE_SDL_IMAGE_WEBP=y BR2_PACKAGE_SDL_IMAGE_XCF=y BR2_PACKAGE_SDL_IMAGE_XPM=y BR2_PACKAGE_SDL_IMAGE_XV=y BR2_PACKAGE_SDL_MIXER=y BR2_PACKAGE_SDL_MIXER_MIDI_TIMIDITY=y BR2_PACKAGE_SDL_NET=y BR2_PACKAGE_SDL_TTF=y BR2_PACKAGE_QT6=y BR2_PACKAGE_QT6BASE_CONCURRENT=y BR2_PACKAGE_QT6BASE_DBUS=y BR2_PACKAGE_QT6BASE_VULKAN=y BR2_PACKAGE_QT6BASE_FONTCONFIG=y BR2_PACKAGE_QT6BASE_HARFBUZZ=y BR2_PACKAGE_QT6BASE_GIF=y BR2_PACKAGE_QT6BASE_JPEG=y BR2_PACKAGE_QT6BASE_PNG=y BR2_PACKAGE_QT6BASE_WIDGETS=y BR2_PACKAGE_QT6BASE_PRINTSUPPORT=y BR2_PACKAGE_QT6BASE_SYSLOG=y BR2_PACKAGE_QT6BASE_TEST=y BR2_PACKAGE_QT6BASE_TSLIB=y BR2_PACKAGE_QT6CORE5COMPAT=y BR2_PACKAGE_QT6SERIALBUS=y BR2_PACKAGE_QT6SVG=y BR2_PACKAGE_EVEMU=y BR2_PACKAGE_EVTEST=y BR2_PACKAGE_KBD=y BR2_PACKAGE_LIBG7221=y BR2_PACKAGE_LIBGSM=y BR2_PACKAGE_LIBILBC=y BR2_PACKAGE_LIBSAMPLERATE=y BR2_PACKAGE_OPENCORE_AMR=y BR2_PACKAGE_PORTAUDIO=y BR2_PACKAGE_WEBRTC_AUDIO_PROCESSING=y BR2_PACKAGE_SQLITE_ENABLE_COLUMN_METADATA=y BR2_PACKAGE_IMLIB2=y BR2_PACKAGE_IMLIB2_JPEG=y BR2_PACKAGE_IMLIB2_PNG=y BR2_PACKAGE_IMLIB2_GIF=y BR2_PACKAGE_IMLIB2_TIFF=y BR2_PACKAGE_IMLIB2_ID3=y BR2_PACKAGE_LIBJPEG=y BR2_PACKAGE_LIBDRM_INSTALL_TESTS=y BR2_PACKAGE_LIBFREEIMAGE=y BR2_PACKAGE_LIBVA=y BR2_PACKAGE_WAYLAND=y BR2_PACKAGE_WAYLAND_UTILS=y BR2_PACKAGE_LIBAIO=y BR2_PACKAGE_LIBV4L=y BR2_PACKAGE_LIBV4L_UTILS=y BR2_PACKAGE_LIBOPENH264=y BR2_PACKAGE_LIBYUV=y BR2_PACKAGE_X264=y BR2_PACKAGE_X264_CLI=y BR2_PACKAGE_LIBPJSIP=y BR2_PACKAGE_LIBUPNP=y BR2_PACKAGE_LIBCAP=y BR2_PACKAGE_FMT=y BR2_PACKAGE_PCRE2_32=y BR2_PACKAGE_DHCPCD=y BR2_PACKAGE_FREESWITCH=y BR2_PACKAGE_FREESWITCH_MOD_BCG729=y BR2_PACKAGE_OPENSSH=y BR2_PACKAGE_TCPDUMP=y BR2_PACKAGE_VSFTPD=y BR2_PACKAGE_ZSH=y BR2_PACKAGE_KMOD=y BR2_PACKAGE_UTIL_LINUX_LIBFDISK=y BR2_PACKAGE_UTIL_LINUX_AGETTY=y BR2_PACKAGE_UTIL_LINUX_FSCK=y BR2_PACKAGE_UTIL_LINUX_HWCLOCK=y BR2_PACKAGE_UTIL_LINUX_KILL=y BR2_PACKAGE_UTIL_LINUX_LSFD=y BR2_PACKAGE_UTIL_LINUX_MORE=y BR2_PACKAGE_UTIL_LINUX_MOUNT=y BR2_PACKAGE_UTIL_LINUX_SULOGIN=y BR2_TARGET_ROOTFS_EXT2=y BR2_TARGET_ROOTFS_EXT2_SIZE="512M" BR2_TARGET_ROOTFS_TAR_GZIP=y BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y ``` 经过测试,低版本QT Creator交叉编译的QT APP应用程序可以运行在高版本库上面;但是高版本QT Creator 编译的app应用程序不能跑在低版本的QT库上面。 ## 运行QT前的配置 通过上面的测试可知,触摸屏的input设备是 `/dev/input/event1`。注意我的buildroot里面配置了字体,如果不配置字体,QT应用会用方框代替字符。将下面的环境变量导入到当前终端中。 ```bash # 通过上面的evtest测试可知event1为触摸屏 export TSLIB_TSDEVICE=/dev/input/event1 export QT_QPA_FB_TSLIB=1 export QT_QPA_PLATFORM=linuxfb export QT_QPA_FONTDIR=/usr/share/fonts export LC_ALL=en_US.UTF-8 export LANG=en_US.UTF-8 # QT适配高分屏 export QT_SCREEN_SCALE_FACTORS=2 ``` 打开程序测试,观察现象 下载QT开发工具:https://download.qt.io/archive/online_installers/ 后面会写一篇上位机QT交叉编译器搭建,马上回来~

  • 2024-08-16
  • 发表了主题帖: 【米尔 NXP i.MX93 开发板评测】GDB调试

    # GDB调试 在调试应用程序时出了问题,需要在线调试,下面看看在设备端进行GDB调试的方法。 配置`buildroot`,生成目标设备`gdb`工具,打包生成文件系统下载到设备中。 ```bash Target packages         Debugging, profiling and benchmark ``` 重新编译要调试的app,添加编译参数`-g`增加调试信息。下面以`buildroot`中的`libpjsip`为例进行说明。 `buildroot`默认情况下不带调试信息,找到`libpjsip`这个包的配置文件`libpjsip.mk`增加一行`LIBPJSIP_CFLAGS += -g` 重新编译`libpjsip` ```bash make libpjsip-dirclean make libpjsip-rebuild ``` 将需要调试的应用程序下载到开发板,使用GDB进行调试。 ```bash gdb samples/aarch64-buildroot-linux-gnu/simpleua (gdb) set args sip:bruce@192.168.1.228 (gdb) set print pretty on (gdb) set listsize 20 (gdb) b main (gdb) r Starting program: /root/pjsip-apps/bin/samples/aarch64-buildroot-linux-gnu/simpleua sip:bruce@192.168.1.228 warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available. Breakpoint 1, main (argc=2, argv=0xffffc2490e08)     at ../src/samples/simpleua.c:225 225     { (gdb) n ``` 以上步骤操作说明: 1. 使用GDB加载应用程序,`gdb samples/aarch64-buildroot-linux-gnu/simpleua` 2. 设置几个参数:`args` 给应用的参数,`print pretty on` 格式化结构体(更方便查看变量),`set listsize 20` 设置一次显示的行数(默认10行) 3. 设置断点 `b main` 4. 运行:r 5. 发现程序在mian函数第一行停住,等待进一步操作指令。 运行过程中需要打印复杂结构体,比如这里的`local_sdp`指针变量 ``` (gdb) p *local_sdp.media[0] ``` 所有变量都会显示出来 还可以继续深挖下去,通过这种方法能查看所有变量的值。 ```bash (gdb) p *local_sdp.media[0].attr $9 = (pjmedia_sdp_attr *) 0xaaaac01b10c8 (gdb) p **local_sdp.media[0].attr $10 = {   name = {     ptr = 0xffff949899f8 "rtcp",     slen = 4   },   value = {     ptr = 0xaaaac01b10e8 "4001 IN IP4 192.168.1.189",     slen = 25   } } (gdb) ``` 经过上面的调试,终于找到应用程序API调用失败是因为缺少编码器。将`package/libpjsip/libpjsip.mk`中屏蔽的编码器都打开。再次测试`simpleua`程序呼叫成功。

  • 2024-08-14
  • 发表了主题帖: 【米尔 NXP i.MX93 开发板评测】buildroot交叉编译实践

    本帖最后由 小麦克 于 2024-8-14 16:30 编辑 # buildroot交叉编译实践 `buildroot`用来作为嵌入式linux系统开发还是非常方便的,编译器配置为`buildroot`自动生成。 `uboot`和`linux`内核采用开发板自带的。通过`buildroot`制作`rootfs`,然后再使用`buildroot`制作交叉编译的环境。这个环境中包含了我们之前加入的库,我们开发新的app就可以交叉编译并链接。 ## 编译 当前的`buildroot`配置如下(保存为myirdeconfig放到`configs`目录) ```bash BR2_aarch64=y BR2_cortex_a55=y BR2_ARM_FPU_VFPV4D16=y BR2_KERNEL_HEADERS_6_1=y BR2_PACKAGE_GLIBC_UTILS=y BR2_TOOLCHAIN_BUILDROOT_CXX=y BR2_PACKAGE_HOST_GDB=y BR2_INIT_SYSTEMD=y BR2_SYSTEM_DHCP="eth0" BR2_SYSTEM_DEFAULT_PATH="/bin:/sbin:/usr/bin:/usr/sbin" BR2_PACKAGE_ALSA_UTILS=y BR2_PACKAGE_ALSA_UTILS_ALSACONF=y BR2_PACKAGE_ALSA_UTILS_ACONNECT=y BR2_PACKAGE_ALSA_UTILS_ALSALOOP=y BR2_PACKAGE_ALSA_UTILS_ALSAUCM=y BR2_PACKAGE_ALSA_UTILS_ALSATPLG=y BR2_PACKAGE_ALSA_UTILS_AMIDI=y BR2_PACKAGE_ALSA_UTILS_AMIXER=y BR2_PACKAGE_ALSA_UTILS_APLAY=y BR2_PACKAGE_ALSA_UTILS_APLAYMIDI=y BR2_PACKAGE_ALSA_UTILS_ARECORDMIDI=y BR2_PACKAGE_ALSA_UTILS_ASEQDUMP=y BR2_PACKAGE_ALSA_UTILS_ASEQNET=y BR2_PACKAGE_ALSA_UTILS_BAT=y BR2_PACKAGE_ALSA_UTILS_IECSET=y BR2_PACKAGE_ALSA_UTILS_SPEAKER_TEST=y BR2_PACKAGE_FFMPEG_GPL=y BR2_PACKAGE_FFMPEG_NONFREE=y BR2_PACKAGE_FFMPEG_FFPLAY=y BR2_PACKAGE_FFMPEG_FFPROBE=y BR2_PACKAGE_FFMPEG_POSTPROC=y BR2_PACKAGE_FLAC=y BR2_PACKAGE_GSTREAMER1=y BR2_PACKAGE_GSTREAMER1_CHECK=y BR2_PACKAGE_GST1_PLUGINS_BASE_PLUGIN_APP=y BR2_PACKAGE_GST1_PLUGINS_BAYER2RGB_NEON=y BR2_PACKAGE_GST1_PLUGINS_GOOD=y BR2_PACKAGE_GST1_LIBAV=y BR2_PACKAGE_VLC=y BR2_PACKAGE_TREE=y BR2_PACKAGE_MMC_UTILS=y BR2_PACKAGE_LIBPJSIP=y BR2_PACKAGE_DHCPCD=y BR2_PACKAGE_FREESWITCH=y BR2_PACKAGE_OPENSSH=y BR2_PACKAGE_TCPDUMP=y BR2_PACKAGE_VSFTPD=y BR2_PACKAGE_UTIL_LINUX_LIBFDISK=y BR2_PACKAGE_UTIL_LINUX_HWCLOCK=y BR2_PACKAGE_UTIL_LINUX_KILL=y BR2_PACKAGE_UTIL_LINUX_LSFD=y BR2_PACKAGE_UTIL_LINUX_MORE=y BR2_TARGET_ROOTFS_EXT2=y BR2_TARGET_ROOTFS_EXT2_SIZE="256M" BR2_TARGET_ROOTFS_TAR_GZIP=y BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y ``` 注意这里打开了 `BR2_PACKAGE_HOST_ENVIRONMENT_SETUP` ,有了这个配置会生成`output/host/environment-setup`脚本,执行`source`命令即可当前开发环境设置为交叉编译,跨平台的`cmake`也搞好了,非常的方便。 配置并编译,等待编译成功 ```bash make myirdeconfig make # 将当前的环境设置为交叉编译 source output/host/environment-setup # 测试一下变量 $ echo $CC aarch64-buildroot-linux-gnu-gcc ``` 可以大概看一下`environment-setup`脚本为我们做的事情。导出了很多变量,还有`configure`和`cmake`别名 编译`cmake`工程时,交叉编译配置都省了 ```bash cat

  • 2024-08-13
  • 发表了主题帖: 【米尔 NXP i.MX93 开发板评测】cmake交叉编译

    本帖最后由 小麦克 于 2024-8-13 15:48 编辑 # cmake交叉编译模版工程 本文通过一个简单的示例,演示如何在 CMake 工程中添加交叉编译的配置,实现编译不同硬件平台的可执行文件。 ## CMake概述 CMake 是一个项目构建工具,并且是跨平台的。关于项目构建我们所熟知的还有Makefile(通过 make 命令进行项目的构建),大多是IDE软件都集成了make,比如:VS 的 nmake、linux 下的 GNU make、Qt 的 qmake等,如果自己动手写 makefile,会发现,makefile 通常依赖于当前的编译平台,而且编写 makefile 的工作量比较大,解决依赖关系时也容易出错。 而 CMake 恰好能解决上述问题, 其允许开发者指定整个工程的编译流程,在根据编译平台,自动生成本地化的Makefile和工程文件,最后用户只需make编译即可,所以可以把CMake看成一款自动生成 Makefile的工具,其编译流程如下图: ## 示例 ### 目录结构 ```bahs $ tree . ├── arm_linux_setup.cmake ├── CMakeLists.txt └── hello.c 1 directory, 3 files ``` arm_linux_setup.cmake 这里的`aarch64-buildroot-linux-gnu-gcc`是通过`buildroot`生成的交叉编译器,其他编译器也可以用,名称有差异,记得替换 ```cmake set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(target_arch aarch64-linux-gnu) set(CMAKE_C_COMPILER aarch64-buildroot-linux-gnu-gcc) set(CMAKE_CXX_COMPILER aarch64-buildroot-linux-gnu-g++) set(CMAKE_LIBRARY_ARCHITECTURE ${target_arch} CACHE STRING "" FORCE) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) ``` CMakeLists.txt ```cmake cmake_minimum_required(VERSION 3.1.3) project(hello) set( HELLO_SRCS hello.c) add_executable(${PROJECT_NAME} ${HELLO_SRCS}) ``` hello.c ```c #include int main(void) {     printf("Hello, CMake\n");     return 0; } ``` ### 编译 在项目根目录下面新建一个`build`,放cmake生成的中间文件 ```bash mkdir build cd build cmake .. # 编译成主机平台 make # 编译成功生成x86-64平台hello $ file hello hello: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=d55b52333ab9da5f0b106b3af84a8d4ef78f9a02, for GNU/Linux 3.2.0, not stripped ``` 交叉编译 ```bash # 交叉编译 rm -rf * cmake -DCMAKE_TOOLCHAIN_FILE=../arm_linux_setup.cmake .. make # 交叉编译成功生成aarch64平台hello $ file hello hello: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 6.1.0, not stripped ``` 上传开发板执行试试~

  • 回复了主题帖: 【米尔 NXP i.MX93 开发板评测】USB下载工具-UUU

  • 发表了主题帖: 【米尔 NXP i.MX93 开发板评测】USB下载工具-UUU

    # USB下载工具-UUU 由前面的调试可知,通过SD更新镜像比较麻烦,需要SD卡并且操作的步骤也比较多。这篇来试一下NXP的[uuu](https://github.com/nxp-imx/mfgtools.git)下载工具。 `uuu`通过USB接口可以下载`uboot`,`Image`,`dtb`,`rootfs`等等,还可以执行自定义的指令。通过自定义的脚本,非常灵活。有了这个工具,后续生产及更新都非常方便。由于使用了USB高速模式,下载速度也非常快。 在GitHub的发布页面有一个uuu.pdf文档,想了解`uuu`工作原理的可以去看看。 这个工具支持`linux`,`windows`,`macos` ## uuu配置 先来看下文件构成: 1. boot目录放了imx-uboot文件`flash.bin`(myir编译出来的文件名为`imx-boot-myd-lmx9x-sd.bin-flash_singleboot`),linux内核 `Image`,设备树`myir-imx93-11x11.dtb` 2. filesystem放打包后的文件系统,这里放的是buildroot生产的`rootfs.tar` 3. modules 放打包好的内核模块 `modules.tar.gz` 4. `fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.zst.u-boot` 是NXP提供的RAMDISK,通过uboot启动后和uuu进行交互操作 5. `imx93-emmc.uuu` 下载控制脚本文件,根据需要修改。 6. `uuu` `uuu.exe` linux和windows的可执行文件,两个系统都可以下载,方便! `imx93-emmc.uuu` 脚本 ```bash uuu_version 1.5.163 # Please Replace below items with actually file names # @_flash.bin                        | boot loader, flash.bin # @_Image                        | kernel image, arm64 is Image, arm32 it is zImage, here is Image # @_board.dtb                        | board dtb file, here is imx93-11x11-evk.dtb # @_initramfs.cpio.gz.uboot        | mfgtool init ramfs, here is fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.zst.u-boot # @_rootfs.tar.zst                | rootfs, here is imx-image-multimedia-imx93evk.tar.zst # @_uTee.tar                        | optee image, put dummy _uTee.tar file here if platform is not MX6/MX7* # This command will be run when i.MX6/7 i.MX8MM, i.MX8MQ SDP: boot -f boot/flash.bin # This command will be run when ROM support stream mode # i.MX8QXP, i.MX8QM SDPS: boot -f boot/flash.bin # SDPU will be deprecated. please use SDPV instead of SDPU # { SDPU: delay 1000 SDPU: write -f boot/flash.bin -offset 0x57c00 SDPU: jump # } # These commands will be run when use SPL and will be skipped if no spl # if (SPL support SDPV) # { SDPV: delay 1000 SDPV: write -f boot/flash.bin -skipspl SDPV: jump # } # use uboot burn bootloader to eMMC # becaue difference chip, offset is difference # you can use kernel to do that for specific boards FB: ucmd setenv fastboot_dev mmc FB: ucmd setenv mmcdev ${emmc_dev} FB: flash bootloader boot/flash.bin FB: ucmd if env exists emmc_ack; then ; else setenv emmc_ack 0; fi; FB: ucmd setenv emmc_cmd mmc partconf ${emmc_dev} ${emmc_ack} 1 0 FB: ucmd if test "${emmc_skip_fb}" != "yes"; then run emmc_cmd; fi FB: ucmd setenv emmc_cmd mmc bootbus ${emmc_dev} 2 0 1; FB: ucmd if test "${emmc_skip_fb}" != "yes"; then run emmc_cmd; fi FB: ucmd setenv fastboot_buffer ${loadaddr} FB: download -f boot/Image FB: ucmd setenv fastboot_buffer ${fdt_addr} FB: download -f boot/myir-imx93-11x11.dtb FB: ucmd setenv fastboot_buffer ${initrd_addr} FB: download -f fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.zst.u-boot #FB: ucmd setenv bootargs console=${console},${baudrate} earlycon=${earlycon},${baudrate} FB: acmd ${kboot} ${loadaddr} ${initrd_addr} ${fdt_addr} # get mmc dev number from kernel command line # Wait for emmc FBK: ucmd while [ ! -e /dev/mmcblk*boot0 ]; do sleep 1; echo "wait for /dev/mmcblk*boot* appear"; done; # serach emmc device number, if your platform have more than two emmc chip, please echo dev number >/tmp/mmcdev FBK: ucmd dev=`ls /dev/mmcblk*boot*`; dev=($dev); dev=${dev[0]}; dev=${dev#/dev/mmcblk}; dev=${dev%boot*}; echo $dev > /tmp/mmcdev; # dd to clear the possible MBR FBK: ucmd mmc=`cat /tmp/mmcdev`; dd if=/dev/zero of=/dev/mmcblk${mmc} bs=512 count=1 # create partition FBK: ucmd mmc=`cat /tmp/mmcdev`; PARTSTR=$'8M,120M,0c\n,5120M,83\n,128M,83\n5416M,,83\n'; echo "$PARTSTR" | sfdisk --force /dev/mmcblk${mmc} FBK: ucmd sync # FAT FBK: ucmd mmc=`cat /tmp/mmcdev`; while [ ! -e /dev/mmcblk${mmc}p1 ]; do sleep 1; done FBK: ucmd mmc=`cat /tmp/mmcdev`; mkfs.vfat /dev/mmcblk${mmc}p1 FBK: ucmd mmc=`cat /tmp/mmcdev`; mkdir -p /mnt/fat FBK: ucmd mmc=`cat /tmp/mmcdev`; mount -t vfat /dev/mmcblk${mmc}p1 /mnt/fat FBK: ucp  boot/Image t:/mnt/fat FBK: ucp  boot/myir-imx93-11x11.dtb t:/mnt/fat FBK: ucp  boot/myir-imx93-11x11-root.dtb t:/mnt/fat FBK: ucmd sync FBK: ucmd umount /mnt/fat # ROOTFS FBK: ucmd mmc=`cat /tmp/mmcdev`; mkfs.ext4 -F /dev/mmcblk${mmc}p2 FBK: ucmd mkdir -p /mnt/ext4 FBK: ucmd mmc=`cat /tmp/mmcdev`; mount /dev/mmcblk${mmc}p2 /mnt/ext4 FBK: acmd export EXTRACT_UNSAFE_SYMLINKS=1; tar --warning=no-timestamp -xz -C /mnt/ext4 FBK: ucp filesystem/rootfs.tar.gz t:- FBK: ucmd sync # PARAMETER FBK: ucmd mmc=`cat /tmp/mmcdev`; mkfs.ext4 -F /dev/mmcblk${mmc}p3 FBK: ucmd sync # APPFS FBK: ucmd mmc=`cat /tmp/mmcdev`; mkfs.ext4 -F /dev/mmcblk${mmc}p4 FBK: ucmd sync # modules FBK: ucmd mkdir -p /mnt/ext4/lib/modules FBK: acmd tar  --warning=no-timestamp -x -C /mnt/ext4/lib/modules FBK: ucp modules/modules.tar.gz t:- FBK: ucmd sync FBK: ucmd umount /mnt/ext4 FBK: DONE ``` ## 下载 设置拨码开关为USB下载,执行指令,重新上电启动,即开始下载。 ```bash # Windows环境 .\uuu.exe .\imx93-emmc.uuu # Linux环境 ./uuu ./imx93-emmc.uuu ``` 下载完成,设置eMMC启动,重新上电检查。 ## WLAN驱动问题 上电启动后,自带的WLAN驱动好像有点问题。但是不影响使用,有时间再回头看这个问题。输入root登录系统。

  • 2024-08-11
  • 回复了主题帖: 【米尔 NXP i.MX93 开发板评测】IMX93视频播放性能测试

    lugl4313820 发表于 2024-8-10 22:56   大佬,是不是太激动了,好象是多了一位数,或者多了一个零。 没有错,Linux和windows系统CPU占用率表示方式不一样: Linux系统根据系统有多少个CPU核心来确定总使用率,iMX.93有两个核心,最大CPU使用率为200%

  • 发表了主题帖: 【米尔 NXP i.MX93 开发板评测】RAMDISK实践

    # RAMDISK实践 > 编译开发板自带的内核源码,制作一个`RAMDISK`,放到SD卡中加载测试内核;由于UBOOT功能有限,可以使用ramdisk添加更高级的维护功能,比如设备升级与工厂生产刷机。后面我们实现升级功能时会用到。 ## 制作RAMDISK 使用`busybox`生成一个精简`initramdisk` ### 内核编译 参考米尔文档 《MYD-LMX9X_Linux软件开发指南.pdf》 ```bash # 配置交叉编译器 source /opt/fsl-imx-xwayland/6.1-mickledore/environment-setuparmv8a-poky-linux cd MYD-LMX9X-Linux-L6.1.55-V1.0.0 ./build-linux-zh.sh # 选择编译线程数,等待一会儿编译成功后会生成output目录 cd output output$ ll -h 总计 65M drwxrwxr-x 2 bruce bruce 4.0K Aug 11 06:42 ./ drwxrwxr-x 4 bruce bruce 4.0K Aug 11 06:31 ../ -rw-rw-r-- 1 bruce bruce  34M Aug 11 06:42 Image -rw-rw-r-- 1 bruce bruce  31M Aug 11 06:42 modules.tar.gz -rw-rw-r-- 1 bruce bruce  45K Aug 11 06:42 myir-imx93-11x11.dtb -rw-rw-r-- 1 bruce bruce  47K Aug 11 06:42 myir-imx93-11x11-lvds-10-1.dtb -rw-rw-r-- 1 bruce bruce  46K Aug 11 06:42 myir-imx93-11x11-lvds.dtb -rw-rw-r-- 1 bruce bruce  46K Aug 11 06:42 myir-imx93-11x11-RGB.dtb -rw-rw-r-- 1 bruce bruce  45K Aug 11 06:42 myir-imx93-11x11-root.dtb ``` 重新配置内核,支持`RAM block device` ```bash # 进入内核源代码目录 cd myir-imx-linux # 配置 make menuconfig # 将RAM block驱动编译进内核 Device Drivers  --->         Block devices  --->                    RAM block device support                         (1)     Default number of RAM disks                         (65536) Default RAM disk size (kbytes) make # 生成我们需要的 arch/arm64/boot/Image ``` **注意:**这里不能使用`./build-linux-zh.sh`,脚本编译时会再次使用DEFCONFIG生成配置文件`.config`,会将我们设置好的配置清除掉。如果想用,可以重新拷贝一份deconfig,配置好`RAM DISK`,然后替代这里的 `DEFCONFIG="imx_v8_defconfig"` ```shell DEFCONFIG="imx_v8_defconfig" compile_linux(){     echo "开始配置内核"     cd ${LOACL_PATH}/${LINUX_NAME}     make ${DEFCONFIG} > /dev/null 2>&1     echo "开始编译内核"     LDFLAGS="" CC="$CC" make -j ${THREAD_NUM}  > /dev/null 2>&1 &     make_pid=$!     bar_test ${make_pid}     echo "编译完成" } ``` ### update.sh 编写刷机脚本 `update.sh`,需要添加执行权限 ```bash #!/bin/sh # eMMC device node node=/dev/mmcblk0 # size in MB BOOT_ROM_SIZE=8 ROOT_FS_SIZE=5120 PARAM_FS_SIZE=128 APP_FS_START=5416 mount -o remount,rw / # wait for the SD/MMC device node ready while [ ! -e ${node} ] do         sleep 1         echo "wait for ${node} appear" done # TODO: check eMMC partitions EMMC_PARTITIONS=("/dev/mmcblk0p1" "/dev/mmcblk0p2" "/dev/mmcblk0p3") for PARTITION in "${EMMC_PARTITIONS[@]}"; do         if [ -e "$PARTITION" ]; then                 echo "$PARTITION exist."         else                 echo "$PARTITION not exist."         fi done # call sfdisk to create partition table # destroy the partition table dd if=/dev/zero of=${node} bs=1024 count=1 # p1 8M    ~ 128M   FAT(120MB) # p2 128M  ~ 5248M  ROOTFS(5GB) # p3 5248M ~ 5376   PARAM(128MB) # p4 5376  ~ END    APP(left) echo ">>> sfdisk ${node}" sfdisk --force ${node} /sys/block/mmcblk0boot0/force_ro         dd if=/mnt/flash/flash.bin of=/dev/mmcblk0boot0 conv=fsync         echo 1 > /sys/block/mmcblk0boot0/force_ro         mmc bootpart enable 1 1 /dev/mmcblk0 fi while [ ! -e /dev/mmcblk0p1 ] do         sleep 1         echo "waiting... /dev/mmcblk0p1" done # burn dtb and Image if [ -f /mnt/flash/Image ] then         echo ">>> copy dtb and Image -> /dev/mmcblk0p1"         mkfs.vfat /dev/mmcblk0p1         mkdir -p /tmp/kernel         mount -t vfat /dev/mmcblk0p1 /tmp/kernel         cp /mnt/flash/Image /tmp/kernel         cp /mnt/flash/imx93-11x11-atk.dtb /tmp/kernel         cp /mnt/flash/ramdisk.img.gz /tmp/kernel         sync         umount /tmp/kernel fi # burn rootfs if [ -f /mnt/flash/rootfs.tar ] then         echo ">>> burn rootfs -> /dev/mmcblk0p2"         # mkfs.ext4 -F -E nodiscard /dev/mmcblk0p2         mkfs.ext4 -F /dev/mmcblk0p2         mkdir -p /tmp/rootfs         mount -t ext4 /dev/mmcblk0p2 /tmp/rootfs         tar -xf /mnt/flash/rootfs.tar -C /tmp/rootfs         sync         umount /tmp/rootfs fi # parameter: 128MB mkfs.ext4 -F -E nodiscard /dev/mmcblk0p3 # APP: using left space mkfs.ext4 -F -E nodiscard /dev/mmcblk0p4 sync sleep 1 echo ">>>>>>>>>>> DONE

  • 2024-08-09
  • 发表了主题帖: 【米尔 NXP i.MX93 开发板评测】IMX93视频播放性能测试

    本帖最后由 小麦克 于 2024-8-9 18:04 编辑 # IMX93视频播放性能测试 iMX.93带两个64位Cortex-A55 CPU,主频1.7GHz,由于芯片内部没有H.264硬件编解码器,播放视频时必须依靠CPU进行软解,而H.264编解码非常耗资源。 Linux系统根据系统有多少个CPU核心来确定总使用率,iMX.93有两个核心,最大CPU使用率为200% 源视频为网上下载的4K高清视频,通过`ffmpeg`工具得到几个测试分辨率 ```bash ./ffmpeg.exe -i 7121088-uhd_2160_3840_25fps.mp4 -vf scale=1080:1920 video2_1080.mp4 ./ffmpeg.exe -i 7121088-uhd_2160_3840_25fps.mp4 -vf scale=720:1280 video2_720.mp4 ./ffmpeg.exe -i 7121088-uhd_2160_3840_25fps.mp4 -vf scale=540:960 video2_540.mp4 ``` 将视频上传到开发板 播放测试 ```bash gst-play --loop video_1920.mp4 ``` 测试视频信息 播放1920X1080 CPU占用率 测试结果如下: 1)1920X1080分辨率视频CPU占用率160%左右 2)1280X720p分辨率适配CPU占用率74%左右 3)960X540分辨率CPU占用率45%左右 由以上分析可知,实际应用中,考虑双向视频对讲是消耗资源最高的使用场景,使用不大于720p分辨率时应该可以满足项目需求。

  • 2024-08-05
  • 回复了主题帖: 【米尔 NXP i.MX93 开发板评测】U-BOOT SD卡加载镜像问题

    刚才使用正点原子的开发板测试了一下,测试了多遍,SD卡读取正常。使用同样的SD和程序。而且发现正点原子的SD卡读取速度明显更快。 这个问题可能需要找米尔的厂家支持一下。

  • 2024-08-04
  • 回复了主题帖: 【米尔 NXP i.MX93 开发板评测】U-BOOT SD卡加载镜像问题

    有谁遇到过这种情况的?

学过的课程

最近访客

< 1/2 >

统计信息

已有56人来访过

  • 芯积分:110
  • 好友:1
  • 主题:31
  • 回复:129

留言

你需要登录后才可以留言 登录 | 注册


450803313 2014-8-9
小麦克: 没有,我已经工作了
O ,是IT行业?
450803313 2014-8-8
hi,你最近在学zigbee?
查看全部