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-07-29 zdzn first version
9 */
10
11 #include <rthw.h>
12 #include <rtthread.h>
13
14 #include "board.h"
15 #include "drv_uart.h"
16 #include "drv_timer.h"
17
18 #include "cp15.h"
19
20 #ifdef RT_USING_SMP
21 unsigned int cntfrq;
22 #endif
23
rt_hw_timer_isr(int vector,void * parameter)24 void rt_hw_timer_isr(int vector, void *parameter)
25 {
26 rt_tick_increase();
27 #ifndef RT_USING_SMP
28 ARM_TIMER_IRQCLR = 0;
29 #else
30 mask_cntv();
31 __DSB();
32 write_cntv_tval(cntfrq);
33 __DSB();
34 unmask_cntv();
35 __DSB();
36 #endif
37 }
38
rt_hw_timer_init()39 int rt_hw_timer_init()
40 {
41 #ifndef RT_USING_SMP
42 /* timer_clock = apb_clock/(pre_divider + 1) */
43 ARM_TIMER_PREDIV = (250 - 1);
44
45 ARM_TIMER_RELOAD = 0;
46 ARM_TIMER_LOAD = 0;
47 ARM_TIMER_IRQCLR = 0;
48 ARM_TIMER_CTRL = 0;
49
50 ARM_TIMER_RELOAD = 10000;
51 ARM_TIMER_LOAD = 10000;
52
53 /* 23-bit counter, enable interrupt, enable timer */
54 ARM_TIMER_CTRL = (1 << 1) | (1 << 5) | (1 << 7);
55 #else
56 __DSB();
57 cntfrq = 35000;
58 write_cntv_tval(cntfrq);
59 enable_cntv();
60 __DSB();
61 enable_cpu_timer_intr(rt_hw_cpu_id());
62 #endif
63
64 rt_hw_interrupt_install(IRQ_ARM_TIMER, rt_hw_timer_isr, RT_NULL, "tick");
65 rt_hw_interrupt_umask(IRQ_ARM_TIMER);
66 return 0;
67 }
68 #ifdef RT_USING_SMP
69 extern void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler);
70
ipi_handler()71 void ipi_handler()
72 {
73 rt_scheduler_ipi_handler(0,RT_NULL);
74 }
75 #endif
76
idle_wfi(void)77 void idle_wfi(void)
78 {
79 asm volatile ("wfi");
80 }
81
rt_hw_board_init(void)82 void rt_hw_board_init(void)
83 {
84 /* initialize hardware interrupt */
85 rt_hw_interrupt_init();
86 rt_hw_vector_init();
87 /* initialize uart */
88 rt_hw_uart_init();
89 /* initialize timer for os tick */
90 rt_hw_timer_init();
91 rt_thread_idle_sethook(idle_wfi);
92 #if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
93 /* set console device */
94 rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
95 #endif
96 #ifdef RT_USING_HEAP
97 /* initialize memory system */
98 rt_kprintf("heap: 0x%08x - 0x%08x\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
99 rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
100 #endif
101
102 #ifdef RT_USING_SMP
103 /* install IPI handle */
104 rt_hw_ipi_handler_install(IRQ_ARM_MAILBOX, ipi_handler);
105 rt_hw_interrupt_umask(IRQ_ARM_MAILBOX);
106 enable_cpu_ipi_intr(0);
107 #endif
108 #ifdef RT_USING_COMPONENTS_INIT
109 rt_components_board_init();
110 #endif
111
112 }
113
114
115 void _reset(void);
116 void secondary_cpu_start(void);
117
118 #ifdef RT_USING_SMP
rt_hw_secondary_cpu_up(void)119 void rt_hw_secondary_cpu_up(void)
120 {
121 int i;
122 int retry,val;
123 rt_cpu_dcache_clean_flush();
124 rt_cpu_icache_flush();
125 /*TODO maybe, there is some bug */
126 for (i = RT_CPUS_NR - 1; i>0; i-- )
127 {
128 rt_kprintf("boot cpu:%d\n", i);
129 setup_bootstrap_addr(i, (int)_reset);
130 __SEV();
131 __DSB();
132 __ISB();
133 retry = 10;
134 rt_thread_delay(RT_TICK_PER_SECOND/1000);
135 do
136 {
137 val = CORE_MAILBOX3_CLEAR(i);
138 if (val == 0)
139 {
140 rt_kprintf("start OK: CPU %d \n",i);
141 break;
142 }
143 rt_thread_delay(RT_TICK_PER_SECOND);
144
145 retry --;
146 if (retry <= 0)
147 {
148 rt_kprintf("can't start for CPU %d \n",i);
149 break;
150 }
151 } while (1);
152 }
153 __DSB();
154 __SEV();
155 }
156
secondary_cpu_c_start(void)157 void secondary_cpu_c_start(void)
158 {
159 uint32_t id;
160 id = rt_hw_cpu_id();
161 rt_kprintf("cpu = 0x%08x\n",id);
162 rt_hw_timer_init();
163 rt_kprintf("cpu %d startup.\n",id);
164 rt_hw_vector_init();
165 enable_cpu_ipi_intr(id);
166 rt_hw_spin_lock(&_cpus_lock);
167 rt_system_scheduler_start();
168 }
169
rt_hw_secondary_cpu_idle_exec(void)170 void rt_hw_secondary_cpu_idle_exec(void)
171 {
172 __WFE();
173 }
174
175 #endif
176
177
178