Arduino中添加自定义板卡

参考链接:

参考工程:

基本步骤:

  1. 下载现有的bsp并复制一份
  2. 更新定义文件(variant.h、varient.cpp)
  3. 创建Board条目(Board.txt)
  4. 更新Board版本 (platform.txt)
  5. 准备安装 (json)
  6. 在 Arduino IDE 中安装开发板

对于Windows的bsp路径位于:C:\Users\username\AppData\Local\Arduino15\packages\

其中一般的目录结构如下:

  • arduino:厂家名字
    • hardware:硬件
      • samd:某一系列芯片
        • 1.8.11:对应的bsp版本号
          • bootloaders
          • drivers:该系列芯片需要的驱动
          • libraries:常用库
          • variants:具体的bsp和引脚配置
            • arduino_zero:具体板卡
              • variant.cpp/variant.h:gpio编号定义
            • xxx:其他板卡
          • boards.txt:包含每个板卡的构建与配置信息
          • platform.txt:包含板卡的编译信息
    • tools:工具

Arduino平台规范

这是 Arduino 平台规范,用于从 Arduino IDE 1.5.x 系列开始的 Arduino 开发软件。

Platforms 为 Arduino 开发软件添加了对新板的支持。它们可以通过 Boards Manager 或手动安装到 Arduino 的 Sketchbook 文件夹(又名“用户目录”)的 hardware 文件夹中。

一个平台可能只包含一个配置文件。

hardware文件夹结构

新的hardware文件夹具有分为两个级别的层次结构:

  • 第一级是vendor/maintainer(供应商/维护者)
  • 第二级是支持的架构

vendor/maintainer(供应商/维护者)可以有多个受支持的架构。例如,下面我们有三个硬件供应商,分别称为“arduino”、“yyyyy”和“xxxxx”:

1
2
3
4
hardware/arduino/avr/...     - Arduino - AVR Boards
hardware/arduino/sam/... - Arduino - SAM (32bit ARM) Boards
hardware/yyyyy/avr/... - Yyy - AVR
hardware/xxxxx/avr/... - Xxx - AVR
  • 供应商“arduino”有两种支持的架构(AVR 和 SAM),而“xxxxx”和“yyyyy”只有 AVR。

架构文件夹区分大小写(例如 AVR != avr)。

如果可能,在创建硬件包(hardware packages)时遵循现有的体系结构命名约定。使用供应商文件夹名称来区分您的包。体系结构文件夹名称用于确定库兼容性并允许引用来自同一体系结构的另一个核心的资源,因此使用非标准体系结构名称可能会产生有害影响。

架构配置

每个架构都必须通过一组配置文件进行配置:

  • platform.txt:包含所用 CPU 架构的定义(编译器、构建过程参数、用于上传的工具等)
  • boards.txt:包含板的定义(板名称、构建和上传代码的参数等)
  • programmers.txt:包含外部程序员的定义(通常用于在空白 CPU/板卡上刻录引导加载程序)

配置文件格式

配置文件是“key=value”属性的列表。一个属性的值可以使用另一个属性的值来表示,方法是将其名称放在方括号“{”“}”中。例如:

1
2
3
4
compiler.path=/tools/g++_arm_none_eabi/bin/
compiler.c.cmd=arm-none-eabi-gcc
[....]
recipe.c.o.pattern={compiler.path}{compiler.c.cmd}
  • 在本示例中,recipe.c.o.pattern 属性将设置为 /tools/g++_arm_none_eabi/bin/arm-none-eabi-gcc,这是属性 compiler.path 和 compiler.c.cmd 的组合。
注释

以#开头的行被视为注释,将被忽略。

1
2
3
# Like in this example
# --------------------
# I'm a comment!
定操作系统的自动属性覆盖

我们可以为属性指定特定于操作系统的值。例如以下文件:

1
2
tools.bossac.cmd=bossac
tools.bossac.cmd.windows=bossac.exe
  • 将属性 tools.bossac.cmd 在 Linux 和 macOS 上设置为值 bossac,在 Windows 上设置为 bossac.exe。支持的后缀是 .linux、.windows 和 .macosx。
全局预定义属性

以下自动生成的属性可以在所有配置文件中全局使用:

  • {runtime.platform.path}: 板级文件夹的绝对路径(即包含boards.txt的文件夹)
  • {runtime.hardware.path}: hardware文件夹的绝对路径(即包含板级文件夹的文件夹)
  • {runtime.ide.path}: Arduino IDE 或 Arduino CLI 文件夹的绝对路径
  • {runtime.ide.version}: Arduino IDE 的版本号作为数字(每个版本号组件使用两位数字,并删除点和前导零,因此 Arduino IDE 1.8.3 变为 01.08.03,变为 runtime.ide.version=10803)。使用Arduino IDE以外的Arduino开发软件时,设置为无意义的版本号。
  • {ide_version}: {runtime.ide.version}的兼容性别名
  • {runtime.os}: 正在运行的操作系统(“linux”、“windows”、“macosx”)
  • {software}: 设置为"ARDUINO"
  • {name}: 平台供应商名称
  • {_id}: 正在编译的板卡 ID
  • {build.fqbn}: 正在编译的板卡的 FQBN(完全限定板名称)。 FQBN 遵循以下格式:: VENDOR:ARCHITECTURE:BOARD_ID[:MENU_ID=OPTION_ID[,MENU2_ID=OPTION_ID ...]]
  • {build.source.path}: 正在编译的用户编写代码的路径。如果改代码处于未保存状态,它将是其临时文件夹的路径。
  • {build.library_discovery_phase}: 在搜索库期间设置为 1,在正常构建期间设置为 0。使用此属性定义的宏可用于在搜索期间禁用重量级标头以减少编译时间。此属性已添加到 Arduino IDE 1.8.14/Arduino Builder 1.6.0/Arduino CLI 0.12.0。注意:出于同样的意图,在 Arduino Builder 1.5.3/Arduino CLI 0.10.0 中的库发现过程中,-DARDUINO_LIB_DISCOVERY_PHASE 被添加到 recipe.preproc.macros。该标志被更灵活的 {build.library_discovery_phase} 属性取代。
  • {compiler.optimization_flags}: 详见“用户代码调试配置”
  • {extra.time.utc}: Unix 时间(自 1970-01-01T00:00:00Z 以来的秒数),取决于运行构建的计算机
  • {extra.time.local}: 带有本地时区和 DST 偏移量的 Unix 时间
  • {extra.time.zone}: 没有 DST 组件的本地时区偏移量
  • {extra.time.dst}: 当地夏令时偏移

兼容性说明:Arduino IDE 1.6.0 之前的版本在 {runtime.ide.version} 中每个版本号组件仅使用一位数字(因此 1.5.9 是 159,而不是 10509)。

platform.txt

platform.txt 文件包含有关平台特定方面的信息(编译器命令行标志、路径、系统库等)。

必须定义以下元数据:

1
2
name=Arduino AVR Boards
version=1.5.3
  • name:显示为Arduino IDE的Board menu部分标题或arduino-cli core list输出的name字段
  • version:目前未使用,保留供将来使用(可能与Boards Manager一起处理对内核的依赖)

构建过程

platform.txt 文件用于配置构建过程。这是通过食谱(recipes)列表完成的。每个配方(recipe)都是一个命令行表达式,它解释了如何为每个构建步骤调用编译器(或其他工具)以及应该传递哪个参数。

Arduino 开发软件在开始构建之前确定要编译的文件列表。该列表由以下内容组成:

  • 用户的代码
  • 所选板核心中的源代码
  • 用户代码中使用的库中的源代码

创建一个临时文件夹来存储构建中的中间产物,其路径可通过全局属性 {build.path} 获得。还设置了带有项目名称的属性 {build.project_name} 和带有架构名称的属性 {build.arch}。

  • {build.path}: 用于存储构建过程中的临时文件夹的路径
  • {build.project_name}: 项目名称
  • {build.arch}: MCU 架构(avr、sam 等…)

还有一些其他的 {build.xxx} 属性可用,在本指南的 board.txt 部分进行了解释。

编译源代码的方法

我们说过 Arduino 开发软件确定要编译的文件列表。每个文件都可以是用 C(.c 文件)、C++(.cpp 文件)或汇编(.S 文件)编写的源代码。每种语言都使用其各自的配方(recipe)进行编译:

  • recipe.c.o.pattern: for C files
  • recipe.cpp.o.pattern: for CPP files
  • recipe.S.o.pattern: for Assembly files

可以通过连接以下自动生成的属性(对于编译的每个文件)来构建配方:

  • {includes}: 格式为“-I/include/path -I/another/path …”的包含路径列表
  • {source_file}: 源文件的路径
  • {object_file}: 输出文件的路径

例如,以下用于 AVR:

1
2
3
4
5
6
7
8
9
## Compiler global definitions
compiler.path={runtime.ide.path}/tools/avr/bin/
compiler.c.cmd=avr-gcc
compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections -MMD

[......]

## Compile c files
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
  • 请注意,某些属性(例如 {build.mcu})取自本规范稍后记录的 board.txt 文件。
构建 core.a 存档文件的方法

所选板的core按照上一段所述进行编译,但从编译中获得的目标文件也使用 recipe.ar.pattern 归档到名为 core.a 的静态库中。

可以通过连接以下自动生成的属性来构建:

  • {object_file}: 要包含在存档中的目标文件
  • {archive_file_path}: 完全限定的存档文件(例如“/path/to/core.a”)。此属性是在 Arduino IDE 1.6.6/arduino builder 1.0.0-beta12 中添加的,作为 {build.path}/{archive_file} 的替代品。
  • {archive_file}: 结果存档的名称(例如“core.a”)

例如,Arduino 为 AVR 提供了以下内容:

1
2
3
4
5
6
7
compiler.ar.cmd=avr-ar
compiler.ar.flags=rcs

[......]

## Create archives
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} "{archive_file_path}" "{object_file}"
链接的方法

前面步骤生成的所有工件(用户代码目标文件、库目标文件和 core.a 存档)都使用 recipe.c.combine.pattern 链接在一起。

可以通过连接以下自动生成的属性来构建配方:

  • {object_files}: 要包含在存档中的目标文件列表(“file1.o file2.o …”)
  • {archive_file_path}: 完全限定的存档文件(例如“/path/to/core.a”)。此属性是在 Arduino IDE 1.6.6/arduino builder 1.0.0-beta12 中添加的,作为 {build.path}/{archive_file} 的替代品。
  • {archive_file}: core存档文件的名称(例如“core.a”)
  • {compiler.libraries.ldflags}:预编译库的链接标志,包括自动生成的库路径的 -L 标志和库文件的 -l 标志,以及通过 library.properties 的 ldflags 字段提供的任何自定义标志。为了支持预编译库,platform.txt 必须包含 compiler.libraries.ldflags 的定义,任何自动生成的标志都将附加到该定义中。在 Arduino IDE 1.8.6/arduino-builder 1.4.0 中添加了对预编译库的支持。

例如,以下用于 AVR:

1
2
3
4
5
6
7
8
9
compiler.c.elf.flags=-Os -Wl,--gc-sections
compiler.c.elf.cmd=avr-gcc

compiler.libraries.ldflags=

[......]

## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} -o "{build.path}/{build.project_name}.elf" {object_files} {compiler.libraries.ldflags} "{archive_file_path}" "-L{build.path}" -lm
提取可执行文件和其他二进制数据的方法