Skip to content

Commit 946f973

Browse files
Fix polling and IRQ memory corruption
The IRQ callback routine ended up passing in a stack variable address. For main app code this is legal because the app blocks until the LWIP call returns. But for IRQs, it returns immediately (can't block in IRQ) and the stack pointer we passed in will be corrupt. Use a dumb static (heap) variable for now. W5100 is now running with multiple AdvancedWebServer clients in parallel with a WiFiClient MOTD process on core 1, in parallel. Rewriting the CYW43 driver to work with this TBD.
1 parent 0b14547 commit 946f973

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

cores/rp2040/freertos/FreeRTOSConfig.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,14 @@
9696
#define configGENERATE_RUN_TIME_STATS 1
9797
#endif
9898
#ifdef configGENERATE_RUN_TIME_STATS
99+
#ifdef __cplusplus
100+
extern "C" {
101+
#endif
99102
extern void vMainConfigureTimerForRunTimeStats(void);
100103
extern unsigned long ulMainGetRunTimeCounterValue(void);
104+
#ifdef __cplusplus
105+
};
106+
#endif
101107
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() //vMainConfigureTimerForRunTimeStats()
102108
#define portGET_RUN_TIME_COUNTER_VALUE() ulMainGetRunTimeCounterValue()
103109
#endif

cores/rp2040/lwip_wrap.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,19 @@ extern "C" {
832832
#ifdef __FREERTOS
833833
if (fromISR) {
834834
// In ISR we can't check what the current thread is
835-
__callback_req req = { cb, cbData };
835+
static __callback_req req = { cb, cbData }; // TODO HACK HERE
836+
// We pass in the address of an unknown sized request to the LWIP work queue
837+
// For normal mode that address is on the app stack, which will be frozen until
838+
// the callback is performed. So no problem, that stack address will remain valid.
839+
// Here, we're in an ISR and won't block, just put a pointer on the queue and
840+
// return from the interrupt. The stack address, there, is no longer safe and you
841+
// will see memory corruption when the actual app thread uses its stack.
842+
// We can't allocate memory in an IRQ in FreeRTOS, so for now we'll just have
843+
// a single heap-based (static) request which will live forever. As long as
844+
// only a single lwip_callback from IRQ is present we're OK. Should you have 2
845+
// IRQ driver network cards, this will fail.
846+
// A more satisfying method might have the NIC driver pass in its own class local
847+
// preallocated storage space which we can use.
836848
__lwip(__callback, &req, fromISR);
837849
return;
838850
} else if (!__isLWIPThread()) {

libraries/lwIP_Ethernet/src/LwipEthernet.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,13 @@ static TaskHandle_t _ethernetTask;;
235235

236236
static void stage2(void *cbData) {
237237
(void) cbData;
238+
ethernet_arch_lwip_gpio_mask();
238239
// Scan the installed Ethernet drivers
239240
for (auto handlePacket : _handlePacketList) {
240241
// Note that each NIC needs to use its own mutex to ensure LWIP isn't doing something with it at the time we want to poll
241-
// handlePacket.second();
242+
handlePacket.second();
242243
}
244+
ethernet_arch_lwip_gpio_unmask();
243245
// Do LWIP stuff as needed
244246
sys_check_timeouts();
245247
}

0 commit comments

Comments
 (0)