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