Exemplo n.º 1
0
/**************************************************************************************************
 * @fn          macRxOff
 *
 * @brief       Turn off the receiver if it's not already off.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macRxOff(void)
{
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);
  if (macRxOnFlag)
  {
    macRxOnFlag = 0;
    MAC_RADIO_RXTX_OFF();
    MAC_DEBUG_TURN_OFF_RX_LED();
    
    /* just in case a receive was about to start, flush the receive FIFO */
    MAC_RADIO_FLUSH_RX_FIFO();

    /* clear any receive interrupt that happened to squeak through */
    MAC_RADIO_CLEAR_RX_THRESHOLD_INTERRUPT_FLAG();

  }
  HAL_EXIT_CRITICAL_SECTION(s);
}
Exemplo n.º 2
0
/**************************************************************************************************
 * @fn          macBackoffTimerCapture
 *
 * @brief       Returns the most recently captured backoff count
 *
 * @param       none
 *
 * @return      last backoff count that was captured
 **************************************************************************************************
 */
uint32 macBackoffTimerCapture(void)
{
  halIntState_t  s;
  uint32 backoffCapture;

  HAL_ENTER_CRITICAL_SECTION(s);
  backoffCapture = MAC_RADIO_BACKOFF_CAPTURE();
  HAL_EXIT_CRITICAL_SECTION(s);

#ifdef MAC_RADIO_FEATURE_HARDWARE_OVERFLOW_NO_ROLLOVER
  /*
   *  See other instance of this #ifdef for detailed comments.
   *  Those comments apply to the backoff capture value too.
   */
  if (backoffCapture >= backoffTimerRollover)
  {
    return(0);
  }
#endif
  
  return(backoffCapture);
}
Exemplo n.º 3
0
/*********************************************************************
 * @fn      osal_pwrmgr_powerconserve
 *
 * @brief   This function is called from the main OSAL loop when there are
 *          no events scheduled and shouldn't be called from anywhere else.
 *
 * @param   none.
 *
 * @return  none.
 */
void osal_pwrmgr_powerconserve( void ){
 	uint32        next;
 	halIntState_t intState;

 	// Should we even look into power conservation
 	if ( pwrmgr_attribute.pwrmgr_device != PWRMGR_ALWAYS_ON ) {
    	// Are all tasks in agreement to conserve
    	if ( pwrmgr_attribute.pwrmgr_task_state == 0 ) {
      		// Hold off interrupts.
      		HAL_ENTER_CRITICAL_SECTION( intState );

      		// Get next time-out
      		next = osal_next_timeout();

      		// Re-enable interrupts.
      		HAL_EXIT_CRITICAL_SECTION( intState );

      		// Put the processor into sleep mode
      		OSAL_SET_CPU_INTO_SLEEP( next );
    	}
  	}
}
Exemplo n.º 4
0
/**************************************************************************************************
 * @fn          macMcuOverflowSetCount
 *
 * @brief       Sets the value of the hardware overflow counter.
 *
 * @param       count - new overflow count value
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macMcuOverflowSetCount(uint32 count)
{
  halIntState_t  s;

  MAC_ASSERT(! (count >> 24) );   /* illegal count value */

  /* save the current overflow count */
  accumulatedOverflowCount += macMcuOverflowCount();

  /* deduct the initial count */
  accumulatedOverflowCount -= count;

  HAL_ENTER_CRITICAL_SECTION(s);
  MAC_MCU_T2_ACCESS_OVF_COUNT_VALUE();

  /* for efficiency, the 32-bit value is decoded using endian abstracted indexing */
  /* T2OF2 must be written last */
  T2MOVF0 = (uint32)((uint8 *)&count)[UINT32_NDX0];
  T2MOVF1 = (uint32)((uint8 *)&count)[UINT32_NDX1];
  T2MOVF2 = (uint32)((uint8 *)&count)[UINT32_NDX2];
  HAL_EXIT_CRITICAL_SECTION(s);
}
Exemplo n.º 5
0
/**************************************************************************************************
 * @fn          macMcuOverflowCount
 *
 * @brief       Returns the value of the overflow counter which is a special hardware feature.
 *              The overflow count actually is 24 bits of information.
 *
 * @param       none
 *
 * @return      value of overflow counter
 **************************************************************************************************
 */
MAC_INTERNAL_API uint32 macMcuOverflowCount(void)
{
  uint32         overflowCount;
  halIntState_t  s;

  /* for efficiency, the 32-bit value is encoded using endian abstracted indexing */

  HAL_ENTER_CRITICAL_SECTION(s);

  /* This T2 access macro allows accessing both T2MOVFx and T2Mx */
  MAC_MCU_T2_ACCESS_OVF_COUNT_VALUE();

  /* Latch the entire T2MOVFx first by reading T2M0. */
  T2M0;
  ((uint8 *)&overflowCount)[UINT32_NDX0] = T2MOVF0;
  ((uint8 *)&overflowCount)[UINT32_NDX1] = T2MOVF1;
  ((uint8 *)&overflowCount)[UINT32_NDX2] = T2MOVF2;
  ((uint8 *)&overflowCount)[UINT32_NDX3] = 0;
  HAL_EXIT_CRITICAL_SECTION(s);

  return (overflowCount);
}
Exemplo n.º 6
0
/*********************************************************************
 * @fn      osal_timer_num_active
 *
 * @brief
 *
 *   This function counts the number of active timers.
 *
 * @return  u8 - number of timers
 */
u8 osal_timer_num_active( void )
{
  halIntState_t intState;
  u8 num_timers = 0;
  osalTimerRec_t *srchTimer;

  HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.

  // Head of the timer list
  srchTimer = timerHead;

  // Count timers in the list
  while ( srchTimer != NULL )
  {
    num_timers++;
    srchTimer = srchTimer->next;
  }

  HAL_EXIT_CRITICAL_SECTION( intState );   // Re-enable interrupts.

  return num_timers;
}
Exemplo n.º 7
0
/*******************************************************************************
 * @fn          RFHAL_NextDataEntryDone API
 *
 * @brief       This function is used to mark the next System data entry on a
 *              data entry queue as Pending so that the radio can once again
 *              use it. It should be called after the user has processed the
 *              data entry.
 *
 * input parameters
 *
 * @param       dataEntryQueue_t - Pointer to data entry queue.
 *
 * output parameters
 *
 * @param       None.
 *
 * @return      None.
 */
void RFHAL_NextDataEntryDone( dataEntryQ_t *pDataEntryQ )
{
  halIntState_t  cs;
  dataQ_t       *pDataQueue;

#ifdef DEBUG
  RFHAL_ASSERT( pDataEntryQ != NULL );
#endif // DEBUG

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

  if ( pDataQueue->pNextDataEntry != NULL )
  {
    HAL_ENTER_CRITICAL_SECTION(cs);

    // mark the next System data entry as Pending
    pDataQueue->pNextDataEntry->status = DATASTAT_PENDING;

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

    HAL_EXIT_CRITICAL_SECTION(cs);

    // return pointer to next entry, or NULL if there isn't one
    // Note: For a ring buffer, there is always another.
    return; //( pDataQueue->pNextDataEntry );
  }
  else // we are at the end of a linked list
  {
    // ALT: Could set pNextDataEntry to first entry, but could be problematic
    //       if the radio data queue commands are being used to add/remove
    //       data entries.
  }

  // return next data entry to may be processed by System software
  return;
}
Exemplo n.º 8
0
/**************************************************************************************************
 * @fn          macRadioSetChannel
 *
 * @brief       Set radio channel.
 *
 * @param       channel - channel number, valid range is 11 through 26. Allow
 *              channels 27 and 28 for some Japanese customers.
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macRadioSetChannel(uint8 channel)
{
  halIntState_t  s;

  MAC_ASSERT((channel >= 11) && (channel <= 28));  /* illegal channel */

  /* critical section to make sure transmit does not start while updating channel */
  HAL_ENTER_CRITICAL_SECTION(s);

  /* set requested channel */
  reqChannel = channel;

  /*
   *  If transmit is not active, update the radio hardware immediately.  If transmit is active,
   *  the channel will be updated at the end of the current transmit.
   */
  if (!macTxActive)
  {
    macRadioUpdateChannel();
  }

  HAL_EXIT_CRITICAL_SECTION(s);
}
Exemplo n.º 9
0
/**************************************************************************************************
 * @fn          macMcuOverflowSetPeriod
 *
 * @brief       Set overflow count period value.  An interrupt is triggered when the overflow
 *              count equals this period value.
 *
 * @param       count - overflow count compare value
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macMcuOverflowSetPeriod(uint32 count)
{
  halIntState_t  s;
  uint8 enableCompareInt = 0;

  MAC_ASSERT( !(count >> 24) );   /* illegal count value */

  HAL_ENTER_CRITICAL_SECTION(s);

  /*  Disable overflow compare interrupts. */
  if (T2IRQM & TIMER2_OVF_PERM)
  {
    enableCompareInt = 1;
    T2IRQM &= ~TIMER2_OVF_PERM;
  }

  MAC_MCU_T2_ACCESS_OVF_PERIOD_VALUE();

  /* for efficiency, the 32-bit value is decoded using endian abstracted indexing */
  T2MOVF0 = ((uint8 *)&count)[UINT32_NDX0];
  T2MOVF1 = ((uint8 *)&count)[UINT32_NDX1];
  T2MOVF2 = ((uint8 *)&count)[UINT32_NDX2];

  /*
   *  Now that new compare value is stored, clear the interrupt flag.  This is important just
   *  in case a false match was generated as the multi-byte compare value was written.
   */
  T2IRQF &= ~TIMER2_OVF_PERF;

  /* re-enable overflow compare interrupts if they were previously enabled */
  if (enableCompareInt)
  {
    T2IRQM |= TIMER2_OVF_PERM;
  }

  HAL_EXIT_CRITICAL_SECTION(s);
}
Exemplo n.º 10
0
/**************************************************************************************************
 * @fn          macBackoffTimerICallPwrNotify
 *
 * @brief       power state transition notify callback function
 *
 * @param       pwrTrans  power transition
 * @param       data      custom data - not used
 *
 * @return      none
 **************************************************************************************************
 */
static void macBackoffTimerICallPwrNotify(ICall_PwrTransition pwrTrans,
                                          ICall_PwrNotifyData *data)
{
  if (pwrTrans == ICALL_PWR_AWAKE_FROM_STANDBY)
  {
    /* Wakeup must be handled from the thread context.
     * Signal the event to the OSAL thread. */
    halIntState_t is;

    HAL_ENTER_CRITICAL_SECTION(is);
    macBackoffTimerEvents |= MAC_BACKOFF_TIMER_EVENT_POWER_WAKEUP;
    HAL_EXIT_CRITICAL_SECTION(is);
    ICall_signal(osal_semaphore);
  }
  else if (pwrTrans == ICALL_PWR_ENTER_STANDBY)
  {
    /* Stop RAT timer */
    macRATValue = macStopRAT();

    /* Park CM0 */
    MAC_RADIO_POWER_DOWN();

    /* The following calls are necessary to prevent a race condition in 
     * pg2_leakage_workaround that causes CM3 to constantly firing up CPE1
     * interrupts during power up until CM3 crashes.
     */
    ICall_disableInt( INT_RF_CPE0 );
    ICall_disableInt( INT_RF_CPE1 );
    ICall_disableInt( INT_RF_HW );
    ICall_disableInt( INT_RF_CMD_ACK );
  }
  else if (pwrTrans == ICALL_PWR_ENTER_SHUTDOWN)
  {
    /* Park CM0 */
    MAC_RADIO_POWER_DOWN();
  }
}
Exemplo n.º 11
0
/**************************************************************************************************
 * @fn          HalKeyPoll
 *
 * @brief       This function is called by Hal_ProcessEvent() on a HAL_KEY_EVENT.
 *
 * input parameters
 *
 * None.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 **************************************************************************************************
 */
void HalKeyPoll(void)
{
  uint8 newKeys;

  if (Hal_KeyIntEnable)
  {
    halIntState_t intState;
    HAL_ENTER_CRITICAL_SECTION(intState);
    newKeys = isrKeys;
    isrKeys = 0;
    HAL_EXIT_CRITICAL_SECTION(intState);
  }
  else
  {
    uint8 keys = HalKeyRead();
    newKeys = (halKeys ^ keys) & keys;
    halKeys = keys;
  }

  if (newKeys && pHalKeyProcessFunction)
  {
    (pHalKeyProcessFunction)(newKeys, HAL_KEY_STATE_NORMAL);
  }
}
Exemplo n.º 12
0
/******************************************************************************
 * @fn      HalSPIRead
 *
 * @brief   Read from the external NV storage via SPI.
 *
 * @param   addr - Offset into the external NV.
 * @param   pBuf - Pointer to buffer to copy the bytes read from external NV.
 * @param   len - Number of bytes to read from external NV.
 *
 * @return  None.
 *****************************************************************************/
static void HalSPIRead(uint32 addr, uint8 *pBuf, uint16 len)
{
#if !HAL_OTA_BOOT_CODE
  uint8 shdw = P1DIR;
  halIntState_t his;
  HAL_ENTER_CRITICAL_SECTION(his);
  P1DIR |= BV(3);
#endif

  XNV_SPI_BEGIN();
  do
  {
    xnvSPIWrite(XNV_STAT_CMD);
  } while (XNV_SPI_RX() & XNV_STAT_WIP);
  XNV_SPI_END();
  asm("NOP"); asm("NOP");

  XNV_SPI_BEGIN();
  xnvSPIWrite(XNV_READ_CMD);
  xnvSPIWrite(addr >> 16);
  xnvSPIWrite(addr >> 8);
  xnvSPIWrite(addr);
  xnvSPIWrite(0);

  while (len--)
  {
    xnvSPIWrite(0);
    *pBuf++ = XNV_SPI_RX();
  }
  XNV_SPI_END();

#if !HAL_OTA_BOOT_CODE
  P1DIR = shdw;
  HAL_EXIT_CRITICAL_SECTION(his);
#endif
}
/**
 * Main entry function for the stack image
 */
int stack_main( void *arg )
{
  /* User reconfiguration of BLE Controller and Host variables */
  setBleUserConfig( (bleUserCfg_t *)arg );
  
  /* Establish OSAL for a stack service that requires accompanying
   * messaging service */
  if (ICall_enrollService(ICALL_SERVICE_CLASS_BLE_MSG,
                          (ICall_ServiceFunc) osal_service_entry,
                          &osal_entity, &osal_semaphore) !=
      ICALL_ERRNO_SUCCESS)
  {
    /* abort */
    ICall_abort();
  }

  halIntState_t state;
  HAL_ENTER_CRITICAL_SECTION(state);
  
  // Turn off interrupts
  //osal_int_disable( INTS_ALL );

  // Initialize NV System
  osal_snv_init( );

  // Initialize the operating system
  osal_init_system();

  // Allow interrupts
  //osal_int_enable( INTS_ALL );
  HAL_EXIT_CRITICAL_SECTION(state);

  osal_start_system(); // No Return from here

  return 0;  // Shouldn't get here.
}
Exemplo n.º 14
0
/***********************************************************************************
* @fn           halUartPollRx
*
* @brief        Poll for data from USB.
*
* @param        none
*
* @return       none
*/
static void halUartPollRx(void)
{
  uint8 cnt;
  uint8 ep = USBFW_GET_SELECTED_ENDPOINT();
  USBFW_SELECT_ENDPOINT(4);

  // If the OUT endpoint has received a complete packet.
  if (USBFW_OUT_ENDPOINT_DISARMED())
  {
    halIntState_t intState;

    HAL_ENTER_CRITICAL_SECTION(intState);
    // Get length of USB packet, this operation must not be interrupted.
    cnt = USBFW_GET_OUT_ENDPOINT_COUNT_LOW();
    cnt += USBFW_GET_OUT_ENDPOINT_COUNT_HIGH() >> 8;
    HAL_EXIT_CRITICAL_SECTION(intState);

    while (cnt--)
    {
      halUartRxQ[halUartRxT++] = USBF4;
    }
    USBFW_ARM_OUT_ENDPOINT();

#if !defined HAL_SB_BOOT_CODE
    // If the USB has transferred in more Rx bytes, reset the Rx idle timer.

    // Re-sync the shadow on any 1st byte(s) received.
    if (rxTick == 0)
    {
      rxShdw = ST0;
    }
    rxTick = HAL_UART_USB_IDLE;
#endif
  }
#if !defined HAL_SB_BOOT_CODE
  else if (rxTick)
Exemplo n.º 15
0
void macRadioSetTxPower(uint8 txPower)
{
  halIntState_t  s;

  /* if the selected dBm is out of range, use the closest available */
  if (txPower > MAC_RADIO_TX_POWER_MAX_MINUS_DBM)
  {
    txPower = MAC_RADIO_TX_POWER_MAX_MINUS_DBM;
  }

  /*
   *  Set the global variable reqTxPower.  This variable is referenced
   *  by the function macRadioUpdateTxPower() to write the radio register.
   *
   *  A lookup table is used to translate the power level to the register
   *  value.
   */
  HAL_ENTER_CRITICAL_SECTION(s);
  reqTxPower = macRadioDefsTxPowerTable[txPower];
  HAL_EXIT_CRITICAL_SECTION(s);

  /* update the radio power setting */
  macRadioUpdateTxPower();
}
Exemplo n.º 16
0
/*******************************************************************************
 * @fn          RFHAL_FreeNextTxDataEntry API
 *
 * @brief       This function is used to free the next TX data entry based on
 *              the internal data entry queue pointer. This routine should be
 *              used after the radio FW indicates a TX Entry Done interrupt.
 *              Once freed, the internal data entry queue is updated to the
 *              next entry.
 *
 *              Note: It is assumed the data entry queue is really based on a
 *                    data queue.
 *
 * input parameters
 *
 * @param       pDataEntryQ - Pointer to data entry queue.
 *
 * output parameters
 *
 * @param       None.
 *
 * @return      None.
 */
void RFHAL_FreeNextTxDataEntry( dataEntryQ_t *pDataEntryQ )
{
  halIntState_t cs;
  dataEntry_t   *pNextEntry;

  HAL_ENTER_CRITICAL_SECTION(cs);

  // get next data entry to free (i.e. head of internal queue)
  pNextEntry = ((dataQ_t *)pDataEntryQ)->pNextDataEntry;

  // update the internal next data entry pointer based on pCurEntry
  // Note: If this was the last data entry on the queue, then pCurEntry would
  //       be NULL, and so would pNextDataEntry. If this was not the last data
  //       entry on the queue, then pNextDataEntry should point to the current
  //       entry. So pNextEntry in either case.
  ((dataQ_t *)pDataEntryQ)->pNextDataEntry = pNextEntry->pNextEntry;

  // free the TX data entry given by the internal next data entry
  osal_bm_free( (void *)pNextEntry );

  HAL_EXIT_CRITICAL_SECTION(cs);

  return;
}
Exemplo n.º 17
0
/*=================================================================================================
 * @fn          rxStartIsr
 *
 * @brief       First ISR state for receiving a packet - compute packet length, allocate
 *              buffer, initialize buffer.  Acknowledgements are handled immediately without
 *              allocating a buffer.
 *
 * @param       none
 *
 * @return      none
 *=================================================================================================
 */
static void rxStartIsr(void)
{
  uint8  addrLen;
  uint8  ackWithPending;
  uint8  dstAddrMode;
  uint8  srcAddrMode;
  uint8  mhrLen = 0;

  MAC_ASSERT(!macRxActive); /* receive on top of receive */

  /* indicate rx is active */
  macRxActive = MAC_RX_ACTIVE_STARTED;

  /*
   *  For bullet proof functionality, need to see if the receiver was just turned off.
   *  The logic to request turning off the receiver, disables interrupts and then checks
   *  the value of macRxActive.  If it is TRUE, the receiver will not be turned off.
   *
   *  There is a small hole though.  It's possible to attempt turning off the receiver
   *  in the window from when the receive interrupt fires and the point where macRxActive
   *  is set to TRUE.  To plug this hole, the on/off status must be tested *after*
   *  macRxActive has been set.  If the receiver is off at this point, there is nothing
   *  in the RX fifo and the receive is simply aborted.
   *
   *  Also, there are some considerations in case a hard disable just happened.  Usually,
   *  the receiver will just be off at this point after a hard disable.  The check described
   *  above will account for this case too.  However, if a hard disable were immediately
   *  followed by an enable, the receiver would be on.  To catch this case, the receive
   *  FIFO is also tested to see if it is empty.  Recovery is identical to the other cases.
   */
  if (!macRxOnFlag || MAC_RADIO_RX_FIFO_IS_EMPTY())
  {
    /* reset active flag */
    macRxActive = MAC_RX_ACTIVE_NO_ACTIVITY;

    /*
     *  To be absolutely bulletproof, must make sure no transmit queue'ed up during
     *  the tiny, tiny window when macRxActive was not zero.
     */
    rxPostRxUpdates();

    /* return immediately from here */
    return;
  }

  /*
   *  If interrupts are held off for too long it's possible the previous "transmit done"
   *  callback is pending.  If this is the case, it needs to be completed before
   *  continuing with the receive logic.
   */
  MAC_RADIO_FORCE_TX_DONE_IF_PENDING();

  /*
   *  It's possible receive logic is still waiting for confirmation of an ACK that went out
   *  for the previous receive.  This is OK but the callback needs to be canceled at this point.
   *  That callback execute receive cleanup logic that will run at the completion
   *  of *this* receive.  Also, it is important the flag for the outgoing ACK to be cleared.
   */
  MAC_RADIO_CANCEL_ACK_TX_DONE_CALLBACK();
  macRxOutgoingAckFlag = 0;

  /*
   *  Make a module-local copy of macRxFilter.  This prevents the selected
   *  filter from changing in the middle of a receive.
   */
  rxFilter = macRxFilter;

  /*-------------------------------------------------------------------------------
   *  Read initial frame information from FIFO.
   *
   *   This code is not triggered until the following are in the RX FIFO:
   *     frame length          - one byte containing length of MAC frame (excludes this field)
   *     frame control field   - two bytes defining frame type, addressing fields, control flags
   *     sequence number       - one byte unique sequence identifier
   *     additional two bytes  - these bytes are available in case the received frame is an ACK,
   *                             if so, the frame can be verified and responded to immediately,
   *                             if not an ACK, these bytes will be processed normally
   */

  /* read frame length, frame control field, and sequence number from FIFO */
  MAC_RADIO_READ_RX_FIFO(rxBuf, MAC_PHY_PHR_LEN + MAC_FCF_FIELD_LEN + MAC_SEQ_NUM_FIELD_LEN);

  /* bytes to read from FIFO equals frame length minus length of MHR fields just read from FIFO */
  rxUnreadLen = (rxBuf[0] & PHY_PACKET_SIZE_MASK) - MAC_FCF_FIELD_LEN - MAC_SEQ_NUM_FIELD_LEN;

  /*
   *  Workaround for chip bug #1547.  The receive buffer can sometimes be corrupted by hardware.
   *  This usually occurs under heavy traffic.  If a corrupted receive buffer is detected
   *  the entire receive buffer is flushed.
   */
  if ((rxUnreadLen > (MAC_A_MAX_PHY_PACKET_SIZE - MAC_FCF_FIELD_LEN - MAC_SEQ_NUM_FIELD_LEN)) ||
      (MAC_FRAME_TYPE(&rxBuf[1]) > MAC_FRAME_TYPE_MAX_VALID))
  {
    MAC_RADIO_FLUSH_RX_FIFO();
    rxDone();
    return;
  }


  /*-------------------------------------------------------------------------------
   *  Process ACKs.
   *
   *  If this frame is an ACK, process it immediately and exit from here.
   *  If this frame is not an ACK and transmit is listening for an ACK, let
   *  the transmit logic know an non-ACK was received so transmit can complete.
   *
   *  In promiscuous mode ACKs are treated like any other frame.
   */
  if ((MAC_FRAME_TYPE(&rxBuf[1]) == MAC_FRAME_TYPE_ACK) && (rxPromiscuousMode == PROMISCUOUS_MODE_OFF))
  {
    halIntState_t  s;
    uint8 fcsBuf[MAC_FCF_FIELD_LEN];
    /*
     *  There are guaranteed to be two unread bytes in the FIFO.  By defintion, for ACK frames
     *  these two bytes will be the FCS.
     */

    /* read FCS from FIFO (threshold set so bytes are guaranteed to be there) */
    MAC_RADIO_READ_RX_FIFO(fcsBuf, MAC_FCS_FIELD_LEN);

    /*
     *  This critical section ensures that the ACK timeout won't be triggered in the
     *  middle of receiving the ACK frame.
     */
    HAL_ENTER_CRITICAL_SECTION(s);

    /* see if transmit is listening for an ACK */
    if (macTxActive == MAC_TX_ACTIVE_LISTEN_FOR_ACK)
    {
      MAC_ASSERT(pMacDataTx != NULL); /* transmit buffer must be present */

      /* record link quality metrics for the receive ACK */
      {
        int8 rssiDbm;
        uint8 corr;

        rssiDbm = PROPRIETARY_FCS_RSSI(fcsBuf) + MAC_RADIO_RSSI_OFFSET;
        MAC_RADIO_RSSI_LNA_OFFSET(rssiDbm);
        corr = PROPRIETARY_FCS_CORRELATION_VALUE(fcsBuf);

        pMacDataTx->internal.mpduLinkQuality = macRadioComputeLQI(rssiDbm, corr);
        pMacDataTx->internal.correlation = corr;
        pMacDataTx->internal.rssi= rssiDbm;
      }

      /*
       *  It's okay if the ACK timeout is triggered here. The callbacks for ACK received
       *  or ACK not received will check "macTxActive" flag before taking any actions.
       */
      HAL_EXIT_CRITICAL_SECTION(s);

      /*
       *  An ACK was received so transmit logic needs to know.  If the FCS failed,
       *  the transmit logic still needs to know.  In that case, treat the frame
       *  as a non-ACK to complete the active transmit.
       */
      if (PROPRIETARY_FCS_CRC_OK(fcsBuf))
      {
        /* call transmit logic to indicate ACK was received */
        macTxAckReceivedCallback(MAC_SEQ_NUMBER(&rxBuf[1]), MAC_FRAME_PENDING(&rxBuf[1]));
      }
      else
      {
        macTxAckNotReceivedCallback();
      }
    }
    else
    {
      HAL_EXIT_CRITICAL_SECTION(s);
    }

    /* receive is done, exit from here */
    rxDone();
    return;
  }
  else if (macTxActive == MAC_TX_ACTIVE_LISTEN_FOR_ACK)
  {
    macTxAckNotReceivedCallback();
  }

  /*-------------------------------------------------------------------------------
   *  Apply filtering.
   *
   *  For efficiency, see if filtering is even 'on' before processing.  Also test
   *  to make sure promiscuous mode is disabled.  If promiscuous mode is enabled,
   *  do not apply filtering.
   */
  if ((rxFilter != RX_FILTER_OFF) && !rxPromiscuousMode)
  {
    if (/* filter all frames */
         (rxFilter == RX_FILTER_ALL) ||

         /* filter non-beacon frames */
         ((rxFilter == RX_FILTER_NON_BEACON_FRAMES) &&
          (MAC_FRAME_TYPE(&rxBuf[1]) != MAC_FRAME_TYPE_BEACON)) ||

         /* filter non-command frames */
         ((rxFilter == RX_FILTER_NON_COMMAND_FRAMES) &&
          ((MAC_FRAME_TYPE(&rxBuf[1]) != MAC_FRAME_TYPE_COMMAND))))
    {
      /* discard rest of frame */
      rxDiscardFrame();
      return;
    }
  }

  /*-------------------------------------------------------------------------------
   *  Compute length of addressing fields.  Compute payload length.
   */

  /* decode addressing modes */
  dstAddrMode = MAC_DEST_ADDR_MODE(&rxBuf[1]);
  srcAddrMode = MAC_SRC_ADDR_MODE(&rxBuf[1]);

  /*
  *  Workaround for chip bug #1547.  The receive buffer can sometimes be corrupted by hardware.
   *  This usually occurs under heavy traffic.  If a corrupted receive buffer is detected
   *  the entire receive buffer is flushed.
   */
  if (macChipVersion == REV_A)
  {
    if ((srcAddrMode == ADDR_MODE_RESERVERED) || (dstAddrMode == ADDR_MODE_RESERVERED))
    {
      MAC_RADIO_FLUSH_RX_FIFO();
      rxDone();
      return;
    }
  }

  /*
   *  Compute the addressing field length.  A lookup table based on addressing
   *  mode is used for efficiency.  If the source address is present and the
   *  frame is intra-PAN, the PAN Id is not repeated.  In this case, the address
   *  length is adjusted to match the smaller length.
   */
  addrLen = macRxAddrLen[dstAddrMode] + macRxAddrLen[srcAddrMode];
  if ((srcAddrMode != SADDR_MODE_NONE) && MAC_INTRA_PAN(&rxBuf[1]))
  {
    addrLen -= MAC_PAN_ID_FIELD_LEN;
  }

  /*
   *  If there are not enough unread bytes to include the computed address
   *  plus FCS field, the frame is corrupted and must be discarded.
   */
  if ((addrLen + MAC_FCS_FIELD_LEN) > rxUnreadLen)
  {
    /* discard frame and exit */
    rxDiscardFrame();
    return;
  }

  /* aux security header plus payload length is equal to unread bytes minus
   * address length, minus the FCS
   */
  rxPayloadLen = rxUnreadLen - addrLen - MAC_FCS_FIELD_LEN;

  /*-------------------------------------------------------------------------------
   *  Allocate memory for the incoming frame.
   */
  if (MAC_SEC_ENABLED(&rxBuf[1]))
  {
    /* increase the allocation size of MAC header for security */
    mhrLen = MAC_MHR_LEN;
  }

  pRxBuf = (macRx_t *) MEM_ALLOC(sizeof(macRx_t) + mhrLen + rxPayloadLen);
  if (pRxBuf == NULL)
  {
    /* Cancel the outgoing TX ACK */
    MAC_RADIO_CANCEL_TX_ACK();

    /* buffer allocation failed, discard the frame and exit*/
    rxDiscardFrame();
    return;
  }

  /*-------------------------------------------------------------------------------
   *  Set up to process ACK request.  Do not ACK if in promiscuous mode.
   */
  ackWithPending = 0;
  if (!rxPromiscuousMode)
  {
    macRxOutgoingAckFlag = MAC_ACK_REQUEST(&rxBuf[1]);
  }

  /*-------------------------------------------------------------------------------
   *  Process any ACK request.
   */
  if (macRxOutgoingAckFlag)
  {
    halIntState_t  s;

    /*
     *  This critical section ensures that the callback ISR is initiated within time
     *  to guarantee correlation with the strobe.
     */
    HAL_ENTER_CRITICAL_SECTION(s);

    /* Do not ack data packet with pending more data */
    if( MAC_FRAME_TYPE(&rxBuf[1]) == MAC_FRAME_TYPE_COMMAND )
    {
      if( macRxCheckMACPendingCallback())
      {
        /* Check is any mac data pending for end devices */
        ackWithPending = MAC_RX_FLAG_ACK_PENDING;
      }
      else
      {
        if( macSrcMatchIsEnabled )
        {
          /* When autopend is enabled, check if allpending is set to true */
          if( MAC_SrcMatchCheckAllPending() == MAC_AUTOACK_PENDING_ALL_ON )
          {
            ackWithPending = MAC_RX_FLAG_ACK_PENDING;
          }
        }
        else
        {
          /* When autopend is disabled, check the application pending callback */
          if( macRxCheckPendingCallback() )
          {
            ackWithPending = MAC_RX_FLAG_ACK_PENDING;
          }
        }
      }
    }

    if( ackWithPending == MAC_RX_FLAG_ACK_PENDING )
    {
      MAC_RADIO_TX_ACK_PEND();
    }
    else
    {
      MAC_RADIO_TX_ACK();
    }


    /* request a callback to macRxAckTxDoneCallback() when the ACK transmit has finished */
    MAC_RADIO_REQUEST_ACK_TX_DONE_CALLBACK();
    HAL_EXIT_CRITICAL_SECTION(s);
  }

 /*-------------------------------------------------------------------------------
  *  Populate the receive buffer going up to high-level.
  */

  /* configure the payload buffer
   * save MAC header pointer regardless of security status.
   */
  pRxBuf->mhr.p   = pRxBuf->msdu.p   = (uint8 *) (pRxBuf + 1);
  pRxBuf->mhr.len = pRxBuf->msdu.len =  rxPayloadLen;

  if (MAC_SEC_ENABLED(&rxBuf[1]))
  {
    /* Copy FCF and sequence number to RX buffer */
    pRxBuf->mhr.len = MAC_FCF_FIELD_LEN + MAC_SEQ_NUM_FIELD_LEN;
    osal_memcpy(pRxBuf->mhr.p, &rxBuf[1], pRxBuf->mhr.len);
    pRxBuf->mhr.p += pRxBuf->mhr.len;
  }

  /* set internal values */
  pRxBuf->mac.srcAddr.addrMode  = srcAddrMode;
  pRxBuf->mac.dstAddr.addrMode  = dstAddrMode;
  pRxBuf->mac.timestamp         = MAC_RADIO_BACKOFF_CAPTURE();
  pRxBuf->mac.timestamp2        = MAC_RADIO_TIMER_CAPTURE();

  /* Special Case for Enhanced Beacon Request which has a different
   * frame version
   */
#ifdef FEATURE_ENHANCED_BEACON
  if( MAC_FRAME_VERSION(&rxBuf[1]) == 2 )
  {
      pRxBuf->internal.frameType  = MAC_FRAME_TYPE_INTERNAL_MAC_VERSION_E | \
                                  MAC_FRAME_TYPE(&rxBuf[1]);
  }
  else
#endif
  {
    pRxBuf->internal.frameType  = MAC_FRAME_TYPE(&rxBuf[1]);
  }

  pRxBuf->mac.dsn               = MAC_SEQ_NUMBER(&rxBuf[1]);
  pRxBuf->internal.flags        = INTERNAL_FCF_FLAGS(&rxBuf[1]) | ackWithPending;

  /*-------------------------------------------------------------------------------
   *  If the processing the addressing fields does not require more bytes from
   *  the FIFO go directly address processing function.  Otherwise, configure
   *  interrupt to jump there once bytes are received.
   */
  if (addrLen == 0)
  {
    /* no addressing fields to read, prepare for payload interrupts */
    pFuncRxState = &rxPayloadIsr;
    rxPrepPayload();
  }
  else
  {
    /* need to read and process addressing fields, prepare for address interrupt */
    rxNextLen = addrLen;
    if (MAC_SEC_ENABLED(&rxBuf[1]))
    {
      /* When security is enabled, read off security control field as well */
      MAC_RADIO_SET_RX_THRESHOLD(rxNextLen + MAC_SEC_CONTROL_FIELD_LEN);
    }
    else
    {
      MAC_RADIO_SET_RX_THRESHOLD(rxNextLen);
    }
    pFuncRxState = &rxAddrIsr;
  }
}
Exemplo n.º 18
0
/**************************************************************************************************
 * @fn          MAC_MlmeSetReq
 *
 * @brief       This direct execute function sets an attribute value
 *              in the MAC PIB.
 *
 * input parameters
 *
 * @param       pibAttribute - The attribute identifier.
 * @param       pValue - pointer to the attribute value.
 *
 * output parameters
 *
 * None.
 *
 * @return      The status of the request, as follows:
 *              MAC_SUCCESS Operation successful.
 *              MAC_UNSUPPORTED_ATTRIBUTE Attribute not found.
 *
 **************************************************************************************************
 */
uint8 MAC_MlmeSetReq(uint8 pibAttribute, void *pValue)
{
  uint8         i;
  halIntState_t intState;

  if (pibAttribute == MAC_BEACON_PAYLOAD)
  {
    macPib.pBeaconPayload = pValue;
    return MAC_SUCCESS;
  }

  /* look up attribute in PIB table */
  if ((i = macPibIndex(pibAttribute)) == MAC_PIB_INVALID)
  {
    return MAC_UNSUPPORTED_ATTRIBUTE;
  }

  /* do range check; no range check if min and max are zero */
  if ((macPibTbl[i].min != 0) || (macPibTbl[i].max != 0))
  {
    /* if min == max, this is a read-only attribute */
    if (macPibTbl[i].min == macPibTbl[i].max)
    {
      return MAC_READ_ONLY;
    }

    /* check for special cases */
    if (pibAttribute == MAC_MAX_FRAME_TOTAL_WAIT_TIME)
    {
      if ((*((uint16 *) pValue) < MAC_MAX_FRAME_RESPONSE_MIN) ||
          (*((uint16 *) pValue) > MAC_MAX_FRAME_RESPONSE_MAX))
      {
        return MAC_INVALID_PARAMETER;
      }
    }

    /* range check for general case */
    if ((*((uint8 *) pValue) < macPibTbl[i].min) || (*((uint8 *) pValue) > macPibTbl[i].max))
    {
      return MAC_INVALID_PARAMETER;
    }

  }

  /* set value in PIB */
  HAL_ENTER_CRITICAL_SECTION(intState);
  osal_memcpy((uint8 *) &macPib + macPibTbl[i].offset, pValue, macPibTbl[i].len);
  HAL_EXIT_CRITICAL_SECTION(intState);

  /* handle special cases */
  switch (pibAttribute)
  {
    case MAC_PAN_ID:
      /* set pan id in radio */
      macRadioSetPanID(macPib.panId);
      break;

    case MAC_SHORT_ADDRESS:
      /* set short address in radio */
      macRadioSetShortAddr(macPib.shortAddress);
      break;

    case MAC_RX_ON_WHEN_IDLE:
      /* turn rx on or off */
      if (macPib.rxOnWhenIdle)
      {
        macRxEnable(MAC_RX_WHEN_IDLE);
      }
      else
      {
        macRxDisable(MAC_RX_WHEN_IDLE);
      }
      break;

    case MAC_LOGICAL_CHANNEL:
      macRadioSetChannel(macPib.logicalChannel);
      break;

    case MAC_EXTENDED_ADDRESS:
      /* set ext address in radio */
      macRadioSetIEEEAddr(macPib.extendedAddress.addr.extAddr);
      break;

#ifndef MAC_OBSOLETE_PHY_TRANSMIT_POWER
    /* Define MAC_OBSOLETE_PHY_TRANSMIT_POWER to save some code */

    case MAC_PHY_TRANSMIT_POWER:
      /* Legacy transmit power attribute */
#if !defined HAL_MAC_USE_REGISTER_POWER_VALUES && \
  !defined HAL_PA_LNA && !defined HAL_PA_LNA_CC2590
      /* Legacy transmit power attribute value for CC2530 alone,
       * or runtime selection support build means a negative absolute value.
       * However, when used as register power values or
       * with HAL_PA_LNAxxx definition (without runtime selection)
       * the attribute value is not a negative absolute value. */
      macPib.phyTransmitPower = (uint8)(-(int8)macPib.phyTransmitPower);
#endif /* !defined HAL_MAC_USE_REGISTER_POWER_VALUES && ... */
      /* pass through to next case -- do not break*/

#endif /* MAC_OBSOLETE_PHY_TRANSMIT_POWER */

    case MAC_PHY_TRANSMIT_POWER_SIGNED:
      (void)macRadioSetTxPower(macPib.phyTransmitPower);
      break;

    default:
      break;
  }

  return MAC_SUCCESS;
}
Exemplo n.º 19
0
/**************************************************************************************************
 * @fn          macTxFrame
 *
 * @brief       Transmit the frame pointed to by pMacDataTx with the specified type.
 *              NOTE! It is not legal to call this function from interrupt context.
 *
 * @param       txType - type of transmit
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macTxFrame(uint8 txType)
{
  MAC_ASSERT(!macTxActive);            /* transmit on top of transmit */

  /* mark transmit as active */
  macTxActive = MAC_TX_ACTIVE_INITIALIZE;

  /*
   *  The MAC will not enter sleep mode if there is an active transmit.  However, if macSleep() is
   *  ever called from interrupt context, it possible to enter sleep state after a transmit is
   *  intiated but before macTxActive is set.  To recover from this, the transmit must be aborted
   *  and proper notificiation given to high-level.
   */
  if (macSleepState != MAC_SLEEP_STATE_AWAKE)
  {
    /* notify high-level that transmit had to be aborted */
    txComplete(MAC_TX_ABORTED);

    /* exit from transmit logic */
    return;
  }

  /* save transmit type */
  macTxType = txType;

  /*-------------------------------------------------------------------------------
   *  Prepare for transmit.
   */
  if (macTxType == MAC_TX_TYPE_SLOTTED)
  {
    MAC_RADIO_TX_PREP_SLOTTED();
  }

#ifdef FEATURE_GREEN_POWER
  else if (macTxType == MAC_TX_TYPE_GREEN_POWER)
  {
    txGreenPowerPrep();
  }
#endif /* #ifdef FEATURE_GREEN_POWER */

  else
  {
    MAC_ASSERT((macTxType == MAC_TX_TYPE_SLOTTED_CSMA) || (macTxType == MAC_TX_TYPE_UNSLOTTED_CSMA));

    nb = 0;
    macTxBe = (pMacDataTx->internal.txOptions & MAC_TXOPTION_ALT_BE) ? pMacPib->altBe : pMacPib->minBe;

    if ((macTxType == MAC_TX_TYPE_SLOTTED_CSMA) && (pMacPib->battLifeExt))
    {
      macTxBe = MIN(2, macTxBe);
    }

    txCsmaPrep();
  }

  /*-------------------------------------------------------------------------------
   *  Load transmit FIFO unless this is a retransmit.  No need to write
   *  the FIFO again in that case.
   */
  if (!txRetransmitFlag)
  {
    uint8 * p;
    uint8   lenMhrMsdu;

    MAC_ASSERT(pMacDataTx != NULL); /* must have data to transmit */

    /* save needed parameters */
    txAckReq = MAC_ACK_REQUEST(pMacDataTx->msdu.p);
    txSeqn   = MAC_SEQ_NUMBER(pMacDataTx->msdu.p);

    /* set length of frame (note: use of term msdu is a misnomer, here it's actually mhr + msdu) */
    lenMhrMsdu = pMacDataTx->msdu.len;

    /* calling code guarantees an unused prepended byte  */
    p = pMacDataTx->msdu.p - PREPENDED_BYTE_LEN;

    /* first byte of buffer is length of MPDU */
    *p = lenMhrMsdu + MFR_LEN;

    /*
     *  Flush the TX FIFO.  This is necessary in case the previous transmit was never
     *  actually sent (e.g. CSMA failed without strobing TXON).  If bytes are written to
     *  the FIFO but not transmitted, they remain in the FIFO to be transmitted whenever
     *  a strobe of TXON does happen.
     */
    MAC_RADIO_FLUSH_TX_FIFO();

    /* write bytes to FIFO, prepended byte is included, MFR is not (it's generated by hardware) */
    MAC_RADIO_WRITE_TX_FIFO(p, PREPENDED_BYTE_LEN + lenMhrMsdu);
  }

  /*-------------------------------------------------------------------------------
   *  If not receiving, start the transmit.  If receive is active
   *  queue up the transmit.
   *
   *  Critical sections around the state change prevents any sort of race condition
   *  with  macTxStartQueuedFrame().  This guarantees function txGo() will only be
   *  called once.
   */
  {
    halIntState_t  s;

    HAL_ENTER_CRITICAL_SECTION(s);
    if (!macRxActive && !macRxOutgoingAckFlag)
    {
      macTxActive = MAC_TX_ACTIVE_GO;
      HAL_EXIT_CRITICAL_SECTION(s);
      txGo();
    }
    else
    {
      macTxActive = MAC_TX_ACTIVE_QUEUED;
      HAL_EXIT_CRITICAL_SECTION(s);
    }
  }
}
Exemplo n.º 20
0
/**************************************************************************************************
 * @fn          MAC_MlmeSetReq
 *
 * @brief       This direct execute function sets an attribute value
 *              in the MAC PIB.
 *
 * input parameters
 *
 * @param       pibAttribute - The attribute identifier.
 * @param       pValue - pointer to the attribute value.
 *
 * output parameters
 *
 * None.
 *
 * @return      The status of the request, as follows:
 *              MAC_SUCCESS Operation successful.
 *              MAC_UNSUPPORTED_ATTRIBUTE Attribute not found.
 *
 **************************************************************************************************
 */
uint8 MAC_MlmeSetReq(uint8 pibAttribute, void *pValue)
{
    uint8         i;
    halIntState_t intState;

    if (pibAttribute == MAC_BEACON_PAYLOAD)
    {
        pMacPib->pBeaconPayload = pValue;
        return MAC_SUCCESS;
    }

    /* look up attribute in PIB table */
    if ((i = MAP_macPibIndex(pibAttribute)) == MAC_PIB_INVALID)
    {
        return MAC_UNSUPPORTED_ATTRIBUTE;
    }

    /* do range check; no range check if min and max are zero */
    if ((macPibTbl[i].min != 0) || (macPibTbl[i].max != 0))
    {
        /* if min == max, this is a read-only attribute */
        if (macPibTbl[i].min == macPibTbl[i].max)
        {
            return MAC_READ_ONLY;
        }

        /* check for special cases */
        if (pibAttribute == MAC_MAX_FRAME_TOTAL_WAIT_TIME)
        {
            if ((*((uint16 *) pValue) < MAC_MAX_FRAME_RESPONSE_MIN) ||
                    (*((uint16 *) pValue) > MAC_MAX_FRAME_RESPONSE_MAX))
            {
                return MAC_INVALID_PARAMETER;
            }
        }

        /* range check for general case */
        if ((*((uint8 *) pValue) < macPibTbl[i].min) || (*((uint8 *) pValue) > macPibTbl[i].max))
        {
            return MAC_INVALID_PARAMETER;
        }

    }

    /* set value in PIB */
    HAL_ENTER_CRITICAL_SECTION(intState);
    osal_memcpy((uint8 *) pMacPib + macPibTbl[i].offset, pValue, macPibTbl[i].len);
    HAL_EXIT_CRITICAL_SECTION(intState);

    /* handle special cases */
    switch (pibAttribute)
    {
    case MAC_PAN_ID:
        /* set pan id in radio */
        macRadioSetPanID(pMacPib->panId);
        break;

    case MAC_SHORT_ADDRESS:
        /* set short address in radio */
        macRadioSetShortAddr(pMacPib->shortAddress);
        break;

    case MAC_RX_ON_WHEN_IDLE:
        /* turn rx on or off */
        if (pMacPib->rxOnWhenIdle)
        {
            macRxEnable(MAC_RX_WHEN_IDLE);
        }
        else
        {
            macRxDisable(MAC_RX_WHEN_IDLE);
        }
        break;

    case MAC_LOGICAL_CHANNEL:
        macRadioSetChannel(pMacPib->logicalChannel);
        break;

    case MAC_EXTENDED_ADDRESS:
        /* set ext address in radio */
        macRadioSetIEEEAddr(pMacPib->extendedAddress.addr.extAddr);
        break;

    case MAC_PHY_TRANSMIT_POWER_SIGNED:
        (void)macRadioSetTxPower(pMacPib->phyTransmitPower);
        break;

    case MAC_RF4CE_POWER_SAVINGS:
        pMacPib->rf4cepowerSavings = *(uint8 *)pValue;
        break;

    case MAC_FRAME_VERSION_SUPPORT:
        pMacPib->frameVersionSupport = *(uint8 *)pValue;
        break;

    default:
        break;
    }

    return MAC_SUCCESS;
}
Exemplo n.º 21
0
/*********************************************************************
 * @fn      osal_mem_alloc
 *
 * @brief   Implementation of the allocator functionality.
 *
 * @param   size - number of bytes to allocate from the heap.
 *
 * @return  void * - pointer to the heap allocation; NULL if error or failure.
 */
void *osal_mem_alloc( uint16 size )
{
  osalMemHdr_t *prev = NULL;
  osalMemHdr_t *hdr;
  halIntState_t intState;
  uint16 tmp;
  uint8 coal = 0;

  OSALMEM_ASSERT( size );

  size += HDRSZ;

  // Calculate required bytes to add to 'size' to align to halDataAlign_t.
  if ( sizeof( halDataAlign_t ) == 2 )
  {
    size += (size & 0x01);
  }
  else if ( sizeof( halDataAlign_t ) != 1 )
  {
    const uint8 mod = size % sizeof( halDataAlign_t );

    if ( mod != 0 )
    {
      size += (sizeof( halDataAlign_t ) - mod);
    }
  }

  HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.

  // Smaller allocations are first attempted in the small-block bucket.
  if ( size <= OSALMEM_SMALL_BLKSZ )
  {
    hdr = ff1;
  }
  else
  {
    hdr = ff2;
  }
  tmp = *hdr;

  do
  {
    if ( tmp & OSALMEM_IN_USE )
    {
      tmp ^= OSALMEM_IN_USE;
      coal = 0;
    }
    else
    {
      if ( coal != 0 )
      {
#if ( OSALMEM_METRICS )
        blkCnt--;
        blkFree--;
#endif

        *prev += *hdr;

        if ( *prev >= size )
        {
          hdr = prev;
          tmp = *hdr;
          break;
        }
      }
      else
      {
        if ( tmp >= size )
        {
          break;
        }

        coal = 1;
        prev = hdr;
      }
    }

    hdr = (osalMemHdr_t *)((uint8 *)hdr + tmp);

    tmp = *hdr;
    if ( tmp == 0 )
    {
      hdr = NULL;
      break;
    }


  } while ( 1 );

  if ( hdr != NULL )
  {
    tmp -= size;

    // Determine whether the threshold for splitting is met.
    if ( tmp >= OSALMEM_MIN_BLKSZ )
    {
      // Split the block before allocating it.
      osalMemHdr_t *next = (osalMemHdr_t *)((uint8 *)hdr + size);
      *next = tmp;
      *hdr = (size | OSALMEM_IN_USE);

#if ( OSALMEM_METRICS )
      blkCnt++;
      if ( blkMax < blkCnt )
      {
        blkMax = blkCnt;
      }
      memAlo += size;
#endif
    }
    else
    {
#if ( OSALMEM_METRICS )
      memAlo += *hdr;
      blkFree--;
#endif

      *hdr |= OSALMEM_IN_USE;
    }

#if ( OSALMEM_METRICS )
    if ( memMax < memAlo )
    {
      memMax = memAlo;
    }
#endif

#if ( OSALMEM_PROFILER )
  {
    uint8 idx;
    size = *hdr ^ OSALMEM_IN_USE;

    for ( idx = 0; idx < OSALMEM_PROMAX; idx++ )
    {
      if ( size <= proCnt[idx] )
      {
        break;
      }
    }
    proCur[idx]++;
    if ( proMax[idx] < proCur[idx] )
    {
      proMax[idx] = proCur[idx];
    }
    proTot[idx]++;
  }
#endif

    hdr++;

#if ( OSALMEM_PROFILER )
    (void)osal_memset( (uint8 *)hdr, OSALMEM_ALOC, (size - HDRSZ) );

    /* A small-block could not be allocated in the small-block bucket.
     * When this occurs significantly frequently, increase the size of the
     * bucket in order to restore better worst case run times. Set the first
     * profiling bucket size in proCnt[] to the small-block bucket size and
     * divide proSmallBlkMiss by the corresponding proTot[] size to get % miss.
     * Best worst case time on TrasmitApp was achieved at a 0-15% miss rate
     * during steady state Tx load, 0% during idle and steady state Rx load.
     */
    if ( (size <= OSALMEM_SMALL_BLKSZ) && (hdr > ff2) )
    {
      proSmallBlkMiss++;
    }
#endif
  }

  HAL_EXIT_CRITICAL_SECTION( intState );  // Re-enable interrupts.

  return (void *)hdr;
}
Exemplo n.º 22
0
/**************************************************************************************************
 * @fn          spiParseRx
 *
 * @brief       Parse all available bytes from the spiRxBuf[]; parse Rx data into the spiRxDat[].
 *
 * input parameters
 *
 * None.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 */
static void spiParseRx(void)
{
  uint8 done = 0;
  halIntState_t  cs;
  
#ifdef HAL_SPI_MASTER
  uint8 numNotSOF = 0;
  uint8 count = 0;

  SPI_SET_CSn_OUT();
#endif //HAL_SPI_MASTER
  
  while (!done)
  {
    if (!SPI_NEW_RX_BYTE(spiRxIdx))
    {
#if defined HAL_SPI_MASTER
      // Clock a byte from slave
      SPI_CLOCK_RX(1);
#else
      break;
#endif
    }

    uint8 ch = SPI_GET_RX_BYTE(spiRxIdx);
    SPI_CLR_RX_BYTE(spiRxIdx);
    SPI_LEN_T_INCR(spiRxIdx);
    
#ifdef HAL_SPI_MASTER
    // If searching for a SOF byte limit the number of bytes searched
    // to SPI_FRM_LEN
    if ( spiRxPktState == SPIRX_STATE_SOF )
    {
      count++;
      numNotSOF = ( ch == SPI_SOF ) ? numNotSOF : numNotSOF + 1;
      
      // Haven't recieved an SOF. Assume not a packet but only break if there is
      // no new bytes in the RX buffer to read
      if ( numNotSOF > SPI_FRM_LEN && numNotSOF == count ) 
      {
        // Clear all Rx'ed NULL bytes
        while(SPI_NEW_RX_BYTE(spiRxIdx))
        {
          SPI_CLR_RX_BYTE(spiRxIdx);
          SPI_LEN_T_INCR(spiRxIdx);
        }
        break;
      }
    }
#endif //HAL_SPI_MASTER
    
    switch (spiRxPktState)
    {
    case SPIRX_STATE_SOF:
      if (ch == SPI_SOF)
      {
        spiRxPktState = SPIRX_STATE_LEN;

        /* At this point, the master has effected the protocol for ensuring that the SPI slave is
         * awake, so set the spiRxLen to non-zero to prevent the slave from re-entering sleep until
         * the entire packet is received - even if the master interrupts the sending of the packet
         * by de-asserting/re-asserting MRDY one or more times
	 */
        spiRxLen = 1;
      }
      break;

    case SPIRX_STATE_LEN:
      if ((ch == 0) || (ch > SPI_MAX_DAT_LEN))
      {
        spiRxPktState = SPIRX_STATE_SOF;
        spiRxLen = 0;
      }
      else
      {
        spiRxFcs = spiRxLen = ch;
        spiRxTemp = spiRxTail;
        spiRxCnt = 0;
        spiRxPktState = SPIRX_STATE_DATA;
#if defined HAL_SPI_MASTER
        if (!SPI_NEW_RX_BYTE(spiRxIdx)) /* Fix for simultaneous TX/RX to avoid extra clock pulses to SPI Slave */
        {
          halIntState_t intState;      
          HAL_ENTER_CRITICAL_SECTION(intState);
          SPI_CLOCK_RX(ch + 1); /* Clock out the SPI Frame Data bytes and FCS */
          HAL_EXIT_CRITICAL_SECTION(intState);
        }
#endif
      }
      break;

    case SPIRX_STATE_DATA:
      spiRxFcs ^= ch;
      spiRxDat[spiRxTemp] = ch;

      SPI_LEN_T_INCR(spiRxTemp);

      if (++spiRxCnt == spiRxLen)
      {
        spiRxPktState = SPIRX_STATE_FCS;
      }
      break;

    case SPIRX_STATE_FCS:
      spiRxPktState = SPIRX_STATE_SOF;
#ifdef POWER_SAVING
      pktFound = TRUE;
#endif

      if (ch == spiRxFcs)
      {
        spiRxTail = spiRxTemp;
      }
      else
      {
        dbgFcsByte = ch;
#ifdef RBA_UART_TO_SPI
        badFcsPktCount++;
#endif
      }
      spiRxCnt = spiRxLen = 0;

#ifdef HAL_SPI_MASTER
      // Clear any trailing empty Rx'ed bytes
      // Should only receive one frame per MRDY assertion
      while(SPI_NEW_RX_BYTE(spiRxIdx))
      {
        SPI_CLR_RX_BYTE(spiRxIdx);
        SPI_LEN_T_INCR(spiRxIdx);
      }
      done = 1;
#endif //HAL_SPI_MASTER
      
      break;

    default:
      HAL_ASSERT(0);
      break;
    }
  }
  spiTxLen = 0;
  
  HAL_ENTER_CRITICAL_SECTION(cs);
  spiRdyIsr = 0;
  HAL_EXIT_CRITICAL_SECTION(cs);

#ifdef HAL_SPI_MASTER
  SPI_CLR_CSn_OUT();
  
#ifdef RBA_UART_TO_SPI
  // Must wait until slave has ended transaction because
  // the RBA implementation cannot delay writes so this is a 
  // forced delay....
  while(SPI_RDY_IN());
#endif
#else
  SPI_CLR_RDY_OUT();
#endif //HAL_SPI_MASTER
  
}
Exemplo n.º 23
0
/**************************************************************************************************
 * @fn          HalUARTPollSPI
 *
 * @brief       SPI Transport Polling Manager.
 *
 * input parameters
 *
 * None.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 */
static void HalUARTPollSPI(void)
{
#ifdef HAL_SPI_MASTER
#else
#if defined POWER_SAVING  
  pktFound = FALSE;
#endif
  if ( ( spiRdyIsr ) || (SPI_RDY_IN()) )
  {
    CLEAR_SLEEP_MODE();

#if defined HAL_SBL_BOOT_CODE
    if(!spiTxLen)
    {   
      UxDBUF = 0x00; /* Zero out garbage from UxDBUF */
      
      HAL_DMA_ARM_CH(HAL_SPI_CH_RX); /* Arm RX DMA */

      asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); 
      asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); 
      asm("NOP");

      halIntState_t intState;      
      HAL_ENTER_CRITICAL_SECTION(intState);
      
      SPI_SET_RDY_OUT(); /* SPI_RDYOut = 0 */
      SPI_CLR_RDY_OUT(); /* SPI_RDYOut = 1 */

      HAL_EXIT_CRITICAL_SECTION(intState);
    }
#endif
#if defined POWER_SAVING      
    pktFound = TRUE;
#endif
  }
#endif

#ifdef HAL_SPI_MASTER
  if ( spiRdyIsr && !writeActive) 
  {
    spiParseRx();
  }
#else //SPI Slave
  if ( spiRdyIsr && !writeActive )
  {
     if ( !(UxCSR & CSR_ACTIVE) )
     {
       // MRDY has gone low to set spiRdyIsr
       // and has now gone high if SPI_RDY_IN
       // is false, read RXed bytes
       spiParseRx();
     }
     else
     {
       // MRDY has gone low and is still low
       // Set SRDY low to signal ready to RX
       SPI_SET_RDY_OUT();
     }
  }
#endif //HAL_SPI_MASTER

#if defined HAL_SPI_MASTER
  if( SPI_RX_RDY())
#else
  if (SPI_RX_RDY() && !spiTxLen)
#endif
  {
    if (spiCB != NULL)
    {
      spiCB((HAL_UART_SPI - 1), HAL_UART_RX_TIMEOUT);
    }
  }

#if defined POWER_SAVING
  if  ( SPI_RDY_IN()|| SPI_RX_RDY() || spiRxLen || spiTxLen || spiRdyIsr ||  pktFound || SPI_RDY_OUT() )
  {
    CLEAR_SLEEP_MODE();
  }
  else if ( (!pktFound) && (!SPI_NEW_RX_BYTE(spiRxIdx)) )
  {
    PxIEN |= SPI_RDYIn_BIT; 
    SPI_CLR_RDY_OUT();
  }
#endif
}
Exemplo n.º 24
0
/**************************************************************************************************
 * @fn      HalAdcRead
 *
 * @brief   Read the ADC based on given channel and resolution
 *
 * @param   channel - channel where ADC will be read
 * @param   resolution - the resolution of the value
 *
 * @return  16 bit value of the ADC in offset binary format.
 *
 *          Note that the ADC is "bipolar", which means the GND (0V) level is mid-scale.
 *          Note2: This function assumes that ADCCON3 contains the voltage reference.
 **************************************************************************************************/
uint16 HalAdcRead (uint8 channel, uint8 resolution)
{
  int16  reading = 0;

#if (HAL_ADC == TRUE)
  uint8   i, resbits;
  uint8   adcChannel = 1;
  uint32  padConfig, dirConfig;
  halIntState_t s;
  
  /*
   * If Analog input channel is AIN0..AIN7, make sure corresponing PA pin is 
   * setup. Only port A can be used as input to the ADC. If any pin on port A 
   * is to be used as an ADC input, the appropriate register, IOC_PAx_OVER, 
   * must be set to analog (that is, bit 0 must be set to 1). 
   */
  
  /* Hold off interrupts */
  HAL_ENTER_CRITICAL_SECTION(s);
      
  switch (channel)
  {
  case HAL_ADC_CHN_AIN0:
  case HAL_ADC_CHN_AIN1:
  case HAL_ADC_CHN_AIN2:
  case HAL_ADC_CHN_AIN3:
  case HAL_ADC_CHN_AIN4:
  case HAL_ADC_CHN_AIN5:
  case HAL_ADC_CHN_AIN6:
  case HAL_ADC_CHN_AIN7:
    adcChannel <<= channel;
  break;
  case HAL_ADC_CHN_A0A1:
    adcChannel = HAL_BITS_CHN_A0A1;
    break;
  
  case HAL_ADC_CHN_A2A3:
    adcChannel = HAL_BITS_CHN_A2A3;
    break;
  case HAL_ADC_CHN_A4A5:
    adcChannel = HAL_BITS_CHN_A4A5;
    break;
  case HAL_ADC_CHN_A6A7:
    adcChannel = HAL_BITS_CHN_A6A7;
    break; 
  default:
    adcChannel = 0;
    break;
  } 
  
  /* save the current pad setting of the PortA pin */
  padConfig = IOCPadConfigGet(GPIO_A_BASE, adcChannel);
  
  /* save the current gpio setting of the PortA pin */
  dirConfig = GPIODirModeGet(GPIO_A_BASE, adcChannel);
  
  /* set the PortA pin to Analog */
  IOCPadConfigSet(GPIO_A_BASE, adcChannel, IOC_OVERRIDE_ANA);
  
  /* set the PortA pin direction to input */
  GPIODirModeSet(GPIO_A_BASE, adcChannel, GPIO_DIR_MODE_IN);

  /* Convert resolution to decimation rate */
  switch (resolution)
  {
    case HAL_ADC_RESOLUTION_8:
      resbits = HAL_ADC_DEC_064;
      break;
    case HAL_ADC_RESOLUTION_10:
      resbits = HAL_ADC_DEC_128;
      break;
    case HAL_ADC_RESOLUTION_12:
      resbits = HAL_ADC_DEC_256;
      break;
    case HAL_ADC_RESOLUTION_14:
    default:
      resbits = HAL_ADC_DEC_512;
      break;
  }

  /* writing to this register starts the extra conversion */
  ADCCON3 = channel | resbits | adcRef;

  /* Wait for the conversion to be done */
  while (!(ADCCON1 & HAL_ADC_EOC));
  
  /* Set the pad configuration to previous value*/
  IOCPadConfigSet(GPIO_A_BASE, adcChannel, padConfig);
 
  /* Set the GPIO direction to previous value*/
  GPIODirModeSet(GPIO_A_BASE, adcChannel, dirConfig);
  
  /* Read the result */
  reading = (int16) (ADCL);
  reading |= (int16) (ADCH << 8);
  
  /* Enable interrupts */
  HAL_EXIT_CRITICAL_SECTION(s);

  /* Treat small negative as 0 */
  if (reading < 0)
    reading = 0;

  switch (resolution)
  {
    case HAL_ADC_RESOLUTION_8:
      reading >>= 8;
      break;
    case HAL_ADC_RESOLUTION_10:
      reading >>= 6;
      break;
    case HAL_ADC_RESOLUTION_12:
      reading >>= 4;
      break;
    case HAL_ADC_RESOLUTION_14:
    default:
      reading >>= 2;
    break;
  }
#else
  /* unused arguments */
  (void) channel;
  (void) resolution;
#endif

  return ((uint16)reading);
}
Exemplo n.º 25
0
/**************************************************************************************************
 * @fn          halMacTimerElapsed
 *
 * @brief       Determine the number of MAC timer ticks elapsed during sleep.
 *
 * input parameters
 *
 * @param       timeout - pointer to the 320us timeout.
 *
 * output parameters
 *
 * None.
 *
 * @return      Number of timer ticks elapsed during sleep.
 **************************************************************************************************
 */
uint32 halMacTimerElapsed( uint32 *timeout )
{
  volatile uint16 tar;
  volatile uint16 taccr;
  uint32          ticks;
  uint32          timeout_u320; /* 320 us timeout */
  halIntState_t   s;

  /* read the currrent count + compare count (MAC timer must be in CTC mode) */
  HAL_ENTER_CRITICAL_SECTION(s);

#ifdef __msp430x54x
  tar = HAL_MAC_SLEEP_TIMER_TAR();
#endif

  /* Halt timer before read anything */
  HAL_MAC_SLEEP_TIMER_SPEED_UP();

  HAL_EXIT_CRITICAL_SECTION(s);

#ifdef __msp430x54x
  /* With MSP430F5438 RTM silicon, when the counter mode is moved from 'up'
   * to 'stop' and the timer counter equals the capture/compare value in a
   * TACCRx register the transition of modes will pull the TAR bits (15:4)
   * to a '1' momentarily. Re-initialize TAR as a temporary workaround until
   * the post-RTM revisions of silicon with this bug fixed.
   */
  HAL_MAC_SLEEP_TIMER_TAR() = tar;
#else
  /* Read timer registers */
  tar = HAL_MAC_SLEEP_TIMER_TAR();
#endif

  taccr = HAL_MAC_SLEEP_TIMER_COMPARE();

  /* store current timer count */
  ticks = tar;

  /* calculate elapsed time or somthing else woke up the MCU */
  if ( taccr <= halSleepTimerStart )
  {
    ticks += taccr;
  }
  ticks -= halSleepTimerStart;

  /* adjust timeout for the next sleep cycle */
  timeout_u320 = ticks * 3125 / 4096;
  if ( *timeout >= timeout_u320 )
  {
    *timeout -= timeout_u320;
  }

  /* Restore current MAC count */
  HAL_MAC_SLEEP_TIMER_SET_COMPARE(halSleepTimerCompareStart);
  HAL_MAC_SLEEP_TIMER_TAR() = halSleepTimerStart;

  /* Restart timer */
  HAL_MAC_SLEEP_TIMER_RESTART();

  /* Return elapsed time in units of 320us */
  return ( timeout_u320 );
}
Exemplo n.º 26
0
/**************************************************************************************************
 * @fn          DMAExecCrc
 *
 * @brief       This function assumes CRC has been initialized and sets up and
 *              starts a dma tranfer from a flash page to the CRC HW module.
 *
 * @note        This function assumes DMA channel 0 is available for use.
 *
 * input parameters
 *
 * @param       page - A valid flash page number.
 * @param       offset - A valid offset into the page.
 * @param       len - A valid number of bytes to calculate crc of.
 *
 * @return      None.
 **************************************************************************************************
 */
void DMAExecCrc(uint8 page, uint16 offset, uint16 len) {

  uint8 memctr = MEMCTR;  // Save to restore.
  
  // Calculate the offset into the containing flash bank as it gets mapped into XDATA.
  uint16 address = (offset + HAL_FLASH_PAGE_MAP) +
                   ((page % HAL_FLASH_PAGE_PER_BANK) * HAL_FLASH_PAGE_SIZE);

  // Pointer to DMA config structure
  halDMADesc_t *dmaCh0_p = &dmaCh0;
  
#if !defined HAL_OAD_BOOT_CODE
  halIntState_t is;
#endif

  page /= HAL_FLASH_PAGE_PER_BANK;  // Calculate the flash bank from the flash page.

#if !defined HAL_OAD_BOOT_CODE
  HAL_ENTER_CRITICAL_SECTION(is);
#endif
  
  // Calculate and map the containing flash bank into XDATA.
  MEMCTR = (MEMCTR & 0xF8) | page;  // page is actually bank
  
  // Start address for CRC calculation in the XDATA mapped flash bank
  HAL_DMA_SET_SOURCE(dmaCh0_p, address);
  
  // Destination for data transfer, RNDH mapped to XDATA
  HAL_DMA_SET_DEST(dmaCh0_p, 0x70BD);
  
  // One whole page (or len) at a time
  HAL_DMA_SET_LEN(dmaCh0_p, len);
  
  // 8-bit, block, no trigger
  HAL_DMA_SET_WORD_SIZE(dmaCh0_p, HAL_DMA_WORDSIZE_BYTE);
  HAL_DMA_SET_TRIG_MODE(dmaCh0_p, HAL_DMA_TMODE_BLOCK);
  HAL_DMA_SET_TRIG_SRC(dmaCh0_p, HAL_DMA_TRIG_NONE);
  
  // SRC += 1, DST = constant, no IRQ, all 8 bits, high priority
  HAL_DMA_SET_SRC_INC(dmaCh0_p, HAL_DMA_SRCINC_1);
  HAL_DMA_SET_DST_INC(dmaCh0_p, HAL_DMA_DSTINC_0);
  HAL_DMA_SET_IRQ(dmaCh0_p, HAL_DMA_IRQMASK_DISABLE);
  HAL_DMA_SET_M8(dmaCh0_p, HAL_DMA_M8_USE_8_BITS);
  HAL_DMA_SET_PRIORITY(dmaCh0_p, HAL_DMA_PRI_HIGH);
  
  // Tell DMA Controller where above configuration can be found
  HAL_DMA_SET_ADDR_DESC0(&dmaCh0);
  
  // Arm the DMA channel (0)
  HAL_DMA_ARM_CH(0);
  
  // 9 cycles wait
  asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
  asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
  
  // Start DMA tranfer
  HAL_DMA_MAN_TRIGGER(0);
  
  // Wait for dma to finish.
  while(DMAREQ & 0x1);
  
  // Restore bank mapping
  MEMCTR = memctr;

#if !defined HAL_OAD_BOOT_CODE
  HAL_EXIT_CRITICAL_SECTION(is);
#endif
}
Exemplo n.º 27
0
//-------------------------------------------------------------------
// @fn      halIntUnlock
// @brief   Set interrupt state back to the state it had before calling halIntLock().
//          Should always be used together with halIntLock().
// @param   key
// @return  none
//-------------------------------------------------------------------
void halIntUnlock(uint16 key)
{
    HAL_EXIT_CRITICAL_SECTION(key);
}
Exemplo n.º 28
0
static
#endif /* USE_ICALL */
void macBackoffTimerEventHandler(void)
{
  halIntState_t is;
  uint8 events;
  HAL_ENTER_CRITICAL_SECTION(is);
  events = macBackoffTimerEvents;
  macBackoffTimerEvents = 0;
  HAL_EXIT_CRITICAL_SECTION(is);

  if (events & MAC_BACKOFF_TIMER_EVENT_POWER_WAKEUP)
  {
    // Wakeup radio
    // Turning on radio domain before clock set up seems to cause
    // unexpected interrupt.
    // Hence interrupt shall be disabled here.
    MB_DisableInts();

    // Enable clocks for all radio internal modules.
    // Use Non-Buff access for safety and check for sanity
    HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = 0x7FF;

    /* Setup mailbox */
    macSetupMailbox();

#ifdef DEBUG_SW_TRACE
    /* re-enable RF trace output for FPGA */
    MB_SendCommand( BUILD_DIRECT_PARAM_EXT_CMD( CMD_ENABLE_DEBUG, 0x1D40 ) ); /* or 0x1940 for less trace */
    DBG_PRINT0(DBGSYS, "RF Trace Resumes...");
#endif /* DEBUG_SW_TRACE */

    /* Start off CM0. Patch it. */
    macSetupRfHal();

    /* Restore states */
    MAC_RADIO_SET_CHANNEL(macPhyChannel);
    MAC_RADIO_SET_PAN_COORDINATOR(macPanCoordinator);
    MAC_RADIO_SET_PAN_ID(pMacPib->panId);
    MAC_RADIO_SET_SHORT_ADDR(pMacPib->shortAddress);
    MAC_RADIO_SET_IEEE_ADDR(pMacPib->extendedAddress.addr.extAddr);

#if !defined( USE_FPGA )
#ifdef USE_ICALL
    // Switch back to HFOSC.
    while (!ICall_pwrIsStableXOSCHF());
    ICall_pwrSwitchXOSCHF();
#endif /* USE_ICALL */
#ifdef OSAL_PORT2TIRTOS
    // Switches back to HFOSC.
    while (!Power_isStableXOSC_HF());
    Power_switchXOSC_HF();
#endif /* OSAL_PORT2TIRTOS */
#endif /* !defined( USE_FPGA ) */

    /* Synchronize RAT timer */
    macSyncStartRAT(macRATValue);

    /* Turn on autoack */
    MAC_RADIO_TURN_ON_AUTO_ACK();

    /* Initialize SRCEXTPENDEN and SRCSHORTPENDEN to zeros */
    MAC_RADIO_SRC_MATCH_INIT_EXTPENDEN();
    MAC_RADIO_SRC_MATCH_INIT_SHORTPENDEN();

    /* Start 15.4 Radio */
    macSetupRadio();

    /* Restore timer comparators */
    MAC_RADIO_BACKOFF_SET_PERIOD(macBackoffTimerRollover);
    MAC_RADIO_BACKOFF_SET_COMPARE(backoffTimerTrigger);

#if 0 /* Following code should be disabled normally */
    /* Code for wakeup lead time calibration */
    {
      static uint32 macBackoffTimerMinMargin = 0xffffffffu;
      uint32 delta = macPrevPeriodRatCount +
        backoffTimerTrigger * MAC_BACKOFF_TO_RAT_RATIO - MAC_RAT_COUNT;
      if (delta < macBackoffTimerMinMargin)
      {
        macBackoffTimerMinMargin = delta;
      }
    }
#endif
  }

  /* Note that MAC_BACKOFF_TIMER_EVENT_POWER_TIMER_EXP handling must always
   * occur after handling of MAC_BACKOFF_TIMER_EVENT_POWER_WAKEUP event
   * because the device might be waking up upon the timer event itself
   * in which case, radio has to be turned on before updating the RAT timer.
   */
  if (events & MAC_BACKOFF_TIMER_EVENT_POWER_TIMER_EXP)
  {
    /* Update wakeup schedule, which most likely would vote not to enter
     * sleep state. */
    HAL_ENTER_CRITICAL_SECTION(is);
    MAC_BACKOFF_TIMER_UPDATE_WAKEUP();
    HAL_EXIT_CRITICAL_SECTION(is);
  }
}
Exemplo n.º 29
0
/**************************************************************************************************
 * @fn          osal_mem_alloc
 *
 * @brief       This function implements the OSAL dynamic memory allocation functionality.
 *
 * input parameters
 *
 * @param size - the number of bytes to allocate from the HEAP.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 */
#ifdef DPRINTF_OSALHEAPTRACE
void *osal_mem_alloc_dbg( uint16 size, const char *fname, unsigned lnum )
#else /* DPRINTF_OSALHEAPTRACE */
void *osal_mem_alloc( uint16 size )
#endif /* DPRINTF_OSALHEAPTRACE */
{
  osalMemHdr_t *prev = NULL;
  osalMemHdr_t *hdr;
  halIntState_t intState;
  uint8 coal = 0;

  size += OSALMEM_HDRSZ;

  // Calculate required bytes to add to 'size' to align to halDataAlign_t.
  if ( sizeof( halDataAlign_t ) == 2 )
  {
    size += (size & 0x01);
  }
  else if ( sizeof( halDataAlign_t ) != 1 )
  {
    const uint8 mod = size % sizeof( halDataAlign_t );

    if ( mod != 0 )
    {
      size += (sizeof( halDataAlign_t ) - mod);
    }
  }

  HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.

  // Smaller allocations are first attempted in the small-block bucket, and all long-lived
  // allocations are channeled into the LL block reserved within this bucket.
  if ((osalMemStat == 0) || (size <= OSALMEM_SMALL_BLKSZ))
  {
    hdr = ff1;
  }
  else
  {
    hdr = (theHeap + OSALMEM_BIGBLK_IDX);
  }

  do
  {
    if ( hdr->hdr.inUse )
    {
      coal = 0;
    }
    else
    {
      if ( coal != 0 )
      {
#if ( OSALMEM_METRICS )
        blkCnt--;
        blkFree--;
#endif

        prev->hdr.len += hdr->hdr.len;

        if ( prev->hdr.len >= size )
        {
          hdr = prev;
          break;
        }
      }
      else
      {
        if ( hdr->hdr.len >= size )
        {
          break;
        }

        coal = 1;
        prev = hdr;
      }
    }

    hdr = (osalMemHdr_t *)((uint8 *)hdr + hdr->hdr.len);

    if ( hdr->val == 0 )
    {
      hdr = NULL;
      break;
    }
  } while (1);

  if ( hdr != NULL )
  {
    uint16 tmp = hdr->hdr.len - size;

    // Determine whether the threshold for splitting is met.
    if ( tmp >= OSALMEM_MIN_BLKSZ )
    {
      // Split the block before allocating it.
      osalMemHdr_t *next = (osalMemHdr_t *)((uint8 *)hdr + size);
      next->val = tmp;                     // Set 'len' & clear 'inUse' field.
      hdr->val = (size | OSALMEM_IN_USE);  // Set 'len' & 'inUse' field.

#if ( OSALMEM_METRICS )
      blkCnt++;
      if ( blkMax < blkCnt )
      {
        blkMax = blkCnt;
      }
      memAlo += size;
#endif
    }
    else
    {
#if ( OSALMEM_METRICS )
      memAlo += hdr->hdr.len;
      blkFree--;
#endif

      hdr->hdr.inUse = TRUE;
    }

#if ( OSALMEM_METRICS )
    if ( memMax < memAlo )
    {
      memMax = memAlo;
    }
#endif

#if ( OSALMEM_PROFILER )
#if !OSALMEM_PROFILER_LL
    if (osalMemStat != 0)  // Don't profile until after the LL block is filled.
#endif
    {
      uint8 idx;

      for ( idx = 0; idx < OSALMEM_PROMAX; idx++ )
      {
        if ( hdr->hdr.len <= proCnt[idx] )
        {
          break;
        }
      }
      proCur[idx]++;
      if ( proMax[idx] < proCur[idx] )
      {
        proMax[idx] = proCur[idx];
      }
      proTot[idx]++;

      /* A small-block could not be allocated in the small-block bucket.
       * When this occurs significantly frequently, increase the size of the
       * bucket in order to restore better worst case run times. Set the first
       * profiling bucket size in proCnt[] to the small-block bucket size and
       * divide proSmallBlkMiss by the corresponding proTot[] size to get % miss.
       * Best worst case time on TrasmitApp was achieved at a 0-15% miss rate
       * during steady state Tx load, 0% during idle and steady state Rx load.
       */
      if ((hdr->hdr.len <= OSALMEM_SMALL_BLKSZ) && (hdr >= (theHeap + OSALMEM_BIGBLK_IDX)))
      {
        proSmallBlkMiss++;
      }
    }

    (void)osal_memset((uint8 *)(hdr+1), OSALMEM_ALOC, (hdr->hdr.len - OSALMEM_HDRSZ));
#endif

    if ((osalMemStat != 0) && (ff1 == hdr))
    {
      ff1 = (osalMemHdr_t *)((uint8 *)hdr + hdr->hdr.len);
    }

    hdr++;
  }

  HAL_EXIT_CRITICAL_SECTION( intState );  // Re-enable interrupts.
#pragma diag_suppress=Pe767
  HAL_ASSERT(((halDataAlign_t)hdr % sizeof(halDataAlign_t)) == 0);
#pragma diag_default=Pe767

#ifdef DPRINTF_OSALHEAPTRACE
  dprintf("osal_mem_alloc(%u)->%lx:%s:%u\n", size, (unsigned) hdr, fname, lnum);
#endif /* DPRINTF_OSALHEAPTRACE */
  return (void *)hdr;
}
Exemplo n.º 30
0
/******************************************************************************
 * @fn      HalUARTWriteDMA
 *
 * @brief   Write a buffer to the UART, enforcing an all or none policy if the requested length
 *          exceeds the space available.
 *
 * @param   buf - pointer to the buffer that will be written, not freed
 *          len - length of
 *
 * @return  length of the buffer that was sent
 *****************************************************************************/
static uint16 HalUARTWriteDMA(uint8 *buf, uint16 len)
{
#if HAL_UART_TX_BY_ISR
  // Enforce all or none.
  if (HAL_UART_DMA_TX_AVAIL() < len)
  {
    return 0;
  }

  for (uint16 cnt = 0; cnt < len; cnt++)
  {
    dmaCfg.txBuf[dmaCfg.txTail] = *buf++;
    dmaCfg.txMT = 0;

    if (dmaCfg.txTail >= HAL_UART_DMA_TX_MAX-1)
    {
      dmaCfg.txTail = 0;
    }
    else
    {
      dmaCfg.txTail++;
    }

    // Keep re-enabling ISR as it might be keeping up with this loop due to other ints.
    IEN2 |= UTXxIE;
  }
#else
  txIdx_t txIdx;
  uint8 txSel;
  halIntState_t his;

  HAL_ENTER_CRITICAL_SECTION(his);
  txSel = dmaCfg.txSel;
  txIdx = dmaCfg.txIdx[txSel];
  HAL_EXIT_CRITICAL_SECTION(his);

  // Enforce all or none.
  if ((len + txIdx) > HAL_UART_DMA_TX_MAX)
  {
    return 0;
  }

  (void)memcpy(&(dmaCfg.txBuf[txSel][txIdx]), buf, len);

  HAL_ENTER_CRITICAL_SECTION(his);
  /* If an ongoing DMA Tx finished while this buffer was being *appended*, then another DMA Tx
   * will have already been started on this buffer, but it did not include the bytes just appended.
   * Therefore these bytes have to be re-copied to the start of the new working buffer.
   */
  if (txSel != dmaCfg.txSel)
  {
    HAL_EXIT_CRITICAL_SECTION(his);
    txSel ^= 1;

    (void)memcpy(&(dmaCfg.txBuf[txSel][0]), buf, len);
    HAL_ENTER_CRITICAL_SECTION(his);
    dmaCfg.txIdx[txSel] = len;
  }
  else
  {
    dmaCfg.txIdx[txSel] = txIdx + len;
  }

  // If there is no ongoing DMA Tx, then the channel must be armed here.
  if (dmaCfg.txIdx[(txSel ^ 1)] == 0)
  {
    HAL_EXIT_CRITICAL_SECTION(his);
    HalUARTArmTxDMA();
  }
  else
  {
    dmaCfg.txMT = FALSE;
    HAL_EXIT_CRITICAL_SECTION(his);
  }
#endif

  return len;
}