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.

CC2640/CC2650 missed semaphore causes task to remain blocked

Expert 1340 points
Other Parts Discussed in Thread: CC2640, SYSBIOS

I have firmware based on the SimpleBLEPeripheral (using CCSv6 on the CC2640). The MCU interfaces multiple sensors via GPIO pins and uses the Sensor Controller. The sensors trigger hwi via GPIO edge and the Sensor Controller issues hwi via fwSwitchOutputBuffer. These hwi simply post semaphore (and lights a debugging LED) to wake up the application task and read data from the sensor that triggered the hwi. The hwi seem to always be serviced (a debugging LED is lit when the hwi runs). However there are times when the semaphore does not wake up the application task (the same debugging LED is remains lit even though the task code for that sensor calls for it to become unlit). What could be the cause of this? Thanks!

  • Hello Tosa,
    Can you post the content of your HWI function?
    I guess you are using a binary semaphore? Could it be that the HWI runs again before you reach semaphore pend in your code?
  • Hi Eirik,

    I tried two versions of semaphore. The first is using the semaphore/queue as it is shown in the SimpleBLEPeripheral example. The Sensor Controller and each sensor's hwi enqueues a msg as in

    SensorDriver_enqueueMsg(SD_CHAR_CHANGE_EVT, paramID);

    In my second version I use only a counting semaphore (and no queue). Each sensor sets a flag and posts the semaphore as in

    // Store the event.
    events |= SD_SC_EVT;
    // Wake up the application.
    Semaphore_post(sem);

    Both versions have the missed semaphore issue for any given sensor at any random time. The hwi for the Sensor Controller is:

    static void SensorDriver_scAlertCallback(void)
    {
    	// FIXME
    	scifClearAlertIntSource();
    	scifAckAlertEvents();
    
    //  // Store the event.
    //  events |= SD_SC_EVT;
    //
    //  // Wake up the application.
    //  Semaphore_post(sem);
    	SensorDriver_charValueChangeCB(TIADS1298DATAREADY);   // enqueue msg
    } // scTaskAlertCallback
    

    Is the default semaphore type in SimpleBLEPeripheral binary? I see the following code:

    static ICall_Semaphore sem;
    ICall_registerApp(&selfEntity, &sem);

    but nothing explicitly to initialize it like:

    Semaphore_Params semParams;
    Semaphore_Params_init(&semParams);
    semParams.mode = Semaphore_Mode_COUNTING;
    Semaphore_construct(&semScTaskAlert, 0, &semParams);
    

    Thanks for your help on this.

  • Hi Eirik,

    Any comments on my previous post? Thanks!
  • Is the code stuck forever like this?
    Then you code might be stuck in your task. have you debugged your task to verify if this is the case.
  • Hi Eirik,

    I verified the task is not running or stuck. The task would un-light the respective LED for the sensor whose hwi triggered a semaphore post, but the LED remains lit. The same task processes reads from other sensors and their LEDs toggle, so the task is not stuck, but the sensor who's interrupt was not serviced remains in a non-responsive state since its interrupt register is never cleared by the task.

  • Adding additional debug details per email and phone:

    - Tosa has tried isolating the issue by trying a modified code which only services one sensor in the system. When this is done there appear to be no issues
    - When adding in a second sensor to the system, lockup issues start occurring where a read/interrupt clearing operation is not completed for one of the sensors
    - Each of the three sensors requires a different task because of varying interfaces

    Tosa would you be able to share the task code for reading the sensors and clearing the interrupts?

    Eirik, is there any reason why a task posted to the semaphore would be missed in some cases? It seems that running independently the tasks are operating without issues but adding in multiple sensors with HWIs causes issues. In what condition would the task code posted to the semaphore fail to execute?

    Thank You,
    Casey McCrea
  • Could this be a race condition on setting and clearing bits in the events variable?  If you set and clear separate variables to flag these events does that fix things?

  • Hello Casey,

    The application must ensure that a tickPeriod is not too short for the Sensor Controller to complete its tasks within a single tick interval. The tick period is set when you call the scifStartRtcTicksNow() function. The actual sensor controller framework code will start by clearing the RTC Channel 2 wake up event upon wakeup and wait for it to be cleared during powerdown before setting the clear bit in WUEVCLR back to 0. 

    From C:\Program Files (x86)\Texas Instruments\Sensor Controller Studio\fw_templates\framework_template.asm:

                           ; Wait for the ACK event to be cleared
    /waitOnRtcClearing:    iobtst      #IOB_WUC_WUEV_RTC, [#IOP_WUC_WUEVFLAGS]
                           biob1       /waitOnRtcClearing
                           iobclr      #IOB_WUC_WUEV_RTC, [#IOP_WUC_WUEVCLR]

    I believe you can get stuck here forever.

  • Thanks for the inputs from everyone!

    To clarify Casey's post,  I have two separate (or perhaps the same issue): one is some kind of system lockup (per this forum thread); the second is a "missed semaphore" issue which this forum thread is addressing.

    In my firmware, I have a single task that does sensor reads (either using MCU's I2C, SPI, GPIO (bit-bang SPI). The Sensor Controller is also used to read data from a sensor. The task is awoken with a semaphore queue (similar to that in SimpleBLEPeripheral) with a parameter identifying which sensor is to be read. My thought is that since I'm using a single task with a sempahore queue, then whenever a sensor has data ready to be read, it will wake up the task (if the task is not already reading another sensor's data) and then read the data. If another sensor is in the process of having its data read, then this new sensor will simply wait until its semaphore gets processed. 

    In the sensor HWI, I only call 

    PINCC26XX_setOutputValue(Board_AIN1, Board_LED_ON);
    SensorDriver_enqueueMsg(SD_CHAR_CHANGE_EVT, paramID); 

    to verify with an LED that the HWI occured. In the task code for the specific sensor, I clear the LED and read the sensor's data. When the system fails, I see the remain LED lit, implying that the semaphore was posted but not serviced.

    I tried various combinations of sensors (there are three in my system), and only running 1 at a time does not show this missed sempahore issue. I don't think it's an issue with the Sensor Controllers tickPeriod since it runs fine by itself, and also if I simply disable the sensor control and just run the other two sensors on their HWIs, the system issues still occur. Also, disabling the bit banged sensor doesn't help, so I don't think it's an issue with the bit banging driver.

    Thanks again for everyone's advice; I appreciate the inputs, and hopefully can narrow down and resolve this soon.

  • Correction to my answer:
    You will not get stuck, but the next scheduled task may be skipped/omitted as the next event flag may be cleared immediately if it occurs during the execution of a task.
  • Hello Tosa,
    I would recommend to add some sort of logging functionality to verify the program flow. This could help you narrow down the sequence of events and possibly find the issue. You can refer to how log messages are implemented on the latest Project 0 example code. Also check out all the steps covered in chapter 9 in the CC2640 Bluetooth low energy Software Developer’s Guide (swru393).
  • Did this get resolved?

    To enable kernel logging, first you cannot use the kernel in the ROM. It was built without instrumentation. So remove the ROM settings in the .cfg file. Note: this will increase the size of the application since the kernel code will now be in flash.

    When you are not using the ROM, you can enable the kernel logging in the .cfg file:
    BIOS.logsEnabled = true;

    And use the UIA LoggingSetup module in the .cfg. Since you want to see the Hwi events, you need to turn that on also in LoggingSetup. It's off by default since it generally floods the logs.
    var LoggingSetup = xdc.useModule('ti.uia.sysbios.LoggingSetup');
    LoggingSetup.sysbiosHwiLogging = true;

    You can either use ROV to look at the log records (Tools->ROV->LoggerStopmode) or use System Analyzer in CCS to get the records.

    Todd
  • Todd,

    There is still some confusion here. Can you please assist:

    "In regards to logging, what exactly information would you like me to log? I do have LEDs lit in strategic areas to allow me to asses program flow. As far as logging goes, it seems to only update in stop mode, so if the device locks up, I won’t be able to stop it…Furthermore , it seems that I need to disable the definitions for xdc_runtime_Log_DISABLE_ALL and xdc_runtime_Assert_DISABLE_ALL to get custom logging to work, but the software developer guide swru393e says not to undefined these in table 9.1. Could you please clarify?””

    Thanks,
    Casey
  • With the kernel logging enabled, the main thing you see is all the context switches. So you see when a Hwi starts, when a task preempts another task, etc.

    By locking up, I'm assuming you lose emulation. In this case, you are correct that the stopmode logging is not that useful. You can set-up logging out the UART also. Let me know if you are interested in that.

    Todd