-
Notifications
You must be signed in to change notification settings - Fork 72
Description
EDIT: I changed the issue's name to more appropriately track the purpose of this thread after relevant information has been uncovered surrounding the original problem.
I have been trying to determine the appropriate uVisor ACL such that I can use the Ethernet hardware on the FRDM K64F development board. After a few hours of debugging and tracing the problem I managed to determine two points of failure when using EthernetInterface.cpp and (a dependency thereof) the LWIP implementation; the root of the corresponding source tree can be found here.
The first problem I found was that the LWIP implementation was trying to disable the MPU, which I thought might be problematic for uVisor.
MPU->CESR &= ~MPU_CESR_VLD_MASK;
I have defined the MPU as an enabled memory range in my ACL, but that does not prevent the system from stopping on that instruction.
const UvisorBoxAclItem g_main_acl[] = {
{SIM, sizeof(*SIM), UVISOR_TACLDEF_PERIPH},
{OSC, sizeof(*OSC), UVISOR_TACLDEF_PERIPH},
{MCG, sizeof(*MCG), UVISOR_TACLDEF_PERIPH},
{PORTA, sizeof(*PORTA), UVISOR_TACLDEF_PERIPH},
{PORTB, sizeof(*PORTB), UVISOR_TACLDEF_PERIPH},
{PORTC, sizeof(*PORTC), UVISOR_TACLDEF_PERIPH},
{PORTD, sizeof(*PORTD), UVISOR_TACLDEF_PERIPH},
{PORTE, sizeof(*PORTE), UVISOR_TACLDEF_PERIPH},
{RTC, sizeof(*RTC), UVISOR_TACLDEF_PERIPH},
{LPTMR0, sizeof(*LPTMR0), UVISOR_TACLDEF_PERIPH},
{PIT, sizeof(*PIT), UVISOR_TACLDEF_PERIPH},
{SMC, sizeof(*SMC), UVISOR_TACLDEF_PERIPH},
{UART0, sizeof(*UART0), UVISOR_TACLDEF_PERIPH},
{I2C0, sizeof(*I2C0), UVISOR_TACLDEF_PERIPH},
{SPI0, sizeof(*SPI0), UVISOR_TACLDEF_PERIPH},
{MPU, sizeof(*MPU), UVISOR_TACLDEF_PERIPH},
/* EthernetInterface */
{ENET, sizeof(*ENET), UVISOR_TACLDEF_PERIPH},
{EWM, sizeof(*EWM), UVISOR_TACLDEF_PERIPH},
};
The second problem was related to a call to EnableIRQ in fsl_enet.c. At the highest level, a call to EthernetInterface.connect() will lead to execution of the following.
/* Enables Ethernet interrupt and NVIC. */
ENET_EnableInterrupts(base, config->interrupt);
if (config->interrupt & (kENET_RxByteInterrupt | kENET_RxFrameInterrupt))
{
EnableIRQ(s_enetRxIrqId[instance]);
}
if (config->interrupt & (kENET_TxByteInterrupt | kENET_TxFrameInterrupt))
{
EnableIRQ(s_enetTxIrqId[instance]);
}
if (config->interrupt & (kENET_BabrInterrupt | kENET_BabtInterrupt | kENET_GraceStopInterrupt | kENET_MiiInterrupt |
kENET_EBusERInterrupt | kENET_LateCollisionInterrupt | kENET_RetryLimitInterrupt |
kENET_UnderrunInterrupt | kENET_PayloadRxInterrupt | kENET_WakeupInterrupt))
{
EnableIRQ(s_enetErrIrqId[instance]);
}
As it turns out, EnableIRQ() is an inline function defined in fsl_common.h as a link to an NVIC_EnableIRQ call:
static inline void EnableIRQ(IRQn_Type interrupt)
{
#if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && (FSL_FEATURE_SOC_INTMUX_COUNT > 0)
if (interrupt < FSL_FEATURE_INTMUX_IRQ_START_INDEX)
#endif
{
NVIC_EnableIRQ(interrupt);
}
}
I could not trace the NVIC definition down any further as there were a very large number of them. However, I did check out the generated source code in a disassembler and it seems that NVIC_EnableIRQ is being translated to an SVC 3 call.
Are there a special configuration required for this? Does the default SVC_Handler function not handled this case for enabling interrupts? The behavior I am observing is that a call to this function never returns, so I can only guess (since I do not have a debugger) that the uVisor is trapping on this call.
As a side note, I tried using UVISOR_PERMISSIVE for my main ACL, but the problem still persists.
Are there any obvious problems with using NVIC_EnableIRQ or writing to the MPU? Are there additional configuration requirements to support either?
If I comment out the offending MPU and NVIC_EnableIRQ lines then everything executes without issue -- except the Ethernet hardware does not work, of course.