Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions espstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ type StackConfig struct {
MaxTCPPorts int
MaxUDPPorts int
PassivePeers int
// AcceptBroadcast4 enables reception of IPv4 broadcast packets.
// Must be true when running a DHCP server (AP mode).
AcceptBroadcast4 bool
}

// DHCPConfig configures DHCP address acquisition.
Expand All @@ -57,15 +60,16 @@ func NewStack(dev *NetDev, cfg StackConfig) (*Stack, error) {
stack := &Stack{dev: dev}
const MTU = MaxFrameSize - ethernet.MaxOverheadSize + 4 // CRC not included:+4
xcfg := xnet.StackConfig{
DNSServer: cfg.DNSServer,
NTPServer: cfg.NTPServer,
Hostname: cfg.Hostname,
MaxActiveTCPPorts: uint16(cfg.MaxTCPPorts),
MaxActiveUDPPorts: uint16(cfg.MaxUDPPorts),
RandSeed: time.Now().UnixNano() ^ cfg.RandSeed,
HardwareAddress: mac,
MTU: MTU,
PassivePeers: cfg.PassivePeers,
DNSServer: cfg.DNSServer,
NTPServer: cfg.NTPServer,
Hostname: cfg.Hostname,
MaxActiveTCPPorts: uint16(cfg.MaxTCPPorts),
MaxActiveUDPPorts: uint16(cfg.MaxUDPPorts),
RandSeed: time.Now().UnixNano() ^ cfg.RandSeed,
HardwareAddress: mac,
MTU: MTU,
PassivePeers: cfg.PassivePeers,
AcceptIPv4Broadcast: cfg.AcceptBroadcast4,
}
if cfg.StaticAddress.IsValid() && cfg.StaticAddress.Is4() {
xcfg.StaticAddress4 = cfg.StaticAddress.As4()
Expand Down
7 changes: 4 additions & 3 deletions examples/ap/main-ap.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ func main() {

println("ap: creating lneto stack...")
stack, err := espradio.NewStack(nd, espradio.StackConfig{
Hostname: ssid,
StaticAddress: addr,
MaxUDPPorts: 2,
Hostname: ssid,
StaticAddress: addr,
MaxUDPPorts: 2,
AcceptBroadcast4: true,
})
if err != nil {
failure("ap: stack err: " + err.Error())
Expand Down
16 changes: 12 additions & 4 deletions isr.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,16 @@ void espradio_user_exception(uint32_t cause, uint32_t epc, uint32_t excvaddr, ui

/* ---- ISR fn/arg storage ---- */

static void (*s_isr_fn[32])(void *);
static void *s_isr_arg[32];
/* On ESP32, place WiFi-only tables in DRAM1 (.wifibss) to free SRAM2 for
* the Go GC heap. On other targets they stay in normal .bss. */
#if CONFIG_IDF_TARGET_ESP32
#define WIFIBSS __attribute__((section(".wifibss")))
#else
#define WIFIBSS
#endif

static void (*s_isr_fn[32])(void *) WIFIBSS;
static void *s_isr_arg[32] WIFIBSS;

/* Bitmask of ISR slots registered via espradio_set_intr (WiFi sources only). */
static uint32_t s_wifi_isr_slots;
Expand Down Expand Up @@ -140,8 +148,8 @@ void espradio_task_yield_from_isr(void) {
static volatile uint32_t s_isr_ring_head;
static volatile uint32_t s_isr_ring_tail;
static volatile uint32_t s_isr_ring_drops;
static void *s_isr_ring_queue[ESPRADIO_ISR_RING_SIZE];
static uint8_t s_isr_ring_items[ESPRADIO_ISR_RING_SIZE][ESPRADIO_ISR_ITEM_SIZE];
static void *s_isr_ring_queue[ESPRADIO_ISR_RING_SIZE] WIFIBSS;
static uint8_t s_isr_ring_items[ESPRADIO_ISR_RING_SIZE][ESPRADIO_ISR_ITEM_SIZE] WIFIBSS;

int32_t espradio_queue_send_from_isr(void *queue, void *item, void *hptw) {
if (hptw) {
Expand Down
37 changes: 19 additions & 18 deletions netif.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,18 @@ extern void (*mesh_rxcb)(void);

static void blob_cb_noop(void) { }

/* pp_wdev_funcs relocation: the ROM ppTask dispatcher calls through a
* heap-allocated function-pointer table (pp_wdev_funcs, 196 entries = 0x310
* bytes). DMA corruption can zero heap entries at runtime → pc:nil crash.
* After esp_wifi_start() we copy the table into static .bss and redirect
* the ROM pointer there, where DMA cannot reach. */
/* DMA-corruption workaround tables: relocate heap-allocated function-pointer
* tables to static .bss where DMA cannot reach. Only needed on ESP32-C3/S3;
* on the original ESP32 the blob manages these tables itself and the entry
* counts differ, so these are compiled out to save ~1.9 KB BSS. */
#define PP_WDEV_FUNCS_ENTRIES 196
static uint32_t s_pp_wdev_save[PP_WDEV_FUNCS_ENTRIES];

/* net80211_funcs relocation: same DMA corruption issue as pp_wdev_funcs.
* The blob allocates this table on the heap; we relocate to static .bss.
* net80211_funcs_init writes ~44 entries; 128 provides safe headroom. */
#define NET80211_FUNCS_MAX_ENTRIES 128
static uint32_t s_net80211_funcs_save[NET80211_FUNCS_MAX_ENTRIES];

/* g_phyFuns relocation: the PHY function table lives at a fixed DRAM address
* (0x3fcef3d4, size 0x298 = 166 words) that can be corrupted at runtime —
* entries are overwritten with arena allocation addresses, causing
* InstructionFetchError when the PHY calibration timer reads temperature.
* Relocate to static .bss after init and redirect g_phyFuns. */
#define PHY_FUNCS_TABLE_WORDS 166
#if !CONFIG_IDF_TARGET_ESP32
static uint32_t s_pp_wdev_save[PP_WDEV_FUNCS_ENTRIES];
static uint32_t s_net80211_funcs_save[NET80211_FUNCS_MAX_ENTRIES];
static uint32_t s_phyFuns_save[PHY_FUNCS_TABLE_WORDS];
#endif
extern void *g_phyFuns;

/* ppCheckTxConnTrafficIdle is called only by PM timer callbacks (pm_dream,
Expand Down Expand Up @@ -213,9 +204,11 @@ void espradio_restore_rom_ptrs(void) {
if ((uint32_t)(uintptr_t)g_osi_funcs_p != s_saved_g_osi_funcs_p)
g_osi_funcs_p = (wifi_osi_funcs_t *)(uintptr_t)s_saved_g_osi_funcs_p;
/* esp_phy_enable resets g_phyFuns to the fixed DRAM address on every call.
* Redirect it back to our static copy. */
* Redirect it back to our static copy (C3/S3 only). */
#if !CONFIG_IDF_TARGET_ESP32
if (g_phyFuns != s_phyFuns_save && s_phyFuns_save[0] != 0)
g_phyFuns = s_phyFuns_save;
#endif
}

#define ESPRADIO_NETIF_RXRING_SIZE 6
Expand All @@ -226,7 +219,15 @@ typedef struct {
uint16_t len;
} espradio_rx_frame_t;

/* On ESP32, place the RX ring in the dedicated DRAM1 region (SRAM1 pool 7/6)
* to free ~9.6 KB of SRAM2 for the Go GC heap. The linker script's .rxring
* section sits before the arena in DRAM1. On other targets the ring stays in
* normal .bss. */
#if CONFIG_IDF_TARGET_ESP32
static espradio_rx_frame_t s_rx_ring[ESPRADIO_NETIF_RXRING_SIZE] __attribute__((section(".rxring")));
#else
static espradio_rx_frame_t s_rx_ring[ESPRADIO_NETIF_RXRING_SIZE];
#endif
static volatile uint32_t s_rx_head;
static volatile uint32_t s_rx_tail;
static volatile uint32_t s_rx_cb_count;
Expand Down
11 changes: 6 additions & 5 deletions netlink/ap.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,12 @@ func (n *Esplink) NetConnectAP(params APConnectParams) error {
udpPorts = 1 // reserve one slot for the DHCP server
}
espstack, err := espradio.NewStack(nd, espradio.StackConfig{
Hostname: params.Hostname,
StaticAddress: params.StaticAddr,
MaxUDPPorts: udpPorts,
MaxTCPPorts: params.MaxTCPPorts,
PassivePeers: params.PassivePeers,
Hostname: params.Hostname,
StaticAddress: params.StaticAddr,
MaxUDPPorts: udpPorts,
MaxTCPPorts: params.MaxTCPPorts,
PassivePeers: params.PassivePeers,
AcceptBroadcast4: true,
})
if err != nil {
if debug {
Expand Down
9 changes: 8 additions & 1 deletion osi.c
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,13 @@ static int espradio_read_mac(uint8_t* mac, unsigned int type) {
return rc;
}

/* On ESP32, place WiFi-only tables in DRAM1 (.wifibss) to free SRAM2. */
#if CONFIG_IDF_TARGET_ESP32
#define WIFIBSS __attribute__((section(".wifibss")))
#else
#define WIFIBSS
#endif

#define TIMER_SLOTS 32
static struct {
void *ptimer;
Expand All @@ -790,7 +797,7 @@ static struct {
bool pending_setfn;
uint64_t interval_us;
uint64_t deadline_us;
} timer_slots[TIMER_SLOTS];
} timer_slots[TIMER_SLOTS] WIFIBSS;
static unsigned timer_slots_used;

void espradio_timer_fire(void *ptimer);
Expand Down
2 changes: 1 addition & 1 deletion pcap_debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ var _ = pcap.Configure(machine.Serial, xnet.CapturePrinterConfig{
})

func printPacket(msg string, frame []byte) {
pcap.PrintPacket(msg, frame)
pcap.PrintEthernet(msg, frame)
}
Loading