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; }
/***************************************************************************//** * @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; } }
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 ); } }
/***************************************************************************//** * @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; }