Skip to content

Commit

Permalink
[Feature] Better chip unsafe pin definitions (#153)
Browse files Browse the repository at this point in the history
* Start implementing per-chip constants

* Implement more chip limitations

* Add valid pin listing methods

* Fix Pico naming

* Add compile time pin definition check
  • Loading branch information
hhvrc authored and LucHeart committed Jan 22, 2024
1 parent 4d7d88a commit 2c7b5e9
Show file tree
Hide file tree
Showing 5 changed files with 249 additions and 50 deletions.
47 changes: 0 additions & 47 deletions include/Board.h

This file was deleted.

234 changes: 234 additions & 0 deletions include/Chipset.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
#pragma once

#include <driver/gpio.h>

#include <bitset>

// The following chipsets are supported by the OpenShock firmware.
// To find documentation for a specific chipset, see the docs link.
// You need to navigate to the datasheets pin's section, the unsafe pins are usually listed under the "Strapping Pins" section.
// We want to avoid using these pins as they are used for boot mode and SDIO slave timing selection, and its easy to encounter issues if we use them.
#pragma region Chipset Definitions
// ESP8266EX
//
// Chips: ESP8266EX
//
// Docs: https://www.espressif.com/sites/default/files/documentation/0a-esp8266ex_datasheet_en.pdf
#ifdef OPENSHOCK_FW_CHIP_ESP8266EX
#define OPENSHOCK_FW_CHIP_NAME "ESP8266EX"
// GPIO3, GPIO1 is used for UART0 RXD/TXD.
// GPIO0, GPIO2, and GPIO15 are used for boot mode and SDIO slave timing selection.
#define CHIP_UNSAFE_GPIO(pin) (pin == GPIO_NUM_0 || pin == GPIO_NUM_1 || pin == GPIO_NUM_2 || pin == GPIO_NUM_3 || pin == GPIO_NUM_15)
#endif

// ESP8285
//
// Chips: ESP8285N08, ESP8285H16
//
// Docs: https://www.espressif.com/sites/default/files/documentation/0a-esp8285_datasheet_en.pdf
#ifdef OPENSHOCK_FW_CHIP_ESP8285
#define OPENSHOCK_FW_CHIP_NAME "ESP8285"
// GPIO3, GPIO1 is used for UART0 RXD/TXD.
// GPIO0, GPIO2, and GPIO15 are used for boot mode and SDIO slave timing selection.
#define CHIP_UNSAFE_GPIO(pin) (pin == GPIO_NUM_0 || pin == GPIO_NUM_1 || pin == GPIO_NUM_2 || pin == GPIO_NUM_3 || pin == GPIO_NUM_15)
#endif

// ESP8684
//
// Chips: ESP8684H1, ESP8684H2, ESP8684H4
//
// Docs: https://www.espressif.com/sites/default/files/documentation/esp8684_datasheet_en.pdf
// Docs: https://www.espressif.com/sites/default/files/documentation/esp8684_technical_reference_manual_en.pdf#bootctrl
#ifdef OPENSHOCK_FW_CHIP_ESP8684
#define OPENSHOCK_FW_CHIP_NAME "ESP8684"
// GPIO3, GPIO1 is used for UART0 RXD/TXD.
// GPIO8, GPIO9 are strapping pins used to control the boot mode adn ROM code printing
#define CHIP_UNSAFE_GPIO(pin) (pin == GPIO_NUM_1 || pin == GPIO_NUM_3 || pin == GPIO_NUM_8 || pin == GPIO_NUM_9)
#endif

// ESP8685
//
// Chips: ESP8685H2, ESP8685H4
//
// Docs: https://www.espressif.com/sites/default/files/documentation/esp8685_datasheet_en.pdf
#ifdef OPENSHOCK_FW_CHIP_ESP8685
#define OPENSHOCK_FW_CHIP_NAME "ESP8685"
// GPIO20, GPIO21 is used for UART0 RXD/TXD.
// GPIO2, GPIO8, GPIO9 are strapping pins.
#define CHIP_UNSAFE_GPIO(pin) (pin == GPIO_NUM_2 || pin == GPIO_NUM_8 || pin == GPIO_NUM_9 || pin == GPIO_NUM_20 || pin == GPIO_NUM_21)
#endif

// ESP32
//
// Chips: ESP32-D0WD-V3, ESP32-D0WDR2-V3, ESP32-U4WDH, ESP32-S0WD, ESP32-D0WD, ESP32-D0WDQ6, ESP32-D0WDQ6-V3
//
// Docs: https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf
#ifdef OPENSHOCK_FW_CHIP_ESP32
#define OPENSHOCK_FW_CHIP_NAME "ESP32"

// GPIO1, GPIO3 is used for UART0 RXD/TXD.
// GPIO0, GPIO2 is used to control the boot mode of the chip.
// GPIO5, GPIO15 is used for SDIO slave timing selection.
// GPIO6, GPIO7, GPIO8, GPIO9, GPIO11, GPIO16, GPIO17 is used for SPI flash connection. (DO NOT TOUCH)
//
// See: ESP32 Series Datasheet Version 4.3 Section 2.2 Pin Overview
// See: ESP32 Series Datasheet Version 4.3 Section 2.4 Strapping Pins
#define CHIP_UNSAFE_GPIO(pin) \
(pin == GPIO_NUM_1 || pin == GPIO_NUM_3 || pin == GPIO_NUM_0 || pin == GPIO_NUM_2 || pin == GPIO_NUM_5 || pin == GPIO_NUM_15 || pin == GPIO_NUM_6 || pin == GPIO_NUM_7 || pin == GPIO_NUM_8 || pin == GPIO_NUM_9 || pin == GPIO_NUM_11 || pin == GPIO_NUM_16 \
|| pin == GPIO_NUM_17)
#endif

// ESP32-PICO-D4
//
// Chips: ESP32-PICO-D4
//
// Docs: https://www.espressif.com/sites/default/files/documentation/esp32-pico_series_datasheet_en.pdf (Section 2.1.2 - 2.1.3 Pin Description and Pin Mapping between ESP and Flash/PSRAM)
#ifdef OPENSHOCK_FW_CHIP_ESP32PICOD4
#define OPENSHOCK_FW_CHIP_NAME "ESP32-PICO-D4"
// GPIO3, GPIO1 is used for UART0 RXD/TXD.
// GPIO25, GPIO27, GPIO29, GPIO30, GPIO31, GPIO32, GPIO33 is used for SPI flash connection. (DO NOT TOUCH)
// GPIO12, GPIO0, GPIO2, GPIO15, and GPIO5 are used for boot mode and SDIO slave timing selection.
#define CHIP_UNSAFE_GPIO(pin) (pin == GPIO_NUM_3 || pin == GPIO_NUM_1 || pin == GPIO_NUM_25 || pin == GPIO_NUM_27 || pin == GPIO_NUM_29 || pin == GPIO_NUM_30 || pin == GPIO_NUM_31 || pin == GPIO_NUM_32 || pin == GPIO_NUM_33 || pin == GPIO_NUM_12 || pin == GPIO_NUM_0 || pin == GPIO_NUM_2 || pin == GPIO_NUM_15 || pin == GPIO_NUM_5)
#endif

// ESP32-PICO-V3
//
// Chips:, ESP32-PICO-V3, ESP32-PICO-V3-02
//
// Docs: https://www.espressif.com/sites/default/files/documentation/esp32-pico_series_datasheet_en.pdf
#ifdef OPENSHOCK_FW_CHIP_ESP32PICOV3
#define OPENSHOCK_FW_CHIP_NAME "ESP32-PICO-V3"
// GPIO3, GPIO1 is used for UART0 RXD/TXD.
// GPIO6, GPIO11, GPIO9, GPIO10 is used for SPI flash connection. (DO NOT TOUCH)
// GPIO12, GPIO0, GPIO2, GPIO15, and GPIO5 are used for boot mode and SDIO slave timing selection.
#define CHIP_UNSAFE_GPIO(pin) (pin == GPIO_NUM_3 || pin == GPIO_NUM_1 || pin == GPIO_NUM_6 || pin == GPIO_NUM_11 || pin == GPIO_NUM_9 || pin == GPIO_NUM_10 || pin == GPIO_NUM_12 || pin == GPIO_NUM_0 || pin == GPIO_NUM_2 || pin == GPIO_NUM_15 || pin == GPIO_NUM_5)
#endif

// ESP32-S2
//
// Chips: ESP32-S2, ESP32-S2FH2, ESP32-S2FH4, ESP32-S2FN4R2, ESP32-S2R2
//
// Docs: https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf
#ifdef OPENSHOCK_FW_CHIP_ESP32S2
#define OPENSHOCK_FW_CHIP_NAME "ESP32-S2"
// GPIO44, GPIO43 is used for UART0 RXD/TXD.
// GPIO29, GPIO26, GPIO32, GPIO31, GPIO30, GPIO28, GPIO27 is used for SPI flash connection. (DO NOT TOUCH)
// GPIO0, GPIO45, GPIO46 is strapping pins used to control the boot mode and misc. functions.
#define CHIP_UNSAFE_GPIO(pin) (pin == GPIO_NUM_44 || pin == GPIO_NUM_43 || pin == GPIO_NUM_29 || pin == GPIO_NUM_26 || pin == GPIO_NUM_32 || pin == GPIO_NUM_31 || pin == GPIO_NUM_30 || pin == GPIO_NUM_28 || pin == GPIO_NUM_27 || pin == GPIO_NUM_0 || pin == GPIO_NUM_45 || pin == GPIO_NUM_46)
#endif

// ESP32-S3
//
// Chips: ESP32-S3, ESP32-S3FN8, ESP32-S3R2, ESP32-S3R8, ESP32-S3R8V, ESP32-S3R16V, ESP32-S3FH4R2
//
// Docs: https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf
#ifdef OPENSHOCK_FW_CHIP_ESP32S3
#define OPENSHOCK_FW_CHIP_NAME "ESP32-S3"
// GPIO44, GPIO43 is used for UART0 RXD/TXD.
// GPIO30, GPIO29, GPIO26, GPIO32, GPIO31, GPIO28, GPIO27, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37 is used for SPI flash connection. (DO NOT TOUCH)
// GPIO0, GPIO3, GPIO45, GPIO46 is strapping pins used to control the boot mode and misc. functions.
#define CHIP_UNSAFE_GPIO(pin) (pin == GPIO_NUM_44 || pin == GPIO_NUM_43 || pin == GPIO_NUM_30 || pin == GPIO_NUM_29 || pin == GPIO_NUM_26 || pin == GPIO_NUM_32 || pin == GPIO_NUM_31 || pin == GPIO_NUM_28 || pin == GPIO_NUM_27 || pin == GPIO_NUM_33 || pin == GPIO_NUM_34 || pin == GPIO_NUM_35 || pin == GPIO_NUM_36 || pin == GPIO_NUM_37 || pin == GPIO_NUM_0 || pin == GPIO_NUM_3 || pin == GPIO_NUM_45 || pin == GPIO_NUM_46)
#endif

// ESP32-S3-PICO-1
//
// Chips: ESP32-S3-PICO-1-N8R2, ESP32-S3-PICO-1-N8R8
//
// Docs: https://www.espressif.com/sites/default/files/documentation/esp32-s3-pico-1_datasheet_en.pdf
#ifdef OPENSHOCK_FW_CHIP_ESP32S3PICO1
#define OPENSHOCK_FW_CHIP_NAME "ESP32-S3-PICO-1"
#error "ESP32-S3-PICO-1 is not supported yet."
#endif

// ESP32-C3
//
// Chips: ESP32-C3, ESP32-C3FN4, ESP32-C3FH4, ESP32-C3FH4AZ
//
// Docs: https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf
#ifdef OPENSHOCK_FW_CHIP_ESP32C3
#define OPENSHOCK_FW_CHIP_NAME "ESP32-C3"
#error "ESP32-C3 is not supported yet."
#endif

// ESP32-C6
//
// Chips: ESP32-C6, ESP32-C6FH4
//
// Docs: https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf
#ifdef OPENSHOCK_FW_CHIP_ESP32C6
#define OPENSHOCK_FW_CHIP_NAME "ESP32-C6"
#error "ESP32-C6 is not supported yet."
#endif

#pragma endregion

/// Board specific bad-pin bypasses for compatibility reasons.
/// To be clear, these pins are still unsafe, but we need to use them for compatibility reasons.
#pragma region Board Specific Bypasses

#ifdef OPENSHOCK_FW_BOARD_WEMOSD1MINIESP32
#define OPENSHOCK_BYPASSED_GPIO(pin) (pin == 15)
#endif
#ifdef OPENSHOCK_FW_BOARD_WEMOSLOLINS2MINI
#define OPENSHOCK_BYPASSED_GPIO(pin) (pin == 15)
#endif
#ifdef OPENSHOCK_FW_BOARD_PISHOCK2023
#define OPENSHOCK_BYPASSED_GPIO(pin) (pin == 12)
#endif
#ifdef OPENSHOCK_FW_BOARD_PISHOCKLITE2021
#define OPENSHOCK_BYPASSED_GPIO(pin) (pin == 15)
#endif
#ifdef OPENSHOCK_FW_BOARD_SEEEDXIAOESP32S3
#define OPENSHOCK_BYPASSED_GPIO(pin) (pin == 21)
#endif
#ifdef OPENSHOCK_FW_BOARD_OPENSHOCKCOREV1
#define OPENSHOCK_BYPASSED_GPIO(pin) (pin == 15)
#endif
#ifndef OPENSHOCK_BYPASSED_GPIO
#define OPENSHOCK_BYPASSED_GPIO(pin) (false)
#endif

#pragma endregion

#define OPENSHOCK_IS_VALID_GPIO(pin) ((pin < GPIO_NUM_MAX && !CHIP_UNSAFE_GPIO(pin)) || OPENSHOCK_BYPASSED_GPIO(pin))
#define OPENSHOCK_IS_VALID_INPUT_GPIO(pin) ((OPENSHOCK_IS_VALID_GPIO(pin) && (GPIO_IS_VALID_GPIO(pin) && !GPIO_IS_VALID_OUTPUT_GPIO(pin))) || OPENSHOCK_BYPASSED_GPIO(pin))
#define OPENSHOCK_IS_VALID_OUTPUT_GPIO(pin) ((OPENSHOCK_IS_VALID_GPIO(pin) && GPIO_IS_VALID_OUTPUT_GPIO(pin)) || OPENSHOCK_BYPASSED_GPIO(pin))

namespace OpenShock {
constexpr bool IsValidGPIOPin(std::uint8_t pin) {
return OPENSHOCK_IS_VALID_GPIO(pin);
}
constexpr bool IsValidInputPin(std::uint8_t pin) {
return OPENSHOCK_IS_VALID_INPUT_GPIO(pin);
}
constexpr bool IsValidOutputPin(std::uint8_t pin) {
return OPENSHOCK_IS_VALID_OUTPUT_GPIO(pin);
}
constexpr std::bitset<UINT8_MAX+1> GetValidGPIOPins() {
std::bitset<UINT8_MAX+1> pins;
for (std::uint8_t i = 0; i < GPIO_NUM_MAX; i++) {
if (IsValidGPIOPin(i)) {
pins.set(i);
}
}
return pins;
}
constexpr std::bitset<UINT8_MAX+1> GetValidInputPins() {
std::bitset<UINT8_MAX+1> pins;
for (std::uint8_t i = 0; i < GPIO_NUM_MAX; i++) {
if (IsValidInputPin(i)) {
pins.set(i);
}
}
return pins;
}
constexpr std::bitset<UINT8_MAX+1> GetValidOutputPins() {
std::bitset<UINT8_MAX+1> pins;
for (std::uint8_t i = 0; i < GPIO_NUM_MAX; i++) {
if (IsValidOutputPin(i)) {
pins.set(i);
}
}
return pins;
}
} // namespace OpenShock
4 changes: 4 additions & 0 deletions include/Constants.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "Chipset.h"

#include <cstdint>

#ifndef OPENSHOCK_API_DOMAIN
Expand All @@ -19,6 +21,8 @@
#ifndef OPENSHOCK_RF_TX_GPIO
#warning "OPENSHOCK_RF_TX_GPIO is not defined, using default value of UINT8_MAX"
#define OPENSHOCK_RF_TX_GPIO UINT8_MAX
#elif !OPENSHOCK_IS_VALID_OUTPUT_GPIO(OPENSHOCK_RF_TX_GPIO)
#error "OPENSHOCK_RF_TX_GPIO is not a valid output GPIO, and is not declared as bypassed by board specific definitions, refusing to compile"
#endif

namespace OpenShock::Constants {
Expand Down
12 changes: 10 additions & 2 deletions scripts/embed_env_vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,17 @@ def get_git_commit() -> str | None:

# Find env variables based on only the pioenv and sysenv.
def get_pio_firmware_vars() -> dict[str, str | int | bool]:
fw_board = pio.get_string('PIOENV')
fw_chip = pio.get_string('BOARD_MCU')

def macroify(s: str) -> str:
return s.upper().replace('-', '').replace('_', '')

vars = {}
vars['OPENSHOCK_FW_BOARD'] = pio.get_string('PIOENV')
vars['OPENSHOCK_FW_CHIP'] = pio.get_string('BOARD_MCU')
vars['OPENSHOCK_FW_BOARD'] = fw_board
vars['OPENSHOCK_FW_BOARD_' + macroify(fw_board)] = True # Used for conditional compilation.
vars['OPENSHOCK_FW_CHIP'] = fw_chip
vars['OPENSHOCK_FW_CHIP_' + macroify(fw_chip)] = True # Used for conditional compilation.
vars['OPENSHOCK_FW_MODE'] = pio_build_type
git_commit = get_git_commit()
if git_commit is not None:
Expand Down
2 changes: 1 addition & 1 deletion src/CommandHandler.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "CommandHandler.h"

#include "Board.h"
#include "Chipset.h"
#include "config/Config.h"
#include "Constants.h"
#include "Logging.h"
Expand Down

0 comments on commit 2c7b5e9

Please sign in to comment.