This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.


    Hello Everyone,

    I'm having a strange issue with a new implementation with embOS 4.26, STM32L4 uc and GCC 8.0-2019q3. The problem is with the OS_TICK_Handle function that is causing OS_ERR_ILLEGAL_OUT ISR error as soon as it is called. SysTick_Handler function is directly called from the isr vector and is the hardware systick timer.

    Source Code

    1. //! Handler for SystemTick interrupt.
    2. /*!
    3. * This is the code that gets called when the processor receives a
    4. * _SysTick exception. SysTick is used as OS timer tick.
    5. */
    6. void SysTick_Handler(void) {
    7. OS_EnterNestableInterrupt();
    8. OS_TICK_Handle();
    9. #if OS_USE_JLINKMEM
    10. JLINKMEM_Process();
    11. #endif
    12. OS_LeaveNestableInterrupt();
    13. }
    Display All
    The same code above is working fine in other projects.

    The workaround I found is to call the SysTick_Handler function from "OS_CallNestableISR" and now I'm wondering how it could have worked in the previous projects and why my usual implementation is not working.

  • Hello,

    While we're not aware of any issues regarding OS_TICK_Handle(), we'd of course like to help you in finding the cause for the observed behavior.

    Generally speaking, OS_ERR_ILLEGAL_OUT_ISR is indicated whenever embOS assumes that an API function that may only be called from an ISR was called from a context that is not an ISR.
    This is done by checking the variable OS_Global.InInt, which should have been incremented before by calling either OS_EnterNestableInterrupt() or OS_EnterInterrupt().
    This, in return, would indicate that your code does not actually call either of these functions, though the code snippet provided above does clearly show a call to OS_EnterNestableInterrupt(). Alternatively, OS_Global.InInt may also have been corrupted by the application, which could then result in the exact same behavior. Hence, could you please check if the code gets in fact executed and OS_Global.InInt gets incremented from 0 to 1?

    Calling OS_CallNestableISR() - while it seems to solve the problem - unfortunately is not a proper solution. That function is mandatory to use for certain architectures, but Cortex-M is none of these architectures. Since the function merely calls OS_EnterNestableInterrupt() and then executes the given ISR routine, the sudden change in behavior would once more indicate that OS_EnterNestableInterrupt() was not called explicitly.

    By the way: Since you're working with embOS 4.26, you may also want to have a look at segger.com/products/rtos/embos…tex-m/embos-cortex-m-gcc/ , for more recent versions of embOS for Cortex-M and GCC do provide several start projects for STM32L4 devices that could serve as a starting point for your own project. Also, please have a look into the release notes on that page, too: Recent versions contain various new features and improvements that could be of interest to you as well, hence you might want to consider updating embOS to one of these versions.

    Please let me know if I can be of any further help.

    Best regards,
  • Dear Martin,

    thanks for your reply. I've checked the OS_Global struct and realize that this struct was not aligned between our library that contains the embos and the application that uses such library.

    More in detail we were using SYMBOLS+=-DOS_PROFILE=0 in the library while SYMBOLS+=-DOS_LIBMODE_DP in the application. The structure below was then not consistent in the whole project and causes the error.

    C Source Code

    1. struct OS_GLOBAL_STRUCT {
    2. OS_COUNTERS Counters;
    3. OS_PENDING Pending;
    4. OS_TASK * pCurrentTask; // Pointer to current Task
    5. #if (OS_SUPPORT_INT_PRIORITY != 0)
    6. OS_IPL_DI_TYPE Ipl_DI;
    7. OS_IPL_EI_TYPE Ipl_EI;
    8. #endif
    9. OS_TASK * pTask; // Linked list of all Tasks
    10. OS_TASK volatile * volatile pActiveTask;
    11. #if (OS_SUPPORT_TIMER != 0)
    12. OS_TIMER * pTimer; // Linked list of all active Timers
    13. OS_TIMER * pCurrentTimer; // Actual expired timer which called callback
    14. OS_TIMER_HANDLER* pfCheckTimer; // Timer handler function, set when OS_StartTimer() is called
    15. #endif // OS_SUPPORT_TIMER
    16. volatile OS_I32 Time;
    17. OS_TIME TimeDex;
    18. #ifdef OS_U64
    19. OS_U64 TickCnt;
    20. #endif
    21. #if (OS_RR_SUPPORTED != 0)
    22. OS_U8 TimeSlice;
    23. OS_U8 TimeSliceAtStart;
    24. #endif
    25. #if (OS_SUPPORT_TICKLESS != 0)
    26. OS_TIME TicklessFactor;
    27. OS_BOOL TicklessExpired;
    28. voidRoutine *pfEndTicklessMode;
    29. #endif
    30. #if (OS_PROFILE != 0)
    31. const OS_TRACE_API* pTrace;
    32. OS_U8 ProfilingOn;
    33. #endif
    34. #if ((OS_DEBUG != 0) || (OS_TRACE != 0))
    35. OS_U8 InInt; // Used in Debug builds of embOS only
    36. #endif
    37. #if OS_SUPPORT_MPU
    38. OS_MPU_MEM_CONFIG MemConfig; // RAM/ROM memory settings
    39. #if (OS_DEBUG != 0)
    40. OS_MPU_DEBUG MPUDebug;
    41. #endif
    42. #endif
    43. };
    Display All
    Thanks a lot for your support.