fbuild 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of fbuild might be problematic. Click here for more details.
- fbuild/__init__.py +0 -0
- fbuild/assets/example.txt +1 -0
- fbuild/build/__init__.py +117 -0
- fbuild/build/archive_creator.py +186 -0
- fbuild/build/binary_generator.py +444 -0
- fbuild/build/build_component_factory.py +131 -0
- fbuild/build/build_state.py +325 -0
- fbuild/build/build_utils.py +98 -0
- fbuild/build/compilation_executor.py +422 -0
- fbuild/build/compiler.py +165 -0
- fbuild/build/compiler_avr.py +574 -0
- fbuild/build/configurable_compiler.py +612 -0
- fbuild/build/configurable_linker.py +637 -0
- fbuild/build/flag_builder.py +186 -0
- fbuild/build/library_dependency_processor.py +185 -0
- fbuild/build/linker.py +708 -0
- fbuild/build/orchestrator.py +67 -0
- fbuild/build/orchestrator_avr.py +656 -0
- fbuild/build/orchestrator_esp32.py +797 -0
- fbuild/build/orchestrator_teensy.py +543 -0
- fbuild/build/source_compilation_orchestrator.py +220 -0
- fbuild/build/source_scanner.py +516 -0
- fbuild/cli.py +566 -0
- fbuild/cli_utils.py +312 -0
- fbuild/config/__init__.py +16 -0
- fbuild/config/board_config.py +457 -0
- fbuild/config/board_loader.py +92 -0
- fbuild/config/ini_parser.py +209 -0
- fbuild/config/mcu_specs.py +88 -0
- fbuild/daemon/__init__.py +34 -0
- fbuild/daemon/client.py +929 -0
- fbuild/daemon/compilation_queue.py +293 -0
- fbuild/daemon/daemon.py +474 -0
- fbuild/daemon/daemon_context.py +196 -0
- fbuild/daemon/error_collector.py +263 -0
- fbuild/daemon/file_cache.py +332 -0
- fbuild/daemon/lock_manager.py +270 -0
- fbuild/daemon/logging_utils.py +149 -0
- fbuild/daemon/messages.py +301 -0
- fbuild/daemon/operation_registry.py +288 -0
- fbuild/daemon/process_tracker.py +366 -0
- fbuild/daemon/processors/__init__.py +12 -0
- fbuild/daemon/processors/build_processor.py +157 -0
- fbuild/daemon/processors/deploy_processor.py +327 -0
- fbuild/daemon/processors/monitor_processor.py +146 -0
- fbuild/daemon/request_processor.py +401 -0
- fbuild/daemon/status_manager.py +216 -0
- fbuild/daemon/subprocess_manager.py +316 -0
- fbuild/deploy/__init__.py +17 -0
- fbuild/deploy/deployer.py +67 -0
- fbuild/deploy/deployer_esp32.py +314 -0
- fbuild/deploy/monitor.py +495 -0
- fbuild/interrupt_utils.py +34 -0
- fbuild/packages/__init__.py +53 -0
- fbuild/packages/archive_utils.py +1098 -0
- fbuild/packages/arduino_core.py +412 -0
- fbuild/packages/cache.py +249 -0
- fbuild/packages/downloader.py +366 -0
- fbuild/packages/framework_esp32.py +538 -0
- fbuild/packages/framework_teensy.py +346 -0
- fbuild/packages/github_utils.py +96 -0
- fbuild/packages/header_trampoline_cache.py +394 -0
- fbuild/packages/library_compiler.py +203 -0
- fbuild/packages/library_manager.py +549 -0
- fbuild/packages/library_manager_esp32.py +413 -0
- fbuild/packages/package.py +163 -0
- fbuild/packages/platform_esp32.py +383 -0
- fbuild/packages/platform_teensy.py +312 -0
- fbuild/packages/platform_utils.py +131 -0
- fbuild/packages/platformio_registry.py +325 -0
- fbuild/packages/sdk_utils.py +231 -0
- fbuild/packages/toolchain.py +436 -0
- fbuild/packages/toolchain_binaries.py +196 -0
- fbuild/packages/toolchain_esp32.py +484 -0
- fbuild/packages/toolchain_metadata.py +185 -0
- fbuild/packages/toolchain_teensy.py +404 -0
- fbuild/platform_configs/esp32.json +150 -0
- fbuild/platform_configs/esp32c2.json +144 -0
- fbuild/platform_configs/esp32c3.json +143 -0
- fbuild/platform_configs/esp32c5.json +151 -0
- fbuild/platform_configs/esp32c6.json +151 -0
- fbuild/platform_configs/esp32p4.json +149 -0
- fbuild/platform_configs/esp32s3.json +151 -0
- fbuild/platform_configs/imxrt1062.json +56 -0
- fbuild-1.1.0.dist-info/METADATA +447 -0
- fbuild-1.1.0.dist-info/RECORD +93 -0
- fbuild-1.1.0.dist-info/WHEEL +5 -0
- fbuild-1.1.0.dist-info/entry_points.txt +5 -0
- fbuild-1.1.0.dist-info/licenses/LICENSE +21 -0
- fbuild-1.1.0.dist-info/top_level.txt +2 -0
- fbuild_lint/__init__.py +0 -0
- fbuild_lint/ruff_plugins/__init__.py +0 -0
- fbuild_lint/ruff_plugins/keyboard_interrupt_checker.py +158 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Board configuration loader for Arduino boards.
|
|
3
|
+
|
|
4
|
+
This module provides functionality to load and parse board-specific configurations
|
|
5
|
+
from boards.txt files, extracting MCU type, frequency, and other build parameters.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Dict, Optional
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BoardConfigError(Exception):
|
|
13
|
+
"""Exception raised for board configuration errors."""
|
|
14
|
+
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class BoardConfig:
|
|
19
|
+
"""
|
|
20
|
+
Loader and parser for Arduino boards.txt configuration.
|
|
21
|
+
|
|
22
|
+
boards.txt files contain board-specific definitions like MCU type,
|
|
23
|
+
frequency, fuse settings, and other build parameters.
|
|
24
|
+
|
|
25
|
+
Example boards.txt entry:
|
|
26
|
+
uno.name=Arduino Uno
|
|
27
|
+
uno.build.mcu=atmega328p
|
|
28
|
+
uno.build.f_cpu=16000000L
|
|
29
|
+
uno.build.board=AVR_UNO
|
|
30
|
+
uno.build.core=arduino
|
|
31
|
+
uno.build.variant=standard
|
|
32
|
+
|
|
33
|
+
Usage:
|
|
34
|
+
# Load from boards.txt file
|
|
35
|
+
config = BoardConfig.from_boards_txt(Path("boards.txt"), "uno")
|
|
36
|
+
|
|
37
|
+
# Or create directly with known values
|
|
38
|
+
config = BoardConfig(
|
|
39
|
+
name="uno",
|
|
40
|
+
mcu="atmega328p",
|
|
41
|
+
f_cpu="16000000L",
|
|
42
|
+
board="AVR_UNO",
|
|
43
|
+
core="arduino",
|
|
44
|
+
variant="standard"
|
|
45
|
+
)
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
# Default Arduino Uno configuration (used as fallback)
|
|
49
|
+
UNO_DEFAULTS = {
|
|
50
|
+
"name": "Arduino Uno",
|
|
51
|
+
"mcu": "atmega328p",
|
|
52
|
+
"f_cpu": "16000000L",
|
|
53
|
+
"board": "AVR_UNO",
|
|
54
|
+
"core": "arduino",
|
|
55
|
+
"variant": "standard",
|
|
56
|
+
"vid": "0x2341",
|
|
57
|
+
"pid": "0x0043",
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Other common boards with defaults
|
|
61
|
+
BOARD_DEFAULTS = {
|
|
62
|
+
"uno": UNO_DEFAULTS,
|
|
63
|
+
"mega": {
|
|
64
|
+
"name": "Arduino Mega",
|
|
65
|
+
"mcu": "atmega2560",
|
|
66
|
+
"f_cpu": "16000000L",
|
|
67
|
+
"board": "AVR_MEGA2560",
|
|
68
|
+
"core": "arduino",
|
|
69
|
+
"variant": "mega",
|
|
70
|
+
},
|
|
71
|
+
"nano": {
|
|
72
|
+
"name": "Arduino Nano",
|
|
73
|
+
"mcu": "atmega328p",
|
|
74
|
+
"f_cpu": "16000000L",
|
|
75
|
+
"board": "AVR_NANO",
|
|
76
|
+
"core": "arduino",
|
|
77
|
+
"variant": "eightanaloginputs",
|
|
78
|
+
},
|
|
79
|
+
"leonardo": {
|
|
80
|
+
"name": "Arduino Leonardo",
|
|
81
|
+
"mcu": "atmega32u4",
|
|
82
|
+
"f_cpu": "16000000L",
|
|
83
|
+
"board": "AVR_LEONARDO",
|
|
84
|
+
"core": "arduino",
|
|
85
|
+
"variant": "leonardo",
|
|
86
|
+
},
|
|
87
|
+
"esp32-c3-devkitm-1": {
|
|
88
|
+
"name": "ESP32-C3 DevKit M-1",
|
|
89
|
+
"mcu": "esp32c3",
|
|
90
|
+
"f_cpu": "160000000L",
|
|
91
|
+
"board": "ESP32_DEV",
|
|
92
|
+
"core": "esp32",
|
|
93
|
+
"variant": "esp32c3",
|
|
94
|
+
},
|
|
95
|
+
"esp32-c6-devkitc-1": {
|
|
96
|
+
"name": "ESP32-C6 DevKit C-1",
|
|
97
|
+
"mcu": "esp32c6",
|
|
98
|
+
"f_cpu": "160000000L",
|
|
99
|
+
"board": "ESP32_DEV",
|
|
100
|
+
"core": "esp32",
|
|
101
|
+
"variant": "esp32c6",
|
|
102
|
+
},
|
|
103
|
+
"esp32-c6-devkitm-1": {
|
|
104
|
+
"name": "ESP32-C6 DevKit M-1",
|
|
105
|
+
"mcu": "esp32c6",
|
|
106
|
+
"f_cpu": "160000000L",
|
|
107
|
+
"board": "ESP32_DEV",
|
|
108
|
+
"core": "esp32",
|
|
109
|
+
"variant": "esp32c6",
|
|
110
|
+
},
|
|
111
|
+
"esp32-c5-devkitc-1": {
|
|
112
|
+
"name": "ESP32-C5 DevKit C-1",
|
|
113
|
+
"mcu": "esp32c5",
|
|
114
|
+
"f_cpu": "160000000L",
|
|
115
|
+
"board": "ESP32_DEV",
|
|
116
|
+
"core": "esp32",
|
|
117
|
+
"variant": "esp32c5",
|
|
118
|
+
},
|
|
119
|
+
"teensy40": {
|
|
120
|
+
"name": "Teensy 4.0",
|
|
121
|
+
"mcu": "imxrt1062",
|
|
122
|
+
"f_cpu": "600000000L",
|
|
123
|
+
"board": "TEENSY40",
|
|
124
|
+
"core": "teensy4",
|
|
125
|
+
"variant": "teensy40",
|
|
126
|
+
},
|
|
127
|
+
"teensy41": {
|
|
128
|
+
"name": "Teensy 4.1",
|
|
129
|
+
"mcu": "imxrt1062",
|
|
130
|
+
"f_cpu": "600000000L",
|
|
131
|
+
"board": "TEENSY41",
|
|
132
|
+
"core": "teensy4",
|
|
133
|
+
"variant": "teensy41",
|
|
134
|
+
},
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
def __init__(
|
|
138
|
+
self,
|
|
139
|
+
name: str,
|
|
140
|
+
mcu: str,
|
|
141
|
+
f_cpu: str,
|
|
142
|
+
board: str,
|
|
143
|
+
core: str = "arduino",
|
|
144
|
+
variant: str = "standard",
|
|
145
|
+
vid: Optional[str] = None,
|
|
146
|
+
pid: Optional[str] = None,
|
|
147
|
+
extra_flags: Optional[Dict[str, str]] = None,
|
|
148
|
+
):
|
|
149
|
+
"""
|
|
150
|
+
Initialize board configuration.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
name: Human-readable board name (e.g., "Arduino Uno")
|
|
154
|
+
mcu: Microcontroller type (e.g., "atmega328p")
|
|
155
|
+
f_cpu: CPU frequency (e.g., "16000000L")
|
|
156
|
+
board: Board identifier for defines (e.g., "AVR_UNO")
|
|
157
|
+
core: Core library name (default: "arduino")
|
|
158
|
+
variant: Variant directory name (default: "standard")
|
|
159
|
+
vid: USB Vendor ID (optional)
|
|
160
|
+
pid: USB Product ID (optional)
|
|
161
|
+
extra_flags: Additional board-specific flags (optional)
|
|
162
|
+
"""
|
|
163
|
+
self.name = name
|
|
164
|
+
self.mcu = mcu
|
|
165
|
+
self.f_cpu = f_cpu
|
|
166
|
+
self.board = board
|
|
167
|
+
self.core = core
|
|
168
|
+
self.variant = variant
|
|
169
|
+
self.vid = vid
|
|
170
|
+
self.pid = pid
|
|
171
|
+
self.extra_flags = extra_flags or {}
|
|
172
|
+
|
|
173
|
+
@property
|
|
174
|
+
def platform(self) -> str:
|
|
175
|
+
"""
|
|
176
|
+
Detect platform type from MCU.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
Platform identifier: "avr", "esp32", or "teensy"
|
|
180
|
+
"""
|
|
181
|
+
if self.mcu.startswith("atmega"):
|
|
182
|
+
return "avr"
|
|
183
|
+
elif self.mcu.startswith("esp32"):
|
|
184
|
+
return "esp32"
|
|
185
|
+
elif self.mcu.startswith("imxrt"):
|
|
186
|
+
return "teensy"
|
|
187
|
+
else:
|
|
188
|
+
# Default to AVR for unknown
|
|
189
|
+
return "avr"
|
|
190
|
+
|
|
191
|
+
@classmethod
|
|
192
|
+
def from_boards_txt(
|
|
193
|
+
cls,
|
|
194
|
+
boards_txt_path: Path,
|
|
195
|
+
board_id: str,
|
|
196
|
+
overrides: Optional[Dict[str, str]] = None,
|
|
197
|
+
) -> "BoardConfig":
|
|
198
|
+
"""
|
|
199
|
+
Load board configuration from a boards.txt file.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
boards_txt_path: Path to boards.txt file
|
|
203
|
+
board_id: Board identifier (e.g., "uno", "mega")
|
|
204
|
+
overrides: Optional overrides from platformio.ini
|
|
205
|
+
(e.g., board_build.mcu, board_build.f_cpu)
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
BoardConfig instance
|
|
209
|
+
|
|
210
|
+
Raises:
|
|
211
|
+
BoardConfigError: If file not found or board not defined
|
|
212
|
+
|
|
213
|
+
Example:
|
|
214
|
+
config = BoardConfig.from_boards_txt(
|
|
215
|
+
Path("hardware/arduino/avr/boards.txt"),
|
|
216
|
+
"uno"
|
|
217
|
+
)
|
|
218
|
+
"""
|
|
219
|
+
if not boards_txt_path.exists():
|
|
220
|
+
raise BoardConfigError(f"boards.txt not found: {boards_txt_path}")
|
|
221
|
+
|
|
222
|
+
# Parse boards.txt
|
|
223
|
+
board_data = cls._parse_boards_txt(boards_txt_path, board_id)
|
|
224
|
+
|
|
225
|
+
if not board_data:
|
|
226
|
+
raise BoardConfigError(f"Board '{board_id}' not found in {boards_txt_path}")
|
|
227
|
+
|
|
228
|
+
# Apply overrides from platformio.ini (board_build.*)
|
|
229
|
+
if overrides:
|
|
230
|
+
board_data.update(overrides)
|
|
231
|
+
|
|
232
|
+
# Extract required fields with validation
|
|
233
|
+
try:
|
|
234
|
+
return cls(
|
|
235
|
+
name=board_data.get("name", board_id),
|
|
236
|
+
mcu=board_data["mcu"],
|
|
237
|
+
f_cpu=board_data["f_cpu"],
|
|
238
|
+
board=board_data["board"],
|
|
239
|
+
core=board_data.get("core", "arduino"),
|
|
240
|
+
variant=board_data.get("variant", "standard"),
|
|
241
|
+
vid=board_data.get("vid"),
|
|
242
|
+
pid=board_data.get("pid"),
|
|
243
|
+
extra_flags={
|
|
244
|
+
k: v
|
|
245
|
+
for k, v in board_data.items()
|
|
246
|
+
if k
|
|
247
|
+
not in {
|
|
248
|
+
"name",
|
|
249
|
+
"mcu",
|
|
250
|
+
"f_cpu",
|
|
251
|
+
"board",
|
|
252
|
+
"core",
|
|
253
|
+
"variant",
|
|
254
|
+
"vid",
|
|
255
|
+
"pid",
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
)
|
|
259
|
+
except KeyError as e:
|
|
260
|
+
raise BoardConfigError(f"Board '{board_id}' is missing required field: {e}") from e
|
|
261
|
+
|
|
262
|
+
@classmethod
|
|
263
|
+
def from_board_id(cls, board_id: str, overrides: Optional[Dict[str, str]] = None) -> "BoardConfig":
|
|
264
|
+
"""
|
|
265
|
+
Load board configuration using built-in defaults.
|
|
266
|
+
|
|
267
|
+
This is a fallback when boards.txt is not available. It uses
|
|
268
|
+
hardcoded configurations for common Arduino boards.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
board_id: Board identifier (e.g., "uno", "mega")
|
|
272
|
+
overrides: Optional overrides (e.g., from platformio.ini)
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
BoardConfig instance
|
|
276
|
+
|
|
277
|
+
Raises:
|
|
278
|
+
BoardConfigError: If board_id not recognized
|
|
279
|
+
|
|
280
|
+
Example:
|
|
281
|
+
config = BoardConfig.from_board_id("uno")
|
|
282
|
+
"""
|
|
283
|
+
# Normalize board_id (handle common variations)
|
|
284
|
+
board_id = board_id.lower()
|
|
285
|
+
if board_id == "megaatmega2560":
|
|
286
|
+
board_id = "mega"
|
|
287
|
+
|
|
288
|
+
if board_id not in cls.BOARD_DEFAULTS:
|
|
289
|
+
raise BoardConfigError(f"Unknown board: {board_id}. " + f"Supported boards: {', '.join(cls.BOARD_DEFAULTS.keys())}")
|
|
290
|
+
|
|
291
|
+
board_data = cls.BOARD_DEFAULTS[board_id].copy()
|
|
292
|
+
|
|
293
|
+
# Apply overrides
|
|
294
|
+
if overrides:
|
|
295
|
+
board_data.update(overrides)
|
|
296
|
+
|
|
297
|
+
return cls(
|
|
298
|
+
name=board_data["name"],
|
|
299
|
+
mcu=board_data["mcu"],
|
|
300
|
+
f_cpu=board_data["f_cpu"],
|
|
301
|
+
board=board_data["board"],
|
|
302
|
+
core=board_data.get("core", "arduino"),
|
|
303
|
+
variant=board_data.get("variant", "standard"),
|
|
304
|
+
vid=board_data.get("vid"),
|
|
305
|
+
pid=board_data.get("pid"),
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
@staticmethod
|
|
309
|
+
def _parse_boards_txt(boards_txt_path: Path, board_id: str) -> Dict[str, str]:
|
|
310
|
+
"""
|
|
311
|
+
Parse boards.txt file and extract configuration for a specific board.
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
boards_txt_path: Path to boards.txt
|
|
315
|
+
board_id: Board identifier to extract
|
|
316
|
+
|
|
317
|
+
Returns:
|
|
318
|
+
Dictionary of board configuration keys and values
|
|
319
|
+
|
|
320
|
+
Example boards.txt format:
|
|
321
|
+
uno.name=Arduino Uno
|
|
322
|
+
uno.build.mcu=atmega328p
|
|
323
|
+
uno.build.f_cpu=16000000L
|
|
324
|
+
"""
|
|
325
|
+
board_data = {}
|
|
326
|
+
prefix = f"{board_id}."
|
|
327
|
+
|
|
328
|
+
try:
|
|
329
|
+
with open(boards_txt_path, "r", encoding="utf-8") as f:
|
|
330
|
+
for line in f:
|
|
331
|
+
line = line.strip()
|
|
332
|
+
|
|
333
|
+
# Skip comments and empty lines
|
|
334
|
+
if not line or line.startswith("#"):
|
|
335
|
+
continue
|
|
336
|
+
|
|
337
|
+
# Parse key=value pairs
|
|
338
|
+
if "=" not in line:
|
|
339
|
+
continue
|
|
340
|
+
|
|
341
|
+
key, value = line.split("=", 1)
|
|
342
|
+
key = key.strip()
|
|
343
|
+
value = value.strip()
|
|
344
|
+
|
|
345
|
+
# Only process lines for our board
|
|
346
|
+
if not key.startswith(prefix):
|
|
347
|
+
continue
|
|
348
|
+
|
|
349
|
+
# Remove board prefix and extract the field name
|
|
350
|
+
# uno.build.mcu -> mcu (from build.*)
|
|
351
|
+
# uno.name -> name
|
|
352
|
+
field = key[len(prefix) :]
|
|
353
|
+
|
|
354
|
+
# Handle build.* fields
|
|
355
|
+
if field.startswith("build."):
|
|
356
|
+
field = field[6:] # Remove 'build.' prefix
|
|
357
|
+
|
|
358
|
+
# Handle upload.* fields (vid, pid)
|
|
359
|
+
elif field.startswith("upload."):
|
|
360
|
+
field = field[7:] # Remove 'upload.' prefix
|
|
361
|
+
|
|
362
|
+
board_data[field] = value
|
|
363
|
+
|
|
364
|
+
except KeyboardInterrupt as ke:
|
|
365
|
+
from fbuild.interrupt_utils import handle_keyboard_interrupt_properly
|
|
366
|
+
|
|
367
|
+
handle_keyboard_interrupt_properly(ke)
|
|
368
|
+
except Exception as e:
|
|
369
|
+
raise BoardConfigError(f"Failed to parse {boards_txt_path}: {e}") from e
|
|
370
|
+
|
|
371
|
+
return board_data
|
|
372
|
+
|
|
373
|
+
def get_defines(self) -> Dict[str, str]:
|
|
374
|
+
"""
|
|
375
|
+
Get preprocessor defines for this board configuration.
|
|
376
|
+
|
|
377
|
+
Returns:
|
|
378
|
+
Dictionary of define names to values
|
|
379
|
+
|
|
380
|
+
Example:
|
|
381
|
+
{
|
|
382
|
+
'PLATFORMIO': '60118',
|
|
383
|
+
'F_CPU': '16000000L',
|
|
384
|
+
'ARDUINO': '10819',
|
|
385
|
+
'ARDUINO_AVR_UNO': '',
|
|
386
|
+
'ARDUINO_ARCH_AVR': '',
|
|
387
|
+
'__AVR_ATmega328P__': ''
|
|
388
|
+
}
|
|
389
|
+
"""
|
|
390
|
+
defines = {
|
|
391
|
+
"PLATFORMIO": "60118", # PlatformIO version identifier
|
|
392
|
+
"F_CPU": self.f_cpu,
|
|
393
|
+
"ARDUINO": "10819", # Arduino version (1.8.19)
|
|
394
|
+
f"ARDUINO_{self.board}": "",
|
|
395
|
+
"ARDUINO_ARCH_AVR": "",
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
# Add MCU-specific define (e.g., __AVR_ATmega328P__)
|
|
399
|
+
mcu_define = f"__AVR_{self.mcu.upper()}__"
|
|
400
|
+
defines[mcu_define] = ""
|
|
401
|
+
|
|
402
|
+
# Add any extra defines from board configuration
|
|
403
|
+
for key, value in self.extra_flags.items():
|
|
404
|
+
if key.startswith("define_"):
|
|
405
|
+
define_name = key[7:].upper()
|
|
406
|
+
defines[define_name] = value
|
|
407
|
+
|
|
408
|
+
return defines
|
|
409
|
+
|
|
410
|
+
def get_include_paths(self, core_path: Path) -> list[Path]:
|
|
411
|
+
"""
|
|
412
|
+
Get include paths for compilation.
|
|
413
|
+
|
|
414
|
+
Args:
|
|
415
|
+
core_path: Path to Arduino core installation
|
|
416
|
+
|
|
417
|
+
Returns:
|
|
418
|
+
List of include directory paths
|
|
419
|
+
|
|
420
|
+
Example:
|
|
421
|
+
[
|
|
422
|
+
Path('/path/to/cores/arduino'),
|
|
423
|
+
Path('/path/to/variants/standard')
|
|
424
|
+
]
|
|
425
|
+
"""
|
|
426
|
+
return [
|
|
427
|
+
core_path / "cores" / self.core,
|
|
428
|
+
core_path / "variants" / self.variant,
|
|
429
|
+
]
|
|
430
|
+
|
|
431
|
+
def get_core_sources_dir(self, core_path: Path) -> Path:
|
|
432
|
+
"""
|
|
433
|
+
Get path to core source files directory.
|
|
434
|
+
|
|
435
|
+
Args:
|
|
436
|
+
core_path: Path to Arduino core installation
|
|
437
|
+
|
|
438
|
+
Returns:
|
|
439
|
+
Path to core sources (e.g., cores/arduino)
|
|
440
|
+
"""
|
|
441
|
+
return core_path / "cores" / self.core
|
|
442
|
+
|
|
443
|
+
def get_variant_dir(self, core_path: Path) -> Path:
|
|
444
|
+
"""
|
|
445
|
+
Get path to board variant directory.
|
|
446
|
+
|
|
447
|
+
Args:
|
|
448
|
+
core_path: Path to Arduino core installation
|
|
449
|
+
|
|
450
|
+
Returns:
|
|
451
|
+
Path to variant directory (e.g., variants/standard)
|
|
452
|
+
"""
|
|
453
|
+
return core_path / "variants" / self.variant
|
|
454
|
+
|
|
455
|
+
def __repr__(self) -> str:
|
|
456
|
+
"""String representation of board configuration."""
|
|
457
|
+
return f"BoardConfig(name='{self.name}', mcu='{self.mcu}', f_cpu='{self.f_cpu}', board='{self.board}')"
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Board configuration loading utilities.
|
|
2
|
+
|
|
3
|
+
This module provides utilities for loading board configurations with support
|
|
4
|
+
for both built-in boards and platform-specific boards (ESP32, etc.).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Dict
|
|
8
|
+
|
|
9
|
+
from .board_config import BoardConfig, BoardConfigError
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BoardConfigLoader:
|
|
13
|
+
"""Utility class for loading board configurations with platform detection."""
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def load_board_config(board_id: str, env_config: Dict) -> BoardConfig:
|
|
17
|
+
"""
|
|
18
|
+
Load board configuration with platform-specific handling.
|
|
19
|
+
|
|
20
|
+
This method first attempts to load the board from built-in defaults.
|
|
21
|
+
If that fails and the platform is ESP32, it creates a minimal BoardConfig
|
|
22
|
+
with MCU detection based on the board ID.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
board_id: Board identifier (e.g., 'uno', 'esp32dev')
|
|
26
|
+
env_config: Environment configuration from platformio.ini
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
BoardConfig instance
|
|
30
|
+
|
|
31
|
+
Raises:
|
|
32
|
+
BoardConfigError: If board configuration cannot be loaded
|
|
33
|
+
"""
|
|
34
|
+
# Extract overrides from env_config (board_build.*)
|
|
35
|
+
overrides = {}
|
|
36
|
+
for key, value in env_config.items():
|
|
37
|
+
if key.startswith("board_build."):
|
|
38
|
+
override_key = key[12:] # Remove 'board_build.' prefix
|
|
39
|
+
overrides[override_key] = value
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
# Try to load from built-in defaults first
|
|
43
|
+
return BoardConfig.from_board_id(board_id, overrides)
|
|
44
|
+
except BoardConfigError:
|
|
45
|
+
# Check if this is an ESP32 board by looking at platform URL
|
|
46
|
+
platform_url = env_config.get("platform", "")
|
|
47
|
+
if "espressif32" in platform_url or "esp32" in platform_url.lower():
|
|
48
|
+
# For ESP32 boards, create a minimal BoardConfig
|
|
49
|
+
# The actual board JSON will be loaded by ESP32Platform
|
|
50
|
+
mcu = BoardConfigLoader._detect_esp32_mcu(board_id)
|
|
51
|
+
|
|
52
|
+
return BoardConfig(
|
|
53
|
+
name=board_id,
|
|
54
|
+
mcu=mcu,
|
|
55
|
+
f_cpu="240000000L", # Default ESP32 frequency
|
|
56
|
+
board="ESP32_DEV",
|
|
57
|
+
core="esp32",
|
|
58
|
+
variant="esp32",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# If not ESP32, re-raise original error
|
|
62
|
+
raise BoardConfigError(f"Unknown board: {board_id}\n" + "Supported AVR boards: uno, mega, nano, leonardo\n" + "For ESP32 boards, ensure platform URL contains 'espressif32'")
|
|
63
|
+
|
|
64
|
+
@staticmethod
|
|
65
|
+
def _detect_esp32_mcu(board_id: str) -> str:
|
|
66
|
+
"""
|
|
67
|
+
Detect ESP32 MCU variant from board ID.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
board_id: Board identifier
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
MCU identifier (esp32, esp32s3, esp32c3, etc.)
|
|
74
|
+
"""
|
|
75
|
+
board_id_lower = board_id.lower()
|
|
76
|
+
|
|
77
|
+
# Check for specific ESP32 variants
|
|
78
|
+
if "esp32s3" in board_id_lower or "esp32-s3" in board_id_lower:
|
|
79
|
+
return "esp32s3"
|
|
80
|
+
elif "esp32s2" in board_id_lower or "esp32-s2" in board_id_lower:
|
|
81
|
+
return "esp32s2"
|
|
82
|
+
elif "esp32c3" in board_id_lower or "esp32-c3" in board_id_lower:
|
|
83
|
+
return "esp32c3"
|
|
84
|
+
elif "esp32c6" in board_id_lower or "esp32-c6" in board_id_lower:
|
|
85
|
+
return "esp32c6"
|
|
86
|
+
elif "esp32c2" in board_id_lower or "esp32-c2" in board_id_lower:
|
|
87
|
+
return "esp32c2"
|
|
88
|
+
elif "esp32h2" in board_id_lower or "esp32-h2" in board_id_lower:
|
|
89
|
+
return "esp32h2"
|
|
90
|
+
else:
|
|
91
|
+
# Default to esp32
|
|
92
|
+
return "esp32"
|