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.

CC1352P: BLE 5.0 communication setting for proper communication

Part Number: CC1352P
Other Parts Discussed in Thread: SYSCONFIG,

Hi Support,

I am facing issues in receiving data on BLE 5.0 while other device is sending beacon ( broadcasting data), I can able to receive 6 out of 10 broadcast. I have tried to change  Min Max time  at broadcaster and changed scan window and interval at observer side but it does not help me to achieve 100 % communication rate. 

Does some help or doc available that guide me to do correct setting of parameter for proper communication in beacon ( broadcast mode)

I am using multirole sample application for testing. below is my setting for Adv parameters. 

GapAdv_params_t advParams1 = {
.eventProps = GAP_ADV_PROP_CONNECTABLE,// | GAP_ADV_PROP_LEGACY | GAP_ADV_PROP_SCANNABLE,
.primIntMin = 160,//240,
.primIntMax = 176,//280,
.primChanMap = GAP_ADV_CHAN_ALL,
.peerAddrType = PEER_ADDRTYPE_PUBLIC_OR_PUBLIC_ID,
.peerAddr = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa },
.filterPolicy = GAP_ADV_WL_POLICY_ANY_REQ,
.txPower = 16,//GAP_ADV_TX_POWER_NO_PREFERENCE,
.primPhy = GAP_ADV_PRIM_PHY_1_MBPS,//GAP_ADV_PRIM_PHY_1_MBPS,
.secPhy = GAP_ADV_SEC_PHY_CODED_S8,//GAP_ADV_SEC_PHY_CODED_S8,
.sid = 0
};

below is my scan code

#define SCAN_PARAM_DFLT_INTERVAL 560 //800
/// Default scan window (in 625 us ticks)
#define SCAN_PARAM_DFLT_WINDOW 528 //800

void multi_role_enableScan( void )
{
uint8_t temp8;

// Setup scanning

// Register callback to process Scanner events
GapScan_registerCb(multi_role_scanCB, NULL);

// Set Scanner Event Mask
GapScan_setEventMask(GAP_EVT_SCAN_ENABLED | GAP_EVT_SCAN_DISABLED |
GAP_EVT_ADV_REPORT);

// Set Scan PHY parameters
GapScan_setPhyParams(DEFAULT_SCAN_PHY| SCAN_PRIM_PHY_CODED, SCAN_TYPE_PASSIVE,
SCAN_PARAM_DFLT_INTERVAL, SCAN_PARAM_DFLT_WINDOW);

temp8 = SCAN_FLT_DUP_ENABLE;
GapScan_setParam(SCAN_PARAM_FLT_DUP, &temp8);
}

  • Hi Jai,

    There seems to be a problem with CurrentConsumptionDetails.docx, can you re-upload it?

    If something is still going on in the application the device will not go to sleep. E.g. the application is processing an event. This is why I would be curious to see the call stack when this happens. I would suggest running the application without the debugger attached, then attach the debugger when this happens. 

    You can also check the power constraints when this happens. (The power constraints will not be affected by whether or not you have a debugger attached.) The various drivers use power constraints so releasing them in the application is not a guarantee that they will stay released.

  • Hi Marie,

    Please find the attached doc again, could you able to find my source code files? if not let me know I will attache them.

    in my application, I have event's those are coming when data received, or clock events. clock events are comes at every 100 ms, so I observed some current pulse at every 100ms, I stop clock events when I goes to sleep. So I does not observe current pulse at every 100ms when my device goes to sleep.

    I am not sure about data received event how much time it will take to process, but when it come my application gets it and then process it. and then goes to sleep.

    But in problematic case my device goes to sleep but keep on consuming 2mA current, it wakeup on button press it perform data transmits and receive activity and then goes again to sleep but the current remain same 2mA. so it stuck and prevents going into sleep. 

    when you say my application still processing event, then how much time it will take to complete it, I observe my device keep on consuming 2mA it mean it never comes out from this ( this only happen when problem comes else not).

    Please note:- I have verified GPIO status all are having same status when my device is in sleep in problematic case and non problematic case. so it looks like my application is performing sleep as desired, but core is not going to sleep.

    can you explain how I can check power constraints ? and is there some constraints that never get releases in some case like happen with my app.

    as I explained earlier I have only used below constraints, which I clear before going to sleep, can you have a look of my code and let me know if I have done anything wrong with it. Please refer method "PTD_ReadyForSleep_g"

    Power_releaseConstraint(PowerCC26XX_SB_DISALLOW);

    Power_releaseConstraint(PowerCC26XX_IDLE_PD_DISALLOW); 

    " I would suggest running the application without the debugger attached, then attach the debugger when this happens. "4113.CurrentConsumptionDetails.docx

    I will try to simulate this, but I suspect when I connect debugger my device get reset, it works as desired and the problem is resolved.

     

  • Hi Marie,

    can you please let me know your work timings, and time zone. It will help me to query accordingly to get quick response. at the moment this take 1 day time.

  • Hi Marie,

    I have uploaded file on https://app.box.com/folder/ please find from there, this is created by Chander G

  • Hi Jai,

    Thank you, I received the file from Chander. Will look into it.

  • Hi Marie,

    I did not able to find "PowerCC26X2_module.constraintMask"variable in code,  may it is a part of object code ( SDK) so it's not have access to me,  but I did find an API that return the constraint Mask that is “Power_getConstraintMask”

     I observe when this problem comes my constraints mask remain 0x0C, I don’t know why but because of this my device does not go to sleep and consume 1.5 mA current.

    This constraint does not get clear even when below release constraints is called. 

    Power_releaseConstraint(PowerCC26XX_SB_DISALLOW);

    Power_releaseConstraint(PowerCC26XX_IDLE_PD_DISALLOW);

     It looks like SDK goes in some unknown state and ignoring release constraints API.

    regards Jai.

  • Hi Jai,

    Can you send me or Chander the Production.c file? 

    I was mistaken yesterday. The power constraints are incremental, meaning that if you set the SB_Disallow constraint twice you will need to remove it twice for the device to go to standby. 

    When you use the UART_read API the UART driver will make sure the device does not go to sleep until the UART transfer has completed. Thus you should not need to set any power constraints in your application at all. 

  • Hi Marie,

    Thanks for your replay please find my responce.

    #I was mistaken yesterday. The power constraints are incremental, meaning that if you set the SB_Disallow constraint twice you will need to remove it twice for the device to go to standby. 

    Jai:- that my be a reason, but as now I am not setting any constraint in my application for its normal use, so things are working as desired.

    #When you use the UART_read API the UART driver will make sure the device does not go to sleep until the UART transfer has completed. Thus you should not need to set any power constraints in your application at all. 

    Jai:- may be, but as I have to receive message on UART too, that seems not working, if I does not set constraint my UART does work as desired, it does not respond to any receive command. this may be because of  the way I have implemented UART

    the reason may be "Production_TaskRun_g" is called at every 100ms and in between my device stays in sleep if I does not set "Power_setConstraint" , this may result in UART not working as it does not receive anything.

    Below is information about my code

    I set constraint only when I need to enable UART, else not, code that perform this is in PTD_main.c file 

    if (PIN_getInputValue(CONFIG_PIN_0) == 0)
    {
    /* Giving 100 Ms Delay Checking Debounce to avoide false production mode */
    Task_sleep(100*100);
    if (PIN_getInputValue(CONFIG_PIN_0) == 0)
    {
    PtdTaskState = ePtdState_ProductTest;
    Production_TaskInit_g();
    Power_setConstraint(PowerCC26XX_SB_DISALLOW);
    // Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
    }else{}
    }else{}

    I am release this constraints when my UART work is over this happen when "Production_TaskRun_g(): returns True.

    case ePtdState_ProductTest:
    if( cTrue == Production_TaskRun_g() )
    {
    Production_Sleep_g();
    PtdTaskState = ePtdState_Sleep;
    Power_releaseConstraint(PowerCC26XX_SB_DISALLOW);

    Please find attached files.

    /** @file           PTD_main.c
    *   @copyright      Copyright (c) 2016 Secure International Holdings Pte. Ltd.
    *   @author         Written by: Jagdish Kushwaha
    *   @date           Started on:  20/05/2020
    *   @brief          This is a PTD application main file 
    */
    /* *********************************************************************** */
    /* included files */
    #include "util.h"
    #include "Typedef.h"
    #include "PTD_main.h"
    #include "PTDTimer.h"
    #include <ti_drivers_config.h>
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/rf/RF.h>
    #include "ti_drivers_config.h"
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    
    #include "Commissioning.h"
    #include "Data.h"
    #include "Flash.h"
    #include "Aes128.h"
    #include "LCD.h"
    #include "Ble.h"
    #include "Production.h"
    #include "PTDScreen.h"
    #include "HDCSensor.h"
    #include "Schedular.h"
    #include "multi_role.h"
    #include <ti/sysbios/knl/Task.h>
    #include "ll_common.h"
    #include <ti/drivers/Power.h>
    #include <ti/drivers/power/PowerCC26XX.h>
    #include <unistd.h>
    #include "keypad.h"
    #include "TimeSetting.h"
    #include "UserInterface.h"
    #include "SmlUtil.h"
    #include "DisplayLCD.h"
    #include <ti/drivers/Watchdog.h>
    /* ======================================================================= */
    
    /* #defines */
    /* ----------------------------------------------------------------------- */
    
    /* type definitions */
    
    /* ----------------------------------------------------------------------- */
    
    /* definitions of static (local) variables */
    /** 
     PTD state machine clock comes at every 10ms
    */
    static Clock_Struct PtdCommissionClock;
    static tePtdState PtdTaskState;
    Watchdog_Handle watchdogHandle;
    tUI8 IsDeviceInSleep = cFalse;
    tUI8 CommissioningTimer;        /* decrement at every cCommissioningFreq  */
    tUI32 nTimTick;
    
    /* ----------------------------------------------------------------------- */
    
    /* definitions of external (global)variables(Use of global is Not recommended)*/
    
    /* ----------------------------------------------------------------------- */
    
    /* definitions of constant data tables */
    
    /* ----------------------------------------------------------------------- */
    
    /* prototypes of local (static) functions */
    void initRfFrontendCustom(void);
    void watchdogCallback(uintptr_t watchdogHandle);
    void PTD_InitWatchDog( void );
    static void PTD_CommissionHandler(UArg a0);
    /* ======================================================================= */
    
    /* ----------------------------------------------------------------------- */
    void PTD_Init_g( void )
    {
      PTD_InitWatchDog( );
      Data_Init_g( );
      GPIO_init( );
      Lcd_Init_g( );
      Ble_Init_g( );
      HDC_Init_g( );
      Flash_Init_g( );
      Screen_InitParam_g( );
      Schedular_InitParam_g( );
      Commissioning_PowerOnInit_g( );
      DateInit_g( );
      UX_ResetAllVariable_g( );
      PtdTaskState = ePtdState_Init;
      Util_constructClock(&PtdCommissionClock, PTD_CommissionHandler,
                          cCommissioningFreq, cCommissioningFreq, false, 0);  
        /* If Top button pressd  enter in production test mode */
    #if cAlwaysProductionMode 
      PtdTaskState = ePtdState_ProductTest;
      Production_TaskInit_g();
    #else /* cAlwaysProductionMode */
    
    #if cDebugUartEnable
      Production_TaskInit_g();
    #endif
      
      if( Flash_IsPtdCommissioned_g( ) == cPtdCommissioned ) 
      { /* Configure HDC sensor if PTD commissioned else not */
        HDC_ConfigSensor_g();
        Keypad_EnableInt_g( eKeyEnable_All );
      }
      else
      {
        Keypad_EnableInt_g( eKeyEnable_Top );
      }
      
      if (PIN_getInputValue(CONFIG_PIN_0) == 0)
      {
        /* Giving 100 Ms Delay Checking Debounce to avoide false production mode */
        Task_sleep(100*100);
        if (PIN_getInputValue(CONFIG_PIN_0) == 0)
        {
          PtdTaskState = ePtdState_ProductTest; 
          Production_TaskInit_g();
          Power_setConstraint(PowerCC26XX_SB_DISALLOW);
    //      Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);      
        }else{}  
      }else{}
    #endif  /* cAlwaysProductionMode */
      PTD_StartTask_g();
    
    #ifdef cTestEnable  
      #include "Testing.h"
      PtdTaskState = ePtdState_Normal;
      HDC_ConfigSensor_g( );
      LoadDefaultData();
    #endif
    
    #ifdef cDisableSleep  
      Power_disablePolicy();
    #endif  
    }
    
    static void PTD_CommissionHandler(UArg a0)
    {
      if( CommissioningTimer > 0 )
      {
        CommissioningTimer--;
        PTD_StartTask_g();
      }  
    }
    /* ----------------------------------------------------------------------- */
    void PTD_Task_g( void )
    {
      tUI8 aBuff[ 2u ];
      tCommissioningStatus CommissStatus;
      static tUI32 PtdTaskTick;
      
      IsDeviceInSleep = cFalse;
      PTD_FeedWatchDog();
      Lcd_Task_g();
      Timer_UpdateTick_g();
      (void) BLE_CommsFsm_g( );
    
    #ifdef cConfigChngByUart
      Production_TaskRun_g();
    #endif
      
    #if defined( cTestEnable ) || defined( cPacketSniffer )  
      #include "Testing.h"  
      #ifdef cPacketSniffer  
        static tUI8 blEnableScan = cTrue;
          if( blEnableScan )
          {
            blEnableScan = cFalse;
            BLE_EnableScan_g();
            tUI8 status;
            status = HCI_LE_ClearWhiteListCmd();        
          }
      #else
        Testing_g( );    
      #endif
    #else  
      switch( PtdTaskState )
      {
        case ePtdState_Init:
          /* PTD will wakeup from deep sleep */
          if( cPtdCommissioned == Flash_IsPtdCommissioned_g( ) )
          {
            Ble_ReadData_g( eDataReqUpdate );
            PtdTaskState = ePtdState_Normal; 
          }  
          else
          {
            Lcd_AllOff_g( );
            Display_UpdateGuidingArea2Text_g( "TO SETUP    ",12u, cFlashDisable );
            Display_UpdateGuidingArea1_g( "HOLD MENU BUTTON", cFlashDisable );
            Lcd_Update_g( );    
            PtdTaskState = ePtdState_WaitToStart;
            PtdTaskTick = Timer_GetTick_g( );
          }
          break;
      case ePtdState_WaitToStart:
          if( Keypad_GetEvent_g( cKey_Top ) == eKeyEvent_Hold )
          {
            Keypad_EnableInt_g( eKeyEnable_All );
            /* We want to clear hold counter in this specific case */
            Keypad_GetEvent_g( cKey_ClearAllCounter );
            PtdTaskState = ePtdState_Commissioning;
            Commissioning_InitParam_g( eDevTypePTD );
            if (!Util_isActive(&PtdCommissionClock))
            {
             Util_startClock(&PtdCommissionClock);
             CommissioningTimer = cCommissioningTout;
            }
            else{}       
          }else if( cTrue == Timer_IsOver_g( PtdTaskTick, cStartCommissionTimeout ))
          {
            PtdTaskState = ePtdState_Sleep;
          }
          else{}  
          break;
          
        case ePtdState_ProductTest:
          if( cTrue == Production_TaskRun_g() )
          {
            Production_Sleep_g();
            PtdTaskState = ePtdState_Sleep;
            Power_releaseConstraint(PowerCC26XX_SB_DISALLOW);
    //        Power_releaseConstraint(PowerCC26XX_IDLE_PD_DISALLOW);        
            if( Flash_IsPtdCommissioned_g( ) == cPtdCommissioned ) 
            { /* Configure HDC sensor if PTD commissioned else not */
              HDC_ConfigSensor_g();
            }
            else{}
          }else{}
          break;
        case ePtdState_Commissioning:
          CommissStatus = Commissioning_Task_g( );
          if( CommissStatus == eStatus_Success )
          {
            Screen_ResetTick_g( );
            aBuff[ 0u ] = cPtdCommissioned;
            Flash_WriteData( eFlashCommissFlag, 1u, aBuff );
            Screen_CreateMenu_g( cScreenDefault );
            if (Util_isActive(&PtdCommissionClock))
            {
              Util_stopClock(&PtdCommissionClock);
            }        
            PtdTaskState = ePtdState_Normal;
          }
          else if( CommissStatus == eStatus_Back )
          { /* If commissioning duration expire go to sleep */
            if( CommissioningTimer == 0u )
            {  
              PtdTaskState = ePtdState_Sleep;
              if (Util_isActive(&PtdCommissionClock))
              {
                Util_stopClock(&PtdCommissionClock);
              }
            }
            else
            {/* Sleep here Commissioning clock will wakeup */
              Util_restartClock(&PtdCommissionClock, cCommissioningFreq);
              PTD_ReadyForSleep_g();
            }                       
          }      
          else{}
          if( Keypad_GetEvent_g( cKeyBack ) == eKeyEvent_Hold )
          {
            (void)Keypad_GetEvent_g( cKey_ClearAllEvt );
            Screen_CreateMenu_g( cScreenFactoryReset );
            PtdTaskState = ePtdState_Normal;
          }else{}
          break;
        case ePtdState_Normal:
          if( cTrue == Screen_Display_g( ) )
          {
            PtdTaskState = ePtdState_Sleep; 
          }
          break;
          
        case ePtdState_Sleep:
        /* If any key is pressed */
          if(Keypad_IsKeyPressed_g() == cTrue )
          {/* Clear all key event after wake up */
            Keypad_GetEvent_g( cKey_ClearAllEvt );
            PtdTaskState = ePtdState_Init; 
          }else if (BLE_CommsFsm_g() == cTrue ) /* Safe to sleep */
          {
            PTD_ReadyForSleep_g();
          }else{}
          break;      
        default:
          PtdTaskState = ePtdState_Sleep;
          break;
      }
    #endif
    }
    /* ----------------------------------------------------------------------- */
    void PTD_Task_NextStage( void )
    {
      if( Flash_IsPtdCommissioned_g( ) != cPtdCommissioned ) 
      {
        PtdTaskState = ePtdState_Commissioning;
        Commissioning_InitParam_g( eDevTypePTD );
      }
      else
      {
        PtdTaskState = ePtdState_Normal;
      }            
    }  
    /* ----------------------------------------------------------------------- */
    void PTD_ReadyForSleep_g( void )
    {
    //  tUI8 ConstraintMsk;
      PTD_StopTask_g();
      Screen_ResetAll_g( );
      BLE_StopSensorBroadCast_g( cFalse );
      Lcd_Sleep_g();
      Keypad_Sleep_g();    
      Commissioning_InitVariableOnSleep_g( );
      UX_ResetAllVariable_g( );
    //  ConstraintMsk = Power_getConstraintMask();
    //  Power_releaseConstraint(PowerCC26XX_SB_DISALLOW);
    //  ConstraintMsk = Power_getConstraintMask();
    //  Power_releaseConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
    //  ConstraintMsk = Power_getConstraintMask();
      IsDeviceInSleep = cTrue;
      Rtc_Sleep_g();
    }
    /* ----------------------------------------------------------------------- */
    /*
     * ======== Antenna switching ========
     */
    /*
     * ======== rfDriverCallbackAntennaSwitching ========
     * Function to handle antenna switching.
     */
    void rfDriverCallbackAntennaSwitching(RF_Handle client, RF_GlobalEvent events, void *arg)
    {
    
        static PIN_Handle antennaPins;
        static PIN_State antennaState;
        /* Protect against repeated RF_init */
        static bool initialized = false;
    
        /* Local variable. */
        bool    sub1GHz   = false;
        uint8_t loDivider = 0;
    
        if (!initialized && events & RF_GlobalEventInit) 
        {
          /* Don't do it again */
          initialized = true;
          PIN_Config antennaConfig[] = {
          CONFIG_RF_24GHZ | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,      /* Path disabled */
          CONFIG_RF_HIGH_PA | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,      /* Path disabled */
          CONFIG_RF_SUB1GHZ | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,      /* Path disabled */
          PIN_TERMINATE
          };
          antennaPins = PIN_open(&antennaState, antennaConfig);
        }
        else if (events & RF_GlobalEventRadioSetup) 
        {
          /* Switch off all paths. */
          PINCC26XX_setOutputValue(CONFIG_RF_24GHZ, 0);
          PINCC26XX_setOutputValue(CONFIG_RF_HIGH_PA, 0);
          PINCC26XX_setOutputValue(CONFIG_RF_SUB1GHZ, 0);
    
          /* Decode the current PA configuration. */
          RF_TxPowerTable_PAType paType = (RF_TxPowerTable_PAType)RF_getTxPower(client).paType;
    
          /* Decode the generic argument as a setup command. */
          RF_RadioSetup* setupCommand = (RF_RadioSetup*)arg;
    
          switch (setupCommand->common.commandNo) 
          {
            case (CMD_RADIO_SETUP):
            case (CMD_BLE5_RADIO_SETUP):
                loDivider = RF_LODIVIDER_MASK & setupCommand->common.loDivider;
    
                /* Sub-1GHz front-end. */
                if (loDivider != 0) {
                    sub1GHz = true;
                }
                break;
            case (CMD_PROP_RADIO_DIV_SETUP):
                loDivider = RF_LODIVIDER_MASK & setupCommand->prop_div.loDivider;
    
                /* Sub-1GHz front-end. */
                if (loDivider != 0) {
                    sub1GHz = true;
                }
                break;
            default:break;
          }
    
          if (sub1GHz) 
          {
              /* Sub-1 GHz */
              if (paType == RF_TxPowerTable_HighPA) {
                  /* PA enable --> HIGH PA
                   * LNA enable --> Sub-1 GHz
                   */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_GPIO);
                  /* Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
                           de-asserted on CC1352 Rev A. */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_RFC_GPO3);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_RFC_GPO0);
              } else {
                  /* RF core active --> Sub-1 GHz */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setOutputValue(CONFIG_RF_SUB1GHZ, 1);
              }
          } else {
              /* 2.4 GHz */
              if (paType == RF_TxPowerTable_HighPA)
              {
                  /* PA enable --> HIGH PA
                   * LNA enable --> 2.4 GHz
                   */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_RFC_GPO0);
                  /* Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
                           de-asserted on CC1352 Rev A. */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_RFC_GPO3);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
              } else {
                  /* RF core active --> 2.4 GHz */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setOutputValue(CONFIG_RF_24GHZ, 1);
              }
          }
        }
        else if (events & RF_GlobalEventRadioPowerDown) {
            /* Switch off all paths. */
            PINCC26XX_setOutputValue(CONFIG_RF_24GHZ, 0);
            PINCC26XX_setOutputValue(CONFIG_RF_HIGH_PA, 0);
            PINCC26XX_setOutputValue(CONFIG_RF_SUB1GHZ, 0);
    
            /* Reset the IO multiplexer to GPIO functionality */
            PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_GPIO);
            PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_GPIO);
            PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
        }
    }
    
    #ifdef cEnableWatchDog
    /* ----------------------------------------------------------------------- */
    void PTD_InitWatchDog( void )
    {
      uint32_t        reloadValue;
      Watchdog_Params params;  
      Watchdog_init();
      /* Open a Watchdog driver instance */
      Watchdog_Params_init(&params);
      params.callbackFxn = (Watchdog_Callback) watchdogCallback;
      params.debugStallMode = Watchdog_DEBUG_STALL_ON;
    
      params.resetMode = Watchdog_RESET_ON;
      watchdogHandle = Watchdog_open(CONFIG_WATCHDOG_0, &params);
      if (watchdogHandle == NULL) {
        /* Error opening Watchdog */
        while (1) {}
      }  
      
    //  Watchdog_close(watchdogHandle);
          /*
         * The watchdog reload value is initialized during the
         * Watchdog_open() call. The reload value can also be
         * set dynamically during runtime.
         *
         * Converts TIMEOUT_MS to watchdog clock ticks.
         * This API is not applicable for all devices.
         * See the device specific watchdog driver documentation
         * for your device.
         */
        /* Watchdog reset value is 10 minutes */
        /* Put this value to 70 sec and temperature read rutine called at every 60 sec */
        reloadValue = Watchdog_convertMsToTicks(watchdogHandle, 70*1000);
        /*
         * A value of zero (0) indicates the converted value exceeds 32 bits
         * OR that the API is not applicable for this specific device.
         */
        if (reloadValue != 0) 
        {
            Watchdog_setReload(watchdogHandle, reloadValue);
        }
    }
    /* ----------------------------------------------------------------------- */
    /*
     *  ======== watchdogCallback ========
     */
    void watchdogCallback(uintptr_t watchdogHandle_p)
    {
      /*
       * If the Watchdog Non-Maskable Interrupt (NMI) is called,
       * loop until the device resets. Some devices will invoke
       * this callback upon watchdog expiration while others will
       * reset. See the device specific watchdog driver documentation
       * for your device.
       */
    //  Lcd_AllOff_g();
    //  Display_UpdateGuidingArea1_g("WATCHDOG EXPIRE", 0);
    //  Lcd_Update_g( );
    //  Task_sleep(1000*100);  
      
    #ifdef  cTestWatchDogRst
      #include "SmlUtil.h"
      tUI8 aBuffer[ 16u ];
      tUI32 PresentRstCnt;
      Flash_GetData( eFlashMfgSr, aBuffer );
      PresentRstCnt = UTIL_StrToInt( aBuffer );
      PresentRstCnt++;
      UTIL_MemSet( aBuffer, 0x30, 16u ); /* Making all zero */
      UTIL_IntToStr( PresentRstCnt, aBuffer );
      Flash_WriteData( eFlashMfgSr, 8u, aBuffer );
    #endif
      while (1) {}
    }
    
    /* ----------------------------------------------------------------------- */
    void PTD_FeedWatchDog( void )
    {
      Watchdog_clear(watchdogHandle);
    }
    #else
    /* Dummy methods */
    void PTD_FeedWatchDog( void )
    {
    }
    void PTD_InitWatchDog( void )
    {
    }  
    #endif
    
    tUI8 PTD_GetSleepStatus( void )
    {
      return (IsDeviceInSleep );
    }
    
    /* *********************************************************************** */
    #if ChangeHistory
    /* 
    $Log$
    */
    #endif
    /* End =================================================================== */
    
    /** @file           Production.c
    *   @copyright      Copyright (c) 2016 Secure International Holdings Pte. Ltd.
    *   @author         Written by: Jagdish Kushwaha
    *   @date           Started on:  14/04/2020
    *   @brief          This file will perform Production test support over UART  
    */
    /* *********************************************************************** */
    /* included files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/UART.h>
    #include "HDCSensor.h"
    #include "Production.h"
    #include "Typedef.h"
    #include "Flash.h"
    #include "icall.h"
    #include <ti/drivers/PIN.h>
    #include "ti_drivers_config.h"
    #include "Keypad.h"
    #include "SmlUtil.h"
    #include "multi_role.h"
    #include "LCD.h"
    #include "BattRead.h"
    #include "DisplayLCD.h"
    #include <driverlib/aon_batmon.h>
    #include "UtilCrcChkSum.h"
    #include "data.h"
    #include "PTDTimer.h"
    #include "UtilCrcChksum.h"
    #include "PTDScreen.h"
    /* Macros ---------------------------------------------------------------- */
    
    #define cUARTBufSize                  (64u)
    
    /* Private typedef ------------------------------------------------------- */
    /**
     * MLP command structure
     */
    typedef struct
    {
      tUI16 InfoFieldLen;
      tUI8 u8_Part;
      tUI8 InfoFieldType;
      tUI8 PartRxDataPtr[ cUARTBufSize ];
      tUI32 u32_Tmr;    /* Interbyte Timeout */
    } t_MlpHdr;
    
    /**
     * Message type
     */
    typedef enum
    {
      eProtocolCtrlMsg,
      eOperationalMsg,
      eApplicationMsg,
      eZclMsg,
      eDlmsMsg
    } tMlpMsgType;
    
    /* Constants Variables --------------------------------------------------- */
    
    /* Private variables ----------------------------------------------------- */
    tUI8 aOutBuff[ cUARTBufSize ] = { 0x00 };
    static tUI8 aUart1RxData[ cUARTBufSize ];
    static tUI8 KeyEnable[ cNumOfKeys ];
    static tUI8 KeyCount[ cNumOfKeys ];
    static tUI8 aMasterMac[ cMACLen ];
    UART_Handle UARTHandler;
    t_MlpHdr MlpHdr;
    tUI32 nProductionTick;
    tUI32 nRoundTripTick;
    static tUI8 RoundTripRspWait;
    static tUI8 RoundTripRspRcvd;
    /* Private functions ----------------------------------------------------- */
    /**
      Function to send MLP response
      @param    aBuff_p   Response buffer
      @param    nLen_p    Buffer length
    */
    static void MlpSendData( 
      tUI8 aBuff_p[ ], 
      tUI16 Len_p );
    /* ----------------------------------------------------------------------- */
    /**
      Function to add MLP header to command
      @param    aBuff_p   Data buffer
      @param    Len_p     Buffer length
      @param    Type_p    Command type
      @param    Part_p    Part number
    */
    static void MlpPutHdr( 
      tUI8 aBuff_p[ ],
      tUI16 Len_p, 
      tUI8 Type_p, 
      tUI8 Part_p );
    /* ----------------------------------------------------------------------- */
    /**
      Function to verify MLP frame
      @param    nMsgLen_p
      @return   cTrue, cFalse
    */
    static tUI8 MlpGetFrameStatus( tUI16 nMsgLen_p );
    /* ----------------------------------------------------------------------- */
    /**
      Function to send NACK
    */
    static void MlpMsgNack( void );
    /* ----------------------------------------------------------------------- */
    /**
      Enable key for production 
      @param    iKey_p   Key number
    */
    static void Production_ConfigKeyTest( tUI8 iKey_p );
    /* ----------------------------------------------------------------------- */
    /**
      Key press counter
      @param    iKey_p   Key number
    */
    static tUI8 Production_GetKeyPressCount( 
      tUI8 iKey_p, 
      tUI8 aBuff_p[ ] );
    /* ----------------------------------------------------------------------- */
    /**
      Read keypad in production mode
    */
    static void Production_ReadKeypad( void );
    /* ----------------------------------------------------------------------- */
    /**
      Function to handle uart command
      @return cTrue - Go to sleep, cFalse - Waiting for another command
    */
    static tUI8 MlpProcOperationalMsg ( void );
    /* ----------------------------------------------------------------------- */
    /**
      Awaiting round trip command response from other device
    */
    static void Production_AwaitingRoundTripResponse( void );
    /* ----------------------------------------------------------------------- */
    #ifdef cConfigChngByUart
    /* ----------------------------------------------------------------------- */
    void Production_Parse_BleCnfgParams( tUI8 aDataBuf_p[ ] );
    /* ----------------------------------------------------------------------- */
    void Production_AddWhiteLst( tUI8 aDataBuf_p[ ] );
    /* ----------------------------------------------------------------------- */
    void Production_ClearWhiteLst( void );
    #endif
    /* ======================================================================= */
    void Production_TaskInit_g( void )
    {
      UART_Params UARTParam;
    
      UART_init();
      UART_Params_init( &UARTParam );
      UARTParam.writeDataMode = UART_DATA_BINARY;
      UARTParam.readDataMode = UART_DATA_BINARY;
      UARTParam.readReturnMode = UART_RETURN_FULL;
      UARTParam.readEcho = UART_ECHO_OFF;
      UARTParam.baudRate = 115200uL;
      UARTParam.readTimeout = 1uL;
      UARTHandler = UART_open( CONFIG_DISPLAY_UART, &UARTParam );
    
      if ( UARTHandler == NULL )
      {
        PTD_ASSERT(15);
      }
      nProductionTick = Timer_GetTick_g( );
      RoundTripRspWait = cFalse;
    #ifdef cPtdDebug
      UART_write(UARTHandler, "Hello", 5u);
    #endif
    }
    /* ----------------------------------------------------------------------- */
    tUI8 Production_TaskRun_g( void )
    {
      tUI8 GoToSleep = cFalse; 
      tUI16 nReadByteCnt; 
      
      nReadByteCnt = UART_read( UARTHandler, &MlpHdr.PartRxDataPtr, cUARTBufSize );
      if( nReadByteCnt )      
      {
        nProductionTick = Timer_GetTick_g( );
        if( cTrue == MlpGetFrameStatus( nReadByteCnt ) )
        {
          GoToSleep = MlpProcOperationalMsg( );
        }
        else
        {
          MlpMsgNack( );
        }
      }
      else{}
    #if !defined cAlwaysProductionMode  
      if( Timer_IsOver_g( nProductionTick, cProductionTimeout ) )
      {
        nProductionTick = Timer_GetTick_g( );
        GoToSleep = cTrue;
      }
      else{}
    #endif  
      Production_ReadKeypad( );
      Production_AwaitingRoundTripResponse( );  
      return GoToSleep;
    }
    /* ----------------------------------------------------------------------- */
    void Production_Sleep_g( void )
    {
      UART_readCancel( UARTHandler );
      UART_close( UARTHandler );
    }
    /* ----------------------------------------------------------------------- */
    static tUI8 MlpProcOperationalMsg( void )
    {
      tUI8 Status = cFalse;
      tUI8 nMsgLen = 0u;
      tUI8 SerialData[ 18u ];
      
      aOutBuff[ 4u ] = aUart1RxData[ 0u ];
      aOutBuff[ 5u ] = aUart1RxData[ 1u ];
      switch( aUart1RxData[ 0u ] ) /* Cmd Type */
      {
        case 0x0Cu: /* Memory Write/Read Cmd */
          switch( aUart1RxData[ 1u ] )
          {
            case 0x04u: /* Read customer serial number */
              if( cTrue == Flash_GetData( eFlashMfgSr, &aOutBuff[ 6u ] ))
              {
                nMsgLen = cSrNumLen;
              }
              else
              {
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Address size Error */
                nMsgLen = 2u;
              }		  
              break;
            case 0x03u: /* Read Manufacture serial number */
              if( cTrue == Flash_GetData( eFlashCCASr, &aOutBuff[ 6u ] ))
              {
                nMsgLen = cSrNumLen;
              }
              else
              {
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Address size Error */
                nMsgLen = 2u;						
              }	
              break;
            case 0x05u: /* Write Manufacture serial number */
              
              Flash_WriteData( eFlashCCASr, 8u, &aUart1RxData[ 2u ] );
              if( cTrue == Flash_GetData( eFlashCCASr, /*(tUI8*)&*/SerialData ) )
              {
                nMsgLen = cSrNumLen;
                UTIL_MemCpy( &aOutBuff[ 6u ], SerialData, nMsgLen );
              }
              else
              {
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Address size Error */
                nMsgLen = 2u;										
              }
              break;
            case 0x06u: /* Write customer serial number */
              Flash_WriteData( eFlashMfgSr, 8u, &aUart1RxData[ 2u ] );
              if( cTrue == Flash_GetData( eFlashMfgSr, SerialData ) )
              {
                nMsgLen = cSrNumLen;
                UTIL_MemCpy( &aOutBuff[ 6u ], SerialData, nMsgLen );
              }
              else
              {
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Address size Error */
                nMsgLen = 2u;										
              }
              break;
            case 0x07u: /* Read MAC address */
              BLE_GetMac_g( &aOutBuff[ 6u ] );
              nMsgLen = cMACLen;
              break;
            default:
              aOutBuff[ 6u ] = 0xFF; /* Error */
              aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
              nMsgLen = 2u;
              break;
          }
          break;
        case 0x80: 
          switch( aUart1RxData[ 1u ] )
          {
            case 0x00: /* Get PTD Firmware version */
              nMsgLen = UTIL_ConstStrLen(cPtdFwVersion);
              UTIL_MemCpy( &aOutBuff[ 6u ], cPtdFwVersion, nMsgLen );
              break;
    /* JAG This for external flash test not required for PTD */          
    //        case 0x89:/* Flash test, Read MAC ID and serial number */
    //          BLE_GetMac_g( &aOutBuff[ 7u ] );
    //          nMsgLen = cMACLen;
    //          if( cTrue == Flash_GetData( eFlashCCASr, &aOutBuff[ 6u + nMsgLen ] ))
    //          {
    //            nMsgLen += cSrNumLen;
    //          }
    //          else
    //          {
    //            aOutBuff[ 6u ] = 0xFF;
    //            aOutBuff[ 7u ] = 0xFF; /* Address size Error */
    //            nMsgLen = 2u;						
    //          }
    //          break;
    
            case 0x01: /* Read Battery Voltage */
              nMsgLen = ADC_ReadBatt_g(&aOutBuff[ 6u ]);
              break;
    
            case 0x02: /* Put PTD in deep sleep */
              aOutBuff[ 6u ] = 0x00;
              nMsgLen = 1u;
              Status = cTrue;
              break;
              
            case 0x03:/* Read HW type */
              aOutBuff[ 6u ] = 0x37;
              nMsgLen = 1u;
              break;
              
            case 0x8D:/* Read temperature and humidity */
              nMsgLen = HDC_TrigAndRead_g( &aOutBuff[ 6u ]);
              break;
            case 0x94:/* Display Test  */
              aOutBuff[ 6u ] = 0x00;
              nMsgLen = 1u;          
              switch( aUart1RxData[ 2u ] )
              {
                case 0x00: /* Display Off  */
                  Lcd_AllOff_g( );
                  Lcd_Update_g( );		  
                  break;          
                case 0x01: /* Display all On  */
                  Lcd_AllOn_g( );
                  Lcd_Update_g( );		  
                  break;          
                case 0x02: /* Display Even On  */
                  Lcd_EvenOn_g( );
                  Lcd_Update_g( );		  
                  break;          
                case 0x03: /* Display Odd On  */
                  Lcd_OddOn_g( );
                  Lcd_Update_g( );		  
                  break;
                default: 
                  aOutBuff[ 6u ] = 0xFF; /* Error */
                  aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
                  nMsgLen = 2u;			  
                  break;
              }
              break;
            case 0x95:/* Turn on/off backlight */
              if( aUart1RxData[ 2u ] == 0x00 )
              {
                GPIO_write(BACKLIT_PIN, cBackLitOff ); /* backlight */
                aOutBuff[ 6u ] = 0x00;
                nMsgLen = 1u;
              }
              else if( aUart1RxData[ 2u ] == 0xFF )
              {
                GPIO_write(BACKLIT_PIN, cBackLitOn ); /* backlight */
                aOutBuff[ 6u ] = 0x00;
                nMsgLen = 1u;
              }		  
              else
              {	
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
                nMsgLen = 2u;			  
              }		
              break;
            case 0x96:/* Perform round trip test */
              UTIL_MemCpy( aMasterMac, &aUart1RxData[ 2u ], cMACLen );
              RoundTripRspWait = cTrue;
              RoundTripRspRcvd = cFalse;
              nRoundTripTick = Timer_GetTick_g( );
              Ble_SendRoundTripCmd_g(aMasterMac);
              break;
              
            case 0x98:/* Start Button test */
              if( (( aUart1RxData[ 2u ] <= cNumOfKeys ) &&
                   ( aUart1RxData[ 2u ] > 0u ))         || 
                  ( aUart1RxData[ 2u ] == 0xFF ))
              {
                /* Start Key test here */
                Production_ConfigKeyTest(  aUart1RxData[ 2u ] );
                aOutBuff[ 6u ] = 0x00;
                nMsgLen = 1u;
              }
              else
              {
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
                nMsgLen = 2u;			  
              }
              break;
            case 0x99:/* Read button press count */
              if( (( aUart1RxData[ 2u ] <= cNumOfKeys ) &&
                   ( aUart1RxData[ 2u ] > 0u ))         || 
                  ( aUart1RxData[ 2u ] == 0xFF ))
              {            
                nMsgLen = Production_GetKeyPressCount( aUart1RxData[ 2u ],
                                 &aOutBuff[ 6u ]);
              }
              else
              {
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
                nMsgLen = 2u;			  
              }		  
              break;   
    
    #ifdef cConfigChngByUart
            case 0x9A: /* Put PTD in deep sleep */
              aOutBuff[ 6u ] = 0x00;
              nMsgLen = 1u;
              Production_Parse_BleCnfgParams( &aUart1RxData[ 2u ] );
              break;
              
            case 0x9B: /* Add White list  */
              aOutBuff[ 6u ] = 0x00;
              nMsgLen = 1u;
              Production_AddWhiteLst( &aUart1RxData[ 2u ] );
              break;          
    
            case 0x9C: /* Add White list  */
              aOutBuff[ 6u ] = 0x00;
              nMsgLen = 1u;
              Production_ClearWhiteLst( );
              break;                    
    #endif
            default:
              aOutBuff[ 6u ] = 0xFF; /* Error */
              aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
              nMsgLen = 2u;
              break;
          }
          break;
          
        default:    /* unknown command */
          aOutBuff[ 6u ] = 0xFF; /* Error */
          aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
          nMsgLen = 2u;
          break;
      }
      if( nMsgLen != 0u)
      {  
        nMsgLen += 2u; /* +Command length of 2 bytes */
        MlpSendData( aOutBuff, nMsgLen);
      }else{}  
      return( Status );
    }
    /* ----------------------------------------------------------------------- */
    static void MlpMsgNack( void )
    {
      tUI8 aOutBuff[ 8u ];
      tUI8 nMsgLen = 0u;
      
      aOutBuff[ 4u ] = 0xFF; /* Error */
      aOutBuff[ 5u ] = 0xFF; /* Unsuported command */
      nMsgLen = 2u;
      
      MlpSendData( aOutBuff, nMsgLen );
    }
    /* ----------------------------------------------------------------------- */
    static tUI8 MlpGetFrameStatus( tUI16 nMsgLen_p )
    {
      tUI8 u8_Temp;
        
      /* 2  bytes  will contain the length of frame */
      MlpHdr.InfoFieldLen = UTIL_ConvLiToU16( MlpHdr.PartRxDataPtr );
      u8_Temp = (tUI8)(MlpHdr.InfoFieldLen & 0x001F);
      MlpHdr.InfoFieldLen = (((MlpHdr.InfoFieldLen & 0xFF00) >> 3) | u8_Temp);
      /* Get field type */ 
      MlpHdr.InfoFieldType = MlpHdr.PartRxDataPtr[ 2u ];
      /* Get received part number */
      MlpHdr.u8_Part = MlpHdr.PartRxDataPtr[ 3u ];
    
      if(0 == ESL_CRC_CalcV41( 0u, MlpHdr.PartRxDataPtr,  nMsgLen_p ) )
      {
        UTIL_MemCpy( &aUart1RxData[ 0u ], &MlpHdr.PartRxDataPtr[ 4u ], 
        (MlpHdr.InfoFieldLen + 1u) );
        //nRxIdx += ( MlpHdr.InfoFieldLen + 1u );
      }
      else
      {
        return cFalse;
      }
      return cTrue;
    }
    /* ----------------------------------------------------------------------- */
    static void MlpSendData( 
      tUI8 aBuff_p[ ], 
      tUI16 nLen_p )
    { 
      tUI16 Crc = 0;
      /* Adding MLP header to command */
      MlpPutHdr( aBuff_p, (tUI16)nLen_p, eOperationalMsg, 0u );
      nLen_p += 4; /* Adding header length */
      Crc = ESL_CRC_CalcV41( Crc, aBuff_p, nLen_p );
      UTIL_ConvU16ToBi( Crc, &aBuff_p[ nLen_p ] );
      nLen_p += 2u;
      
      UART_write(UARTHandler, aBuff_p, nLen_p);
    }
    /* ----------------------------------------------------------------------- */
    static void MlpPutHdr( 
      tUI8 aBuff_p[ ],
      tUI16 Len_p, 
      tUI8 Type_p, 
      tUI8 Part_p )
    {	/* Clear Buffer */
      tUI8 Temp;
    	
      Len_p -= 1u;
    	
      Temp = (tUI8)(Len_p & 0x001Fu);
      Len_p = ( ((Len_p << 3u) & 0xFF00u) | Temp );
      /* Put Length */
      UTIL_ConvU16ToLi( Len_p, aBuff_p );
      /* Put Type */
      aBuff_p[ 2u ]= Type_p;
      /* Put Part Number */
      aBuff_p[ 3u ]= Part_p;
    }
    /* ----------------------------------------------------------------------- */
    static void Production_ConfigKeyTest( tUI8 iKey_p )
    {
      tUI8 iIndex = 0u;
      
      UTIL_MemSet(KeyEnable, 0x00, sizeof(KeyEnable));
      if( iKey_p == 0xFF )
      {
        while( iIndex < cNumOfKeys )
        {
          KeyEnable[ iIndex ] = cTrue;
          KeyCount[ iIndex ] = 0u;
          iIndex++;
        }
      }
      else
      {
        iKey_p--; /* Reducing index */
        KeyEnable[ iKey_p ] = cTrue;
        KeyCount[ iKey_p ] = 0u;
      }
    }
    /* ----------------------------------------------------------------------- */
    static tUI8 Production_GetKeyPressCount( 
      tUI8 iKey_p, 
      tUI8 aBuff_p[ ] )
    {
      tUI8 iIndex = 0u;
      tUI8 iKeyCnt = 0u;
      if( iKey_p == 0xFF )
      {
        while( iKeyCnt < cNumOfKeys )
        {
          aBuff_p[iIndex++] = iKeyCnt + 1u;
          aBuff_p[iIndex++] = KeyCount[ iKeyCnt ];
          iKeyCnt++;
        }
      }
      else
      {
        aBuff_p[iIndex++] = iKey_p;
        aBuff_p[iIndex++] = KeyCount[ iKey_p - 1u ];
      }
      return iIndex;
    }
    /* ----------------------------------------------------------------------- */
    static void Production_ReadKeypad( void )
    {
      tUI8 Index = 0u;
      while( Index < cNumOfKeys )
      {
        if( KeyEnable[ Index] == cTrue )
        {
          if( Keypad_GetEvent_g( Index ) != eKeyEvent_NotPressed )
          {
            KeyCount[ Index ]++;
          }
          else{}
        }
        Index++;
      }
    }
    /* ----------------------------------------------------------------------- */
    void Production_Chk_RoundTrip_g( tUI8 aDataBuf_p[ ] )
    {
      tUI8 aSerialNo[ cSrNumLen ];
      tUI8 nDataIdx;
      /* Check Master Mac */
      if(UTIL_MemCmp( aMasterMac, aDataBuf_p, cMACLen ) == 0 )
      {
        nDataIdx = cOffset_PayloadStart - cOffset_SrcMacAddress;
        /* Check round trip responce */
        if( aDataBuf_p[ nDataIdx++ ] == 0x01u )
        {  
          /* Get Dut Serial Number */
          Flash_GetData( eFlashMfgSr, aSerialNo);
          /* Check Dut Serial number */
          if(UTIL_MemCmp( aSerialNo, &aDataBuf_p[ nDataIdx ], cSrNumLen ) == 0 )
          {
            RoundTripRspRcvd = cTrue;
          }else{}  
        }else{PTD_ASSERT(16);}  
      }else{}  
    }
    /* ----------------------------------------------------------------------- */
    static void Production_AwaitingRoundTripResponse( void )
    {
      tUI8 aOutBuff[ 12u ];
      if ( RoundTripRspWait == cTrue )
      {
        aOutBuff[ 4u ] = 0x80; /* Round Trip Command */
        aOutBuff[ 5u ] = 0x96;
        if ( RoundTripRspRcvd == cTrue )
        {
          aOutBuff[ 6u ] = 0x00; /* Sucess */
          aOutBuff[ 7u ] = GetRSSI( ); /* Received Packet RSSI value */
          RoundTripRspWait = cFalse;
          MlpSendData( aOutBuff, 4u );  
        }
        else if( Timer_IsOver_g( nRoundTripTick, cRoundTripResponseTimeout ) )
        {
          aOutBuff[ 6u ] = 0xFF; /* Error */
          RoundTripRspWait = cFalse;
          MlpSendData( aOutBuff, 3u );  
        }else{}
      }else{}
    }
    /* ----------------------------------------------------------------------- */
    #ifdef cConfigChngByUart
    #include "gap_scanner.h"
    #include <ti/sysbios/knl/Task.h>
    /* Test Command */
    /*
    Minimum interval  2 Bytes  (n * 0.625 ms)
    maximum interval  2 Bytes  (n * 0.625 ms)
    Advertise type    1 byte   USE_DURATION 0 or USE_MAX_EVENTS 1 
    Advertise value   2 bytes  Duration ( in mS)  or max event 
    Scane type        1 bype   PASSIVE 0u or ACTIVE 1
    Scan Interval     2 bytes  (n * 0.625 ms)
    Scan Window       2 bytes  (n * 0.625 ms)    
    
    809A 01020120000A0B000C0D0A0F 
    809A 00A000B000044C0002300210
    */          
    
    tUI16 nMinInterval = 160u;
    tUI16 nMaxInterval = 176u;
    tUI8 nAdvType = 0; /* USE_DURATION 0 or USE_MAX_EVENTS 1 */
    tUI16 nAdvValue = 1100u ; /* Duration in mS or Max Event count  */
    tUI8 nScanType = SCAN_TYPE_PASSIVE; /* PASSIVE 0u or ACTIVE 1 */
    tUI16 nScanInterval = SCAN_PARAM_DFLT_INTERVAL;
    tUI16 nScanWindow = SCAN_PARAM_DFLT_WINDOW;
    
    void Production_Parse_BleCnfgParams( 
      tUI8 aDataBuf_p[ ] )
    {
      tUI8 iIdx = 0u;  
      
      nMinInterval   = UTIL_ConvBiToU16(&aDataBuf_p[iIdx]);
      iIdx += 2;
      nMaxInterval   = UTIL_ConvBiToU16(&aDataBuf_p[iIdx]);
      iIdx += 2;  
      nAdvType       = aDataBuf_p[iIdx];
      iIdx += 1;
      nAdvValue      = UTIL_ConvBiToU16(&aDataBuf_p[iIdx]);
      iIdx += 2;
      nScanType      = aDataBuf_p[iIdx];
      iIdx += 1;
      nScanInterval  = UTIL_ConvBiToU16(&aDataBuf_p[iIdx]);
      iIdx += 2;
      nScanWindow    = UTIL_ConvBiToU16(&aDataBuf_p[iIdx]);
      iIdx += 2;  
    }
    /* ----------------------------------------------------------------------- */
    tUI8 NoOfWhiteLstEntry = 0;
    tUI8 WhiteLstMac [cMACLen * 4 ]; /* Add filter of max 4 Mac */
    
    tUI8 TotalWhiteLstEntry = 0;
    tUI8 WhiteLstMacAdd [cMACLen ]; /* Add filter of max 4 Mac */
    tUI8 temp8;
    
    /*
    aDataBuf_p  6 Bytes  MacAddress
    */          
    void Production_AddWhiteLst( tUI8 aDataBuf_p[ ] )                             
    {
      tUI8 status;
    /*TODOJAG Needs to enter white list variable in global array */  
    //  temp8 = SCAN_FLT_POLICY_ALL;
    //  status = GapScan_setParam(SCAN_PARAM_FLT_POLICY, &temp8);
    
    //  status = HCI_LE_ClearWhiteListCmd();
      
      UTIL_MemCpy(WhiteLstMacAdd, aDataBuf_p, cMACLen );
      status = HCI_LE_AddWhiteListCmd(HCI_PUBLIC_DEVICE_ADDRESS, WhiteLstMacAdd);  
    //  TotalWhiteLstEntry++;
      temp8 = SCAN_FLT_POLICY_WL;
    //  temp8 = SCAN_FLT_POLICY_WL_RPA;
      status = GapScan_setParam(SCAN_PARAM_FLT_POLICY, &temp8);  
      BLE_DisableScan_g();  
      BLE_EnableScan_g();
      
      /* Add entry */
    //  if( aDataBuf_p[ 0u ] == 1 )
    //  {  
    //    if( NoOfWhiteLstEntry <= 4 )
    //    {
    //      UTIL_MemCpy( &WhiteLstMac[NoOfWhiteLstEntry * cMACLen ], &aDataBuf_p[ 1u ], cMACLen );  
    //      NoOfWhiteLstEntry++;
    //    }  
    //  }
    //  else /* Remove entry */
    //  {
    //    NoOfWhiteLstEntry = 0u;
    //  }  
    }
    /* ----------------------------------------------------------------------- */
    void Production_ClearWhiteLst( void )                             
    {
      tUI8 status;
      BLE_DisableScan_g();  
       status = HCI_LE_ClearWhiteListCmd();
       BLE_EnableScan_g();
    }  
    #endif
    /* ----------------------------------------------------------------------- */
    #ifdef cDebugUartEnable
    void Production_SendUartLog_g( 
      tUI8 nDataLen_p, 
      tUI8 aDataBuff_p[ ] )
    {
      tUI8 aBuf_p[512u ];
      tUI16 index;
      for(index = 0u; index < nDataLen_p; index++)
      {
        UTIL_CnvrtHexToAscii( aDataBuff_p[index ], &aBuf_p[index * 2] );
      }  
      aBuf_p[index * 2] = 0x0D;
      UART_write(UARTHandler, aBuf_p, (nDataLen_p * 2u) + 1u);
    }
    /* ----------------------------------------------------------------------- */
    void DebugPrint_g( 
      tUI8 aString[ ], 
      tUI8 nCode_p )
    {
      tUI8 aBuf_p[16u ];
      tUI8 nLen;
      tUI8 aUrtBuf_p[32u ];
      UTIL_MemSet( aBuf_p, 0u, 16u );
      UTIL_MemSet( aUrtBuf_p, 0u, 32u );
      UTIL_ConstStrCpy(aUrtBuf_p, aString);
      UTIL_CnvrtHexToAscii( nCode_p, aBuf_p );
    //  UTIL_IntToStr( (tUI32)nCode_p, aBuf_p );
      UTIL_ConstStrCat(aUrtBuf_p,aBuf_p);
      nLen = UTIL_ConstStrLen(aUrtBuf_p);
      UART_write(UARTHandler, aUrtBuf_p, nLen);
      aUrtBuf_p[0] = 0x0Du;
      UART_write(UARTHandler, aUrtBuf_p, 1u);
    //  if(nCode_p != 0 )
    //  {
    //    PTD_ASSERT(0xB1);
    //  }  
    }
    #else
    void Production_SendUartLog_g( 
      tUI8 nDataLen_p, 
      tUI8 aDataBuff_p[ ] )
    {
      /* Dummy method */
    }
    
    void DebugPrint_g( 
      tUI8 aString[ ], 
      tUI8 nCode_p )
    {
    //  if(nCode_p != 0 )
    //  {
    //    PTD_ASSERT(0xB1);
    //  }  
      /* Dummy method */
    }  
    #endif
    /* *********************************************************************** */
    #ifdef ChangeHistory
    
    #endif
    /* End =================================================================== */
    

  • Hi Marie,

    This a new observation 

    In long run test I observe, that one current peak is coming at around every 15 minutes, it does not increase my sleep current much, but I want to know why it is coming.

    It does come in debug mode too. I kept break point in below code of "Multi_role.c" file but my code does not come at the break point. It looks like stack is doing some activity. I just want to know what is this and is this normal.

    static void multi_role_taskFxn(UArg a0, UArg a1)
    {
    // Initialize application
    multi_role_init();
    for (;;)
    {
    uint32_t events;
    PTD_FeedWatchDog();
    // Waits for an event to be posted associated with the calling thread.
    // Note that an event associated with a thread is posted when a
    // message is queued to the message receive queue of the thread
    events = Event_pend(syncEvent, Event_Id_NONE, MR_ALL_EVENTS,
    ICALL_TIMEOUT_FOREVER);

    if (events)  I kept break point here.
    {

    Please find code file from drop box 

  • Hi Marie,

    Can you please send me API again that put device in shutdown mode. Can you please also share some document that help to understand How this works and what is not allowed in this mode.

    You told in our last meeting, in shutdown mode clock interrupts does not work. I want to use this mode for keeping our product in warehouse, and I want my device to come out from this when my device is hard reset by giving reset pulse to CC1352P's reset pin, otherwise it stays in shutdown mode. for this I will kept my button interrupt disabled, it will only enabled when my device restart. 

  • Hi Jai,

    1. I think the reason why you are not receiving UART when you are not setting the constraint is that the readTimeout value is too low. From Production.c line 158:

    UARTParam.readTimeout = 1uL;

    This parameter describes how long from the UART_read call the driver will poll the Rx line. Since you have set it to 1 it will time out almost immediately after you call UART_read. When is the UART message coming? E.g. if you know it's coming about 100 ms after UART_read is called, it could be good to set the readTimeout to 200 ms just to be sure.

    Please also note that if you send the device to sleep while waiting for a UART message the wake-up process may take too long so that the device is not able to receive the UART message.

    2. Shutdown mode:

    The API is Power_shutdown().

    You can see an example for how to use it in the pinShutdown example:

    For waking up from shutdown you need a hardware input, e.g. toggle pin, press a button.

    In your case I understood you have a clock interrupt (software interrupt) which needs to wake up the application. This is not possible when the device is in shutdown.

  • Hi Marie,

    Thanks for your reply it make sense,

    Do you think setting constraint is not a good idea for UART and I have to make changes in my code, or this is OK and I can keep it as it is?

    I have one more requirements, I want to disable button interrupt in some situation, for this I am using method "Keypad_DisableInt" of attached file.

    in this I am disabling wake up and interrupts on all button.

    I observed that even after disabling interrupt when I press button, interrupt comes and my callback "Keypad_KeyPressCallback" comes, this I have checked in debug mode.

    Is it OK, if I am performing interrupt disabling operation, from another interrupts service rutine ? in this code I am doing this from my clock ISR.

    can you please review below code of attached file and let me know if I have missed something.

    /* .c file Template
    Copyright (c) 2020 Secure International Holdings Pte. Ltd.
    
    File name:   Keypad.c
    Written by:  JagdishK/Kamlesh Parihar
    Started on:  05/04/2020
    
    $Header$
    
    Description: Module to perform key scanning and read status 
    */
    /* *********************************************************************** */
    /* included files */
    #include "keypad.h"
    #include "Typedef.h"
    #include "ti_drivers_config.h"
    #include "util.h"
    #include <ti/drivers/GPIO.h>
    #include "multi_role.h"
    #include "PTDScreen.h"
    #include <ti/sysbios/family/arm/m3/Hwi.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    #include "LCD.h"
    #include "Commissioning.h"
    #include "Ble.h"
    #include "PTD_main.h"
    /* ======================================================================= */
    
    /* #defines */
    /* ----------------------------------------------------------------------- */
    
    /* type definitions */
    typedef struct
    {
      tUI8 KeypadState;
      tKeyEventType KeyEventType[ cNumOfKeys ];
    }tKeyInfo;
    
    /* ----------------------------------------------------------------------- */
    
    /* definitions of static (local) variables */
    static tKeyInfo KeyInfo;
    
    // Key pullup enable clock
    static Clock_Struct keyPullEnableClock;
    
    // Key debounce clock
    static Clock_Struct keyChangeClock;
    
    // Memory for the GPIO module to construct a Hwi
    Hwi_Struct callbackHwiKeys;
    
    // PIN configuration structure to set all KEY pins as inputs with pullups enabled
    /*TODOJAG disable pullups in these keys PIN_NOPULL for saving current consumption */
    PIN_Config keyPinsCfg[] =
    {
        CONFIG_PIN_BTN1   | PIN_GPIO_OUTPUT_DIS  | PIN_INPUT_EN  |  PIN_NOPULL,
        CONFIG_PIN_BTN2   | PIN_GPIO_OUTPUT_DIS  | PIN_INPUT_EN  |  PIN_NOPULL,
        CONFIG_PIN_0      | PIN_GPIO_OUTPUT_DIS  | PIN_INPUT_EN  |  PIN_NOPULL,
        CONFIG_PIN_4      | PIN_GPIO_OUTPUT_DIS  | PIN_INPUT_EN  |  PIN_NOPULL,
        PIN_TERMINATE
    };
    
    PIN_State  keyPins;
    PIN_Handle hKeyPins;
    
    /* ----------------------------------------------------------------------- */
    
    /* definitions of external (global)variables(Use of global is Not recommended)*/
    
    /* ----------------------------------------------------------------------- */
    
    /* definitions of constant data tables */
    const tUI8 ckeyIds[ cNumOfKeys ] = {CONFIG_PIN_BTN1,
                                        CONFIG_PIN_BTN2,
                                        CONFIG_PIN_0,
                                        CONFIG_PIN_4,
                                        };
    /* ----------------------------------------------------------------------- */
    
    /* prototypes of local (static) functions */
    static void Keypad_PullEnableHandler(UArg a0);
    void Keypad_Disable( void );
    void Keypad_Init( void );
    void Keypad_Scan( void );
    void Keypad_DisableInt(void);
    void Keypad_EnableInt(void);
    static void Keypad_keyPollHandler(UArg a0);
    static void Keypad_KeyPressCallback(PIN_Handle hPin, PIN_Id pinId);
    /* ======================================================================= */
    /**
      Function to return Initialize keypad module 
      @param  void
    */
    void Keypad_Init( void )
    {
      tUI8 iKeyId = 0;
      while( iKeyId < (tUI8)cNumOfKeys )
      {
        KeyInfo.KeyEventType[ iKeyId ] = eKeyEvent_NotPressed;
        iKeyId++;
      }
      /* Enable Key Pad pullup Vcc */
      GPIO_write(BTN_PULLUP_CNTRL, cKeyPullupEnable);
      KeyInfo.KeypadState = cEnable;
    }
    /* -----------------------------------------------------------------------
     * @fn      Keypad_GetEvent_g
     *
     * @brief   Read key press events  
     *
     * @param   Key Id for getting events 
     *
     * @return  tKeyEventType key pad events 
     */
    tKeyEventType Keypad_GetEvent_g( tUI8 iKeyNum_p )
    {
      tKeyEventType PreviousEvent;
      if(cKey_ClearAllEvt == iKeyNum_p )
      { /* Clear all key events */ 
        KeyInfo.KeyEventType[ 0u ] = eKeyEvent_NotPressed;
        KeyInfo.KeyEventType[ 1u ] = eKeyEvent_NotPressed;
        KeyInfo.KeyEventType[ 2u ] = eKeyEvent_NotPressed;
        KeyInfo.KeyEventType[ 3u ] = eKeyEvent_NotPressed;
      }
      else
      {  
        PreviousEvent = KeyInfo.KeyEventType[ iKeyNum_p ];
        KeyInfo.KeyEventType[ iKeyNum_p ] = eKeyEvent_NotPressed;
    //    KeyInfo.KeyEventType[ 0u ] = eKeyEvent_NotPressed;
    //    KeyInfo.KeyEventType[ 1u ] = eKeyEvent_NotPressed;
    //    KeyInfo.KeyEventType[ 2u ] = eKeyEvent_NotPressed;
    //    KeyInfo.KeyEventType[ 3u ] = eKeyEvent_NotPressed;
      }    
      return PreviousEvent;
    }
    /* ----------------------------------------------------------------------- */
    tUI8 Keypad_IsKeyPressed_g( void )
    {
      tUI8 iKeyId;
      tUI8 IsKeyPressed = cFalse;
      for(iKeyId = 0u; iKeyId < cNumOfKeys; iKeyId++)
      {
        if(KeyInfo.KeyEventType[iKeyId] != eKeyEvent_NotPressed)
        {
          IsKeyPressed = cTrue;
          break;
        }  
      }
    return(IsKeyPressed);  
    }
    /* ----------------------------------------------------------------------- */
    /**
      Perform keypad scanning 
      @param  void
    */
    void Keypad_Scan( void )
    {
      static tUI16 aKeyPressTimer[ cNumOfKeys ] = {0u};
      tUI8 iKeyId;
      tUI8 iKeyPressed = cFalse;
      static tUI16 nBackLitOffTmr = 0;
    
      for(iKeyId = 0; iKeyId < cNumOfKeys; iKeyId++)
      {
        aKeyPressTimer[ iKeyId ]++;
        /* Key released */    
        if( PIN_getInputValue(ckeyIds[iKeyId]) != 0 )
        {
          if( ( aKeyPressTimer[ iKeyId ] > cTimeDebounce ) && 
              ( aKeyPressTimer[ iKeyId ] < (cTimeHold - cScrollSpeedOnKeyHold) ) )
          {
            KeyInfo.KeyEventType[ iKeyId ] = eKeyEvent_Pressed;
            iKeyPressed = cTrue;
          }else{}
    //      else
    //      {
    //        KeyInfo.KeyEventType[ iKeyId ] = eKeyEvent_NotPressed;
    //      }      
          aKeyPressTimer[ iKeyId ] = 0u;			
        }
        else
        {
          if( aKeyPressTimer[ iKeyId ] > cTimeDisableKey )
          {
            aKeyPressTimer[ iKeyId ]= 0u;
            KeyInfo.KeyEventType[ iKeyId ] = eKeyEvent_NotPressed;
            KeyInfo.KeypadState = cDisable;
            Keypad_Disable();
          }         	        
          else if( aKeyPressTimer[ iKeyId ] > cTimeHold )
          {
            KeyInfo.KeyEventType[ iKeyId ] = eKeyEvent_Hold;
            aKeyPressTimer[ iKeyId ] -= cScrollSpeedOnKeyHold;
            
            iKeyPressed = cTrue;
          }
        }
      }
      if( iKeyPressed )
      {
        iKeyPressed = cFalse;
        Commissioning_ResetLocalTimer_g( );
        BLE_StopSensorBroadCast_g( cTrue ); /*TODOJAG This needs to be reviewed why beacon creating problem for normal communication */
        if(cTrue == PTD_GetSleepStatus())
        {  
          PTD_StartTask_g();
        }  
        Screen_ResetTick_g( );
        GPIO_write( BACKLIT_PIN, cBackLitOn );
        nBackLitOffTmr = cBackLitTimeout;
      }else{} 
      
      /* Turn off backlight after timeout */
      if( nBackLitOffTmr )
      {
        nBackLitOffTmr--;
        if( nBackLitOffTmr == 0u )
        {
          GPIO_write(BACKLIT_PIN, cBackLitOff );
        }else{}  
      }  
    }
    
    /* -----------------------------------------------------------------------
     * @fn      Keypad_Disable
     *
     * @brief   Disable keypad pullups to reduce current consumption if key  
     *          Kept pressed 
     * @param   none
     *
     * @return  none
     */
    void Keypad_Disable( void )
    {
      GPIO_write(BTN_PULLUP_CNTRL, cKeyPullupDisable);
      Util_constructClock(&keyPullEnableClock, Keypad_PullEnableHandler,
                          (cTimeKeyKeptDisable), 0, false, 0);
      Util_startClock(&keyPullEnableClock);
      Keypad_DisableInt();  
    }  
    /* -----------------------------------------------------------------------
     * @fn      Keypad_PullEnableHandler
     *
     * @brief   handler come after timeout   
     *          Kept pressed 
     * @param   UArg a0 - ignored
     *
     * @return  none
     */
    static void Keypad_PullEnableHandler(UArg a0)
    {
      Keypad_EnableInt();
    }
    
    /* ----------------------------------------------------------------------- */
    /**
      Initiate SPI data send
      @param  TxData_p      Send data buffer
    */
    void Board_initKeys( void )
    {
      // Initialize KEY pins. Enable int after callback registered
      hKeyPins = PIN_open(&keyPins, keyPinsCfg);
      PIN_registerIntCb(hKeyPins, Keypad_KeyPressCallback);
    
      Keypad_EnableInt();
      // Setup keycallback for keys
      /* First handler comes at 1mS then at every cKeyPollFreq */
      Util_constructClock(&keyChangeClock, Keypad_keyPollHandler,
                          1, cKeyPollFreq, false, 0);
    }
    /* ----------------------------------------------------------------------- */
    static void Keypad_KeyPressCallback(PIN_Handle hPin, PIN_Id pinId)
    {
      if (!Util_isActive(&keyChangeClock))
      {
       Util_startClock(&keyChangeClock);
      }
      else{}
    }
    /* ----------------------------------------------------------------------- */
    static void Keypad_keyPollHandler(UArg a0)
    {
      Keypad_Scan();
    }
    /* ----------------------------------------------------------------------- */
    void Keypad_EnableInt(void)
    {
      PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_BTN1 | PIN_IRQ_NEGEDGE);
      PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_BTN2 | PIN_IRQ_NEGEDGE);
      PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_0    | PIN_IRQ_NEGEDGE);
      PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_4    | PIN_IRQ_NEGEDGE);
    
    #ifdef POWER_SAVING
      //Enable wakeup
      PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_BTN1 | PINCC26XX_WAKEUP_NEGEDGE);
      PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_BTN2 | PINCC26XX_WAKEUP_NEGEDGE);
      PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_0    | PINCC26XX_WAKEUP_NEGEDGE);
      PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_4    | PINCC26XX_WAKEUP_NEGEDGE);
    #endif //POWER_SAVING
      Keypad_Init();
    }
    /* ----------------------------------------------------------------------- */
    void Keypad_DisableInt(void)
    {
      PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_BTN1 | PIN_IRQ_DIS);
      PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_BTN2 | PIN_IRQ_DIS);
      PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_0    | PIN_IRQ_DIS);
      PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_4    | PIN_IRQ_DIS);
    
    #ifdef POWER_SAVING
      //Enable wakeup
      PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_BTN1 | PINCC26XX_NO_WAKEUP);
      PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_BTN2 | PINCC26XX_NO_WAKEUP);
      PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_0    | PINCC26XX_NO_WAKEUP);
      PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_4    | PINCC26XX_NO_WAKEUP);
    
    #endif //POWER_SAVING
      if (Util_isActive(&keyChangeClock))
      {
        Util_stopClock(&keyChangeClock);
      }  
    }
    /* ----------------------------------------------------------------------- */
    void Keypad_Sleep_g(void)
    {
      /* Turn off key polling clock */
      if (Util_isActive(&keyChangeClock))
      {
        Util_stopClock(&keyChangeClock);
      }  
    }
    /* *********************************************************************** */
    #if ChangeHistory
    /* 
    $Log$
    */
    #endif
    /* End =================================================================== */
    

    PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_BTN1 | PIN_IRQ_DIS);
    PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_BTN2 | PIN_IRQ_DIS);
    PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_0 | PIN_IRQ_DIS);
    PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_4 | PIN_IRQ_DIS);

    #ifdef POWER_SAVING
    //Enable wakeup
    PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_BTN1 | PINCC26XX_NO_WAKEUP);
    PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_BTN2 | PINCC26XX_NO_WAKEUP);
    PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_0 | PINCC26XX_NO_WAKEUP);
    PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_4 | PINCC26XX_NO_WAKEUP);

    #endif //POWER_SAVING
    if (Util_isActive(&keyChangeClock))
    {
    Util_stopClock(&keyChangeClock);
    }

    Cheers

    Jai

  • Hi Jai, answers inline,

    Do you think setting constraint is not a good idea for UART and I have to make changes in my code, or this is OK and I can keep it as it is?

    [Marie] I think the constraints you are setting is causing the issue where the device does not go to sleep. I would recommend you to remove the power driver calls and set the UART timeout value to a higher value.

    I have one more requirements, I want to disable button interrupt in some situation, for this I am using method "Keypad_DisableInt" of attached file.

    in this I am disabling wake up and interrupts on all button.

    I observed that even after disabling interrupt when I press button, interrupt comes and my callback "Keypad_KeyPressCallback" comes, this I have checked in debug mode.

    Is it OK, if I am performing interrupt disabling operation, from another interrupts service rutine ? in this code I am doing this from my clock ISR.

    [Marie] No this should be avoided.

    can you please review below code of attached file and let me know if I have missed something.

    Keypad.c
    PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_BTN1 | PIN_IRQ_DIS);
    PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_BTN2 | PIN_IRQ_DIS);
    PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_0 | PIN_IRQ_DIS);
    PIN_setConfig(hKeyPins, PIN_BM_IRQ, CONFIG_PIN_4 | PIN_IRQ_DIS);

    #ifdef POWER_SAVING
    //Enable wakeup
    PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_BTN1 | PINCC26XX_NO_WAKEUP);
    PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_BTN2 | PINCC26XX_NO_WAKEUP);
    PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_0 | PINCC26XX_NO_WAKEUP);
    PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, CONFIG_PIN_4 | PINCC26XX_NO_WAKEUP);

    #endif //POWER_SAVING
    if (Util_isActive(&keyChangeClock))
    {
    Util_stopClock(&keyChangeClock);
    }

    [Marie] PIN_setConfig() will require you to close and open the pin handle to take effect. Instead you can use the PIN_setInterrupt() API.

  • Hi Jai,

    Actually no point in using PIN_setInterrupt(). The PIN configuration is not really meant to be configured at runtime so the PIN driver doesn't handle your usecase so smoothly. I think you will actually need to call first PIN_close, then make the configuration, then open again.

  • Hi Marie,

    Thanks for your inputs, I request you to please respond you on all of my quires, if you feel my query is wrong or not relevant, please do mentioned in your response.

    I have asked 

    Is it OK, if I am performing interrupt disabling operation, from another interrupts service rutine ? in this code I am doing this from my clock ISR.

    Now I want to know same is applicable for Pin close or not, I mean calling Pin close for software clock ISR is ok or it may have some issue.

    regards

    Jai

  • Hi Jai,

    It's ok to call PIN close from a software clock ISR. 

  • Hi Marie,

    I want to enable boot-loader backdoor on my application, for this I have used "Device configuration" section in sysConfig tool there I have choose  Bootloader Backdoor DIO. I have below observation with this setting.

    My application works as desired when I choose DIO 14 or 15 as a bootloader backdoor, and my application enable boot loader only when device start when any of these DIO is low at power up.

    But when I choose any other free DIO ( DIO 29), after programming my device start bootloader it does not start my application and going straight to bootloader.

    Please note:- this I/O is pulled up externally so it is not have a case of my device accidentally going to boot loader mode. Is there some other setting that I am missing please let me know.

    My application is based on multirole sample application.   

  • Hi Jai,

    I'm not able to reproduce. I just tested with the standard multi-role example from the SimpleLink CC13x2/CC26x2 SDK v. 4.30 and using CCS 10.1.1. When I configure the bootloader backdoor pin to pin 29 I don't see any issue. When I power-cycle my board the device boots into the application image (I can see it write over UART and I can see it advertise.)

  • Hi Marie,

    Did this pin configured as GPIO in your application, and did you checked it goes to boot-loader mode or not ? 

  • I did experiment on my development board CC1352-P and observed that, it does not enabled bootloader, if I select other GPIO I have tested with DIO 29 and DIO 27. 

    with only DIO 14 and DIO 15 it enable boot-loader I did not understand this behavior, let me know if I am missing anything in enabling boo-tolader. 

  • Hi Jai,

    Ok sorry, I misunderstood your observation.

    Yes I'm seeing the same thing when I set BL backdoor pin to DIO 27 it's not entering the bootloader when I attach a jumper between DIO 27 and GND and reset the device.

    This could be several reasons so please allow me to rech out to the software developer.

  • Hi Marie,

    any updates on this please, 

    On my hardware ( custom one) I am having different observation, my hardware goes to boot-loader mode on power up straight forward. this is just opposite behavior observed on CC1352 development board.

    If my device goes in bootloader mode, is there some other ways to bring it out from it without reset, does it comes out automatically after timeout.

      

  • Hi Jai,

    Sorry for the delay. I'm still investigating.

    When you have finished using the bootloader you can send the following command to reset the device: COMMAND_RESET . This command is documented in the Technical Reference Manual, Table 10-3. Supported Bootloader Commands.

  • Hi Jai,

    I'm sorry, this is actually a bug in the ROM bootloader.  We recently discovered this bug and we are planning to add it to the errata notes as soon as possible. I have attached the bug description below but the short version is that you can only use DIO5 - DIO25 for the bootloader backdoor.

    The highest possible DIO number that can be used for the bootloader backdoor is limited
    to the number of available GPIOs minus 1. The bootloader backdoor pin is configured
    through SET_CCFG_BL_CONFIG_BL_PIN_NUMBER in ccfg.c. That means that if the
    device has x GPIOs, the highest DIO number that can be selected for the bootloader
    backdoor is DIOx-1, even if higher DIO numbers are available for the device.

  • Hi Marie,

    Thanks for the information provided, I don't know what to do now as its a change in our hardware while it is already released.

    I did not understand your response fully please help me on this. 

    Did you mean that I can only choose any DIO between DIO5 to  DIO 25? but when you say "number of available GPIOs minus 1" does it mean the total numbers of GPIO used ( counts) or the highest number of DIO used which is in my case DIO30, why then why DIO29 as bootloader backdoor is not working.

    I guess you are referring CONFIG_PIN_COUNT from file ti drivers config.c file ( refer attached ), its value is 26 for my application this is why you says' DIO5 to DIO25.

    But his does not make any sense, as if some application  have less then 4 GPIO  then how I would have choose bootloader backdoor pin, as 4 -1 become 3 and you will not find any GPIO which is name less then DIO5 (I did not find  DIO3). Please make it clear. 

    Please also note:- I am getting different behavior on my hardware and on CC1352 development board. on CC1352 development board Bootloader is not getting activated it application which always run, while on my hardware bootloader always get activated, this is irrespective to any state ( high or low) of DIO29, please explain why I am getting different behavior, is this because of sample application of multirole is having less GPIO's or something else. 

    regards

    Jai

    /*
     *  ======== ti_devices_config.c ========
     *  Customer Configuration for CC26XX and CC13XX devices.
     *
     *  DO NOT EDIT - This file is generated by the SysConfig tool.
     *
     */
    
    //#####################################
    // Force VDDR high setting (Higher output power but also higher power consumption)
    // This is also called "boost mode"
    //#####################################
    
    // Use default VDDR trim
    #define CCFG_FORCE_VDDR_HH                              0x0        
    
    
    //#####################################
    // Power settings
    //#####################################
    
    // Use the DC/DC during recharge in powerdown
    #define SET_CCFG_MODE_CONF_DCDC_RECHARGE                0x0
    
    // Use the DC/DC during active mode
    #define SET_CCFG_MODE_CONF_DCDC_ACTIVE                  0x0
    
    
    //#####################################
    // Clock settings
    //#####################################
    
    // LF RCOSC
    #define SET_CCFG_MODE_CONF_SCLK_LF_OPTION               0x3
    
    // Apply cap-array delta
    #define SET_CCFG_MODE_CONF_XOSC_CAP_MOD                 0x0 
    #define SET_CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA          0x3
    
    //#####################################
    // Special HF clock source setting
    //#####################################
    
    // HF source is a 48 MHz xtal
    #define SET_CCFG_MODE_CONF_XOSC_FREQ                    0x2    
    
    //#####################################
    // Bootloader settings
    //#####################################
    
    // Enable ROM boot loader
    #define SET_CCFG_BL_CONFIG_BOOTLOADER_ENABLE            0xC5
    
    // Enabled boot loader backdoor
    #define SET_CCFG_BL_CONFIG_BL_ENABLE                    0xC5
    
    // DIO number for boot loader backdoor
    #define SET_CCFG_BL_CONFIG_BL_PIN_NUMBER                0xf
    
    // Active low to open boot loader backdoor
    #define SET_CCFG_BL_CONFIG_BL_LEVEL                     0x0
    
    
    //#####################################
    // Debug access settings
    //#####################################
    
    // Disable unlocking of TI FA option.
    #define SET_CCFG_CCFG_TI_OPTIONS_TI_FA_ENABLE           0x00
    
    // Access enabled if also enabled in FCFG
    #define SET_CCFG_CCFG_TAP_DAP_0_CPU_DAP_ENABLE          0xC5
    
    // Access enabled if also enabled in FCFG
    #define SET_CCFG_CCFG_TAP_DAP_0_PWRPROF_TAP_ENABLE      0xC5
    
    // Access disabled
    #define SET_CCFG_CCFG_TAP_DAP_0_TEST_TAP_ENABLE         0x00
    
    // Access disabled
    #define SET_CCFG_CCFG_TAP_DAP_1_PBIST2_TAP_ENABLE       0x00
    
    // Access disabled
    #define SET_CCFG_CCFG_TAP_DAP_1_PBIST1_TAP_ENABLE       0x00
    
    // Access disabled
    #define SET_CCFG_CCFG_TAP_DAP_1_AON_TAP_ENABLE          0x00
    
    
    //#####################################
    // Select between cache or GPRAM
    //#####################################
    // Cache is enabled and GPRAM is disabled (unavailable)
    #define SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM           0x1
    
    
    
    /*
     *  ======== Include Base Settings for device ========
     */
    
    #include <ti/devices/DeviceFamily.h>
    #include DeviceFamily_constructPath(startup_files/ccfg.c)
    

  • Hi Jai,

    CC1352P has 26 GPIOs with the defined DIO range DIO5 to DIO30. However the bug described forces that the highest DIO that can be used for bootloader backdoor pin is DIO 25.

    The bug also means that if you set a higher DIO (e.g. DIO 29) to bootloader backdoor, it will default to DIO25. Could this explain the issue you are seeing with your custom hardware?

    BTW we have now updated the CC1352P errata note to include this one: 

     

  • Marie,

    So I have found a bug with TI software, i heard somewhere that if you found a bug in TI software you will be appreciated by TI is it true??

    my project is completed, i would like to say thanks you you, your were always helpful to us and quick in response, there was some time when I need things to be solve on priority and your quick response really helped that time.

    We have discussed a lot of important things in this post, I would like to refer it in future as well is there some way that I can add this ticket to favorite list and can refer it in future.

    regards

    Jai kushwaha

  • Hi Jai,

    Yes we always appreciate customers who help us improve our software :)

    If this is an issue we have not yet discussed please post here or send me an e-mail with the details.

    I also appreciate our collaboration and I'm happy you have finished the development!

  • hi Marie,

    I was talking about the bug we have observed regarding boot loader backdoor Pins.

    I have one more observation that is if I do GapAdv_enable  for a duration 900ms while GapScan_enable is permanently enabled, my device stays in advertising mode and keep on advertising infinitely. Ideally it should be disabled after 900mS but it does not.

    to me it looks a bug with SDK, so I did a work around in my code, I enable scan only after my adv is completed.

    in below code if I call "BLE_EnableScan_g();" my device stuck and keep on doing adv, while if I do not call ( comment ) "BLE_EnableScan_g();" adv happens for 900 ms and then stops.

    void BLE_StartTransmission_g( 

    tUI8 nLen_p,
    tUI8 aData[],
    tUI8 nRetry_p,
    tUI8 IsScanEnable_p,
    tUI8 IsReceiverAdv_p )
    {
    tUI8 aSendBuff[ 256u ];
    tUI8 nDataLen = 0;

    /* Adding Broadcast header */
    UTIL_MemCpy( aSendBuff, caBroadcastHeader, cBLE_BroadCastHeaderSize );
    UTIL_MemCpy( &aSendBuff[ cBLE_BroadCastHeaderSize ], aData, nLen_p );
    nDataLen = nLen_p + cBLE_BroadCastHeaderSize;

    multi_role_enableAdvert( aSendBuff, nDataLen, nRetry_p, IsReceiverAdv_p, IsScanEnable );

    if( IsScanEnable_p == cTrue )
    {
    BLE_EnableScan_g();
    }
    else{}
    //multi_role_enableAdvert( aSendBuff, nDataLen, nRetry_p, IsReceiverAdv_p );
    }

    You have my source code you can look in code how I have used below two methods.

    multi_role_enableAdvert

    and 

    BLE_EnableScan_g();

    void multi_role_enableAdvert(
    uint8_t aData_p[],
    uint8_t nLen_p,
    uint8_t nRetry_p,
    uint16_t nDuration,
    uint8_t IsScanEn )
    {
    uint8_t status = FAILURE;

    status = GapAdv_prepareLoadByHandle(advHandle, GAP_ADV_FREE_OPTION_DONT_FREE );
    DebugPrint_g( "PLdByHndl=", status );

    /* Copy data in send buffer */
    UTIL_MemCpy( TxDataBuff, aData_p, nLen_p );
    status = GapAdv_loadByHandle(advHandle, GAP_ADV_DATA_TYPE_ADV, nLen_p,
    TxDataBuff);
    DebugPrint_g( "LdByHndl=", status );

    status = GapAdv_enable(advHandle, GAP_ADV_ENABLE_OPTIONS_USE_DURATION ,
    cAdvDuration);
    DebugPrint_g( "AdvEnabl=", status );
    }

    --------------

    void BLE_EnableScan_g( void )
    {

    // AckReceived = cFalse; /* When Ack received from Receiver this will become True */
    /* Start scanning */
    // multi_role_enableScan( );
    //IsScanEnable = GapScan_enable(0, cBLE_ScanTime, 0);
    IsScanEnable = GapScan_enable(0, 0, 0);
    DebugPrint_g( "Scan_Enable=", IsScanEnable );
    IsScanEnable = cTrue;
    }

     

  • Hi Jai,

    Can you tell me the value of cAdvDuration when this happens?

    If I understand you correctly, advertisement stops after 900 ms in these two cases:

    - device is only advertising (no scanning)

    - infinite scanning is enabled after advertising is enabled.

    Please let me know if I misunderstood.

  • Hi Marie,

    the value of cAdvDuration                   (90), 

    Case 1 when  scan is enabled by  calling "GapScan_enable(0, 0, 0);" and then if I do adv then a situation created that my device keep on advertising scanning may work at that time but I have more concerned why adv not stops after 900ms.

    Case 2while if i do adv without scan enable that is by not calling GapScan_enable(0, 0, 0), my adv stop with in 900ms, that is what expected.

    so the issue is why in case 1 Adv does not stops after 900ms, I have observed it never stops and my device keep on advertising. 

    Cheers

    Jai. 

     

  • Hi Marie,

    you response is awaited. possible it an issue with the BLE SDK. 

  • Hi Jai,

    I'm sorry, I missed your post.

    If I remember correctly you are using SimpleLink SDK 3.40. Were you able to reproduce this issue with a standard multi role example?

    (BTW I don't know if you saw the newest SDK, 4.40 SDK. We have updated the BLE Scheduler to be a lot more flexible, might be worth to take a look :) )

  • Hi Marie,

    This issue of continuous Adv is coming with SDK 4.40.

    Cheers

    Jai

  • Hi Jai,

    Just so you know - your scan window is set to 330 ms, so the device will only be available to advertise every 330 ms. However your advertisement interval is set to 100 ms. I would try setting either the scan window to 100 ms, or the advertisement interval to 330 ms.

    Can you let it run for approx 20 seconds and see if advertising has ended at this time?

  • Hi Marie,

    As I mentioned earlier, it never comes out from Advertising loop, it keep on advertising for infinite time.  I have tested this on 2 products when they fall in this situation they were continuously adverting the same packets as asked to transmit earlier. after 3 days I have reset those products and then advertisement stops on these two product.

    I have explain everything about this problem I don't have much to explain about it. i request you to please read post again from start you will know everything about the application we have develop and to simulate this issue at your end.

    I can understand you have pointed something for scan intervals, but the question is whatever the setting application made  device should come out from this situation. This bug is very critical for our battery operated products.

    Cheers

    Jai

  • Hi Jai,

    I have reproduced your issue. I also noticed using GAP_ADV_ENABLE_OPTIONS_USE_MAX_EVENTS has the same issue.

    I will work with the software team to find a fix for you. For now, can you implement a clock object to disable advertising after 900 ms has passed?

  • Hi Marie,

    Thanks for acknowledging the bug in SDK

    I would like to add one more observation, to me its a 3rd bug I have observed.

    In my same application if I performed "Power_releaseConstraint(PowerCC26XX_SB_DISALLOW) while this constraint was not set earlier by calling Power_setConstraint(PowerCC26XX_SB_DISALLOW) API, this result in a SDK assert and my application code hanged, it never comes from this state, the only way to recover from this hanged state is reset.

    You probably asked why I am doing so releasing constraint while it was not set, it is done because I have handled button ISR differently which caused this issue, as my sleep code is common and called before every sleep, but in some case when I wakeup I did not set constraints  and trigger sleep.

    but SDK should have a check for this, it should ignore Power_releaseConstraint is that constraint was not set and some how called from the application.

     regards

    Jai 

     

  • Hi Jai,

    Sorry, I don't have an update about the scheduler bug yet. Did you test the work-around I suggested? (Implement a clock object to disable advertising after 900 ms has passed.)

    For the release constraint issue, this is intended behavior. As a safe guard you can implement a check in your application. 

  • Hi Marie,

    Thanks for the acknowledgment, 

    I have implemented a workaround for both of these SDK  observations in my application, by mentioning here I want to help the other developer who will be developing application using the same SDK.

    I guest its worth mentioning somewhere how to avoid such condition so that a new developer should not get similar problem as I faced.    

    regards

    Jai

  • Hi Jai,

    I talked to the software developer team. They have not yet found the root cause. Our goal is to have a fix implemented in the next SimpleLink SDK.

  • Hi Marie,

    I have observed a strange issue at our production line, in BLE module CC1352 the impedance between VDDS3 and Ground is getting reduced and after sometime the module is becoming dead.

    this problem is coming around 30% of the product produced, this is very critical problem for us, can you please help us on this by discussing it with your team immediately,  does any other of your customer also faced similar issue.

    I will be good if we have a meeting on this at the earliest.

  • Hi Jai,

    This is being handled over e-mail. I will close the thread for now.

  • Ok Marie,

    we are facing one more issue in UART.

    we are using Dio12 and Dio13 for Uart Rx and Tx, same as used in your sample application and in Boot-loader, there we observed problem our code hands and never returns from UART_read(); API.

    if we comment this calling of this API in (//UART_read(); ) our code, we did not observe hang issue. this problem is coming in some condition when UART RX and TX are receiving some noise, else things working as desired.

    this we have simulated by connecting floating wire of 8 inch length at both UART tx and Rx lines ( Dio12 and Dio 13) and then when UART_read(); called our code hanged, it happen only when we use UART functionality else code work as it should be.

    Can you please let us know, what causing the UART_read(); hangs, please not this problem is not coming with debugging, it coming with actual product so I could not be able to provide any information.  

    I can understand it is produced by an hardware problem, but we want to know why the code hangs?

    I also want to know how a pull up can be configured on these UART lines using sysconfig tool, sysconfig give options to enable pullup for DIO's when they are made input but I did not get anything when a DIO is made as UART.

    Thanks 

    Jai

  • Hi Jai,

    Torstein sent you an e-mail, please let me know if this answered the question.

  • Hi Marie,

    Torstein reply partially answer my question regarding how to enable pull up, but I want to know why code hangs too.

    do you want me to ask this on same email chain or you will answer it here, please note code only hangs when it execute UART_read(); else it works fine, that too only happens when some noise injected to UART lines.

    please refer attached source files, if you find anything wrong in UART handling let me know.

    /** @file           Production.c
    *   @copyright      Copyright (c) 2016 Secure International Holdings Pte. Ltd.
    *   @author         Written by: Jagdish Kushwaha
    *   @date           Started on:  14/04/2020
    *   @brief          This file will perform Production test support over UART  
    */
    /* *********************************************************************** */
    /* included files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/UART.h>
    #include "HDCSensor.h"
    #include "Production.h"
    #include "Typedef.h"
    #include "Flash.h"
    #include "icall.h"
    #include <ti/drivers/PIN.h>
    #include "ti_drivers_config.h"
    #include "Keypad.h"
    #include "SmlUtil.h"
    #include "multi_role.h"
    #include "LCD.h"
    #include "BattRead.h"
    #include "DisplayLCD.h"
    #include <driverlib/aon_batmon.h>
    #include "UtilCrcChkSum.h"
    #include "data.h"
    #include "PTDTimer.h"
    #include "UtilCrcChksum.h"
    #include "PTDScreen.h"
    /* Macros ---------------------------------------------------------------- */
    
    #define cUARTBufSize                  (64u)
    
    /* Private typedef ------------------------------------------------------- */
    /**
     * MLP command structure
     */
    typedef struct
    {
      tUI16 InfoFieldLen;
      tUI8 u8_Part;
      tUI8 InfoFieldType;
      tUI8 PartRxDataPtr[ cUARTBufSize ];
      tUI32 u32_Tmr;    /* Interbyte Timeout */
    } t_MlpHdr;
    
    /**
     * Message type
     */
    typedef enum
    {
      eProtocolCtrlMsg,
      eOperationalMsg,
      eApplicationMsg,
      eZclMsg,
      eDlmsMsg
    } tMlpMsgType;
    
    /** 
    BLE fsm states
    */
    typedef enum
    {
      RoundTrip_Idle,
      RoundTrip_WaitforTx,
      RoundTrip_WaitForRx
    }teRoundTrip_Fsm;
    /* Constants Variables --------------------------------------------------- */
    
    /* Private variables ----------------------------------------------------- */
    tUI8 aOutBuff[ cUARTBufSize ] = { 0x00 };
    static tUI8 aUart1RxData[ cUARTBufSize ];
    static tUI8 KeyEnable[ cNumOfKeys ];
    static tUI8 KeyCount[ cNumOfKeys ];
    static tUI8 aMasterMac[ cMACLen ];
    UART_Handle UARTHandler;
    t_MlpHdr MlpHdr;
    tUI32 nProductionTick;
    tUI32 nRoundTripTick;
    static tUI8 RoundTripRspRcvd;
    teRoundTrip_Fsm nRoundTripFsmState;
    /* Private functions ----------------------------------------------------- */
    /**
      Function to send MLP response
      @param    aBuff_p   Response buffer
      @param    nLen_p    Buffer length
    */
    static void MlpSendData( 
      tUI8 aBuff_p[ ], 
      tUI16 Len_p );
    /* ----------------------------------------------------------------------- */
    /**
      Function to add MLP header to command
      @param    aBuff_p   Data buffer
      @param    Len_p     Buffer length
      @param    Type_p    Command type
      @param    Part_p    Part number
    */
    static void MlpPutHdr( 
      tUI8 aBuff_p[ ],
      tUI16 Len_p, 
      tUI8 Type_p, 
      tUI8 Part_p );
    /* ----------------------------------------------------------------------- */
    /**
      Function to verify MLP frame
      @param    nMsgLen_p
      @return   cTrue, cFalse
    */
    static tUI8 MlpGetFrameStatus( tUI16 nMsgLen_p );
    /* ----------------------------------------------------------------------- */
    /**
      Function to send NACK
    */
    static void MlpMsgNack( void );
    /* ----------------------------------------------------------------------- */
    /**
      Enable key for production 
      @param    iKey_p   Key number
    */
    static void Production_ConfigKeyTest( tUI8 iKey_p );
    /* ----------------------------------------------------------------------- */
    /**
      Key press counter
      @param    iKey_p   Key number
    */
    static tUI8 Production_GetKeyPressCount( 
      tUI8 iKey_p, 
      tUI8 aBuff_p[ ] );
    /* ----------------------------------------------------------------------- */
    /**
      Read keypad in production mode
    */
    static void Production_ReadKeypad( void );
    /* ----------------------------------------------------------------------- */
    /**
      Function to handle uart command
      @return cTrue - Go to sleep, cFalse - Waiting for another command
    */
    static tUI8 MlpProcOperationalMsg ( void );
    /* ----------------------------------------------------------------------- */
    /**
      Awaiting round trip command response from other device
    */
    static void Production_AwaitingRoundTripResponse( void );
    /* ----------------------------------------------------------------------- */
    #ifdef cConfigChngByUart
    /* ----------------------------------------------------------------------- */
    void Production_Parse_BleCnfgParams( tUI8 aDataBuf_p[ ] );
    /* ----------------------------------------------------------------------- */
    void Production_AddWhiteLst( tUI8 aDataBuf_p[ ] );
    /* ----------------------------------------------------------------------- */
    void Production_ClearWhiteLst( void );
    #endif
    /* ======================================================================= */
    void Production_TaskInit_g( void )
    {
      UART_Params UARTParam;
      
      UART_init();
      UART_Params_init( &UARTParam );
      UARTParam.writeDataMode = UART_DATA_BINARY;
      UARTParam.readDataMode = UART_DATA_BINARY;
      UARTParam.readReturnMode = UART_RETURN_FULL;
      UARTParam.readEcho = UART_ECHO_OFF;
      UARTParam.baudRate = 115200uL;
      UARTParam.readTimeout = 1uL;
      UARTHandler = UART_open( CONFIG_DISPLAY_UART, &UARTParam );
    
      if ( UARTHandler == NULL )
      {
        PTD_ASSERT(15);
      }
      nProductionTick = Timer_GetTick_g( );
    #ifdef cPtdDebug
      UART_write(UARTHandler, "Hello", 5u);
    #endif
      nRoundTripFsmState = RoundTrip_Idle;
    }
    /* ----------------------------------------------------------------------- */
    tUI8 Production_TaskRun_g( void )
    {
      tUI8 GoToSleep = cFalse; 
      tUI16 nReadByteCnt; 
      
      nReadByteCnt = UART_read( UARTHandler, &MlpHdr.PartRxDataPtr, cUARTBufSize );
      if( nReadByteCnt )      
      {
        nProductionTick = Timer_GetTick_g( );
        if( cTrue == MlpGetFrameStatus( nReadByteCnt ) )
        {
          GoToSleep = MlpProcOperationalMsg( );
        }
        else
        {
          MlpMsgNack( );
        }
      }
      else{}
    #if !defined cAlwaysProductionMode  
      if( Timer_IsOver_g( nProductionTick, cProductionTimeout ) )
      {
        nProductionTick = Timer_GetTick_g( );
        GoToSleep = cTrue;
      }
      else{}
    #endif  
      Production_ReadKeypad( );
      Production_AwaitingRoundTripResponse( );  
      return GoToSleep;
    }
    /* ----------------------------------------------------------------------- */
    void Production_Sleep_g( void )
    {
      UART_readCancel( UARTHandler );
      UART_close( UARTHandler );
    }
    /* ----------------------------------------------------------------------- */
    static tUI8 MlpProcOperationalMsg( void )
    {
      tUI8 Status = cFalse;
      tUI8 nMsgLen = 0u;
      tUI8 SerialData[ 18u ];
      
      aOutBuff[ 4u ] = aUart1RxData[ 0u ];
      aOutBuff[ 5u ] = aUart1RxData[ 1u ];
      switch( aUart1RxData[ 0u ] ) /* Cmd Type */
      {
        case 0x0Cu: /* Memory Write/Read Cmd */
          switch( aUart1RxData[ 1u ] )
          {
            case 0x04u: /* Read customer serial number */
              if( cTrue == Flash_GetData( eFlashMfgSr, &aOutBuff[ 6u ] ))
              {
                nMsgLen = cSrNumLen;
              }
              else
              {
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Address size Error */
                nMsgLen = 2u;
              }		  
              break;
            case 0x03u: /* Read Manufacture serial number */
              if( cTrue == Flash_GetData( eFlashCCASr, &aOutBuff[ 6u ] ))
              {
                nMsgLen = cSrNumLen;
              }
              else
              {
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Address size Error */
                nMsgLen = 2u;						
              }	
              break;
            case 0x05u: /* Write Manufacture serial number */
              
              Flash_WriteData( eFlashCCASr, 8u, &aUart1RxData[ 2u ] );
              if( cTrue == Flash_GetData( eFlashCCASr, /*(tUI8*)&*/SerialData ) )
              {
                nMsgLen = cSrNumLen;
                UTIL_MemCpy( &aOutBuff[ 6u ], SerialData, nMsgLen );
              }
              else
              {
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Address size Error */
                nMsgLen = 2u;										
              }
              break;
            case 0x06u: /* Write customer serial number */
              Flash_WriteData( eFlashMfgSr, 8u, &aUart1RxData[ 2u ] );
              if( cTrue == Flash_GetData( eFlashMfgSr, SerialData ) )
              {
                nMsgLen = cSrNumLen;
                UTIL_MemCpy( &aOutBuff[ 6u ], SerialData, nMsgLen );
              }
              else
              {
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Address size Error */
                nMsgLen = 2u;										
              }
              break;
            case 0x07u: /* Read MAC address */
              BLE_GetMac_g( &aOutBuff[ 6u ] );
              nMsgLen = cMACLen;
              break;
            default:
              aOutBuff[ 6u ] = 0xFF; /* Error */
              aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
              nMsgLen = 2u;
              break;
          }
          break;
        case 0x80: 
          switch( aUart1RxData[ 1u ] )
          {
            case 0x00: /* Get PTD Firmware version */
              nMsgLen = UTIL_ConstStrLen(cPtdFwVersion);
              UTIL_MemCpy( &aOutBuff[ 6u ], cPtdFwVersion, nMsgLen );
              break;
    /* JAG This for external flash test not required for PTD */          
    //        case 0x89:/* Flash test, Read MAC ID and serial number */
    //          BLE_GetMac_g( &aOutBuff[ 7u ] );
    //          nMsgLen = cMACLen;
    //          if( cTrue == Flash_GetData( eFlashCCASr, &aOutBuff[ 6u + nMsgLen ] ))
    //          {
    //            nMsgLen += cSrNumLen;
    //          }
    //          else
    //          {
    //            aOutBuff[ 6u ] = 0xFF;
    //            aOutBuff[ 7u ] = 0xFF; /* Address size Error */
    //            nMsgLen = 2u;						
    //          }
    //          break;
    
            case 0x01: /* Read Battery Voltage */
              nMsgLen = ADC_ReadBatt_g(&aOutBuff[ 6u ]);
              break;
    
            case 0x02: /* Put PTD in deep sleep */
              aOutBuff[ 6u ] = 0x00;
              nMsgLen = 1u;
              Status = cTrue;
              break;
              
            case 0x03:/* Read HW type */
              aOutBuff[ 6u ] = 0x37;
              nMsgLen = 1u;
              break;
              
            case 0x8D:/* Read temperature and humidity */
              nMsgLen = HDC_TrigAndRead_g( &aOutBuff[ 6u ]);
              break;
            case 0x94:/* Display Test  */
              aOutBuff[ 6u ] = 0x00;
              nMsgLen = 1u;          
              switch( aUart1RxData[ 2u ] )
              {
                case 0x00: /* Display Off  */
                  Lcd_AllOff_g( );
                  Lcd_Update_g( );		  
                  break;          
                case 0x01: /* Display all On  */
                  Lcd_AllOn_g( );
                  Lcd_Update_g( );		  
                  break;          
                case 0x02: /* Display Even On  */
                  Lcd_EvenOn_g( );
                  Lcd_Update_g( );		  
                  break;          
                case 0x03: /* Display Odd On  */
                  Lcd_OddOn_g( );
                  Lcd_Update_g( );		  
                  break;
                default: 
                  aOutBuff[ 6u ] = 0xFF; /* Error */
                  aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
                  nMsgLen = 2u;			  
                  break;
              }
              break;
            case 0x95:/* Turn on/off backlight */
              if( aUart1RxData[ 2u ] == 0x00 )
              {
                GPIO_write(BACKLIT_PIN, cBackLitOff ); /* backlight */
                aOutBuff[ 6u ] = 0x00;
                nMsgLen = 1u;
              }
              else if( aUart1RxData[ 2u ] == 0xFF )
              {
                GPIO_write(BACKLIT_PIN, cBackLitOn ); /* backlight */
                aOutBuff[ 6u ] = 0x00;
                nMsgLen = 1u;
              }		  
              else
              {	
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
                nMsgLen = 2u;			  
              }		
              break;
            case 0x96:/* Perform round trip test */
              UTIL_MemCpy( aMasterMac, &aUart1RxData[ 2u ], cMACLen );
              RoundTripRspRcvd = cFalse;
              nRoundTripTick = Timer_GetTick_g( );
              nRoundTripFsmState = RoundTrip_WaitforTx;
              /* This must here because if Adv done while scan is enabled code stuck 
                 in not ending advertisement loop and creat issue */
              BLE_DisableScan_g();          
              Ble_SendRoundTripCmd_g(aMasterMac);
              break;
              
            case 0x98:/* Start Button test */
              if( (( aUart1RxData[ 2u ] <= cNumOfKeys ) &&
                   ( aUart1RxData[ 2u ] > 0u ))         || 
                  ( aUart1RxData[ 2u ] == 0xFF ))
              {
                /* Start Key test here */
                Production_ConfigKeyTest(  aUart1RxData[ 2u ] );
                aOutBuff[ 6u ] = 0x00;
                nMsgLen = 1u;
              }
              else
              {
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
                nMsgLen = 2u;			  
              }
              break;
            case 0x99:/* Read button press count */
              if( (( aUart1RxData[ 2u ] <= cNumOfKeys ) &&
                   ( aUart1RxData[ 2u ] > 0u ))         || 
                  ( aUart1RxData[ 2u ] == 0xFF ))
              {            
                nMsgLen = Production_GetKeyPressCount( aUart1RxData[ 2u ],
                                 &aOutBuff[ 6u ]);
              }
              else
              {
                aOutBuff[ 6u ] = 0xFF; /* Error */
                aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
                nMsgLen = 2u;			  
              }		  
              break;   
    
    #ifdef cConfigChngByUart
            case 0x9A: /* Put PTD in deep sleep */
              aOutBuff[ 6u ] = 0x00;
              nMsgLen = 1u;
              Production_Parse_BleCnfgParams( &aUart1RxData[ 2u ] );
              break;
              
            case 0x9B: /* Add White list  */
              aOutBuff[ 6u ] = 0x00;
              nMsgLen = 1u;
              Production_AddWhiteLst( &aUart1RxData[ 2u ] );
              break;          
    
            case 0x9C: /* Add White list  */
              aOutBuff[ 6u ] = 0x00;
              nMsgLen = 1u;
              Production_ClearWhiteLst( );
              break;                    
    #endif
            default:
              aOutBuff[ 6u ] = 0xFF; /* Error */
              aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
              nMsgLen = 2u;
              break;
          }
          break;
          
        default:    /* unknown command */
          aOutBuff[ 6u ] = 0xFF; /* Error */
          aOutBuff[ 7u ] = 0xFF; /* Unsuported command */
          nMsgLen = 2u;
          break;
      }
      if( nMsgLen != 0u)
      {  
        nMsgLen += 2u; /* +Command length of 2 bytes */
        MlpSendData( aOutBuff, nMsgLen);
      }else{}  
      return( Status );
    }
    /* ----------------------------------------------------------------------- */
    static void MlpMsgNack( void )
    {
      tUI8 aOutBuff[ 8u ];
      tUI8 nMsgLen = 0u;
      
      aOutBuff[ 4u ] = 0xFF; /* Error */
      aOutBuff[ 5u ] = 0xFF; /* Unsuported command */
      nMsgLen = 2u;
      
      MlpSendData( aOutBuff, nMsgLen );
    }
    /* ----------------------------------------------------------------------- */
    static tUI8 MlpGetFrameStatus( tUI16 nMsgLen_p )
    {
      tUI8 u8_Temp;
        
      /* 2  bytes  will contain the length of frame */
      MlpHdr.InfoFieldLen = UTIL_ConvLiToU16( MlpHdr.PartRxDataPtr );
      u8_Temp = (tUI8)(MlpHdr.InfoFieldLen & 0x001F);
      MlpHdr.InfoFieldLen = (((MlpHdr.InfoFieldLen & 0xFF00) >> 3) | u8_Temp);
      /* Get field type */ 
      MlpHdr.InfoFieldType = MlpHdr.PartRxDataPtr[ 2u ];
      /* Get received part number */
      MlpHdr.u8_Part = MlpHdr.PartRxDataPtr[ 3u ];
    
      if(0 == ESL_CRC_CalcV41( 0u, MlpHdr.PartRxDataPtr,  nMsgLen_p ) )
      {
        UTIL_MemCpy( &aUart1RxData[ 0u ], &MlpHdr.PartRxDataPtr[ 4u ], 
        (MlpHdr.InfoFieldLen + 1u) );
        //nRxIdx += ( MlpHdr.InfoFieldLen + 1u );
      }
      else
      {
        return cFalse;
      }
      return cTrue;
    }
    /* ----------------------------------------------------------------------- */
    static void MlpSendData( 
      tUI8 aBuff_p[ ], 
      tUI16 nLen_p )
    { 
      tUI16 Crc = 0;
      /* Adding MLP header to command */
      MlpPutHdr( aBuff_p, (tUI16)nLen_p, eOperationalMsg, 0u );
      nLen_p += 4; /* Adding header length */
      Crc = ESL_CRC_CalcV41( Crc, aBuff_p, nLen_p );
      UTIL_ConvU16ToBi( Crc, &aBuff_p[ nLen_p ] );
      nLen_p += 2u;
      
      UART_write(UARTHandler, aBuff_p, nLen_p);
    }
    /* ----------------------------------------------------------------------- */
    static void MlpPutHdr( 
      tUI8 aBuff_p[ ],
      tUI16 Len_p, 
      tUI8 Type_p, 
      tUI8 Part_p )
    {	/* Clear Buffer */
      tUI8 Temp;
    	
      Len_p -= 1u;
    	
      Temp = (tUI8)(Len_p & 0x001Fu);
      Len_p = ( ((Len_p << 3u) & 0xFF00u) | Temp );
      /* Put Length */
      UTIL_ConvU16ToLi( Len_p, aBuff_p );
      /* Put Type */
      aBuff_p[ 2u ]= Type_p;
      /* Put Part Number */
      aBuff_p[ 3u ]= Part_p;
    }
    /* ----------------------------------------------------------------------- */
    static void Production_ConfigKeyTest( tUI8 iKey_p )
    {
      tUI8 iIndex = 0u;
      
      UTIL_MemSet(KeyEnable, 0x00, sizeof(KeyEnable));
      if( iKey_p == 0xFF )
      {
        while( iIndex < cNumOfKeys )
        {
          KeyEnable[ iIndex ] = cTrue;
          KeyCount[ iIndex ] = 0u;
          iIndex++;
        }
      }
      else
      {
        iKey_p--; /* Reducing index */
        KeyEnable[ iKey_p ] = cTrue;
        KeyCount[ iKey_p ] = 0u;
      }
    }
    /* ----------------------------------------------------------------------- */
    static tUI8 Production_GetKeyPressCount( 
      tUI8 iKey_p, 
      tUI8 aBuff_p[ ] )
    {
      tUI8 iIndex = 0u;
      tUI8 iKeyCnt = 0u;
      if( iKey_p == 0xFF )
      {
        while( iKeyCnt < cNumOfKeys )
        {
          aBuff_p[iIndex++] = iKeyCnt + 1u;
          aBuff_p[iIndex++] = KeyCount[ iKeyCnt ];
          iKeyCnt++;
        }
      }
      else
      {
        aBuff_p[iIndex++] = iKey_p;
        aBuff_p[iIndex++] = KeyCount[ iKey_p - 1u ];
      }
      return iIndex;
    }
    /* ----------------------------------------------------------------------- */
    static void Production_ReadKeypad( void )
    {
      tUI8 Index = 0u;
      while( Index < cNumOfKeys )
      {
        if( KeyEnable[ Index] == cTrue )
        {
          if( Keypad_GetEvent_g( Index ) != eKeyEvent_NotPressed )
          {
            KeyCount[ Index ]++;
          }
          else{}
        }
        Index++;
      }
    }
    /* ----------------------------------------------------------------------- */
    void Production_Chk_RoundTrip_g( tUI8 aDataBuf_p[ ] )
    {
      tUI8 aSerialNo[ cSrNumLen ];
      tUI8 nDataIdx;
      /* Check Master Mac */
      if(UTIL_MemCmp( aMasterMac, aDataBuf_p, cMACLen ) == 0 )
      {
        nDataIdx = cOffset_PayloadStart - cOffset_SrcMacAddress;
        /* Check round trip responce */
        if( aDataBuf_p[ nDataIdx++ ] == 0x01u )
        {  
          /* Get Dut Serial Number */
          Flash_GetData( eFlashMfgSr, aSerialNo);
          /* Check Dut Serial number */
          if(UTIL_MemCmp( aSerialNo, &aDataBuf_p[ nDataIdx ], cSrNumLen ) == 0 )
          {
            RoundTripRspRcvd = cTrue;
            BLE_DisableScan_g();
          }else{}  
        }else{PTD_ASSERT(16);}  
      }else{}  
    }
    /* ----------------------------------------------------------------------- */
    static void Production_AwaitingRoundTripResponse( void )
    {
      tUI8 aOutBuff[ 12u ];
    
      switch( nRoundTripFsmState )
      {
        case RoundTrip_Idle:
          /* Do nothing */
          break;
        case RoundTrip_WaitforTx:   /* Wait till PTD finish its Transmission */
          /* Come in reciving mode befor Receiver start Tx, as per Vikram Sir's sugestion */
          if( cTrue == Timer_IsOver_g( nRoundTripTick, cWaitForTx ))
          {
            BLE_EnableScan_g();    /* Enable Scan */
            nRoundTripFsmState = RoundTrip_WaitForRx;
          }else{}      
          break;
        case RoundTrip_WaitForRx:   /* Wait till data received from receiver  */
          aOutBuff[ 4u ] = 0x80; /* Round Trip Command */
          aOutBuff[ 5u ] = 0x96;
          if ( RoundTripRspRcvd == cTrue )
          {
            aOutBuff[ 6u ] = 0x00; /* Sucess */
            aOutBuff[ 7u ] = GetRSSI( ); /* Received Packet RSSI value */
            nRoundTripFsmState = RoundTrip_Idle;
            MlpSendData( aOutBuff, 4u );  
          }
          else if( Timer_IsOver_g( nRoundTripTick, cRoundTripResponseTimeout ) )
          {
            BLE_DisableScan_g();
            aOutBuff[ 6u ] = 0xFF; /* Error */
            nRoundTripFsmState = RoundTrip_Idle;
            MlpSendData( aOutBuff, 3u );  
          }else{}
          break;      
        default: 
          nRoundTripFsmState = RoundTrip_Idle;
          break;
      }  
      
    }
    /* ----------------------------------------------------------------------- */
    #ifdef cConfigChngByUart
    #include "gap_scanner.h"
    #include <ti/sysbios/knl/Task.h>
    /* Test Command */
    /*
    Minimum interval  2 Bytes  (n * 0.625 ms)
    maximum interval  2 Bytes  (n * 0.625 ms)
    Advertise type    1 byte   USE_DURATION 0 or USE_MAX_EVENTS 1 
    Advertise value   2 bytes  Duration ( in mS)  or max event 
    Scane type        1 bype   PASSIVE 0u or ACTIVE 1
    Scan Interval     2 bytes  (n * 0.625 ms)
    Scan Window       2 bytes  (n * 0.625 ms)    
    
    809A 01020120000A0B000C0D0A0F 
    809A 00A000B000044C0002300210
    */          
    
    tUI16 nMinInterval = 160u;
    tUI16 nMaxInterval = 176u;
    tUI8 nAdvType = 0; /* USE_DURATION 0 or USE_MAX_EVENTS 1 */
    tUI16 nAdvValue = 1100u ; /* Duration in mS or Max Event count  */
    tUI8 nScanType = SCAN_TYPE_PASSIVE; /* PASSIVE 0u or ACTIVE 1 */
    tUI16 nScanInterval = SCAN_PARAM_DFLT_INTERVAL;
    tUI16 nScanWindow = SCAN_PARAM_DFLT_WINDOW;
    
    void Production_Parse_BleCnfgParams( 
      tUI8 aDataBuf_p[ ] )
    {
      tUI8 iIdx = 0u;  
      
      nMinInterval   = UTIL_ConvBiToU16(&aDataBuf_p[iIdx]);
      iIdx += 2;
      nMaxInterval   = UTIL_ConvBiToU16(&aDataBuf_p[iIdx]);
      iIdx += 2;  
      nAdvType       = aDataBuf_p[iIdx];
      iIdx += 1;
      nAdvValue      = UTIL_ConvBiToU16(&aDataBuf_p[iIdx]);
      iIdx += 2;
      nScanType      = aDataBuf_p[iIdx];
      iIdx += 1;
      nScanInterval  = UTIL_ConvBiToU16(&aDataBuf_p[iIdx]);
      iIdx += 2;
      nScanWindow    = UTIL_ConvBiToU16(&aDataBuf_p[iIdx]);
      iIdx += 2;  
    }
    /* ----------------------------------------------------------------------- */
    tUI8 NoOfWhiteLstEntry = 0;
    tUI8 WhiteLstMac [cMACLen * 4 ]; /* Add filter of max 4 Mac */
    
    tUI8 TotalWhiteLstEntry = 0;
    tUI8 WhiteLstMacAdd [cMACLen ]; /* Add filter of max 4 Mac */
    tUI8 temp8;
    
    /*
    aDataBuf_p  6 Bytes  MacAddress
    */          
    void Production_AddWhiteLst( tUI8 aDataBuf_p[ ] )                             
    {
      tUI8 status;
    /*TODOJAG Needs to enter white list variable in global array */  
    //  temp8 = SCAN_FLT_POLICY_ALL;
    //  status = GapScan_setParam(SCAN_PARAM_FLT_POLICY, &temp8);
    
    //  status = HCI_LE_ClearWhiteListCmd();
      
      UTIL_MemCpy(WhiteLstMacAdd, aDataBuf_p, cMACLen );
      status = HCI_LE_AddWhiteListCmd(HCI_PUBLIC_DEVICE_ADDRESS, WhiteLstMacAdd);  
    //  TotalWhiteLstEntry++;
      temp8 = SCAN_FLT_POLICY_WL;
    //  temp8 = SCAN_FLT_POLICY_WL_RPA;
      status = GapScan_setParam(SCAN_PARAM_FLT_POLICY, &temp8);  
      BLE_DisableScan_g();  
      BLE_EnableScan_g();
      
      /* Add entry */
    //  if( aDataBuf_p[ 0u ] == 1 )
    //  {  
    //    if( NoOfWhiteLstEntry <= 4 )
    //    {
    //      UTIL_MemCpy( &WhiteLstMac[NoOfWhiteLstEntry * cMACLen ], &aDataBuf_p[ 1u ], cMACLen );  
    //      NoOfWhiteLstEntry++;
    //    }  
    //  }
    //  else /* Remove entry */
    //  {
    //    NoOfWhiteLstEntry = 0u;
    //  }  
    }
    /* ----------------------------------------------------------------------- */
    void Production_ClearWhiteLst( void )                             
    {
      tUI8 status;
      BLE_DisableScan_g();  
       status = HCI_LE_ClearWhiteListCmd();
       BLE_EnableScan_g();
    }  
    #endif
    /* ----------------------------------------------------------------------- */
    #ifdef cDebugUartEnable
    void Production_SendUartLog_g( 
      tUI8 nDataLen_p, 
      tUI8 aDataBuff_p[ ] )
    {
      tUI8 aBuf_p[512u ];
      tUI16 index;
      for(index = 0u; index < nDataLen_p; index++)
      {
        UTIL_CnvrtHexToAscii( aDataBuff_p[index ], &aBuf_p[index * 2] );
      }  
      aBuf_p[index * 2] = 0x0D;
      UART_write(UARTHandler, aBuf_p, (nDataLen_p * 2u) + 1u);
    }
    /* ----------------------------------------------------------------------- */
    void DebugPrint_g( 
      tUI8 aString[ ], 
      tUI8 nCode_p )
    {
      tUI8 aBuf_p[16u ];
      tUI8 nLen;
      tUI8 aUrtBuf_p[32u ];
      UTIL_MemSet( aBuf_p, 0u, 16u );
      UTIL_MemSet( aUrtBuf_p, 0u, 32u );
      UTIL_ConstStrCpy(aUrtBuf_p, aString);
      UTIL_CnvrtHexToAscii( nCode_p, aBuf_p );
    //  UTIL_IntToStr( (tUI32)nCode_p, aBuf_p );
      UTIL_ConstStrCat(aUrtBuf_p,aBuf_p);
      nLen = UTIL_ConstStrLen(aUrtBuf_p);
      UART_write(UARTHandler, aUrtBuf_p, nLen);
      aUrtBuf_p[0] = 0x0Du;
      UART_write(UARTHandler, aUrtBuf_p, 1u);
    //  if(nCode_p != 0 )
    //  {
    //    PTD_ASSERT(0xB1);
    //  }  
    }
    #else
    void Production_SendUartLog_g( 
      tUI8 nDataLen_p, 
      tUI8 aDataBuff_p[ ] )
    {
      /* Dummy method */
    }
    
    void DebugPrint_g( 
      tUI8 aString[ ], 
      tUI8 nCode_p )
    {
    //  if(nCode_p != 0 )
    //  {
    //    PTD_ASSERT(0xB1);
    //  }  
      /* Dummy method */
    }  
    #endif
    /* *********************************************************************** */
    #ifdef ChangeHistory
    
    #endif
    /* End =================================================================== */
    

  • Hi Marie,

    Kindly respond to UART Hang issue at the earliest.

  • Hi Marie,

     UART_read() return error code ,  UART_STATUS_ERROR  can you please explain in which scenarios this error code is reported, does it has anything to do with hand we are observing.

    /*!
    * @brief Generic error status code returned by UART_control().
    *
    * UART_control() returns UART_STATUS_ERROR if the control code was not executed
    * successfully.
    */
    #define UART_STATUS_ERROR (-1)

  • If you include the UART driver in the project and step into UART_read(), are you able to see where exactly the code hangs? 

  • Hi Jai,

    Do you still have an issue with this?

    If you include the UART driver in the project and step into UART_read(), are you able to see where exactly the code hangs?