Example #1
0
int sl_trng_poll( TRNG_TypeDef *device,
                  unsigned char *output,
                  size_t len,
                  size_t *olen )
{
    size_t output_len = 0;
    size_t chunk_len = 0;
    size_t available;
    int ret = 0;

    while (output_len < len)
    {
        available = device->FIFOLEVEL * 4;
        if (available == 0)
        {
            break;
        }

#if !defined(SL_TRNG_IGNORE_ALL_ALARMS)
        /* Check status for current data in FIFO
         * and handle any error conditions. */
        ret = sl_trng_check_status( device );
#if defined(SL_TRNG_IGNORE_NOISE_ALARMS)
        /* Ignore noise alarms by returning 0 (OK) if they occur and
         * keeping the already generated random data. */
        if ( (ret == SL_TRNG_ERR_PRELIMINARY_NOISE_ALARM) ||
             (ret == SL_TRNG_ERR_NOISE_ALARM) )
        {
            ret = 0;
            continue;
        }
#else
        /* Noise alarms trigger a FIFO clearing, and we need to throw
         * away the collected entropy. */
        if ( (ret == SL_TRNG_ERR_PRELIMINARY_NOISE_ALARM) ||
             (ret == SL_TRNG_ERR_NOISE_ALARM) )
        {
            ret = 0;
            output_len = 0;
            continue;
        }
#endif
        /* Alarm has been signaled so we throw the generated data away. */
        if (ret != 0)
        {
            output_len = 0;
            break;
        }
#endif

        chunk_len = SL_MIN(len - output_len, available);
        sl_trng_read_chunk(device, output + output_len, chunk_len);
        output_len += chunk_len;
    }

    *olen = output_len;
    return ret;
}
Example #2
0
File: em_can.c Project: sg-/mbed-os
/***************************************************************************//**
 * @brief
 *   Read the data from a Message Object in the RAM and store it in message.
 *
 * @details
 *   Read all the information from the RAM on this Message Object : the data but
 *   also the configuration of the other registers.
 *
 * @param[in] can
 *   Pointer to CAN peripheral register block.
 *
 * @param[in] interface
 *   Indicate which Message Interface Register to use.
 *
 * @param[in] message
 *   Message Object
 ******************************************************************************/
void CAN_ReadMessage(CAN_TypeDef *can,
                     uint8_t interface,
                     CAN_MessageObject_TypeDef *message)
{
  CAN_MIR_TypeDef * mir = &can->MIR[interface];
  uint32_t buffer;
  uint32_t i;

  /* Make sure msgNum is in the correct range */
  EFM_ASSERT((message->msgNum > 0) && (message->msgNum <= 32));

  CAN_ReadyWait(can, interface);

  /* Set which registers to read from the RAM */
  mir->CMDMASK = CAN_MIR_CMDMASK_WRRD_READ
                 | CAN_MIR_CMDMASK_MASKACC
                 | CAN_MIR_CMDMASK_ARBACC
                 | CAN_MIR_CMDMASK_CONTROL
                 | CAN_MIR_CMDMASK_CLRINTPND
                 | CAN_MIR_CMDMASK_TXRQSTNEWDAT
                 | CAN_MIR_CMDMASK_DATAA
                 | CAN_MIR_CMDMASK_DATAB;

  /* Send reading request and wait (3 to 6 cpu cycle) */
  CAN_SendRequest(can, interface, message->msgNum, true);

  /* Get dlc from the control register */
  message->dlc = ((mir->CTRL & _CAN_MIR_CTRL_DLC_MASK) >> _CAN_MIR_CTRL_DLC_SHIFT);

  /* Make sure dlc is in the correct range */
  EFM_ASSERT(message->dlc <= 8);

  /* Copy the data from the MIR registers to the Message Object message */
  buffer = mir->DATAL;
  for (i = 0; i < SL_MIN(message->dlc, 4U); ++i) {
    message->data[i] = buffer & 0xFF;
    buffer = buffer >> 8;
  }
  if (message->dlc > 3) {
    buffer = mir->DATAH;
    for (i = 0; i < message->dlc - 4U; ++i) {
      message->data[i + 4] = buffer & 0xFF;
      buffer = buffer >> 8;
    }
  }
Example #3
0
static void rescheduleRtc( uint32_t rtcCnt )
{
  int i;
  uint64_t min = UINT64_MAX;

  // Find the timer with shortest timeout.
  for ( i = 0; i < EMDRV_RTCDRV_NUM_TIMERS; i++ ) {
    if (    ( timer[ i ].running   == true )
         && ( timer[ i ].remaining <  min  ) ) {
      min = timer[ i ].remaining;
    }
  }

  rtcRunning = false;
  if ( min != UINT64_MAX ) {
    min = SL_MIN( min, RTC_CLOSE_TO_MAX_VALUE );
#if defined( RTCDRV_USE_RTC )
    if ( inTimerIRQ == false ) {
      lastStart = ( rtcCnt ) & RTC_COUNTER_MASK;
    } else
#endif
    {
      lastStart = rtcCnt;
    }
    RTC_INTCLEAR( RTC_COMP_INT );

    RTC_COMPARESET( rtcCnt + min );

#if defined( EMODE_DYNAMIC )
    // When RTC is running, we can not allow EM3 or EM4.
    if ( sleepBlocked == false ) {
      sleepBlocked = true;
      SLEEP_SleepBlockBegin( sleepEM3 );
    }
#endif

    rtcRunning = true;

    // Reenable compare IRQ.
    RTC_INTENABLE( RTC_COMP_INT );
  }
}
Example #4
0
/***************************************************************************//**
 * @brief
 *    Start a timer.
 *
 * @note
 *    It is legal to start an already running timer.
 *
 * @param[in] id The id of the timer to start.
 * @param[in] type Timer type, oneshot or periodic. See @ref RTCDRV_TimerType_t.
 * @param[in] timeout Timeout expressed in milliseconds. If the timeout value
 *            is 0, the callback function will be called immediately and
 *            the timer will not be started.
 * @param[in] callback Function to call on timer expiry. See @ref
 *            RTCDRV_Callback_t. NULL is a legal value.
 * @param[in] user Extra callback function parameter for user application.
 *
 * @return
 *    @ref ECODE_EMDRV_RTCDRV_OK on success.@n
 *    @ref ECODE_EMDRV_RTCDRV_ILLEGAL_TIMER_ID if id has an illegal value.@n
 *    @ref ECODE_EMDRV_RTCDRV_TIMER_NOT_ALLOCATED if the timer is not reserved.
 ******************************************************************************/
Ecode_t RTCDRV_StartTimer(  RTCDRV_TimerID_t id,
                            RTCDRV_TimerType_t type,
                            uint32_t timeout,
                            RTCDRV_Callback_t callback,
                            void *user )
{
  uint32_t timeElapsed, cnt, compVal, loopCnt = 0;
  uint32_t timeToNextTimerCompletion;

  // Check if valid timer ID.
  if ( id >= EMDRV_RTCDRV_NUM_TIMERS ) {
    return ECODE_EMDRV_RTCDRV_ILLEGAL_TIMER_ID;
  }

  INT_Disable();
  if ( ! timer[ id ].allocated ) {
    INT_Enable();
    return ECODE_EMDRV_RTCDRV_TIMER_NOT_ALLOCATED;
  }

  if ( timeout == 0 ) {
    if ( callback != NULL ) {
      callback( id, user );
    }
    INT_Enable();
    return ECODE_EMDRV_RTCDRV_OK;
  }

  cnt = RTC_COUNTERGET();

  timer[ id ].callback  = callback;
  timer[ id ].ticks     = MSEC_TO_TICKS( timeout );
  if (rtcdrvTimerTypePeriodic == type) {
    // Calculate compensation value for periodic timers.
    timer[ id ].periodicCompensationUsec = 1000 * timeout -
      (timer[ id ].ticks * TICK_TIME_USEC);
    timer[ id ].periodicDriftUsec = TICK_TIME_USEC/2;
  }
  else
  {
    // Compensate for the fact that CNT is normally COMP0+1 after a
    // compare match event on some devices.
    timer[ id ].ticks -= RTC_ONESHOT_TICK_ADJUST;
  }
  // Add one tick in order to compensate if RTC is close to an increment event.
  timer[ id ].remaining = timer[ id ].ticks + 1;
  timer[ id ].running   = true;
  timer[ id ].timerType = type;
  timer[ id ].user      = user;

  if ( inTimerIRQ == true ) {
    // Exit now, remaining processing will be done in IRQ handler.
    INT_Enable();
    return ECODE_EMDRV_RTCDRV_OK;
  }

  // StartTimer() may recurse, keep track of recursion level.
  if ( startTimerNestingLevel < UINT32_MAX ) {
    startTimerNestingLevel++;
  }

  if ( rtcRunning == false ) {

#if defined( RTCDRV_USE_RTC )
    lastStart = ( cnt ) & RTC_COUNTER_MASK;
#elif defined( RTCDRV_USE_RTCC )
    lastStart = cnt;
#endif

    RTC_INTCLEAR( RTC_COMP_INT );

    compVal = SL_MIN( timer[ id ].remaining, RTC_CLOSE_TO_MAX_VALUE );
    RTC_COMPARESET( cnt + compVal );

    // Start the timer system by enabling the compare interrupt.
    RTC_INTENABLE( RTC_COMP_INT );

#if defined( EMODE_DYNAMIC )
    // When RTC is running, we can not allow EM3 or EM4.
    if ( sleepBlocked == false ) {
      sleepBlocked = true;
      SLEEP_SleepBlockBegin( sleepEM3 );
    }
#endif

    rtcRunning = true;

  } else {

    // The timer system is running. We must stop, update timers with the time
    // elapsed so far, find the timer with the shortest timeout and then restart.
    // As StartTimer() may be called from the callbacks we only do this
    // processing at the first nesting level.
    if ( startTimerNestingLevel == 1  ) {

      timer[ id ].running = false;
      // This loop is repeated if CNT is incremented while processing.
      do {

        RTC_INTDISABLE( RTC_COMP_INT );

        timeElapsed = TIMEDIFF( cnt, lastStart );
#if defined( RTCDRV_USE_RTC )
        // Compensate for the fact that CNT is normally COMP0+1 after a
        // compare match event.
        if ( timeElapsed == RTC_MAX_VALUE ) {
          timeElapsed = 0;
        }
#endif

        // Update all timers with elapsed time.
        checkAllTimers( timeElapsed );

        // Execute timer callbacks.
        executeTimerCallbacks();

        // Set timer to running only after checkAllTimers() is called once.
        if ( loopCnt == 0 ) {
          timer[ id ].running = true;
        }
        loopCnt++;

        // Restart RTC according to next timeout.
        rescheduleRtc( cnt );

        cnt = RTC_COUNTERGET();
        timeElapsed = TIMEDIFF( cnt, lastStart );
        timeToNextTimerCompletion = TIMEDIFF( RTC_COMPAREGET(), lastStart );

        /* If the counter has passed the COMP(ARE) register value since we
           checked the timers, then we should recheck the timers and reschedule
           again. */
      }
      while ( rtcRunning && (timeElapsed > timeToNextTimerCompletion));
    }
  }

  if ( startTimerNestingLevel > 0 ) {
    startTimerNestingLevel--;
  }

  INT_Enable();
  return ECODE_EMDRV_RTCDRV_OK;
}