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