diff --git a/boards/generic_wl5e.json b/boards/generic_wl5e.json new file mode 100644 index 00000000..87e14043 --- /dev/null +++ b/boards/generic_wl5e.json @@ -0,0 +1,31 @@ +{ + "build": { + "core": "stm32", + "cpu": "cortex-m4", + "extra_flags": "-DSTM32WLxx -DSTM32WLE5xx -DARDUINO_GENERIC_WLE5CCUX", + "f_cpu": "48000000L", + "mcu": "stm32wle5ccu", + "variant": "STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U", + "product_line": "STM32WLE5xx" + }, + "debug": { + "default_tools": [ + "stlink" + ], + "jlink_device": "STM32WLE5CC", + "openocd_target": "stm32wlx", + "svd_path": "STM32WLE5_CM4.svd" + }, + "frameworks": ["arduino"], + "name": "BB-STM32WL", + "upload": { + "maximum_ram_size": 65536, + "maximum_size": 262144, + "protocol": "cmsis-dap", + "protocols": [ + "cmsis-dap" + ] + }, + "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32wl-series.html", + "vendor": "ST" +} diff --git a/platformio.ini b/platformio.ini index 554645c4..f06c8cff 100644 --- a/platformio.ini +++ b/platformio.ini @@ -184,4 +184,24 @@ lib_ignore = lib_deps = ${arduino_base.lib_deps} ${environmental_base.lib_deps} - https://github.com/kokke/tiny-AES-c.git \ No newline at end of file + https://github.com/kokke/tiny-AES-c.git + +[stm32wl5e_base] +platform = ststm32 +board = generic_wl5e +framework = arduino +build_type = debug +build_flags = + ${arduino_base.build_flags} + -Isrc/platform/stm32wl -g + -DHAL_SUBGHZ_MODULE_ENABLED +# Arduino/PlatformIO framework-arduinoststm32 package does not presently have SUBGHZSPI support +# -DPIN_SPI_MOSI=PINSUBGHZSPIMOSI -DPIN_SPI_MISO=PINSUBGHZSPIMISO -DPIN_SPI_SCK=PINSUBGHZSPISCK +build_src_filter = + ${arduino_base.build_src_filter} - - - - - - - - - - - - - +lib_deps = + ${env.lib_deps} + https://github.com/jgromes/RadioLib.git + https://github.com/kokke/tiny-AES-c.git +lib_ignore = + mathertel/OneButton@^2.0.3 diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 633a8dd5..e7073851 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -43,6 +43,10 @@ RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq : NotifiedWorkerThread("RadioIf"), module(cs, irq, rst, busy, spi, spiSettings), iface(_iface) { instance = this; +#if defined(ARCH_STM32WL) && defined(USE_SX1262) + module.setCb_digitalWrite(stm32wl_emulate_digitalWrite); + module.setCb_digitalRead(stm32wl_emulate_digitalRead); +#endif } #ifdef ARCH_ESP32 diff --git a/src/platform/stm32wl/STM32WLCryptoEngine.cpp b/src/platform/stm32wl/STM32WLCryptoEngine.cpp new file mode 100644 index 00000000..535d88cf --- /dev/null +++ b/src/platform/stm32wl/STM32WLCryptoEngine.cpp @@ -0,0 +1,36 @@ +#include "configuration.h" +#include "CryptoEngine.h" +#include "aes.hpp" + +class STM32WLCryptoEngine : public CryptoEngine +{ + public: + STM32WLCryptoEngine() {} + + ~STM32WLCryptoEngine() {} + + /** + * Encrypt a packet + * + * @param bytes is updated in place + */ + virtual void encrypt(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes) override + { + if (key.length > 0) { + AES_ctx ctx; + initNonce(fromNode, packetNum); + AES_init_ctx_iv(&ctx, key.bytes, nonce); + AES_CTR_xcrypt_buffer(&ctx, bytes, numBytes); + } + } + + virtual void decrypt(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes) override + { + // For CTR, the implementation is the same + encrypt(fromNode, packetNum, numBytes, bytes); + } + + private: +}; + +CryptoEngine *crypto = new STM32WLCryptoEngine(); diff --git a/src/platform/stm32wl/architecture.h b/src/platform/stm32wl/architecture.h new file mode 100644 index 00000000..02196eaf --- /dev/null +++ b/src/platform/stm32wl/architecture.h @@ -0,0 +1,31 @@ +#pragma once + +#define ARCH_STM32WL + +// +// defaults for STM32WL architecture +// + +// +// set HW_VENDOR +// + +#ifndef HW_VENDOR + #define HW_VENDOR HardwareModel_PRIVATE_HW +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void stm32wl_emulate_digitalWrite(long unsigned int pin, long unsigned int value); + int stm32wl_emulate_digitalRead(long unsigned int pin); +#ifdef __cplusplus +} +#endif + +/* virtual pins for stm32wl_emulate_digitalWrite() / stm32wl_emulate_digitalRead() to recognize */ +#define SX126X_CS 1000 +#define SX126X_DIO1 1001 +#define SX126X_RESET 1003 +#define SX126X_BUSY 1004 + diff --git a/src/platform/stm32wl/layer.c b/src/platform/stm32wl/layer.c new file mode 100644 index 00000000..1352b391 --- /dev/null +++ b/src/platform/stm32wl/layer.c @@ -0,0 +1,67 @@ +#include +#include "architecture.h" +#include "stm32wlxx.h" +#include "stm32wlxx_hal.h" + +void HardFault_Handler(void) +{ + asm("bkpt"); +} + +void stm32wl_emulate_digitalWrite(long unsigned int pin, long unsigned int value) +{ + switch (pin) + { + case SX126X_CS: /* active low */ + if (value) + LL_PWR_UnselectSUBGHZSPI_NSS(); + else + LL_PWR_SelectSUBGHZSPI_NSS(); + break; + case SX126X_RESET: /* active low */ + if (value) + LL_RCC_RF_DisableReset(); + else + { + LL_RCC_RF_EnableReset(); + LL_RCC_HSE_EnableTcxo(); + LL_RCC_HSE_Enable(); + while (!LL_RCC_HSE_IsReady()); + } + break; + default: + asm("bkpt"); + break; + } +} + +static bool irq_happened; + +void SUBGHZ_Radio_IRQHandler(void) +{ + NVIC_DisableIRQ(SUBGHZ_Radio_IRQn); + irq_happened = true; +} + +int stm32wl_emulate_digitalRead(long unsigned int pin) +{ + int outcome = 0; + + switch (pin) + { + case SX126X_BUSY: +// return ((LL_PWR_IsActiveFlag_RFBUSYMS() & LL_PWR_IsActiveFlag_RFBUSYS()) == 1UL); + outcome = LL_PWR_IsActiveFlag_RFBUSYS(); + break; + case SX126X_DIO1: + default: + NVIC_ClearPendingIRQ(SUBGHZ_Radio_IRQn); + irq_happened = false; + NVIC_EnableIRQ(SUBGHZ_Radio_IRQn); + for (int i = 0; i < 64; i++) asm("nop"); + outcome = irq_happened; + break; + } + return outcome; +} + diff --git a/src/platform/stm32wl/main-stm32wl.cpp b/src/platform/stm32wl/main-stm32wl.cpp new file mode 100644 index 00000000..f5b83a70 --- /dev/null +++ b/src/platform/stm32wl/main-stm32wl.cpp @@ -0,0 +1,27 @@ +#include +#include +#include "configuration.h" +#include "RTC.h" + +void setBluetoothEnable(bool on) {} + +void playStartMelody() {} + +void updateBatteryLevel(uint8_t level) {} + +void getMacAddr(uint8_t *dmac) +{ + for (int i = 0; i < 6; i++) + dmac[i] = i; +} + +void cpuDeepSleep(uint64_t msecToWake) {} + +/* pacify libc_nano */ +extern "C" { +int _gettimeofday( struct timeval *tv, void *tzvp ) +{ + return -1; +} +} + diff --git a/variants/wio-e5/platformio.ini b/variants/wio-e5/platformio.ini new file mode 100644 index 00000000..0050d411 --- /dev/null +++ b/variants/wio-e5/platformio.ini @@ -0,0 +1,4 @@ +[env:wio-e5] +extends = stm32wl5e_base +build_flags = ${stm32wl5e_base.build_flags} -Ivariants/wio-e5 -DHAL_DAC_MODULE_ONLY + -DSERIAL_UART_INSTANCE=1 -DPIN_SERIAL_RX=PB7 -DPIN_SERIAL_TX=PB6 diff --git a/variants/wio-e5/variant.h b/variants/wio-e5/variant.h new file mode 100644 index 00000000..3ef371e2 --- /dev/null +++ b/variants/wio-e5/variant.h @@ -0,0 +1,29 @@ +/* +Wio-E5 mini (formerly LoRa-E5 mini) +https://www.seeedstudio.com/LoRa-E5-mini-STM32WLE5JC-p-4869.html +https://www.seeedstudio.com/LoRa-E5-Wireless-Module-p-4745.html +*/ + +/* +This variant is a work in progress. +Do not expect a working Meshtastic device with this target. +*/ + +#ifndef _VARIANT_WIOE5_ +#define _VARIANT_WIOE5_ + +//Arduino/PlatformIO support for SUBGHZSPI is not currently available +//#define USE_SX1262 + +#ifdef USE_SX1262 + #define HAS_RADIO 1 + + /* module only transmits through RFO_HP */ + #define SX126X_RXEN PA5 + #define SX126X_TXEN PA4 + + /* TCXO fed by internal LDO option behind PB0 pin */ + #define SX126X_E22 +#endif + +#endif \ No newline at end of file