1 /*
2 * Copyright (c) 2020-2021, Bluetrum Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2020-11-18 greedyhao first version
9 */
10
11 #include <rthw.h>
12 #include "board.h"
13
14 int rt_hw_usart_init(void);
15 void my_printf(const char *format, ...);
16 void my_print_r(const void *buf, uint16_t cnt);
17 void timer0_cfg(uint32_t ticks);
18 void rt_soft_isr(int vector, void *param);
19 void cpu_irq_comm(void);
20 void set_cpu_irq_comm(void (*irq_hook)(void));
21 void load_cache();
22 void os_cache_init(void);
23 void sys_error_hook(uint8_t err_no);
24 void huart_timer_isr(void);
25
26 typedef void (*spiflash_init_func)(uint8_t sf_read, uint8_t dummy);
27
28 static struct rt_mutex mutex_spiflash = {0};
29 static struct rt_mutex mutex_cache = {0};
30 extern volatile rt_atomic_t rt_interrupt_nest;
31 extern uint32_t __heap_start, __heap_end;
32
33 #ifdef RT_USING_CONSOLE
hal_printf(const char * fmt,...)34 void hal_printf(const char *fmt, ...)
35 {
36 rt_device_t console = rt_console_get_device();
37
38 va_list args;
39 rt_size_t length;
40 static char rt_log_buf[RT_CONSOLEBUF_SIZE];
41
42 va_start(args, fmt);
43 /* the return value of vsnprintf is the number of bytes that would be
44 * written to buffer had if the size of the buffer been sufficiently
45 * large excluding the terminating null byte. If the output string
46 * would be larger than the rt_log_buf, we have to adjust the output
47 * length. */
48 length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
49 if (length > RT_CONSOLEBUF_SIZE - 1)
50 length = RT_CONSOLEBUF_SIZE - 1;
51 #ifdef RT_USING_DEVICE
52 if (console == RT_NULL)
53 {
54 rt_hw_console_output(rt_log_buf);
55 }
56 else
57 {
58 rt_uint16_t old_flag = console->open_flag;
59
60 console->open_flag |= RT_DEVICE_FLAG_STREAM;
61 rt_device_write(console, 0, rt_log_buf, length);
62 console->open_flag = old_flag;
63 }
64 #else
65 rt_hw_console_output(rt_log_buf);
66 #endif
67 va_end(args);
68 }
69 #endif
70
71 rt_section(".irq")
os_interrupt_enter(void)72 void os_interrupt_enter(void)
73 {
74 rt_interrupt_enter();
75 }
76
77 rt_section(".irq")
os_interrupt_leave(void)78 void os_interrupt_leave(void)
79 {
80 rt_interrupt_leave();
81 }
82
83 typedef void (*isr_t)(void);
84 rt_section(".irq")
register_isr(int vector,isr_t isr)85 isr_t register_isr(int vector, isr_t isr)
86 {
87 char buf[8] = {0};
88 rt_snprintf(buf, sizeof(buf), "sys%d", vector);
89 rt_isr_handler_t handle = (rt_isr_handler_t)isr;
90 rt_hw_interrupt_install(vector, handle, RT_NULL, buf);
91 }
92
93 rt_section(".irq.timer")
timer0_isr(int vector,void * param)94 void timer0_isr(int vector, void *param)
95 {
96 rt_interrupt_enter();
97 TMR0CPND = BIT(9);
98 rt_tick_increase();
99 #ifdef RT_USING_SERIAL
100 huart_timer_isr();
101 #endif
102 rt_interrupt_leave();
103 }
104
timer0_init(void)105 void timer0_init(void)
106 {
107 TMR0CON = BIT(7); //TIE
108 TMR0CNT = 0;
109
110 rt_hw_interrupt_install(IRQ_TMR0_VECTOR, timer0_isr, RT_NULL, "tick");
111 }
112
timer0_cfg(uint32_t ticks)113 void timer0_cfg(uint32_t ticks)
114 {
115 TMR0PR = (uint32_t)(ticks - 1UL); //1ms interrupt
116 TMR0CON |= BIT(0); // EN
117 }
118
hal_get_ticks(void)119 uint32_t hal_get_ticks(void)
120 {
121 return rt_tick_get();
122 }
123
hal_mdelay(uint32_t nms)124 void hal_mdelay(uint32_t nms)
125 {
126 rt_thread_mdelay(nms);
127 }
128
hal_udelay(uint32_t nus)129 void hal_udelay(uint32_t nus)
130 {
131 rt_hw_us_delay(nus);
132 }
133
134 /**
135 * The time delay function.
136 *
137 * @param us microseconds.
138 */
139 rt_section(".com_text")
rt_hw_us_delay(rt_uint32_t us)140 void rt_hw_us_delay(rt_uint32_t us)
141 {
142 rt_uint32_t ticks;
143 rt_uint32_t told, tnow, tcnt = 0;
144 rt_uint32_t reload = TMR0PR;
145
146 ticks = us * reload / (1000 / RT_TICK_PER_SECOND);
147 told = TMR0CNT;
148 while (1)
149 {
150 tnow = TMR0CNT;
151 if (tnow != told)
152 {
153 if (tnow < told)
154 {
155 tcnt += told - tnow;
156 }
157 else
158 {
159 tcnt += reload - tnow + told;
160 }
161 told = tnow;
162 if (tcnt >= ticks)
163 {
164 break;
165 }
166 }
167 }
168 }
169
rt_hw_systick_init(void)170 void rt_hw_systick_init(void)
171 {
172 CLKCON2 &= 0x00ffffff;
173 CLKCON2 |= (25 << 24); //配置x26m_div_clk = 1M (timer, ir, fmam ...用到)
174 CLKCON0 &= ~(7 << 23);
175 CLKCON0 |= BIT(24); //tmr_inc select x26m_div_clk = 1M
176
177 set_sysclk(SYSCLK_48M);
178
179 /* Setting software interrupt */
180 set_cpu_irq_comm(cpu_irq_comm);
181 rt_hw_interrupt_install(IRQ_SW_VECTOR, rt_soft_isr, RT_NULL, "sw_irq");
182
183 timer0_init();
184 hal_set_tick_hook(timer0_cfg);
185 hal_set_ticks(get_sysclk_nhz() / RT_TICK_PER_SECOND);
186
187 PICCON |= 0x10002;
188 }
189
rt_hw_board_init(void)190 void rt_hw_board_init(void)
191 {
192 WDT_DIS();
193 rt_hw_systick_init();
194
195 #ifdef RT_USING_HEAP
196 rt_system_heap_init(&__heap_start, &__heap_end);
197 #endif
198
199 #ifdef RT_USING_PIN
200 rt_hw_pin_init();
201 #endif // RT_USING_PIN
202
203 #ifdef RT_USING_SERIAL
204 rt_hw_usart_init();
205 #endif // RT_USING_SERIAL
206
207 #if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
208 rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
209 #endif // RT_USING_CONSOLE
210
211 #ifdef RT_USING_COMPONENTS_INIT
212 rt_components_board_init();
213 #endif
214 }
215
216 rt_section(".irq.cache")
cache_init(void)217 void cache_init(void)
218 {
219 os_cache_init();
220 rt_mutex_init(&mutex_spiflash, "flash_mutex", RT_IPC_FLAG_PRIO);
221 rt_mutex_init(&mutex_cache, "cache_mutex", RT_IPC_FLAG_PRIO);
222 }
223
224 rt_section(".irq.cache")
os_spiflash_lock(void)225 void os_spiflash_lock(void)
226 {
227 if ((rt_thread_self() != RT_NULL) && (rt_interrupt_nest == 0))
228 {
229 rt_mutex_take(&mutex_spiflash, RT_WAITING_FOREVER);
230 }
231 }
232
233 rt_section(".irq.cache")
os_spiflash_unlock(void)234 void os_spiflash_unlock(void)
235 {
236 if ((rt_thread_self() != RT_NULL) && (rt_interrupt_nest == 0))
237 {
238 rt_mutex_release(&mutex_spiflash);
239 }
240 }
241
242 rt_section(".irq.cache")
os_cache_lock(void)243 void os_cache_lock(void)
244 {
245 if ((rt_thread_self() != RT_NULL) && (rt_interrupt_nest == 0))
246 {
247 rt_mutex_take(&mutex_cache, RT_WAITING_FOREVER);
248 }
249 }
250
251 rt_section(".irq.cache")
os_cache_unlock(void)252 void os_cache_unlock(void)
253 {
254 if ((rt_thread_self() != RT_NULL) && (rt_interrupt_nest == 0))
255 {
256 rt_mutex_release(&mutex_cache);
257 }
258 }
259
260 rt_section(".irq.err.str")
261 static const char stack_info[] = "thread sp=0x%x name=%s";
262
rt_hw_console_output(const char * str)263 void rt_hw_console_output(const char *str)
264 {
265 my_printf(str);
266 }
267
268 /**
269 * @brief print exception error
270 * @note Every message needed to print, must put in .comm exction.
271 * @note (IRQ in Flash: %x %x - %x %x\n, -, rt_interrupt_nest, PC, miss_addr)
272 * miss_addr: The address in map file minus 0x10000000
273 */
274 rt_section(".irq.err")
exception_isr(void)275 void exception_isr(void)
276 {
277 #if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
278 extern long list_thread(void);
279 #endif
280 sys_error_hook(1);
281
282 #if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
283 rt_console_set_device(RT_NULL);
284 rt_kprintf(stack_info, rt_thread_self()->sp, rt_thread_self()->parent.name);
285 #endif
286
287 while (1);
288 }
289