summaryrefslogtreecommitdiff
path: root/ports/risc-v64/gnu/example_build/erbium/trap.c
blob: d839e6eabd767a6af33514a7fbbc5b0bd9bc1508 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/***************************************************************************
 * Copyright (c) 2026 Eclipse ThreadX contributors
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License which is available at
 * https://opensource.org/licenses/MIT.
 *
 * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5).
 * The AI-generated portions may be considered public domain (CC0-1.0)
 * and not subject to the project's licence. The human contributor has
 * reviewed and verified that the code is correct.
 *
 * SPDX-License-Identifier: MIT and CC0-1.0
 **************************************************************************/

/* Machine-mode trap dispatcher for the Erbium example.  */

#include "csr.h"
#include "uart.h"
#include "hwtimer.h"
#include "plic.h"
#include <stdint.h>
#include <tx_api.h>

#define MCAUSE_INT_BIT          ((uintptr_t)1 << (__riscv_xlen - 1))
#define MCAUSE_M_TIMER          (MCAUSE_INT_BIT | 7u)
#define MCAUSE_M_EXTERNAL       (MCAUSE_INT_BIT | 11u)

extern void _tx_timer_interrupt(void);

static void print_hex(uintptr_t val)
{
    const char digits[] = "0123456789ABCDEF";

    uart_putc('0');
    uart_putc('x');
    for (int i = (int)(sizeof(uintptr_t) * 2) - 1; i >= 0; i--)
        uart_putc(digits[(val >> (i * 4)) & 0xFu]);
    uart_putc('\r');
    uart_putc('\n');
}

static void trap_halt(const char *reason, uintptr_t mcause, uintptr_t mepc, uintptr_t mtval)
{
    uart_puts(reason);
    uart_puts("mcause:");
    print_hex(mcause);
    uart_puts("mepc:");
    print_hex(mepc);
    uart_puts("mtval:");
    print_hex(mtval);

    /* Spin rather than WFI, as everywhere else in this example.  */
    while (1)
        ;
}

void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval)
{
    if (mcause == MCAUSE_M_TIMER)
    {
        hwtimer_handler();
        _tx_timer_interrupt();
    }
    else if (mcause == MCAUSE_M_EXTERNAL)
    {
        if (plic_irq_intr() != 0)
            trap_halt("[INTERRUPT]: external interrupt not handled, halting", mcause, mepc, mtval);
    }
    else if ((mcause & MCAUSE_INT_BIT) != 0u)
    {
        trap_halt("[INTERRUPT]: unexpected interrupt, halting", mcause, mepc, mtval);
    }
    else
    {
        trap_halt("[EXCEPTION]: unhandled exception, halting", mcause, mepc, mtval);
    }
}