LPC546xx: lwip bare-metal (NO_SYS=1) and disabling interrupts

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

LPC546xx: lwip bare-metal (NO_SYS=1) and disabling interrupts

2,734件の閲覧回数
giusloq
Contributor III

If I understood well, ethernet driver is interrupt driven, so some critical lwip functions are called from interrupt context. This must be done with great care, because is not generally safe.

Indeed SDK code set LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT and defines sys_arch_protect() as:

sys_prot_t sys_arch_protect(void)
{
  sys_prot_t result;
  result = (sys_prot_t)DisableGlobalIRQ();
  return result;
}

In the end, interrupts are disabled frequently, mainly every time a dynamic allocation is needed, from the heap or from a memory pool.

Is there a way to avoid disabling interrupts so frequently?

 

ラベル(2)
0 件の賞賛
返信
3 返答(返信)

2,716件の閲覧回数
giusloq
Contributor III

I'm looking at the lwip porting function (sys_arch.c) for NO_SYS=0 too (FreeRTOS), starting from lpcxpresso54628_lwip_mqtt_freertos SDK example.

Here I found SYS_LIGHTWEIGHT_PROT=1, SYS_ARCH_PROTECT macro calls sys_arch_protect function that is implemented as:

sys_prot_t sys_arch_protect(void)
{
    sys_prot_t result = 0;

#ifdef __CA7_REV
    if (SystemGetIRQNestingLevel())
#else
    if (__get_IPSR())
#endif
    {
        result = portSET_INTERRUPT_MASK_FROM_ISR();
    }
    else
    {
        portENTER_CRITICAL();
    }
    return result;
}

What does it do? __get_IPSR() should returns 0 if the running context is not an interrupt, so this function seems to disable only lower priorities interrupts if an interrupt (whatever it is) is running, otherwise all the interrupts are globally disabled.

This isn't clear to me, I was expecting exactly the opposite. If an interrupt context is actually running, we can only disable all interrupts, otherwise we can disable only lower priorities interrupts.

Besides, I understood interrupts are disabled not only in bare-metal systems, but also with FreeRTOS. Why do we need to disable interrupts if we have mutexes? Does this depends from the Ethernet driver implementation that is interrupt driven and calls lwip function in ISR functions?

0 件の賞賛
返信

2,717件の閲覧回数
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

Regarding your question, for critical code execution which is not allowed to be interrupted, you have to use the LIST_ENTER_CRITICAL() /LIST_EXIT_CRITICAL() to disable/enable interrupt, I do not think there is the other way.

#define LIST_ENTER_CRITICAL() uint32_t regPrimask = DisableGlobalIRQ();
#define LIST_EXIT_CRITICAL() EnableGlobalIRQ(regPrimask);

 

Hope it can help you

BR

XiangJun Rong

0 件の賞賛
返信

2,710件の閲覧回数
giusloq
Contributor III

I'm studying NXP code examples. I don't need to add additional code.

When NO_SYS=1 (bare-metal), NXP code disables interrupts with sys_arch_protect() that calls DisableGlobalIRQ().

lwip calls sys_arch_protect() in many points, for example in mem_malloc. This means interrupts are disabled very frequently. I'd like to understand why this is necessary and if there's a solution to this, because disabling interrupts isn't a good practice.

I thought a solution could have been using FreeRTOS, but even in this case sys_arch_protect() disables interrupts. So the problem remains.

0 件の賞賛
返信