Skip to content

FreeRTOS layer selects interrupt primitives by compiler rather than by target, breaking hosted GCC builds #586

Description

@fdesbiens

utility/rtos_compatibility_layers/FreeRTOS/FreeRTOS.h chooses the interrupt primitives by compiler rather than by target:

#ifndef portDISABLE_INTERRUPTS
#if defined(__IAR_SYSTEMS_ICC__)
#define portDISABLE_INTERRUPTS() __disable_interrupt()
#elif defined(__GNUC__ )
#define portDISABLE_INTERRUPTS() __disable_interrupts()
#elif defined(__ARMCC_VERSION)
#define portDISABLE_INTERRUPTS() __disable_irq()
#else
UINT _tx_thread_interrupt_disable(VOID);
#define portDISABLE_INTERRUPTS() _tx_thread_interrupt_disable()
#endif
#endif

portENABLE_INTERRUPTS is structured the same way.

__disable_interrupts() is a bare metal intrinsic. GCC hosted on Linux does not provide it, so any GCC build that is not for a bare metal target selects a symbol that does not exist. The failure is at link time, in vPortEnterCritical() and vPortExitCritical():

undefined reference to `__disable_interrupts'
undefined reference to `__enable_interrupts'

The #else branch already carries a portable fallback built on the ThreadX primitives, _tx_thread_interrupt_disable() and _tx_thread_interrupt_restore(), which would work here. It is simply unreachable for any GNU build.

Impact

The compatibility layer cannot be built with GCC for a hosted target without the application defining both macros itself. That includes the Linux port, which is what the regression suites use, so it is the first thing anyone hits when testing the layer on a host.

Workaround in place

The suite added in #583 defines both macros in its own FreeRTOSConfig.h, pointing them at the ThreadX primitives from the header's own #else branch. Both macros are #ifndef guarded, so a configuration file can pre-empt the choice. That is a fixture level workaround, not a fix.

Suggested fix

Gate the compiler branches on the target as well, so that a GNU build only selects __disable_interrupts() when the target actually provides it, and otherwise falls through to the ThreadX based branch. The ThreadX fallback is correct everywhere ThreadX runs, so it is a reasonable default with the intrinsics as the special case rather than the other way round.

Notes

Found while building the regression suite in #583.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions