text: /***************************************************************************//**
   * @file 	board.c
   * @brief 	Board support of RT-Thread RTOS for EFM32
   *  COPYRIGHT (C) 2012, RT-Thread Development Team
   * @author 	onelife
   * @version 1.0
   *******************************************************************************
   * @section License
   * The license and distribution terms for this file may be found in the file
   * LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
   *******************************************************************************
   * @section Change Logs
   * Date			Author		Notes
   * 2010-12-21	onelife		Initial creation for EFM32
   * 2011-05-06	onelife		Add EFM32 development kit and SPI Flash support
   * 2011-07-12	onelife		Add SWO output enable function
   * 2011-12-08	onelife		Add giant gecko development kit support
   * 2011-12-09	onelife		Add giant gecko support
   * 2011-12-09   onelife     Add LEUART module support
   * 2011-12-14   onelife     Add LFXO enabling routine in driver initialization
   *  function
   * 2011-12-15   onelife     Add MicroSD initialization routine in driver
   *  initialization function
   * 2011-12-29   onelife     Add keys and joystick initialization routine in
   *  driver initialization function
   * 2012-02-15   onelife     Modify SWO setup function to support giant gecko
   * 2012-xx-xx   onelife     Modify system clock and ticket related code
   ******************************************************************************/
  
  /***************************************************************************//**
   * @addtogroup efm32
   * @{
   ******************************************************************************/
  
  /* Includes ------------------------------------------------------------------*/
  #include "board.h"
  
  /* Private typedef -----------------------------------------------------------*/
  /* Private define ------------------------------------------------------------*/
  #define IS_NVIC_VECTTAB(VECTTAB) 		(((VECTTAB) == RAM_MEM_BASE) || \
  										((VECTTAB) == FLASH_MEM_BASE))
  #define IS_NVIC_OFFSET(OFFSET) 			((OFFSET) < 0x000FFFFF)
  
  /***************************************************************************//**
   * @addtogroup SysTick_clock_source
   * @{
   ******************************************************************************/
  #define SysTick_CLKSource_MASK          ((rt_uint32_t)0x00000004)
  #define SysTick_CLKSource_RTC		    ((rt_uint32_t)0x00000000)
  #define SysTick_CLKSource_HFCORECLK		((rt_uint32_t)0x00000004)
  #define IS_SYSTICK_CLK_SOURCE(SOURCE)	(((SOURCE) == SysTick_CLKSource_RTC) || \
  										((SOURCE) == SysTick_CLKSource_HFCORECLK))
  /***************************************************************************//**
   * @}
   ******************************************************************************/
  
  /* Private macro -------------------------------------------------------------*/
  /* Private variables ---------------------------------------------------------*/
  /* Private function prototypes -----------------------------------------------*/
  /* Private functions ---------------------------------------------------------*/
  /***************************************************************************//**
   * @brief
   *   Set the allocation and offset of the vector table
   *
   * @details
   *
   * @note
   *
   * @param[in] NVIC_VectTab
   *	 Indicate the vector table is allocated in RAM or ROM
   *
   * @param[in] Offset
   *   The vector table offset
   ******************************************************************************/
  static void NVIC_SetVectorTable(
  	rt_uint32_t NVIC_VectTab,
  	rt_uint32_t Offset)
  {
  	/* Check the parameters */
  	RT_ASSERT(IS_NVIC_VECTTAB(NVIC_VectTab));
  	RT_ASSERT(IS_NVIC_OFFSET(Offset));
  
  	SCB->VTOR = NVIC_VectTab | (Offset & (rt_uint32_t)0x1FFFFF80);
  }
  
  /***************************************************************************//**
   * @brief
   *   Configure the address of vector table
   *
   * @details
   *
   * @note
   *
   ******************************************************************************/
  static void NVIC_Configuration(void)
  {
  #ifdef  VECT_TAB_RAM
  	/* Set the vector table allocated at 0x20000000 */
  	NVIC_SetVectorTable(RAM_MEM_BASE, 0x0);
  #else  /* VECT_TAB_FLASH  */
  	/* Set the vector table allocated at 0x00000000 */
  	NVIC_SetVectorTable(FLASH_MEM_BASE, 0x0);
  #endif
  
  	/* Set NVIC Preemption Priority Bits: 0 bit for pre-emption, 4 bits for
  	   subpriority */
  	NVIC_SetPriorityGrouping(0x7UL);
  
  	/* Set Base Priority Mask Register */
  	__set_BASEPRI(EFM32_BASE_PRI_DEFAULT);
  }
  
  /***************************************************************************//**
   * @brief
   *   Configure the SysTick clock source
   *
   * @details
   *
   * @note
   *
   * @param[in] SysTick_CLKSource
   *	 Specifies the SysTick clock source.
   *
   * @arg SysTick_CLKSource_HCLK_Div8
   * 	 AHB clock divided by 8 selected as SysTick clock source.
   *
   * @arg SysTick_CLKSource_HCLK
   *	 AHB clock selected as SysTick clock source.
   ******************************************************************************/
  static void SysTick_CLKSourceConfig(rt_uint32_t SysTick_CLKSource)
  {
      /* Check the parameters */
      RT_ASSERT(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
  
      rt_uint32_t ctrl = SysTick->CTRL;
  
      ctrl &= ~SysTick_CLKSource_MASK;
      ctrl |= SysTick_CLKSource;
  
      SysTick->CTRL = ctrl;
  }
  
  /***************************************************************************//**
   * @brief
   *   Configure the SysTick for OS tick.
   *
   * @details
   *
   * @note
   *
   ******************************************************************************/
  static void  SysTick_Configuration(void)
  {
  #if defined(EFM32_USING_LFXO)
      /* LETIMER0 configurations */
      const LETIMER_Init_TypeDef letimerInit =
      {
          .enable         = true,                 /* Start counting when init completed. */
          .debugRun       = false,                /* Counter shall not keep running during debug halt. */
          .rtcComp0Enable = false,                /* Don't start counting on RTC COMP0 match. */
          .rtcComp1Enable = false,                /* Don't start counting on RTC COMP1 match. */
          .comp0Top       = true,                 /* Load COMP0 register into CNT when counter underflows. COMP is used as TOP */
          .bufTop         = false,                /* Don't load COMP1 into COMP0 when REP0 reaches 0. */
          .out0Pol        = 0,                    /* Idle value for output 0. */
          .out1Pol        = 0,                    /* Idle value for output 1. */
          .ufoa0          = letimerUFOANone,      /* No output on output 0. */
          .ufoa1          = letimerUFOANone,      /* No output on output 1. */
          .repMode        = letimerRepeatFree     /* Count until stopped by SW. */
      };
  
      CMU_ClockDivSet(cmuClock_LETIMER0, cmuClkDiv_8);
      CMU_ClockEnable(cmuClock_LETIMER0, true);
      LETIMER_CompareSet(LETIMER0, 0,
          EFM32_LETIMER_TOP_100HZ * RT_TICK_PER_SECOND / 100);
  
      /* Enable underflow interrupt */
      LETIMER_IntClear(LETIMER0, LETIMER_IF_UF);
      LETIMER_IntEnable(LETIMER0, LETIMER_IF_UF);
      /* Enable LETIMER0 interrupt vector in NVIC */
      NVIC_ClearPendingIRQ(LETIMER0_IRQn);
      NVIC_SetPriority(LETIMER0_IRQn, EFM32_IRQ_PRI_DEFAULT);
      NVIC_EnableIRQ(LETIMER0_IRQn);
  
      /* Start LETIMER0 */
      LETIMER_Init(LETIMER0, &letimerInit);
  #else
  	rt_uint32_t 	coreClk;
  	rt_uint32_t 	cnts;
  
  	coreClk = SystemCoreClockGet();
  	cnts = coreClk / RT_TICK_PER_SECOND;
  
  	SysTick_Config(cnts);
  	SysTick_CLKSourceConfig(SysTick_CLKSource_HFCORECLK);
  #endif
  }
  
  /***************************************************************************//**
   * @brief
   *   Enable SWO.
   *
   * @details
   *
   * @note
   *
   ******************************************************************************/
  void Swo_Configuration(void)
  {
  	rt_uint32_t *dwt_ctrl = (rt_uint32_t *) 0xE0001000;
  	rt_uint32_t *tpiu_prescaler = (rt_uint32_t *) 0xE0040010;
  	rt_uint32_t *tpiu_protocol = (rt_uint32_t *) 0xE00400F0;
  
      CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_GPIO;
      /* Enable Serial wire output pin */
      GPIO->ROUTE |= GPIO_ROUTE_SWOPEN;
  #if defined(_EFM32_GIANT_FAMILY)
      /* Set location 0 */
      GPIO->ROUTE = (GPIO->ROUTE & ~(_GPIO_ROUTE_SWLOCATION_MASK)) | GPIO_ROUTE_SWLOCATION_LOC0;
  
      /* Enable output on pin - GPIO Port F, Pin 2 */
      GPIO->P[5].MODEL &= ~(_GPIO_P_MODEL_MODE2_MASK);
      GPIO->P[5].MODEL |= GPIO_P_MODEL_MODE2_PUSHPULL;
      #else
      /* Set location 1 */
      GPIO->ROUTE = (GPIO->ROUTE & ~(_GPIO_ROUTE_SWLOCATION_MASK)) | GPIO_ROUTE_SWLOCATION_LOC1;
      /* Enable output on pin */
      GPIO->P[2].MODEH &= ~(_GPIO_P_MODEH_MODE15_MASK);
      GPIO->P[2].MODEH |= GPIO_P_MODEH_MODE15_PUSHPULL;
  #endif
      /* Enable debug clock AUXHFRCO */
      CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCOEN;
  
      while(!(CMU->STATUS & CMU_STATUS_AUXHFRCORDY));
  
      /* Enable trace in core debug */
      CoreDebug->DHCSR |= 1;
      CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
  
      /* Enable PC and IRQ sampling output */
      *dwt_ctrl = 0x400113FF;
      /* Set TPIU prescaler to 16. */
      *tpiu_prescaler = 0xf;
      /* Set protocol to NRZ */
      *tpiu_protocol = 2;
      /* Unlock ITM and output data */
      ITM->LAR = 0xC5ACCE55;
      ITM->TCR = 0x10009;
  }
  
  /***************************************************************************//**
   * @brief
   *   Initialize the board.
   *
   * @details
   *
   * @note
   *
   ******************************************************************************/
  void rt_hw_board_init(void)
  {
  	/* Chip errata */
  	CHIP_Init();
  
      /* Initialize DVK board register access */
  #if defined(EFM32_GXXX_DK)
  	DVK_init();
  #elif defined(EFM32GG_DK3750)
      DVK_init(DVK_Init_EBI);
  
      /* Disable all DVK interrupts */
      DVK_disableInterrupt(BC_INTEN_MASK);
      DVK_clearInterruptFlags(BC_INTFLAG_MASK);
  #endif
  
  	/* config NVIC Configuration */
  	NVIC_Configuration();
  
  #if defined(EFM32_USING_HFXO)
  	/* Configure external oscillator */
  	SystemHFXOClockSet(EFM32_HFXO_FREQUENCY);
  
      /* Switching the CPU clock source to HFXO */
      CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO);
  
      /* Turning off the high frequency RC Oscillator (HFRCO) */
      CMU_OscillatorEnable(cmuOsc_HFRCO, false, false);
  #endif
  
  #if defined(EFM32_USING_LFXO)
      CMU_ClockSelectSet(cmuClock_LFA,cmuSelect_LFXO);
      CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO);
  #endif
  
  #if defined(EFM32_SWO_ENABLE)
      /* Enable SWO */
  	Swo_Configuration();
  #endif
  
  	/* Enable high frequency peripheral clock */
  	CMU_ClockEnable(cmuClock_HFPER, true);
  	/* Enabling clock to the interface of the low energy modules */
  	CMU_ClockEnable(cmuClock_CORELE, true);
      /* Enable GPIO clock */
  	CMU_ClockEnable(cmuClock_GPIO, true);
  
      /* Configure the SysTick */
      SysTick_Configuration();
  }
  
  /***************************************************************************//**
   * @brief
   *   Initialize the hardware drivers.
   *
   * @details
   *
   * @note
   *
   ******************************************************************************/
  void rt_hw_driver_init(void)
  {
  	/* Initialize DMA */
  	rt_hw_dma_init();
  
      /* Select LFXO for specified module (and wait for it to stabilize) */
  #if (!defined(EFM32_USING_LFXO) && defined(RT_USING_RTC))
  #error "Low frequency clock source is needed for using RTC"
  #endif
  
  #if (!defined(EFM32_USING_LFXO )&& \
      (defined(RT_USING_LEUART0) || defined(RT_USING_LEUART1)))
  #error "Low frequency clock source is needed for using LEUART"
  #endif
  
  	/* Initialize USART */
  #if (defined(RT_USING_USART0) || defined(RT_USING_USART1) || \
      defined(RT_USING_USART2) || defined(RT_USING_UART0) || \
      defined(RT_USING_UART1))
  	rt_hw_usart_init();
  #endif
  
      /* Initialize LEUART */
  #if (defined(RT_USING_LEUART0) || defined(RT_USING_LEUART1))
      rt_hw_leuart_init();
  #endif
  
  	/* Setup Console */
  #if defined(EFM32_GXXX_DK)
      DVK_enablePeripheral(DVK_RS232A);
      DVK_enablePeripheral(DVK_SPI);
  #elif defined(EFM32GG_DK3750)
   #if (RT_CONSOLE_DEVICE == EFM_UART1)
      DVK_enablePeripheral(DVK_RS232_UART);
   #elif (RT_CONSOLE_DEVICE == EFM_LEUART1)
      DVK_enablePeripheral(DVK_RS232_LEUART);
   #endif
  #endif
  	rt_console_set_device(CONSOLE_DEVICE);
  
  	/* Initialize Timer */
  #if (defined(RT_USING_TIMER0) || defined(RT_USING_TIMER1) || defined(RT_USING_TIMER2))
  	rt_hw_timer_init();
  #endif
  
  	/* Initialize ADC */
  #if defined(RT_USING_ADC0)
  	rt_hw_adc_init();
  #endif
  
  	/* Initialize ACMP */
  #if (defined(RT_USING_ACMP0) || defined(RT_USING_ACMP1))
  	rt_hw_acmp_init();
  #endif
  
  	/* Initialize IIC */
  #if (defined(RT_USING_IIC0) || defined(RT_USING_IIC1))
  	rt_hw_iic_init();
  #endif
  
  	/* Initialize RTC */
  #if defined(RT_USING_RTC)
  	rt_hw_rtc_init();
  #endif
  
      /* Enable SPI access to MicroSD card */
  #if defined(EFM32_USING_SPISD)
   #if defined(EFM32_GXXX_DK)
      DVK_writeRegister(BC_SPI_CFG, 1);
   #elif defined(EFM32GG_DK3750)
      DVK_enablePeripheral(DVK_MICROSD);
   #endif
  #endif
  
      /* Enable SPI access to Ethernet */
  #if defined(EFM32_USING_ETHERNET)
   #if defined(EFM32GG_DK3750)
      DVK_enablePeripheral(DVK_ETH);
   #endif
  #endif
  
      /* Initialize LCD */
  #if defined(EFM32_USING_LCD)
      efm32_spiLcd_init();
  #endif
  
      /* Initialize Keys */
  #if defined(EFM32_USING_KEYS)
   #if defined(EFM32GG_DK3750)
      efm32_hw_keys_init();
   #endif
  #endif
  
  }
  
  /***************************************************************************//**
   * @}
   ******************************************************************************/
  