This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/MSP-EXP432P401R: Problem with I2C slave example and threads

Part Number: MSP-EXP432P401R

Tool/software: TI-RTOS

I am using the latest 1.30.00.40 SDK. I loaded the I2C master and slave examples onto two LaunchPads and with no modifications everything works fine. But as soon as I add another thread on the slave side, the i2c communication breaks.

I don't know if I am just not initializing the new thread correctly, but I basically duplicated everything from the main thread. To make it simple, all the second thread does is blink the led.

Also, why doesn't usleep() or sleep() work? Whenever I call either of those, it seems like everything just halts.

Either thread works fine by itself, just not together. I hope it's just something silly that I'm overlooking because eventually I'll need two i2c slave threads, one i2c master thread (separate busses), and some other threads all running at the same time, and if I can't even do this simple thing, I'll have a problem. I already have the i2c master thread running good in another project and eventually will need to integrate everything together. One small step at a time...

Here is my modified main_tirtos.c from the slave example, all other files are unchanged:

/*
 *  ======== main_tirtos.c ========
 */
#include <stdint.h>
#include <unistd.h>

#include <ti/drivers/GPIO.h>

/* POSIX Header files */
#include <pthread.h>

/* RTOS header files */
#include <ti/sysbios/BIOS.h>

/* Example/Board Header files */
#include "Board.h"

extern void *mainThread(void *arg0);
void *dummyThread(void *arg0);

/* Stack size in bytes */
#define THREADSTACKSIZE    1024

void *dummyThread(void *arg0)
{
    #define DELAY 1000000
    int i;

    /* Call driver init functions */
    GPIO_init();

    while (1) {
        GPIO_toggle(Board_GPIO_LED0);
        //usleep(1000000); //doesn't work, why?? Led just stays on solid
        //sleep(1); //doesn't work either, why?? Led just stays on solid
        for(i=0; i<DELAY; i++) {} //silly delay
    }
}

/*
 *  ======== main ========
 */
int main(void)
{
    pthread_t           thread, dummy_Thread;
    pthread_attr_t      pAttrs, dummy_pAttrs;
    struct sched_param  priParam, dummy_priParam;
    int                 retc;
    int                 detachState;

    /* Call driver init functions */
    Board_initGeneral();

    /* Set priority and stack size attributes */
    pthread_attr_init(&pAttrs);
    pthread_attr_init(&dummy_pAttrs);
    priParam.sched_priority = 1;
    dummy_priParam.sched_priority = 1;

    detachState = PTHREAD_CREATE_DETACHED;
    retc = pthread_attr_setdetachstate(&pAttrs, detachState);
    if (retc != 0) {
        /* pthread_attr_setdetachstate() failed */
        while (1);
    }
    retc = pthread_attr_setdetachstate(&dummy_pAttrs, detachState);
    if (retc != 0) {
        /* pthread_attr_setdetachstate() failed */
        while (1);
    }

    pthread_attr_setschedparam(&pAttrs, &priParam);
    pthread_attr_setschedparam(&dummy_pAttrs, &dummy_priParam);

    retc |= pthread_attr_setstacksize(&pAttrs, THREADSTACKSIZE);
    if (retc != 0) {
        /* pthread_attr_setstacksize() failed */
        while (1);
    }
    retc |= pthread_attr_setstacksize(&dummy_pAttrs, THREADSTACKSIZE);
    if (retc != 0) {
        /* pthread_attr_setstacksize() failed */
        while (1);
    }

    retc = pthread_create(&thread, &pAttrs, mainThread, NULL);
    if (retc != 0) {
        /* pthread_create() failed */
        while (1);
    }
    retc = pthread_create(&dummy_Thread, &dummy_pAttrs, dummyThread, NULL);
    if (retc != 0) {
        /* pthread_create() failed */
        while (1);
    }

    BIOS_start();

    return (0);
}

Thanks.

Also, in another post, I saw mention of a POSIX workshop in the SimpleLink Academy for the 1.30 SDK, but could not find it.

  • Hello,

    Excellent question!  The workshop is in TI Resource explorer, here is a link.

    At first glance, I would have suggested to make dummyThread a higher priority than mainThread and to call sleep or usleep (but if usleep, then with value less than 1,000,000).  This would let the dummyThread toggle the LED and then block with the call of sleep.  Blocking means that the thread (task) will surrender execution to other threads until it is ready to execute again.  Since it is now a higher priority than mainThread, it will take control away from the lower priority thread as soon as the timeout has finished so that it can toggle the LED and call sleep once more.

    I tried this solution.  It looked like it mostly works, however I was not able to test the I2C lines yet until tomorrow.  I did run into a situation intermitently where the code would get stuck in an unexpected location.  I am not sure why the code gets stuck here sometimes and not others, but I will defiinitely be looking into this more closely very soon.

    For now, I would suggest looking into the SimpleLink Academy and also trying to implement as I describe above and let me know if you run into any issues along the way.  Hope this helps some.

  • Hi John,

    Higher priority means higher number? Either way, the led stays solid when I use sleep() or usleep().

    mainThread priority 1, dummyThread priority 1:
    i2c does not work, but led works with 'silly loop'
    i2c works, but led stays solid with either sleep(1) or usleep(500000)

    mainThread priority 2, dummyThread priority 1:
    i2c and led works with 'silly loop'
    i2c works, but led stays solid with either sleep(1) or usleep(500000)

    mainThread priority 1, dummyThread priority 2:
    i2c does not work, but led works with 'silly loop'
    i2c works, but led stays solid with either sleep(1) or usleep(500000)

    By i2c not working, I mean that only the first instruction from the master goes through. The master never reaches the end and prints 'I2C closed!'.

    sleep() and usleep() is not working for me.

    Thanks.
  • ferdster said:
    Hi John,

    Higher priority means higher number? Correct. Either way, the led stays solid when I use sleep() or usleep().  I would be very surprised if sleep() and usleep() do not work, what revision of silicon do you have?
     
    mainThread priority 1, dummyThread priority 1: This makes sense to me...
    i2c does not work, but led works with 'silly loop'  The silly loop is non-blocking, so the other priority never has a chance to run.
    i2c works, but led stays solid with either sleep(1) or usleep(500000) Sleep is a blocking function, so dummyThread gives execution to mainThread and mainThread runs. If mainThread never blocks, dummyThread will not run again.
     
    mainThread priority 2, dummyThread priority 1:
    i2c and led works with 'silly loop'
    i2c works, but led stays solid with either sleep(1) or usleep(500000)

    mainThread priority 1, dummyThread priority 2:
    i2c does not work, but led works with 'silly loop'
    i2c works, but led stays solid with either sleep(1) or usleep(500000) This is where there might be an issue with the code example.  I need to look at the code a little more to verify, but I think it is possible that we run into some priority inversion here.  When dummyThread's sleep() expires, it should pre-empt mainThread since it is higher priority.  I have noticed places where this is not true, I need to look a little deeper into the code to learn why not.
     
    By i2c not working, I mean that only the first instruction from the master goes through. The master never reaches the end and prints 'I2C closed!'.
     OK, that is fair.  I checked that I2C sent some signals, but not that it actually finished or verified that the correct data was sent.  I will go back today and check that too.
    sleep() and usleep() is not working for me.  This is very odd, can you try commenting out the following and tell me if you get a blinking LED.  (Using the sleep() and/or usleep() function.)

    //    retc = pthread_create(&thread, &pAttrs, mainThread, NULL);
    //    if (retc != 0) {
    //        /* pthread_create() failed */
    //        while (1);
    //    }



    Thanks.

    Can you also verify your hardware setup is correct for the I2C Bus?  Using this example code, along with its counterpart "i2cslaveexample1", the SDA pins on each device should connect to each other (Master P6.4, Slave P1.6) and SCL pins to eachother (Master P6.5, Slave P1.7).  There should also be two 10K resistors, one on each of these lines, as pull-up resistors to Vcc.  Can you verify this for me on your board?

     

  • Hi John,

    I reinstalled CCSv7 and started from scratch. Now sleep() and usleep() work - I think the problem might have been with the tirtos_builds project (I previously modified it to use the RTC).

    I'm using two red LaunchPads which I assume use the latest silicon as I just purchased them two weeks ago. I programmed one as the master (i2cmasterexample1) and the other with my modified slave code (both threads with priority=1). I modified the master to loop forever and run through the i2c transactions every second. Everything worked perfectly/continuously for more than 10,000 cycles.

    I then added a second slave thread (priority=1) onto the slave launchpad using USCI_B3 (P6.6, P6.7). So now the slave launchpad is running a total of 3 threads (i2c slaves on USCI_B0 and USCI_B3, and the dummyThread). I programmed a third launchpad as another master so that I now have two masters connected to my slave launchpad continuously talking to it. Initially everything looked like it was working, but eventually one of the two slave threads would lockup causing one of the masters to get stuck.

    Thanks.

  • Ok, I played around with it some more using different combinations and no matter what I try, I can only have one I2C thread running reliably.

    The end goal is to have one Launchpad run multiple threads, including:
    1) I2C master on USCI_B1
    2) I2C slave on USCI_B0
    3) I2C slave on USCI_B3
    4) GPIO/button interrupts

    Running a single I2C master thread works fine and running a single I2C slave thread works fine, but as soon as I try to combine them, one of the threads will eventually get stuck. Same when trying to run two I2C slave threads.

    I am simulating everything using the MSP432 Launchpads and have 10K pull-ups on the SDA/SCL lines. I have a total of four MSP432 LaunchPads.

    Thanks.
  • Could you attach these files so I can look through your code and run it on my own device?  Maybe I will be able to help you track this down that way.

  • Hi John,

    I attached the two projects.

    Master - this only runs one thread querying an i2c slave on USCI_B1 (SDA/SCL P6.4/P6.5). It's basically the stock example from the MSP432 1.30.00.40 SDK, modified to add a counter and loop forever.

    Slave - In the attached configuration, this is running two threads: one i2c master on USCI_B1 (P6.4/P6.5) and one i2c slave on USCI_B0 (P1.6/P1.7). The master thread is basically the same as the one above and the slave thread is from the example. In this project you can also enable a third thread for running a second i2c slave on USCI_B3 (P6.6/P6.7), but that 'pthread_create' is currently commented out.

    My testing environment consists of four MSP432 LaunchPads (Rev. C). Two programmed with the slave project and one or two programmed with the master project.

    LP1: Slave project. Connected to LP2 (P1.6<->P6.4, P1.7<->P6.5) and LP3 (P6.4<->P1.6, P6.5<->P1.7). To test second i2c slave, connect to LP4 (P6.6<->P6.4 and P6.7<->P6.5)

    LP2: Master project.

    LP3: Slave project (the i2c master thread on this LP will block since there is no i2c slave connected, or you can disable the i2c master thread).

    LP4: Master project.

    All I2C lines have 10K pull-ups to 3.3V.

    I hope all this makes sense and you can get everything up and running and figure out what the issue is. In the attached configuration, LP2 will eventually stop printing because the slave on LP1 stops responding.

    Thanks for the help!

    ferdster_1.zip

  • You say the slave on LP1 stops responding. 

    Do you mean LP3 (slave thread connected to LP1) stops responding to LP1(Master thread)?

    or

    Do you mean the LP1(slave thread) stops responding to LP2?  { Or that LP1(slave thread) stops responding to LP4? }

  • So, far in most of my trials, LP1 (master) to LP3 (slave) runs pretty reliable. I.e. LP1 keeps printing and I've had the count on it up to 100000. But I have seen LP3 (slave) stop responding too after a while. Remember LP1 and LP3 are running the same identical code, except that on LP3 the master thread is blocked since it has no slave connected, but this alone seems to make the slave thread run much more reliably.

    Most of the time it's LP1 (slave) that stops responding to LP2 (master). I.e. LP2 master will print out to ~200 (sometimes as low as 20 or as high as 1000). In most instances, LP1 is holding SCL low and if I manually toggle it by physically moving the jumper to 3.3V and back, it will continue (no reset on either board required). But sometimes that doesn't work and on the scope is see a continuous clock on SCL and SDA high, then I have to reset LP1 and LP2.

    Thanks.

  • Hi John,

    Any updates? Were you able to run the projects and replicate what I am seeing?

    Thanks.
  • Ferdster,

    I have not had the resources available to set this up yet.  I am trying to gather the necessary things to help you with this, but I also have some other responsibilities ongoing at the same time so I am not able to promise you a definite time frame for being able to track this down with you.

    Since you have this setup already, are you able to run the devices in debug and isolate which device hangs in code and where it does so?  I think a great methodology is to test each individual thread just on its own to see if it fails or succeeds and then slowly introduce the new threads in a way that any changes you make are regression-testable.  That is to say, test the individual threads first and then introduce new threads in a way that they do not break the functionality of the previous threads.

    Also, there is an ROV tool in CCS which will allow you to see which threads(tasks) are running, blocked, preempted, etc as well as which HWIs are enabled/active.  It is helpful at times.

    I will try to assist you as I can, but at this time I do not have the time and resources to replicate your setup.

**Attention** This is a public forum