]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/synchronize_harts.c
Update RISCC-V-RV32-SiFive_HiFive1_FreedomStudio project to latest tools and metal...
[freertos] / FreeRTOS / Demo / RISC-V_RV32_SiFive_HiFive1_FreedomStudio / freedom-metal / src / synchronize_harts.c
1 /* Copyright 2019 SiFive, Inc */
2 /* SPDX-License-Identifier: Apache-2.0 */
3
4 #include <metal/machine.h>
5 #include <metal/machine/platform.h>
6 #include <metal/io.h>
7 #include <metal/cpu.h>
8
9 #define METAL_REG(base, offset)   (((unsigned long)(base) + (offset)))
10 #define METAL_REGW(base, offset)  (__METAL_ACCESS_ONCE((__metal_io_u32 *)METAL_REG((base), (offset))))
11 #define METAL_MSIP(base, hart)    (METAL_REGW((base),4*(hart)))
12
13 /*
14  * _synchronize_harts() is called by crt0.S to cause harts > 0 to wait for
15  * hart 0 to finish copying the datat section, zeroing the BSS, and running
16  * the libc contstructors.
17  */
18 __attribute__((section(".init")))
19 void __metal_synchronize_harts() {
20 #if __METAL_DT_MAX_HARTS > 1
21
22     int hart;
23     __asm__ volatile("csrr %0, mhartid" : "=r" (hart) ::);
24
25     uintptr_t msip_base = 0;
26
27     /* Get the base address of the MSIP registers */
28 #ifdef __METAL_DT_RISCV_CLINT0_HANDLE
29     msip_base = __metal_driver_sifive_clint0_control_base(__METAL_DT_RISCV_CLINT0_HANDLE);
30     msip_base += METAL_RISCV_CLINT0_MSIP_BASE;
31 #elif __METAL_DT_RISCV_CLIC0_HANDLE
32     msip_base = __metal_driver_sifive_clic0_control_base(__METAL_DT_RISCV_CLIC0_HANDLE);
33     msip_base += METAL_RISCV_CLIC0_MSIP_BASE;
34 #else
35 #pragma message(No handle for CLINT or CLIC found, harts may be unsynchronized after init!)
36 #endif
37
38     /* Disable machine interrupts as a precaution */
39     __asm__ volatile("csrc mstatus, %0" :: "r" (METAL_MSTATUS_MIE));
40
41     if (hart == 0) {
42         /* Hart 0 waits for all harts to set their MSIP bit */
43         for (int i = 1 ; i < __METAL_DT_MAX_HARTS; i++) {
44             while (METAL_MSIP(msip_base, i) == 0) ;
45         }
46
47         /* Hart 0 clears everyone's MSIP bit */
48         for (int i = 1 ; i < __METAL_DT_MAX_HARTS; i++) {
49             METAL_MSIP(msip_base, i) = 0;
50         }
51     } else {
52         /* Other harts set their MSIP bit to indicate they're ready */
53         METAL_MSIP(msip_base, hart) = 1;
54         __asm__ volatile ("fence w,rw");
55
56         /* Wait for hart 0 to clear the MSIP bit */
57         while (METAL_MSIP(msip_base, hart) == 1) ;
58     }
59
60 #endif /* __METAL_DT_MAX_HARTS > 1 */
61 }
62