专栏首页twowinterzephyr笔记 2.1 应用程序开发基础

zephyr笔记 2.1 应用程序开发基础

1 前言

本篇笔记先做些应用开发的基础准备工作,官网英文教程见此

官方把这个教程放偏后的位置,导致我之前自己去学习 Cmake 和 Ninja 的相关知识,多做了一些重复工作。

我正在学习 Zephyr,一个很可能会用到很多物联网设备上的操作系统,如果你也感兴趣,可点此查看帖子zephyr学习笔记汇总

2 概览

Zephyr 根目录包含源码,内核配置选项以及编译定义。 根目录下的 application 目录负责 Zephyr 上的应用程序,包含所有与应用程序相关的文件,包括配置选项和源码。

一个应用程序目录一般是这样:

<home>/app
├── CMakeLists.txt
├── prj.conf
└── src
    └── main.c

CMakeLists.txt: 这个文件主要告诉 CMake 编译系统如何找到其他应用程序文件,包括硬件相关的内核配置文件,是否可以在硬件上运行或者debug程序等等。

Kernel configuration files: 每个应用文件都会提供一个配置文件(以 .conf 结尾),用于定义内核配置选项数值。如果忽视这个文件,或者无有效数值,则内核会使用默认的配置数值。

应用程序源码:应用程序的源码使用 C 或者汇编,通常都会放在 src 的子目录下。

3 Creating an Application

// 待补充,后面新建自己程序时再看。

4 编译应用程序 Build an Application

Zephyr 编译系统会编译并链接所有组件成为单个应用镜像。这里使用 ninja 来演示。

i. 基础介绍

1.进入应用程序目录 /app. 2.输入如下命令,将会按照 应用程序的 CMakeLists.txt 文件的设置,编译出应用程序的 zephyr.elf 镜像。

mkdir build
cd build
cmake -GNinja ..
ninja

如果需要,可以使用 CONF_FILE 参数,来指定相关的 .conf 文件来配置编译应用程序。这样设置将会覆盖原本的 .config 文件。例如:

# On Linux/macOS
export CONF_FILE=prj.alternate.conf
# On Windows
set CONF_FILE=prj.alternate.conf

cmake -GNinja ..
ninja

如果需要,可以为不同的硬件板子生成项目文件,通过定义环境变量 BOARD。

CONF_FILE 和 BOARD 参数都可以在编译应用时指定。

ii. 编译目录内容

<home>/app/build
├── build.ninja
├── CMakeCache.txt
├── CMakeFiles
├── cmake_install.cmake
├── rules.ninja
└── zephyr
  • build.ninja, 执行它可编译应用程序。
  • zephyr 目录,是编译生成文件的工作目录。

运行 ninja 后,编译输出的文件将会写入 zephyr 子目录。(这不是 Zephyr 根目录,不是 Zephyr 源码目录。)

  • .config, 包含配置信息,用来编译用的。
  • 各类 object 文件 (.o 文件 和 .a 文件) 包含了已编译的内核和应用源码。
  • zephyr.elf, 包含最终的连接应用和内核的二进制文件。其他二进制输出格式,例如 .hex 和 .bin,也都支持。

iii. 重编译应用程序

Zephyr 编译系统只重编译可能影响应用镜像的部分。因此重编译应用程序通常要比第一次要快。

如果需要强制重编译整个系统,可按照如下步骤: 1.打开控制台,进入编译目录/app/build。 2.输入如下命令,可删除应用程序生成的文件,但 .config 文件不会被删除掉。

ninja clean

或者,输入如下命令,可删除应用程序所有生成的文件,包括 .config 文件,它包含了应用程序根据板子类型生成的当前配置信息。

ninja pristine

3.之后可按照上面提到的“编译应用程序”步骤来编译。

5 运行应用程序

应用程序既可以在真实硬件板子上运行,也可以在模拟设备上运行。

在硬件板子上运行

1.编译应用程序。 2.保证你的板子连接到主机。通常都是USB连接。 3.在 build 目录 /app/build,运行如下控制台命令,将会把编译好的 Zephyr 二进制文件写入,并且运行到板子上。

ninja flash

Zephyr 编译系统集成了板子支持文件,使用硬件特定的工具来烧写 Zephyr 二进制文件到你的硬件,之后运行。

每次你运行 flash 命令,你的应用程序将会重编译并重新烧写。

如果板子支持不完全,通过 Zephyr 编译系统就可能无法烧写。如果你收到错误消息,需要到你的板子文档上确认如何烧写。

注意: 当 Linux 上开发时,通常需要安装 特定的 udev 规则,来使能非ROOT用户通过USB设备接入你的板子。如果烧写失败,需要到你的板子文档上确认。

6 自定义板子

7 应用程序调试

8 Eclipse Debugging

9 CMake Details

overview

CMake 用来编译应用程序和内核。CMake 编译分为两步,第一步称作 配置,配置期间,CMakeLists.txt 编译脚本会执行。配置结束后,CMake 便有了内部模型,可以生成针对主机的编译脚本。

CMake 支持为很多编译系统生成脚本,但目前 Zephyr 只支持 Ninja 和 Make 这两个编译系统。配置之后,开始执行生成的编译脚本。这些编译脚本可以重编译应用程序,而不需要执行 CMake。不管怎么样,变动之后,编译前都必须再执行配置步骤。编译脚本会检测这些情况,并自动重新配置,有些时候必须要手动。

Zephyr 使用 CMake 的’target’概念来识别编译。target 可以是可执行文件,一个库文件,或者一个生成文件。对于应用开发者,library target 是最需要了解的。所有的源码都是通过包含 library target 来编译。

Library targets 可以通过如下 CMakeLists.txt 编译脚本来加入源码。

target_sources(app PRIVATE src/main.c)

在上面的 CMakeLists.txt 中,已存在的 library target 名为 app,为其配置包含源码文件 src/main.c。PRIVATE 关键字表明我们正在修改内部。使用 PUBLIC 关键字可以修改链接的其他库文件。这种情况下,使用 PUBLIC 会导致链接 app 的其他 libraries 包含入 src/main.c,这是我们所不期望的。PUBLIC 关键词在修改包含路径是比较有用。

应用程序的 CMakeLists.txt

每个应用程序都必须包含 CMakeLists.txt,这个文件是编译系统的入口。最后的 zephyr.elf 镜像既包含应用程序也包含内核库。

这一小节描述如何在 CMakeLists.txt 进行操作。按照如下步骤执行。

1.如果要针对某个硬件编译,可以写如下语句:

set(BOARD qemu_x86)

2.应用程序都需要配置文件,正常是使用 prj.conf 文件。如果要特殊要求,可以使用 CONF_FILE 变量来定义。

10 Application Configuration

11 Application-Specific Code

12 总结

End

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 和ESP8266 Arduino谈场恋爱 03 玩几个例程

    在IDE工具栏上点击“File”->“Examples”->“ESP8266”->“Blink”

    twowinter
  • zephyr笔记 2.1.1 线程的生命周期

    http://docs.zephyrproject.org/kernel/threads/lifecycle.html

    twowinter
  • Redis 学习笔记 3.4 列表类型

    列表类型 (list) 可以存储一个有序的字符串列表,常用的操作是向列表的两端添加元素,或者获得列表的某一个片段。

    twowinter
  • .Net Micro Framework移植环境准备

    移植准备 .Net Micro Framework移植必须安装PK最新版本,可以从官网(http://netmf.codeplex.com/)下载,建议安装到C...

    大石头
  • R-批量文件读取

    文件的批量读取,一般在拿到数据时,如果是大批量的数据,那么就需要多次的读取 10个文件以为的内容通过10行的内容可以读取,但是如果是上百个文件,那么读取的 时候...

    用户7760819
  • 预处理--》编译--》运行的区别

    相信很多人懂这个问题,也很多人没想过,包括我,今天看书想到了就写下来。先看程序(抱歉在linux下没有找到舒服的可以复制terminal的工具,只好截图了,将就...

    s1mba
  • 如何保证static变量只初始化一次

    static变量分为两种情况:第一种是初始化为常量,在编译的时候就可以确定初始值;第二种是初始值在运行的时候才能确定,比如赋值为函数的返回值或 某个类的实例。

    gaigai
  • [现代编译原理C语言描述].(美国)Andrew.W.Appel.清晰版

    《现代编译原理:C语言描述》全面讲述了现代编译器的结构、编译算法和实现方法,是Andrew w.Apple的“虎书”——Modern Compiler Impl...

    用户3157710
  • java开发_STMP邮箱客户端_发送邮件

    http://zhiwenweb.cn/jszx/czxt/201009/20179.html

    Hongten
  • PHP-错误处理

    通过trigger_error产生一个用户级别的 error/warning/notice 信息

    cwl_java

扫码关注云+社区

领取腾讯云代金券