driverge-mcp 0.1.0-beta.2 → 0.1.0-beta.3
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.
- package/README.md +43 -26
- package/dist/codegen/esp32.d.ts +8 -5
- package/dist/codegen/esp32.js +124 -54
- package/dist/codegen/esp32.js.map +1 -1
- package/dist/codegen/lint.js +61 -9
- package/dist/codegen/lint.js.map +1 -1
- package/dist/codegen/portable-cpp.js +43 -38
- package/dist/codegen/portable-cpp.js.map +1 -1
- package/dist/codegen/portable.d.ts +20 -10
- package/dist/codegen/portable.js +157 -113
- package/dist/codegen/portable.js.map +1 -1
- package/dist/codegen/stm32.d.ts +8 -5
- package/dist/codegen/stm32.js +123 -53
- package/dist/codegen/stm32.js.map +1 -1
- package/dist/pdf/manufacturer.js +12 -0
- package/dist/pdf/manufacturer.js.map +1 -1
- package/dist/pdf/microchip-summary-table.d.ts +10 -0
- package/dist/pdf/microchip-summary-table.js +300 -0
- package/dist/pdf/microchip-summary-table.js.map +1 -0
- package/dist/pdf/onsemi-register-table.d.ts +7 -0
- package/dist/pdf/onsemi-register-table.js +271 -0
- package/dist/pdf/onsemi-register-table.js.map +1 -0
- package/dist/pdf/part.js +3 -0
- package/dist/pdf/part.js.map +1 -1
- package/dist/pdf/ti-field-descriptions.js +9 -3
- package/dist/pdf/ti-field-descriptions.js.map +1 -1
- package/dist/pdf/ti-register-map.js +44 -8
- package/dist/pdf/ti-register-map.js.map +1 -1
- package/dist/schema/assemble.js +15 -0
- package/dist/schema/assemble.js.map +1 -1
- package/package.json +1 -1
- package/schemas/datasheet.schema.json +4 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<p align="center"><em>Datasheet PDF → embedded C/C++ driver, from any MCP client.</em></p>
|
|
5
5
|
|
|
6
6
|
<p align="center">
|
|
7
|
-
<a href="https://www.npmjs.com/package/driverge-mcp"><img alt="npm" src="https://img.shields.io/npm/v/driverge-mcp"></a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/driverge-mcp"><img alt="npm (beta)" src="https://img.shields.io/npm/v/driverge-mcp/beta"></a>
|
|
8
8
|
<a href="https://github.com/MehmetTopuz/driverge-mcp/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/MehmetTopuz/driverge-mcp/actions/workflows/ci.yml/badge.svg"></a>
|
|
9
9
|
<a href="LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-blue"></a>
|
|
10
10
|
<img alt="status" src="https://img.shields.io/badge/status-closed%20beta-orange">
|
|
@@ -108,14 +108,16 @@ changes.
|
|
|
108
108
|
|
|
109
109
|
| Target | Bus binding | Buses | Language | Maturity |
|
|
110
110
|
|---|---|---|---|---|
|
|
111
|
-
| **Portable (thin-HAL)** | user-implemented
|
|
111
|
+
| **Portable (thin-HAL)** | user-implemented `<part>_hal_*` seam | I²C, SPI, UART, CAN | C / C++ | **Beta** — host-tested, gcc-compiled in CI; not yet on hardware |
|
|
112
112
|
| **ESP32** | ESP-IDF (`i2c_master_*`, `spi_master`, `uart`, TWAI) | I²C, SPI, UART, CAN | C / C++ | **Experimental** — one informal I²C bring-up; SPI/UART/CAN never on hardware |
|
|
113
|
-
| **STM32** | CubeHAL (`HAL_I2C_*`, `HAL_SPI_*` + GPIO CS, `HAL_UART_*`) | I²C, SPI, UART | C / C++ | **Experimental** —
|
|
113
|
+
| **STM32** | CubeHAL (`HAL_I2C_*`, `HAL_SPI_*` + GPIO CS, `HAL_UART_*`) | I²C, SPI, UART | C / C++ | **Experimental** — 3 hardware field tests (NUCLEO-G474RE, hand-completed); no automated compile gate yet |
|
|
114
114
|
| **Arduino** | `Wire` / `SPI` | — | C++ | not implemented |
|
|
115
115
|
|
|
116
|
-
STM32 CAN is planned (the bxCAN/FDCAN family split needs its own pass)
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
STM32 CAN is planned (the bxCAN/FDCAN family split needs its own pass), and a
|
|
117
|
+
next wave of native targets — RP2040/RP2350, TI MSPM0, NXP MCX/i.MX RT,
|
|
118
|
+
Nuvoton NuMicro, Microchip PIC, and eventually Zephyr — is on the
|
|
119
|
+
[Roadmap](#roadmap). Asking a target for a bus it doesn't support fails fast
|
|
120
|
+
with a clear `UnsupportedBusError` rather than emitting a wrong seam. Pass
|
|
119
121
|
`language: "cpp"` to `generate_driver` for a class-based C++ driver
|
|
120
122
|
(`.hpp`/`.cpp`) instead of the default C output — same registers, same seam,
|
|
121
123
|
same validation. What "Beta" and "Experimental" mean exactly is spelled out in
|
|
@@ -136,8 +138,8 @@ The extraction pipeline is regression-tested against real datasheets from
|
|
|
136
138
|
| LSM6DSRX | STMicroelectronics | register map | 31 regs, 91 bit-fields |
|
|
137
139
|
| MAX30102 | Maxim Integrated | register map | 20 regs, 33 bit-fields |
|
|
138
140
|
|
|
139
|
-
Other tested parts (ADXL345, MLX90614, AEAT-8811, PCA9685, VL53L3CX, TLE5014
|
|
140
|
-
extract **partially** or **defer** to the host AI — the pipeline says so
|
|
141
|
+
Other tested parts (ADXL345, MLX90614, AEAT-8811, PCA9685, VL53L3CX, TLE5014,
|
|
142
|
+
TCA6408A) extract **partially** or **defer** to the host AI — the pipeline says so
|
|
141
143
|
explicitly instead of guessing. The full, always-current matrix lives in the
|
|
142
144
|
[coverage scorecard](tests/scorecard/scorecard.snap.md).
|
|
143
145
|
|
|
@@ -146,17 +148,20 @@ explicitly instead of guessing. The full, always-current matrix lives in the
|
|
|
146
148
|
Driverge is in **closed beta** (`0.1.0-beta.x`, npm `beta` dist-tag).
|
|
147
149
|
|
|
148
150
|
**Proven today (host-level):**
|
|
149
|
-
- The full deterministic test suite is green (
|
|
151
|
+
- The full deterministic test suite is green (540-plus tests) on a clean
|
|
150
152
|
TypeScript build, and the **portable** driver is compiled by a real `gcc`
|
|
151
|
-
gate in CI.
|
|
152
|
-
- The extraction pipeline is regression-tested against **
|
|
153
|
-
and reports its own coverage honestly — 7 fully extracted,
|
|
153
|
+
gate in CI (including a multi-driver link gate).
|
|
154
|
+
- The extraction pipeline is regression-tested against **14 real datasheets**
|
|
155
|
+
and reports its own coverage honestly — 7 fully extracted, 4 partial, 3
|
|
154
156
|
deferred (see the [coverage scorecard](tests/scorecard/scorecard.snap.md)).
|
|
155
157
|
|
|
156
158
|
**Not yet proven — this is the beta → v0.1.0 gate:**
|
|
157
|
-
- **On-hardware behavior is not gated.**
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
- **On-hardware behavior is not gated by CI.** STM32 has now run on real
|
|
160
|
+
hardware — three NUCLEO-G474RE field tests (onsemi FXL6408 I²C, TI TUSS4470
|
|
161
|
+
SPI, Microchip CAP1206 I²C), each hand-completed and folded back into the
|
|
162
|
+
generator — and ESP32 has one informal I²C bring-up (MPU-9250). There is still
|
|
163
|
+
no clean, repeatable automated hardware pass, so every generated driver needs
|
|
164
|
+
review before you flash it.
|
|
160
165
|
- The native ESP32/STM32 seams are not yet built by an automated compile gate
|
|
161
166
|
(ESP-IDF / CubeIDE) — only the portable target is.
|
|
162
167
|
- Only one MCP client has been exercised end-to-end.
|
|
@@ -206,23 +211,27 @@ re-parse, and the full JSON stays readable at `driverge://datasheet/<ref>`.
|
|
|
206
211
|
### The thin-HAL seam
|
|
207
212
|
|
|
208
213
|
Generated drivers touch hardware through a tiny per-bus seam — and nothing
|
|
209
|
-
else
|
|
214
|
+
else. Seam symbols are **prefixed with the part's slug** (e.g.
|
|
215
|
+
`bme280_hal_i2c_read`) so two Driverge drivers can link into one firmware
|
|
216
|
+
image without symbol collisions:
|
|
210
217
|
|
|
211
|
-
| Bus | Seam functions (plus `
|
|
218
|
+
| Bus | Seam functions (plus `<part>_hal_delay_ms`) |
|
|
212
219
|
|---|---|
|
|
213
|
-
| I²C |
|
|
214
|
-
| SPI | `
|
|
215
|
-
| UART |
|
|
216
|
-
| CAN | `
|
|
220
|
+
| I²C | `<part>_hal_i2c_read`, `<part>_hal_i2c_write` |
|
|
221
|
+
| SPI | `<part>_hal_spi_transfer(tx, rx, len)` (one call = one CS-framed **full-duplex** transaction; `rx` may be `NULL` for write-only, and write-then-read devices are served by padding `tx` with dummy bytes) |
|
|
222
|
+
| UART | `<part>_hal_uart_write`, `<part>_hal_uart_read` |
|
|
223
|
+
| CAN | `<part>_hal_can_transfer` (one call = one frame exchange) |
|
|
217
224
|
|
|
218
225
|
The transfer seams return `int` — **`0` on success, non-zero on a bus error**
|
|
219
226
|
(NACK, timeout) — and the generated register accessors propagate that status
|
|
220
227
|
instead of swallowing it; native seams (ESP32, STM32) return their vendor
|
|
221
|
-
status, which is already `0` on success.
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
228
|
+
status, which is already `0` on success. Native targets also emit a seam
|
|
229
|
+
companion header (`<part>_hal_stm32.h` / `<part>_hal_esp32.h`) declaring the
|
|
230
|
+
one-time `bind` call that points the seam at your peripheral handle.
|
|
231
|
+
`validate_driver` enforces seam purity: a driver that calls a vendor
|
|
232
|
+
peripheral API outside the seam fails the lint. Buses with no universal
|
|
233
|
+
register-access primitive (UART, CAN) get their device-specific framing as a
|
|
234
|
+
marked `TODO(driverge)` gap, completed by the host AI and then linted.
|
|
226
235
|
|
|
227
236
|
### The fill-in loop
|
|
228
237
|
|
|
@@ -277,6 +286,7 @@ development.
|
|
|
277
286
|
| Env var | Default | Purpose |
|
|
278
287
|
|---|---|---|
|
|
279
288
|
| `DRIVERGE_OUT_ROOT` | server's working directory | Root that `generate_driver`'s `out_dir` writes are confined to. Any `out_dir` that resolves outside this root is rejected (`out_dir "…" escapes the allowed root`). Set it to the directory you want drivers written into. |
|
|
289
|
+
| `DRIVERGE_MAX_PDF_BYTES` | `67108864` (64 MiB) | Maximum PDF size `analyze_datasheet` will read. A larger file is rejected with a clear "PDF too large" error before any parsing — bounds memory use on a hostile or accidentally huge input. |
|
|
280
290
|
|
|
281
291
|
Set it in the MCP config's `env` block, e.g.:
|
|
282
292
|
|
|
@@ -431,6 +441,13 @@ datasheet prose, and `validate_driver` checks the result.
|
|
|
431
441
|
(I²C, SPI, UART, CAN) ✅; C or C++ output ✅. *(current)*
|
|
432
442
|
- **v1.0** — broader vendor/part coverage, STM32 CAN (bxCAN/FDCAN), and a
|
|
433
443
|
stable, versioned JSON schema.
|
|
444
|
+
- **v1.x** — new native MCU targets (same portable thin-HAL core, one seam
|
|
445
|
+
file per platform; prioritized by beta-tester demand): **RP2040/RP2350**
|
|
446
|
+
(pico-sdk), **TI MSPM0** (DriverLib), **NXP MCX / i.MX RT** (MCUXpresso
|
|
447
|
+
`fsl_lpi2c`/`fsl_lpspi`), **Nuvoton NuMicro** (BSP Standard Driver), and
|
|
448
|
+
**Microchip PIC** (MCC Melody for 8/16-bit; Harmony v3 for PIC32).
|
|
449
|
+
- **Later** — a **Zephyr** meta-target (devicetree-based `i2c`/`spi` API):
|
|
450
|
+
one seam covering Nordic nRF and every other Zephyr-supported vendor.
|
|
434
451
|
|
|
435
452
|
Day-to-day progress is tracked in the [CHANGELOG](CHANGELOG.md).
|
|
436
453
|
|
package/dist/codegen/esp32.d.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { DatasheetJson } from "../schema/types.js";
|
|
2
2
|
import type { CodegenLanguage, DriverArtifact } from "./types.js";
|
|
3
3
|
/**
|
|
4
|
-
* Portable core + an ESP-IDF seam implementation
|
|
5
|
-
* language "c" (default) the seam is `<slug>_hal_esp32.c
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Portable core + an ESP-IDF seam implementation + a seam companion header for
|
|
5
|
+
* the same part. With language "c" (default) the seam is `<slug>_hal_esp32.c`;
|
|
6
|
+
* with language "cpp" it is `<slug>_hal_esp32.cpp` and its core include is
|
|
7
|
+
* `#include "<slug>.hpp"` (see coreInclude/seamPath above) — everything else
|
|
8
|
+
* in the seam content is identical either way. The companion header
|
|
9
|
+
* (`<slug>_hal_esp32.h`) is always a plain `.h` file, in BOTH language runs.
|
|
10
|
+
* File order in the artifact: [core header, core source, companion header,
|
|
11
|
+
* seam source] — see tests/codegen/esp32.test.ts.
|
|
9
12
|
*/
|
|
10
13
|
export declare function generateEsp32Driver(json: DatasheetJson, opts?: {
|
|
11
14
|
language?: CodegenLanguage;
|
package/dist/codegen/esp32.js
CHANGED
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
// ESP32 (ESP-IDF) target. Per platform-code-generation-targets, a native target
|
|
2
2
|
// does NOT replace the thin HAL — it *pre-fills* the seam. So the ESP32 driver is
|
|
3
3
|
// the exact portable core (unchanged, still platform-agnostic) PLUS a
|
|
4
|
-
// <
|
|
5
|
-
// ESP-IDF v5 drivers
|
|
6
|
-
//
|
|
4
|
+
// <slug>_hal_esp32.c that implements the bus's thin-HAL seam + <slug>_hal_delay_ms
|
|
5
|
+
// with ESP-IDF v5 drivers, PLUS a <slug>_hal_esp32.h companion header declaring
|
|
6
|
+
// the <slug>_esp32_bind(...) prototype the seam .c defines. The user drops all
|
|
7
|
+
// four files into an ESP-IDF component; only the board's bus/pin bring-up
|
|
8
|
+
// stays a TODO(driverge).
|
|
9
|
+
//
|
|
10
|
+
// Session E (2026-07-11 field-test findings — see raw/stm32-test-results/*.md
|
|
11
|
+
// and the approved plan, whose findings generalize to every native target):
|
|
12
|
+
// every seam symbol is PER-DRIVER PREFIXED (`<slug>_hal_*` — see busSeam in
|
|
13
|
+
// portable.ts), so two Driverge drivers in one project never collide at link.
|
|
14
|
+
// The SPI seam is also now a single full-duplex <slug>_hal_spi_transfer(tx,
|
|
15
|
+
// rx, len) — one spi_transaction_t (length = len*8, tx_buffer/rx_buffer, no
|
|
16
|
+
// SPI_DEVICE_HALFDUPLEX flag) — matching the portable core's contract exactly.
|
|
7
17
|
//
|
|
8
18
|
// I2C/SPI/UART/CAN only: the I2C seam references `${PREFIX}_I2C_ADDR`, a macro
|
|
9
19
|
// the portable core only defines for I2C parts; the SPI seam needs the portable
|
|
10
|
-
// core's
|
|
11
|
-
// uart driver around
|
|
12
|
-
// wraps ESP-IDF's TWAI (Two-Wire Automotive Interface,
|
|
13
|
-
// controller) driver around
|
|
14
|
-
// ESP-IDF seam here, so this target refuses
|
|
15
|
-
// emit an uncompilable seam.
|
|
20
|
+
// core's <slug>_hal_spi_transfer declaration; the UART seam (Session B) wraps
|
|
21
|
+
// ESP-IDF's uart driver around <slug>_hal_uart_write/<slug>_hal_uart_read; the
|
|
22
|
+
// CAN seam (Session C) wraps ESP-IDF's TWAI (Two-Wire Automotive Interface,
|
|
23
|
+
// ESP-IDF's CAN 2.0 controller) driver around <slug>_hal_can_transfer — any
|
|
24
|
+
// other bus (unknown) has no ESP-IDF seam here, so this target refuses
|
|
25
|
+
// (UnsupportedBusError) rather than emit an uncompilable seam.
|
|
16
26
|
import { prefixOf, slug } from "./ident.js";
|
|
17
27
|
import { generatePortableCppDriver } from "./portable-cpp.js";
|
|
18
28
|
import { generatePortableDriver } from "./portable.js";
|
|
@@ -26,24 +36,73 @@ import { UnsupportedBusError } from "./types.js";
|
|
|
26
36
|
// nothing: the .hpp declares the hal_* seam inside `extern "C"`, so compiling
|
|
27
37
|
// this seam as C++ still emits plain C-linkage definitions the class methods
|
|
28
38
|
// can call, and both ESP-IDF and a C++-enabled CubeMX project compile .cpp
|
|
29
|
-
// sources natively.
|
|
39
|
+
// sources natively. The seam companion header (Session E) stays a plain `.h`
|
|
40
|
+
// file in BOTH language runs — its own `extern "C"` guard makes it valid from
|
|
41
|
+
// either a C or a C++ translation unit, so there is nothing to switch on
|
|
42
|
+
// `language` for (see companionHeaderEsp32 below).
|
|
30
43
|
function coreInclude(name, language) {
|
|
31
44
|
return `#include "${name}.${language === "cpp" ? "hpp" : "h"}"`;
|
|
32
45
|
}
|
|
33
46
|
function seamPath(name, language) {
|
|
34
47
|
return `${name}_hal_esp32.${language === "cpp" ? "cpp" : "c"}`;
|
|
35
48
|
}
|
|
49
|
+
function companionHeaderName(name) {
|
|
50
|
+
return `${name}_hal_esp32.h`;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Session E: the seam companion header. Declares the `<slug>_esp32_bind(...)`
|
|
54
|
+
* prototype the seam .c/.cpp defines — the CAP1206/FXL6408 field sessions both
|
|
55
|
+
* had to hand-write this prototype into their own application code
|
|
56
|
+
* (raw/stm32-test-results/*.md §6) because Driverge never emitted it.
|
|
57
|
+
* `includeLine` is the ESP-IDF driver header the bind signature's vendor
|
|
58
|
+
* type(s) need (driver/i2c_master.h, driver/spi_master.h, driver/uart.h,
|
|
59
|
+
* driver/twai.h); `bindProtoLine` is the exact signature (identical to the
|
|
60
|
+
* `<ret> <slug>_esp32_bind(...) {` line the seam defines, just with a
|
|
61
|
+
* trailing `;` instead of a body) — passed in by each halImplX below so the
|
|
62
|
+
* header and the definition can never drift.
|
|
63
|
+
*/
|
|
64
|
+
function companionHeaderEsp32(name, prefix, includeLine, bindProtoLine) {
|
|
65
|
+
const guard = `${prefix}_HAL_ESP32_H`;
|
|
66
|
+
const content = [
|
|
67
|
+
"/*",
|
|
68
|
+
` * ${prefix} — ESP-IDF HAL seam companion header (generated by Driverge).`,
|
|
69
|
+
" *",
|
|
70
|
+
` * Declares ${name}_esp32_bind(), which ${name}_hal_esp32.c/.cpp defines.`,
|
|
71
|
+
" * Include this header from your application code to call it after bus/",
|
|
72
|
+
" * peripheral bring-up.",
|
|
73
|
+
" */",
|
|
74
|
+
`#ifndef ${guard}`,
|
|
75
|
+
`#define ${guard}`,
|
|
76
|
+
"",
|
|
77
|
+
"#ifdef __cplusplus",
|
|
78
|
+
'extern "C" {',
|
|
79
|
+
"#endif",
|
|
80
|
+
"",
|
|
81
|
+
includeLine,
|
|
82
|
+
"",
|
|
83
|
+
bindProtoLine,
|
|
84
|
+
"",
|
|
85
|
+
"#ifdef __cplusplus",
|
|
86
|
+
"}",
|
|
87
|
+
"#endif",
|
|
88
|
+
`#endif /* ${guard} */`,
|
|
89
|
+
"",
|
|
90
|
+
].join("\n");
|
|
91
|
+
return { path: companionHeaderName(name), content };
|
|
92
|
+
}
|
|
36
93
|
function halImplI2c(name, prefix, language) {
|
|
37
94
|
const content = [
|
|
38
95
|
"/*",
|
|
39
96
|
` * ${prefix} — ESP-IDF (i2c_master) HAL seam implementation (generated by Driverge).`,
|
|
40
97
|
" *",
|
|
41
98
|
" * Drop this beside the portable core; it fills the thin-HAL seam with the",
|
|
42
|
-
" * ESP-IDF v5 i2c_master driver.
|
|
43
|
-
` *
|
|
44
|
-
" * once before using the driver. The
|
|
99
|
+
" * ESP-IDF v5 i2c_master driver. See the companion header",
|
|
100
|
+
` * (${companionHeaderName(name)}) for the ${name}_esp32_bind() prototype —`,
|
|
101
|
+
" * call it once (after i2c_new_master_bus()) before using the driver. The",
|
|
102
|
+
" * driver core stays byte-for-byte portable.",
|
|
45
103
|
" */",
|
|
46
104
|
coreInclude(name, language),
|
|
105
|
+
`#include "${companionHeaderName(name)}"`,
|
|
47
106
|
"#include <string.h>",
|
|
48
107
|
'#include "driver/i2c_master.h"',
|
|
49
108
|
'#include "freertos/FreeRTOS.h"',
|
|
@@ -66,7 +125,7 @@ function halImplI2c(name, prefix, language) {
|
|
|
66
125
|
` return i2c_master_bus_add_device(bus, &cfg, &s_${name}_dev);`,
|
|
67
126
|
"}",
|
|
68
127
|
"",
|
|
69
|
-
|
|
128
|
+
`int ${name}_hal_i2c_write(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) {`,
|
|
70
129
|
" uint8_t buf[33];",
|
|
71
130
|
" (void)addr; /* the device handle already encodes the bus address */",
|
|
72
131
|
" if ((size_t)len + 1u > sizeof buf) {",
|
|
@@ -77,17 +136,18 @@ function halImplI2c(name, prefix, language) {
|
|
|
77
136
|
` return i2c_master_transmit(s_${name}_dev, buf, (size_t)len + 1u, ${prefix}_I2C_TIMEOUT_MS);`,
|
|
78
137
|
"}",
|
|
79
138
|
"",
|
|
80
|
-
|
|
139
|
+
`int ${name}_hal_i2c_read(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) {`,
|
|
81
140
|
" (void)addr;",
|
|
82
141
|
` return i2c_master_transmit_receive(s_${name}_dev, ®, 1, data, len, ${prefix}_I2C_TIMEOUT_MS);`,
|
|
83
142
|
"}",
|
|
84
143
|
"",
|
|
85
|
-
|
|
144
|
+
`void ${name}_hal_delay_ms(uint32_t ms) {`,
|
|
86
145
|
" vTaskDelay(pdMS_TO_TICKS(ms));",
|
|
87
146
|
"}",
|
|
88
147
|
"",
|
|
89
148
|
].join("\n");
|
|
90
|
-
|
|
149
|
+
const header = companionHeaderEsp32(name, prefix, '#include "driver/i2c_master.h"', `esp_err_t ${name}_esp32_bind(i2c_master_bus_handle_t bus, uint32_t scl_speed_hz);`);
|
|
150
|
+
return [header, { path: seamPath(name, language), content }];
|
|
91
151
|
}
|
|
92
152
|
function halImplSpi(name, prefix, language) {
|
|
93
153
|
const content = [
|
|
@@ -95,13 +155,14 @@ function halImplSpi(name, prefix, language) {
|
|
|
95
155
|
` * ${prefix} — ESP-IDF (spi_master) HAL seam implementation (generated by Driverge).`,
|
|
96
156
|
" *",
|
|
97
157
|
" * Drop this beside the portable core; it fills the thin-HAL seam with the",
|
|
98
|
-
" * ESP-IDF v5 spi_master driver: one
|
|
99
|
-
` *
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
" * byte-for-byte portable.",
|
|
158
|
+
" * ESP-IDF v5 spi_master driver: one full-duplex, polling transaction per",
|
|
159
|
+
` * ${name}_hal_spi_transfer() call. See the companion header`,
|
|
160
|
+
` * (${companionHeaderName(name)}) for the ${name}_esp32_bind() prototype —`,
|
|
161
|
+
" * call it once (after spi_bus_initialize()) before using the driver. The",
|
|
162
|
+
" * driver core stays byte-for-byte portable.",
|
|
103
163
|
" */",
|
|
104
164
|
coreInclude(name, language),
|
|
165
|
+
`#include "${companionHeaderName(name)}"`,
|
|
105
166
|
"#include <string.h>",
|
|
106
167
|
'#include "driver/spi_master.h"',
|
|
107
168
|
'#include "freertos/FreeRTOS.h"',
|
|
@@ -114,7 +175,6 @@ function halImplSpi(name, prefix, language) {
|
|
|
114
175
|
" * see fill_in_brief.hal_setup_todo for the SPI mode this part expects. */",
|
|
115
176
|
`esp_err_t ${name}_esp32_bind(spi_host_device_t host, int cs_gpio, int clock_hz) {`,
|
|
116
177
|
" spi_device_interface_config_t cfg = {",
|
|
117
|
-
" .flags = SPI_DEVICE_HALFDUPLEX,",
|
|
118
178
|
" .spics_io_num = cs_gpio,",
|
|
119
179
|
" .clock_speed_hz = clock_hz,",
|
|
120
180
|
" .mode = 0, /* see fill_in_brief.hal_setup_todo for this part's SPI mode */",
|
|
@@ -123,22 +183,24 @@ function halImplSpi(name, prefix, language) {
|
|
|
123
183
|
` return spi_bus_add_device(host, &cfg, &s_${name}_dev);`,
|
|
124
184
|
"}",
|
|
125
185
|
"",
|
|
126
|
-
"
|
|
186
|
+
"/* Full-duplex: ONE spi_transaction_t clocks tx out and rx in together — no",
|
|
187
|
+
" * half-duplex device flag needed; hardware CS works fine in full-duplex too. */",
|
|
188
|
+
`int ${name}_hal_spi_transfer(const uint8_t *tx, uint8_t *rx, uint16_t len) {`,
|
|
127
189
|
" spi_transaction_t t;",
|
|
128
190
|
" memset(&t, 0, sizeof t);",
|
|
129
|
-
" t.length = 8 *
|
|
130
|
-
" t.rxlength = 8 * rx_len;",
|
|
191
|
+
" t.length = 8 * len;",
|
|
131
192
|
" t.tx_buffer = tx;",
|
|
132
193
|
" t.rx_buffer = rx;",
|
|
133
194
|
` return spi_device_polling_transmit(s_${name}_dev, &t);`,
|
|
134
195
|
"}",
|
|
135
196
|
"",
|
|
136
|
-
|
|
197
|
+
`void ${name}_hal_delay_ms(uint32_t ms) {`,
|
|
137
198
|
" vTaskDelay(pdMS_TO_TICKS(ms));",
|
|
138
199
|
"}",
|
|
139
200
|
"",
|
|
140
201
|
].join("\n");
|
|
141
|
-
|
|
202
|
+
const header = companionHeaderEsp32(name, prefix, '#include "driver/spi_master.h"', `esp_err_t ${name}_esp32_bind(spi_host_device_t host, int cs_gpio, int clock_hz);`);
|
|
203
|
+
return [header, { path: seamPath(name, language), content }];
|
|
142
204
|
}
|
|
143
205
|
function halImplUart(name, prefix, language) {
|
|
144
206
|
const content = [
|
|
@@ -146,13 +208,14 @@ function halImplUart(name, prefix, language) {
|
|
|
146
208
|
` * ${prefix} — ESP-IDF (uart) HAL seam implementation (generated by Driverge).`,
|
|
147
209
|
" *",
|
|
148
210
|
" * Drop this beside the portable core; it fills the thin-HAL seam with the",
|
|
149
|
-
" * ESP-IDF v5 UART driver.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
" * driver. The driver core stays byte-for-byte portable. See",
|
|
211
|
+
" * ESP-IDF v5 UART driver. See the companion header",
|
|
212
|
+
` * (${companionHeaderName(name)}) for the ${name}_esp32_bind() prototype —`,
|
|
213
|
+
" * call it once (after uart_param_config + uart_driver_install) before",
|
|
214
|
+
" * using the driver. The driver core stays byte-for-byte portable. See",
|
|
153
215
|
" * fill_in_brief.hal_setup_todo for the baud rate/config to use.",
|
|
154
216
|
" */",
|
|
155
217
|
coreInclude(name, language),
|
|
218
|
+
`#include "${companionHeaderName(name)}"`,
|
|
156
219
|
'#include "driver/uart.h"',
|
|
157
220
|
'#include "freertos/FreeRTOS.h"',
|
|
158
221
|
'#include "freertos/task.h"',
|
|
@@ -165,11 +228,11 @@ function halImplUart(name, prefix, language) {
|
|
|
165
228
|
` s_${name}_port = port;`,
|
|
166
229
|
"}",
|
|
167
230
|
"",
|
|
168
|
-
|
|
231
|
+
`void ${name}_hal_uart_write(const uint8_t *data, uint16_t len) {`,
|
|
169
232
|
` uart_write_bytes(s_${name}_port, (const char *)data, len);`,
|
|
170
233
|
"}",
|
|
171
234
|
"",
|
|
172
|
-
|
|
235
|
+
`uint16_t ${name}_hal_uart_read(uint8_t *data, uint16_t len, uint32_t timeout_ms) {`,
|
|
173
236
|
` int n = uart_read_bytes(s_${name}_port, data, len, pdMS_TO_TICKS(timeout_ms));`,
|
|
174
237
|
" if (n < 0) {",
|
|
175
238
|
" return 0;",
|
|
@@ -177,12 +240,13 @@ function halImplUart(name, prefix, language) {
|
|
|
177
240
|
" return (uint16_t)n;",
|
|
178
241
|
"}",
|
|
179
242
|
"",
|
|
180
|
-
|
|
243
|
+
`void ${name}_hal_delay_ms(uint32_t ms) {`,
|
|
181
244
|
" vTaskDelay(pdMS_TO_TICKS(ms));",
|
|
182
245
|
"}",
|
|
183
246
|
"",
|
|
184
247
|
].join("\n");
|
|
185
|
-
|
|
248
|
+
const header = companionHeaderEsp32(name, prefix, '#include "driver/uart.h"', `void ${name}_esp32_bind(uart_port_t port);`);
|
|
249
|
+
return [header, { path: seamPath(name, language), content }];
|
|
186
250
|
}
|
|
187
251
|
function halImplCan(name, prefix, language) {
|
|
188
252
|
const content = [
|
|
@@ -191,10 +255,10 @@ function halImplCan(name, prefix, language) {
|
|
|
191
255
|
" *",
|
|
192
256
|
" * Drop this beside the portable core; it fills the thin-HAL seam with the",
|
|
193
257
|
" * ESP-IDF v5 TWAI (Two-Wire Automotive Interface — ESP-IDF's CAN 2.0",
|
|
194
|
-
" * controller) driver.
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
" * The driver core stays byte-for-byte portable. See",
|
|
258
|
+
" * controller) driver. See the companion header",
|
|
259
|
+
` * (${companionHeaderName(name)}) for the ${name}_esp32_bind() prototype —`,
|
|
260
|
+
" * call it once (after twai_driver_install()/twai_start()) before using the",
|
|
261
|
+
" * driver. The driver core stays byte-for-byte portable. See",
|
|
198
262
|
" * fill_in_brief.hal_setup_todo for the bitrate/acceptance-filter config.",
|
|
199
263
|
" *",
|
|
200
264
|
` * ${name}_esp32_bind() deliberately takes NO arguments: unlike I2C/SPI/UART`,
|
|
@@ -204,6 +268,7 @@ function halImplCan(name, prefix, language) {
|
|
|
204
268
|
" * signature parity with the other targets' bind().",
|
|
205
269
|
" */",
|
|
206
270
|
coreInclude(name, language),
|
|
271
|
+
`#include "${companionHeaderName(name)}"`,
|
|
207
272
|
"#include <string.h>",
|
|
208
273
|
'#include "driver/twai.h"',
|
|
209
274
|
'#include "freertos/FreeRTOS.h"',
|
|
@@ -214,7 +279,7 @@ function halImplCan(name, prefix, language) {
|
|
|
214
279
|
`void ${name}_esp32_bind(void) {`,
|
|
215
280
|
"}",
|
|
216
281
|
"",
|
|
217
|
-
|
|
282
|
+
`int ${name}_hal_can_transfer(uint32_t id, const uint8_t *tx, uint8_t tx_len, uint8_t *rx, uint8_t *rx_len, uint32_t timeout_ms) {`,
|
|
218
283
|
" twai_message_t tx_msg;",
|
|
219
284
|
" memset(&tx_msg, 0, sizeof tx_msg);",
|
|
220
285
|
" tx_msg.identifier = id;",
|
|
@@ -241,19 +306,23 @@ function halImplCan(name, prefix, language) {
|
|
|
241
306
|
" return 0;",
|
|
242
307
|
"}",
|
|
243
308
|
"",
|
|
244
|
-
|
|
309
|
+
`void ${name}_hal_delay_ms(uint32_t ms) {`,
|
|
245
310
|
" vTaskDelay(pdMS_TO_TICKS(ms));",
|
|
246
311
|
"}",
|
|
247
312
|
"",
|
|
248
313
|
].join("\n");
|
|
249
|
-
|
|
314
|
+
const header = companionHeaderEsp32(name, prefix, '#include "driver/twai.h"', `void ${name}_esp32_bind(void);`);
|
|
315
|
+
return [header, { path: seamPath(name, language), content }];
|
|
250
316
|
}
|
|
251
317
|
/**
|
|
252
|
-
* Portable core + an ESP-IDF seam implementation
|
|
253
|
-
* language "c" (default) the seam is `<slug>_hal_esp32.c
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
318
|
+
* Portable core + an ESP-IDF seam implementation + a seam companion header for
|
|
319
|
+
* the same part. With language "c" (default) the seam is `<slug>_hal_esp32.c`;
|
|
320
|
+
* with language "cpp" it is `<slug>_hal_esp32.cpp` and its core include is
|
|
321
|
+
* `#include "<slug>.hpp"` (see coreInclude/seamPath above) — everything else
|
|
322
|
+
* in the seam content is identical either way. The companion header
|
|
323
|
+
* (`<slug>_hal_esp32.h`) is always a plain `.h` file, in BOTH language runs.
|
|
324
|
+
* File order in the artifact: [core header, core source, companion header,
|
|
325
|
+
* seam source] — see tests/codegen/esp32.test.ts.
|
|
257
326
|
*/
|
|
258
327
|
export function generateEsp32Driver(json, opts = {}) {
|
|
259
328
|
const bus = json.protocol.bus;
|
|
@@ -264,22 +333,23 @@ export function generateEsp32Driver(json, opts = {}) {
|
|
|
264
333
|
const prefix = prefixOf(json.metadata.part);
|
|
265
334
|
const language = opts.language ?? "c";
|
|
266
335
|
const base = language === "cpp" ? generatePortableCppDriver(json) : generatePortableDriver(json);
|
|
267
|
-
const hal = bus === "SPI"
|
|
336
|
+
const [companionHeader, hal] = bus === "SPI"
|
|
268
337
|
? halImplSpi(name, prefix, language)
|
|
269
338
|
: bus === "UART"
|
|
270
339
|
? halImplUart(name, prefix, language)
|
|
271
340
|
: bus === "CAN"
|
|
272
341
|
? halImplCan(name, prefix, language)
|
|
273
342
|
: halImplI2c(name, prefix, language);
|
|
343
|
+
const headerName = companionHeaderName(name);
|
|
274
344
|
const hal_setup_todo = bus === "SPI"
|
|
275
|
-
? `Bring up the ESP-IDF SPI bus (spi_bus_initialize with your MOSI/MISO/SCLK pins and host), then call ${name}_esp32_bind(host, cs_gpio, clock_hz) before the first driver call. Confirm this part's SPI mode (0-3) and maximum clock speed from the datasheet's SPI timing section.`
|
|
345
|
+
? `Bring up the ESP-IDF SPI bus (spi_bus_initialize with your MOSI/MISO/SCLK pins and host), then call ${name}_esp32_bind(host, cs_gpio, clock_hz) before the first driver call (prototype in ${headerName}). Confirm this part's SPI mode (0-3) and maximum clock speed from the datasheet's SPI timing section.`
|
|
276
346
|
: bus === "UART"
|
|
277
|
-
? `Install the ESP-IDF UART driver (uart_param_config + uart_driver_install) on your chosen port with this part's baud rate/parity/stop-bits (see the datasheet's serial interface section), then call ${name}_esp32_bind(port) before the first driver call.`
|
|
347
|
+
? `Install the ESP-IDF UART driver (uart_param_config + uart_driver_install) on your chosen port with this part's baud rate/parity/stop-bits (see the datasheet's serial interface section), then call ${name}_esp32_bind(port) before the first driver call (prototype in ${headerName}).`
|
|
278
348
|
: bus === "CAN"
|
|
279
|
-
? `Install and start the ESP-IDF TWAI driver (twai_driver_install + twai_start) on your chosen TX/RX GPIOs with this part's bitrate and an acceptance filter covering its message IDs (see the datasheet's CAN bus timing/message-ID section), then call ${name}_esp32_bind() before the first driver call.`
|
|
280
|
-
: `Bring up the ESP-IDF I2C master bus (i2c_new_master_bus with your SDA/SCL GPIOs and port), then call ${name}_esp32_bind(bus, 400000) before the first driver call. Tune ${prefix}_I2C_TIMEOUT_MS if needed.`;
|
|
349
|
+
? `Install and start the ESP-IDF TWAI driver (twai_driver_install + twai_start) on your chosen TX/RX GPIOs with this part's bitrate and an acceptance filter covering its message IDs (see the datasheet's CAN bus timing/message-ID section), then call ${name}_esp32_bind() before the first driver call (prototype in ${headerName}).`
|
|
350
|
+
: `Bring up the ESP-IDF I2C master bus (i2c_new_master_bus with your SDA/SCL GPIOs and port), then call ${name}_esp32_bind(bus, 400000) before the first driver call (prototype in ${headerName}). Tune ${prefix}_I2C_TIMEOUT_MS if needed.`;
|
|
281
351
|
return {
|
|
282
|
-
files: [...base.files, hal],
|
|
352
|
+
files: [...base.files, companionHeader, hal],
|
|
283
353
|
fill_in_brief: {
|
|
284
354
|
...base.fill_in_brief,
|
|
285
355
|
hal_setup_todo,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"esp32.js","sourceRoot":"","sources":["../../src/codegen/esp32.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,kFAAkF;AAClF,sEAAsE;AACtE,
|
|
1
|
+
{"version":3,"file":"esp32.js","sourceRoot":"","sources":["../../src/codegen/esp32.ts"],"names":[],"mappings":"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"}
|