Page 1 of 1

A problem of chSchGoSleepS()

Posted: Tue Jan 07, 2014 6:57 am
by rocky
Hi,

I'm using STM32F4 Discovery, ChibiOS 2.6.1, all compile-time debugging options are enabled. An external interrupt is used to notify some data is ready. I have one thread waiting, and use the interrupt ISR to wakeup the thread. I use EXT driver for the external interrupt. Following is the code:

Code: Select all

static int pending = 0;
static Thread *waiter = NULL;

static void ext_callback(EXTDriver *extp, expchannel_t channel)
{
    chSysLockFromIsr();
    pending++;
    if (waiter != NULL) {
        Thread *th = waiter;
        th->p_u.rdymsg = RDY_OK;
        waiter = NULL;
        chSchReadyI(th);
    }
    chSysUnlockFromIsr();
}

static msg_t waiter_thread(void *p)
{
    while (1) {
        chSysLock();
        if (pending == 0) {
            waiter = chThdSelf();
            chSchGoSleepS(THD_STATE_SUSPENDED);
        }
        pending = 0;
        chSysUnlock();

        fetch_data();
    }
}


Here is my problem. Once waiter_thread call into chSchGoSleepS(), it never come back. And in debugger if I set breakpoint in ext_callback(), it never get triggered. It look as if the external interrupt was always disabled after calling chSchGoSleepS().

However, if I replace chSchGoSleepS() with chSchGoSleepTimeoutS(), external interrupt is working. But the waiter_thread always wakeup by time-out not by ISR. And debugger shows ext_callback() never has chance to call chSchReadyI() (because waiter == NULL all the time). Again it looks like the interrupt was disabled before the chSchGoSleepTimeoutS() returns.

I'm wondering what went wrong? I wrote this code according to how SPI implementation in ChibiOS. What am I missing? Thanks a lot!

Re: A problem of chSchGoSleepS()

Posted: Tue Jan 07, 2014 9:34 am
by Giovanni
Hi,

Does the program stop in an halt or it continues to run? if it is halted please verify the string pointed by dbg_panic_msg.

Giovanni

Re: A problem of chSchGoSleepS()

Posted: Tue Jan 07, 2014 5:52 pm
by rocky
Thanks for looking at it, Giovanni.

The program continue running, because I have another test thread which just flash LEDs in order and print messages to serial console regularly, it runs fine while the waiter thread trapped in chSchGoSleepS().

The threads are creates in standard way as following, I hope that's correct:

Code: Select all

static WORKING_AREA(waiter_thread_wa, 512);
...
chThdCreateStatic(waiter_thread_wa, sizeof(waiter_thread_wa), HIGHPRIO, waiter_thread, NULL);


Do you have other suggestions on how to diagnose this? Thanks.

BTW my understanding about locking in ChibiOS: chSysLock() disables regular interrupts, any context switch must be happened inside of chSysLock(), so one thread goes to sleep, and scheduled thread wakes up and first thing to do is chSysUnlock() to enable regular interrupts. Is that correct?

Re: A problem of chSchGoSleepS()

Posted: Tue Jan 07, 2014 6:56 pm
by Giovanni
Hi,

Yes correct, the sequence is always lock-switch-unlock, interrupts never stay disabled.

In you case are you sure that the thread goes to sleep before the callback is called?

Also, could you try to use a semaphore instead? Initialize the semaphore to zero (chSemInit), reset it to zero from the callback (chSemResetI) and wait on it from the thread (chSemWait), this is usually safer and allows you to have multiple threads waiting.

Giovanni

Re: A problem of chSchGoSleepS()

Posted: Wed Jan 08, 2014 7:53 am
by rocky
Hi Giovanni, now it's more clear that the problem is somewhere in the custom FPGA I'm using to generate external interrupt. It has nothing to do with ChibiOS. I'm very sorry I wasted your time. But I still learn a lot from the conversation with you, thanks again!