Esempio n. 1
0
__ramfunc void FlushFlash( void )
#endif
{
  /* We can't serve interrupts while erasing or writing to flash. */
  INT_Disable();

  MSC->LOCK = MSC_UNLOCK_CODE;

  /* Erase flash page */
  MSC_ErasePage( (uint32_t*)flashStatus.pPageBase );

  /* Program flash page */
  MSC_WriteWord( (uint32_t*)flashStatus.pPageBase, flashPageBuf, flashPageSize );

  MSC->LOCK = 0;

  INT_Enable();
}
Esempio n. 2
0
/***************************************************************************//**
 * @brief
 *    Stop a given timer.
 *
 * @param[in] id The id of the timer to stop.
 *
 * @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_StopTimer( RTCDRV_TimerID_t id )
{
  // 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;
  }

  timer[ id ].running = false;
  INT_Enable();

  return ECODE_EMDRV_RTCDRV_OK;
}
Esempio n. 3
0
/*! \brief Mailbox pend function
 *
 *	Only tasks can pend on mailboxes. If a mailbox is not empty the message is returned to the caller and the system call
 *	returns with SYS_OK. When there is no message the task is pending and SYS_ERROR is returned. If the caller 
 *	specifed a timeout value a timer is started and the task is delayed from execution. After the timeout expires
 *	(no task or interrupt posted a message) the task is unblocked and \e SYS_MBX_TOUT is passed to the task's entry 
 *	parameter. If somebody posted a message the timer is removed and the \e SYS_MBX values is passed to the task.
 *  \param ph		handle to mailbox
 *  \param pmsg 	pointer caller where the message will be copied
 *  \param tout 	timeout value 
 *	\retval SYS_OK if there was a message in mailbox
 *	\retval SYS_ERR if there was no messages in mailbox
 *  \attention MBX_pend can not be called from an ISR.
 */
STATUS MBX_Pend(HANDLE *ph, void *pmsg, uint16 tout) {	
	tcb_t *ptcb;
	mcb_t *pmcb;
    msg_t *pmsg_entry;        
	size_t flags;
	
	ptcb = get_curr_tsk();
	pmcb = (mcb_t*) ph;

	flags = INT_Disable();
	
	/* Check if there is a message already in the mailbox */
	if( !(pmsg_entry = (msg_t*) dequeue_top_object( (queue_t*) &pmcb->full_list)) ) {
		if( tout == NO_WAIT ) {
    		INT_Restore( flags );
            return SYS_ERROR;
    	}
        ptcb->pqueue = (queue_t*) &pmcb->emptyq;
        ptcb->flags = TSK_MBX_PEND;
		
		enqueue_top_object(&pmcb->emptyq, (dll_t*) ptcb);
		append_timeout(ptcb, &mbx_tout_clb, tout);
          
       	INT_Restore( flags );
        return SYS_ERROR;
	}
	/* Copy message to task */ 
	memcpy( pmsg, pmsg_entry->pdata, pmcb->len );
	
	/* Check if there was a task waiting for an empty entry in the mailbox */
	if( (ptcb = (tcb_t*) dequeue_top_object( (queue_t*) &pmcb->fullq)) ) {
		ptcb->flags	= TSK_READY;
		ptcb->event = SYS_MBX;
		ptcb->pmsg_entry = pmsg_entry;
		priority_enqueue_tsk( ptcb );
		remove_timeout( &ptcb->tic );		
	}
	else {
		enqueue_bottom_object( (queue_t*) &pmcb->free_list, (dll_t*) pmsg_entry );
	}
    INT_Restore( flags );
    return SYS_OK;
}
void *memoryPtrFromHandle(void *handle)
{
  void *ptr = NULL;

  // Make sure we were given a valid handle
  if((handle == INVALID_BUFFER_OBJ) || ((uint32_t)handle > BUFFER_POOL_SIZE))
  {
    return NULL;
  }

  INT_Disable();
  if(memoryObjs[(uint32_t)handle].refCount > 0)
  {
    ptr = memoryObjs[(uint32_t)handle].data;
  }
  INT_Enable();

  return ptr;
}
Esempio n. 5
0
/**************************************************************************//**
 * @brief Receive a byte from USART/LEUART and put into global buffer
 * @return -1 on failure, or positive character integer on sucesss
 *****************************************************************************/
int UART1_ReadChar(void)
{
  int c = -1;

  INT_Disable();
  if (rxCount > 0)
  {
    c = rxBuffer[rxReadIndex];
    rxReadIndex++;
    if (rxReadIndex == RXBUFSIZE)
    {
      rxReadIndex = 0;
    }
    rxCount--;
  }
  INT_Enable();

  return c;
}
Esempio n. 6
0
/***************************************************************************//**
 * @brief
 *  Initialize DMADRV.
 *
 * @details
 *  The DMA hw is initialized.
 *
 * @return
 *  @ref ECODE_EMDRV_DMADRV_OK on success. On failure an appropriate
 *  DMADRV @ref Ecode_t is returned.
 ******************************************************************************/
Ecode_t DMADRV_Init( void )
{
  int i;
#if defined( EMDRV_DMADRV_UDMA )
  DMA_Init_TypeDef dmaInit;
#elif defined( EMDRV_DMADRV_LDMA )
  LDMA_Init_t dmaInit = LDMA_INIT_DEFAULT;
  dmaInit.ldmaInitCtrlNumFixed = EMDRV_DMADRV_DMA_CH_PRIORITY;
#endif


  INT_Disable();
  if ( initialized )
  {
    INT_Enable();
    return ECODE_EMDRV_DMADRV_ALREADY_INITIALIZED;
  }
  initialized = true;
  INT_Enable();

  if ( EMDRV_DMADRV_DMA_IRQ_PRIORITY > 7 )
  {
    return ECODE_EMDRV_DMADRV_PARAM_ERROR;
  }

  for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
  {
    chTable[ i ].allocated = false;
  }

#if defined( EMDRV_DMADRV_UDMA )
  NVIC_SetPriority( DMA_IRQn, EMDRV_DMADRV_DMA_IRQ_PRIORITY );
  dmaInit.hprot        = 0;
  dmaInit.controlBlock = dmaControlBlock;
  DMA_Init( &dmaInit );
#elif defined( EMDRV_DMADRV_LDMA )
  dmaInit.ldmaInitIrqPriority = EMDRV_DMADRV_DMA_IRQ_PRIORITY;
  LDMA_Init( &dmaInit );
#endif

  return ECODE_EMDRV_DMADRV_OK;
}
Esempio n. 7
0
/**************************************************************************//**
 * @brief Decode single byte to BOOTLOADER_Hijack
 *****************************************************************************/
__ramfunc uint8_t dec_rxByte(void)
{
  uint8_t ch;

  //while ( !decBuf.pendingBytes ) ;
  /* Copy data from buffer */
#if CRITICAL_PROTECTION==1
  INT_Disable();
#endif
  ch        = decBuf.data[decBuf.rdI];
  decBuf.rdI = (decBuf.rdI + 1) % BUFFERSIZE;
  /* Decrement pending byte counter */
  decBuf.pendingBytes--;

#if CRITICAL_PROTECTION==1
  INT_Enable();
#endif
  USART_txByte( ch ) ;
  return( ch );
}
Esempio n. 8
0
void halIrqxIsr(uint8_t pin)
{
  UNUSED_VAR(pin);

  INT_Disable();
  
  /* Clear IT flag */
  GPIO_IntClear(1 << RF_INT_PIN);

  /* Call IT handler function if defined */
  if (halExtDeviceIntCB != NULL) {
    (*halExtDeviceIntCB)();
  }

  INT_Enable();

  if (halExtDeviceIntPending()) {
    // Repend this IT
    GPIO_IntSet(1 << RF_INT_PIN);
  }
}
Esempio n. 9
0
/***************************************************************************//**
 * @brief
 *   Sets the system to sleep into the lowest possible energy mode.
 *
 * @details
 *   This function takes care of the system states protected by the sleep block
 *   provided by SLEEP_SleepBlockBegin() / SLEEP_SleepBlockEnd(). It allows
 *   the system to go into the lowest possible energy mode that the device can
 *   be set into at the time of the call of this function.
 *   This function will not go lower than EM3 because leaving EM4 requires
 *   resetting MCU. To enter into EM4 call SLEEP_ForceSleepInEM4().
 *
 * @return
 *   Energy Mode that was entered. Possible values:
 *   @li sleepEM0
 *   @li sleepEM1
 *   @li sleepEM2
 *   @li sleepEM3
 ******************************************************************************/
SLEEP_EnergyMode_t SLEEP_Sleep(void)
{
  SLEEP_EnergyMode_t allowedEM;

  INT_Disable();

  allowedEM = SLEEP_LowestEnergyModeGet();

  if ((allowedEM >= sleepEM1) && (allowedEM <= sleepEM3))
  {
    SLEEP_EnterEMx(allowedEM);
  }
  else
  {
    allowedEM = sleepEM0;
  }

  INT_Enable();

  return(allowedEM);
}
Esempio n. 10
0
/***************************************************************************//**
 * @brief
 *    Check if a given timer is running.
 *
 * @param[in] id The id of the timer to query.
 *
 * @param[out] isRunning True if timer is running. False if not running.
 *                       Only valid if return status is ECODE_EMDRV_RTCDRV_OK.
 *
 * @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.@n
 *    @ref ECODE_EMDRV_RTCDRV_PARAM_ERROR if an invalid isRunning pointer was
 *         supplied.
 ******************************************************************************/
Ecode_t RTCDRV_IsRunning( RTCDRV_TimerID_t id, bool *isRunning )
{
  // Check if valid timer ID.
  if ( id >= EMDRV_RTCDRV_NUM_TIMERS ) {
    return ECODE_EMDRV_RTCDRV_ILLEGAL_TIMER_ID;
  }

  // Check pointer validity.
  if ( isRunning == NULL ) {
    return ECODE_EMDRV_RTCDRV_PARAM_ERROR;
  }

  INT_Disable();
  // Check if timer is reserved.
  if ( ! timer[ id ].allocated ) {
    INT_Enable();
    return ECODE_EMDRV_RTCDRV_TIMER_NOT_ALLOCATED;
  }
  *isRunning = timer[ id ].running;
  INT_Enable();

  return ECODE_EMDRV_RTCDRV_OK;
}
Esempio n. 11
0
/***************************************************************************//**
 * @brief
 *  Free an allocate (reserved) DMA channel.
 *
 * @param[in] channelId
 *  The channel Id to free.
 *
 * @return
 *  @ref ECODE_EMDRV_DMADRV_OK on success. On failure an appropriate
 *  DMADRV @ref Ecode_t is returned.
 ******************************************************************************/
Ecode_t DMADRV_FreeChannel( unsigned int channelId )
{
  if ( !initialized )
  {
    return ECODE_EMDRV_DMADRV_NOT_INITIALIZED;
  }

  if ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
  {
    return ECODE_EMDRV_DMADRV_PARAM_ERROR;
  }

  INT_Disable();
  if ( chTable[ channelId ].allocated )
  {
    chTable[ channelId ].allocated = false;
    INT_Enable();
    return ECODE_EMDRV_DMADRV_OK;
  }
  INT_Enable();

  return ECODE_EMDRV_DMADRV_ALREADY_FREED;
}
Esempio n. 12
0
/**************************************************************************//**
 * @brief Receive a byte from USART/LEUART and put into global buffer
 * @return -1 on failure, or positive character integer on sucesss
 *****************************************************************************/
int RETARGET_ReadChar(void)
{
  int c = -1;

  if (initialized == false)
  {
    RETARGET_SerialInit();
  }

  INT_Disable();
  if (rxCount > 0)
  {
    c = rxBuffer[rxReadIndex];
    rxReadIndex++;
    if (rxReadIndex == RXBUFSIZE)
    {
      rxReadIndex = 0;
    }
    rxCount--;
  }
  INT_Enable();

  return c;
}
Esempio n. 13
0
/***************************************************************************//**
 * @brief
 *   Active SO Interrupt handler
 * @note
 * 		Note: may be called synchronously (completion == NULL), in which case
 * 		this function does not return until the SO interrupt occurs, or
 * 		asynchronously (completion != NULL), in which case this function merely
 * 		sets up the interrupt, returns to the caller, and the caller should do
 * 		whatever is desired until the SO interrupt occurs, at which time the
 * 		completion function is called.
 * @param[in] level
 * 		Determines Edge Level Interrupt: Rising/Falling, spiflash_info->so_done_level
 * 		is the variable that is passed into the function and is initialized in the
 * 		Device table found in spiflash.c
 * @param[in] *completion
 * 		Completion State machine callback function
 * @param[in] *completion_ref
 * 		Argument to be passed to completion callback
 *******************************************************************************/
void spi_wait_so(uint8_t level,
                 spi_completion_fn_t *completion,  // completion callback fn
		         void *completion_ref)  // argument to be passed to completion callback
{
	so_completion = completion;
	so_completion_ref = completion_ref;
	so_busy = true;

	INT_Disable();

	// enable IRQ
	// The EFM32 has edge-triggered interrupts, so we'll never get an
	// interrupt if the port pin was already at the desired level.  To
	// avoid deadlock, we check the pin state here, and if it's already
	// at the desired level, simulate an edge interrupt.
	p1 = GPIO_PinInGet(RX_PORT, RX_PIN);
	if (p1 == level)
	{
		so_irq_fake_count++;
		SO_IRQ(NULL);
	}
	else
	{
		// Note that GPIO_IntConfig will clear any pending IRQ for the pin
		GPIO_IntConfig(RX_PORT, RX_PIN,
					   level,  // risingEdge
					   !level, // fallingEdge
					   true);  // enable
	}
	INT_Enable();

	// if called synchronously, actually wait here
	if (!completion)
		while (so_busy)
			enter_low_power_state();
}
void* memoryAllocate(uint32_t size)
{
  uint32_t i = 0;
  void *handle = INVALID_BUFFER_OBJ;

  // We can't support sizes greater than the maximum heap buffer size
  if(size > MAX_BUFFER_SIZE) {
    return INVALID_BUFFER_OBJ;
  }

  INT_Disable();
  for(i = 0; i < BUFFER_POOL_SIZE; i++)
  {
    if(memoryObjs[i].refCount == 0)
    {
      memoryObjs[i].refCount = 1;
      handle = (void*)i;
      break;
    }
  }
  INT_Enable();

  return handle;
}
Esempio n. 15
0
/***************************************************************************//**
 * @brief
 *   Stop USB device operation.
 *
 * @details
 *   Device operation is stopped by disconnecting the pullup resistor from the
 *   appropriate USB data line. Often referred to as a "soft" disconnect.
 ******************************************************************************/
void USBD_Disconnect( void )
{
  INT_Disable();
  USBDHAL_Disconnect();
  INT_Enable();
}
Esempio n. 16
0
/***************************************************************************//**
 * @brief
 *   Start a DMA transfer.
 *
 * @param[in] ch
 *   DMA channel.
 *
 * @param[in] transfer
 *   Initialization structure used to configure the transfer.
 *
 * @param[in] descriptor
 *   Transfer descriptor, can be an array of descriptors linked together.
 ******************************************************************************/
void LDMA_StartTransfer(  int ch,
                          LDMA_TransferCfg_t *transfer,
                          LDMA_Descriptor_t  *descriptor )
{
  uint32_t tmp;
  uint32_t chMask = 1 << ch;

  EFM_ASSERT( ch < DMA_CHAN_COUNT );
  EFM_ASSERT( transfer != NULL );
  EFM_ASSERT( !( transfer->ldmaReqSel & ~_LDMA_CH_REQSEL_MASK ) );

  EFM_ASSERT( !( ( transfer->ldmaCtrlSyncPrsClrOff << _LDMA_CTRL_SYNCPRSCLREN_SHIFT )
                 & ~_LDMA_CTRL_SYNCPRSCLREN_MASK ) );
  EFM_ASSERT( !( ( transfer->ldmaCtrlSyncPrsClrOn << _LDMA_CTRL_SYNCPRSCLREN_SHIFT )
                 & ~_LDMA_CTRL_SYNCPRSCLREN_MASK ) );
  EFM_ASSERT( !( ( transfer->ldmaCtrlSyncPrsSetOff << _LDMA_CTRL_SYNCPRSSETEN_SHIFT )
                 & ~_LDMA_CTRL_SYNCPRSSETEN_MASK ) );
  EFM_ASSERT( !( ( transfer->ldmaCtrlSyncPrsSetOn << _LDMA_CTRL_SYNCPRSSETEN_SHIFT  )
                 & ~_LDMA_CTRL_SYNCPRSSETEN_MASK ) );

  EFM_ASSERT( !( ( transfer->ldmaCfgArbSlots << _LDMA_CH_CFG_ARBSLOTS_SHIFT )
                 & ~_LDMA_CH_CFG_ARBSLOTS_MASK ) );
  EFM_ASSERT( !( ( transfer->ldmaCfgSrcIncSign << _LDMA_CH_CFG_SRCINCSIGN_SHIFT )
                 & ~_LDMA_CH_CFG_SRCINCSIGN_MASK ) );
  EFM_ASSERT( !( ( transfer->ldmaCfgDstIncSign << _LDMA_CH_CFG_DSTINCSIGN_SHIFT )
                 & ~_LDMA_CH_CFG_DSTINCSIGN_MASK ) );
  EFM_ASSERT( !( ( transfer->ldmaLoopCnt << _LDMA_CH_LOOP_LOOPCNT_SHIFT )
                 & ~_LDMA_CH_LOOP_LOOPCNT_MASK ) );

  LDMA->CH[ ch ].REQSEL = transfer->ldmaReqSel;

  LDMA->CH[ ch ].LOOP =
    (   transfer->ldmaLoopCnt       << _LDMA_CH_LOOP_LOOPCNT_SHIFT     );

  LDMA->CH[ ch ].CFG =
    ( transfer->ldmaCfgArbSlots     << _LDMA_CH_CFG_ARBSLOTS_SHIFT     )
    | ( transfer->ldmaCfgSrcIncSign << _LDMA_CH_CFG_SRCINCSIGN_SHIFT   )
    | ( transfer->ldmaCfgDstIncSign << _LDMA_CH_CFG_DSTINCSIGN_SHIFT   );

  /* Set descriptor address. */
  LDMA->CH[ ch ].LINK = (uint32_t)descriptor & _LDMA_CH_LINK_LINKADDR_MASK;

  /* Clear pending channel interrupt. */
  LDMA->IFC = chMask;

  /* Critical region. */
  INT_Disable();

  /* Enable channel interrupt. */
  LDMA->IEN |= chMask;

  if ( transfer->ldmaReqDis )
  {
    LDMA->REQDIS |= chMask;
  }

  if ( transfer->ldmaDbgHalt )
  {
    LDMA->DBGHALT |= chMask;
  }

  tmp = LDMA->CTRL;

  if ( transfer->ldmaCtrlSyncPrsClrOff )
  {
    tmp &= ~_LDMA_CTRL_SYNCPRSCLREN_MASK
           | (~transfer->ldmaCtrlSyncPrsClrOff << _LDMA_CTRL_SYNCPRSCLREN_SHIFT);
  }

  if ( transfer->ldmaCtrlSyncPrsClrOn )
  {
    tmp |= transfer->ldmaCtrlSyncPrsClrOn << _LDMA_CTRL_SYNCPRSCLREN_SHIFT;
  }

  if ( transfer->ldmaCtrlSyncPrsSetOff )
  {
    tmp &= ~_LDMA_CTRL_SYNCPRSSETEN_MASK
           | (~transfer->ldmaCtrlSyncPrsSetOff << _LDMA_CTRL_SYNCPRSSETEN_SHIFT);
  }

  if ( transfer->ldmaCtrlSyncPrsSetOn )
  {
    tmp |= transfer->ldmaCtrlSyncPrsSetOn << _LDMA_CTRL_SYNCPRSSETEN_SHIFT;
  }

  LDMA->CTRL = tmp;

  BUS_RegMaskedClear(&LDMA->CHDONE, chMask);  /* Clear the done flag.     */
  LDMA->LINKLOAD = chMask;                    /* Enable descriptor load.  */
  BUS_RegMaskedSet(&LDMA->CHEN, chMask);      /* Enable channel.          */

  /* Critical region end. */
  INT_Enable();
}
Esempio n. 17
0
__ramfunc
#endif
#endif /* !EM_MSC_RUN_FROM_FLASH */
__STATIC_INLINE MSC_Status_TypeDef
  MSC_LoadWriteData(uint32_t* data,
                    uint32_t numWords,
                    MSC_WriteStrategy_Typedef writeStrategy)
{
  uint32_t timeOut;
  uint32_t wordIndex;
  uint32_t wordsPerDataPhase;
  MSC_Status_TypeDef retval = mscReturnOk;

#if defined(_MSC_WRITECTRL_LPWRITE_MASK) && defined(_MSC_WRITECTRL_WDOUBLE_MASK)
  /* If LPWRITE (Low Power Write) is NOT enabled, set WDOUBLE (Write Double word) */
  if (!(MSC->WRITECTRL & MSC_WRITECTRL_LPWRITE))
  {
    /* If the number of words to be written are odd, we need to align by writing
       a single word first, before setting the WDOUBLE bit. */
    if (numWords & 0x1)
    {
      /* Wait for the MSC to become ready for the next word. */
      timeOut = MSC_PROGRAM_TIMEOUT;
      while ((!(MSC->STATUS & MSC_STATUS_WDATAREADY)) && (timeOut != 0))
      {
        timeOut--;
      }
      /* Check for timeout */
      if (timeOut == 0)
      {
        return mscReturnTimeOut;
      }
      /* Clear double word option, in order to write the initial single word. */
      MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
      /* Write first data word. */
      MSC->WDATA = *data++;
      MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;

      /* Wait for the operation to finish. It may be required to change the WDOUBLE
         config after the initial write. It should not be changed while BUSY. */
      timeOut = MSC_PROGRAM_TIMEOUT;
      while((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
      {
        timeOut--;
      }
      /* Check for timeout */
      if (timeOut == 0)
      {
        return mscReturnTimeOut;
      }
      /* Subtract this initial odd word for the write loop below */
      numWords -= 1;
      retval = mscReturnOk;
    }
    /* Now we can set the double word option in order to write two words per
       data phase. */
    MSC->WRITECTRL |= MSC_WRITECTRL_WDOUBLE;
    wordsPerDataPhase = 2;
  }
  else
#endif /* defined( _MSC_WRITECTRL_LPWRITE_MASK ) && defined( _MSC_WRITECTRL_WDOUBLE_MASK ) */
  {
    wordsPerDataPhase = 1;
  }

  /* Write the rest as double word write if wordsPerDataPhase == 2 */
  if (numWords > 0)
  {
    /**** Write strategy: mscWriteIntSafe ****/
    if (writeStrategy == mscWriteIntSafe)
    {
      /* Requires a system core clock at 1MHz or higher */
      EFM_ASSERT(SystemCoreClockGet() >= 1000000);
      wordIndex = 0;
      while(wordIndex < numWords)
      {
        MSC->WDATA = *data++;
        wordIndex++;
        if (wordsPerDataPhase == 2)
        {
          while (!(MSC->STATUS & MSC_STATUS_WDATAREADY));
          MSC->WDATA = *data++;
          wordIndex++;
        }
        MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;

        /* Wait for the transaction to finish. */
        timeOut = MSC_PROGRAM_TIMEOUT;
        while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
        {
          timeOut--;
        }
        /* Check for timeout */
        if (timeOut == 0)
        {
          retval = mscReturnTimeOut;
          break;
        }
#if defined( _EFM32_GECKO_FAMILY )
        MSC->ADDRB += 4;
        MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
#endif
      }
    }

    /**** Write strategy: mscWriteFast ****/
    else
    {
#if defined( _EFM32_GECKO_FAMILY )
      /* Gecko does not have auto-increment of ADDR. */
      EFM_ASSERT(0);
#else
      /* Requires a system core clock at 14MHz or higher */
      EFM_ASSERT(SystemCoreClockGet() >= 14000000);

      wordIndex = 0;
      INT_Disable();
      while(wordIndex < numWords)
      {
        /* Wait for the MSC to be ready for the next word. */
        while (!(MSC->STATUS & MSC_STATUS_WDATAREADY))
        {
          /* If the write to MSC->WDATA below missed the 30us timeout and the
             following MSC_WRITECMD_WRITETRIG command arrived while
             MSC_STATUS_BUSY is 1, then the MSC_WRITECMD_WRITETRIG could be ignored by
             the MSC. In this case, MSC_STATUS_WORDTIMEOUT is set to 1
             and MSC_STATUS_BUSY is 0. A new trigger is therefore needed here to
             complete write of data in MSC->WDATA.
             If WDATAREADY became high since entry into this loop, exit and continue
             to the next WDATA write.
          */
          if ((MSC->STATUS & (MSC_STATUS_WORDTIMEOUT
                              | MSC_STATUS_BUSY
                              | MSC_STATUS_WDATAREADY))
              == MSC_STATUS_WORDTIMEOUT)
          {
            MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
          }
        }
        MSC->WDATA = *data;
        if ((wordsPerDataPhase == 1)
            || ((wordsPerDataPhase == 2) && (wordIndex & 0x1)))
        {
          MSC->WRITECMD = MSC_WRITECMD_WRITETRIG;
        }
        data++;
        wordIndex++;
      }
      INT_Enable();

      /* Wait for the transaction to finish. */
      timeOut = MSC_PROGRAM_TIMEOUT;
      while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
      {
        timeOut--;
      }
      /* Check for timeout */
      if (timeOut == 0)
      {
        retval = mscReturnTimeOut;
      }
#endif
    } /* writeStrategy */
  }

#if defined( _MSC_WRITECTRL_WDOUBLE_MASK )
  /* Clear double word option, which should not be left on when returning. */
  MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
#endif

  return retval;
}
Esempio n. 18
0
/*
 * USB_IRQHandler() is the first level handler for the USB peripheral interrupt.
 */
void USB_IRQHandler( void )
{
	uint32_t status;
	bool servedVbusInterrupt = false;

	INT_Disable();

#if ( USB_PWRSAVE_MODE )
	if ( USBD_poweredDown )
	{
		/* Switch USBC clock from 32kHz to HFCLK to be able to read USB */
		/* peripheral registers.                                        */
		/* If we woke up from EM2, HFCLK is now HFRCO.                  */

		CMU_OscillatorEnable( cmuOsc_HFXO, true, false);  /* Prepare HFXO. */
		CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV;
		while ( !( CMU->STATUS & CMU_STATUS_USBCHFCLKSEL ) ) { }
	}
#endif /* if ( USB_PWRSAVE_MODE ) */

	if ( USB->IF && ( USB->CTRL & USB_CTRL_VREGOSEN ) )
	{
		if ( USB->IF & USB_IF_VREGOSH )
		{
			USB->IFC = USB_IFC_VREGOSH;

			if ( USB->STATUS & USB_STATUS_VREGOS )
			{
				servedVbusInterrupt = true;
				DEBUG_USB_INT_LO_PUTS( "\nVboN" );

#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF )
				if ( UsbPowerUp() )
#endif
				{
					USBDHAL_EnableUsbResetInt();
				}

				USBD_SetUsbState( USBD_STATE_POWERED );
			}
		}

		if ( USB->IF & USB_IF_VREGOSL )
		{
			USB->IFC = USB_IFC_VREGOSL;

			if ( !( USB->STATUS & USB_STATUS_VREGOS ) )
			{
				servedVbusInterrupt = true;
				DEBUG_USB_INT_LO_PUTS( "\nVboF" );

				USB->GINTMSK = 0;
				USB->GINTSTS = 0xFFFFFFFF;

#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF )
				UsbPowerDown();
#endif
				USBD_SetUsbState( USBD_STATE_NONE );
			}
		}
	}

	status = USBHAL_GetCoreInts();
	if ( status == 0 )
	{
		INT_Enable();
		if ( !servedVbusInterrupt )
		{
			DEBUG_USB_INT_LO_PUTS( "\nSinT" );
		}
		return;
	}

	HANDLE_INT( USB_GINTSTS_RESETDET   )
	HANDLE_INT( USB_GINTSTS_WKUPINT    )
	HANDLE_INT( USB_GINTSTS_USBSUSP    )
	HANDLE_INT( USB_GINTSTS_SOF        )
	HANDLE_INT( USB_GINTSTS_ENUMDONE   )
	HANDLE_INT( USB_GINTSTS_USBRST     )
	HANDLE_INT( USB_GINTSTS_IEPINT     )
	HANDLE_INT( USB_GINTSTS_OEPINT     )

	INT_Enable();

	if ( status != 0 )
	{
		DEBUG_USB_INT_LO_PUTS( "\nUinT" );
	}
}
Esempio n. 19
0
/***************************************************************************//**
 * @brief
 *   Start a write (IN) transfer on an endpoint.
 *
 * @param[in] epAddr
 *   Endpoint address.
 *
 * @param[in] data
 *   Pointer to transfer data buffer. This buffer must be WORD (4 byte) aligned.
 *
 * @param[in] byteCount
 *   Transfer length.
 *
 * @param[in] callback
 *   Function to be called on transfer completion. Supply NULL if no callback
 *   is needed. See @ref USB_XferCompleteCb_TypeDef.
 *
 * @return
 *   @ref USB_STATUS_OK on success, else an appropriate error code.
 ******************************************************************************/
int USBD_Write( int epAddr, void *data, int byteCount,
                USB_XferCompleteCb_TypeDef callback )
{
  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );

  if ( ep == NULL )
  {
    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Illegal endpoint" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

  if ( (   byteCount > MAX_XFER_LEN                           ) ||
       ( ( byteCount / ep->packetSize ) > MAX_PACKETS_PR_XFER )    )
  {
    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Illegal transfer size" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

#if !defined( USB_SLAVEMODE )
  if ( (uint32_t)data & 3 )
  {
    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Misaligned data buffer" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }
#endif

  INT_Disable();
  if ( USBDHAL_EpIsStalled( ep ) )
  {
    INT_Enable();
    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Endpoint is halted" );
    return USB_STATUS_EP_STALLED;
  }

  if ( ep->state != D_EP_IDLE )
  {
    INT_Enable();
    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Endpoint is busy" );
    return USB_STATUS_EP_BUSY;
  }

  if ( ( ep->num > 0 ) && ( USBD_GetUsbState() != USBD_STATE_CONFIGURED ) )
  {
    INT_Enable();
    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Device not configured" );
    return USB_STATUS_DEVICE_UNCONFIGURED;
  }

  ep->buf       = (uint8_t*)data;
  ep->remaining = byteCount;
  ep->xferred   = 0;

  if ( ep->num == 0 )
  {
    ep->in = true;
  }
  else if ( ep->in != true )
  {
    INT_Enable();
    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Illegal EP direction" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

  ep->state          = D_EP_TRANSMITTING;
  ep->xferCompleteCb = callback;

  USBD_ArmEp( ep );
  INT_Enable();
  return USB_STATUS_OK;
}
Esempio n. 20
0
/***************************************************************************//**
 * @brief
 *   Abort all pending transfers.
 *
 * @details
 *   Aborts transfers for all endpoints currently in use. Pending
 *   transfers on the default endpoint (EP0) are not aborted.
 ******************************************************************************/
void USBD_AbortAllTransfers( void )
{
  INT_Disable();
  USBDHAL_AbortAllTransfers( USB_STATUS_EP_ABORTED );
  INT_Enable();
}
Esempio n. 21
0
/*==============================================================================
  hal_enterCritical()
==============================================================================*/
void hal_enterCritical( void )
{
    /* enter critical section */
    INT_Disable();

} /* hal_enterCritical() */
Esempio n. 22
0
static void dequeueFifoBuffer(COM_Port_t port, uint16_t count)
{
  INT_Disable();
  FIFO_DEQUEUE_MULTIPLE(comhandle[port]->txQueue,comhandle[port]->txsize,count);
  INT_Enable();
}
Esempio n. 23
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;
}
Esempio n. 24
0
/***************************************************************************//**
 * @brief
 *   Initializes USB device hardware and internal protocol stack data structures,
 *   then connects the data-line (D+ or D-) pullup resistor to signal host that
 *   enumeration can begin.
 *
 * @note
 *   You may later use @ref USBD_Disconnect() and @ref USBD_Connect() to force
 *   reenumeration.
 *
 * @param[in] p
 *   Pointer to device initialization struct. See @ref USBD_Init_TypeDef.
 *
 * @return
 *   @ref USB_STATUS_OK on success, else an appropriate error code.
 ******************************************************************************/
int USBD_Init( const USBD_Init_TypeDef *p )
{
  int numEps;
  USBD_Ep_TypeDef *ep;
  uint8_t txFifoNum;
  uint8_t *conf, *confEnd;
  USB_EndpointDescriptor_TypeDef *epd;
  uint32_t totalRxFifoSize, totalTxFifoSize, numInEps, numOutEps;

  CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO );
#if ( USB_USBC_32kHz_CLK == USB_USBC_32kHz_CLK_LFXO )
  CMU_OscillatorEnable( cmuOsc_LFXO, true, false );
#else
  CMU_OscillatorEnable( cmuOsc_LFRCO, true, false );
#endif
  USBTIMER_Init();

  memset( dev, 0, sizeof( USBD_Device_TypeDef ) );

  dev->setup                = dev->setupPkt;
  dev->deviceDescriptor     = p->deviceDescriptor;
  dev->configDescriptor     = (USB_ConfigurationDescriptor_TypeDef*)
                              p->configDescriptor;
  dev->stringDescriptors    = p->stringDescriptors;
  dev->numberOfStrings      = p->numberOfStrings;
  dev->state                = USBD_STATE_LASTMARKER;
  dev->savedState           = USBD_STATE_NONE;
  dev->lastState            = USBD_STATE_NONE;
  dev->callbacks            = p->callbacks;
  dev->remoteWakeupEnabled  = false;

  /* Initialize EP0 */

  ep                 = &dev->ep[ 0 ];
  ep->in             = false;
  ep->buf            = NULL;
  ep->num            = 0;
  ep->mask           = 1;
  ep->addr           = 0;
  ep->type           = USB_EPTYPE_CTRL;
  ep->txFifoNum      = 0;
  ep->packetSize     = USB_EP0_SIZE;
  ep->remaining      = 0;
  ep->xferred        = 0;
  ep->state          = D_EP_IDLE;
  ep->xferCompleteCb = NULL;
  ep->fifoSize       = USB_EP0_SIZE / 4;

  totalTxFifoSize = ep->fifoSize * p->bufferingMultiplier[ 0 ];
  totalRxFifoSize = (ep->fifoSize + 1) * p->bufferingMultiplier[ 0 ];

#if defined( DEBUG_USB_API )
  /* Do a sanity check on the configuration descriptor */
  {
    int i;

    /* Check if bLength's adds up exactly to wTotalLength */
    i = 0;
    conf = (uint8_t*)dev->configDescriptor;
    confEnd = conf + dev->configDescriptor->wTotalLength;

    while ( conf < confEnd )
    {
      if ( *conf == 0 )
        break;

      i += *conf;
      conf += *conf;
    }

    if ( ( conf != confEnd                          ) ||
         ( i != dev->configDescriptor->wTotalLength )    )
    {
      DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal configuration descriptor" );
      EFM_ASSERT( false );
      return USB_STATUS_ILLEGAL;
    }
  }
#endif /* defined( DEBUG_USB_API ) */

  /* Parse configuration decriptor */
  numEps = 0;
  numInEps  = 0;
  numOutEps = 0;
  conf = (uint8_t*)dev->configDescriptor;
  confEnd = conf + dev->configDescriptor->wTotalLength;

  txFifoNum = 1;
  while ( conf < confEnd )
  {
    if ( *conf == 0 )
    {
      DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal configuration descriptor" );
      EFM_ASSERT( false );
      return USB_STATUS_ILLEGAL;
    }

    if ( *(conf + 1) == USB_ENDPOINT_DESCRIPTOR )
    {
      numEps++;
      epd = (USB_EndpointDescriptor_TypeDef*)conf;

      ep                 = &dev->ep[ numEps ];
      ep->in             = ( epd->bEndpointAddress & USB_SETUP_DIR_MASK ) != 0;
      ep->buf            = NULL;
      ep->addr           = epd->bEndpointAddress;
      ep->num            = ep->addr & USB_EPNUM_MASK;
      ep->mask           = 1 << ep->num;
      ep->type           = epd->bmAttributes & CONFIG_DESC_BM_TRANSFERTYPE;
      ep->packetSize     = epd->wMaxPacketSize;
      ep->remaining      = 0;
      ep->xferred        = 0;
      ep->state          = D_EP_IDLE;
      ep->xferCompleteCb = NULL;
      if ( ep->in )
      {
        numInEps++;
        ep->txFifoNum = txFifoNum++;
        ep->fifoSize = (ep->packetSize/4) * p->bufferingMultiplier[ numEps ];
        dev->inEpAddr2EpIndex[ ep->num ] = numEps;
        totalTxFifoSize += ep->fifoSize;
        if ( ep->num > MAX_NUM_IN_EPS )
        {
          DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal IN EP address" );
          EFM_ASSERT( false );
          return USB_STATUS_ILLEGAL;
        }
      }
      else
      {
        numOutEps++;
        ep->fifoSize = (ep->packetSize/4 + 1) * p->bufferingMultiplier[ numEps ];
        dev->outEpAddr2EpIndex[ ep->num ] = numEps;
        totalRxFifoSize += ep->fifoSize;
        if ( ep->num > MAX_NUM_OUT_EPS )
        {
          DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal OUT EP address" );
          EFM_ASSERT( false );
          return USB_STATUS_ILLEGAL;
        }
      }
    }
    conf += *conf;
  }

  /* Rx-FIFO size: SETUP packets : 4*n + 6    n=#CTRL EP's
   *               GOTNAK        : 1
   *               Status info   : 2*n        n=#OUT EP's (EP0 included) in HW
   */
  totalRxFifoSize += 10 + 1 + ( 2 * (MAX_NUM_OUT_EPS + 1) );

  if ( numEps != NUM_EP_USED )
  {
    DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal EP count" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

  if ( numInEps > MAX_NUM_IN_EPS )
  {
    DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal IN EP count" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

  if ( numOutEps > MAX_NUM_OUT_EPS )
  {
    DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal OUT EP count" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

  INT_Disable();

  /* Enable USB clock */
  CMU->HFCORECLKEN0 |= CMU_HFCORECLKEN0_USB | CMU_HFCORECLKEN0_USBC;
  CMU_ClockSelectSet( cmuClock_USBC, cmuSelect_HFCLK );

  USBHAL_DisableGlobalInt();

  if ( USBDHAL_CoreInit( totalRxFifoSize, totalTxFifoSize ) == USB_STATUS_OK )
  {
    USBDHAL_EnableUsbResetInt();
    USBHAL_EnableGlobalInt();
    NVIC_ClearPendingIRQ( USB_IRQn );
    NVIC_EnableIRQ( USB_IRQn );
  }
  else
  {
    INT_Enable();
    DEBUG_USB_API_PUTS( "\nUSBD_Init(), FIFO setup error" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF )
  if ( USBHAL_VbusIsOn() )
  {
    USBD_SetUsbState( USBD_STATE_POWERED );
  }
  else
#endif
  {
    USBD_SetUsbState( USBD_STATE_NONE );
  }

  INT_Enable();
  return USB_STATUS_OK;
}
/**************************************************************************//**
 * @brief vPortSetupTimerInterrupt
 * Override the default definition of vPortSuppressTicksAndSleep() that is weakly
 * defined in the FreeRTOS Cortex-M3 port layer layer
 *****************************************************************************/
void vPortSuppressTicksAndSleep(portTickType xExpectedIdleTime)
{
  unsigned long ulReloadValue, ulCompleteTickPeriods;
  portTickType  xModifiableIdleTime;
  /* Make sure the SysTick reload value does not overflow the counter. */
  if (xExpectedIdleTime > xMaximumPossibleSuppressedTicks)
  {
    xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
  }

  /* Calculate the reload value required to wait xExpectedIdleTime
   * tick periods.  -1 is used because this code will execute part way
   * through one of the tick periods, and the fraction of a tick period is
   * accounted for later. */
  ulReloadValue = (ulTimerReloadValueForOneTick * (xExpectedIdleTime ));
  if (ulReloadValue > ulStoppedTimerCompensation)
  {
    ulReloadValue -= ulStoppedTimerCompensation;
  }

  /* Stop the SysTick momentarily.  The time the SysTick is stopped for
   * is accounted for as best it can be, but using the tickless mode will
   * inevitably result in some tiny drift of the time maintained by the
   * kernel with respect to calendar time. */
  /* Stop the RTC clock*/
  BURTC_Enable(false);
  /* Enter a critical section but don't use the taskENTER_CRITICAL()
   * method as that will mask interrupts that should exit sleep mode. */
  INT_Disable();
  /* The tick flag is set to false before sleeping.  If it is true when sleep
   * mode is exited then sleep mode was probably exited because the tick was
   * suppressed for the entire xExpectedIdleTime period. */
  intTickFlag = false;
  /* If a context switch is pending or a task is waiting for the scheduler
   * to be unsuspended then abandon the low power entry. */
  if (eTaskConfirmSleepModeStatus() == eAbortSleep)
  {
    BURTC_Enable(true);
    /* Re-enable interrupts */
    INT_Enable();
  }
  else
  {
    /* Set the new reload value. */
    ulReloadValue -= BURTC_CounterGet();
    BURTC_CompareSet(0, ulReloadValue);
    /* Restart the counter*/
    BURTC_CounterReset();
    /* Sleep until something happens.  configPRE_SLEEP_PROCESSING() can
     * set its parameter to 0 to indicate that its implementation contains
     * its own wait for interrupt or wait for event instruction, and so wfi
     * should not be executed again.  However, the original expected idle
     * time variable must remain unmodified, so a copy is taken. */
    xModifiableIdleTime = xExpectedIdleTime;
    configPRE_SLEEP_PROCESSING(xModifiableIdleTime);
    if (xModifiableIdleTime > 0)
    {
      SLEEP_Sleep();
      __DSB();
      __ISB();
    }
    configPOST_SLEEP_PROCESSING(xExpectedIdleTime);
    /* Stop SysTick.  Again, the time the SysTick is stopped for is
     * accounted for as best it can be, but using the tickless mode will
     * inevitably result in some tiny drift of the time maintained by the
     * kernel with respect to calendar time. */
    BURTC_Enable(false);
    /* Re-enable interrupts - see comments above __disable_interrupt()
     * call above. */
    INT_Enable();
    if (intTickFlag != false)
    {
      /* The tick interrupt has already executed,
       * Reset the alarm value with whatever remains of this tick period. */
      BURTC_CompareSet(0, TIMER_CAPACITY & (ulTimerReloadValueForOneTick - BURTC_CounterGet()));
      /* The tick interrupt handler will already have pended the tick
       * processing in the kernel.  As the pending tick will be
       * processed as soon as this function exits, the tick value
       * maintained by the tick is stepped forward by one less than the
       * time spent waiting. */
      ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
    }
    else
    {
      /* Some other interrupt than system tick ended the sleep.
       * Calculate how many tick periods passed while the processor
       * was waiting */
      ulCompleteTickPeriods = BURTC_CounterGet() / ulTimerReloadValueForOneTick;

      /* The reload value is set to whatever fraction of a single tick
       * period remains. */
      if (ulCompleteTickPeriods == 0)
      {
        ulReloadValue = ulTimerReloadValueForOneTick - BURTC_CounterGet();
      }
      else
      {
        ulReloadValue = BURTC_CounterGet() - (ulCompleteTickPeriods * ulTimerReloadValueForOneTick);
      }
      BURTC_CompareSet(0, ulReloadValue);
    }
    /* Restart the RTCounter*/
    BURTC_CounterReset();
    /* The tick forward by the number of tick periods that
     * remained in a low power state. */
    vTaskStepTick(ulCompleteTickPeriods);
  }
}
Esempio n. 26
0
void RTCC_IRQHandler(void)
#endif
{
  uint32_t flags, timeElapsed, cnt, timeToNextTimerCompletion;

  INT_Disable();

  // CNT will normally be COMP0+1 at this point,
  // unless IRQ latency exceeded one tick period.

  flags = RTC_INTGET();

  if ( flags & RTC_COMP_INT ) {

    // Stop timer system by disabling the compare IRQ.
    // Update all timers with the time elapsed, call callbacks if needed,
    // then find the timer with the shortest timeout (if any at all) and
    // reenable the compare IRQ if needed.

    inTimerIRQ = true;

    cnt = RTC_COUNTERGET();

    // This loop is repeated if CNT is incremented while processing.
    do {

      RTC_INTDISABLE( RTC_COMP_INT );

      timeElapsed = TIMEDIFF( cnt, lastStart );

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

      // Execute timer callbacks.
      executeTimerCallbacks();

      // 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));
    inTimerIRQ = false;
  }

#if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
  if ( flags & RTC_OF_INT ) {
    uint64_t ticks;

    RTC_INTCLEAR( RTC_OF_INT );

    ticks             = MAX_RTC_TICK_CNT - wallClockInitTime;
    wallClockInitTime = 0;
    wallClockTime    += TICKS_TO_SEC( ticks );
  }
#endif

  INT_Enable();
}
Esempio n. 27
0
/*
 * USB_IRQHandler() is the first level handler for the USB peripheral interrupt.
 */
void USB_IRQHandler( void )
{
  uint32_t status;
  bool servedVbusInterrupt = false;

  INT_Disable();

#if ( USB_PWRSAVE_MODE )
  if ( USBD_poweredDown )
  {
    /* Switch USBC clock from 32kHz to a 48MHz clock to be able to  */
    /* read USB peripheral registers.                               */
    /* If we woke up from EM2, HFCLK is now HFRCO.                  */

    /* Restore clock oscillators.*/
#if defined( CMU_OSCENCMD_USHFRCOEN )
    if ( ( CMU->STATUS & CMU_STATUS_USHFRCOENS ) == 0 )/*Wakeup from EM2 ?*/
    {
      CMU->OSCENCMD = ( cmuStatus
                        & ( CMU_STATUS_AUXHFRCOENS | CMU_STATUS_HFXOENS ) )
                      | CMU_OSCENCMD_USHFRCOEN;
    }
#else
    if ( ( CMU->STATUS & CMU_STATUS_HFXOENS ) == 0 ) /* Wakeup from EM2 ? */
    {
      CMU->OSCENCMD = cmuStatus
                      & ( CMU_STATUS_AUXHFRCOENS | CMU_STATUS_HFXOENS );
    }
#endif

    /* Select correct USBC clock.*/
#if defined( CMU_OSCENCMD_USHFRCOEN )
    CMU->CMD = CMU_CMD_USBCCLKSEL_USHFRCO;
    while ( ( CMU->STATUS & CMU_STATUS_USBCUSHFRCOSEL ) == 0 ){}
#else
    CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV;
    while ( ( CMU->STATUS & CMU_STATUS_USBCHFCLKSEL ) == 0 ){}
#endif
  }
#endif /* if ( USB_PWRSAVE_MODE ) */

  if ( USB->IF && ( USB->CTRL & USB_CTRL_VREGOSEN ) )
  {
    if ( USB->IF & USB_IF_VREGOSH )
    {
      USB->IFC = USB_IFC_VREGOSH;

      if ( USB->STATUS & USB_STATUS_VREGOS )
      {
        servedVbusInterrupt = true;
        DEBUG_USB_INT_LO_PUTS( "\nVboN" );

#if ( USB_PWRSAVE_MODE )
        if ( UsbPowerUp() )
        {
          USBDHAL_EnableUsbResetAndSuspendInt();
        }
        USBD_SetUsbState( USBD_STATE_POWERED );
#endif
      }
    }

    if ( USB->IF & USB_IF_VREGOSL )
    {
      USB->IFC = USB_IFC_VREGOSL;

      if ( ( USB->STATUS & USB_STATUS_VREGOS ) == 0 )
      {
        servedVbusInterrupt = true;
        DEBUG_USB_INT_LO_PUTS( "\nVboF" );

#if ( USB_PWRSAVE_MODE )
#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF )
        if ( !USBD_poweredDown )
        {
          USB->GINTMSK = 0;
          USB->GINTSTS = 0xFFFFFFFF;
        }

        UsbPowerDown();
#endif
        USBD_SetUsbState( USBD_STATE_NONE );
#endif
      }
    }
  }

  status = USBHAL_GetCoreInts();
  if ( status == 0 )
  {
    INT_Enable();
    if ( !servedVbusInterrupt )
    {
      DEBUG_USB_INT_LO_PUTS( "\nSinT" );
    }
    return;
  }

  HANDLE_INT( USB_GINTSTS_RESETDET   )
  HANDLE_INT( USB_GINTSTS_WKUPINT    )
  HANDLE_INT( USB_GINTSTS_USBSUSP    )
  HANDLE_INT( USB_GINTSTS_SOF        )
  HANDLE_INT( USB_GINTSTS_ENUMDONE   )
  HANDLE_INT( USB_GINTSTS_USBRST     )
  HANDLE_INT( USB_GINTSTS_IEPINT     )
  HANDLE_INT( USB_GINTSTS_OEPINT     )

  INT_Enable();

  if ( status != 0 )
  {
    DEBUG_USB_INT_LO_PUTS( "\nUinT" );
  }
}
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCountAfterSleep;
eSleepModeStatus eSleepAction;
TickType_t xModifiableIdleTime;

	/* THIS FUNCTION IS CALLED WITH THE SCHEDULER SUSPENDED. */

	/* Make sure the RTC reload value does not overflow the counter. */
	if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
	{
		xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
	}

	/* Calculate the reload value required to wait xExpectedIdleTime tick
	periods. */
	ulReloadValue = ulReloadValueForOneTick * xExpectedIdleTime;
	if( ulReloadValue > ulStoppedTimerCompensation )
	{
		/* Compensate for the fact that the RTC is going to be stopped
		momentarily. */
		ulReloadValue -= ulStoppedTimerCompensation;
	}

	/* Stop the RTC momentarily.  The time the RTC is stopped for is accounted
	for as best it can be, but using the tickless mode will inevitably result
	in some tiny drift of the time maintained by the kernel with respect to
	calendar time. */
	RTCC_Enable( false );

	/* Enter a critical section but don't use the taskENTER_CRITICAL() method as
	that will mask interrupts that should exit sleep mode. */
	INT_Disable();
	__asm volatile( "dsb" );
	__asm volatile( "isb" );

	/* The tick flag is set to false before sleeping.  If it is true when sleep
	mode is exited then sleep mode was probably exited because the tick was
	suppressed for the entire xExpectedIdleTime period. */
	ulTickFlag = pdFALSE;

	/* If a context switch is pending then abandon the low power entry as the
	context switch might have been pended by an external interrupt that	requires
	processing. */
	eSleepAction = eTaskConfirmSleepModeStatus();
	if( eSleepAction == eAbortSleep )
	{
		/* Restart tick and continue counting to complete the current time
		slice. */
		RTCC_Enable( true );

		/* Re-enable interrupts - see comments above the RTCC_Enable() call
		above. */
		INT_Enable();
	}
	else
	{
		RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValue );

		/* Restart the RTC. */
		RTCC_Enable( true );

		/* Allow the application to define some pre-sleep processing. */
		xModifiableIdleTime = xExpectedIdleTime;
		configPRE_SLEEP_PROCESSING( xModifiableIdleTime );

		/* xExpectedIdleTime being set to 0 by configPRE_SLEEP_PROCESSING()
		means the application defined code has already executed the WAIT
		instruction. */
		if( xModifiableIdleTime > 0 )
		{
			__asm volatile( "dsb" );
			SLEEP_Sleep();
			__asm volatile( "isb" );
		}

		/* Allow the application to define some post sleep processing. */
		configPOST_SLEEP_PROCESSING( xModifiableIdleTime );

		/* Stop RTC.  Again, the time the SysTick is stopped for is accounted
		for as best it can be, but using the tickless mode will	inevitably
		result in some tiny drift of the time maintained by the	kernel with
		respect to calendar time. */
		RTCC_Enable( false );
		ulCountAfterSleep = RTCC_CounterGet();

		/* Re-enable interrupts - see comments above the INT_Enable() call
		above. */
		INT_Enable();
		__asm volatile( "dsb" );
		__asm volatile( "isb" );

		if( ulTickFlag != pdFALSE )
		{
			/* The tick interrupt has already executed, although because this
			function is called with the scheduler suspended the actual tick
			processing will not occur until after this function has exited.
			The tick interrupt handler will already have pended the tick
			processing in the kernel.  As the pending tick will be processed as
			soon as this function exits, the tick value	maintained by the tick
			is stepped forward by one less than the	time spent sleeping.  The
			actual stepping of the tick appears later in this function. */
			ulCompleteTickPeriods = xExpectedIdleTime - 1UL;

			/* The interrupt should have reset the CCV value. */
			configASSERT( RTCC_ChannelCCVGet( lpRTCC_CHANNEL ) == ulReloadValueForOneTick );
		}
		else
		{
			/* Something other than the tick interrupt ended the sleep.  How
			many complete tick periods passed while the processor was
			sleeping? */
			ulCompleteTickPeriods = ulCountAfterSleep / ulReloadValueForOneTick;

			/* The next interrupt is configured to occur at whatever fraction of
			the current tick period remains by setting the reload value back to
			that required for one tick, and truncating the count to remove the
			counts that are greater than the reload value. */
			RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValueForOneTick );
			ulCountAfterSleep %= ulReloadValueForOneTick;
			RTCC_CounterSet( ulCountAfterSleep );
		}

		/* Restart the RTC so it runs up to the alarm value.  The alarm value
		will get set to the value required to generate exactly one tick period
		the next time the RTC interrupt executes. */
		RTCC_Enable( true );

		/* Wind the tick forward by the number of tick periods that the CPU
		remained in a low power state. */
		vTaskStepTick( ulCompleteTickPeriods );
	}
void start_atomic()
{
	INT_Disable();
}
Esempio n. 30
0
/** Block the microcontroller from sleeping below a certain mode
 *
 * This will block sleep() from entering an energy mode below the one given.
 * -- To be called by peripheral HAL's --
 *
 * After the peripheral is finished with the operation, it should call unblock with the same state
 *
 */
void blockSleepMode(sleepstate_enum minimumMode)
{
    INT_Disable();
    sleep_block_counter[minimumMode]++;
    INT_Enable();
}