blob: b3444155b09ff5df18ca05b167bb2d02275cd644 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "handler.h"
#include "sw/device/lib/common.h"
#include "sw/device/lib/uart.h"
/**
* Default exception handler. Can be overidden.
*/
void handler_exception(void) __attribute__((aligned(4), interrupt, weak));
/**
* SW IRQ handler. Can be overidden.
*/
void handler_irq_software(void) __attribute__((aligned(4), interrupt, weak));
/**
* Timer IRQ handler. Can be overidden.
*/
void handler_irq_timer(void) __attribute__((aligned(4), interrupt, weak));
/**
* external IRQ handler. Can be overidden.
*/
void handler_irq_external(void) __attribute__((aligned(4), interrupt, weak));
/**
* Instruction access fault. Can be overriden.
*/
void handler_instr_acc_fault(void) __attribute__((aligned(4), interrupt, weak));
/**
* Illegal Instruction fault. Can be overriden.
*/
void handler_instr_ill_fault(void) __attribute__((aligned(4), interrupt, weak));
;
/**
* Breakpoint handler. Can be overriden.
*/
void handler_bkpt(void) __attribute__((aligned(4), interrupt, weak));
/**
* Load store unit fault. Can be overriden.
*/
void handler_lsu_fault(void) __attribute__((aligned(4), interrupt, weak));
/**
* Exception call handler. Can be overriden.
*/
void handler_ecall(void) __attribute__((aligned(4), interrupt, weak));
/**
* Return value of mtval
*/
static uint32_t get_mtval(void) {
uint32_t mtval;
asm volatile("csrr %0, mtval" : "=r"(mtval) : :);
return mtval;
}
/**
* Default Error Handling
* @param error message supplied by caller
* TODO - this will be soon by a real print formatting
*/
static void print_exc_msg(const char *msg) {
const uint32_t mtval = get_mtval();
uart_send_str((char *)msg);
uart_send_str("MTVAL value is ");
uart_send_uint(mtval, 32);
uart_send_str("\n");
while (1) {
};
}
// Below functions are default weak exception handlers meant to be overriden
void handler_exception(void) {
uint32_t mcause;
exc_id_t exc_cause;
asm volatile("csrr %0 , mcause" : "=r"(mcause) : :);
exc_cause = (exc_id_t)(mcause & kIdMax);
switch (exc_cause) {
case kInstMisa:
handler_instr_acc_fault();
break;
case kInstAccFault:
handler_instr_acc_fault();
break;
case kInstIllegalFault:
handler_instr_ill_fault();
break;
case kBkpt:
handler_bkpt();
break;
case kLoadAccFault:
handler_lsu_fault();
break;
case kStrAccFault:
handler_lsu_fault();
break;
case kECall:
handler_ecall();
break;
default:
while (1) {
};
}
}
void handler_irq_software(void) {
uart_send_str("Software IRQ triggered!\n");
while (1) {
}
}
void handler_irq_timer(void) {
uart_send_str("Timer IRQ triggered!\n");
while (1) {
}
}
void handler_irq_external(void) {
uart_send_str("External IRQ triggered!\n");
while (1) {
}
}
void handler_instr_acc_fault(void) {
const char fault_msg[] =
"Instruction access fault, mtval shows fault address\n";
print_exc_msg(fault_msg);
}
void handler_instr_ill_fault(void) {
const char fault_msg[] =
"Illegal Instruction fault, mtval shows instruction content\n";
print_exc_msg(fault_msg);
}
void handler_bkpt(void) {
const char exc_msg[] =
"Breakpoint triggerd, mtval shows the breakpoint address\n";
print_exc_msg(exc_msg);
}
void handler_lsu_fault(void) {
const char exc_msg[] = "Load/Store fault, mtval shows the fault address\n";
print_exc_msg(exc_msg);
}
void handler_ecall(void) {
uart_send_str("Environment call encountered\n");
while (1) {
}
}