]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/freedom-e-sdk/env/freedom-e300-hifive1/init.c
Move the call to traceTASK_DELETE() to before port portPRE_TASK_DELETE_HOOK() as...
[freertos] / FreeRTOS / Demo / RISC-V-Qemu-sifive_e-FreedomStudio / freedom-e-sdk / env / freedom-e300-hifive1 / init.c
1 #include <stdint.h>\r
2 #include <stdio.h>\r
3 #include <unistd.h>\r
4 \r
5 #include "platform.h"\r
6 #include "encoding.h"\r
7 \r
8 extern int main(int argc, char** argv);\r
9 extern void trap_entry();\r
10 \r
11 static unsigned long mtime_lo(void)\r
12 {\r
13   return *(volatile unsigned long *)(CLINT_CTRL_ADDR + CLINT_MTIME);\r
14 }\r
15 \r
16 #ifdef __riscv32\r
17 \r
18 static uint32_t mtime_hi(void)\r
19 {\r
20   return *(volatile uint32_t *)(CLINT_CTRL_ADDR + CLINT_MTIME + 4);\r
21 }\r
22 \r
23 uint64_t get_timer_value()\r
24 {\r
25   while (1) {\r
26     uint32_t hi = mtime_hi();\r
27     uint32_t lo = mtime_lo();\r
28     if (hi == mtime_hi())\r
29       return ((uint64_t)hi << 32) | lo;\r
30   }\r
31 }\r
32 \r
33 #else /* __riscv32 */\r
34 \r
35 uint64_t get_timer_value()\r
36 {\r
37   return mtime_lo();\r
38 }\r
39 \r
40 #endif\r
41 \r
42 unsigned long get_timer_freq()\r
43 {\r
44   return 32768;\r
45 }\r
46 \r
47 static void use_hfrosc(int div, int trim)\r
48 {\r
49   // Make sure the HFROSC is running at its default setting\r
50   PRCI_REG(PRCI_HFROSCCFG) = (ROSC_DIV(div) | ROSC_TRIM(trim) | ROSC_EN(1));\r
51   while ((PRCI_REG(PRCI_HFROSCCFG) & ROSC_RDY(1)) == 0) ;\r
52   PRCI_REG(PRCI_PLLCFG) &= ~PLL_SEL(1);\r
53 }\r
54 \r
55 static void use_pll(int refsel, int bypass, int r, int f, int q)\r
56 {\r
57   // Ensure that we aren't running off the PLL before we mess with it.\r
58   if (PRCI_REG(PRCI_PLLCFG) & PLL_SEL(1)) {\r
59     // Make sure the HFROSC is running at its default setting\r
60     use_hfrosc(4, 16);\r
61   }\r
62 \r
63   // Set PLL Source to be HFXOSC if available.\r
64   uint32_t config_value = 0;\r
65 \r
66   config_value |= PLL_REFSEL(refsel);\r
67 \r
68   if (bypass) {\r
69     // Bypass\r
70     config_value |= PLL_BYPASS(1);\r
71 \r
72     PRCI_REG(PRCI_PLLCFG) = config_value;\r
73 \r
74     // If we don't have an HFXTAL, this doesn't really matter.\r
75     // Set our Final output divide to divide-by-1:\r
76     PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0));\r
77   } else {\r
78     // In case we are executing from QSPI,\r
79     // (which is quite likely) we need to\r
80     // set the QSPI clock divider appropriately\r
81     // before boosting the clock frequency.\r
82 \r
83     // Div = f_sck/2\r
84     SPI0_REG(SPI_REG_SCKDIV) = 8;\r
85 \r
86     // Set DIV Settings for PLL\r
87     // Both HFROSC and HFXOSC are modeled as ideal\r
88     // 16MHz sources (assuming dividers are set properly for\r
89     // HFROSC).\r
90     // (Legal values of f_REF are 6-48MHz)\r
91 \r
92     // Set DIVR to divide-by-2 to get 8MHz frequency\r
93     // (legal values of f_R are 6-12 MHz)\r
94 \r
95     config_value |= PLL_BYPASS(1);\r
96     config_value |= PLL_R(r);\r
97 \r
98     // Set DIVF to get 512Mhz frequncy\r
99     // There is an implied multiply-by-2, 16Mhz.\r
100     // So need to write 32-1\r
101     // (legal values of f_F are 384-768 MHz)\r
102     config_value |= PLL_F(f);\r
103 \r
104     // Set DIVQ to divide-by-2 to get 256 MHz frequency\r
105     // (legal values of f_Q are 50-400Mhz)\r
106     config_value |= PLL_Q(q);\r
107 \r
108     // Set our Final output divide to divide-by-1:\r
109     PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0));\r
110 \r
111     PRCI_REG(PRCI_PLLCFG) = config_value;\r
112 \r
113     // Un-Bypass the PLL.\r
114     PRCI_REG(PRCI_PLLCFG) &= ~PLL_BYPASS(1);\r
115 \r
116     // Wait for PLL Lock\r
117     // Note that the Lock signal can be glitchy.\r
118     // Need to wait 100 us\r
119     // RTC is running at 32kHz.\r
120     // So wait 4 ticks of RTC.\r
121     uint32_t now = mtime_lo();\r
122     while (mtime_lo() - now < 4) ;\r
123 \r
124     // Now it is safe to check for PLL Lock\r
125     while ((PRCI_REG(PRCI_PLLCFG) & PLL_LOCK(1)) == 0) ;\r
126   }\r
127 \r
128   // Switch over to PLL Clock source\r
129   PRCI_REG(PRCI_PLLCFG) |= PLL_SEL(1);\r
130 }\r
131 \r
132 static void use_default_clocks()\r
133 {\r
134   // Turn off the LFROSC\r
135   AON_REG(AON_LFROSC) &= ~ROSC_EN(1);\r
136 \r
137   // Use HFROSC\r
138   use_hfrosc(4, 16);\r
139 }\r
140 \r
141 static unsigned long __attribute__((noinline)) measure_cpu_freq(size_t n)\r
142 {\r
143   unsigned long start_mtime, delta_mtime;\r
144   unsigned long mtime_freq = get_timer_freq();\r
145 \r
146   // Don't start measuruing until we see an mtime tick\r
147   unsigned long tmp = mtime_lo();\r
148   do {\r
149     start_mtime = mtime_lo();\r
150   } while (start_mtime == tmp);\r
151 \r
152   unsigned long start_mcycle = read_csr(mcycle);\r
153 \r
154   do {\r
155     delta_mtime = mtime_lo() - start_mtime;\r
156   } while (delta_mtime < n);\r
157 \r
158   unsigned long delta_mcycle = read_csr(mcycle) - start_mcycle;\r
159 \r
160   return (delta_mcycle / delta_mtime) * mtime_freq\r
161          + ((delta_mcycle % delta_mtime) * mtime_freq) / delta_mtime;\r
162 }\r
163 \r
164 unsigned long get_cpu_freq()\r
165 {\r
166   static uint32_t cpu_freq;\r
167 \r
168   if (!cpu_freq) {\r
169     // warm up I$\r
170     measure_cpu_freq(1);\r
171     // measure for real\r
172     cpu_freq = measure_cpu_freq(10);\r
173   }\r
174 \r
175   return cpu_freq;\r
176 }\r
177 \r
178 static void uart_init(size_t baud_rate)\r
179 {\r
180   GPIO_REG(GPIO_IOF_SEL) &= ~IOF0_UART0_MASK;\r
181   GPIO_REG(GPIO_IOF_EN) |= IOF0_UART0_MASK;\r
182   UART0_REG(UART_REG_DIV) = get_cpu_freq() / baud_rate - 1;\r
183   UART0_REG(UART_REG_TXCTRL) |= UART_TXEN;\r
184 }\r
185 \r
186 \r
187 \r
188 #ifdef USE_PLIC\r
189 extern void handle_m_ext_interrupt();\r
190 #endif\r
191 \r
192 #ifdef USE_M_TIME\r
193 extern void handle_m_time_interrupt();\r
194 #endif\r
195 \r
196 uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc)\r
197 {\r
198   if (0){\r
199 #ifdef USE_PLIC\r
200     // External Machine-Level interrupt from PLIC\r
201   } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)) {\r
202     handle_m_ext_interrupt();\r
203 #endif\r
204 #ifdef USE_M_TIME\r
205     // External Machine-Level interrupt from PLIC\r
206   } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){\r
207     handle_m_time_interrupt();\r
208 #endif\r
209   }\r
210   else {\r
211     write(1, "trap\n", 5);\r
212     _exit(1 + mcause);\r
213   }\r
214   return epc;\r
215 }\r
216 \r
217 void _init()\r
218 {\r
219   \r
220   #ifndef NO_INIT\r
221   use_default_clocks();\r
222   use_pll(0, 0, 1, 31, 1);\r
223   uart_init(115200);\r
224 \r
225   printf("core freq at %d Hz\n", (int)get_cpu_freq());\r
226 \r
227   write_csr(mtvec, &trap_entry);\r
228   if (read_csr(misa) & (1 << ('F' - 'A'))) { // if F extension is present\r
229     write_csr(mstatus, MSTATUS_FS); // allow FPU instructions without trapping\r
230     write_csr(fcsr, 0); // initialize rounding mode, undefined at reset\r
231   }\r
232   #endif\r
233   \r
234 }\r
235 \r
236 void _fini()\r
237 {\r
238 }\r