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 48655 points

Replies: 1

Views: 1130

Part Number: SIMPLELINK-CC2640R2-SDK

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. Fix various memory leaks in rtls_ctrl

Include the following near other #includes

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

Replace rtlsRunEvt_t structure definition with the following, (add status member).

typedef struct
{
  uint8_t status;
  uint32_t timeToNextEvent;
  int8_t rssi;
  uint8_t channel;
} rtlsRunEvt_t;

Add the following forward declaration near others (at the top of the file after #includes)

void RTLSCtrl_resetTof(rtlsTof_t *tofControlBlock);

Add status reporting to RTLSCtrl_syncEventNotify(), replace existing function with this one

void RTLSCtrl_syncEventNotify(rtlsStatus_e status, uint32_t timeToNextEvent, int8_t rssi, uint8_t channel)
{
  rtlsRunEvt_t *pMsg;

  if ((pMsg = (rtlsRunEvt_t *)RTLSCtrl_malloc(sizeof(rtlsRunEvt_t))) == NULL)
  {
    // We failed to allocate, host was already notified, just exit
    return;
  }

  pMsg->status = status;
  pMsg->timeToNextEvent = timeToNextEvent;
  pMsg->rssi = rssi;
  pMsg->channel = channel;

  RTLSCtrl_enqueueMsg(RTLS_RUN_EVENT, (uint8_t *)pMsg);
}

Add the following API to rtls_ctrl.c

void RTLSCtrl_resetTof(rtlsTof_t *tofControlBlock)
{
  // Close TOF Driver
  TOF_close(gRtlsData.tofControlBlock.tofHandle);

  // Free result/calibration arrays if they are allocated
  if (tofControlBlock->pTofAverage)
  {
    RTLSUTIL_FREE(tofControlBlock->pTofAverage);
  }

  if (tofControlBlock->pTofLastRun)
  {
    RTLSUTIL_FREE(tofControlBlock->pTofLastRun);
  }

  // Reset the control block
  memset(tofControlBlock, 0, sizeof(rtlsTof_t));
}

Add the following to RTLSCtrl_setTofParams() (line 731)

  // If ToF Driver was already open and we got a Set Params request, close and re-open
  // Flush all ToF params from control block
  if (gRtlsData.tofControlBlock.tofHandle)
  {
    RTLSCtrl_resetTof(&gRtlsData.tofControlBlock);
  }

Remove the following from RTLSCtrl_setTofParams()(line 702)

memset(tofDriverParams.pT1RSSIBuf, 0, T1RssiBufSize);

Remove the from RTLSCtrl_setTofParams() (line 732)

  // If ToF Driver was already open and we got a Set Params request, close and re-open
  // Flush all ToF params from control block
  if (gRtlsData.tofControlBlock.tofHandle)
  {
    TOF_close(gRtlsData.tofControlBlock.tofHandle);

    // Free result/calibration arrays if they are allocated
    if (gRtlsData.tofControlBlock.pTofLastRun)
    {
      RTLSUTIL_FREE(gRtlsData.tofControlBlock.pTofLastRun);
    }

    if (gRtlsData.tofControlBlock.pTofCalib)
    {
      RTLSUTIL_FREE(gRtlsData.tofControlBlock.pTofCalib);
    }

    if (gRtlsData.tofControlBlock.pTofLastRun)
    {
      RTLSUTIL_FREE(gRtlsData.tofControlBlock.pTofLastRun);
    }

    // Reset the control block
    memset(&gRtlsData.tofControlBlock, 0, sizeof(rtlsTof_t));
  }

Replace the contents of RTLSCtrl_tofChangeState() with the following

void RTLSCtrl_tofChangeState(rtlsEnableTofCmd_t *tofNewState)
{
  rtlsEnableTofCmd_t *tofEnable = tofNewState;
  uint8_t *syncReq;

  // Enable/disable Sync mechanism
  if ((syncReq = (uint8_t *)RTLSCtrl_malloc(sizeof(uint8_t))) == NULL)
  {
    // We failed to allocate, host was already notified, just exit
    return;
  }

  // If we are not in auto-mode, enable/disable Slave immediately
  if (gRtlsData.rtlsCapab.capab & RTLS_CAP_RTLS_MASTER &&
      gRtlsData.tofControlBlock.tofConfig.runMode != TOF_MODE_AUTO)
  {
    RTLSCtrl_sendRtlsRemoteCmd(RTLS_REMOTE_CMD_TOF_ENABLE, (uint8_t *)tofEnable, sizeof(rtlsEnableTofCmd_t));
    gRtlsData.tofControlBlock.bSlaveTofEnabled = tofEnable->enableTof;
  }

  *syncReq = tofEnable->enableTof;

  // Enable/disable sync events
  RTLSCtrl_callRtlsApp(RTLS_REQ_ENABLE_SYNC, syncReq);

  if (tofEnable->enableTof == RTLS_TRUE)
  {
    gRtlsData.connStateBm |= RTLS_STATE_TOF_ENABLED;
  }
  else
  {
    gRtlsData.connStateBm &= ~(RTLS_STATE_TOF_ENABLED);
  }
}

Add the following to the end of the RTLSCtrl_processRtlsPacket() function:

  if(pRtlsPkt != NULL)
  {
    RTLSUTIL_FREE(pRtlsPkt);
    pRtlsPkt = NULL;
  }

Replace the contents of RTLSCtrl_processHostMessage() with the following:

void RTLSCtrl_processHostMessage(rtlsHostMsg_t *pHostMsg)
{
  // Note that messages that stop in this module should be freed here
  // Messages that are passed to the application should NOT be freed here, they are freed by the receiver
  // Messages that do not have payload are not freed either
  if (pHostMsg->cmdType == HOST_SYNC_REQ)
  {
    switch(pHostMsg->cmdId)
    {
      case RTLS_CMD_IDENTIFY:
      {
        RTLSHost_sendMsg(RTLS_CMD_IDENTIFY, HOST_SYNC_RSP, (uint8_t *)&gRtlsData.rtlsCapab, sizeof(rtlsCapabilities_t));
      }
      break;

      case RTLS_CMD_SCAN:
      {
        RTLSCtrl_scanReqEvt();
      }
      break;

      case RTLS_CMD_CONNECT:
      {
        RTLSCtrl_connReqEvt(pHostMsg->pData);
      }
      break;

      case RTLS_CMD_TERMINATE_LINK:
      {
        RTLSCtrl_terminateLink();
      }
      break;

      case RTLS_CMD_RESET_DEVICE:
      {
        RTLSCtrl_resetDevice();
      }
      break;

#ifdef RTLS_LOCATIONING_AOA
      case RTLS_CMD_AOA_SET_PARAMS:
      {
        RTLSCtrl_setAoaParams(pHostMsg->pData);

        RTLSUTIL_FREE(pHostMsg->pData);
      }
      break;

      case RTLS_CMD_AOA_ENABLE:
      {
        RTLSCtrl_enableAoaCmd(pHostMsg->pData);

        RTLSUTIL_FREE(pHostMsg->pData);
      }
      break;
#else
      case RTLS_CMD_TOF_SET_PARAMS:
      {
        RTLSCtrl_setTofParams(pHostMsg->pData);

        RTLSUTIL_FREE(pHostMsg->pData);
      }
      break;

      case RTLS_CMD_TOF_ENABLE:
      {
        RTLSCtrl_enableTofCmd(pHostMsg->pData);

        RTLSUTIL_FREE(pHostMsg->pData);
      }
      break;

      case RTLS_CMD_TOF_GET_SEC_SEED:
      {
        RTLSCtrl_getTofSecSeed();
      }
      break;

#ifdef RTLS_PASSIVE
      case RTLS_CMD_TOF_SET_SEC_SEED:
      {
        RTLSCtrl_setTofSecSeed(pHostMsg->pData);

        RTLSUTIL_FREE(pHostMsg->pData);
      }
      break;
#endif // RTLS_PASSIVE
#endif // !(RTLS_LOCATIONING_AOA) - RTLS_LOCATIONING_TOF

#ifdef RTLS_PASSIVE
      case RTLS_CMD_CONN_PARAMS:
      {
        // Note that passive receives a different data structure than the master
        RTLSCtrl_connReqEvt(pHostMsg->pData);
      }
      break;
#endif

      default:
      {
        rtlsStatus_e status = RTLS_ILLEGAL_CMD;
        RTLSHost_sendMsg(RTLS_CMD_ERROR, HOST_SYNC_RSP, (uint8_t *)&status, sizeof(rtlsStatus_e));
      }
      break;
    }
  }
}

Add the following to rtls_ctrl.h

#ifdef USE_ICALL
#include "icall.h"
#endif

Within rtls_ctrl.h, replace everything between MACROS and TYPEDEFS with the following:

#ifdef USE_ICALL
#define RTLSUTIL_MALLOC(pAlloc, size) {                               \
                                        pAlloc = ICall_malloc(size);  \
                                      }

#define RTLSUTIL_FREE(pMsg)           ICall_free(pMsg)
#else
#define RTLSUTIL_MALLOC(pAlloc, size) {                           \
                                        volatile uint32_t keyHwi; \
                                        volatile uint32_t keySwi; \
                                        keyHwi = Hwi_disable();   \
                                        keySwi = Swi_disable();   \
                                        pAlloc = malloc(size);    \
                                        Swi_restore(keySwi);      \
                                        Hwi_restore(keyHwi);      \
                                      }

#define RTLSUTIL_FREE(pFree)          {                           \
                                        volatile uint32_t keyHwi; \
                                        volatile uint32_t keySwi; \
                                        keyHwi = Hwi_disable();   \
                                        keySwi = Swi_disable();   \
                                        free(pFree);              \
                                        pFree = NULL;             \
                                        Swi_restore(keySwi);      \
                                        Hwi_restore(keyHwi);      \
                                      }
#endif

Add the following to rtls_ctrl_aoa.c (near other #includes)

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

Replace the definition of RTLSCtrl_syncEventNotify() in rtls_ctrl_api.h with the following

void RTLSCtrl_syncEventNotify(rtlsStatus_e status, uint32_t timeToNextEvent, int8_t rssi, uint8_t channel);

Add the following to rtls_ctrl_tof.c (at top near other includes)

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

Replace the contents of TOFSecurity_open() with the following

int TOFSecurity_open(tofSecHandle_t *tofSecHandle, tofSecCfgPrms_t *tofSecCfgPrms)
{
	uint16_t sizeOfBuffToAlloc;

  //  Verify params valid
  if((0 == tofSecCfgPrms->syncWordSize) || (0 == tofSecCfgPrms->totalNumOfSyncWords))
  {
    return TOF_SEC_INVALID_PRMS_FAIL_E;
  }
  
  // Copy configuration parameters to handle
  memcpy(&(tofSecHandle->tofSecCfgParams),tofSecCfgPrms, sizeof(tofSecCfgPrms_t));

  // Init buffer/s sizes
  if(TOF_MODE_DBL_BUF == tofSecHandle->tofSecCfgParams.bUseDoubleBuffer)
  {
    tofSecHandle->numOfSyncWordsPerBuffer = TOF_SEC_DBL_BUFF_SIZE;
  }
  else
  {
    tofSecHandle->numOfSyncWordsPerBuffer = tofSecCfgPrms->totalNumOfSyncWords;
  }

	// Calculate size of buffer/s
  sizeOfBuffToAlloc = sizeof(uint8_t) * tofSecCfgPrms->syncWordSize * tofSecHandle->numOfSyncWordsPerBuffer;

	// Allocate first buffer
  RTLSUTIL_MALLOC(tofSecHandle->pSyncWordBuffer1, sizeOfBuffToAlloc);
  if(NULL == (tofSecHandle->pSyncWordBuffer1))
  {
    RTLSUTIL_FREE(tofSecHandle);
    return TOF_SEC_ALLOC_FAIL_E;
  }

  // Allocate 2nd buffer?
  if(TOF_MODE_DBL_BUF == tofSecCfgPrms->bUseDoubleBuffer)
  {  
    RTLSUTIL_MALLOC(tofSecHandle->pSyncWordBuffer2, sizeOfBuffToAlloc);
    if(NULL == (tofSecHandle->pSyncWordBuffer2))
    {
      RTLSUTIL_FREE(tofSecHandle->pSyncWordBuffer1);
      RTLSUTIL_FREE(tofSecHandle);
      return TOF_SEC_ALLOC_FAIL_E;
    }
  }

  // Init AES128 hardware
  CryptoCC26XX_init();
  CryptoCC26XX_Params_init(&(tofSecHandle->encParams));

  tofSecHandle->encHandle = CryptoCC26XX_open(0, FALSE, &(tofSecHandle->encParams));
  if(NULL == tofSecHandle->encHandle)
  {
    RTLSUTIL_FREE(tofSecHandle->pSyncWordBuffer1);

    if(TOF_MODE_DBL_BUF == tofSecCfgPrms->bUseDoubleBuffer)
    {
      RTLSUTIL_FREE(tofSecHandle->pSyncWordBuffer2);
    }
    RTLSUTIL_FREE(tofSecHandle);

    return TOF_SEC_AES_FAIL_E;
  }

  // allocate a key store index
  // Note: A key does not have to be specified at this time, and can be loaded as needed.
  tofSecHandle->encKey = CryptoCC26XX_allocateKey(tofSecHandle->encHandle, CRYPTOCC26XX_KEY_ANY, NULL);
  ASSERT(CRYPTOCC26XX_STATUS_ERROR != (int)tofSecHandle->encKey);

  return TOF_SEC_SUCCESS_E;
}

6a. Update RTLS sample applications to support above changes to RTLSCtrl_syncEventNotify()

In rtls_master.c replace RTLSMaster_connEvtCB() with the following

static void RTLSMaster_connEvtCB(Gap_ConnEventRpt_t *pReport)
{
  if (CONNECTION_EVENT_REGISTRATION_CAUSE(FOR_TOF))
  {
    rtlsStatus_e status;

    // Convert BLE specific status to RTLS Status
    if (pReport->status != GAP_CONN_EVT_STAT_MISSED)
    {
      status = RTLS_SUCCESS;
    }
    else
    {
      status = RTLS_FAIL;
    }

    RTLSCtrl_syncEventNotify(status, pReport->nextTaskTime, pReport->lastRssi, pReport->channel);
  }

  if (pReport != NULL)
  {
    // Free the report once we are done using it
    ICall_free(pReport);
  }
}

In rtls_passive.c replace RTLSPassive_monitorCompleteEvt() with the following:

static void RTLSPassive_monitorCompleteEvt(uint8_t *pData)
{
  monitorCompleteEvt_t *pCompleteEvt = (monitorCompleteEvt_t *)pData;
  uint32_t nextStartTime;
  uint32_t currentTime;
  uint32_t nextEventTimeUs;
  int8_t slaveRssi;
  uint8_t channel;
  rtlsStatus_e status;

  // Convert CM Status to RTLS Status
  if (pCompleteEvt->status == CM_SUCCESS)
  {
    status = RTLS_SUCCESS;
  }
  else
  {
    status = RTLS_FAIL;
  }
  
   // Set up the next monitor session
  (void)ubCM_start(ubCM_findNextPriorityEvt());

  if (gRtlsSyncEnabled == RTLS_TRUE)
  {
    // Get the next start time
    nextStartTime = ubCMConnInfo.ArrayOfConnInfo[pCompleteEvt->sessionId - 1].nextStartTime;

    currentTime = RF_getCurrentTime();
    nextEventTimeUs = RF_convertRatTicksToUs(nextStartTime - currentTime);

    // We are interested in the slave RSSI and channel
    slaveRssi = (int8_t)ubCMConnInfo.ArrayOfConnInfo[pCompleteEvt->sessionId - 1].rssiSlave;
    channel = (uint8_t)ubCMConnInfo.ArrayOfConnInfo[pCompleteEvt->sessionId - 1].currentChan;

    RTLSCtrl_syncEventNotify(status, nextEventTimeUs, slaveRssi, channel);
  }
}

In rtls_slave.c replace the contents of RTLSSlave_processConnEvt() with the following

static void RTLSSlave_processConnEvt(Gap_ConnEventRpt_t *pReport)
{ 
  if (CONNECTION_EVENT_REGISTRATION_CAUSE(FOR_ATT_RSP))
  {
    // The GATT server might have returned a blePending as it was trying
    // to process an ATT Response. Now that we finished with this
    // connection event, let's try sending any remaining ATT Responses
    // on the next connection event.
    RTLSSlave_sendAttRsp();
  }

  // Do a TOF Run, at the end of the active connection period
  if (CONNECTION_EVENT_REGISTRATION_CAUSE(FOR_TOF))
  {
    rtlsStatus_e status;

    // Convert BLE specific status to RTLS Status
    if (pReport->status != GAP_CONN_EVT_STAT_MISSED)
    {
      status = RTLS_SUCCESS;
    }
    else
    {
      status = RTLS_FAIL;
    }

    RTLSCtrl_syncEventNotify(status, pReport->nextTaskTime, pReport->lastRssi, pReport->channel);
  }
}

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.

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.