mirror of https://github.com/meshcore-dev/MeshCore
committed by
GitHub
10 changed files with 513 additions and 239 deletions
@ -0,0 +1,97 @@ |
|||
#ifdef WITH_W5100S_POE |
|||
|
|||
#include <Arduino.h> |
|||
#include <nrf.h> |
|||
#include "W5100SPoE.h" |
|||
|
|||
// ── Early RST release (constructor priority 200) ─────────────────────────────
|
|||
// Runs before setup(), right after SystemInit — earlier than the ETHERNET_ENABLED
|
|||
// constructor in RAK4631Board.cpp that powers the peripheral rail (WB_IO2,
|
|||
// priority 102 runs first) but well before setup()/board.begin(), so the
|
|||
// W5100S starts drawing its full operating current as early as possible,
|
|||
// before the RAK19018 (Silvertel) converter's foldback timer expires.
|
|||
//
|
|||
// Raw registers because the Arduino GPIO layer isn't up this early.
|
|||
static void __attribute__((constructor(200))) w5100s_early_rst_release() { |
|||
// P0.21 = W5100S RST → HIGH (release from reset)
|
|||
NRF_P0->PIN_CNF[21] = |
|||
(GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) | |
|||
(GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | |
|||
(GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | |
|||
(GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | |
|||
(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); |
|||
NRF_P0->OUTSET = (1UL << 21); |
|||
} |
|||
|
|||
// ── Bit-banged SPI to the W5100S ────────────────────────────────────────────
|
|||
// Shares the SPI bus (SCK=3 / MOSI=30 / MISO=29) with the SX1262 radio; only
|
|||
// the chip-select differs (W5100S CS=26, SX1262 NSS=42). Bit-banged so it
|
|||
// works regardless of which SPIClass owns the bus and runs before RadioLib.
|
|||
// W5100S frame: write [0xF0][hi][lo][data], read [0x0F][hi][lo]->[data].
|
|||
#define ETH_SCK_PIN 3 |
|||
#define ETH_MOSI_PIN 30 |
|||
#define ETH_MISO_PIN 29 |
|||
#define LORA_NSS_PIN 42 |
|||
|
|||
static void bb_write_reg(uint16_t addr, uint8_t data) { |
|||
const uint8_t frame[4] = { 0xF0, (uint8_t)(addr >> 8), (uint8_t)(addr & 0xFF), data }; |
|||
digitalWrite(W5100S_CS_PIN, LOW); |
|||
for (uint8_t b = 0; b < 4; b++) { |
|||
uint8_t v = frame[b]; |
|||
for (int8_t i = 7; i >= 0; i--) { |
|||
digitalWrite(ETH_MOSI_PIN, (v >> i) & 1); |
|||
digitalWrite(ETH_SCK_PIN, HIGH); |
|||
digitalWrite(ETH_SCK_PIN, LOW); |
|||
} |
|||
} |
|||
digitalWrite(W5100S_CS_PIN, HIGH); |
|||
} |
|||
|
|||
static uint8_t bb_read_reg(uint16_t addr) { |
|||
const uint8_t frame[3] = { 0x0F, (uint8_t)(addr >> 8), (uint8_t)(addr & 0xFF) }; |
|||
digitalWrite(W5100S_CS_PIN, LOW); |
|||
for (uint8_t b = 0; b < 3; b++) { |
|||
uint8_t v = frame[b]; |
|||
for (int8_t i = 7; i >= 0; i--) { |
|||
digitalWrite(ETH_MOSI_PIN, (v >> i) & 1); |
|||
digitalWrite(ETH_SCK_PIN, HIGH); |
|||
digitalWrite(ETH_SCK_PIN, LOW); |
|||
} |
|||
} |
|||
uint8_t out = 0; |
|||
for (int8_t i = 7; i >= 0; i--) { |
|||
digitalWrite(ETH_SCK_PIN, HIGH); |
|||
out = (out << 1) | (digitalRead(ETH_MISO_PIN) & 1); |
|||
digitalWrite(ETH_SCK_PIN, LOW); |
|||
} |
|||
digitalWrite(W5100S_CS_PIN, HIGH); |
|||
return out; |
|||
} |
|||
|
|||
// ── Full W5100S bring-up ────────────────────────────────────────────────────
|
|||
// Called from RAK4631Board::begin(). Confirms RST is driven (Arduino API, in
|
|||
// case the core re-init touched it), then soft-resets and reads VERSIONR.
|
|||
// Returns VERSIONR (0x51 = healthy W5100S).
|
|||
uint8_t w5100s_poe_init() { |
|||
delay(20); // let the rail/W5100S settle after the ETHERNET_ENABLED ctor's WB_IO2 enable
|
|||
|
|||
// Park both chip-selects HIGH on the shared bus, RST released.
|
|||
pinMode(LORA_NSS_PIN, OUTPUT); digitalWrite(LORA_NSS_PIN, HIGH); |
|||
pinMode(W5100S_CS_PIN, OUTPUT); digitalWrite(W5100S_CS_PIN, HIGH); |
|||
pinMode(W5100S_RST_PIN, OUTPUT); digitalWrite(W5100S_RST_PIN, HIGH); |
|||
|
|||
pinMode(ETH_SCK_PIN, OUTPUT); digitalWrite(ETH_SCK_PIN, LOW); |
|||
pinMode(ETH_MOSI_PIN, OUTPUT); digitalWrite(ETH_MOSI_PIN, LOW); |
|||
pinMode(ETH_MISO_PIN, INPUT); |
|||
|
|||
bb_write_reg(0x0000, 0x80); // MR: software reset
|
|||
delay(2); |
|||
|
|||
uint8_t ver = bb_read_reg(0x0080); // VERSIONR (0x51 on W5100S)
|
|||
|
|||
// Chip stays powered and out of reset; PHY auto-negotiates with the switch
|
|||
// and the W5100S draws its full operating current.
|
|||
return ver; |
|||
} |
|||
|
|||
#endif // WITH_W5100S_POE
|
|||
@ -0,0 +1,36 @@ |
|||
#pragma once |
|||
|
|||
// W5100S early activation for PoE operation on RAK10720 (RAK4631 + RAK13800 +
|
|||
// RAK19018).
|
|||
//
|
|||
// ROOT CAUSE (confirmed via RAK forum + Meshtastic rak4631_eth_gw variant):
|
|||
// The RAK19018 PoE module (Silvertel Ag9905MT) enters a non-continuous
|
|||
// "gated pulse" mode when the load is below ~125-200 mA. A bare MeshCore
|
|||
// repeater draws only a few mA, so the converter never latches → the supply
|
|||
// pulses and the device never boots (fade-in / brighten / die / repeat LED).
|
|||
//
|
|||
// The fix: bring the W5100S PHY into its active state as early as possible.
|
|||
// An active W5100S draws ~120 mA — enough to keep the Silvertel converter
|
|||
// latched in continuous mode. The peripheral power rail (WB_IO2 / P1.02) is
|
|||
// already driven HIGH by an early constructor in RAK4631Board.cpp whenever
|
|||
// ETHERNET_ENABLED is set; this file only handles releasing RST (the rail
|
|||
// alone isn't enough — the chip must actually be brought out of reset and
|
|||
// made to draw its full current well before the Ethernet library's own
|
|||
// (later, disruptive) bring-up runs).
|
|||
//
|
|||
// Pin mapping (from Meshtastic rak4631_eth_gw variant.h):
|
|||
// RST → PIN_ETHERNET_RESET = 21 (P0.21 / WB_IO3)
|
|||
// CS → PIN_ETHERNET_SS = 26 (WB_SPI_CS)
|
|||
// SPI → SPI1 (SCK=3, MISO=29, MOSI=30) [not used in Layer 1]
|
|||
|
|||
#ifndef W5100S_RST_PIN |
|||
#define W5100S_RST_PIN 21 // P0.21 / WB_IO3
|
|||
#endif |
|||
|
|||
#ifndef W5100S_CS_PIN |
|||
#define W5100S_CS_PIN 26 // WB_SPI_CS
|
|||
#endif |
|||
|
|||
// Called from RAK4631Board::begin(); fully brings up the W5100S (soft reset +
|
|||
// activation) so it draws full operating current. Returns VERSIONR (0x51 = ok).
|
|||
uint8_t w5100s_poe_init(); |
|||
Loading…
Reference in new issue