feat(compiler): Serial = USB-CDC cuando boards.txt lo declara, como el hardware fisico
Tres piezas: - _arduino_board_flags lee <id>.build.board y <id>.build.cdc_on_boot de boards.txt (cache, mismo patron que _arduino_variant). - Cada compile escribe velxio_board.cmake (incluido OPTIONAL por el CMakeLists ANTES de project(), asi los defines llegan a TODOS los componentes — que Serial sea el CDC se decide dentro del core Arduino): ARDUINO_<BOARD> siempre que boards.txt lo nombre (los sketches de vendor hacen #ifdef ARDUINO_XIAO_ESP32S3), y ARDUINO_USB_CDC_ON_BOOT=1 + ARDUINO_USB_MODE=1 cuando cdc_on_boot=1. USB_MODE va FORZADO a 1 (HWCDC por USB-Serial-JTAG, la opcion de menu USBMode=hwcdc): el motor modela esa consola, no la pila OTG/TinyUSB. Ir por archivo y no por env hace el flag dependencia de configure: CMake reconfigura al cambiar. - CONFIG_ESP_CONSOLE_SECONDARY_NONE en el sdkconfig: sin ella el ROM/IDF espejan cada byte de log al USB y el monitor unico del emulador (que mezcla ambos streams) mostraria el log entero dos veces en builds CDC.
This commit is contained in:
parent
a419b13cb1
commit
e648f416ae
|
|
@ -10,5 +10,11 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/user_libs")
|
|||
list(APPEND EXTRA_COMPONENT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/user_libs")
|
||||
endif()
|
||||
|
||||
# Board identity defines written per-build by espidf_compiler (ARDUINO_<BOARD>,
|
||||
# ARDUINO_USB_CDC_ON_BOOT/ARDUINO_USB_MODE when boards.txt declares CDC). Must
|
||||
# run BEFORE project() so the definitions propagate to every component -- what
|
||||
# `Serial` IS gets decided inside the arduino core's own sources.
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/velxio_board.cmake OPTIONAL)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(velxio-sketch)
|
||||
|
|
|
|||
|
|
@ -57,6 +57,11 @@ CONFIG_FREERTOS_HZ=1000
|
|||
|
||||
# ── Console ──────────────────────────────────────────────────────────────
|
||||
CONFIG_ESP_CONSOLE_UART_DEFAULT=y
|
||||
# No secondary console: on USB-Serial-JTAG chips the ROM/IDF would mirror every
|
||||
# log byte to the USB console too, and the emulator merges both streams into ONE
|
||||
# serial monitor -- the whole log would show twice on CDC builds. Logs stay on
|
||||
# UART0; the USB channel carries only what the sketch prints through HWCDC.
|
||||
CONFIG_ESP_CONSOLE_SECONDARY_NONE=y
|
||||
|
||||
# ── Arduino-as-component: we provide our own app_main (main.cpp) ─────────
|
||||
CONFIG_AUTOSTART_ARDUINO=n
|
||||
|
|
|
|||
|
|
@ -546,6 +546,50 @@ class ESPIDFCompiler:
|
|||
self._variant_cache[key] = variant
|
||||
return variant
|
||||
|
||||
_board_flags_cache: dict = {}
|
||||
|
||||
def _arduino_board_flags(self, board_fqbn: str) -> dict:
|
||||
"""USB/identity flags for this FQBN from arduino-esp32's boards.txt.
|
||||
|
||||
Returns {'board': str|None, 'cdc_on_boot': bool}:
|
||||
- ``board``: the ``<id>.build.board`` name — arduino-cli defines
|
||||
``ARDUINO_<board>`` from it and vendor sketches #ifdef on it.
|
||||
- ``cdc_on_boot``: ``<id>.build.cdc_on_boot=1`` — on real hardware
|
||||
``Serial`` is then the USB CDC, not UART0. Boards like the XIAO
|
||||
ESP32S3 expose UART0's default RX pin (GPIO44) as a plain Dx pin,
|
||||
so building them with Serial on UART0 is not just unfaithful: a
|
||||
pinMode() on that pin tears the UART driver down mid-sketch.
|
||||
"""
|
||||
board_id = board_fqbn.split(':')[-1].split('?')[0].strip()
|
||||
if board_id in self._board_flags_cache:
|
||||
return self._board_flags_cache[board_id]
|
||||
flags = {'board': None, 'cdc_on_boot': False}
|
||||
roots = [
|
||||
r
|
||||
for r in (
|
||||
os.environ.get('ARDUINO_ESP32_V3_PATH', '/opt/arduino-esp32-3'),
|
||||
os.environ.get('ARDUINO_ESP32_PATH', '/opt/arduino-esp32'),
|
||||
)
|
||||
if r
|
||||
]
|
||||
for root in roots:
|
||||
boards_txt = Path(root) / 'boards.txt'
|
||||
if not boards_txt.is_file():
|
||||
continue
|
||||
try:
|
||||
text = boards_txt.read_text(encoding='utf-8', errors='ignore')
|
||||
except OSError:
|
||||
continue
|
||||
for line in text.splitlines():
|
||||
if line.startswith(f'{board_id}.build.board='):
|
||||
flags['board'] = line.split('=', 1)[1].strip() or None
|
||||
elif line.startswith(f'{board_id}.build.cdc_on_boot='):
|
||||
flags['cdc_on_boot'] = line.split('=', 1)[1].strip() == '1'
|
||||
if flags['board'] is not None:
|
||||
break
|
||||
self._board_flags_cache[board_id] = flags
|
||||
return flags
|
||||
|
||||
def _idf_target(self, board_fqbn: str) -> str:
|
||||
"""Map FQBN to IDF_TARGET."""
|
||||
if self._is_esp32c3(board_fqbn):
|
||||
|
|
@ -2811,6 +2855,36 @@ class ESPIDFCompiler:
|
|||
)
|
||||
defaults_path.write_text(rendered_sdkconfig, encoding='utf-8')
|
||||
|
||||
# Board identity defines (velxio_board.cmake, included OPTIONAL by the
|
||||
# template's top CMakeLists BEFORE project() so they reach EVERY
|
||||
# component — `Serial`'s mapping is decided inside the arduino core's
|
||||
# own sources, a sketch-only define cannot move it). Going through a
|
||||
# file instead of an env var makes it a configure dependency: CMake
|
||||
# re-runs when it changes, env vars it silently ignores.
|
||||
board_cmake_lines = ['# generated by espidf_compiler — do not edit']
|
||||
if arduino_mode and not pure_idf:
|
||||
flags = self._arduino_board_flags(board_fqbn)
|
||||
if flags['board']:
|
||||
macro = re.sub(r'[^A-Z0-9_]', '_', str(flags['board']).upper())
|
||||
board_cmake_lines.append(
|
||||
f'add_compile_definitions(ARDUINO_{macro})'
|
||||
)
|
||||
if flags['cdc_on_boot']:
|
||||
# USB_MODE is FORCED to 1 (HWCDC over USB-Serial-JTAG, the
|
||||
# boards.txt "USBMode=hwcdc" menu choice) even when the board's
|
||||
# default is 0 (USB-OTG/TinyUSB): the engine models the
|
||||
# Serial-JTAG console; the OTG device stack it does not.
|
||||
board_cmake_lines.append(
|
||||
'add_compile_definitions(ARDUINO_USB_CDC_ON_BOOT=1 ARDUINO_USB_MODE=1)'
|
||||
)
|
||||
board_cmake = '\n'.join(board_cmake_lines) + '\n'
|
||||
board_cmake_path = project_dir / 'velxio_board.cmake'
|
||||
prev_board_cmake = (
|
||||
board_cmake_path.read_text(encoding='utf-8') if board_cmake_path.exists() else None
|
||||
)
|
||||
if prev_board_cmake != board_cmake:
|
||||
board_cmake_path.write_text(board_cmake, encoding='utf-8')
|
||||
|
||||
# ESP-IDF only SEEDS sdkconfig from sdkconfig.defaults when sdkconfig is
|
||||
# ABSENT. Persistent build dirs live in the build volume and keep a
|
||||
# stale sdkconfig across image rebuilds, so a defaults change (a new
|
||||
|
|
|
|||
Loading…
Reference in New Issue