ExpressLRS开源代码之硬件管脚定义
1. 源由
硬件工程师更加侧重硬件设计,比如:sch, pcb layout, manufacture等相关方面的产品设计。
而往往很多时候再做嵌入式智能产品的时候,硬件需要结合既有软件的定义进行硬件IO的规划,比如:管脚定义。
同样的一个GPIO到底做什么用途,为什么要做这个用途,并非简单的硬件就能确定,往往需要从功能需求,在产品架构设计的时候就要考虑清楚。
随着嵌入式系统资源的日益丰富,嵌入式软件设计也慢慢从原有单片机汇编强耦合方式编程,逐步通过配置文件或者宏定义等方式来将软硬件管脚定义解耦。
下面我们就来谈谈ExpressLRS开源之硬件管脚定义。
2. 分析
ExpressLRS开源代码从软件设计的角度,是从Arduino框架进行应用开发的。在硬件管脚定义的解耦方面通过json文件格式进行定义。
从理解的角度,首先需要从ExpressLRS开源代码之工程结构开始入手,有兴趣的朋友可以走读下这个链接。
通过工程结构,可以非常快速的找到硬件和管脚定义的关联关系:
2.1 产品(product)
src\hardware\targets.json
e.g. plain
"plain": {
"product_name": "Generic ESP8285 SX127x 900MHz RX",
"lua_name": "ELRS 900RX",
"layout_file": "Generic 900.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp8285",
"firmware": "Unified_ESP8285_900_RX",
"prior_target_name": "DIY_900_RX_ESP8285_SX127x"
},
注:这里我们以generic这个系列产品为例,当然如果需要ELRS开发团队支持,那就需要按照ELRS要求的供应商规范,完成硬件认证。
届时,ELRS开发团队就会将系列产品添加到这个json文件中,作为认证通过的依据。
"generic": {
"name": "Generic targets used as a base",
"tx_900": {
"gemini": {
"product_name": "Generic ESP32 900MHz Gemini TX",
"lua_name": "Gemini 900TX",
"layout_file": "Generic 900 Gemini.json",
"upload_methods": ["uart", "wifi", "etx"],
"platform": "esp32",
"firmware": "Unified_ESP32_900_TX",
"prior_target_name": "Unified_ESP32_900_TX"
}
},
"rx_900": {
"plain": {
"product_name": "Generic ESP8285 SX127x 900MHz RX",
"lua_name": "ELRS 900RX",
"layout_file": "Generic 900.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp8285",
"firmware": "Unified_ESP8285_900_RX",
"prior_target_name": "DIY_900_RX_ESP8285_SX127x"
},
"pwmp": {
"product_name": "Generic ESP8285 SX127x with PWM 900MHz RX",
"lua_name": "ELRS PWMP 900RX",
"layout_file": "Generic 900 PWMP.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp8285",
"firmware": "Unified_ESP8285_900_RX",
"prior_target_name": "DIY_900_RX_PWMP"
},
"true_diversity": {
"product_name": "Generic ESP32 True Diversity PA 900MHz RX",
"lua_name": "Diversity 900RX",
"layout_file": "Generic 900 True Diversity PA.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp32",
"firmware": "Unified_ESP32_900_RX"
},
"true_diversity_pwm16": {
"product_name": "Generic ESP32 True Diversity 16xPWM 900MHz RX ",
"lua_name": "16PWM TD 900RX",
"layout_file": "Generic 900 True Diversity PWM 16.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp32",
"firmware": "Unified_ESP32_900_RX"
}
},
"tx_2400": {
"dupletx": {
"product_name": "Generic Full-duplex 2.4GHz TX",
"lua_name": "DupleTX",
"layout_file": "DIY 2400 DupleTX.json",
"upload_methods": ["uart", "wifi", "etx"],
"platform": "esp32",
"firmware": "Unified_ESP32_2400_TX",
"prior_target_name": "DIY_2400_TX_DUPLETX"
},
"dupletxesp": {
"product_name": "Generic ESP8285 Full-duplex 2.4GHz RX as TX",
"lua_name": "DupleTX ESP",
"layout_file": "DIY 2400 DupleTX ESP.json",
"upload_methods": ["uart", "wifi"],
"platform": "esp8285",
"firmware": "Unified_ESP8285_2400_TX",
"prior_target_name": "DIY_2400_TX_DUPLETX_ESP"
},
"gemini": {
"product_name": "Generic ESP32 2.4Ghz Gemini TX",
"lua_name": "Gemini 2.4TX",
"layout_file": "Generic 2400 Gemini.json",
"upload_methods": ["uart", "wifi", "etx"],
"platform": "esp32",
"firmware": "Unified_ESP32_2400_TX",
"prior_target_name": "DIY_2400_TX_GEMINI"
}
},
"rx_2400": {
"pp": {
"product_name": "Generic STM32 PP 2.4Ghz RX",
"upload_methods": ["stlink", "betaflight"],
"platform": "stm32",
"firmware": "DIY_2400_RX_STM32_CCG_Nano_v0_5",
"stlink": {
"cpus": ["STM32L432KCUx"],
"offset": "0x4000",
"bootloader": "sx1280_rx_nano_pcb_v0.5_bootloader.bin"
}
},
"plain": {
"product_name": "Generic ESP8285 2.4Ghz RX",
"lua_name": "ELRS 2400RX",
"layout_file": "Generic 2400.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp8285",
"firmware": "Unified_ESP8285_2400_RX",
"prior_target_name": "DIY_2400_RX_ESP8285_SX1280"
},
"pwm5": {
"product_name": "Generic ESP8285 5xPWM 2.4Ghz RX",
"lua_name": "ELRS+PWM 2400RX",
"layout_file": "Generic 2400 PWMP5.json",
"upload_methods": ["uart", "wifi"],
"platform": "esp8285",
"firmware": "Unified_ESP8285_2400_RX",
"prior_target_name": "DIY_2400_RX_PWMP"
},
"pwm6": {
"product_name": "Generic ESP8285 6xPWM 2.4Ghz RX",
"lua_name": "ELRS+PWM 2400RX",
"layout_file": "Generic 2400 PWMP6.json",
"upload_methods": ["uart", "wifi"],
"platform": "esp8285",
"firmware": "Unified_ESP8285_2400_RX",
"prior_target_name": "DIY_2400_RX_PWMPEX"
},
"pwm-vario": {
"product_name": "Generic ESP32 PWM Vario 2.4Ghz RX",
"lua_name": "Vario 2400RX",
"layout_file": "Vario 2400.json",
"upload_methods": ["uart", "wifi"],
"platform": "esp32",
"firmware": "Unified_ESP32_2400_RX",
"prior_target_name": "DIY_2400_RX_PWM_VARIO"
},
"pwm7": {
"product_name": "Generic ESP8285 7xPWM 2.4Ghz RX",
"lua_name": "ELRS+PWM 2400RX",
"layout_file": "Generic 2400 PWMP7.json",
"upload_methods": ["uart", "wifi"],
"platform": "esp8285",
"firmware": "Unified_ESP8285_2400_RX"
},
"pa": {
"product_name": "Generic ESP8285 PA 2.4Ghz RX",
"lua_name": "ELRS+PA 2400RX",
"layout_file": "Generic 2400 PA.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp8285",
"firmware": "Unified_ESP8285_2400_RX"
},
"pa-rgb": {
"product_name": "Generic ESP8285 RGB + PA 2.4Ghz RX",
"lua_name": "ELRS+RGB 2400RX",
"layout_file": "Generic 2400 PA RGB.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp8285",
"firmware": "Unified_ESP8285_2400_RX",
"prior_target_name": "DIY_2400_PA_RGB_RX"
},
"diversity": {
"product_name": "Generic ESP8285 Diversity PA 2.4Ghz RX",
"lua_name": "ELRS+D 2400RX",
"layout_file": "Generic 2400 Diversity PA.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp8285",
"firmware": "Unified_ESP8285_2400_RX"
},
"frank": {
"product_name": "Generic ESP32 2.4Ghz Franken RX",
"lua_name": "Frank 2400RX",
"layout_file": "Frank 2400.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp32",
"firmware": "Unified_ESP32_2400_RX"
},
"rx_vtx": {
"product_name": "Generic ESP32 2.4Ghz Rx and VTx",
"lua_name": "Rx+VTx 2400RX",
"layout_file": "Generic 2400 Whoop Rx and VTx.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp32",
"firmware": "Unified_ESP32_2400_RX"
},
"true_diversity": {
"product_name": "Generic ESP32 True Diversity PA 2.4Ghz RX",
"lua_name": "Diversity 2.4RX",
"layout_file": "Generic 2400 True Diversity PA.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp32",
"firmware": "Unified_ESP32_2400_RX"
},
"diversity_pa_vtx": {
"product_name": "Generic ESP32 True Diversity PA 2.4Ghz RX and VTx",
"lua_name": "Div+VTx 2.4RX",
"layout_file": "Generic 2400 True Diversity PA and VTx.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp32",
"firmware": "Unified_ESP32_2400_RX"
},
"diversity_vtx": {
"product_name": "Generic ESP32 True Diversity 2.4Ghz RX and VTx",
"lua_name": "Div+VTx 2.4RX",
"layout_file": "Generic 2400 True Diversity and VTx.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp32",
"firmware": "Unified_ESP32_2400_RX"
},
"true_diversity_pwm16": {
"product_name": "Generic ESP32 True Diversity 16xPWM 2.4Ghz RX ",
"lua_name": "16PWM TD 2.4RX",
"layout_file": "Generic 2400 True Diversity PWM 16.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp32",
"firmware": "Unified_ESP32_2400_RX"
},
"true_diversity_pwm14": {
"product_name": "Generic ESP32 True Diversity PA 14xPWM 2.4Ghz RX ",
"lua_name": "14PWM TD 2.4RX",
"layout_file": "Generic 2400 True Diversity PA PWM 14.json",
"upload_methods": ["uart", "wifi", "betaflight"],
"platform": "esp32",
"firmware": "Unified_ESP32_2400_RX"
}
}
},
2.2 目标(target)
src\targets\*.ini
e.g. diy_900.ini // 根据前面Generic系列,目标使用了DIY系列的配置DIY_900_RX_ESP8285_SX127x
注:这里取DIY系列产品中的一个900接收频段的接收机。
[env:DIY_900_RX_ESP8285_SX127x_via_UART]
extends = env:Unified_ESP8285_900_RX_via_UART
board_config = generic.rx_900.plain
[env:DIY_900_RX_ESP8285_SX127x_via_BetaflightPassthrough]
extends = env:DIY_900_RX_ESP8285_SX127x_via_UART
[env:DIY_900_RX_ESP8285_SX127x_via_WIFI]
extends = env:DIY_900_RX_ESP8285_SX127x_via_UART
2.3 目标抽象(Unified Target)
这里稍微提一下,src\targets\*.ini
下的文件名很多都是直接产品系列(品牌)命名,个人感觉可能是开发者认为需要统一一下硬件描述文件,所以做了一个额外的抽象。
src\targets\unified.ini
e.g. Unified_ESP8285_900_RX_via_UART //根据前面的例子,可以知道这个抽象目标(通常开发者/生产会使用串口烧录)
[env:Unified_ESP8285_900_RX_via_UART]
extends = env_common_esp82xx, radio_900
build_flags =
${env_common_esp82xx.build_flags}
${radio_900.build_flags}
${common_env_data.build_flags_rx}
-include target/Unified_ESP_RX.h
build_src_filter = ${env_common_esp82xx.build_src_filter} -<tx_*.cpp>
board_build.ldscript = ./elrs.flash.1m64.ld
2.4 MCU选型
src\targets\common.ini
e.g. env_common_esp82xx //根据前面的例子,可以知道这个MCU选型
# ------------------------- COMMON ESP82xx DEFINITIONS -----------------
[env_common_esp82xx]
platform = espressif8266@4.2.0
board = esp8285-8285
build_flags =
-D PLATFORM_ESP8266=1
-D VTABLES_IN_FLASH=1
-D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48
-D CONFIG_TCPIP_LWIP=1
-D BEARSSL_SSL_BASIC
-D USE_MSP_WIFI=1
-O2
-I ${PROJECTSRC_DIR}/hal
board_build.f_cpu = 160000000L
board_build.ldscript = eagle.flash.1m.ld
build_src_filter = ${common_env_data.build_src_filter} -<ESP32*.*> -<STM32*.*> -<WS281B*.*>
extra_scripts =
${env.extra_scripts}
pre:python/build_html.py
lib_deps =
makuna/NeoPixelBus @ 2.7.0
ottowinter/ESPAsyncWebServer-esphome @ 3.0.0
bblanchon/ArduinoJson @ 6.19.4
upload_speed = 460800
monitor_speed = 420000
monitor_filters = esp8266_exception_decoder
upload_resetmethod = nodemcu
2.5 管脚定义
在2.1章节中已经给出管脚定义(layout_file)
src\hardware\RXGeneric 900.json
{
"serial_rx": 3,
"serial_tx": 1,
"radio_dio0": 4,
"radio_dio1": 5,
"radio_miso": 12,
"radio_mosi": 13,
"radio_nss": 15,
"radio_rst": 2,
"radio_sck": 14,
"power_min": 0,
"power_high": 2,
"power_max": 2,
"power_default": 2,
"power_control": 0,
"power_values": [8,12,15],
"led": 16,
"button": 0
}
3. 总结
综上所述,Generic ESP8285 SX127x 900MHz RX产品使用:
- MCU:ESP8285
- IO Definition:
"serial_rx": 3,
"serial_tx": 1,
"radio_dio0": 4,
"radio_dio1": 5,
"radio_miso": 12,
"radio_mosi": 13,
"radio_nss": 15,
"radio_rst": 2,
"radio_sck": 14,
"led": 16,
"button": 0
4. 参考资料
【1】[ExpressLRS开源之接收机固件编译烧录步骤](https://blog.csdn.net/lida2003/article/details/132518813)
【2】ExpressLRS开源之RC链路性能测试
【3】ExpressLRS开源之基本调试数据含义
【4】ExpressLRS开源代码之框架结构
【5】ExpressLRS开源代码之工程结构
【6】ExpressLRS开源代码之接收机代码框架结构
【7】ExpressLRS开源代码之发射机代码框架结构