Other Parts Discussed in Thread: BLE-STACK
Tool/software: Code Composer Studio
SDK: simplelink_cc13x2_26x2_sdk_4_10_00_78
IDE: CCS
SCS: 2.6.0.132
HW: CC1352P
RTOS: TI-RTOS w/ POSIX
Starting Point to Application: simple_peripheral_oad_offchip
Issue Overview
Our device consists of a simple sensor application that performs periodic sensor measurements that immediately get sent out via BLE to a gateway. Due to our device requirements, the sensor controller MCU is being used to reduce power usage. We currently are seeing strange behaviors that aren't specifically referenced in TI's SC documentation, so we would like to get word from the e2e community to see if anyone else has any information or experience on the matter.
Without posting a bunch of unrelated code, here is a stripped down version of the problem..
Example #1
// 'scPressureThread' -- SC thread void* scPressureThread(void *arg0) { // Initialize the Sensor Controller... scifOsalInit(); scifOsalRegisterCtrlReadyCallback(scCtrlReadyCallback); scifOsalRegisterTaskAlertCallback(scTaskAlertCallback); scifInit(&scifDriverSetup); int status = sem_init(&SensorControllerSem, 0, 0); for (;;) { sem_wait(&SensorControllerSem); gpio_write(VSEN, 0); // Turn on voltage rail powering the sensors /* * Run the "PressureAndAccelerometer" Execution Code only via TI's recommendation */ if (scifWaitOnNbl(20000) != SCIF_SUCCESS) { //... Handle timeout or usage error ... } else if (scifSwTriggerExecutionCodeNbl( 1 << SCIF_PRESSURE_AND_ACCELEROMETER_TASK_ID) != SCIF_SUCCESS) { //... Handle usage error ... } usleep(100000); // liberal 100ms delay to ensure SC task block finishes execution gpio_write(VSEN, 0); // Turn off voltage rail powering the sensors } }
Observations/Notes on Code Block #1
In the main application, a posix thread is initialized with the SC drivers as shown above. The actual contents of the SC task block are unimportant in this observation. The only thing that I'd like to mention is that
the GPIO pin that is being used to toggle the voltage rail is not being shared between the SC and main application CPU.
When the thread's semaphore gets posted, the power rail to the sensor gets enabled and the SC execution code gets triggered to run. Where things get dodgey is the following usleep() operation under the POSIX
API. The goal was to use POSIX's usleep function to put the main application to sleep for a liberal amount of time (more than enough time for the SC execution code to complete) before waking up and disabling the
power rail since TI's documentation states that the scifSwTriggerExecutionCodeNbl() returns immediately. In reality, this configuration crashes the application. The BLE stops advertising and the sensor controller
thread seems to only partially execute a single time before never executing again.
Example #2
/* Callback for Pressure and Tilt timer */ void pressure_tilt_cb(Timer_Handle handle, int_fast16_t status) { gpio_write(VSEN, 0); } // 'scPressureThread' -- SC thread void* scPressureThread(void *arg0) { // Initialize the Sensor Controller... scifOsalInit(); scifOsalRegisterCtrlReadyCallback(scCtrlReadyCallback); scifOsalRegisterTaskAlertCallback(scTaskAlertCallback); scifInit(&scifDriverSetup); /* Timer setup */ Timer_init(); Timer_Handle pt_tim_handle; Timer_Params params; Timer_Params_init(¶ms); params.periodUnits = Timer_PERIOD_US; params.period = 100000; params.timerMode = Timer_ONESHOT_CALLBACK; params.timerCallback = pressure_tilt_cb; pt_tim_handle = Timer_open(CONFIG_TIMER_PRESSURE_TILT, ¶ms); int status = sem_init(&SensorControllerSem, 0, 0); for (;;) { sem_wait(&SensorControllerSem); gpio_write(VSEN, 1); /* * Run the "PressureAndAccelerometer" Execution Code via TI's recommendation * If either checks result in an unsuccessful call, the thread does not run and the issue is tracked */
Timer_start(pt_tim_handle);
if (scifWaitOnNbl(20000) != SCIF_SUCCESS) { //... Handle timeout or usage error ... } else if (scifSwTriggerExecutionCodeNbl( 1 << SCIF_PRESSURE_AND_ACCELEROMETER_TASK_ID) != SCIF_SUCCESS) { //... Handle usage error ... } } }
Observations/Notes on Code Block #2
For this implementation, the usleep(10000) was replaced by a similar approach to controlling the VSEN rail via a timer callback. In this implementation, the SC execution
block executes properly, the BLE advertising remains, and the application does not appear to hang.
Questions for the TI e2e Community
-
Why does implementation #2 work while #1 does not?
-
What is the mechanism at play when the Sensor controller execution finishes?
-
If the nbl() function does in fact return immediately, why would the usleep() delay method crash the system?
-
Has anyone ran into POSIX/SC limitations before?