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.

Hangups and GPIO Sharing between tasks

Hi,

I have a couple of GPIO-controlled LEDs and a motor on a CC26xx based board.  I have two tasks that would like to use them and the third BLE task.  Everything seems to go fine unless I have the LEDs or motor going when I unplug from a USB power source (I have a battery attached as well and its charged). Then the problem occurs. Also, if I hit a BLE characteristic fast enough while using the LEDs/motor, I can trigger the same problem.  

The problem that appears under these conditions is that the task (let's call it the feedback task) controlling the LEDs/motor appears to die or maybe it's just stuck in sleep. 

All the pins are initialized are initialized in the main task and I do have a PIN_registerIntCb in that task; I'm sharing the pin handle as a global between the tasks.

The code for controlling the LEDs and motor works fine if it's in the main task (and in the feedback task if the above two conditions don't occur).

Any thoughts on what might be the problem?

  • Can you please let us know the version of TI-RTOS and CCS that you are using?

    Hunter Downs said:
    The problem that appears under these conditions is that the task (let's call it the feedback task) controlling the LEDs/motor appears to die or maybe it's just stuck in sleep

    When this problem occurs can you check the Task status in ROV? ROV is the RTOS Object Viewer available in CCS debug view under Tools Menu. In ROV, BIOS > Scan for errors.. and Task > Detailed are the interesting views that you can take a look at.

    Also, can you please share your code/configuration? It would help us look at your Task/GPIO configuration and understand what's happening.

    Vikram

  • Hi Vikram,

    I checked the status in ROV.  Attached is the screenshot. The feedback task that has priority 1 is the Feedback task and it's now blocked on a Task_sleep apparently for a very long time!  While I use Task_sleep in my feedback task, it's definitely not for as long as indicated and I put a guarding if statement around the setting of the Task_sleep so that it was never more than 150000. And yet i get this.

    Keep in mind the code never fails unless I pull the device from the USB while doing the feedback. The UART is on as well when I pull the device from the USB...could it be generating an interrupt that I'm not handling well?

    The feedback task is pretty simple:

    /*********************************************************************
     * @fn      RbFbT_createTask
     *
     * @brief   Task creation function for the feedback Task.
     *
     * @param   none
     *
     * @return  none
     */
    void RbFbT_createTask(void) {
    	Task_Params taskParams;
    
    	// Configure task
    	Task_Params_init(&taskParams);
    	taskParams.stack = RbFb_TaskStack;
    	taskParams.stackSize = RBFB_TASK_STACK_SIZE;
    	taskParams.priority = RBFB_TASK_PRIORITY;
    
    	Task_create(RbFbT_taskFxn,&taskParams,NULL) ;
    
    	//Task_construct(&RbFbTask, RbFbT_taskFxn, &taskParams, NULL);
    }
    
    
    static void RbFbT_init() {
    
    	// ******************************************************************
    	// N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
    	// ******************************************************************
    	// Register the current thread as an ICall dispatcher application
    	// so that the application can send and receive messages.
    	ICall_registerApp(&selfEntity, &semFB);
    
    	// Create an RTOS queue for message from profile to be sent to app.
    	fbMsgQueue = Util_constructQueue(&appMsg);
    
    	//RbFbT_MailboxCreate() ;
    }
    
    
    static void RbFbT_taskFxn(UArg a0, UArg a1) {
    
    	FeedbackMsgObj msg ;
    	FeedBackMsg pAppMsg ;
    
    	// Initialize task
    	RbFbT_init();
    
    	for (;;) {
    
    		// Waits for a signal to the semaphore associated with the calling thread.
    		// Note that the semaphore associated with a thread is signaled when a
    		// message is queued to the message receive queue of the thread or when
    		// ICall_signal() function is called onto the semaphore.
    		ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);
    
    		if (errno == ICALL_ERRNO_SUCCESS) {
    			ICall_EntityID dest;
    			ICall_ServiceEnum src;
    			ICall_HciExtEvt *pMsg = NULL;
    
    			if (ICall_fetchServiceMsg(&src, &dest,
    					(void **) &pMsg) == ICALL_ERRNO_SUCCESS) {
    
    				if (pMsg) {
    					ICall_freeMsg(pMsg);
    				}
    
    			}
    
    			// If RTOS queue is not empty, process app message.
    			if (!Queue_empty(fbMsgQueue)) {
    				pAppMsg = (FeedBackMsg) Util_dequeueMsg(fbMsgQueue);
    
    				RBFbT_doFeedback(pAppMsg) ;
    
    				ICall_free(pAppMsg);
    
    			}
    
    		}
    
    /*
            if (Mailbox_pend(feedbackMailbox, &msg, BIOS_WAIT_FOREVER) == 0) {
            	// Do something
                break;
            }
    */
    
    	} // END of infinite task loop
    }
    
    
    static void RBFbT_doFeedback(FeedBackMsg fbMsg) {
    
    	if ((fbMsg->state & ALERT_STATES) != 0) {
    
    		switch(fbMsg->state & ALERT_STATES) {
    		case RB_ALERT_LEVEL1:
    			Rb_BlinkFB(LED_OFF, LED_OFF, LED_ON, VIBE_OFF, 5);  // Use case B3
    			break ;
    
    		case RB_ALERT_LEVEL2:
    			Rb_GlowFB(LED_OFF, LED_ON, LED_OFF, VIBE_ON, 10);  // Use case D
    			break ;
    
    		case RB_ALERT_LEVEL3:
    			Rb_GlowFB(LED_ON, LED_ON, LED_OFF, VIBE_ON, 15);  // Use case B1
    			break ;
    
    		case RB_ALERT_LEVEL4:
    			Rb_BlinkFB(LED_ON, LED_ON, LED_OFF, VIBE_ON, 5);  // Use case B2
    			break ;
    
    		}
    
    		// Indicate we've done it in the profile
    		FindMe_setAlertLevel(ALERT_LEVEL_NO) ;
    
    
    	} else {
    
    		// Display Unpaired state if applicable
    		if ((fbMsg->state & RB_USER_SET) == 0) {
    			Rb_GlowFB(LED_OFF, LED_OFF, LED_ON, VIBE_OFF, 3);  //
    		}
    
    		// Display battery state
    		switch(fbMsg->state & BATTERY_STATES) {
    			case (RB_BATTERY_GOOD):		 // Use case C1
    				// Blink green
    				Rb_BlinkFB(LED_OFF, LED_ON, LED_OFF, VIBE_OFF, 3);
    			break ;
    
    			case (RB_BATTERY_OKAY):		 // Use case C2
    				Rb_BlinkFB(LED_ON, LED_ON, LED_OFF, VIBE_OFF, 3);
    
    			break ;
    
    			case (RB_BATTERY_LOW):		// Use case C3
    				Rb_BlinkFB(LED_ON, LED_OFF, LED_OFF, VIBE_OFF, 3);
    			break ;
    
    
    			default:
    				Rb_BlinkFB(LED_ON, LED_ON, LED_ON, VIBE_OFF, 3);
    				break ;
    		}
    	}
    
    }
    

    And I'm testing  RB_ALERT_LEVEL1 with blink code that looks like this:

    void Rb_BlinkFB(uint8_t redLED, uint8_t greenLED, uint8_t blueLED, uint8_t vibeMotor, uint8_t nBlinks) {
    	uint8_t volatile i;
    
    
    	setFBcolor(redLED,greenLED,blueLED,vibeMotor) ;
    
    	for (i = 0; i < nBlinks; i++) {
    		turnFBOn();
    		myDelayMs(BLINK_DURATION);
    		turnFBOff() ;
    		myDelayMs(BLINK_DURATION);
    	}
    }
    
    void myDelayMs(uint16_t duration) {
    
    	uint32_t volatile sleepTime = (duration * 1000L) / Clock_tickPeriod ;
    
    	if (sleepTime > 150000L) sleepTime = 0 ;  // Something went wrong
    
    	Task_sleep(sleepTime) ;
    
    }
    

    I'm using CCS 6.1 and BLE Stack 2.0. 

  • Hi Hunter,

    I discussed this issue with our Kernel expert. The timeout value in Task_sleep from ROV is a concern. Is the tick mode in Clock configured to Dynamic (TickMode_DYNAMIC)? Is your application configured to enter low power mode when it is running from battery? In the low power mode, some timers are turned off. If the Clock is configured to any of those timers, then the problem with Task_sleep can occur.

    Can you share your .cfg file?

    Thanks,
    Vikram

  • Hi Vikram,

    Below is the .cfg file. I don''t think TickMode_DYNAMIC is on. As for low power, I'm pretty sure it's on (and if it's not I sure want it on)...POWER_SAVINGS is defined.  How can I find out what timer the clock is configured to and if it gets turned off...my project is heavily based on the SensorTag firmware and I haven't to the best of my knowledge changed any of the timing functions (other than to add the Seconds module).

    BTW, thanks for all your help!

    Cheers,

    Hunter

    var ROM = xdc.useModule('ti.sysbios.rom.ROM');
    ROM.romName = ROM.CC2650;
    
    var Seconds = xdc.useModule('ti.sysbios.hal.Seconds');
    
    
    var Defaults = xdc.useModule('xdc.runtime.Defaults');
    var Types = xdc.useModule('xdc.runtime.Types');
    var Diags = xdc.useModule('xdc.runtime.Diags');
    var Error = xdc.useModule('xdc.runtime.Error');
    var Main = xdc.useModule('xdc.runtime.Main');
    var Memory = xdc.useModule('xdc.runtime.Memory')
    var SysCallback = xdc.useModule('xdc.runtime.SysCallback');
    var System = xdc.useModule('xdc.runtime.System');
    var Text = xdc.useModule('xdc.runtime.Text');
    var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem');
    var Reset = xdc.useModule('xdc.runtime.Reset');
    var BIOS = xdc.useModule('ti.sysbios.BIOS');
    var Clock = xdc.useModule('ti.sysbios.knl.Clock');
    var Task = xdc.useModule('ti.sysbios.knl.Task');
    
    var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
    var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
    var M3Hwi = xdc.useModule('ti.sysbios.family.arm.m3.Hwi');
    var Power = xdc.useModule('ti.sysbios.family.arm.cc26xx.Power');
    
    /* Add UART support */
    var TIRTOS = xdc.useModule('ti.tirtos.TIRTOS');
    TIRTOS.useUART = true;
    
    /* Enable idle task (default). */
    Task.enableIdleTask = true;
    
    /* Idle CPU when threads blocked waiting for an interrupt */
    Power.idle = true;
    Power.policyFunc = Power.standbyPolicy;
    Power.calibrateRCOSC = false;
    
    /* compile out all Assert's */
    Defaults.common$.diags_ASSERT = Diags.ALWAYS_OFF;
    
    /* Don't load string names of modules on the target */
    Defaults.common$.namedModule = false;
    
    /* Allow Mod_create() and Mod_construct() but not delete() or destruct() */
    Defaults.common$.memoryPolicy = Types.CREATE_POLICY;
    
    /* Don't load diagnostic/descriptive text strings on the target */
    Text.isLoaded = false;
    
    /* Use the minimal user-supplied callback provider */
    System.SupportProxy = SysCallback;
    /* no exit handlers needed */
    System.maxAtexitHandlers = 0;
    
    
    /* main() and Hwi, Swi stack size */
    Program.stack = 1024;
    /* no command-line arguments main(argc, argv) needed */
    Program.argSize = 0;
    
    /* build a custom, optimized version of SYS/BIOS */
    BIOS.libType = BIOS.LibType_Custom;
    
    /* no logging - all compiled out */
    BIOS.logsEnabled = false;
    
    /* disable Asserts in SYS/BIOS code */
    BIOS.assertsEnabled = false;
    
    /* Reduce number of Task priority levels to save RAM */
    Task.numPriorities = 6;
    
    /* Set the default Task stack size - used if one is not specified */
    Task.defaultStackSize = 512;
    
    /* Don't check stacks for overflow - saves cycles (and power) and Flash */
    Task.checkStackFlag = false;
    
    /* Disable exception handling to save Flash - undo during active development */
    M3Hwi.enableException = true;
    M3Hwi.excHandlerFunc = null; /* null = default while loop function. Use e.g. "&myFxn" to use your own function. */
    M3Hwi.nvicCCR.UNALIGN_TRP = 0;
    M3Hwi.nvicCCR.DIV_0_TRP = 0;
    
    /* Don't check for interrupt stack overflow during Idle loop */
    Hwi.checkStackFlag = false;
    
    /* Minimize Flash and RAM usage of Error module */
    Error.raiseHook = null; /* null = default while loop function. Use e.g. "&myFxn" to your own handler function. */
    Error.maxDepth = 2;
    
    /* Set the default CPU frequency */
    BIOS.cpuFreq.lo = 48000000;
    
    /* Put reset vector at start of Flash */
    M3Hwi.resetVectorAddress  = 0x0;
    
    /* Put interrupt vector at start of RAM so interrupts can be configured at runtime */
    M3Hwi.vectorTableAddress  = 0x20000000;
    
    /* CC2650 has 50 interrupts */
    M3Hwi.NUM_INTERRUPTS = 50;
    
    /* Create a small heap */
    BIOS.heapSize = 1668;
    
    var Swi = xdc.useModule('ti.sysbios.knl.Swi');
    Swi.numPriorities = 6;
    BIOS.swiEnabled = true;
    
    BIOS.includeXdcRuntime = true;
    
    /* Tasks cannot pend based on priority */
    Semaphore.supportsPriority = false;
    
    /* Change default error function -- just spin */
    Error.policyFxn = Error.policySpin;
    
    /* true:  Allow runtime creation of e.g. semaphores
     * false: Compile out reference to Memory in BIOS */
    BIOS.runtimeCreatesEnabled = true;
    
    
    /* Abort and exit functions -- just spin */
    System.abortFxn = System.abortSpin;
    System.exitFxn = System.exitSpin;
    
    
    /* CC26xx Boot module */
    var Boot = xdc.useModule('ti.sysbios.family.arm.cc26xx.Boot');
    Boot.driverlibVersion = 2;
    Boot.customerConfig = false;
    Boot.checkBackdoor = false;
    
    /* 10 us tick period */
    Clock.tickPeriod = 10;
    
    //var SysMin = xdc.useModule('xdc.runtime.SysMin');
    //System.SupportProxy = SysMin;
    //SysMin.bufSize = 128;
    
    
    //var System = xdc.useModule('xdc.runtime.System');
    //var SysStd = xdc.useModule('xdc.runtime.SysStd');
    //System.SupportProxy = SysStd;
    Task.allBlockedFunc = null;
    

  • Hi Hunter,

    The .cfg file looks fine. In my previous post, I was wondering if you changed any default settings for Clock but looking at the .cfg, the settings are default which should work fine. And also the Power module is set-up, so device should enter low power mode when idle.

    I also talked to our experts regarding the Task_sleep() timeout value again. The stale value displayed in ROV is expected and it does not indicate any issue with the actual code. This indicates the ROV tool could not get the timeout value (which is missing functionality in ROV that will be fixed in a future release).

    To narrow down the issue, firstly can you check if the issue is fixed by removing the UART (for debugging this issue)? Second, can you check if the application works when powered by battery only? Is this a TI board or a custom board? If it is a custom board, does it have hardware support to adjust for any power fluctuation when USB power is unplugged? I don't know much about the hardware features for this device. But we may need to ask hardware experts (in the device forum) whether the device CPU enters a different mode when power fluctuates.

    Vikram