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.

[FAQ] SIMPLELINK-CC2640R2-SDK: RTLS Known Issues and Fixes

Mastermind 49545 points

Replies: 1

Views: 2203

Part Number: SIMPLELINK-CC2640R2-SDK

simplelink_cc13x2_26x2_sdk_3_20_00_68

1. rtls_agent_cli has an issue where the incorrect AoA start request can be invoked via the websocket (e.g. when using RTLS_Monitor GUI)


The fix is to remove any references to _cc2640r2 flavors of commands. from ss_rtls.py. See the snippet below on which code should be removed

    class AoaStartReq_cc2640r2(NpiRequest, SyncReq, FromAp):
        command = Commands.RTLS_CMD_AOA_ENABLE
        struct = Struct(
            "enable" / Int8ul,
        )

    class AoaSetParamsReq_cc2640r2(NpiRequest, SyncReq, FromAp):
        command = Commands.RTLS_CMD_AOA_SET_PARAMS
        struct = Struct(
            "aoaRole" / Enum(Int8ul, AoaRole),
            "aoaResultMode" / Enum(Int8ul, AoaResultMode),
            "cteScanOvs" / Int8ul,
            "cteOffset" / Int8ul,
            "cteTime" / Int16ul,
        )

 

Also the following code should be removed from the bottom of the file:

    @builder_class(AoaStartReq_cc2640r2)
    def aoa_start_cc2640r2(self, enable): pass

    @builder_class(AoaSetParamsReq_cc2640r2)
    def aoa_set_params_cc2640r2(self, aoaRole, aoaResultMode, cteScanOvs, cteOffset, cteTime): pass

2. AoA will not be post processed by rtls_master.


This is a known issue that will be resolved by a future SDK.

 

For convenience, a new binary can be found here, use this in place of the one in the SDK:

/cfs-file/__key/communityserver-discussions-components-files/538/rtls_5F00_agent_5F00_cli.exe

 

simplelink_cc2640r2_sdk_3_10_00_15

1. rtls_master has CACHE_AS_RAM enabled in the Predefined Symbols, however, this is not enough to actually enable using CACHE_AS_RAM feature.

To fix this, please fix the following file: 

add "--define=CACHE_AS_RAM=1" in rtls_master_cc2640r2lp_app.projectspec under linkerBuildOptions section as shown in the picture below

simplelink_cc2640r2_sdk_2_40_00_32

Note: When using USB measurement devices such as Ellisys or Saleae, the RTLS provided scripts may not receive data properly. When logging, the commands may be received over the wire, but not forwarded to the UNPI parser Python. The USB CDC driver in the XDS110 and devices such as the saleae use "bulk" transfers and occasionally these measurement devices will consume 100% of USB bandwidth. See note by Saleae here: https://support.saleae.com/troubleshooting/pc-performance-issues. We recommend using the measurement device on a separate PC if possible, and always plug directly into PC where possible, avoiding hubs.

1. The out of box project for rtls_master and rtls_slave have build error due to the stack_library.projectspec is pointing to a wrong version of XDCTools. (CCS)

To fix this, please fix the following files: 

InstallationFolder\ti\simplelink_cc2640r2_sdk_2_40_00_32\examples\rtos\CC2640R2_LAUNCHXL\blestack\rtls_master\tirtos\ccs\

rtls_master_cc2640r2lp_stack_library.projectspec

InstallationFolder\ti\simplelink_cc2640r2_sdk_2_40_00_32\examples\rtos\CC2640R2_LAUNCHXL\blestack\rtls_slave\tirtos\ccs\

rtls_slave_cc2640r2lp_stack_library.projectspec

Change:

        <property name="products" value="com.ti.rtsc.XDCtools:3.50.08.24_core"/>

To:

          <property name="products" value="com.ti.rtsc.XDCtools:3.51.01.18_core"/>


2. rtlsmanager.py triggers exception on close when running without a websocket (Python)


Add the following code to rtls_manager.py::stop (~line 74)

if self.wss is not None: self.wss.stop()



3. Connection Monitor won't start when certain Connection Parameters are used

In micro_ble_cm.c, change the ubCM_startExt() function:

Remove the following:

ubCMConnInfo.ArrayOfConnInfo[i].scanDuration = (uint16_t)(((data[4]<<8) + data[5]) * 4);

Add the following ~line 789

    uint16_t chanSkip;

    // With a 100ms connection interval we will skip 3 channels into the future
    // This is mainly done to ensure that even a very slow bus is able to send the connection information in time
    // In time: before the Master/Slave already go past the channel that we chose to listen on
    // If Master/Slave are already past this point, we will have to wait numChannels*connInterval until we catch the
    // connection once again
    chanSkip = (uint16_t)((640/ubCMConnInfo.ArrayOfConnInfo[i].connInterval) + 1);
    setNextDataChan(sessionId, chanSkip); //jump some [ms] channels into the future
    ubCMConnInfo.ArrayOfConnInfo[i].currentChan = ubCMConnInfo.ArrayOfConnInfo[i].nextChan;

    // Catch anchor point n+2 connection intervals in the future
    ubCMConnInfo.ArrayOfConnInfo[i].scanDuration = (uint16_t)(ubCMConnInfo.ArrayOfConnInfo[i].connInterval*(chanSkip + 1));

4. Cache as RAM cannot be used with RTLS projects

Due to limited heap memory on rtls_master, it is recommended to use the cache as ram configuration when more intensive results modes such as 

RAW mode. See the guide for enabling Cache as RAM here. First apply changes below, Second apply project settings changes from the guide

http://dev.ti.com/tirex/content/simplelink_cc2640r2_sdk_2_40_00_32/docs/blestack/ble_user_guide/html/ble-stack-common/cache-as-ram.html

In main.c of of the rtls_projects replace any calls to VIMSConfigure() and VIMSModeSet() with the following:

#ifdef CACHE_AS_RAM
  // retain cache during standby
  Power_setConstraint(PowerCC26XX_SB_VIMS_CACHE_RETAIN);
  Power_setConstraint(PowerCC26XX_NEED_FLASH_IN_IDLE);
#else
  // Enable iCache prefetching
  VIMSConfigure(VIMS_BASE, TRUE, TRUE);
  // Enable cache
  VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);
#endif //CACHE_AS_RAM

Add the following to ccfg_app_ble.c above #include <startup_files/ccfg.c>

#ifdef CACHE_AS_RAM
  #define SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM  0x0 /* Enable GPRAM */
#endif //CACHE_AS_RAM


In TOF.c add the following to the end of the pOverrides_2M array

#ifdef CACHE_AS_RAM
    0x00018063,
#endif //CACHE_AS_RAM
    0xFFFFFFFF,
};


5. ToF cannot be closed properly, update settings


Add the following to TOF.c near #includes 

#include <ti/sysbios/hal/Hwi.h>
#include <ti/sysbios/knl/Swi.h>

#include "rtls/rtls_ctrl.h"
#include <stdlib.h>

Change params->freqChangePeriod in ToF_open() to 

params->freqChangePeriod = 2;      // Switch frequency for each 2 packets

Replace the contents of TOF_close() with the following

void TOF_close(ToF_Handle handle)
{
  volatile uint32_t keyHwi;

  // Delete synth calibrations
  handle->synthCal[0].freq = 0;

  // Close RF Handle
  RF_close(handle->rfHandle);

  // Close ToF Security
  TOFSecurity_close(&tofSecHandle);

  // Free Tof Handle
  keyHwi = Hwi_disable();

  free(handle->pFrequencies);
  free(handle->pT1RSSIBuf);

  Hwi_restore(keyHwi);
}

Create a TOF_security close API anywhere in tof_security.c

/*******************************************************************************
 * @fn          TOFSecurity_close API
 *
 * @brief       This function is used to close ToF Security and free buffers
 *
 * input parameters
 *
 * @param       tofSecHandle  - A pointer to an empty tof security handle.
 *
 * output parameters
 *
 * @return      uint8_t - NULL if failed, other if succeeded
 */
int TOFSecurity_close(tofSecHandle_t *tofSecHandle)
{
  volatile uint32_t keyHwi;

  keyHwi = Hwi_disable();

  // Free first buffer
  free(tofSecHandle->pSyncWordBuffer1);

  // If double buffer is enabled, free the other one as well
  if (tofSecHandle->tofSecCfgParams.bUseDoubleBuffer == TOF_MODE_DBL_BUF)
  {
    free(tofSecHandle->pSyncWordBuffer2);
  }

  Hwi_restore(keyHwi);

  return TOF_SEC_SUCCESS_E;
}

Add the following includes to tof_security.c

#include "rtls/rtls_ctrl.h"
#include <ti/sysbios/hal/Hwi.h>

Add the new security API definition to the tof_security.h header file

int TOFSecurity_close(tofSecHandle_t *tofSecHandle);

6. There exists various memory leaks in rtls_ctrl, the fixes are applied to a newer SDK. Please move to SimpleLink CC2640R2 SDK 3.10.00.15 or newer

7. Connection Monitor packets may not be flushed on repeated start/stops


Replace the contents of ull_flushAllDataEntry in ull.c with the following

void ull_flushAllDataEntry( dataEntryQ_t *pDataEntryQ )
{
  dataQ_t         *pDataQueue;
  port_key_t key;
  port_key_t key_s;

  key = port_enterCS_HW();
  key_s = port_enterCS_SW();

  /* point to data queue */
  pDataQueue = (dataQ_t *)pDataEntryQ;

  while ( pDataQueue->pNextDataEntry != NULL &&
          pDataQueue->pNextDataEntry->status != DATA_ENTRY_PENDING)
  {
    /* mark the next System data entry as Pending */
    pDataQueue->pNextDataEntry->status = DATA_ENTRY_PENDING;

    /* advance to the next data entry in the data entry queue */
    pDataQueue->pNextDataEntry = pDataQueue->pNextDataEntry->pNextEntry;
  }

  port_exitCS_SW(key_s);
  port_exitCS_HW(key);
}

Replace the conetents of ull_rxEntryDoneCback() in ull.c with the following:

void ull_rxEntryDoneCback(void)
{
  uint8 dataLen = 0;
  port_key_t key;
  port_key_t key_s;

  key = port_enterCS_HW();
  key_s = port_enterCS_SW();

  dataEntry_t *pDataEntry = ull_getNextDataEntry( (dataEntryQ_t *)urfiScanCmd.pParams->pRxQ );

  /* get pointer to packet */
  if ( (pDataEntry == NULL) || (pDataEntry->status != DATA_ENTRY_FINISHED) )
  {
    port_exitCS_SW(key_s);
    port_exitCS_HW(key);

    /* nothing to do here */
    return;
  }

  /* The callback will be called only if the previous adv packet is
   * processed by uGAP.
   */
  if (Ull_advPktInuse == false)
  {
    Ull_advPktInuse = true;

    /* process RX FIFO data */
    ull_getAdvChanPDU( &dataLen, advPkt );

    /* in all cases, mark the RX queue data entry as free
     * Note: Even if there isn't any heap to copy to, this packet is considered
     *       lost, and the queue entry is marked free for radio use.
     */
    ull_nextDataEntryDone( (dataEntryQ_t *)urfiScanCmd.pParams->pRxQ );
  }

  /* TBD: handle filtering and white list */
  /* TBD: advPkt needs to be dynamically allocated and application freed */

  /* We have an advertisment packet:
   *
   * | Preamble  | Access Addr | PDU         | CRC     |
   * | 1-2 bytes | 4 bytes     | 2-257 bytes | 3 bytes |
   *
   * The PDU is expended to:
   * | Header  | Payload     |
   * | 2 bytes | 1-255 bytes |
   *
   * The Header is expended to:
   * | PDU Type...RxAdd | Length |
   * | 1 byte           | 1 byte |
   *
   * The Payload is expended to:
   * | AdvA    | AdvData    |
   * | 6 bytes | 0-31 bytes |
   *
   * The radio stripps the CRC and replaces it with the postfix.
   *
   * The Postfix is expended to:
   * | RSSI   | Status | TimeStamp |
   * | 1 byte | 1 byte | 4 bytes   |
   *
   * The Status is expended to:
   * | bCrcErr | bIgnore | channel  |
   * | bit 7   | bit 6   | bit 5..0 |
   *
   * Note the advPkt is the beginning of PDU; the dataLen includes
   * the postfix length.
   *
   */

  port_exitCS_SW(key_s);
  port_exitCS_HW(key);

  if (dataLen != 0)
  {
    ull_notifyScanIndication( SUCCESS, dataLen, advPkt );
  }
  return;
}

Replace ull_monitorStop() in ull.c with the following:

void ull_monitorStop(void)
{
  port_key_t key;
  port_key_t key_h;

  key_h = port_enterCS_HW();
  key = port_enterCS_SW();

  if (ulState == ULL_STATE_MONITORING)
  {
    ulState = ULL_STATE_STANDBY;

    /* Cancel or stop generic Rx command */
    if (urfiGenericRxHandle > 0)
    {
      /* flush RF commands */
      RF_flushCmd(urfiHandle, urfiGenericRxHandle, 0);

      /* flush RX queue data entries */
      ull_flushAllDataEntry( (dataEntryQ_t *)urfiGenericRxCmd.pParams->pRxQ);

      urfiGenericRxHandle = URFI_CMD_HANDLE_INVALID;
    }
  }

  port_exitCS_SW(key);
  port_exitCS_HW(key_h);
}

Replace ull_rxEntryDoneCback() in ull.c with the following

void ull_rxEntryDoneCback(void)
{
  uint8 dataLen;
  port_key_t key;
  port_key_t key_s;

  key = port_enterCS_HW();
  key_s = port_enterCS_SW();

  dataEntry_t *pDataEntry = ull_getNextDataEntry( (dataEntryQ_t *)urfiGenericRxCmd.pParams->pRxQ );

  /* get pointer to packet */
  if ( (pDataEntry == NULL) || (pDataEntry->status != DATA_ENTRY_FINISHED) )
  {
    port_exitCS_HW(key);
    port_exitCS_SW(key_s);

    /* nothing to do here */
    return;
  }

  /* process RX FIFO data */
  ull_getPDU( &dataLen, monitorPkt );

  /* in all cases, mark the RX queue data entry as free
   * Note: Even if there isn't any heap to copy to, this packet is considered
   *       lost, and the queue entry is marked free for radio use.
   */
  ull_nextDataEntryDone( (dataEntryQ_t *)urfiGenericRxCmd.pParams->pRxQ );

  port_exitCS_HW(key);
  port_exitCS_SW(key_s);

  /* TBD: monitorPkt can be dynamically allocated and application freed */

  /* We have a packet:
   *
   * | Preamble  | Access Addr | PDU         | CRC     |
   * | 1-2 bytes | 4 bytes     | 2-257 bytes | 3 bytes |
   *
   * The PDU is expended to (in case of RTLS_LOCATIONING_AOA defined)
   * | Header    | Payload     |
   * | 2-3 bytes | 1-255 bytes |
   *
   * If (Header[0] & 0x20 == 0x20) is true, then size of header is 3
   *
   * The Header is expended to:
   * | PDU Type...RxAdd | Length | Additional Info |
   * | 1 byte           | 1 byte |     1 byte      |
   *
   * The PDU is expended to (RTLS_LOCATIONING_AOA is NOT defined)
   * | Header  | Payload     |
   * | 2 bytes | 1-255 bytes |
   *
   * The Header is expended to:
   * | PDU Type...RxAdd | Length |
   * | 1 byte           | 1 byte |
   *
   * The radio stripps the CRC and replaces it with the postfix.
   *
   * The Postfix is expended to:
   * | RSSI   | Status | TimeStamp |
   * | 1 byte | 1 byte | 4 bytes   |
   *
   * The Status is expended to:
   * | bCrcErr | bIgnore | channel  |
   * | bit 7   | bit 6   | bit 5..0 |
   *
   * Note the monitorPkt is the beginning of PDU; the dataLen includes
   * the postfix length.
   *
   */
  if (dataLen != 0)
  {
    ull_notifyMonitorIndication( SUCCESS, ull_sessionId, dataLen, monitorPkt );
  }
  return;
}

8. TOF may fail to be enabled

Remove the following code form ToF.c::ToF_run()

  if (RF_cmdTof.bMaster != ToF_ROLE_SLAVE)
  {
    HWREG(TOF_CORRELATOR_PWR_ADDR) |=  TOF_CORRELATOR_PWR_MASK;
    HWREG(RFC_MCERAM_BASE + 30*4)   =  TOF_CORRELATOR_TRIM;
    HWREG(TOF_CORRELATOR_PWR_ADDR) &= ~TOF_CORRELATOR_PWR_MASK;
  }

Change RF_cmdFs.startTrigger.pastTrig = 1; to 0 and RF_cmdTof.startTrigger.pastTrig = 1; to 0.

9. The RTLS BLE libraries does not work on Windows 32 bit system

simplelink_cc2640r2_sdk_2_30_00_28

1. The TX output power was not initialized in the aoa project, which cause poor range performance when it comes to AoA.

The fix is to add the following line inside AoA.c :: static RF_RadioSetup aoaSetup =

.common.txPower                  = 0x9330,

2. There is issue regarding angle calculation in the AoA receiver project. When the I/Q signal is weak, the shift down >>10 inside AoA.c :: AngleComplexProductComp will cause the calculation to be off.

The fix is to replace content within these three functions inside AoA.c :: static inline int16_t iat2, int16_t iatan2sc, int16_t AngleComplexProductComp

static inline int16_t iat2(int32_t y, int32_t x) {
  return ((y*32+(x/2))/x)*2;  // 3.39 mxdiff
}
int16_t iatan2sc(int32_t y, int32_t x) {
  // determine octant
  if (y >= 0) {   // oct 0,1,2,3
    if (x >= 0) { // oct 0,1
      if (x > y) {
        return iat2(-y, -x)/2 + 0*32;
      } else {
        if (y == 0) return 0; // (x=0,y=0)
        return -iat2(-x, -y)/2 + 2*32;
      }
    } else { // oct 2,3
      // if (-x <= y) {
      if (x >= -y) {
        return iat2(x, -y)/2 + 2*32;
      } else {
        return -iat2(-y, x)/2 + 4*32;
      }
    }
  } else { // oct 4,5,6,7
    if (x < 0) { // oct 4,5
      // if (-x > -y) {
      if (x < y) {
        return iat2(y, x)/2 + -4*32;
      } else {
        return -iat2(x, y)/2 + -2*32;
      }
    } else { // oct 6,7
      // if (x <= -y) {
      if (-x >= y) {
        return iat2(-x, y)/2 + -2*32;
      } else {
        return -iat2(y, -x)/2 + -0*32;
      }
    }
  }
}
// Example code for processing IQ data
int16_t AngleComplexProductComp(int16_t Xre, int16_t Xim, int16_t Yre, int16_t Yim)
{
    int32_t Zre, Zim;
    int16_t angle;

    // X*conj(Y)
    Zre = Xre*Yre + Xim*Yim;
    Zim = Xim*Yre - Xre*Yim;

    // Angle. The angle is returned in 256/2*pi format [-128,127] values
    angle = iatan2sc(Zim, Zre);

    return (angle * angleconst);
}

3. Modifying the DEFAULT_ADVERTISING_INTERVAL when sending ADV_NONCONN_IND packets does not have any effect. To fix this, please make the following three changes inside AoA.c :: void AOA_run(AoA_Handle handle, uint8_t channel, AoA_AntennaConfig *config, uint8_t pktId)

Change:

RF_cmdBleAdvNc.startTrigger.pastTrig = 1;

RF_cmdNopTx.startTrigger.pastTrig = 1;


if (channel == 37)
{
   RF_cmdNopTx.startTime = RF_getCurrentTime() + RF_convertUsToRatTicks(5000);
}

to:

RF_cmdBleAdvNc.startTrigger.pastTrig = 0;

RF_cmdNopTx.startTrigger.pastTrig = 0;


if (channel == 37)
{
   RF_cmdNopTx.startTime = handle->startTime + RF_getCurrentTime() + RF_convertUsToRatTicks(5000);
}
else
{
   RF_cmdNopTx.startTime = RF_getCurrentTime() + RF_convertUsToRatTicks(500);
}

4. lib_search doesn't work for RF multi-mode on MacOS, therefore, you can't run aoa and tof examples on Mac

Regards,

Christin  

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

If the question is answered, please press the  Verify Answer button below the answer to help other users find the correct answer easily.

 

1 Reply

  • Super helpful!

    Cheers,
    Marie H.

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.