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