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 * 2012-02-13 mojingxian first version
9 */
10
11 #include "board.h"
12 #include "rtconfig.h"
13 #include "rtdef.h"
14 #include "rthw.h"
15 #include "drivers/dev_serial.h"
16
17 #include <signal.h>
18 #include <sys/platform.h>
19 #include <ccblkfn.h>
20 #include <sysreg.h>
21 #include <string.h>
22 #include <sys\exception.h>
23 #include <stdio.h>
24
25 #define IVG_CLR(index) (index > 0 ? ((0xFFFFFFF0 << (index * 0x04)) | \
26 (0xFFFFFFF0 >> ((0x08 - index) * 0x04))):0xFFFFFFF0)
27 #define IVG_SET(index,ivg) ((((ivg) - 0x07) & 0x0F) << (index * 0x04))
28
29 #define UART0 ((struct uartport *)pUART_THR)
30 struct serial_int_rx uart0_int_rx;
31 struct serial_device uart0 =
32 {
33 UART0,
34 &uart0_int_rx,
35 RT_NULL
36 };
37 struct rt_device uart0_device;
38
39 /**
40 * This function is to set the EBIU(EXTERNAL BUS INTERFACE UNIT).
41 */
rt_hw_ebiu_init(void)42 static void rt_hw_ebiu_init(void)
43 {
44 *pEBIU_AMBCTL0 = 0xffc2ffc2;
45
46 *pEBIU_AMBCTL1 = 0xffc2ffc3;
47
48 *pEBIU_AMGCTL = 0x010f;
49 }
50
51 /**
52 * This is the timer interrupt service routine.
53 */
EX_INTERRUPT_HANDLER(rt_hw_timer_handler)54 EX_INTERRUPT_HANDLER(rt_hw_timer_handler)
55 {
56 /* enter interrupt */
57 rt_interrupt_enter();
58
59 rt_tick_increase();
60
61 /* leave interrupt */
62 rt_interrupt_leave();
63 }
64
65 /**
66 * This function is called to initialize system tick source (typically a
67 * timer generating interrupts every 1 to 100 mS).
68 * We decided to use Core Timer as the tick interrupt source.
69 */
rt_hw_core_timer_init(void)70 void rt_hw_core_timer_init(void)
71 {
72 *pTCNTL = 1; // Turn on timer, TMPWR
73 *pTSCALE = 0x00;
74 *pTCOUNT = CCLKSPEED / RT_TICK_PER_SECOND;
75 *pTPERIOD = CCLKSPEED / RT_TICK_PER_SECOND;
76 register_handler(ik_timer,rt_hw_timer_handler);
77 *pTCNTL = 0x07; // Start Timer and set Auto-reload
78 }
79
rt_hw_interrupt_init(void)80 void rt_hw_interrupt_init(void)
81 {
82 extern rt_uint32_t rt_interrupt_from_thread;
83 extern rt_uint32_t rt_interrupt_to_thread;
84 extern rt_uint32_t rt_thread_switch_interrupt_flag;
85 extern rt_uint8_t rt_interrupt_nest;
86 extern void interrupt_thread_switch(void);
87
88 register_handler(ik_ivg14,interrupt_thread_switch); //context_vdsp.S
89
90 /* init interrupt nest, and context in thread sp */
91 rt_interrupt_nest = 0;
92 rt_interrupt_from_thread = 0;
93 rt_interrupt_to_thread = 0;
94 rt_thread_switch_interrupt_flag = 0;
95 }
96
rt_hw_pll_init(void)97 static void rt_hw_pll_init(void)
98 {
99 unsigned long imask;
100
101 sysreg_write(reg_SYSCFG, 0x32);
102
103 *pSIC_IWR = 0x01;
104
105 *pPLL_CTL = SET_MSEL(SPEED_MULTIPLE);
106
107 // PLL Re-programming Sequence.
108 // Core is idle'ed to allow the PPL to re-lock.
109 imask = cli();
110 idle();
111 sti(imask);
112 *pVR_CTL = 0x00FB;
113
114 // PLL Re-programming Sequence.
115 // Core is idle'ed to allow the PPL to re-lock.
116 imask = cli();
117 idle();
118 sti(imask);
119
120 *pPLL_DIV = BUS_DIVISOR;
121 }
122
123 /**
124 * This function is called to initialize external sdram.
125 */
rt_hw_exdram_init(void)126 static void rt_hw_exdram_init(void)
127 {
128 // Initalize EBIU control registers to enable all banks
129 *pEBIU_AMBCTL1 = 0xFFFFFF02;
130 ssync();
131
132 *pEBIU_AMGCTL = 0x00FF;
133 ssync();
134
135 // Check if already enabled
136 if (SDRS != ((*pEBIU_SDSTAT) & SDRS))
137 {
138 return;
139 }
140
141 //SDRAM Refresh Rate Control Register
142 *pEBIU_SDRRC = 0x01A0;
143
144 //SDRAM Memory Bank Control Register
145 *pEBIU_SDBCTL = 0x0025; //1.7 64 MB
146
147 //SDRAM Memory Global Control Register
148 *pEBIU_SDGCTL = 0x0091998D;//0x998D0491
149
150 ssync();
151 }
152
uart_set_bitrate(unsigned long bit_rate)153 short uart_set_bitrate(unsigned long bit_rate)
154 {
155 unsigned short int divisor;
156
157 switch (bit_rate)
158 {
159 case 1200:
160 case 2400:
161 case 4800:
162 case 9600:
163 case 19200:
164 case 28800:
165 case 38400:
166 case 57600:
167 case 115200:
168 case 125000:
169 divisor = (unsigned short int) ((float) SCLKSPEED / ((float) bit_rate * 16.0f) + 0.5f);
170
171 *(pUART_LCR) |= DLAB; // Enable access to DLL and DLH registers
172 *(pUART_DLL) = divisor & 0xFF;
173 *(pUART_DLH) = divisor >> 8;
174 *(pUART_LCR) &= ~DLAB; // clear DLAB bit
175
176 break;
177
178 default: // baud rate not supported
179 break;
180 }
181
182 return 0;
183 }
184
rt_hw_uart_init(void)185 void rt_hw_uart_init(void)
186 {
187 // Apply UART configuration 8 bit data, No parity, 1 stop bit
188 *pUART_LCR = 0x0000; // Reset value
189 *pUART_LCR = WLS(8);
190
191 // Ensure that Loopback mode is disabled by clearing LOOP_ENA bit
192 *pUART_MCR = 0x0000; //Reset value
193
194 uart_set_bitrate(19200);// Set communication baudrate 115200
195
196 *pUART_IER = ERBFI;
197
198 // Enable UART clock
199 *pUART_GCTL = UCEN;
200 }
201
uart_put_char(const char c)202 int uart_put_char(const char c)
203 {
204 while (!(*pUART_LSR & THRE))
205 {
206 /* wait */
207 }
208
209 *pUART_THR = c;
210
211 return c;
212 }
213
rt_hw_console_output(const char * str)214 void rt_hw_console_output(const char *str)
215 {
216 while (*str != '\0')
217 {
218 if (*str == '\n')
219 uart_put_char('\r');
220 uart_put_char(*str++);
221 }
222 }
223
EX_INTERRUPT_HANDLER(uart_rx_isr)224 EX_INTERRUPT_HANDLER(uart_rx_isr)
225 {
226 rt_interrupt_enter();
227
228 rt_hw_serial_isr(&uart0_device);
229
230 rt_interrupt_leave();
231 }
232
rt_hw_isr_install(void)233 void rt_hw_isr_install(void)
234 {
235 *pSIC_IWR = 0xFFFFFFFF;
236 *pSIC_IMASK = 0x00000000;
237
238 *pSIC_IAR1 &= IVG_CLR(IAR1_DMA6_UARTRX_IVG);
239 *pSIC_IAR1 |= IVG_SET(IAR1_DMA6_UARTRX_IVG,ik_ivg9);
240 register_handler(ik_ivg9,uart_rx_isr);
241 *pSIC_IMASK |= DMA6_UART_RX_INT_MASK;/* 开中断 */
242 }
243
rt_hw_board_init(void)244 void rt_hw_board_init(void)
245 {
246 rt_hw_pll_init();
247
248 rt_hw_ebiu_init();
249
250 rt_hw_exdram_init();
251
252 rt_hw_uart_init();
253 }
254