OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [lib/] [source/] [neorv32_rte.c] - Blame information for rev 20

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 zero_gravi
// #################################################################################################
2
// # << NEORV32: neorv32_rte.c - NEORV32 Runtime Environment >>                                    #
3
// # ********************************************************************************************* #
4
// # BSD 3-Clause License                                                                          #
5
// #                                                                                               #
6
// # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
7
// #                                                                                               #
8
// # Redistribution and use in source and binary forms, with or without modification, are          #
9
// # permitted provided that the following conditions are met:                                     #
10
// #                                                                                               #
11
// # 1. Redistributions of source code must retain the above copyright notice, this list of        #
12
// #    conditions and the following disclaimer.                                                   #
13
// #                                                                                               #
14
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
15
// #    conditions and the following disclaimer in the documentation and/or other materials        #
16
// #    provided with the distribution.                                                            #
17
// #                                                                                               #
18
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
19
// #    endorse or promote products derived from this software without specific prior written      #
20
// #    permission.                                                                                #
21
// #                                                                                               #
22
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
23
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
24
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
25
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
26
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
27
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
28
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
29
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
30
// # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
31
// # ********************************************************************************************* #
32
// # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
33
// #################################################################################################
34
 
35
 
36
/**********************************************************************//**
37
 * @file neorv32_rte.c
38
 * @author Stephan Nolting
39
 * @brief NEORV32 Runtime Environment.
40
 **************************************************************************/
41
 
42
#include "neorv32.h"
43
#include "neorv32_rte.h"
44
 
45 14 zero_gravi
/**********************************************************************//**
46
 * The >private< trap vector look-up table of the NEORV32 RTE.
47
 **************************************************************************/
48
static uint32_t __neorv32_rte_vector_lut[16] __attribute__((unused)); // trap handler vector table
49
 
50
// private functions
51
static void __attribute__((__interrupt__)) __neorv32_rte_core(void) __attribute__((aligned(16))) __attribute__((unused));
52 6 zero_gravi
static void __neorv32_rte_debug_exc_handler(void)     __attribute__((unused));
53
static void __neorv32_rte_print_true_false(int state) __attribute__((unused));
54 2 zero_gravi
 
55
 
56
/**********************************************************************//**
57 14 zero_gravi
 * Setup NEORV32 runtime environment.
58 2 zero_gravi
 *
59
 * @note This function installs a debug handler for ALL exception and interrupt sources, which
60 14 zero_gravi
 * gives detailed information about the exception/interrupt. Actual handler can be installed afterwards
61
 * via neorv32_rte_exception_install(uint8_t id, void (*handler)(void)).
62 2 zero_gravi
 **************************************************************************/
63 14 zero_gravi
void neorv32_rte_setup(void) {
64 2 zero_gravi
 
65 14 zero_gravi
  // configure trap handler base address
66
  uint32_t mtvec_base = (uint32_t)(&__neorv32_rte_core);
67
  neorv32_cpu_csr_write(CSR_MTVEC, mtvec_base);
68 2 zero_gravi
 
69
  // install debug handler for all sources
70 14 zero_gravi
  uint8_t id;
71
  for (id = 0; id < (sizeof(__neorv32_rte_vector_lut)/sizeof(__neorv32_rte_vector_lut[0])); id++) {
72
    neorv32_rte_exception_uninstall(id); // this will configure the debug handler
73 2 zero_gravi
  }
74
}
75
 
76
 
77
/**********************************************************************//**
78
 * Install exception handler function to NEORV32 runtime environment.
79
 *
80 17 zero_gravi
 * @note Interrupt sources have to be explicitly enabled by the user via the CSR.mie bits via neorv32_cpu_irq_enable(uint8_t irq_sel)
81
 * and the global interrupt enable bit mstatus.mie via neorv32_cpu_eint(void).
82 2 zero_gravi
 *
83 14 zero_gravi
 * @param[in] id Identifier (type) of the targeted exception. See #NEORV32_RTE_TRAP_enum.
84
 * @param[in] handler The actual handler function for the specified exception (function MUST be of type "void function(void);").
85 18 zero_gravi
 * @return 0 if success, 1 if error (invalid id or targeted exception not supported).
86 2 zero_gravi
 **************************************************************************/
87 14 zero_gravi
int neorv32_rte_exception_install(uint8_t id, void (*handler)(void)) {
88 2 zero_gravi
 
89
  // id valid?
90 14 zero_gravi
  if ((id == RTE_TRAP_I_MISALIGNED) || (id == RTE_TRAP_I_ACCESS)     || (id == RTE_TRAP_I_ILLEGAL) ||
91
      (id == RTE_TRAP_BREAKPOINT)   || (id == RTE_TRAP_L_MISALIGNED) || (id == RTE_TRAP_L_ACCESS)  ||
92
      (id == RTE_TRAP_S_MISALIGNED) || (id == RTE_TRAP_S_ACCESS)     || (id == RTE_TRAP_MENV_CALL) ||
93
      (id == RTE_TRAP_MSI)          || (id == RTE_TRAP_MTI)          || (id == RTE_TRAP_MEI)       ||
94
      (id == RTE_TRAP_FIRQ_0)       || (id == RTE_TRAP_FIRQ_1)       || (id == RTE_TRAP_FIRQ_2)    || (id == RTE_TRAP_FIRQ_3)) {
95 2 zero_gravi
 
96 14 zero_gravi
    __neorv32_rte_vector_lut[id]  = (uint32_t)handler; // install handler
97
 
98 2 zero_gravi
    return 0;
99
  }
100
  return 1;
101
}
102
 
103
 
104
/**********************************************************************//**
105
 * Uninstall exception handler function from NEORV32 runtime environment, which was
106 14 zero_gravi
 * previously installed via neorv32_rte_exception_install(uint8_t id, void (*handler)(void)).
107 2 zero_gravi
 *
108 17 zero_gravi
 * @note Interrupt sources have to be explicitly disabled by the user via the CSR.mie bits via neorv32_cpu_irq_disable(uint8_t irq_sel)
109
 * and/or the global interrupt enable bit mstatus.mie via neorv32_cpu_dint(void).
110 2 zero_gravi
 *
111 14 zero_gravi
 * @param[in] id Identifier (type) of the targeted exception. See #NEORV32_RTE_TRAP_enum.
112 18 zero_gravi
 * @return 0 if success, 1 if error (invalid id or targeted exception not supported).
113 2 zero_gravi
 **************************************************************************/
114 14 zero_gravi
int neorv32_rte_exception_uninstall(uint8_t id) {
115 2 zero_gravi
 
116
  // id valid?
117 14 zero_gravi
  if ((id == RTE_TRAP_I_MISALIGNED) || (id == RTE_TRAP_I_ACCESS)     || (id == RTE_TRAP_I_ILLEGAL) ||
118
      (id == RTE_TRAP_BREAKPOINT)   || (id == RTE_TRAP_L_MISALIGNED) || (id == RTE_TRAP_L_ACCESS)  ||
119
      (id == RTE_TRAP_S_MISALIGNED) || (id == RTE_TRAP_S_ACCESS)     || (id == RTE_TRAP_MENV_CALL) ||
120
      (id == RTE_TRAP_MSI)          || (id == RTE_TRAP_MTI)          || (id == RTE_TRAP_MEI)       ||
121
      (id == RTE_TRAP_FIRQ_0)       || (id == RTE_TRAP_FIRQ_1)       || (id == RTE_TRAP_FIRQ_2)    || (id == RTE_TRAP_FIRQ_3)) {
122 2 zero_gravi
 
123 14 zero_gravi
    __neorv32_rte_vector_lut[id] = (uint32_t)(&__neorv32_rte_debug_exc_handler); // use dummy handler in case the exception is accidently triggered
124 2 zero_gravi
 
125
    return 0;
126
  }
127
  return 1;
128
}
129
 
130
 
131
/**********************************************************************//**
132 14 zero_gravi
 * This is the core of the NEORV32 RTE.
133
 *
134
 * @note This function must no be explicitly used by the user.
135
 * @warning When using the the RTE, this function is the ONLY function that can use the 'interrupt' attribute!
136 2 zero_gravi
 **************************************************************************/
137 14 zero_gravi
static void __attribute__((__interrupt__)) __attribute__((aligned(16)))  __neorv32_rte_core(void) {
138 2 zero_gravi
 
139 14 zero_gravi
  register uint32_t rte_mepc   = neorv32_cpu_csr_read(CSR_MEPC);
140
  register uint32_t rte_mcause = neorv32_cpu_csr_read(CSR_MCAUSE);
141
 
142
  // compute return address
143
  if ((rte_mcause & 0x80000000) == 0) { // modify pc only if exception
144
 
145
    // get low half word of faulting instruction
146
    register uint32_t rte_trap_inst;
147
    asm volatile ("lh %[result], 0(%[input_i])" : [result] "=r" (rte_trap_inst) : [input_i] "r" (rte_mepc));
148
 
149
    if ((rte_trap_inst & 3) == 3) { // faulting instruction is uncompressed instruction
150
      rte_mepc += 4;
151
    }
152
    else { // faulting instruction is compressed instruction
153
      rte_mepc += 2;
154
    }
155
 
156
    // store new return address
157
    neorv32_cpu_csr_write(CSR_MEPC, rte_mepc);
158
  }
159
 
160
  // find according trap handler
161
  register uint32_t rte_handler = (uint32_t)(&__neorv32_rte_debug_exc_handler);
162
  switch (rte_mcause) {
163
    case TRAP_CODE_I_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_MISALIGNED]; break;
164
    case TRAP_CODE_I_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ACCESS]; break;
165
    case TRAP_CODE_I_ILLEGAL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ILLEGAL]; break;
166
    case TRAP_CODE_BREAKPOINT:   rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_BREAKPOINT]; break;
167
    case TRAP_CODE_L_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_L_MISALIGNED]; break;
168
    case TRAP_CODE_L_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_L_ACCESS]; break;
169
    case TRAP_CODE_S_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_S_MISALIGNED]; break;
170
    case TRAP_CODE_S_ACCESS:     rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_S_ACCESS]; break;
171
    case TRAP_CODE_MENV_CALL:    rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MENV_CALL]; break;
172
    case TRAP_CODE_MSI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MSI]; break;
173
    case TRAP_CODE_MTI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MTI]; break;
174
    case TRAP_CODE_MEI:          rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MEI]; break;
175
    case TRAP_CODE_FIRQ_0:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_0]; break;
176
    case TRAP_CODE_FIRQ_1:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_1]; break;
177
    case TRAP_CODE_FIRQ_2:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_2]; break;
178
    case TRAP_CODE_FIRQ_3:       rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_3]; break;
179
    default: break;
180
  }
181
 
182
  // execute handler
183
  void (*handler_pnt)(void);
184
  handler_pnt = (void*)rte_handler;
185
  (*handler_pnt)();
186 2 zero_gravi
}
187
 
188
 
189
/**********************************************************************//**
190
 * NEORV32 runtime environment: Debug exception handler, printing various exception/interrupt information via UART.
191 14 zero_gravi
 * @note This function is used by neorv32_rte_exception_uninstall(void) only.
192 2 zero_gravi
 **************************************************************************/
193
static void __neorv32_rte_debug_exc_handler(void) {
194
 
195 15 zero_gravi
  // intro
196
  neorv32_uart_printf("<RTE> ");
197 2 zero_gravi
 
198 15 zero_gravi
  // cause
199 7 zero_gravi
  register uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
200
  switch (trap_cause) {
201 14 zero_gravi
    case TRAP_CODE_I_MISALIGNED: neorv32_uart_printf("Instruction address misaligned"); break;
202
    case TRAP_CODE_I_ACCESS:     neorv32_uart_printf("Instruction access fault"); break;
203
    case TRAP_CODE_I_ILLEGAL:    neorv32_uart_printf("Illegal instruction"); break;
204 18 zero_gravi
    case TRAP_CODE_BREAKPOINT:   neorv32_uart_printf("Breakpoint"); break;
205 14 zero_gravi
    case TRAP_CODE_L_MISALIGNED: neorv32_uart_printf("Load address misaligned"); break;
206
    case TRAP_CODE_L_ACCESS:     neorv32_uart_printf("Load access fault"); break;
207
    case TRAP_CODE_S_MISALIGNED: neorv32_uart_printf("Store address misaligned"); break;
208
    case TRAP_CODE_S_ACCESS:     neorv32_uart_printf("Store access fault"); break;
209 18 zero_gravi
    case TRAP_CODE_MENV_CALL:    neorv32_uart_printf("Environment call"); break;
210 14 zero_gravi
    case TRAP_CODE_MSI:          neorv32_uart_printf("Machine software interrupt"); break;
211
    case TRAP_CODE_MTI:          neorv32_uart_printf("Machine timer interrupt"); break;
212
    case TRAP_CODE_MEI:          neorv32_uart_printf("Machine external interrupt"); break;
213 18 zero_gravi
    case TRAP_CODE_FIRQ_0:       neorv32_uart_printf("Fast interrupt 0"); break;
214
    case TRAP_CODE_FIRQ_1:       neorv32_uart_printf("Fast interrupt 1"); break;
215
    case TRAP_CODE_FIRQ_2:       neorv32_uart_printf("Fast interrupt 2"); break;
216
    case TRAP_CODE_FIRQ_3:       neorv32_uart_printf("Fast interrupt 3"); break;
217 14 zero_gravi
    default:                     neorv32_uart_printf("Unknown (0x%x)", trap_cause); break;
218 2 zero_gravi
  }
219
 
220 15 zero_gravi
  // address
221
  register uint32_t trap_addr  = neorv32_cpu_csr_read(CSR_MEPC);
222
  register uint32_t trap_inst;
223 2 zero_gravi
 
224 15 zero_gravi
  asm volatile ("lh %[result], 0(%[input_i])" : [result] "=r" (trap_inst) : [input_i] "r" (trap_addr));
225
 
226
  if ((trap_cause & 0x80000000) == 0) {
227
    if ((trap_inst & 3) == 3) {
228
      trap_addr -= 4;
229
    }
230
    else {
231
      trap_addr -= 2;
232
    }
233 2 zero_gravi
  }
234 18 zero_gravi
  neorv32_uart_printf(" @ 0x%x, MTVAL=0x%x </RTE>", trap_addr, neorv32_cpu_csr_read(CSR_MTVAL));
235 6 zero_gravi
}
236
 
237
 
238
/**********************************************************************//**
239
 * NEORV32 runtime environment: Print hardware configuration information via UART
240
 **************************************************************************/
241
void neorv32_rte_print_hw_config(void) {
242
 
243
  uint32_t tmp;
244
  int i;
245
  char c;
246
 
247
  neorv32_uart_printf("\n\n<< NEORV32 Hardware Configuration Overview >>\n");
248
 
249
  // CPU configuration
250
  neorv32_uart_printf("\n-- Central Processing Unit --\n");
251
 
252
  // Hart ID
253 12 zero_gravi
  neorv32_uart_printf("Hart ID:          %u\n", neorv32_cpu_csr_read(CSR_MHARTID));
254 6 zero_gravi
 
255 12 zero_gravi
  // Custom user code
256
  neorv32_uart_printf("User code:        0x%x\n", SYSINFO_USER_CODE);
257
 
258 6 zero_gravi
  // HW version
259
  neorv32_uart_printf("Hardware version: ");
260 12 zero_gravi
  neorv32_rte_print_hw_version();
261 6 zero_gravi
  neorv32_uart_printf(" (0x%x)\n", neorv32_cpu_csr_read(CSR_MIMPID));
262
 
263
  // CPU architecture
264
  neorv32_uart_printf("Architecture:     ");
265
  tmp = neorv32_cpu_csr_read(CSR_MISA);
266
  tmp = (tmp >> 30) & 0x03;
267
  if (tmp == 0) {
268
    neorv32_uart_printf("unknown");
269
  }
270
  if (tmp == 1) {
271
    neorv32_uart_printf("RV32");
272
  }
273
  if (tmp == 2) {
274
    neorv32_uart_printf("RV64");
275
  }
276
  if (tmp == 3) {
277
    neorv32_uart_printf("RV128");
278
  }
279
 
280
  // CPU extensions
281 20 zero_gravi
  neorv32_uart_printf(" + ");
282 6 zero_gravi
  tmp = neorv32_cpu_csr_read(CSR_MISA);
283
  for (i=0; i<26; i++) {
284
    if (tmp & (1 << i)) {
285
      c = (char)('A' + i);
286
      neorv32_uart_putc(c);
287
      neorv32_uart_putc(' ');
288
    }
289
  }
290
  neorv32_uart_printf("(0x%x)\n", tmp);
291
 
292
 
293 15 zero_gravi
  // Misc
294
  neorv32_uart_printf("\n-- System --\n");
295
  neorv32_uart_printf("Clock: %u Hz\n", SYSINFO_CLK);
296
 
297
 
298 6 zero_gravi
  // Memory configuration
299 15 zero_gravi
  neorv32_uart_printf("\n-- Processor Memory Configuration --\n");
300 6 zero_gravi
 
301 12 zero_gravi
  uint32_t size = SYSINFO_ISPACE_SIZE;
302
  uint32_t base = SYSINFO_ISPACE_BASE;
303 6 zero_gravi
  neorv32_uart_printf("Instruction memory:   %u bytes @ 0x%x\n", size, base);
304
  neorv32_uart_printf("Internal IMEM:        ");
305 12 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM));
306 6 zero_gravi
  neorv32_uart_printf("Internal IMEM as ROM: ");
307 12 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM));
308 6 zero_gravi
 
309 12 zero_gravi
  size = SYSINFO_DSPACE_SIZE;
310
  base = SYSINFO_DSPACE_BASE;
311 6 zero_gravi
  neorv32_uart_printf("Data memory:          %u bytes @ 0x%x\n", size, base);
312
  neorv32_uart_printf("Internal DMEM:        ");
313 12 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_DMEM));
314 6 zero_gravi
 
315
  neorv32_uart_printf("Bootloader:           ");
316 12 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_BOOTLOADER));
317 6 zero_gravi
 
318
  neorv32_uart_printf("External interface:   ");
319 12 zero_gravi
  __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT));
320 6 zero_gravi
 
321
  // peripherals
322 15 zero_gravi
  neorv32_uart_printf("\n-- Processor Peripherals --\n");
323
 
324 12 zero_gravi
  tmp = SYSINFO_FEATURES;
325 6 zero_gravi
 
326
  neorv32_uart_printf("GPIO:    ");
327 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_GPIO));
328 6 zero_gravi
 
329
  neorv32_uart_printf("MTIME:   ");
330 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_MTIME));
331 6 zero_gravi
 
332
  neorv32_uart_printf("UART:    ");
333 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_UART));
334 6 zero_gravi
 
335
  neorv32_uart_printf("SPI:     ");
336 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_SPI));
337 6 zero_gravi
 
338
  neorv32_uart_printf("TWI:     ");
339 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TWI));
340 6 zero_gravi
 
341
  neorv32_uart_printf("PWM:     ");
342 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_PWM));
343 6 zero_gravi
 
344
  neorv32_uart_printf("WDT:     ");
345 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_WDT));
346 6 zero_gravi
 
347
  neorv32_uart_printf("TRNG:    ");
348 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TRNG));
349 6 zero_gravi
 
350
  neorv32_uart_printf("DEVNULL: ");
351 12 zero_gravi
  __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_DEVNULL));
352 6 zero_gravi
}
353
 
354
 
355
/**********************************************************************//**
356
 * NEORV32 runtime environment: Private function to print true or false.
357
 * @note This function is used by neorv32_rte_print_hw_config(void) only.
358
 *
359
 * @param[in] state Print TRUE when !=0, print FALSE when 0
360
 **************************************************************************/
361
static void __neorv32_rte_print_true_false(int state) {
362
 
363
  if (state) {
364
    neorv32_uart_printf("True\n");
365
  }
366 2 zero_gravi
  else {
367 6 zero_gravi
    neorv32_uart_printf("False\n");
368 2 zero_gravi
  }
369 6 zero_gravi
}
370 2 zero_gravi
 
371
 
372 6 zero_gravi
/**********************************************************************//**
373 12 zero_gravi
 * NEORV32 runtime environment: Function to show the processor version in human-readable format.
374 6 zero_gravi
 **************************************************************************/
375 12 zero_gravi
void neorv32_rte_print_hw_version(void) {
376 6 zero_gravi
 
377
  uint32_t i;
378
  char tmp, cnt;
379
  uint32_t version = neorv32_cpu_csr_read(CSR_MIMPID);
380
 
381
  for (i=0; i<4; i++) {
382
 
383
    tmp = (char)(version >> (24 - 8*i));
384
 
385
    // serial division
386
    cnt = 0;
387
    while (tmp >= 10) {
388
      tmp = tmp - 10;
389
      cnt++;
390
    }
391
 
392
    if (cnt) {
393
      neorv32_uart_putc('0' + cnt);
394
    }
395
    neorv32_uart_putc('0' + tmp);
396
    if (i < 3) {
397
      neorv32_uart_putc('.');
398
    }
399
  }
400 2 zero_gravi
}
401 11 zero_gravi
 
402
 
403
/**********************************************************************//**
404
 * NEORV32 runtime environment: Print project credits
405
 **************************************************************************/
406
void neorv32_rte_print_credits(void) {
407
 
408
  neorv32_uart_print("\n\nThe NEORV32 Processor Project\n"
409
                     "by Stephan Nolting\n"
410
                     "https://github.com/stnolting/neorv32\n"
411
                     "made in Hannover, Germany\n\n");
412
}
413
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.