#include <rt/arch/mix.h>
#include <rt/arch/mpu.h>
#include <rt/arch/mstatus.h>
#include <rt/arch/semihosting.h>
#include <rt/arch/trap.h>
#include <rt/log.h>
#include <rt/panic.h>
#include <rt/tick.h>
#include <rt/trace.h>
#include <rt/trap.h>
#include "mtime.h"
#include <stdint.h>
__attribute__((used)) RT_STACK(stack, 1024);
#define TIMER_FREQ 10000000UL
#define TIMER_INCREMENT (TIMER_FREQ / 1000)
__attribute__((noreturn)) void rt_panic(const char *msg)
{
semihosting_write0(msg);
semihosting_write0("\n");
semihosting_exception(ADP_STOPPED_OS_SPECIFIC);
}
__attribute__((noreturn)) void rt_trap(void)
{
semihosting_exit_success();
}
static void semihosting_write_hex(uint32_t value)
{
static const char hex_chars[] = "0123456789abcdef";
char buf[11];
buf[0] = '0';
buf[1] = 'x';
for (int i = 7; i >= 0; --i)
{
buf[2 + (7 - i)] = hex_chars[(value >> (i * 4)) & 0xf];
}
buf[10] = '\0';
semihosting_write0(buf);
}
void default_trap_handler(void);
RT_TRAP_HANDLER(default_trap_handler)
{
uint32_t mcause;
uint32_t mepc;
uint32_t mtval;
__asm__("csrr %0, mcause" : "=r"(mcause));
__asm__("csrr %0, mepc" : "=r"(mepc));
__asm__("csrr %0, mtval" : "=r"(mtval));
semihosting_write0("unhandled trap\nmcause: ");
semihosting_write_hex(mcause);
semihosting_write0("\nmepc: ");
semihosting_write_hex(mepc);
semihosting_write0("\nmtval: ");
semihosting_write_hex(mtval);
semihosting_write0("\n");
semihosting_exception(ADP_STOPPED_RUNTIME_ERROR_UNKNOWN);
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverride-init"
void (*const rt_trap_vector[])(void) = {
[0 ... 31] = default_trap_handler,
[RT_TRAP_ECALL_U] = rt_ecall_handler,
[RT_TRAP_ECALL_S] = rt_ecall_handler,
[RT_TRAP_ECALL_M] = rt_ecall_handler,
};
#pragma GCC diagnostic pop
void mtime_handler(void);
RT_INTERRUPT_HANDLER(mtime_handler)
{
rt_trace_interrupt_start(MIx_CAUSE_MTI);
uint32_t saved_mepc;
uint32_t saved_mie;
uint32_t saved_mstatus;
__asm__ __volatile__("csrr %0, mepc" : "=r"(saved_mepc));
__asm__ __volatile__("csrrc %0, mie, %1"
: "=r"(saved_mie)
: "r"(MIx_MSI | MIx_MTI));
__asm__ __volatile__("csrrs %0, mstatus, %1"
: "=r"(saved_mstatus)
: "i"(MSTATUS_MIE));
mtimecmp_set(mtimecmp() + TIMER_INCREMENT);
rt_tick_advance();
__asm__("csrw mstatus, %0" : : "r"(saved_mstatus));
__asm__("csrw mepc, %0" : : "r"(saved_mepc));
__asm__("csrw mie, %0" : : "r"(saved_mie));
rt_trace_interrupt_end(MIx_CAUSE_MTI);
}
void init(void);
void init(void)
{
const uint32_t static_region_start =
RT_MPU_TASK_REGION_START_ID + RT_MPU_NUM_TASK_REGIONS;
extern const uint32_t __rx_region__[];
extern const uint32_t __rx_region_size__;
rt_mpu_region_set(static_region_start + 0, (uintptr_t)__rx_region__,
(size_t)&__rx_region_size__,
RT_MPU_PMPCFG_R | RT_MPU_PMPCFG_X | RT_MPU_PMPCFG_NAPOT);
extern const uint32_t __ro_region__[];
extern const uint32_t __ro_region_size__;
rt_mpu_region_set(static_region_start + 1, (uintptr_t)__ro_region__,
(size_t)&__ro_region_size__,
RT_MPU_PMPCFG_R | RT_MPU_PMPCFG_NAPOT);
extern const uint32_t __rw_region__[];
extern const uint32_t __rw_region_size__;
rt_mpu_region_set(static_region_start + 2, (uintptr_t)__rw_region__,
(size_t)&__rw_region_size__,
RT_MPU_PMPCFG_R | RT_MPU_PMPCFG_W | RT_MPU_PMPCFG_NAPOT);
#if !RT_MPU_TASK_REGIONS_ENABLE
extern const uint32_t __task_stack_region__[];
extern const uint32_t __task_stack_region_size__;
rt_mpu_region_set(static_region_start + 3, (uintptr_t)__task_stack_region__,
(size_t)&__task_stack_region_size__, RT_MPU_ATTR_STACK);
#endif
rt_mpu_enable();
mtime_set(0);
mtimecmp_set(TIMER_INCREMENT);
__asm__("csrs mie, %0" : : "r"(MIx_MSI | MIx_MTI));
}
#if RT_LOG_ENABLE
void rt_logf(const char *format, ...)
{
(void)format;
}
void rt_log_flush(void)
{
}
#endif