Other Parts Discussed in Thread: CC1310, SYSBIOS
Hello everybody,
I've build a simple remote controller with 3 relay outputs around the CC1310 launchpads as prototype.
For the remote; the system is working around a 3V battery, current consumption is about 6µA when not in use.
The proto's are currently in use, and we are running into a problem which perhaps you can help me with.
After a few months, 3 or so, the remote gets stuck. To explain myself better I'll explain the software flow:
using TIRTOS; CCS V7 and Windows 10.
I'll first create a task, the transmitPackageTask and a semaphore, configure the led and button pins, configure the interrupts for the buttons and configure the semaphore. Then call BIOS_start().
Now when a button is pressed, the callback will post the semaphore, which will enable the transmitPackageTask to run and send 5 packets with information about the button, batteryvoltage and temperature. After those are sent the semaphore will be pend and the CPU will goes back to sleep.
Has anybody an idea about the CPU getting stuck after a few months? I'll have to go there to measure things like battery voltage and stuff, but the battery was just new.
/* * Copyright (c) 2015-2016, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * ======== Filled with transmitter code ======== */ /* XDCtools Header files */ #include <xdc/std.h> #include <xdc/runtime/System.h> /* BIOS Header files */ #include <ti/sysbios/BIOS.h> #include <ti/sysbios/knl/Clock.h> #include <ti/sysbios/knl/Task.h> #include <ti/sysbios/knl/Semaphore.h> /* TI-RTOS Header files */ #include <ti/drivers/PIN.h> #include <driverlib/aon_batmon.h> #include <ti/drivers/rf/RF.h> #include <ti/drivers/Power.h> #include <ti/drivers/power/PowerCC26XX.h> /* Board Header files */ #include "Board.h" #include "smartrf_settings/smartrf_settings.h" #define TASKSTACKSIZE 1024 #define PAYLOAD_LENGTH 30 Task_Struct task0Struct; Char task0Stack[TASKSTACKSIZE]; /* Pin driver handle */ static PIN_Handle ledPinHandle; static PIN_State ledPinState; static PIN_Handle buttonPinHandle; static PIN_State buttonPinState; static RF_Object rfObject; static RF_Handle rfHandle; Semaphore_Struct semStruct; Semaphore_Handle semaphore; /* * Application LED pin configuration table: * - All LEDs board LEDs are off. */ PIN_Config ledPinTable[] = { Board_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, PIN_TERMINATE }; PIN_Config buttonPinTable[] = { Board_BUTTON0 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE, Board_BUTTON1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE, Board_BUTTON2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE, PIN_TERMINATE }; uint8_t butState = 0; /* * ======== heartBeatFxn ======== * Toggle the Board_LED0. The Task_sleep is determined by arg0 which * is configured for the heartBeat Task instance. */ Void transmitPackageTask(UArg arg0, UArg arg1) { uint8_t i; uint32_t bat_voltage; int32_t temp_deg_cel; uint8_t packet[PAYLOAD_LENGTH]; RF_Params rfParams; RF_Params_init(&rfParams); RF_cmdPropTx.pktLen = PAYLOAD_LENGTH; RF_cmdPropTx.pPkt = packet; /* Reserved data for ID or something else in the future */ packet[3] = (uint8_t) 0; packet[2] = (uint8_t) 0; packet[1] = (uint8_t) 0; packet[0] = (uint8_t) 0; while (1) { Semaphore_pend(semaphore, BIOS_WAIT_FOREVER); /* Request access to the radio */ rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams); /* Set the frequency */ RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0); if(AONBatMonNewBatteryMeasureReady() == 1){ bat_voltage = AONBatMonBatteryVoltageGet(); } if(AONBatMonNewTempMeasureReady() == 1){ temp_deg_cel = AONBatMonTemperatureGetDegC(); } packet[7] = (uint8_t)bat_voltage; //CPU voltage (battery voltage / ADC voltage) packet[6] = (uint8_t)(bat_voltage >> 8); //CPU voltage (battery voltage / ADC voltage) packet[5] = (uint8_t)(bat_voltage >> 16); packet[4] = (uint8_t)(bat_voltage >> 24); packet[12] = (uint8_t)temp_deg_cel; //CPU voltage (battery voltage / ADC voltage) packet[11] = (uint8_t)(temp_deg_cel >> 8); //CPU voltage (battery voltage / ADC voltage) packet[10] = (uint8_t)(temp_deg_cel >> 16); packet[9] = (uint8_t)(temp_deg_cel >> 24); packet[13] = butState; //Buttons: b0 = pin 1, b1 = pin2, b2 = pin 3.....b7 = pin 8 butState = 0; for(i = 0; i < 5; i++){ /* Send packet */ RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0); if (!(result & RF_EventLastCmdDone)) { /* Error */ while(1); } } PIN_setOutputValue(ledPinHandle, Board_LED0, 0); PIN_setOutputValue(ledPinHandle, Board_LED1, 0); RF_close(&rfObject); } } void buttonCallbackFxn(PIN_Handle handle, PIN_Id pinId) { /* Debounce logic, only toggle if the button is still pushed (low) */ CPUdelay(8000*50); if (!PIN_getInputValue(pinId)) { /* Toggle LED based on the button pressed */ switch (pinId) { case Board_BUTTON0: PIN_setOutputValue(ledPinHandle, Board_LED0, 1); butState |= 1; break; case Board_BUTTON1: PIN_setOutputValue(ledPinHandle, Board_LED1, 1); butState |= 2; break; case Board_BUTTON2: PIN_setOutputValue(ledPinHandle, Board_LED1, 1); PIN_setOutputValue(ledPinHandle, Board_LED0, 1); butState |= 4; break; default: /* Do nothing */ break; } Semaphore_post(semaphore); } } /* * ======== main ======== */ int main(void) { Task_Params taskParams; /* Call board init functions */ Board_initGeneral(); AONBatMonEnable(); /* Construct heartBeat Task thread */ Task_Params_init(&taskParams); taskParams.arg0 = 1000000 / Clock_tickPeriod; taskParams.stackSize = TASKSTACKSIZE; taskParams.stack = &task0Stack; Task_construct(&task0Struct, (Task_FuncPtr)transmitPackageTask, &taskParams, NULL); Semaphore_Params semParams; /* Open LED pins */ ledPinHandle = PIN_open(&ledPinState, ledPinTable); if(!ledPinHandle) { System_abort("Error initializing board LED pins\n"); } buttonPinHandle = PIN_open(&buttonPinState, buttonPinTable); if(!buttonPinHandle) { System_abort("Error initializing button pins\n"); } /* Setup callback for button pins */ if (PIN_registerIntCb(buttonPinHandle, &buttonCallbackFxn) != 0) { System_abort("Error registering button callback function"); } Semaphore_Params_init(&semParams); Semaphore_construct(&semStruct, 0, &semParams); semaphore = Semaphore_handle(&semStruct); System_printf("Starting the example\nSystem provider is set to SysMin. " "Halt the target to view any SysMin contents in ROV.\n"); /* SysMin will only print to the console when you call flush or exit */ System_flush(); /* Start BIOS */ BIOS_start(); return (0); }