IDLE_LOOP_HOOK idea

This forum is dedicated to feedback, discussions about ongoing or future developments, ideas and suggestions regarding the ChibiOS projects are welcome. This forum is NOT for support.
Post Reply
likewise
Posts: 18
Joined: Tue Jun 14, 2011 3:43 pm

IDLE_LOOP_HOOK idea

Post by likewise »

Hello all,

currently the IDLE_LOOP_HOOK is a function run by the idle thread.

However, it would be very interesting to have two other hooks:

1) IDLE_ENTRY_HOOK or IDLE_SCHEDULE_HOOK or ...
2) IDLE_EXIT_HOOK or IDLE_PREEMPT_HOOK or ...

that are called once when the idle thread is scheduled in, and when it's scheduled out.

This should be done in such a way that when the idle thread brings the processor in deep sleep, the exit hook is called when it comes out.

I have this on the end of my to-do list so if someone can steal this idea and implement it I buy you a beer next time I see you :)

Regards,

Leon.
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: IDLE_LOOP_HOOK idea

Post by Giovanni »

Hi,

It is an easy change, I would add a context switch hook that would be invoked when the system performs a switch, it would receive pointers to both threads involved so it would be easy to catch the transitions to and from the idle thread (or any other thread),
Performance would receive a hit however, that is a very hot code path.

Giovanni
likewise
Posts: 18
Joined: Tue Jun 14, 2011 3:43 pm

Re: IDLE_LOOP_HOOK idea

Post by likewise »

I add this to chconf.h:

/**
* @brief Switch hook.
* @details This hook is invoked just before thread switching occurs.
*/
#if !defined(THREAD_SWITCH_HOOK) || defined(__DOXYGEN__)
#define THREAD_SWITCH_HOOK(ntp, otp) { \
/* switch hook code here.*/ \
if (ntp == (Thread *)_idle_thread_wa) \
GPIOD->BRR = 0x00000004UL; \
else if (otp == (Thread *)_idle_thread_wa) \
GPIOD->BSRR = 0x00000004UL; \
}
#endif

and I added the macro to port_switch(Thread *ntp, Thread *otp):
...
THREAD_SWITCH_HOOK(ntp, otp);

PUSH_CONTEXT();
...

This gives me a nice "idle" LED on PD2 of STM32F107. It's a bit of a hack, because I use the assumption that the idle Thread pointer points to the idle thread work area (because this is how ChibiOS/RT sets it up).

One question; will _port_switch_from_isr(void) call into port_switch() later?
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: IDLE_LOOP_HOOK idea

Post by Giovanni »

Hi,

_port_switch_from_isr(void) calls the port_switch() by invoking chSchDoRescheduleI().

Your implementation is correct, I would just put the hook just before invoking port_switch() not inside port_switch() because it is a naked function and putting code there could have unexpected results.

I would rename it _port_switch() and then define a macro in chcore_v7m.h port_switch() that first invokes the hook and then calls _port_switch(). The IAR and Keil ports already do that, I think the GCC port will be updated this way too.

Giovanni
likewise
Posts: 18
Joined: Tue Jun 14, 2011 3:43 pm

Re: IDLE_LOOP_HOOK idea

Post by likewise »

Hello Giovanni,

thanks for mentioning the IAR/KEIL ports as a reference. Is there a preference to keep the stack check in the port_switch macro (.h) or in the _port_switch() in .c?

In the macro I have trouble figuring out how to use #if #endif inside the definition of a macro, so I ended up with this...

#if defined(__DOXYGEN__)
#define port_switch(ntp, otp) _port_switch(ntp, otp)
#else
#if defined(CH_DBG_ENABLE_STACK_CHECK)
#define port_switch(ntp, otp) { \
/* Stack overflow check, if enabled.*/ \
register struct intctx *r13 asm ("r13"); \
if ((void *)(r13 - 1) < (void *)(otp + 1)) \
chDbgPanic("stack overflow"); \
THREAD_SWITCH_HOOK(ntp, otp); \
_port_switch(ntp, otp); \
}
#else /* CH_DBG_ENABLE_STACK_CHECK */
#define port_switch(ntp, otp) { \
THREAD_SWITCH_HOOK(ntp, otp); \
_port_switch(ntp, otp); \
}
#endif /* CH_DBG_ENABLE_STACK_CHECK */
#endif
likewise
Posts: 18
Joined: Tue Jun 14, 2011 3:43 pm

Re: IDLE_LOOP_HOOK idea

Post by likewise »

I think now that the "stack overflow" message is there, the stack check should be in the C _port_switch(), to prevent that string from re-appearing in different object files and functions through the macro, taking up extra memory.

The port_switch() macro is used 3 times in the chsch.c file.

Regards,

Leon.
likewise
Posts: 18
Joined: Tue Jun 14, 2011 3:43 pm

Re: IDLE_LOOP_HOOK idea

Post by likewise »

I ended up with this, as indeed the string appeared a few times in the .text section. This is for chcore_v7m.h|c:

.h:

#if defined(__DOXYGEN__)
#define port_switch(ntp, otp) _port_switch(ntp, otp)
#else
#define port_switch(ntp, otp) { \
THREAD_SWITCH_HOOK(ntp, otp); \
_port_switch(ntp, otp); \
}
#endif

.c

#if !defined(__DOXYGEN__)
__attribute__((naked))
#endif
void _port_switch(Thread *ntp, Thread *otp) {
#if CH_DBG_ENABLE_STACK_CHECK
/* Stack overflow check, if enabled.*/
register struct intctx *r13 asm ("r13");
if ((void *)(r13 - 1) < (void *)(otp + 1))
chDbgPanic("stack overflow");
#endif /* CH_DBG_ENABLE_STACK_CHECK */

my chconf.c:

#if !defined(THREAD_SWITCH_HOOK) || defined(__DOXYGEN__)
#define THREAD_SWITCH_HOOK(ntp, otp) thread_switch_hook(ntp, otp)
#endif
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: IDLE_LOOP_HOOK idea

Post by Giovanni »

It looks OK but ultimately I wish to pull the stack checking from there like I explained in the other thread.

Giovanni
Post Reply