1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2019-05-05 jg1uaa the first version
9 */
10
11 #include <rtthread.h>
12 #include <rthw.h>
13
14 #include "board.h"
15 #include "drv_uart.h"
16
17 #define SYSCON_BASE 0x40048000
18 #define MEMMAP HWREG32(SYSCON_BASE + 0x000)
19 #define SYSPLLCTRL HWREG32(SYSCON_BASE + 0x008)
20 #define SYSPLLSTAT HWREG32(SYSCON_BASE + 0x00c)
21 #define SYSPLLCLKSEL HWREG32(SYSCON_BASE + 0x040)
22 #define SYSPLLCLKUEN HWREG32(SYSCON_BASE + 0x044)
23 #define MAINCLKSEL HWREG32(SYSCON_BASE + 0x070)
24 #define MAINCLKUEN HWREG32(SYSCON_BASE + 0x074)
25 #define AHBCLKCTRL HWREG32(SYSCON_BASE + 0x080)
26 #define PDRUNCFG HWREG32(SYSCON_BASE + 0x238)
27
28 #define SCB_BASE 0xe000e000
29 #define SYST_CSR HWREG32(SCB_BASE + 0x010)
30 #define SYST_RVR HWREG32(SCB_BASE + 0x014)
31 #define NVIC_ISER HWREG32(SCB_BASE + 0x100)
32 #define NVIC_ICER HWREG32(SCB_BASE + 0x180)
33 #define NVIC_ISPR HWREG32(SCB_BASE + 0x200)
34 #define NVIC_ICPR HWREG32(SCB_BASE + 0x280)
35 #define NVIC_IPR(irqno) HWREG32(SCB_BASE + 0x400 + (((irqno) / 4) << 2))
36 #define SCB_SHPR3 HWREG32(SCB_BASE + 0xd20)
37
38 extern unsigned char __bss_end__[];
39 extern unsigned char _ram_end[];
40
41 /**
42 * This is the timer interrupt service routine.
43 */
SysTick_Handler(void)44 void SysTick_Handler(void)
45 {
46 /* enter interrupt */
47 rt_interrupt_enter();
48
49 rt_tick_increase();
50
51 /* leave interrupt */
52 rt_interrupt_leave();
53 }
54
UART_IRQHandler(void)55 rt_weak void UART_IRQHandler(void)
56 {
57
58 };
59
os_clock_init(void)60 void os_clock_init(void)
61 {
62 /* bump up system clock 12MHz to 48MHz, using IRC (internal RC) osc. */
63
64 MAINCLKSEL = 0; // main clock: IRC @12MHz (default, for safety)
65 MAINCLKUEN = 0;
66 MAINCLKUEN = 1;
67
68 PDRUNCFG &= ~0x80; // power up System PLL
69
70 SYSPLLCLKSEL = 0; // PLL clock source: IRC osc
71 SYSPLLCLKUEN = 0;
72 SYSPLLCLKUEN = 1;
73
74 SYSPLLCTRL = 0x23; // Fcco = 2 x P x FCLKOUT
75 // 192MHz = 2 x 2 x 48MHz
76 // M = FCLKOUT / FCLKIN
77 // 4 = 48MHz / 12MHz
78
79 while (!(SYSPLLSTAT & 1)); // wait for lock PLL
80
81 MAINCLKSEL = 3; // main clock: system PLL
82 MAINCLKUEN = 0;
83 MAINCLKUEN = 1;
84
85 AHBCLKCTRL |= (1 << 16); // power up IOCON
86 }
87
SysTick_init(void)88 void SysTick_init(void)
89 {
90 rt_uint32_t shpr3;
91
92 /* set SysTick interrupt priority */
93 shpr3 = SCB_SHPR3;
94 shpr3 &= ~0xff000000;
95 shpr3 |= 0x40 << 24;
96 SCB_SHPR3 = shpr3;
97
98 /* start SysTick */
99 SYST_CSR = 0x06; // Clock source:Core, SysTick Exception:enable
100 SYST_RVR = (CPU_CLOCK / RT_TICK_PER_SECOND) - 1;
101 SYST_CSR = 0x07; // Counter:enable
102 }
103
104 /**
105 * This function initializes LPC1114 SoC.
106 */
rt_hw_board_init(void)107 void rt_hw_board_init(void)
108 {
109 os_clock_init();
110
111 /* init SysTick */
112 SysTick_init();
113
114 #ifdef RT_USING_HEAP
115 /* initialize system heap */
116 rt_system_heap_init((void *)&__bss_end__, (void *)&_ram_end);
117 #endif
118 /* initialize uart */
119 #ifdef RT_USING_SERIAL
120 rt_hw_uart_init();
121 #endif
122
123 #if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
124 /* set console device */
125 rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
126 #endif
127
128 #ifdef RT_USING_COMPONENTS_INIT
129 rt_components_board_init();
130 #endif
131 }
132
133 /**
134 * Enable External Interrupt
135 */
NVIC_EnableIRQ(rt_int32_t irqno)136 void NVIC_EnableIRQ(rt_int32_t irqno)
137 {
138 NVIC_ISER = 1UL << (irqno & 0x1f);
139 }
140
141 /**
142 * Disable External Interrupt
143 */
NVIC_DisableIRQ(rt_int32_t irqno)144 void NVIC_DisableIRQ(rt_int32_t irqno)
145 {
146 NVIC_ICER = 1UL << (irqno & 0x1f);
147 }
148
149 /**
150 * Get Pending Interrupt
151 * Different from CMSIS implementation,
152 * returns zero/non-zero, not zero/one.
153 */
NVIC_GetPendingIRQ(rt_int32_t irqno)154 rt_uint32_t NVIC_GetPendingIRQ(rt_int32_t irqno)
155 {
156 return NVIC_ISPR & (1UL << (irqno & 0x1f));
157 }
158
159 /**
160 * Set Pending Interrupt
161 */
NVIC_SetPendingIRQ(rt_int32_t irqno)162 void NVIC_SetPendingIRQ(rt_int32_t irqno)
163 {
164 NVIC_ISPR = 1UL << (irqno & 0x1f);
165 }
166
167 /**
168 * Clear Pending Interrupt
169 */
NVIC_ClearPendingIRQ(rt_int32_t irqno)170 void NVIC_ClearPendingIRQ(rt_int32_t irqno)
171 {
172 NVIC_ICPR = 1UL << (irqno & 0x1f);
173 }
174
175 /**
176 * Set Interrupt Priority
177 * Different from CMSIS implementation,
178 * this code supports only external (device specific) interrupt.
179 */
NVIC_SetPriority(rt_int32_t irqno,rt_uint32_t priority)180 void NVIC_SetPriority(rt_int32_t irqno, rt_uint32_t priority)
181 {
182 rt_uint32_t shift, ipr;
183
184 shift = (irqno % 4) * 8;
185 ipr = NVIC_IPR(irqno);
186 ipr &= ~(0xffUL << shift);
187 ipr |= (priority & 0xff) << shift;
188 NVIC_IPR(irqno) = ipr;
189 }
190