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.

LAUNCHXL-CC26X2R1: Power consumption issue when running simplelink_zigbee_sdk_plugin_2_20_00_06 zed_switch on LAUNCHXL-CC26X2R1

Part Number: LAUNCHXL-CC26X2R1
Other Parts Discussed in Thread: ENERGYTRACE, , Z-STACK, CC2538, CC1352P

I try to use energy trace of CCS to monitor power consumption issue when running simplelink_zigbee_sdk_plugin_2_20_00_06 zed_switch on LAUNCHXL-CC26X2R1. I find a strange behavior is that zed_switch consumes 2.69mA (1st attached screen shot) after zed_switch starts and hasn't join any network. I try to switch to EnergyTrace+[CPU State]+[Peripheral State] and I find RX is not turn off. You can refer to the second attached screen shot. Can TI help to check if this is a bug in simplelink_zigbee_sdk_plugin_2_20_00_06? I expect power consumption of zed_switch should be less than 3 uA when it hasn't joined any Zigbee network.

  • Hi YK,

    Before I attempt to replicate this, can you please do the following?

    1. Define POWER_MEAS, POWER_SAVING, ZED_POWER_CONSUMPTION_WORKAROUND, remove BOARD_DISPLAY_USE_UART, and add Board_shutDownExtFlash() to main.c
    2. Remove all unnecessary isolation jumpers (5V, RXD/TXD, SWO, and TDO/TDI if using 2-pin JTAG for EnergyTrace only, 4-pin is required for ++) and power the MCU externally (Unpopulate VSENS jumper and connect VCC to middle pin, only connecting the USB cable after voltage is applied).
    3. Free run your project inside the debugger.
    4. Test EnergyTrace results against a power amplifier measurement.

    Regards,
    Ryan
  • 1. I define POWER_MEAS, POWER_SAVING, ZED_POWER_CONSUMPTION_WORKAROUND, remove BOARD_DISPLAY_USE_UART, and add Board_shutDownExtFlash() to main.c

    2. Since energy trace need JTag which usesTDO/TDI so I can only remove 5V, RXD/TXD, SWO jumpers. I also power the MCU externally.

    After I free run the project, I see the mean current is 0.002mA but I see it shows 3mA on my power supply to power LAUNCHXL-CC26X2R1 externally. If you look at my new attached energy trace screen shot, you can see RX is still not turn off after device is power on and doesn't join any Zigbee network. I think those defines doesn't fix the issue and please help to verify this from your side. Thanks.

  • Hello Ryan and YK

    I have test this issue by simplelink_zigbee_sdk_plugin_0_95_00_18 .

    You need remove UI functions in zed_switch_cc26x2lp.

    1. Define POWER_MEAS, POWER_SAVING, ZED_POWER_CONSUMPTION_WORKAROUND, remove BOARD_DISPLAY_USE_UART, and add Board_shutDownExtFlash() to main.c
    2. Remove all unnecessary isolation jumpers (5V, RXD/TXD, SWO, and TDO/TDI if using 2-pin JTAG for EnergyTrace only, 4-pin is required for ++) and power the MCU externally (Unpopulate VSENS jumper and connect VCC to middle pin, only connecting the USB cable after voltage is applied).
    3. Free run your project inside the debugger.
    4. Test EnergyTrace results against a power amplifier measurement.

    Please check my test screen shot. You hope you test  in simplelink_zigbee_sdk_plugin_2_20_00_06. .

  • simplelink_zigbee_sdk_plugin_0_95_00_18 Is obsolete Stack version. Please test with simplelink_zigbee_sdk_plugin_2_20_00_06 .
  • Hello YK,

    I have replicated the issue and am discussing a viable solution with the Software Dev Team, thank you for raising this to our attention.

    Regards,
    Ryan
  • Thanks for verifying this and keep us updating what the root cause of this issue is and how to fix it.
  • As an intermediate workaround, you could start network steering BDB commissioning at the end of application initialization. Standby mode should be entered even if it fails to find the network.

    Regards,
    Ryan
  • We need add code in zclSampleDoorLock_ProcessCommissioningStatus :

    static void zclSampleDoorLock_ProcessCommissioningStatus(bdbCommissioningModeMsg_t *bdbCommissioningModeMsg)
    {
    switch(bdbCommissioningModeMsg->bdbCommissioningMode)
    {
    case BDB_COMMISSIONING_FORMATION:
    if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS)
    {
    zstack_bdbStartCommissioningReq_t zstack_bdbStartCommissioningReq;

    //After formation, perform nwk steering again plus the remaining commissioning modes that has not been process yet
    zstack_bdbStartCommissioningReq.commissioning_mode = BDB_COMMISSIONING_MODE_NWK_STEERING | bdbCommissioningModeMsg->bdbRemainingCommissioningModes;
    Zstackapi_bdbStartCommissioningReq(zclSampleDoorLock_Entity,&zstack_bdbStartCommissioningReq);
    }
    else
    {
    //Want to try other channels?
    //try with bdb_setChannelAttribute
    }
    break;
    case BDB_COMMISSIONING_NWK_STEERING:
    if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS)
    {
    //YOUR JOB:
    //We are on the nwk, what now?
    }
    else
    {
     // standby


    }
    break;
    case BDB_COMMISSIONING_FINDING_BINDING:
    if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS)
    {
    //YOUR JOB:
    }
    else
    {
    //YOUR JOB:
    //retry?, wait for user interaction?
    }
    break;
    case BDB_COMMISSIONING_INITIALIZATION:
    //Initialization notification can only be successful. Failure on initialization
    //only happens for ZED and is notified as BDB_COMMISSIONING_PARENT_LOST notification

    //YOUR JOB:
    //We are on a network, what now?

    break;
    #if ZG_BUILD_ENDDEVICE_TYPE
    case BDB_COMMISSIONING_PARENT_LOST:
    if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_NETWORK_RESTORED)
    {
    //We did recover from losing parent
    }
    else
    {
    //Parent not found, attempt to rejoin again after a fixed delay
    Timer_setTimeout( EndDeviceRejoinClkHandle, SAMPLEAPP_END_DEVICE_REJOIN_DELAY );
    Timer_start(&EndDeviceRejoinClkStruct);
    }
    break;
    #endif
    }

    UI_UpdateComissioningStatus(bdbCommissioningModeMsg);
    }

    this's right ?

  • I add the following red lines according to your seggestion but I still see the same problem.

    static void zclSampleSw_initialization(void)
    {

        /* Initialize user clocks */
        zclSampleSw_initializeClocks();

        /* Initialize keys */
        Board_Key_initialize(zclSampleSw_changeKeyCallback);

        /* Initialize the LEDS */
        Board_Led_initialize();

        // Register the current thread as an ICall dispatcher application
        // so that the application can send and receive messages.
        ICall_registerApp(&zclSampleSw_Entity, &sem);


        //Initialize stack
        zclSampleSw_Init();
        {
            zstack_bdbStartCommissioningReq_t zstack_bdbStartCommissioningReq;
            zstack_bdbStartCommissioningReq.commissioning_mode = BDB_COMMISSIONING_MODE_NWK_STEERING;
            Zstackapi_bdbStartCommissioningReq(zclSampleSw_Entity,&zstack_bdbStartCommissioningReq);
        }
    }

  • Hello YK,

    Apologies for the confusion, please add

    #if defined ( POWER_SAVING )
    osal_pwrmgr_device( PWRMGR_BATTERY );
    #endif

    to the BDB_INITIALIZATION case of bdb_reportCommissioningState, specifically in the didSuccess -> ZG_DEVICE_ENDDEVICE_TYPE section for a factory new device (also, #include "OSAL_PwrMgr.h" in bdb.c). Then call bdb_reportCommissioningState(BDB_INITIALIZATION,FALSE); inside of your application initialization as before.  This issue also affects Z-Stack 3.0.1 and as such the Wiki page has been updated.

    Edit: A better solution for osal_pwrmgr.c:

    void osal_pwrmgr_init( void )
    {
    #if !defined USE_ICALL && !defined OSAL_PORT2TIRTOS
    #if defined POWER_SAVING && ZSTACK_END_DEVICE_BUILD
      pwrmgr_attribute.pwrmgr_device = PWRMGR_BATTERY; // Default to power conservation for ZED if power saving enabled.
    #else
      pwrmgr_attribute.pwrmgr_device = PWRMGR_ALWAYS_ON; // No power conservation for routing devices.
    #endif
    #endif /* USE_ICALL */
      pwrmgr_attribute.pwrmgr_task_state = 0; // Cleared. All set to conserve
    #if defined USE_ICALL || defined OSAL_PORT2TIRTOS
      pwrmgr_initialized = TRUE;
    #endif /* defined USE_ICALL || defined OSAL_PORT2TIRTOS */
    }

    Regards,
    Ryan

  •  Just test your latest patch and it doesn't work too. I still see RX is on in energytrace after device starts.

  • Hi YK,

    I apologize for the confusion, you are correct that this latest solution was designed for Z-Stack 3.0.1 and will not work for Z-Stack 3.1.0. Please be patient as we continue to work towards a solution.

    Regards,
    Ryan
  • OK. Will wait your next fix.
  • Do you have any update on this issue?
  • We are still developing a solution for this and hope to provide an update by the end of this week.

    Regards,
    Ryan
  • Hi YK,

    In osal_run_system() of osal.c, please edit the following:

    #include "hmac_map_direct.h"
      if (idx < tasksCnt)
      {
        uint16 events;
        halIntState_t intState;
    
        HAL_ENTER_CRITICAL_SECTION(intState);
        events = macTasksEvents[idx];
        macTasksEvents[idx] = 0;  // Clear the Events for this task.
        HAL_EXIT_CRITICAL_SECTION(intState);
    
        activeTaskID = idx;
        events = (tasksArr[idx])( idx, events );
        activeTaskID = TASK_NO_TASK;
    
        HAL_ENTER_CRITICAL_SECTION(intState);
        macTasksEvents[idx] |= events;  // Add back unprocessed events to the current task.
        HAL_EXIT_CRITICAL_SECTION(intState);
      }
      // Complete pass through all task events with no activity
      // Put the processor/system into sleep
    #if defined (USE_ICALL)
      else
      {
            MAP_macPwrVote(FALSE, FALSE);
      }
    #else
    #if defined( POWER_SAVING )
      else
      {
        osal_pwrmgr_powerconserve();
      }
    #endif
    #endif

    Edit: code format

    Regards, Ryan

  • I revise the following red codes and test it. However, I still see the same problem. Do I miss anything?

    void osal_run_system( void )
    {
      uint8 idx = 0;

    #ifdef USE_ICALL
      uint32 next_timeout_prior = osal_next_timeout();
    #else /* USE_ICALL */
    #ifndef HAL_BOARD_CC2538
      osalTimeUpdate();
    #endif

      Hal_ProcessPoll();
    #endif /* USE_ICALL */

    #ifdef USE_ICALL
      {
        /* Update osal timers to the latest before running any OSAL processes
         * regardless of wakeup callback from ICall because OSAL timers are added
         * relative to the current time. */
        unsigned long newtimestamp = ICall_getTicks();
        uint32 milliseconds;

        if (osal_tickperiod == 1000)
        {
          milliseconds = newtimestamp - osal_last_timestamp;
          osal_last_timestamp = newtimestamp;
        }
        else
        {
          unsigned long long delta = (unsigned long long)
            ((newtimestamp - osal_last_timestamp) & 0xfffffffful);
          delta *= osal_tickperiod;
          delta /= 1000;
          milliseconds = (uint32) delta;
          osal_last_timestamp += (uint32) (delta * 1000 / osal_tickperiod);
        }
        osalAdjustTimer(milliseconds);
        /* Set a value that will never match osal_next_timeout()
         * return value so that the next time can be scheduled.
         */
        next_timeout_prior = 0xfffffffful;
      }
      if (osal_eventloop_hook)
      {
        osal_eventloop_hook();
      }

      for (;;)
      {
        void *msg;
        ICall_EntityID src, dst;
        osal_msg_hdr_t *hdr;
        uint8 dest_id;

        if (ICall_fetchMsg(&src, &dst, &msg) != ICALL_ERRNO_SUCCESS)
        {
          break;
        }

        hdr = (osal_msg_hdr_t *) msg - 1;

    #ifdef ICALL_LITE
        if (hdr->format == ICALL_MSG_FORMAT_DIRECT_API_ID)
        {
            if (osal_icallMsg_hook)
            {
              (*osal_icallMsg_hook)(msg);
            }
        }
        else
    #endif /* ICALL_LITE */      
        {
          dest_id = osal_dispatch2id(dst);
          if (dest_id == TASK_NO_TASK)
          {
            /* Something wrong */
            ICall_abort();
          }
          else
          {
            /* Message towards one of the tasks */
            /* Create a proxy task ID if necessary and
             * queue the message to the OSAL internal queue.
             */
            uint8 proxyid = osal_alien2proxy(hdr->srcentity);

            if (hdr->format == ICALL_MSG_FORMAT_1ST_CHAR_TASK_ID)
            {
              uint8 *bytes = msg;
              *bytes = proxyid;
            }
            else if (hdr->format == ICALL_MSG_FORMAT_3RD_CHAR_TASK_ID)
            {
              uint8 *bytes = msg;
              bytes[2] = proxyid;
            }
            /* now queue the message to the OSAL queue */
            osal_msg_send(dest_id, msg);
          }
        }
      }
    #endif /* USE_ICALL */

      do {
        if (macTasksEvents[idx])  // Task is highest priority that is ready.
        {
          break;
        }
      } while (++idx < tasksCnt);

      if (idx < tasksCnt)
        {
          uint16 events;
          halIntState_t intState;

          HAL_ENTER_CRITICAL_SECTION(intState);
          events = macTasksEvents[idx];
          macTasksEvents[idx] = 0;  // Clear the Events for this task.
          HAL_EXIT_CRITICAL_SECTION(intState);

          activeTaskID = idx;
          events = (tasksArr[idx])( idx, events );
          activeTaskID = TASK_NO_TASK;

          HAL_ENTER_CRITICAL_SECTION(intState);
          macTasksEvents[idx] |= events;  // Add back unprocessed events to the current task.
          HAL_EXIT_CRITICAL_SECTION(intState);
        }
    #if defined ( POWER_SAVING)
    #if defined (USE_ICALL)
      else
      {
        MAP_macPwrVote(FALSE, FALSE);
      }
    #else
      else
      {
        osal_pwrmgr_powerconserve();
      }
    #endif
    #endif
      /* Yield in case cooperative scheduling is being used. */
    #if defined (configUSE_PREEMPTION) && (configUSE_PREEMPTION == 0)
      {
        osal_task_yield();
      }
    #endif

    #if defined USE_ICALL
      /* Note that scheduling wakeup at this point instead of
       * scheduling it upon ever OSAL start timer request,
       * would only work if OSAL start timer call is made
       * from OSAL tasks, but not from either ISR or
       * non-OSAL application thread.
       * In case, OSAL start timer is called from non-OSAL
       * task, the scheduling should be part of OSAL_Timers
       * module.
       * Such a change to OSAL_Timers module was not made
       * in order not to diverge the OSAL implementations
       * too drastically between pure OSAL solution vs.
       * OSAL upon service dispatcher (RTOS).
       * TODO: reconsider the above statement.
       */
      {
        halIntState_t intState;

        uint32 next_timeout_post = osal_next_timeout();
        if (next_timeout_post != next_timeout_prior)
        {
          /* Next wakeup time has to be scheduled */
          if (next_timeout_post == 0)
          {
            /* No timer. Set time to the max */
            next_timeout_post = OSAL_TIMERS_MAX_TIMEOUT;
          }
          if (next_timeout_post > osal_max_msecs)
          {
            next_timeout_post = osal_max_msecs;
          }
          /* Restart timer */
          HAL_ENTER_CRITICAL_SECTION(intState);
          ICall_stopTimer(osal_timerid_msec_timer);
          ICall_setTimerMSecs(next_timeout_post, osal_msec_timer_cback,
                              (void *) (++osal_msec_timer_seq),
                              &osal_timerid_msec_timer);
          HAL_EXIT_CRITICAL_SECTION(intState);
        }
        
    #ifdef ICALL_EVENTS
        /*
         * When using events, OSAL needs to be sure that it will not block itself
         * if any message have yet to been processed.  The OSAL event must be
         * signaled when any messages remain unprocessed at the end of this
         * function.
         */
        if (osal_qHead)
        {
          ICall_signal(osal_syncHandle);
        }
        else
        {
          for (uint8 i = 0; i < tasksCnt; i++)
          {
            if (macTasksEvents[i] != 0)
            {
              ICall_signal(osal_syncHandle);
            }
          }
        }
    #endif /* ICALL_EVENTS */
      }
    #endif /* USE_ICALL */
    }

  • Hi YK,

    Yes, that is the correct location inside of osal.c. Did you include hmac_map_direct.h? I forgot to mention this step earlier, also edited out the POWER_SAVING flag as it will be deprecated in future releases. I have verified this solution so please let me know if you continue to experience difficulty.

    Regards,
    Ryan
  • Do you mean I have to add “#include “hmac_map_direct.h”“ in osal.c and what do you mean “edited out the POWER_SAVING flag”?
  • Anyway, I tried to add “#include “hmac_map_direct.h”“ in osal.c and also define POWER_SAVING in project predefined symbols to test this again. However, I still see RX is always ON.
  • hi Ryan,
    For your modified code, FW can run to "MAP_macPwrVote(FALSE, FALSE);" but the power consumption still keep around 2.6mA.
    Note, by default, the POWER_SAVING flag is not enable.

    Do you verify on "simplelink_zigbee_sdk_plugin_2_20_00_06" "zed_switch_cc26x2lp" project ? Could you share your CCS project code ?
    thank you.
  • YK, Jerry,

    Yes, add “#include “hmac_map_direct.h” in osal.c. Ignore all mention of POWER_SAVING, it is a deprecated flag and will not be used in future releases. RX being on could be an issue with EnergyTrace, please confirm that the power is higher than expected with a ampere meter or power analyzer and all jumpers disconnected. I verified with the exact SDK and project described.

    Regards,
    Ryan
  • If I use external power supply with current meter to measure power consumption (all jumpers between XDS110 and CC1352P are removed and jumpers of red and green led are removed too), I can still see 70uA@3.3V. I think this is still too high in compare with CC253x. I expect the current consumption should be much less than this. Do I still miss anything?
  • I find if I connect CC1352P RX pin to GND, I can see the current consumption becomes 10uA@3.3V and if I also shut down external flash, it will become less than 2uA@3.3V. Then, I try to define BOARD_DISPLAY_USE_UART=0 in project predefined symbols and define CC1352R1_LAUNCHXL_UART0_RX, CC1352R1_LAUNCHXL_UART0_TX, CC1352R1_LAUNCHXL_UART0_CTS, and CC1352R1_LAUNCHXL_UART0_RTS to PIN_UNASSIGNED in CC1352R1_LAUNCHXL.h to disable UART. In this way, I can see power consumption is less than 2uA@3.3V without connecting CC1352P RX pin to GND.
  • I have an extra question. Since this is an issue on energy trance, will your tool team investigate this and provide fix ASAP?
  • Hi YK,

    Thank you for the detailed solution, it will be very useful for other community members. I'm glad to know that you are now operating at the expected power consumption level. I have submitted a ticket for the EnergyTrace bug to be investigated.

    Regards,
    Ryan
  • Thanks for following up Energy Trace issue and if it's possible, please notify me when it is fixed.