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/CC1310: Custom application using the TI 15.4 sensor stack example

Part Number: CC1310
Other Parts Discussed in Thread: TIDA-00489

Tool/software: TI-RTOS

Hey guys,

I have been going through the application code of the TI 15.4 Star Network example using sensor/collector. I was able to get the example working, adapting a few parameters in the config file. I now want to understand the code and make some changes to fit it to my application. Therefor I need some help:

  1. I want to understand the Main_AssertHandler, there are three assert reasons:
    1. Icall: Is this something like an interrupt, caused by a polling of the sensor by the collector?
    2. Hwi: I assume this is a typical hardware interrupt?!
    3. MAC: I honestly don't know where to put that. What kind of assert reason is this?
  2. Scrolling down the "main.c" file of the sensor example one comes to 3 different assert handler, all of them calling the main_assertHandler function.
    1. Main_excHandler
    2. HalAssertHandler
    3. MacHalAssertHandler
    4. When are these functions called?
  3. I want the sensor to count up every time a hardware interrupt occurs. I am not sure where to put this function?!
  4. When the sensor is not transmitting or counting up, is the module going into standby or idle and where can I set it to go into standby to save some power?
  5. If I put the collector to polling every minute, is the collector calling every sensor node successively or does this "polling counter" start when the sensor enters the network? (hope you understand what I mean)
  6. In the sensor example I can send either the ID or the sensor value, I'd like to send both, what is the most elegant way to do this?

Many questions, I know, but especially the first two can help me to get a "firm grasp on the general system architecture" as proposed by the TI team to make my own custom applications :)

Kind regards

Stefan Weigl

  • Hi,

    1. MAIN_ASSERT_ICALL is called in the icall module which manages the indirect function calls between the application and the stack
    MAIN_ASSERT_MAC is called in the stack side when the MAC asserts
    MAIN_ASSERT_HWI_TIRTOS hardware interrupt assert triggered by TI-RTOS

    2. Hal and MacHal assert handlers are called in the 802.15.4 stack side
    Main_excHandler is the TIRTOS HWI Handler called automatically by TI-RTOS when an exception occurs

    3. you can configure the HWI to have a callback and you can count in the callback or trigger an event from the callback and count when you process the event.

    4. the sensors are set up to automatically go to sleep or standby mode once TI-RTOS goes into the idle loop which means that your device should be going to sleep as long as nothing is being transmitted, received or being processed in the device.

    5. the collector does not do the polling, the collector configures the polling interval on the sensors. Based on this polling interval the sensors will wake up and poll the collector for data if there is no data for them they will go back to sleep until the next polling interval.

    6. I am not sure what you mean by ID when you say that you can either send the ID or sensor data. what id are you talking bout? When the sensor sends sensor data it sends it together with a frame control which specifies what type of sensor it is and a cmdId which specifies that the data being sent is sensor data.
  • Hi Hector,

    thank you for the elaborate answer!

    Regarding the points 1-3 from above:

    If I read the code (main.c file from the "Sensor and Collector - TI 15.4-Stack Project Zero" example of the CC13X0 SDK) correctly, no matter which of these 3 assertReasons occurs, the Main_assertHandler - function is called toggling the LEDs.

    My main focus is on implementing my altered TIDA-00489 software code into this example, including 2 basic functions:

    1. Count up if movement is detected (I will do this as proposed in the callback function, since I was also doing this in my TIDA software)
    2. Send the counter value to the collector in a certain time interval, e.g. every 5min.

    Am I right, that I actually do not need the Main_assertHandler at all to get this done?

    Regarding the points 5-6 from above:


    If the sensor polls the collector for data, how can I get the sensor to send data to the collector every 5 min?

    Do I need a timer for that or is there another "polling" option for that?

    If there is a third, more elegant, alternative to achieve this task, let me know.

    By ID, I mean the address of the sensor. I'd like to have the counter value + sensor address, to know which sensor detects the most movements.

    Regarding the point 3 from above:

    static void txTaskFunction(UArg arg0, UArg arg1)
    {
    	/* Init task TI-RTOS objects */
    	initializeTask();       // Der Task wird initialisiert
    
    	/* Backdoor access */
    	uint8_t modeValue = PIN_getInputValue(Board_Mode); 
    
    	if(modeValue == 1)
    	{
    
    	    Power_shutdown(NULL);
    
    		//Trap code here
    		while(1);
    	}
    
    
    	/* Get the reason for reset */
    	uint32_t rSrc = SysCtrlResetSourceGet();   
    	if(rSrc == RSTSRC_WAKEUP_FROM_SHUTDOWN)     
    	{
    		/*** Pin interrupt ***/
    		// Configure GPIO interrupt
    		intr_handle = PIN_open(&intr_state, intrPinTable);
    		PIN_registerIntCb(intr_handle, &intr_HwiFxn);       
    		PIN_setConfig(intr_handle, PIN_BM_IRQ, Board_PIR_Out_Lo | PIN_IRQ_POSEDGE); // IRQ bei positiver Flanke ausgelöst
    		PIN_setConfig(intr_handle, PIN_BM_IRQ, Board_PIR_Out_Hi | PIN_IRQ_POSEDGE); // IRQ bei positiver Flanke ausgelöst
    
    		//Send ON packet
    		sendPacket(0xAA);
    
    		move = 1;           // When system wakes up due to movement, set move = 1
    
                    while(1) 
    		{
    
    		//Wait to make sure there are no more additional movements.
    		//If any movement detected, counter is restarted in the ISR
    		Clock_setTimeout(radioSyncTxClockHandle, PIR_QUIET_TIME / Clock_tickPeriod);
    		Clock_start(radioSyncTxClockHandle);
    
    		Semaphore_pend(radioSyncTxSemHandle, BIOS_WAIT_FOREVER);
    
    		sendPacket(move);  //Send the number of moves.  This assumes the number will be less than 2 bytes
    
    		move = 0;    // Reset move counter.
    
    		//Send OFF packet
    		sendPacket(0xFF);
    
    		}
    
    		//Wait for sensor to settle
    		while(1)
    		{
    			uint8_t pirLowValue  = PIN_getInputValue(Board_PIR_Out_Lo); // Checke Pin Wert vom einen Pin
    			uint8_t pirHighValue = PIN_getInputValue(Board_PIR_Out_Hi); // Checke Pin Wert vom anderen Pin
    
    			if(pirLowValue == 0 && pirHighValue == 0)                   // Sind beide Pins low, ist der Sensor "gesettelt"
    			{
    			    sendPacket(0x44);
    			    break;
    			}
    		}
    	}
    	else        // Falls der Reset anders ausgelöst wurde als durch Interrupt, also durch Einschalten
    	{
    		/*** Power on reset wakeup ***/
    
    		//Send initial packet to show system is up
    		sendPacket(0x00);
    		
    		while(1)
    		{
    
    			//Wait for sensor to start up and settle
    			Clock_setTimeout(radioSyncTxClockHandle, PIR_SETTLE_TIME / Clock_tickPeriod);
    			Clock_start(radioSyncTxClockHandle);
    			Semaphore_pend(radioSyncTxSemHandle, BIOS_WAIT_FOREVER);
    
    			//Check value of comparators. If not low, wait for more time
    			uint8_t pirLowValue  = PIN_getInputValue(Board_PIR_Out_Lo);
    			uint8_t pirHighValue = PIN_getInputValue(Board_PIR_Out_Hi);
    
    			if(pirLowValue == 0 && pirHighValue == 0)
    			{
    				break;
    			}
    
    			else   
    			{
    				//Send error packet
    				sendPacket(0xEE);
    			}
    		}
    	}   
    
    	/* Wait for sensor to settle after RF transmission */
    	Task_sleep(PIR_SHUTDOWN_TIME / Clock_tickPeriod);   
    
    	/* Go to shutdown to wait for next PIR interrupt */
    	PINCC26XX_setWakeup(PinTableWakeUp);    
    	Power_shutdown(NULL);
    
    	/* Should never get here, since shutdown will reset */
    	while(1);
    }
    
    
    //**********CALLBACK FUNCTION**************
    
    void intr_HwiFxn(PIN_Handle hPin, PIN_Id pinId) // Interrupt callback function
    {
    	if(pinId == Board_PIR_Out_Lo || pinId == Board_PIR_Out_Hi) 
    	{
    	    move = move + 1;   // Instead of resetting the clock, add to the move variable
    
    	}
    }

    For a better understanding of my TIDA-00489 code, I added part of the code above. It is basically the same as you can find here: http://www.ti.com/lit/ug/tiduau1b/tiduau1b.pdf

    with a few alterations.

    And now I am not sure, where to put this code. Can I put it in the TaskFkt of the Sensor-Collector Example (see code below)?

    Or can you suggest how to proceed to get my 2 basic functions to work using this example?

    {
    #ifdef TIMAC_AGAMA_FPGA
    //...(deleted)
    #else
        /* Disallow shutting down JTAG, VIMS, SYSBUS during idle state
         * since TIMAC requires SYSBUS during idle. */
    #ifndef POWER_MEAS
        Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
    #endif
    
    #endif
        /* Initialize ICall module */
        ICall_init();
    
        /*
         * Copy the extended address from the CCFG area
         * Assumption: the memory in CCFG_IEEE_MAC_0 and CCFG_IEEE_MAC_1
         * is contiguous and LSB first.
         */
        memcpy(ApiMac_extAddr, (uint8_t *)&(__ccfg.CCFG_IEEE_MAC_0),
               (APIMAC_SADDR_EXT_LEN));
    
        /* Check to see if the CCFG IEEE is valid */
        if(memcmp(ApiMac_extAddr, dummyExtAddr, APIMAC_SADDR_EXT_LEN) == 0)
        {
            /* No, it isn't valid.  Get the Primary IEEE Address */
            memcpy(ApiMac_extAddr, (uint8_t *)(FCFG1_BASE + EXTADDR_OFFSET),
                   (APIMAC_SADDR_EXT_LEN));
        }
    
    
    #ifdef NV_RESTORE
        /* Setup the NV driver */
    #ifdef ONE_PAGE_NV
        NVOCOP_loadApiPtrs(&Main_user1Cfg.nvFps);
    #else
        NVOCTP_loadApiPtrs(&Main_user1Cfg.nvFps);
    #endif
    
        if(Main_user1Cfg.nvFps.initNV)
        {
            Main_user1Cfg.nvFps.initNV( NULL);
        }
    #endif
    
        /* Start tasks of external images */
        ICall_createRemoteTasks();
    
        /* Initialize the application */
        Sensor_init();                      // Here is a lot of important stuff initialized
    
    
        /* Kick off application - Forever loop */
        while(1)
        {
            Sensor_process();       // Here the Ssf_functions are a called!!!
        }
    }

    If you suggest me to further dive into the code or to check some documentation, feel free to post links.

    kind regards

    Stefan

  • Hi Stefan,

    The assert handlers mentioned in your post are there only to handle exceptions or errors in the code. You do not need to add, remove or modify any of those functions to get your application working. The handlers will get executed only if there was a problem in TI-RTOS, or somewhere in the software stack.

    regarding points 5 - 6
    The sensor can send data to the collector whenever it wants since the collector is always listening. in the sensor example application we have a timer which is in charge to send data top the collector and its period is defined by the macro "CONFIG_REPORTING_INTERVAL". please note that the collector sends a configuration message to the sensors when they join the network. this configuration message will set up the polling interval and the reporting interval. You can modify these intervals in the collector side and they are defined by the macros CONFIG_REPORTING_INTERVAL and CONFIG_POLLING_INTERVAL.

    Regarding the sensor address, you do not need to attach this to the sensor value, the sensor packet already has this information. you can extract it when you receive the packet in the callback function "dataIndCB" the address information will be in pDataInd->srcAddr

    Regarding where to put your code,
    You ideally should put your code in the sensor.c file. Probably the best places where you could add your code would be the function "Sensor_init" and "Sensor_process"

    You definitely should take a closer look at the file sensor.c and ssf.c
  • Thank you for your answer. I appreciate your help and I will try to play around a little bit and make some adjustments and alterations.