1 /*
2  * Copyright 2020 ETH Zurich
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * SPDX-License-Identifier: Apache-2.0
17  * Author: Robert Balas (balasr@iis.ee.ethz.ch)
18  * Change Logs:
19  * Date           Author       Notes
20  * 2022-12-08     WangShun     Remove FreeRTOS related code and add RT-Thread code
21  */
22 
23 #include <stdint.h>
24 #include <assert.h>
25 
26 #include <core_pulp_cluster.h>
27 #include <core-v-mcu-config.h>
28 #include "hal_fc_event.h"
29 /* TODO: weird include */
30 #include "core-v-mcu-properties.h"
31 #include "hal_irq.h"
32 #include "hal_soc_eu.h"
33 #include "hal_apb_soc_ctrl_reg_defs.h"
34 #include "udma_uart_driver.h"
35 #include "hal_udma_ctrl_reg_defs.h"
36 #include "hal_udma_uart_reg_defs.h"
37 #include <rthw.h>
38 #include <rtthread.h>
39 #include "rtconfig.h"
40 #ifdef PKG_USING_FREERTOS_WRAPPER
41 #include "N25Q.h"
42 #include "hal_apb_i2cs.h"
43 FLASH_DEVICE_OBJECT gFlashDeviceObject[N_QSPIM];
44 uint8_t gQSPIFlashPresentFlg[N_QSPIM] = {0};
45 uint8_t gMicronFlashDetectedFlg[N_QSPIM] = {0};
46 #endif
47 
48 #define HEAP_SIZE (( unsigned int) (64 * 1024 ))
49 
50 #define FOR_SIMULATION_TESTING 0
51 
52 #if (FOR_SIMULATION_TESTING == 1)
53 
54 typedef struct
55 {
56     volatile uint32_t *rx_saddr;  // 0x00
57     volatile uint32_t rx_size;    // 0x04
58     volatile uint32_t rx_cfg;     // 0x08
59     volatile uint32_t rx_initcfg; // 0x0C
60     volatile uint32_t *tx_saddr;  // 0x10
61     volatile uint32_t tx_size;    // 0x14
62     volatile uint32_t tx_cfg;     // 0x18
63     volatile uint32_t tx_initcfg; // 0x1C
64     volatile uint32_t cfg_glob;   // 0x20
65     volatile uint32_t cfg_ll;     // 0x24
66     volatile uint32_t cfg_ur;     // 0x28
67     volatile uint32_t cfg_size;   // 0x2C
68     volatile uint32_t cfg_filter; // 0x30
69     volatile uint32_t vsync_pol;  // 0x34
70 
71 } camera_struct_t;
72 
73 void forSimulationTesting(void);
74 #endif
75 
76 /* test some assumptions we make about compiler settings */
77 static_assert(sizeof(uintptr_t) == 4,
78           "uintptr_t is not 4 bytes. Make sure you are using -mabi=ilp32*");
79 
80 /* Allocate heap to special section. Note that we have no references in the
81  * whole program to this variable (since its just here to allocate space in the
82  * section for our heap), so when using LTO it will be removed. We force it to
83  * stay with the "used" attribute
84  */
85 __attribute__((section(".heap"), used)) uint8_t ucHeap[HEAP_SIZE];
86 
87 /* Inform linker script about .heap section size. Note: GNU ld seems to
88  * internally represent integers with the bfd_vma type, that is a type that can
89  * contain memory addresses (typdefd to some int type depending on the
90  * architecture). uint32_t seems to me the most fitting candidate for rv32.
91  */
92 uint32_t __heap_size = HEAP_SIZE;
93 
94 volatile uint32_t system_core_clock = 5000000u;
95 
96 /* interrupt handling */
97 void timer_irq_handler(uint32_t mcause);
98 void undefined_handler(uint32_t mcause);
99 extern void fc_soc_event_handler1(uint32_t mcause);
100 void (*isr_table[32])(uint32_t);
101 void flash_readid(const struct cli_cmd_entry *pEntry);
102 /**
103  * Board init code. Always call this before anything else.
104  */
105 
setFLLFrequencyInIntegerMode(uint8_t aFLLNum,uint8_t aRefFreqInMHz,uint16_t aMultiplier,uint8_t aDivideRatio_R_Prescale,uint8_t aPS0_L1,uint8_t aPS0_L2)106 uint8_t setFLLFrequencyInIntegerMode(uint8_t aFLLNum, uint8_t aRefFreqInMHz, uint16_t aMultiplier, uint8_t aDivideRatio_R_Prescale, uint8_t aPS0_L1, uint8_t aPS0_L2)
107 {
108     uint8_t lSts = 0;
109     volatile uint32_t *lPLLStartAddress = (uint32_t *)NULL;
110     uint32_t lCounter = 0;
111     uint32_t lCfgVal = 0;
112 
113     uint8_t lPS0_L1 = aPS0_L1 & 0x03;
114     uint8_t lPS0_L2 = aPS0_L2 & 0xFF;
115 
116     if (aFLLNum == 0)
117         lPLLStartAddress = (uint32_t *)FLL1_START_ADDR;
118     else if (aFLLNum == 1)
119         lPLLStartAddress = (uint32_t *)FLL2_START_ADDR;
120     else if (aFLLNum == 2)
121         lPLLStartAddress = (uint32_t *)FLL3_START_ADDR;
122     else
123         lPLLStartAddress = (uint32_t *)NULL;
124 
125     if (lPLLStartAddress != NULL)
126     {
127         if ((aRefFreqInMHz >= 5) && (aRefFreqInMHz <= 500))
128         {
129             if ((aMultiplier > 0) && (aMultiplier < 2048))
130             {
131                 if (aDivideRatio_R_Prescale < 16)
132                 {
133                     *lPLLStartAddress |= (1 << 19);      // Bypass on;
134                     *lPLLStartAddress |= (1 << 2);       // Reset high
135                     *lPLLStartAddress &= ~(1 << 2);      // Reset low;
136                     *lPLLStartAddress &= ~(1 << 18);     // PS0_EN is set to low
137                     *lPLLStartAddress |= (lPS0_L1 << 0); // PS0_L1 0 which gives L01 = 1
138                     *lPLLStartAddress |= (lPS0_L2 << 4); // PS0_L2_INT 0 and PS0_L2_FRAC 0 which gives L02 = 1
139                     *lPLLStartAddress |= (0 << 12);      // PS0_L2_INT 0 and PS0_L2_FRAC 0 which gives L02 = 1
140 
141                     // FLL1 Config 1 register not configuring PS1
142                     *(lPLLStartAddress + 1) = 0;
143 
144                     // FLL1 Config 2 register
145                     lCfgVal = 0;
146                     lCfgVal |= (aMultiplier << 4);          // MULT_INT 0x28 = 40 (40*10 = 400MHz) Multiplier cannot hold 0
147                     lCfgVal |= (1 << 27);               // INTEGER_MODE is enabled
148                     lCfgVal |= (aDivideRatio_R_Prescale << 28); // PRESCALE value (Divide Ratio R = 1)
149 
150                     *(lPLLStartAddress + 2) = lCfgVal;
151 
152                     // FLL1 Config 3 register not configuring SSC
153                     *(lPLLStartAddress + 3) = 0;
154 
155                     // FLL1 Config 4 register
156                     *(lPLLStartAddress + 4) = 0x64;
157 
158                     // FLL1 Config 5 register
159                     *(lPLLStartAddress + 5) = 0x269;
160 
161                     *lPLLStartAddress |= (1 << 2);  // Reset high
162                     *lPLLStartAddress |= (1 << 18); // PS0_EN;
163                     // lCounter = 0;
164                     while ((*(lPLLStartAddress + 4) & 0x80000000) == 0) // Wait for lock detect to go high
165                     {
166                         lCounter++;
167                         if (lCounter >= 0x00010000)
168                         {
169                             lSts = 5; // Unable to achieve lock
170                             lCounter = 0;
171                             break;
172                         }
173                     }
174                     if (lSts == 0)
175                         *(lPLLStartAddress) &= ~(1 << 19); // Bypass off;
176                 }
177                 else
178                 {
179                     lSts = 1; // aDivideRatio_R_Prescale
180                 }
181             }
182             else
183             {
184                 lSts = 2; // Invalid aMultiplier
185             }
186         }
187         else
188         {
189             lSts = 3; // Invalid reference freq
190         }
191     }
192     else
193     {
194         lSts = 4; // Invalid PLL number
195     }
196     return lSts;
197 }
198 
199 int handler_count[32];
200 uint32_t gSpecialHandlingIRQCnt = 0;
201 uint8_t gQSPIIdNum = 0;
202 
system_init(void)203 void system_init(void)
204 {
205     uint32_t lFlashID = 0;
206     SocCtrl_t *soc = APB_SOC_CTRL_ADDR;
207     soc->soft_reset = 1;
208     uint32_t val = 0;
209     uint8_t i = 0;
210     timer_irq_disable();
211 
212     uint32_t *lFFL1StartAddress = (uint32_t *)FLL1_START_ADDR;
213     uint32_t *lFFL2StartAddress = (uint32_t *)FLL2_START_ADDR;
214     uint32_t *lFFL3StartAddress = (uint32_t *)FLL3_START_ADDR;
215 
216     setFLLFrequencyInIntegerMode(0, 10, 40, 1, 0, 1); // 400
217 
218     setFLLFrequencyInIntegerMode(1, 10, 40, 1, 0, 2); // 200
219 
220     setFLLFrequencyInIntegerMode(2, 10, 40, 1, 0, 4); // 100
221 
222     /* Hook up isr table. This table is temporary until we figure out how to  do proper vectored interrupts. */
223     for (int i = 0; i < 32; i++)
224     {
225         isr_table[i] = undefined_handler;
226         handler_count[i] = 0;
227     }
228     isr_table[0x7] = timer_irq_handler;
229     isr_table[0xb] = (void (*)(uint32_t))fc_soc_event_handler1; // 11 for cv32
230 
231     rt_hw_interrupt_init();
232     rt_hw_interrupt_install(0x7, timer_irq_handler, RT_NULL, "timerirq");
233     rt_hw_interrupt_install(0xb, fc_soc_event_handler1, RT_NULL, "eventirq");
234     /* mtvec is set in crt0.S */
235 
236     /* deactivate all soc events as they are enabled by default */
237     pulp_soc_eu_event_init();
238 
239     /* Setup soc events handler. */
240     pi_fc_event_handler_init(11);
241 
242     val = csr_read(CSR_MIE);
243 
244     /* TODO: enable uart */
245     for (uint8_t id = 0; id != N_UART; id++)
246     {
247         udma_uart_open(id, 115200);
248     }
249 
250 #if (FOR_SIMULATION_TESTING == 1)
251     forSimulationTesting();
252 #endif
253 }
254 
system_core_clock_update(void)255 void system_core_clock_update(void)
256 {
257     system_core_clock = pi_fll_get_frequency(FLL_SOC, 0);
258 }
259 
system_core_clock_get(void)260 void system_core_clock_get(void)
261 {
262     system_core_clock_update();
263     return;
264 }
265 
Writeraw(uint8_t uart_id,uint16_t write_len,uint8_t * write_buffer)266 uint16_t Writeraw(uint8_t uart_id, uint16_t write_len, uint8_t* write_buffer) {
267     UdmaUart_t*             puart = (UdmaUart_t*)(UDMA_CH_ADDR_UART + uart_id * UDMA_CH_SIZE);
268 
269     while (puart->status_b.tx_busy) {  // ToDo: Why is this necessary?  Thought the semaphore should have protected
270     }
271 
272     puart->tx_saddr = (uint32_t)write_buffer;
273     puart->tx_size = write_len;
274     puart->tx_cfg_b.en = 1; //enable the transfer
275 
276     return 0;
277 }
278 
timer_irq_handler(uint32_t mcause)279 void timer_irq_handler(uint32_t mcause)
280 {
281 #warning requires critical section if interrupt nesting is used.
282     rt_interrupt_enter();
283     rt_tick_increase();
284     rt_interrupt_leave();
285 }
286 
vSystemIrqHandler(uint32_t mcause)287 void vSystemIrqHandler(uint32_t mcause)
288 {
289     isr_table[mcause & 0x1f](mcause & 0x1f);
290 }
291 
undefined_handler(uint32_t mcause)292 void undefined_handler(uint32_t mcause)
293 {
294     uint32_t RegReadVal = 0;
295 #ifdef __PULP_USE_LIBC
296     abort();
297 #else
298     if ((mcause == 18) || (mcause == 19) || (mcause == 31))
299     {
300         gSpecialHandlingIRQCnt++;
301         if (gSpecialHandlingIRQCnt >= 20)
302         {
303             RegReadVal = csr_read(CSR_MIE);
304             if ((RegReadVal & BIT(mcause)) != 0) // Check if the event interrupt mask is open.
305             {
306                 // close the event interrupt mask.
307                 csr_read_clear(CSR_MIE, BIT(mcause));
308             }
309         }
310     }
311     else
312     {
313         handler_count[mcause]++;
314     }
315 #endif
316 }
317 
rt_systick_config(void)318 void rt_systick_config(void)
319 {
320     extern int timer_irq_init(uint32_t ticks);
321     timer_irq_init(ARCHI_FPGA_FREQUENCY / RT_TICK_PER_SECOND);
322 }
323