1 /*******************************************************************************
2 * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * MPFS HAL Embedded Software
7 *
8 */
9
10 /***************************************************************************
11 * @file mss_util.c
12 * @author Microchip-FPGA Embedded Systems Solutions
13 * @brief Utility functions
14 *
15 */
16 #include <stddef.h>
17 #include <stdbool.h>
18 #include "mpfs_hal/mss_hal.h"
19
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23
24 /*------------------------------------------------------------------------------
25 *
26 */
enable_interrupts(void)27 void enable_interrupts(void) {
28 __enable_irq();
29 }
30
31 /*------------------------------------------------------------------------------
32 *
33 */
disable_interrupts(void)34 uint64_t disable_interrupts(void) {
35 uint64_t psr;
36 psr = read_csr(mstatus);
37 __disable_irq();
38 return(psr);
39 }
40
41 /*------------------------------------------------------------------------------
42 *
43 */
restore_interrupts(uint64_t saved_psr)44 void restore_interrupts(uint64_t saved_psr) {
45 write_csr(mstatus, saved_psr);
46 }
47
48 /*------------------------------------------------------------------------------
49 * Disable all interrupts.
50 */
__disable_irq(void)51 void __disable_irq(void)
52 {
53 clear_csr(mstatus, MSTATUS_MIE);
54 clear_csr(mstatus, MSTATUS_MPIE);
55 }
56
__disable_all_irqs(void)57 void __disable_all_irqs(void)
58 {
59 __disable_irq();
60 write_csr(mie, 0x00U);
61 write_csr(mip, 0x00);
62 }
63
64 /*------------------------------------------------------------------------------
65 * Enable all interrupts.
66 */
__enable_irq(void)67 void __enable_irq(void)
68 {
69 set_csr(mstatus, MSTATUS_MIE); /* mstatus Register- Machine Interrupt Enable */
70 }
71
72 /*------------------------------------------------------------------------------
73 * Enable particular local interrupt
74 */
__enable_local_irq(uint8_t local_interrupt)75 void __enable_local_irq(uint8_t local_interrupt)
76 {
77 if((local_interrupt > (int8_t)0) && (local_interrupt <= LOCAL_INT_MAX))
78 {
79 set_csr(mie, (0x1LLU << (int8_t)(local_interrupt + 16U))); /* mie Register- Machine Interrupt Enable Register */
80 }
81 }
82
83 /*------------------------------------------------------------------------------
84 * Disable particular local interrupt
85 */
__disable_local_irq(uint8_t local_interrupt)86 void __disable_local_irq(uint8_t local_interrupt)
87 {
88 if((local_interrupt > (int8_t)0) && (local_interrupt <= LOCAL_INT_MAX))
89 {
90 clear_csr(mie, (0x1LLU << (int8_t)(local_interrupt + 16U))); /* mie Register- Machine Interrupt Enable Register */
91 }
92 }
93
94 /**
95 * readmcycle(void)
96 * @return returns the mcycle count from hart CSR
97 */
readmcycle(void)98 uint64_t readmcycle(void)
99 {
100 return (read_csr(mcycle));
101 }
102
sleep_ms(uint64_t msecs)103 void sleep_ms(uint64_t msecs)
104 {
105 uint64_t starttime = readmtime();
106 volatile uint64_t endtime = 0U;
107
108 while(endtime < (starttime+msecs)) {
109 endtime = readmtime();
110 }
111 }
112
113 /**
114 * sleep_cycles(uint64_t ncycles)
115 * @param number of cycles to sleep
116 */
sleep_cycles(uint64_t ncycles)117 void sleep_cycles(uint64_t ncycles)
118 {
119 uint64_t starttime = readmcycle();
120 volatile uint64_t endtime = 0U;
121
122 while(endtime < (starttime + ncycles)) {
123 endtime = readmcycle();
124 }
125 }
126
127 /**
128 * get_program_counter(void)
129 * @return returns the program counter
130 */
get_program_counter(void)131 __attribute__((aligned(16))) uint64_t get_program_counter(void)
132 {
133 uint64_t prog_counter;
134 asm volatile ("auipc %0, 0" : "=r"(prog_counter));
135 return (prog_counter);
136 }
137
138 /**
139 * get_stack_pointer(void)
140 * @return Return the stack pointer
141 */
get_stack_pointer(void)142 uint64_t get_stack_pointer(void)
143 {
144 uint64_t stack_pointer;
145 asm volatile ("addi %0, sp, 0" : "=r"(stack_pointer));
146 return (stack_pointer);
147 }
148
149 /**
150 * Return the tp register
151 * The tp register holds the value of the Hart Common memory HLS once not in an
152 * interrupt. If the tp value is used in an interrupt, it is saved first and
153 * restored on exit. This conforms to OpenSBI implementation.
154 *
155 * @return returns the tp register value
156 */
get_tp_reg(void)157 uint64_t get_tp_reg(void)
158 {
159 uint64_t tp_reg_val;
160 asm volatile ("addi %0, tp, 0" : "=r"(tp_reg_val));
161 return (tp_reg_val);
162 }
163
164 #ifdef PRINTF_DEBUG_SUPPORTED
display_address_of_interest(uint64_t * address_of_interest,int nb_locations)165 void display_address_of_interest(uint64_t * address_of_interest, int nb_locations) {
166 uint64_t * p_addr_of_interest = address_of_interest;
167 int inc;
168 mpfs_printf(" Displaying address of interest: 0x%lx\n", p_addr_of_interest);
169
170 for (inc = 0U; inc < nb_locations; ++inc) {
171 mpfs_printf(" address of interest: 0x%lx: 0x%lx\n", p_addr_of_interest, *p_addr_of_interest);
172 p_addr_of_interest = p_addr_of_interest + 8;
173 }
174 }
175 #endif
176
177 #ifdef __cplusplus
178 }
179 #endif
180