SimpliciTI FAQ

From Texas Instruments Wiki
Jump to: navigation, search

Contents

Starting with SimpliciTI - projects, examples, IDE related questions

Out of the box, the Simple-Peer-To-Peer application doesn't seem to work, what did i do wrong?

Please make sure that the LinkTo and LinkListen application have different device address which is defined in smpl_config.dat file (THIS_DEVICE_ADDRESS). In order to enable both devices to communicate with each others, each device must have a unique device address. This means when compiling each application (LinkTo and LinkListen), the macro THIS_DEVICE_ADDRESS shall be changed to different device addresses.

If this doesn't fix the probelm, it is advised to check the packets by using the packet sniffer.


How to Compile SimpliciTI with CCS?

This is described in the SimpliciTI documentation SWRA243 SimpliciTI Sample Application User's Guide - chapter 2.3.2 "Using Code Composer Studio" (usually can be found at C:\Texas Instruments\SimpliciTI-CCS-1.1.1\Documents). Basically it is necessary to define the DEV_ROOT path for the linked resources to the SimpliciTI installation folder path (usually C:\Texas Instruments\SimpliciTI-CCS-1.1.1).

If the SimpliciTI project is copied to another directory outside the SimpliciTI installation folder (by clicking the "Copy projects into workspace" checkbox when importing the CCS project into other folder), it is necessary then to modify the Include path shown as follows:

  • Defining SMPL_ROOT build environment path
Smpl root.PNG
  • Modifying path to the SimpliciTI source folder location
Smpl include path.PNG


How to create custom CCS project with SimpliciTI

In some application, it could be necessary to make a custom CCS project which only refers to the SimpliciTI stack source code, while the application code and the command/configuration file are set to be project specific. Please refer to the following wiki page for the step by step guide for CCS v5 and CCS v4.


Problem in modifying Configuration Files

When having problem in modifying configuration files (smpl_config.dat or smpl_nwk_config.dat), make sure that the project settings refer to the correct project files.

CCSTUDIO (CCS) v5

Right click on the .dat file and select "Properties" (or press Alt+Enter after left click on the file), note the "Location" path of the file. Compare the "Location" path with the one in Project Settings which can be found under "Project" -> "Properties" -> "Build" -> "MSP430 Compiler" -> "Command Files".

Config file location path (left), CCS Config file project setting (middle)

IAR EWB

Right click on the .dat file and select "File Properties...", note the "Location" path of the file. Compare the "Location" path with the one in Project Settings which can be found under "Project" -> "Options" -> "C/C++ Compiler" -> "Extra Options".

Config file location path (left), IAR Config file project setting (right)


I am trying to compile SimpliciTI IAR project but it fails

When trying to compile SimpliciTI IAR project using newer IAR version, it might happen that the compilation fails due to the wrong path of the linker configuration file. For example when trying to compile SimpliciTI-IAR-1.2.0 for CC1110 on IAR 8051 EWB v8.x, the compilation will give the following error:

Error[e12]: Unable to open file 'C:\Program Files\IAR Systems\Embedded Workbench 6.0_0\8051\config\lnk51ew_cc1110.xcl'


Smpl newer iar link error.PNG


This can be easily solved by selecting the correct path to the linker configuration file by going to "Project" -> "Options..." (or press ALT + F7), choose "Linker " category and select the correct path to the linker configuration file as shown follows:


Smpl newer iar linker cfg file path.PNG


As shown above, for example with CC1110, the path should be change from "$TOOLKIT_DIR$\config\lnk51ew_cc1110.xcl" to "$TOOLKIT_DIR$\config\devices\Texas Instruments\lnk51ew_cc1110F32.xcl"


How big is the memory footprint of SimpliciTI software stack?

The answer basically depends on the compile option settings which is used to compile the SimpliciTI Stack (device type, security setting, , etc.). And of course the processor achitecture and compiler also play roles in determining the memory footprint. There are some numbers which can be found here:SimpliciTI#Memory_Requirements, basically derived from out-of-the box compilation. So basically typically, the SimpliciTI stack requires around 5KB - 10KB flash, and for the RAM footprint, it really varies depending on the some factors:

  • Maximum number of connections (NUM_OF_CONNECTIONS compiler option): for each connection, the stack will require between 11 - 20 bytes of RAM size (depending on compile options APP_AUTO_ACK and SMPL_SECURE), which is basically the size of connInfo_t data type defined in nwk.h.
  • Number of message buffer queues: there are basically two kind of message buffer queues: incoming and outgoing message buffers, and the number of buffers in each queues are defined as compile options SIZE_INFRAME_Q and SIZE_OUTFRAME_Q respectively. Each buffers then will occupy the size of frameInfo_t data type defined in nwk_frame.h. The size of framInfo_t depends also on the compile option MAX_NWK_PAYLOAD and MAX_APP_PAYLOAD. If greater value between MAX_NWK_PAYLOAD and MAX_APP_PAYLOAD will be taken as the maximum payload data of SimpliciTI packets (see the beginning of mrfi.h), and counted in the calculation of maximum SimpliciTI frame size (MRFI_MAX_FRAME_SIZE).


Including Radio and MCU Specific Code

In the SimpliciTI projects, only bsp.c and mrfi.c code are directly included in the project. The MCU and Radio specific codes which are located under <SIMPLICITI_BASE_FOLDER>/Components/bsp/boards and <SIMPLICITI_BASE_FOLDER>/Components/mrfi/radios are included by bsp.c and mrfi.c hard-coded in the source.

For the processor specific source code, the code includes the bsp_board.c and the bsp_drivers.c directly in the code of bsp.c as follows:

/* ================================================================================================
 *                                        C Code Includes
 * ================================================================================================
 */
#ifdef BSP_BOARD_C
#include BSP_BOARD_C
#endif
 
#ifdef BSP_DRIVERS_C
#include BSP_DRIVERS_C
#endif

while in the bsp_drivers.c, the code will also include the BSP code for push buttons and LEDs as follows:

/* ================================================================================================
 *                                        C Code Includes
 * ================================================================================================
 */
#if (!defined BSP_NO_LEDS)
#include "drivers/code/bsp_leds.c"
#endif
 
#if (!defined BSP_NO_BUTTONS)
#include "drivers/code/bsp_buttons.c"
#endif

The stack choose the respective MCU BSP according to the selected include path in the project setting, e.g. for IAR projects:

SimpliciTI IAR ProjectSetting IncludeBspPath.PNG

In the screen capture above, it is also shown that by declaring MRFI_CCXXXX, the mrfi.c will choose which radio specific to be compiled:

* ------------------------------------------------------------------------------------------------
 *                                       C Code Includes
 * ------------------------------------------------------------------------------------------------
 */
 
/* ----- Radio Family 1 ----- */
#if (defined MRFI_RADIO_FAMILY1)
#include "radios/family1/mrfi_radio.c"
#include "radios/family1/mrfi_spi.c"
#include "radios/common/mrfi_f1f2.c"
#include "bsp_external/mrfi_board.c"
 
/* ----- Radio Family 2 ----- */
#elif (defined MRFI_RADIO_FAMILY2)
#include "radios/family2/mrfi_radio.c"
#include "radios/common/mrfi_f1f2.c"
 
/* ----- Radio Family 3 ----- */
#elif (defined MRFI_RADIO_FAMILY3)
#include "bsp_external/mrfi_board.c"
#include "radios/family3/mrfi_spi.c"
#include "radios/family3/mrfi_radio.c"
 
/* ----- Radio Family 4 ----- */
#elif (defined MRFI_RADIO_FAMILY4)
#include "radios/family4/mrfi_radio.c"
 
/* ----- Radio Family 5 ----- */
#elif (defined MRFI_RADIO_FAMILY5)
#include "radios/family5/mrfi_radio.c"
#include "radios/family5/mrfi_radio_interface.c"
 
/* ----- Radio Family 6 ----- */
#elif (defined MRFI_RADIO_FAMILY6)
#include "radios/family6/mrfi_radio.c"
 
#else
#error "ERROR: Radio family is not defined."
#endif



Practical FAQ

Debugging RF Connection

  • Make sure that the RF configuration between the transmitter and the receiver match each other. Use SmartRF Studio to generate the smartrf header files used in the stack, and SmartRF Packet Sniffer to see whether the packet is correctly transmitted. If possible try to make both devices to transmit packets and check by using a spectrum analyzer whether the node is operating at the same carrier frequency. Refer to the following guide for getting the test code to test the RF setting using spectrum analyzer.
  • Make sure that if the device is operated as End Device only (RX will be switched off per default during init for End Device), that the RX is turned on explicitly by the application by calling the following line code.
   /* turn on RX. default is RX off. */
   SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0);
  • Make sure that both transmitter and receive node using the same network configuration settings for: SMPL_SECURE (also same key), FREQUENCY_AGILITY, FREQUENCY_HOPPING, APP_AUTO_ACK).
  • Try to debug whether the RX interrupt of the RX module is invoked during a packet reception. This can be done by putting a breakpoint at the following functions:
    • Family 1 Radio (CC2500, CC1100, CC1100, CC110L, CC1100E): MRFI_GpioIsr() in mrfi_radio.c
    • Family 2 Radio (CC2510, CC2511, CC1110, CC1111): MRFI_RfIsr() in mrfi_radio.c
    • Family 3 Radio (CC2520, CC2420): Mrfi_FiFoPIsr() in mrfi_radio.c
    • Family 4 Radio (CC2430, CC2431): MRFI_RxIsr() in mrfi_radio.c
    • Family 5 Radio (CC430): Mrfi_SyncPinRxIsr() in mrfi_radio.c
    • Family 6 Radio (CC2530): MRFI_RxIsr() in mrfi_radio.c
    • Family 7 Radio (CC1120): MRFI_GpioIsr() in mrfi_radio.c

If the functions are not invoked (breakpoint is not triggered), check whether the interrupt is activated during initialization). If the functions are invoked, set breakpoint to the following functions which will be called later on during packet reception process:

  • MRFI_RxCompleteISR() in nwk_frame.c : if this function is not called, most probably the received packet fails during basic RF checking such as checksum, etc. Do step by step debugging on the function listed above to find out the failure.
  • dispatchFrame() in nwk_frame.c : if this function is not called after MRFI_RxCompleteIsr(), most probably the node fails to allocated a receive buffer (nwk_QfindSlot(INQ)) for containing the incoming buffer).
  • lastly the incoming packet will be processed inside dispatchFrame() function to determine whether it is a network (port 0x00-0x1F) or user (port 0x20 - 0x3F) application related. If it is a user application related, the user callback which is registered during SMPL_Init() shall be called. If this fails, try to debug step-by-step debugging in dispatchFrame() function.

NOTE: Per default, all SimpliciTI projects are released with the highest compiler optimization level. In order to be able to debug the code properly, it might be necessary to set the compiler optimization to lower level.


How to change radio configuration of SimpliciTI's supported RF modules?

For each radio/RF module (list of supported radios can be found here: SimpliciTI#Supported_RF_modules), SimpliciTI implements dedicated code which can be found under <SIMPLICITI_BASE_FOLDER>\Components\mrfi\radios folder. The code uses the radio configuration which is stored in the header file which can be found under <SIMPLICITI_BASE_FODER>\Components\mrfi\smartrf folder.

If it is necessary to change the radio settings, the SmartRF Studio can be used to generate the header file containing the custom radio configuration. Please refer to the following wiki for using SmartRF Studio to generate the RF parameter header file for SimpliciTI: SimpliciTI_-_Configuring_RF_Setting.

Compatibility Between Different Transceivers

Several things to be noticed when trying to ensure the compatibility between different transceivers:

  • Standards RF settings such as base/carrier frequency, data rate, modulation, deviation/power, receive filter bandwidth, etc.
  • Bit and byte synchronization/Preamble and sync word settings:
    • For the CC110x and CC111x transceivers, the preamble bits length is configured by MDMCFG1.NUM_PREAMBLE, while the sync words are configured by MDMCFG2.SYNC_MODE for the length SYNC1, SYNC0 for the sync word bytes content.
    • For CC1120 transceivers, the premable bits length and format are configured by PREAMBLE_CFG1.NUM_PREAMBLE and PREAMBLE_CFG1.PREAMBLE_WORD respectively, while the sync words are configured by the SYNC_CFG0.SYNC_MODE for the length and the four registers SYNC0-3 for sync word bytes content.
  • Special Note on CC1120 SimpliciTI porting: since the CC1120 transceiver doesn't implement automatic channel programming such as the other CC11xx with the CHANNR register, the carrier frequency is hard-coded in the code which can be found in the mrfiLogicalChanTable[][] array in mrfi_radio.c. Therefore the SMARTRF_SETTING_FREQ0, SMARTRF_SETTING_FREQ1, SMARTRF_SETTING_FREQ2 setting from the generated smartRF_CC1120.h are not used.


What is the maximum number of devices in SimpliciTI network?

Practically, it can be said that there is basically "no constraint" on the maximum number of devices in SimpliciTI network considering the 4 byte device address. The main constraint of maximum number of End Devices especially in a star topology network (AP as data hub) is basically the data memory size (RAM size) of the Access Point for maintaining the whole connection data. For each connection, the SimpliciTI node needs to allocate a connInfo_t structure (defined in nwk.h) which has the size between 11-14 bytes (depending on the APP_AUTO_ACL and SMPL_SECURE configuration) - might be more if the compiler tries to align the member variables of the structure:

typedef struct
{
  volatile uint8_t     connState;
           uint8_t     hops2target;
#ifdef APP_AUTO_ACK
  volatile uint8_t     ackTID;
#endif
           uint8_t     peerAddr[NET_ADDR_SIZE];
           rxMetrics_t sigInfo;
           uint8_t     portRx;
           uint8_t     portTx;
           linkID_t    thisLinkID;
#ifdef SMPL_SECURE
           uint32_t    connTxCTR;
           uint32_t    connRxCTR;
#endif
} connInfo_t;

Please refer to the following discussions in E2E forum:

NOTE: Limitation in the SimpliciTI code (up to v1.2.0) : in these versions, the code will use 8 bit variable data type for the linkID_t:

typedef uint8_t linkID_t;


and also the iteration variables i when trying to read the connInfo_t connStruct of sPersistInfo such as the following:

connInfo_t *nwk_findPeer(addr_t *peerAddr, uint8_t peerPort)
{
  uint8_t     i;
  connInfo_t *ptr = sPersistInfo.connStruct;
 
  for (i=0; i<SYS_NUM_CONNECTIONS; ++i, ++ptr)
  {
    if (CONNSTATE_CONNECTED == ptr->connState)
    {
      if (!memcmp(peerAddr, ptr->peerAddr, NET_ADDR_SIZE))
      {
        if (peerPort == ptr->portTx)
        {
          return ptr;
        }
      }
    }
  }
 
  return (connInfo_t *)NULL;
}

This will limit basically the number of connections to 256. If necessary, change the linkID_t data type in nwk_types.g and go through the code and changing these iteration variable (e.g. as uint16_t).


What is actually a "port" in SimpliciTI?

The following citation is taken from the SimpliciTI specification in SimpliciTI v1.2.0 documentation regarding the port concept in SimpliciTI:

"Ports are conceptual abstractions that specify the target application handling the frame. The Port numbers 0x00-0x1F are reserved or assigned as “well known Ports:” with specific services. They are intended for use by network management. Port numbers 0x20-0x3F are mapped to user handlers. Port 0x3F is reserved as a broadcast Port to be used when the sending device has not been explicitly linked 2 to the receiving device. Port numbers starting at 0x3E and decreasing are reserved for static allocation by user configurations. This arrangement is intended to accommodate commissioning scenarios."


How can i send address a message to a certain device? The SMPL_Send() function seems to not have any parameter for device addressing

The basic concept of SimpliciTI is peer-to-peer communication, where the connection is established only between two nodes. To establish the connection, a node has to call SMPL_Link(linkID_t *linkID) function and the other node shall call SMPL_LinkListen(linkID_t *linkID) function. Both functions have a parameter which is a pointer to a local buffer residing on the application side.

When the SMPL_Link() and SMPL_LinkListen() functions return successfully, the local buffer will contain the handle of the established connection which can be used later to send or receive messages from the other node. Therefore it is not necessary to work with device addresses on application level, rather it shall only use the link ID handle of the established connection.

The following code snippet shows how the usual SimpliciTI connection is established and used:

Node 1 Node 2

linkID_t linkID1;

.........

// initialize SimpliciTI stack
SMPL_Init(RxCallback);

.........

// send Link request until connection established
while(SMPL_Link(&linkID1) != SMPL_SUCCESS);

.........

// send a message
SMPL_Send(linkID1, OutMsg, OutMsgLen);

linkID_t linkID2;

.........

// initialize SimpliciTI stack
SMPL_Init(RxCallback);

.........

// listen for Link request until connection established
while(SMPL_LinkListen(&linkID2) != SMPL_SUCCESS);

.........

// receive a message
SMPL_Receive(linkID2, InMsg, &InMsgLen);

This is just a simple example describing how the communication is usually done. For real application, refer to the Simple-Peer-To-Peer application which can be found in the SimpliciTI software package.


How to send a broadcast message in SimpliciTI?

To send a broadcast message, use SMPL_LINKID_USER_UUD (defined in nwk.h) as link ID parameter for the SMPL_Send() function.

SMPL_Send(SMPL_LINKID_USER_UUD, msg, msg_len);

For the receiver, it is also necessary to call the SMPL_Receive() function with SMPL_LINKID_USER_UUD as link ID parameter, and if a receive callback is registered with SMPL_Init() function, it will be notified. However polling devices will not get the broadcast messages.

SimpliciTI will always allocate connection handler with the number of NUM_CONNECTIONS+1 (see persistentContext_t structure type in nwk.c which has connStruct[SYS_NUM_CONNECTIONS] with SYS_NUM_CONNECTIONS is defined as (NUM_CONNECTIONS+1)). The last connStruct handler is initialized to handle broadcast messages (see the last part of nwk_nwkInit() function in nwk.c).


How to disconnect an established connection between two nodes?

SimpliciTI v1.1.x and v1.2.x supports SMPL_Unlink() API which is activated if the stack is compiled with EXTENDED_API option. The unlink process can be triggered by calling the SMPL_Unlink() on either node in the connection.

This is a preferred way to disconnect an establised connection between two nodes rather than doing SMPL_Ioctl() with IOCTL_OBJ_CONNOBJ and IOCTL_ACT_DELETE. Both ways will basically erase the connection configuration in the stack of the local node (by calling nwk_freeConnection()), however calling the SMPL_Unlink() the node will send a unlink request to the remote node so that the remote node can also delete its connection configuration.

When the remote node receives the unlink request, it will trigger the smpl_send_unlink_reply() function (nwk_link.c) and also the reply frame.


Does SimpliciTI support message acknowledgement?

Yes. SimpliciTI support message acknowledgement on NWK layer level, which means from application point of view, it will never get the acknowledge message from the RxCallback function (parameter of SMPL_Init() function), instead the only way to know whether the sent message has been ack-ed or not by getting the return value of SMPL_SendOpt().

If a message is sent using SMPL_SendOpt() with SMPL_TXOPTION_ACKREQ flag option (with also APP_AUTO_ACK and EXTENDED_API compile options activated), the function will takes care the ACK checking by itself. If the function succeeds returning SMPL_SUCCESS, this means the sent message has been acknowledge. If the message is successfully sent but no ACK is received, the function will return SMPL_NO_ACK.

The following part of SMPL_SendOpt() function in nwk_api.c shows how the sending and message with acknowledgement request is done:

smplStatus_t SMPL_SendOpt(linkID_t lid, uint8_t *msg, uint8_t len, txOpt_t options)
{
 
  ...................................................
  /* Build an outgoing message frame destined for the port from the
   * connection info using the destination address also from the
   * connection info.
   */
  if (SMPL_TXOPTION_NONE == options)
  {
    pFrameInfo = nwk_buildFrame(pCInfo->portTx, msg, len, pCInfo->hops2target);
  }
#if defined(APP_AUTO_ACK)
  else if (options & SMPL_TXOPTION_ACKREQ)
  {
    if (SMPL_LINKID_USER_UUD != lid)
    {
      pFrameInfo = nwk_buildAckReqFrame(pCInfo->portTx, msg, len, pCInfo->hops2target, &pCInfo->ackTID);
      ackreq     = 1;
    }
    else
    {
      /* can't request an ack on the UUD link ID */
      return SMPL_BAD_PARAM;
    }
  }
#endif  /* APP_AUTO_ACK */
 
  ...................................................
 
#if !defined(APP_AUTO_ACK)
  /* save a little code space with this #if */
  (void) ackreq;    /* keep compiler happy */
  return rc;
#else
  /* we're done if the send failed or no ack requested. */
  if (SMPL_SUCCESS != rc || !ackreq)
  {
    return rc;
  }
 
  NWK_CHECK_FOR_SETRX(radioState);
  NWK_REPLY_DELAY();
  NWK_CHECK_FOR_RESTORE_STATE(radioState);
 
  {
    bspIState_t intState;
 
    /* If the saved TID hasn't been reset then we never got the ack. */
    BSP_ENTER_CRITICAL_SECTION(intState);
    if (pCInfo->ackTID)
    {
      pCInfo->ackTID = 0;
      rc = SMPL_NO_ACK;
    }
    BSP_EXIT_CRITICAL_SECTION(intState);
  }
 
  return rc;
#endif  /* APP_AUTO_ACK */
}

As shown above in the upper part of the code above, if APP_AUTO_ACK (and EXTENDED_API) is enabled and the SMPL_SendOpt() function is called with SMPL_TXOPTION_ACKREQ option bit set, it will then call nwk_buildAckReqFrame() which basically calls also nwk_buildFrame() and with addition setting the ACK REQ bit in the DEVICE INFO byte of the NWK Header. The lower part of the code also shows that the function will do some delay to wait for the incoming acknowledgement.

The following figure shows how the acknowledgement request/reply packets look like:

Smpl ack example dump.PNG


What is the Token used for?

Token are usually used as application unique specifier which distinguish one application with another. It could also be considered to have the same function as PAN ID in Zigbee, where in Zigbee devices can only connect and communication with each other within a PAN ID, while in SimpliciTI devices can only connect and communication with each other if they have the same token. There are basically two types of tokens in SimplciTI: Link Token and Join Token, and both can be changed during run time by using SMPL_Ioctl() function with object IOCTL_OBJ_TOKEN and defined EXTENDED_API.

The tokens shall be changed before initializing the SimpliciTI stack by calling SMPL_Init(). However if necessary changing the tokens should be possible after stack initialization shall be done by disabling the interrupt or radio reception in order to avoid false processing on the token of the incoming messages (the token is used for filtering the incoming message - see below).


Link Token

Join token is usually used in peer to peer topology where there is no Access Point (AP) involved. In the peer-to-peer topology, the two nodes can only establish connection if both have the same Link Token. The Link Token is implemented as sLinkToken in nwk_link.c, and used on the device which is doing SMPL_LinkListen() for comparing the Link Token of the incoming Link message:

static uint8_t smpl_send_link_reply(mrfiPacket_t *frame)
{
  ..................
  /* see if token is correct */
  {
    uint32_t lt;
 
    nwk_getNumObjectFromMsg(MRFI_P_PAYLOAD(frame)+F_APP_PAYLOAD_OS+L_LINK_TOKEN_OS, &lt, sizeof(lt));
    if (lt != sLinkToken)
    {
      return SENT_NO_REPLY;
    }
  }
  ..................


Join Token

The Join Token is used in star topology where an Access Point (AP) is involved. In the star topology, an End Device can only join the Access Point (AP) if both have the same Join Token. The Join Token is implemented as sJoinToken in nwk_join.c, and used by the AP for comparing the Join Token of the incoming Join message:

static void smpl_send_join_reply(mrfiPacket_t *frame)
{
  ..................
  /* see if join token is correct */
  {
    uint32_t jt;
 
    nwk_getNumObjectFromMsg(MRFI_P_PAYLOAD(frame)+F_APP_PAYLOAD_OS+J_JOIN_TOKEN_OS, &jt, sizeof(jt));
    if (jt != sJoinToken)
    {
      return;
    }
  }
  ..................

If the Join Token in the Join request message sent by the End Device matches the Join Token of the AP, the AP will send a reply which contains the Link Token which shall then be used by the End Device.

smplStatus_t nwk_join(void)
{
    ..................
    // sending the Join request
    SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_WRITE, &ioctl_info.send);
 
    ..................
 
    NWK_REPLY_DELAY();
 
    ..................
    if (SMPL_SUCCESS == SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_READ, &ioctl_info.recv))
    {
      uint8_t firstByte = msg[JB_REQ_OS] & (~NWK_APP_REPLY_BIT);
 
      /* Sanity check for correct reply frame. Older version
       * has the length instead of the request as the first byte.
       */
      if ((firstByte == JOIN_REQ_JOIN) ||
          (firstByte == JOIN_REPLY_LEGACY_MSG_LENGTH)
         )
      {
        /* join reply returns link token */
        memcpy(&linkToken, msg+JR_LINK_TOKEN_OS, sizeof(linkToken));
 
        nwk_setLinkToken(linkToken);  // use new Link Token from Join reply message
    ..................


Port Allocation in SimpliciTI

There are two types of port allocation schemes in SimpliciTI: dynamic and static port allocation.

Dynamic Port Allocation

The Dynamic Port Allocation is done by calling the nwk_allocateLocalRxPort() function when sending LINK request or LINK response to establish a connection between two nodes. Each node will allocate a port number between PORT_BASE_NUMBER (0x20) and SMPL_PORT_USER_MAX (0x3E - PORT_USER_STATIC_NUM). The dynamic port number assignment is bottom-up for sending LINK request and top-down for sending LINK response.

Static Port Allocation

The Static Port Allocation is usually done together with SMPL_Commission() function. The number of static port(s) is defined as PORT_USER_STATIC_NUM, and the static port number is assigned as the numbers between SMPL_PORT_STATIC_MAX (0x3E) and the maximum dynamic port number SMPL_PORT_USER_MAX (SMPL_PORT_STATIC_MAX - PORT_USER_STATIC_NUM).


Modifying Power Setting in SimpliciTI

The power settings are housed in an array in the mrfi_radio.c file, and the array is named as mrfiRFPowerTable. The values of the array are settings for the PATABLE registers and the default value used by SimpliciTI is the last entry in the table. Note SimpliciTI only utilizes a two state power level for OOK and only a one state power level for all other modes of modulation. Thus, the chosen power level will be used for all transmissions until a different power level is selected. i.e. no power ramping is supported by SimpliciTI.

The power level can be changed from user code by making the following call:

SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SETPWR, IOCTL_LEVEL_x );

where the x in IOCTL_LEVEL_x is 0, 1, or 2.

This gives up to three different levels dynamically in the code. Changing the values in the array will define what those three levels are.


Restoring connection after power cycle

In order to be able to restore the connection after power cycle, basically the network configuration and the link ID on the application side needs to be saved in a non volatile memory (e.g. Flash). The network configuration can be retrieved by the higher application layer from the lower SimpliciTI stack layer by using the SMPL_Ioctl() function with IOCTL_OBJ_NVOBJ object to get the pointer and the length of the network configuration data (basically the pointer and size of sPersistInfo data structure).

The following example shows an example for restoring the connection after power cycle on eZ430RF2500:

File:SimpliciTI NVOBJ Example eZ430RF2500.zip


How to obtain the remote peer address in SimpliciTI?

At the current SimpliciTI version (v1.1 and v1.2), it is not possible to get the remote peer address. However this can be done by the following modification of the source code:

  • Add the following function to the nwk.c file:
void nwkGetRemotePeerAddr(linkID_t sLinkId, addr_t *peerAddr)
{
  uint8_t index;
 
  if(map_lid2idx(sLinkId, &index))
  {
    memcpy(peerAddr->addr, sPersistInfo.connStruct[index].peerAddr, NET_ADDR_SIZE);
  }
}
  • Add the declaration in the application code to use the function above:
extern void nwkGetRemotePeerAddr(linkID_t sLinkId, addr_t *peerAddr);
 
....
 
void main(void)
{
  addr_t peerAddr;
  linkID_t sLinkId1;
  .....
  // do the linking using SMPL_Link() or SMPL_LinkListen() to get valid linkID
  .....
  nwkGetRemotePeerAddr(sLinkId1, &peerAddr);
  .....
}


How to override the address configuration in smpl_config.dat?

The SimpliciTI node address configuration in smpl_config.dat (THIS_DEVICE_ADDRESS) can be overridden by using SMPL_Ioctl() function with IOCTL_OBJ_ADDR before executing SMPL_Init() function.

const addr_t myAddr = {0x12, 0x34, 0x56, 0x78};
 
void main(void)
{
  .........
 
  // set device address
  SMPL_Ioctl(IOCTL_OBJ_ADDR, IOCTL_ACT_SET, (addr_t*) &myAddr);
 
  // initialize SimpliciTI stack
  SMPL_Init(sRxCallback);
 
  .........
}


How to increase the application payload?

Security Feature Disabled

Most of the example codes come with small data payload (MAX_NWK_PAYLOAD=0 and MAX_APP_PAYLOAD=10). If security feature disabled, the easiest way to increase the data payload is just by increasing the MAX_APP_PAYLOAD. The following example codes shows how this is possible to be done on eZ430-RF2500.

File:SimpliciTI BigPayload Example.zip

Simpliciti bigpayload example packet dump.PNG

The application payload size assignment is basically defined in mrfi.h as follows:

#ifndef SMPL_SECURE
#define  NWK_HDR_SIZE   3
#define  NWK_PAYLOAD    MAX_NWK_PAYLOAD
#else
#define  NWK_HDR_SIZE   6
#define  NWK_PAYLOAD    (MAX_NWK_PAYLOAD+4)
#endif
 
/* if external code has defined a maximum payload, use that instead of default */
#ifdef MAX_APP_PAYLOAD
#ifndef MAX_NWK_PAYLOAD
#error ERROR: MAX_NWK_PAYLOAD not defined
#endif
#if MAX_APP_PAYLOAD < NWK_PAYLOAD
#define MAX_PAYLOAD  NWK_PAYLOAD
#else
#define MAX_PAYLOAD  MAX_APP_PAYLOAD
#endif
#define MRFI_MAX_PAYLOAD_SIZE  (MAX_PAYLOAD+NWK_HDR_SIZE) /* SimpliciTI payload size plus six byte overhead */
#endif
 
 
/* frame definitions */
#define MRFI_ADDR_SIZE              __mrfi_ADDR_SIZE__
#ifndef MRFI_MAX_PAYLOAD_SIZE
#define MRFI_MAX_PAYLOAD_SIZE       __mrfi_MAX_PAYLOAD_SIZE__
#endif
#define MRFI_MAX_FRAME_SIZE         (MRFI_MAX_PAYLOAD_SIZE + __mrfi_FRAME_OVERHEAD_SIZE__)
#define MRFI_RX_METRICS_SIZE        __mrfi_RX_METRICS_SIZE__
#define MRFI_RX_METRICS_RSSI_OFS    __mrfi_RX_METRICS_RSSI_OFS__
#define MRFI_RX_METRICS_CRC_LQI_OFS __mrfi_RX_METRICS_CRC_LQI_OFS__

As can be seen above, if the MAX_NWK_PAYLOAD or MAX_APP_PAYLOAD are defined, the MAX_PAYLOAD will use the bigger value between the two. Then the MAX_PAYLOAD will define the MRFI_MAX_PAYLOAD_SIZE with the addition of NWK_HDR_SIZE. In this case the __mrfi_MAX_PAYLOAD_SIZE__ will be overriden by the calculated value above.


Is it possible to create static linking between two SimpliciTI nodes?

The SMPL_Commission() function can be used to create static linking between two SimpliciTI nodes. Refer also the section #Port Allocation in SimpliciTI explaining the dynamic and static port allocation to understand the port concept. The following example code shows how this can be done:

File:SMPL StaticLink ExampleCode.zip

Normally the two nodes need to exchange the Link request-response message at the beginning to setup the link as shown in the following packet dump:

Smpl dynamic link dump.PNG

By using SMPL_Commission to create the static linking, the linking process can be skipped since the connection is defined statically:

Smpl static link dump.PNG


How to retrieve the RSSI and LQI information in SimpliciTI?

SimpliciTI supports two way of acquiring the information regarding radio RSSI (Receive Signal Strenght Indication) and LQI (Link Quality Indication):

  • For retrieving the RSSI and LQI information of an incoming packet, the SMPL_Ioctl() API function with IOCTL_OBJ_RADIO object IOCTL_ACT_RADIO_SIGINFO action can be used. However it shall be noticed that the function will return only the RSSI and LQI information of the last incoming packet of a link (linkID_t specific) which is read out from the stack using either SMPL_Receive() function or SMPL_Ioctl() function with IOCTL_OBJ_RAD_IO object and IOCTL_ACT_READ action. Basically the stack will copy the RSSI and LQI information which are acquired by the MRFI layer into the connection (linkID_t) specific data structure in the nwk_retrieveFrame() function of nwk_frame.c.
  • It is also possible to get the information of current RSSI value which is sensed by the radio by calling the SMPL_Ioctl() function with IOCTL_OBJ_RADIO object and IOCTL_ACT_RADIO_RSSI action. This will bring the stack to activate the radio module into RX mode and sample the RSSI register.


Is it possible to combine Range Extender and End Device on one device?

According to SimpliciTI Developers Note, it is possible to combine the functionality of End Device and Range Extender by defining both END_DEVICE and RANGE_EXTENDER device types during compilation.

There is a bug related to this feature, and please refer here for the workaround: SimpliciTI#Compiling_with_active_END_DEVICE_and_RANGE_EXTENDER_configuration.


Disabling/Enabling join on AP

For e.g. commissioning like purpose, it is necessary to disable/enable joining process to the AP from ED during run-time. This can be done by using SMPL_Ioctl() function with IOCTL_OBJ_AP_JOIN as follows:

  • Disabling joining:
SMPL_Ioctl(IOCTL_OBJ_AP_JOIN, IOCTL_ACT_OFF, NULL);
  • Enabling joininng:
SMPL_Ioctl(IOCTL_OBJ_AP_JOIN, IOCTL_ACT_ON, NULL);