1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date         Author      Notes
8  * 2010-12-21   onelife     Initial creation for EFM32
9  * 2011-05-06   onelife     Add EFM32 development kit and SPI Flash support
10  * 2011-07-12   onelife     Add SWO output enable function
11  * 2011-12-08   onelife     Add giant gecko development kit support
12  * 2011-12-09   onelife     Add giant gecko support
13  * 2011-12-09   onelife     Add LEUART module support
14  * 2011-12-14   onelife     Add LFXO enabling routine in driver initialization function
15  * 2011-12-15   onelife     Add MicroSD initialization routine in driver
16  *                          initialization function
17  * 2011-12-29   onelife     Add keys and joystick initialization routine in
18  *                          driver initialization function
19  * 2012-02-15   onelife     Modify SWO setup function to support giant gecko
20  * 2012-xx-xx   onelife     Modify system clock and ticket related code
21  */
22 
23 /***************************************************************************//**
24  * @addtogroup efm32
25  * @{
26  ******************************************************************************/
27 
28 /* Includes ------------------------------------------------------------------*/
29 #include "board.h"
30 
31 /* Private typedef -----------------------------------------------------------*/
32 /* Private define ------------------------------------------------------------*/
33 #define IS_NVIC_VECTTAB(VECTTAB)        (((VECTTAB) == RAM_MEM_BASE) || \
34                                         ((VECTTAB) == FLASH_MEM_BASE))
35 #define IS_NVIC_OFFSET(OFFSET)          ((OFFSET) < 0x000FFFFF)
36 
37 /***************************************************************************//**
38  * @addtogroup SysTick_clock_source
39  * @{
40  ******************************************************************************/
41 #define SysTick_CLKSource_MASK          ((rt_uint32_t)0x00000004)
42 #define SysTick_CLKSource_RTC           ((rt_uint32_t)0x00000000)
43 #define SysTick_CLKSource_HFCORECLK     ((rt_uint32_t)0x00000004)
44 #define IS_SYSTICK_CLK_SOURCE(SOURCE)   (((SOURCE) == SysTick_CLKSource_RTC) || \
45                                         ((SOURCE) == SysTick_CLKSource_HFCORECLK))
46 /***************************************************************************//**
47  * @}
48  ******************************************************************************/
49 
50 /* Private macro -------------------------------------------------------------*/
51 /* Private variables ---------------------------------------------------------*/
52 /* Private function prototypes -----------------------------------------------*/
53 /* Private functions ---------------------------------------------------------*/
54 /***************************************************************************//**
55  * @brief
56  *   Set the allocation and offset of the vector table
57  *
58  * @details
59  *
60  * @note
61  *
62  * @param[in] NVIC_VectTab
63  *   Indicate the vector table is allocated in RAM or ROM
64  *
65  * @param[in] Offset
66  *   The vector table offset
67  ******************************************************************************/
NVIC_SetVectorTable(rt_uint32_t NVIC_VectTab,rt_uint32_t Offset)68 static void NVIC_SetVectorTable(
69     rt_uint32_t NVIC_VectTab,
70     rt_uint32_t Offset)
71 {
72     /* Check the parameters */
73     RT_ASSERT(IS_NVIC_VECTTAB(NVIC_VectTab));
74     RT_ASSERT(IS_NVIC_OFFSET(Offset));
75 
76     SCB->VTOR = NVIC_VectTab | (Offset & (rt_uint32_t)0x1FFFFF80);
77 }
78 
79 /***************************************************************************//**
80  * @brief
81  *   Configure the address of vector table
82  *
83  * @details
84  *
85  * @note
86  *
87  ******************************************************************************/
NVIC_Configuration(void)88 static void NVIC_Configuration(void)
89 {
90 #ifdef  VECT_TAB_RAM
91     /* Set the vector table allocated at 0x20000000 */
92     NVIC_SetVectorTable(RAM_MEM_BASE, 0x0);
93 #else  /* VECT_TAB_FLASH  */
94     /* Set the vector table allocated at 0x00000000 */
95     NVIC_SetVectorTable(FLASH_MEM_BASE, 0x0);
96 #endif
97 
98     /* Set NVIC Preemption Priority Bits: 0 bit for pre-emption, 4 bits for
99        subpriority */
100     NVIC_SetPriorityGrouping(0x7UL);
101 
102     /* Set Base Priority Mask Register */
103     __set_BASEPRI(EFM32_BASE_PRI_DEFAULT);
104 }
105 
106 /***************************************************************************//**
107  * @brief
108  *   Configure the SysTick clock source
109  *
110  * @details
111  *
112  * @note
113  *
114  * @param[in] SysTick_CLKSource
115  *   Specifies the SysTick clock source.
116  *
117  * @arg SysTick_CLKSource_HCLK_Div8
118  *   AHB clock divided by 8 selected as SysTick clock source.
119  *
120  * @arg SysTick_CLKSource_HCLK
121  *   AHB clock selected as SysTick clock source.
122  ******************************************************************************/
SysTick_CLKSourceConfig(rt_uint32_t SysTick_CLKSource)123 static void SysTick_CLKSourceConfig(rt_uint32_t SysTick_CLKSource)
124 {
125     /* Check the parameters */
126     RT_ASSERT(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
127 
128     rt_uint32_t ctrl = SysTick->CTRL;
129 
130     ctrl &= ~SysTick_CLKSource_MASK;
131     ctrl |= SysTick_CLKSource;
132 
133     SysTick->CTRL = ctrl;
134 }
135 
136 /***************************************************************************//**
137  * @brief
138  *   Configure the SysTick for OS tick.
139  *
140  * @details
141  *
142  * @note
143  *
144  ******************************************************************************/
SysTick_Configuration(void)145 static void  SysTick_Configuration(void)
146 {
147 #if defined(EFM32_USING_LFXO)
148     /* LETIMER0 configurations */
149     const LETIMER_Init_TypeDef letimerInit =
150     {
151         .enable         = true,                 /* Start counting when init completed. */
152         .debugRun       = false,                /* Counter shall not keep running during debug halt. */
153         .rtcComp0Enable = false,                /* Don't start counting on RTC COMP0 match. */
154         .rtcComp1Enable = false,                /* Don't start counting on RTC COMP1 match. */
155         .comp0Top       = true,                 /* Load COMP0 register into CNT when counter underflows. COMP is used as TOP */
156         .bufTop         = false,                /* Don't load COMP1 into COMP0 when REP0 reaches 0. */
157         .out0Pol        = 0,                    /* Idle value for output 0. */
158         .out1Pol        = 0,                    /* Idle value for output 1. */
159         .ufoa0          = letimerUFOANone,      /* No output on output 0. */
160         .ufoa1          = letimerUFOANone,      /* No output on output 1. */
161         .repMode        = letimerRepeatFree     /* Count until stopped by SW. */
162     };
163 
164     CMU_ClockDivSet(cmuClock_LETIMER0, cmuClkDiv_8);
165     CMU_ClockEnable(cmuClock_LETIMER0, true);
166     LETIMER_CompareSet(LETIMER0, 0,
167         EFM32_LETIMER_TOP_100HZ * RT_TICK_PER_SECOND / 100);
168 
169     /* Enable underflow interrupt */
170     LETIMER_IntClear(LETIMER0, LETIMER_IF_UF);
171     LETIMER_IntEnable(LETIMER0, LETIMER_IF_UF);
172     /* Enable LETIMER0 interrupt vector in NVIC */
173     NVIC_ClearPendingIRQ(LETIMER0_IRQn);
174     NVIC_SetPriority(LETIMER0_IRQn, EFM32_IRQ_PRI_DEFAULT);
175     NVIC_EnableIRQ(LETIMER0_IRQn);
176 
177     /* Start LETIMER0 */
178     LETIMER_Init(LETIMER0, &letimerInit);
179 #else
180     rt_uint32_t     coreClk;
181     rt_uint32_t     cnts;
182 
183     coreClk = SystemCoreClockGet();
184     cnts = coreClk / RT_TICK_PER_SECOND;
185 
186     SysTick_Config(cnts);
187     SysTick_CLKSourceConfig(SysTick_CLKSource_HFCORECLK);
188 #endif
189 }
190 
191 /***************************************************************************//**
192  * @brief
193  *   Enable SWO.
194  *
195  * @details
196  *
197  * @note
198  *
199  ******************************************************************************/
Swo_Configuration(void)200 void Swo_Configuration(void)
201 {
202     rt_uint32_t *dwt_ctrl = (rt_uint32_t *) 0xE0001000;
203     rt_uint32_t *tpiu_prescaler = (rt_uint32_t *) 0xE0040010;
204     rt_uint32_t *tpiu_protocol = (rt_uint32_t *) 0xE00400F0;
205 
206     CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_GPIO;
207     /* Enable Serial wire output pin */
208     GPIO->ROUTE |= GPIO_ROUTE_SWOPEN;
209 #if defined(_EFM32_GIANT_FAMILY)
210     /* Set location 0 */
211     GPIO->ROUTE = (GPIO->ROUTE & ~(_GPIO_ROUTE_SWLOCATION_MASK)) | GPIO_ROUTE_SWLOCATION_LOC0;
212 
213     /* Enable output on pin - GPIO Port F, Pin 2 */
214     GPIO->P[5].MODEL &= ~(_GPIO_P_MODEL_MODE2_MASK);
215     GPIO->P[5].MODEL |= GPIO_P_MODEL_MODE2_PUSHPULL;
216     #else
217     /* Set location 1 */
218     GPIO->ROUTE = (GPIO->ROUTE & ~(_GPIO_ROUTE_SWLOCATION_MASK)) | GPIO_ROUTE_SWLOCATION_LOC1;
219     /* Enable output on pin */
220     GPIO->P[2].MODEH &= ~(_GPIO_P_MODEH_MODE15_MASK);
221     GPIO->P[2].MODEH |= GPIO_P_MODEH_MODE15_PUSHPULL;
222 #endif
223     /* Enable debug clock AUXHFRCO */
224     CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCOEN;
225 
226     while(!(CMU->STATUS & CMU_STATUS_AUXHFRCORDY));
227 
228     /* Enable trace in core debug */
229     CoreDebug->DHCSR |= 1;
230     CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
231 
232     /* Enable PC and IRQ sampling output */
233     *dwt_ctrl = 0x400113FF;
234     /* Set TPIU prescaler to 16. */
235     *tpiu_prescaler = 0xf;
236     /* Set protocol to NRZ */
237     *tpiu_protocol = 2;
238     /* Unlock ITM and output data */
239     ITM->LAR = 0xC5ACCE55;
240     ITM->TCR = 0x10009;
241 }
242 
243 /***************************************************************************//**
244  * @brief
245  *   Initialize the board.
246  *
247  * @details
248  *
249  * @note
250  *
251  ******************************************************************************/
rt_hw_board_init(void)252 void rt_hw_board_init(void)
253 {
254     /* Chip errata */
255     CHIP_Init();
256 
257     /* Initialize DVK board register access */
258 #if defined(EFM32_GXXX_DK)
259     DVK_init();
260 #elif defined(EFM32GG_DK3750)
261     DVK_init(DVK_Init_EBI);
262 
263     /* Disable all DVK interrupts */
264     DVK_disableInterrupt(BC_INTEN_MASK);
265     DVK_clearInterruptFlags(BC_INTFLAG_MASK);
266 #endif
267 
268     /* config NVIC Configuration */
269     NVIC_Configuration();
270 
271 #if defined(EFM32_USING_HFXO)
272     /* Configure external oscillator */
273     SystemHFXOClockSet(EFM32_HFXO_FREQUENCY);
274 
275     /* Switching the CPU clock source to HFXO */
276     CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO);
277 
278     /* Turning off the high frequency RC Oscillator (HFRCO) */
279     CMU_OscillatorEnable(cmuOsc_HFRCO, false, false);
280 #endif
281 
282 #if defined(EFM32_USING_LFXO)
283     CMU_ClockSelectSet(cmuClock_LFA,cmuSelect_LFXO);
284     CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO);
285 #endif
286 
287 #if defined(EFM32_SWO_ENABLE)
288     /* Enable SWO */
289     Swo_Configuration();
290 #endif
291 
292     /* Enable high frequency peripheral clock */
293     CMU_ClockEnable(cmuClock_HFPER, true);
294     /* Enabling clock to the interface of the low energy modules */
295     CMU_ClockEnable(cmuClock_CORELE, true);
296     /* Enable GPIO clock */
297     CMU_ClockEnable(cmuClock_GPIO, true);
298 
299     /* Configure the SysTick */
300     SysTick_Configuration();
301 }
302 
303 /***************************************************************************//**
304  * @brief
305  *   Initialize the hardware drivers.
306  *
307  * @details
308  *
309  * @note
310  *
311  ******************************************************************************/
rt_hw_driver_init(void)312 void rt_hw_driver_init(void)
313 {
314     /* Initialize DMA */
315     rt_hw_dma_init();
316 
317     /* Select LFXO for specified module (and wait for it to stabilize) */
318 #if (!defined(EFM32_USING_LFXO) && defined(RT_USING_RTC))
319 #error "Low frequency clock source is needed for using RTC"
320 #endif
321 
322 #if (!defined(EFM32_USING_LFXO )&& \
323     (defined(RT_USING_LEUART0) || defined(RT_USING_LEUART1)))
324 #error "Low frequency clock source is needed for using LEUART"
325 #endif
326 
327     /* Initialize USART */
328 #if (defined(RT_USING_USART0) || defined(RT_USING_USART1) || \
329     defined(RT_USING_USART2) || defined(RT_USING_UART0) || \
330     defined(RT_USING_UART1))
331     rt_hw_usart_init();
332 #endif
333 
334     /* Initialize LEUART */
335 #if (defined(RT_USING_LEUART0) || defined(RT_USING_LEUART1))
336     rt_hw_leuart_init();
337 #endif
338 
339     /* Setup Console */
340 #if defined(EFM32_GXXX_DK)
341     DVK_enablePeripheral(DVK_RS232A);
342     DVK_enablePeripheral(DVK_SPI);
343 #elif defined(EFM32GG_DK3750)
344  #if (RT_CONSOLE_DEVICE == EFM_UART1)
345     DVK_enablePeripheral(DVK_RS232_UART);
346  #elif (RT_CONSOLE_DEVICE == EFM_LEUART1)
347     DVK_enablePeripheral(DVK_RS232_LEUART);
348  #endif
349 #endif
350     rt_console_set_device(CONSOLE_DEVICE);
351 
352     /* Initialize Timer */
353 #if (defined(RT_USING_TIMER0) || defined(RT_USING_TIMER1) || defined(RT_USING_TIMER2))
354     rt_hw_timer_init();
355 #endif
356 
357     /* Initialize ADC */
358 #if defined(RT_USING_ADC0)
359     rt_hw_adc_init();
360 #endif
361 
362     /* Initialize ACMP */
363 #if (defined(RT_USING_ACMP0) || defined(RT_USING_ACMP1))
364     rt_hw_acmp_init();
365 #endif
366 
367     /* Initialize IIC */
368 #if (defined(RT_USING_IIC0) || defined(RT_USING_IIC1))
369     rt_hw_iic_init();
370 #endif
371 
372     /* Initialize RTC */
373 #if defined(RT_USING_RTC)
374     rt_hw_rtc_init();
375 #endif
376 
377     /* Enable SPI access to MicroSD card */
378 #if defined(EFM32_USING_SPISD)
379  #if defined(EFM32_GXXX_DK)
380     DVK_writeRegister(BC_SPI_CFG, 1);
381  #elif defined(EFM32GG_DK3750)
382     DVK_enablePeripheral(DVK_MICROSD);
383  #endif
384 #endif
385 
386     /* Enable SPI access to Ethernet */
387 #if defined(EFM32_USING_ETHERNET)
388  #if defined(EFM32GG_DK3750)
389     DVK_enablePeripheral(DVK_ETH);
390  #endif
391 #endif
392 
393     /* Initialize LCD */
394 #if defined(EFM32_USING_LCD)
395     efm32_spiLcd_init();
396 #endif
397 
398     /* Initialize Keys */
399 #if defined(EFM32_USING_KEYS)
400  #if defined(EFM32GG_DK3750)
401     efm32_hw_keys_init();
402  #endif
403 #endif
404 
405 }
406 
407 /***************************************************************************//**
408  * @}
409  ******************************************************************************/
410