Second thread causing first thread to function incorrectly even if it's not running yet

Discussions and support about ChibiOS/RT, the free embedded RTOS.
Post Reply
jcbless
Posts: 43
Joined: Wed Apr 16, 2025 2:29 pm
Has thanked: 7 times
Been thanked: 3 times

Second thread causing first thread to function incorrectly even if it's not running yet

Post by jcbless »

I've got two threads. If I start the first thread (temp_thread_1), but I don't start the second thread (Thread1), then temp_thread_1 functions correctly (it does some SPI communications and displays temperatures of components on the board). However, if I start the temp_thread_1, wait 10 seconds, and then start the Thread1, the first thread apparently reads all 0's on SPI and therefore displays default temperatures (even within the 10 seconds prior to the second thread starting). This even happens when the second thread is doing virtually nothing.

Here's some simplified code in the case that works:

Code: Select all

static THD_WORKING_AREA(temp_thread_1_wa, 10000);
static THD_FUNCTION(temp_thread_1, p) {
    (void) p;
    chRegSetThreadName("Temp thread 1");
    // Do some SPI communication
    // Do some I2C communication (will apparently work correctly)
    while (1) {
        // Get temperatures from SPI and I2C and Print data
        chThdSleepMilliseconds(1000);
    }
}

// Working area definition for Thread1
static THD_WORKING_AREA(waThread1, 10000);

// Definition of Thread1 thread
static THD_FUNCTION(Thread1, arg) {

    (void)arg;  
    chRegSetThreadName("speed_set");

    float sv;
    while (true) {
        sv = setVal;  // This one assignment occurs in the stripped out version of this thread function
        chThdSleepMilliseconds(1000);
    }
}

/*
 * Application entry point.
 */
int main(void) {


    /*
   * System initializations.
   * - HAL initialization, this also initializes the configured device drivers
   *   and performs the board-specific initializations.
   * - Kernel initialization, the main() function becomes a thread and the
   *   RTOS is active.
   */
    halInit();
    chSysInit();
    
    // Do some initialization
    
    chThdSleepMilliseconds(1000);
    
    /*
   * Creates ICM thread
   */
    chThdCreateStatic(temp_thread_1_wa, sizeof(temp_thread_1_wa), NORMALPRIO + 2, temp_thread_1, NULL);

    chThdSleepMilliseconds(1000);
    
    chThdSleepMilliseconds(10000);  // Note that I provide a really long delay here

    // In this working case, the second thread is commented out:
    //chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 1, Thread1,
    //                  NULL);
    
    while (1) {
        setVal = 250.0f;
        chThdSleepMilliseconds(500);
        setVal = 125.0f;
        chThdSleepMilliseconds(500);
    }
}


And this is the code that does not work correctly:

Code: Select all

static THD_WORKING_AREA(temp_thread_1_wa, 10000);
static THD_FUNCTION(temp_thread_1, p) {
    (void) p;
    chRegSetThreadName("Temp thread 1");
    // Do some SPI communication
    // Do some I2C communication (will apparently work correctly)
    while (1) {
        // Get temperatures from SPI and I2C and Print data
        chThdSleepMilliseconds(1000);
    }
}

// Working area definition for Thread1
static THD_WORKING_AREA(waThread1, 10000);

// Definition of Thread1 thread
static THD_FUNCTION(Thread1, arg) {

    (void)arg;  
    chRegSetThreadName("speed_set");

    float sv;
    while (true) {
        sv = setVal;  // This one assignment occurs in the stripped out version of this thread function
        chThdSleepMilliseconds(1000);
    }
}

/*
 * Application entry point.
 */
int main(void) {


    /*
   * System initializations.
   * - HAL initialization, this also initializes the configured device drivers
   *   and performs the board-specific initializations.
   * - Kernel initialization, the main() function becomes a thread and the
   *   RTOS is active.
   */
    halInit();
    chSysInit();
    
    // Do some initialization
    
    chThdSleepMilliseconds(1000);
    
    /*
   * Creates ICM thread
   */
    chThdCreateStatic(temp_thread_1_wa, sizeof(temp_thread_1_wa), NORMALPRIO + 2, temp_thread_1, NULL);

    chThdSleepMilliseconds(1000);
    
    chThdSleepMilliseconds(10000);  // Note that I provide a really long delay here and even during this time period, the first thread does not properly do SPI communication

    // In this broken case, the second thread starts 11 seconds after the first thread
    chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 1, Thread1,
                      NULL);
    
    while (1) {
        setVal = 250.0f;
        chThdSleepMilliseconds(500);
        setVal = 125.0f;
        chThdSleepMilliseconds(500);
    }
}


Do you have any idea why adding the chThdCreateStatic() for the second thread breaks the first thread even though that second thread starts well after the first?

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

Re: Second thread causing first thread to function incorrectly even if it's not running yet

Post by Giovanni »

Is FPU enabled in makefile? Most likely the problem is where you are not looking. Is the result the same without using floats?

Giovanni
jcbless
Posts: 43
Joined: Wed Apr 16, 2025 2:29 pm
Has thanked: 7 times
Been thanked: 3 times

Re: Second thread causing first thread to function incorrectly even if it's not running yet

Post by jcbless »

The FPU is enabled in the Makefile. I have tried removing all of the floats and disabling the float support as well to no avail.
jcbless
Posts: 43
Joined: Wed Apr 16, 2025 2:29 pm
Has thanked: 7 times
Been thanked: 3 times

Re: Second thread causing first thread to function incorrectly even if it's not running yet

Post by jcbless »

I went back to my code that matches up to the code snippets above. I changed the stack size on the Thread1 from 10000 to 1000. That allowed both threads to work correctly. Why might dropping the stack size on that thread be helpful? I would expect larger stack sizes (up to a rather large value) to be better.
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Second thread causing first thread to function incorrectly even if it's not running yet

Post by Giovanni »

Changing stack size moves other variables in RAM, depending on which platform you are using this could make a difference.

Giovanni
jcbless
Posts: 43
Joined: Wed Apr 16, 2025 2:29 pm
Has thanked: 7 times
Been thanked: 3 times

Re: Second thread causing first thread to function incorrectly even if it's not running yet

Post by jcbless »

Is there any way to somehow make the behavior predictable? Perhaps is there a simple way to check where everything gets assigned to be in RAM such as a table showing that information? I want to avoid a situation where there's unpredictable behavior which might only show up in corner cases for example. - Thanks
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Second thread causing first thread to function incorrectly even if it's not running yet

Post by Giovanni »

Hi,

It is the .map file, static allocation is all there. Allocation does not make it unpredictable, only corrupting data can have that effect. It could be a stack overflow or some other kind of memory violation, NULL pointers, arrays etc.

Make sure to enable debug options in chconf.h especially assertions and state checker.

Giovanni
Post Reply