feat(boards): let a board declare the RAM and flash it is physically fitted with
An overlay board was invisible to the build-options model: its kind is not in the OSS family sets, so isEsp32Family() said no, the Board Options menu never appeared, and every compile went out with board_options: null - the conservative family default of CONFIG_SPIRAM=n. That is wrong for a module that always ships PSRAM. The ESP32-S3-EYE carries 8 MB of octal PSRAM and esp_camera allocates its frame buffer with MALLOC_CAP_SPIRAM, so its camera examples compiled cleanly and then died at run time with 'cam_dma_config(509): frame buffer malloc failed' - a hardware fact surfacing as a mysterious driver error. Boards now declare defaultBoardOptions, sent when the project saved none of its own. ONLY the declared keys are sent: the backend backfills the rest from its own defaults, which are deliberately not the modal's (huge_app vs min_spiffs), so a board that gains one declared knob does not silently get repartitioned. Boards that declare nothing keep sending null and build bit-for-bit as before. Also route the family predicates through the registry, so overlay ESP32 boards finally get the Tools menu they were missing.
This commit is contained in:
parent
f4ff3e7430
commit
2b7c9b6fb6
|
|
@ -17,6 +17,7 @@
|
|||
* `ad.id in BOARD_KIND_LABELS`, and registration inserts the label.
|
||||
*/
|
||||
import type React from 'react';
|
||||
import type { ESP32BoardOptions } from '../types/boardOptions';
|
||||
import {
|
||||
BOARD_KIND_LABELS,
|
||||
BOARD_KIND_FQBN,
|
||||
|
|
@ -166,6 +167,20 @@ export interface ProBoardDef {
|
|||
* first compile resolves against nothing. */
|
||||
defaultLibraries?: string[];
|
||||
|
||||
/**
|
||||
* Build options this board is physically born with, merged over the family
|
||||
* defaults whenever the project has not saved its own.
|
||||
*
|
||||
* A module carries the RAM and flash it carries: the ESP32-S3-EYE always has
|
||||
* 8 MB of octal PSRAM, and its camera driver allocates the frame buffer with
|
||||
* MALLOC_CAP_SPIRAM. Compiled with the conservative family default
|
||||
* (CONFIG_SPIRAM=n) the sketch builds fine and then dies at run time with
|
||||
* `cam_dma_config(509): frame buffer malloc failed` — a hardware fact
|
||||
* reported as a mysterious driver error. Boards that ship the RAM say so
|
||||
* here; everything else keeps sending no options at all.
|
||||
*/
|
||||
defaultBoardOptions?: Partial<ESP32BoardOptions>;
|
||||
|
||||
/** Sidebar / toolbar accents (fall back to a neutral chip icon). */
|
||||
icon?: string;
|
||||
color?: string;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import axios from 'axios';
|
||||
import { getApiBase } from '../lib/apiBase';
|
||||
import type { ESP32BoardOptions, SpiffsFile } from '../types/boardOptions';
|
||||
import { implicitBoardOptions } from '../types/boardOptions';
|
||||
|
||||
export interface SketchFile {
|
||||
name: string;
|
||||
|
|
@ -117,7 +118,14 @@ export async function compileCode(
|
|||
// Translate camelCase frontend keys to snake_case backend keys. Backend
|
||||
// only inspects these fields for esp32:* FQBNs — other boards pass them
|
||||
// through unread.
|
||||
const board_options = extras?.boardOptions ? { ...extras.boardOptions } : null;
|
||||
// A project that never opened the Board Options modal still has to build for
|
||||
// the module it is running on: ask the board what it ships with. Null for
|
||||
// every board that declares nothing, which is all of the OSS ones.
|
||||
const board_options = extras?.boardOptions
|
||||
? { ...extras.boardOptions }
|
||||
: extras?.boardKind
|
||||
? implicitBoardOptions(extras.boardKind as never)
|
||||
: null;
|
||||
const spiffs_files = extras?.spiffsFiles?.length
|
||||
? extras.spiffsFiles.map((f) => ({ name: f.name, content_b64: f.contentB64 }))
|
||||
: null;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
// modal isn't exposed there.
|
||||
|
||||
import type { BoardKind } from './board';
|
||||
import { getProBoard } from '../lib/proBoardRegistry';
|
||||
|
||||
export type ESP32PartitionScheme =
|
||||
| 'default' // 1.2MB APP / 1.5MB SPIFFS (OTA)
|
||||
|
|
@ -85,11 +86,22 @@ const ESP32_XTENSA_KINDS: ReadonlySet<BoardKind> = new Set([
|
|||
'wemos-lolin32-lite',
|
||||
]);
|
||||
|
||||
// Overlay boards are not in the OSS kind sets, but they declare the chip they
|
||||
// carry (`esp32Family`). Without consulting the registry an overlay ESP32
|
||||
// board silently lost the whole Tools menu — no partition scheme, no PSRAM,
|
||||
// no flash size — on hardware where those knobs matter most.
|
||||
function proEsp32Family(kind: BoardKind): ProEsp32Family | null {
|
||||
return (getProBoard(kind)?.esp32Family as ProEsp32Family | undefined) ?? null;
|
||||
}
|
||||
|
||||
type ProEsp32Family = 'esp32' | 'esp32-s3' | 'esp32-c3' | 'esp32-c6' | 'esp32-p4' | 'esp32-c5';
|
||||
|
||||
export function isEsp32Family(kind: BoardKind): boolean {
|
||||
return (
|
||||
ESP32_XTENSA_KINDS.has(kind) ||
|
||||
ESP32_S3_KINDS.has(kind) ||
|
||||
ESP32_C3_KINDS.has(kind)
|
||||
ESP32_C3_KINDS.has(kind) ||
|
||||
proEsp32Family(kind) !== null
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -98,22 +110,51 @@ export function isEsp32Family(kind: BoardKind): boolean {
|
|||
// - ESP32-S3: optional, "enabled" or "opi" (octal)
|
||||
// - ESP32-C3: no PSRAM support at all — section hidden in UI
|
||||
export function boardSupportsPsram(kind: BoardKind): boolean {
|
||||
const pro = proEsp32Family(kind);
|
||||
if (pro) return pro !== 'esp32-c3' && pro !== 'esp32-c6';
|
||||
return ESP32_XTENSA_KINDS.has(kind) || ESP32_S3_KINDS.has(kind);
|
||||
}
|
||||
|
||||
export function boardSupportsOpiPsram(kind: BoardKind): boolean {
|
||||
return ESP32_S3_KINDS.has(kind);
|
||||
return ESP32_S3_KINDS.has(kind) || proEsp32Family(kind) === 'esp32-s3';
|
||||
}
|
||||
|
||||
export function getDefaultOptionsForKind(kind: BoardKind): ESP32BoardOptions {
|
||||
if (!isEsp32Family(kind)) return { ...DEFAULT_ESP32_OPTIONS };
|
||||
const defaults = { ...DEFAULT_ESP32_OPTIONS };
|
||||
const defaults = { ...DEFAULT_ESP32_OPTIONS, ...boardBornOptions(kind) };
|
||||
// C3 has no PSRAM controller — clear the field so a stale 'enabled'
|
||||
// value from an upgraded project doesn't reach the backend.
|
||||
if (ESP32_C3_KINDS.has(kind)) defaults.psram = 'disabled';
|
||||
if (ESP32_C3_KINDS.has(kind) || !boardSupportsPsram(kind)) defaults.psram = 'disabled';
|
||||
if (defaults.psram === 'opi' && !boardSupportsOpiPsram(kind)) defaults.psram = 'enabled';
|
||||
return defaults;
|
||||
}
|
||||
|
||||
/** What the module physically ships with, as declared by an overlay board
|
||||
* (`ProBoardDef.defaultBoardOptions`). Empty for every OSS board. */
|
||||
function boardBornOptions(kind: BoardKind): Partial<ESP32BoardOptions> {
|
||||
return getProBoard(kind)?.defaultBoardOptions ?? {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Options to compile with when the project saved none of its own.
|
||||
*
|
||||
* Returns null for every board whose module declares nothing, so their
|
||||
* requests keep sending `board_options: null` and build bit-for-bit as before.
|
||||
* When a board DOES declare something, only the declared keys are sent: the
|
||||
* backend backfills the rest from ITS defaults, which are deliberately not the
|
||||
* same as the modal's (`huge_app` there, `min_spiffs` here). Sending a
|
||||
* "complete" set would quietly repartition every board that gained a single
|
||||
* declared knob.
|
||||
*/
|
||||
export function implicitBoardOptions(kind: BoardKind): Partial<ESP32BoardOptions> | null {
|
||||
const born = boardBornOptions(kind);
|
||||
if (Object.keys(born).length === 0) return null;
|
||||
const opts: Partial<ESP32BoardOptions> = { ...born };
|
||||
if (opts.psram && !boardSupportsPsram(kind)) opts.psram = 'disabled';
|
||||
if (opts.psram === 'opi' && !boardSupportsOpiPsram(kind)) opts.psram = 'enabled';
|
||||
return opts;
|
||||
}
|
||||
|
||||
// Human-readable label for a partition scheme. Used in the modal dropdown
|
||||
// so users see "min_spiffs - 1.9MB APP / 190KB SPIFFS (OTA)" instead of
|
||||
// the bare key.
|
||||
|
|
|
|||
Loading…
Reference in New Issue