ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
pc_platform.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file pc_platform.h
6 * @brief The one vendor/die selector for the whole library.
7 *
8 * Multi-vendor portability rests on a single rule: every silicon-specific layer (board profiles,
9 * the crypto accelerator HAL, the physical MAC + PHY) is partitioned into a per-vendor subdir and a
10 * common API header pulls in exactly ONE backend per build. This header owns the "which vendor" decision
11 * so nothing downstream has to re-test toolchain-specific macros - a backend keys off `PC_VENDOR_*`, not
12 * off `CONFIG_IDF_TARGET_*` / `STM32*` / `PICO_*` scattered across the tree.
13 *
14 * Exactly one `PC_VENDOR_*` is 1; every other is defined 0 (so `#if PC_VENDOR_ESP` is always valid, never
15 * relies on an undefined-macro-is-0 fallback). The vendor is derived from the toolchain's own target macro:
16 *
17 * - `PC_VENDOR_ESP` - any Espressif target (ESP-IDF `ESP_PLATFORM` / Arduino-ESP32 `ARDUINO_ARCH_ESP32`).
18 * - `PC_VENDOR_STM` - STM32 (Arduino_Core_STM32 `ARDUINO_ARCH_STM32` / STM32Cube `USE_HAL_DRIVER`).
19 * - `PC_VENDOR_RP` - Raspberry Pi silicon (RP2040 / RP2350: `ARDUINO_ARCH_RP2040` / `PICO_*`).
20 * - `PC_VENDOR_TI` - Texas Instruments (`__TI_COMPILER_VERSION__` or an explicit force).
21 * - `PC_VENDOR_HOST` - native / host build (unit tests): no accelerator, portable software everywhere.
22 *
23 * ESP is detected first and stays byte-for-byte compatible with the pre-selector behavior: on every ESP
24 * build `PC_VENDOR_ESP` is 1, and on host builds it is 0, exactly matching the old
25 * `#if defined(CONFIG_IDF_TARGET_*)` test in board_profile.h.
26 */
27
28#ifndef PROTOCORE_PC_PLATFORM_H
29#define PROTOCORE_PC_PLATFORM_H
30
31#include <stdint.h>
32
33// sdkconfig.h carries CONFIG_IDF_TARGET_* on ESP-IDF / Arduino-ESP32 builds and is absent on host and on
34// other vendors' toolchains. Pull it in here (guarded by __has_include) so vendor + die detection is
35// include-order-independent, the same reason board_profile.h does it. Preceded only by the include guard.
36#if defined(__has_include)
37#if __has_include("sdkconfig.h")
38#include "sdkconfig.h"
39#endif
40#endif
41
42// ---------------------------------------------------------------------------
43// Vendor axis - exactly one is 1.
44// ---------------------------------------------------------------------------
45#if defined(ESP_PLATFORM) || defined(ARDUINO_ARCH_ESP32)
46#define PC_VENDOR_ESP 1
47#elif defined(ARDUINO_ARCH_STM32) || defined(USE_HAL_DRIVER) || defined(STM32_CORE_VERSION)
48#define PC_VENDOR_STM 1
49#elif defined(ARDUINO_ARCH_RP2040) || defined(PICO_RP2040) || defined(PICO_RP2350) || defined(PICO_SDK_VERSION_MAJOR)
50#define PC_VENDOR_RP 1
51#elif defined(__TI_COMPILER_VERSION__) || defined(PC_VENDOR_TI_FORCE)
52#define PC_VENDOR_TI 1
53#else
54#define PC_VENDOR_HOST 1
55#endif
56
57// Every vendor macro is defined (0 when not selected) so downstream code can `#if PC_VENDOR_x` freely.
58#ifndef PC_VENDOR_ESP
59#define PC_VENDOR_ESP 0
60#endif
61#ifndef PC_VENDOR_STM
62#define PC_VENDOR_STM 0
63#endif
64#ifndef PC_VENDOR_RP
65#define PC_VENDOR_RP 0
66#endif
67#ifndef PC_VENDOR_TI
68#define PC_VENDOR_TI 0
69#endif
70#ifndef PC_VENDOR_HOST
71#define PC_VENDOR_HOST 0
72#endif
73
74// ---------------------------------------------------------------------------
75// Vendor capabilities - what backend a vendor's board_drivers/ provides.
76// ---------------------------------------------------------------------------
77//
78// The core never tests these. board_drivers/ does, to decide which backend TU compiles. Each is a
79// deliberate statement by the vendor, not a default: choosing software crypto is legitimate (on some
80// parts it is the only option) but it must be chosen. There is no weak symbol behind any of these -
81// linking no backend is an undefined reference, linking two is a duplicate definition, and both fail
82// the build rather than silently selecting one.
83
84// AES-GCM. 1 = the vendor supplies an accelerated AEAD (board_drivers/hal/<vendor>); 0 = the portable
85// software backend, which is software AES plus a table GHASH.
86//
87// Not a small difference and not a preference: measured sealing 1 KiB on an ESP32-S3 at 240 MHz, the
88// vendor AEAD is 81,085 cycles and the software path 616,567 - 7.6x. Hand it to the vendor whenever
89// there is one; choosing software is legitimate where there is not, but it has to be chosen.
90#ifndef PC_HAS_HW_AESGCM
91#if PC_VENDOR_ESP
92#define PC_HAS_HW_AESGCM 1
93#elif PC_VENDOR_HOST
94#define PC_HAS_HW_AESGCM 0 // a unit-test build has no silicon by definition
95#else
96#error \
97 "ProtoCore: this vendor must state PC_HAS_HW_AESGCM (1 = accelerated AEAD in board_drivers/hal/<vendor>, 0 = portable software AES + table GHASH, ~7.6x slower where measured). Choosing software is fine; defaulting into it is not."
98#endif
99#endif
100
101// DH-2048 / RSA modexp. 1 = the vendor supplies an accelerated backend; 0 = the portable software
102// Montgomery backend (board_drivers/hal/portable), which is data-dependent and NOT constant time -
103// see SECURITY.md, timing.
104#ifndef PC_HAS_HW_BIGNUM
105#if PC_VENDOR_ESP
106#define PC_HAS_HW_BIGNUM 1
107#elif PC_VENDOR_HOST
108#define PC_HAS_HW_BIGNUM 0 // a unit-test build has no silicon by definition
109#else
110#error \
111 "ProtoCore: this vendor must state PC_HAS_HW_BIGNUM (1 = accelerated backend in board_drivers/hal/<vendor>, 0 = portable software Montgomery, which is not constant time). Choosing software crypto is fine; defaulting into it is not."
112#endif
113#endif
114
115// ---------------------------------------------------------------------------
116// Execution context identity
117// ---------------------------------------------------------------------------
118//
119// "Which execution context is running me" is a platform question, not a core one, so the core asks
120// here instead of naming an RTOS. Used by the pools' debug owner tripwire to catch a borrow crossing
121// tasks; it is only ever compared for equality, never interpreted.
122//
123// Returns 0 where there is no such concept (host builds): a single context, so every comparison
124// trivially agrees and the tripwire is a no-op rather than a false alarm.
125uintptr_t pc_platform_context_id(void);
126
127// A single "targets real silicon" convenience (any vendor backend, i.e. not the host software floor).
128#define PC_VENDOR_SILICON (PC_VENDOR_ESP || PC_VENDOR_STM || PC_VENDOR_RP || PC_VENDOR_TI)
129
130#endif // PROTOCORE_PC_PLATFORM_H
uintptr_t pc_platform_context_id(void)