To help others who may find this thread, i post my solution here. This problem is not new, and there had been other suggestions going back several years that one can find with web search. My post is specific to the Vitis 2023.2 install as that’s what i’m working with. I have no idea what had come before.
vTaskStartScheduler() installs the tick timer interrupt handler. It winds its way through the call stack and eventually calls xscugic.c, XScuGic_CfgInitialize() with its own XScuGic instance.
lwip_init() has nothing to do with ethernet interrupts which is handled by xemac_add(). xemac_add() winds its way through the call stack and eventually calls XScuGic_CfgInitialize() with its own XScuGic instance.
XScuGic_CfgInitialize() has buitin guard to prevent doing inititialization more than once with the same XScuGic instance. But since it is called with two separate XScuGic instances it does initialization twice. The second time clobbers the first time thus wiping the tick timer handler.
To minimize side effects, I add but a few changes to XScuGic_CfgInitialize(). Here are my changes:
- Add a guard to prevent certain actions from being done more than once.
- Put the guard around the for loop.
- Put the guard around the call to XScuGic_Stop().
s32 XScuGic_CfgInitialize(XScuGic *InstancePtr,
XScuGic_Config *ConfigPtr,
u32 EffectiveAddr)
{
…
static int32_t XScuGic_CfgInitialize_Done = 0;
…
if (InstancePtr->IsReady != XIL_COMPONENT_IS_READY) {
…
if (!XScuGic_CfgInitialize_Done) {
for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS;
Int_Id++) {
…
}
}
…
if (!XScuGic_CfgInitialize_Done) {
XScuGic_Stop(InstancePtr);
}
…
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
XScuGic_CfgInitialize_Done = 1;
}
return XST_SUCCESS;
}
After these code changes, my test shows that ethernet is functional, and task(s) that call vTaskDelay() wake up as expected.