6.7. System

6.7.1. Functions

void SYS_fatal(void)

This function is called in case of fatal errors. For example, this could occur when a critical configuration goes wrong or system runs out of memory. Software goes into an infinite loop. As an indication to the user, LEDs on the board starting blinking. The system can be recovered only by a cold restart.

void SYS_initTrscnsQ(SYS_trscnQ_s *queue_p)

Initialize the transaction queue. Essentially, head and tail pointers are set to SYS_MAX_BUFF_DESC_CNT.

Parameters:
  • queue_p – Pointer to the queue that needs to be initialized.
void SYS_addToTrscnsQ(SYS_trscnQ_s *queue_p, UINT8_t bdHndl)

Add new entry to the transaction queue.

Parameters:
  • queue_p – Pointer to the queue.
  • bdHndl – Handle to the new entry to be added.
void SYS_delFromTrscnsQ(SYS_trscnQ_s *queue_p, UINT8_t bdHndl)

Delete entry from the transaction queue.

Parameters:
  • queue_p – Pointer to the queue.
  • bdHndl – Handle to the entry to be deleted.
void SYS_loop(void)

This function implements the main system loop. It is called immediately after the platform is initialized and the system is ready to run. It initializes all modules and enters the main loop. In this loop, it checks for events and calls the appropriate functions. Specifically, it checks both the event masks: SYS_globalEvtMsk0 and SYS_globalEvtMsk1. If the device is an RFD, the loop also checks for SYS_GLOBAL_EVT_ENTER_LPM_REQUEST in SYS_globalEvtMsk1. If this is set, the wakeup timer is started and RFD goes into sleep mode.

UINT8_t SYS_allocMem(UINT8_t len)

Allocates memory of the required number of bytes using the global buffer descriptor list SYS_buffDescList.

Parameters:
  • len – Number of bytes of memory requested.
Returns:

Index into the buffer descriptor list where memory is allocated. If allocation fails, SYS_MAX_BUFF_DESC_CNT is returned.

void SYS_freeMem(UINT8_t bdHndl)

Free memory previously allocated via SYS_allocMem(). If the handle into the global buffer descriptor SYS_buffDescList is found to be invalid, a fatal system error is triggered.

Parameters:
  • bdHndl – Index into the buffer descriptor where memory is to be freed.

6.7.2. Globals

UINT16_t SYS_wakeUpIntervalSecs

This variable is applicable only for an RFD. Such devices go into sleep and wakeup periodically. This variable determines the sleep time. It is used in calling PLTFRM_startWakeUpTimer(). Subsequently, the RFD enters sleep mode. The variable is initialized to zero. It is the application’s responsibility to set it to a suitable value. Value is in seconds. To set the value, macro SYS_SET_WAKEUP_INTERVAL() is to be used.

UINT8_t[SYS_BUFF_LEN] SYS_buff

This is the “heap” memory from which memory is dynamically allocated and released. For example, applications would be allocated memory from here when they wish to pack sensor data that is subsequently sent to ADP layer for transmission. Memory buffer is limited in size. Fragmentation problem is possible when enough free memory is present but they are not contiguous. Functions SYS_allocMem() and SYS_freeMem() are used to allocate and free memory respectively.

SYS_buffDesc_s[SYS_MAX_BUFF_DESC_CNT] SYS_buffDescList

This is the buffer descriptor list for managing the “heap” memory as represented by SYS_buff. Each descriptor has an offset into SYS_buff where the allocation starts, plus a length field to indicate size of the allocation. Memory handles commonly passed around in the system are really indices to particular descriptors within this list. SYS_MAX_BUFF_DESC_CNT is widely used to indicate an invalid memory handle.

When memory is requested, memory must be available in SYS_buff but there should also be a free descriptor in this list. The first free descriptor is used for any memory request. Likewise, the first free chunk of memory of the requested size is allocated. Functions SYS_allocMem() and SYS_freeMem() are used to allocate and free memory respectively. These in turn update the descriptors automatically.

Figure 1: Memory management using buffer descriptors

_images/SYS_MemoryMgmt.png
volatile UINT16_t SYS_globalEvtMsk0

This is the global event mask 0 variable. It is initialized to zero. When an event associated with this mask occurs, a flag is set in this variable. The main loop of the system will process are set events in this mask. Once processed, the flag is usually cleared. The flags associated with this mask are:

  • SYS_GLOBAL_EVT_TIMER_A0_EXPIRY
  • SYS_GLOBAL_EVT_TIMER_A1_EXPIRY
  • SYS_GLOBAL_EVT_TIMER_1HZ_PERIODIC_EXPIRY
  • SYS_GLOBAL_EVT_APP_DATA_REQUEST
  • SYS_GLOBAL_EVT_MAC_DATA_CONFIRM
  • SYS_GLOBAL_EVT_MAC_DATA_INDICATION
  • SYS_GLOBAL_EVT_MAC_FRAME_TX_DONE
  • SYS_GLOBAL_EVT_MAC_RETRY_CCA
  • SYS_GLOBAL_EVT_MAC_FRAME_RX_DONE
  • SYS_GLOBAL_EVT_MAC_BCN_REQUEST
  • SYS_GLOBAL_EVT_MAC_SCAN_CONFIRM
  • SYS_GLOBAL_EVT_MAC_DATA_REQ_CMD_RCVD
  • SYS_GLOBAL_EVT_RADIO_RX_FIFO_OVFL
  • AODVL_CTRL_PKT_TX_REQUEST
  • SYS_GLOBAL_EVT_ADP_DATA_CONFIRM
  • SYS_GLOBAL_EVT_ADP_DATA_INDICATION
volatile UINT16_t SYS_globalEvtMsk1

This is the global event mask 1 variable. It is initialized to zero. When an event associated with this mask occurs, a flag is set in this variable. The main loop of the system will process are set events in this mask. Once processed, the flag is usually cleared. The flags associated with this mask are:

  • SYS_GLOBAL_EVT_ADP_FWD_PKT_TX_REQ
  • SYS_GLOBAL_EVT_ADP_DATA_REQUEST
  • SYS_GLOBAL_EVT_MAC_ASSOC_CONFIRM
  • SYS_GLOBAL_EVT_MAC_ASSOC_INDICATION
  • SYS_GLOBAL_EVT_APP_DATA_REQ_POST_RT_DISC
  • SYS_GLOBAL_EVT_ADP_TRSCN_PENDING
  • SYS_GLOBAL_EVT_ENTER_LPM_REQUEST
  • SYS_GLOBAL_EVT_UART_BLOCK_TX_DONE
  • SYS_GLOBAL_EVT_RFD_REASSOC_REQ
  • SYS_GLOBAL_EVT_MLME_POLL_CONFIRM
  • SYS_GLOBAL_EVT_UART_FRAME_PYLD_RCVD
  • SYS_GLOBAL_EVT_UART_FRAME_HDR_RCVD
  • SYS_GLOBAL_EVT_GW_RELAY_REQUEST
  • SYS_GLOBAL_EVT_WAKEUP_TIMER_EXPIRY_EVT

6.7.3. Macros

#define LPWMN_PHY_MODULE      0x1
#define LPWMN_MAC_MODULE      0x2
#define LPWMN_ADP_MODULE      0x3
#define LPWMN_APP_MODULE      0x4
#define LPWMN_PLTFRM_MODULE   0x5
#define LPWMN_SYSTEM_MODULE   0x6


#define SYS_SET_WAKEUP_INTERVAL(timeInSecs)  \
do \
{  \
    SYS_wakeUpIntervalSecs = (timeInSecs);  \
} while (0)


#ifdef PAN_COORD
#ifdef PAN_COORD_NO_MESH
#define SYS_BUFF_LEN  256
#else
#define SYS_BUFF_LEN  256
#endif
#else
#if defined(DEV_TYPE_RFD) || defined(DEV_TYPE_FFD_NO_MESH)
#define SYS_BUFF_LEN  256
#else
#define SYS_BUFF_LEN  256
#endif
#endif

#define SYS_APP_UDP_PORT_NR  0xf0b5


// MAC / Upper layer interface

#define SYS_GLOBAL_EVT_TIMER_A0_EXPIRY        (UINT16_t)(1 << 0)      // Timer A0 (used by MAC)
#define SYS_GLOBAL_EVT_TIMER_A1_EXPIRY        (UINT16_t)(1 << 1)      // Timer A1 (used by APP)
#define SYS_GLOBAL_EVT_TIMER_1HZ_PERIODIC_EXPIRY    (UINT16_t)(1 << 2)   // Used by routing protocol
#define SYS_GLOBAL_EVT_APP_DATA_REQUEST         (UINT16_t)(1 << 3)    // APP -> ADP
#define SYS_GLOBAL_EVT_MAC_DATA_CONFIRM         (UINT16_t)(1 << 4)    // MAC -> APP
#define SYS_GLOBAL_EVT_MAC_DATA_INDICATION      (UINT16_t)(1 << 5)    // MAC -> APP
#define SYS_GLOBAL_EVT_MAC_FRAME_TX_DONE        (UINT16_t)(1 << 6)    // cc2520 -> MAC
#define SYS_GLOBAL_EVT_MAC_RETRY_CCA            (UINT16_t)(1 << 7)    // MAC -> MAC
#define SYS_GLOBAL_EVT_MAC_FRAME_RX_DONE        (UINT16_t)(1 << 8)    // cc2520 -> MAC
#define SYS_GLOBAL_EVT_MAC_BCN_REQUEST          (UINT16_t)(1 << 9)    // MAC -> MAC

#define SYS_GLOBAL_EVT_MAC_SCAN_CONFIRM         (UINT16_t)(1 << 10)   // MAC -> APP
#define SYS_GLOBAL_EVT_MAC_DATA_REQ_CMD_RCVD    (UINT16_t)(1 << 11)   // cc2520 -> MAC
#define SYS_GLOBAL_EVT_RADIO_RX_FIFO_OVFL       (UINT16_t)(1 << 12)   // MAC -> APP
#define AODVL_CTRL_PKT_TX_REQUEST               (UINT16_t)(1 << 13)   // Mesh routing -> MAC
#define SYS_GLOBAL_EVT_ADP_DATA_CONFIRM         (UINT16_t)(1 << 14)   // ADP -> APP
#define SYS_GLOBAL_EVT_ADP_DATA_INDICATION      (UINT16_t)(1 << 15)    // ADP -> APP


#define SYS_GLOBAL_EVT_ADP_FWD_PKT_TX_REQ          (UINT16_t)(1 << 0)    // ADP -> MAC
#define SYS_GLOBAL_EVT_ADP_DATA_REQUEST            (UINT16_t)(1 << 1)    // ADP -> MAC
#define SYS_GLOBAL_EVT_MAC_ASSOC_CONFIRM           (UINT16_t)(1 << 2)    // MAC -> APP
#define SYS_GLOBAL_EVT_MAC_ASSOC_INDICATION        (UINT16_t)(1 << 3)    // MAC -> ADP
#define SYS_GLOBAL_EVT_APP_DATA_REQ_POST_RT_DISC   (UINT16_t)(1 << 4)    // ADP -> ADP
#define SYS_GLOBAL_EVT_ADP_TRSCN_PENDING           (UINT16_t)(1 << 6)    // * -> ADP
#define SYS_GLOBAL_EVT_ENTER_LPM_REQUEST           (UINT16_t)(1 << 7)    // APP -> SYS
#define SYS_GLOBAL_EVT_UART_BLOCK_TX_DONE          (UINT16_t)(1 << 8)    // UART -> SYS
#define SYS_GLOBAL_EVT_RFD_REASSOC_REQ             (UINT16_t)(1 << 9)    // MAC -> NWM
#define SYS_GLOBAL_EVT_MLME_POLL_CONFIRM           (UINT16_t)(1 << 10)   // MAC -> APP
#define SYS_GLOBAL_EVT_UART_FRAME_PYLD_RCVD        (UINT16_t)(1 << 11)   // UART -> SYS
#define SYS_GLOBAL_EVT_UART_FRAME_HDR_RCVD         (UINT16_t)(1 << 12)   // UART -> SYS
#define SYS_GLOBAL_EVT_GW_RELAY_REQUEST            (UINT16_t)(1 << 13)   // GW -> MAC
#define SYS_GLOBAL_EVT_WAKEUP_TIMER_EXPIRY_EVT     (UINT16_t)(1 << 14)   // HW -> APP

#define SYS_MAX_BUFF_DESC_CNT  16


#define SYS_INV_BD_HDNL \
            SYS_MAX_BUFF_DESC_CNT
#define SYS_BD_HNDL_IS_VALID(hndl)  ((hndl) < SYS_MAX_BUFF_DESC_CNT)
#define SYS_GET_BD_BUFF(hndl) (SYS_buff + SYS_buffDescList[(hndl)].offset)
#define SYS_GET_BD_LEN(hndl) SYS_buffDescList[(hndl)].len
#define SYS_ADJ_BD_TAIL(hndl, by)  \
  do \
  {  \
     if (SYS_buffDescList[(hndl)].len > (by))  \
         SYS_buffDescList[(hndl)].len -= (by); \
     else                                      \
         SYS_fatal();                          \
  } while(0)

#define SYS_ADJ_BD_HEAD(hndl, by)  \
  do \
  {  \
     if (SYS_buffDescList[(hndl)].len > by)  \
     {                                       \
         SYS_buffDescList[(hndl)].len -= (by); \
         SYS_buffDescList[(hndl)].offset += (by); \
     }                                       \
     else                                    \
         SYS_fatal();                        \
  } while(0)


// This macro assumes there are "by" unused bytes before the
// specified BD's associated buffer
#define SYS_PULL_BD_HEAD(hndl, by) \
  do \
  {  \
     SYS_buffDescList[(hndl)].len += (by); \
     SYS_buffDescList[(hndl)].offset -= (by); \
  } while(0)


#define SYS_TRSCN_Q_HNDL_FIELD_LEN  0x1

#define SYS_TRSCN_TYPE_FIELD_LEN  0x1

#define SYS_TRSCN_Q_IS_EMPTY(q_p)  ((q_p)->qHead == SYS_MAX_BUFF_DESC_CNT)
#define SYS_TRSCN_Q_IS_NOT_EMPTY(q_p)  ((q_p)->qHead < SYS_MAX_BUFF_DESC_CNT)
#define SYS_GET_TRSCN_Q_HEAD(q_p) ((q_p)->qHead)
#define SYS_GET_TRSCN_Q_TAIL(q_p) ((q_p)->qTail)
#define SYS_GET_TRSCN_Q_BD_BUFF(hndl)  ((SYS_GET_BD_BUFF(hndl)) + SYS_TRSCN_Q_HNDL_FIELD_LEN)
#define SYS_GET_TRSCN_Q_NEXT(hndl) (*(SYS_GET_BD_BUFF(hndl)))
#define SYS_TRSCN_Q_HNDL_VALID(hndl)  ((hndl) < SYS_MAX_BUFF_DESC_CNT)

6.7.4. Type Definitions

typedef struct
{
   UINT8_t offset;
   UINT8_t len;
} SYS_buffDesc_s;

typedef struct
{
  UINT8_t qHead, qTail;
} SYS_trscnQ_s;