#include <rt/arch/csr.h>
#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();
}
void default_trap_handler(void);
RT_TRAP_HANDLER(default_trap_handler)
{
semihosting_write0("unhandled trap\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);
uintptr_t saved_mepc = csrr(CSR_MEPC);
uintptr_t saved_mie = csrrc(CSR_MIE, MIx_MSI | MIx_MTI);
uintptr_t saved_mstatus = csrrs(CSR_MSTATUS, MSTATUS_MIE);
mtimecmp_set(mtimecmp() + TIMER_INCREMENT);
rt_tick_advance();
csrw(CSR_MSTATUS, saved_mstatus);
csrw(CSR_MEPC, saved_mepc);
csrw(CSR_MIE, saved_mie);
rt_trace_interrupt_end(MIx_CAUSE_MTI);
}
#if __has_attribute(optimize)
__attribute__((optimize("O3")))
#endif
__attribute__((noinline)) static void lock_static_regions(void)
{
for (uint32_t i = RT_MPU_TASK_REGION_START_ID + RT_MPU_NUM_TASK_REGIONS;
i < RT_MPU_NUM_REGIONS; ++i)
{
rt_mpu_region_set(i, 0UL, 0UL, RT_MPU_ATTR_NO_ACCESS_LOCKED);
}
}
void init(void);
void init(void)
{
const uint32_t static_region_start =
RT_MPU_TASK_REGION_START_ID + RT_MPU_NUM_TASK_REGIONS;
csrs(CSR_MSECCFG, MSECCFG_RLB);
lock_static_regions();
extern const uint32_t __x_region__[];
extern const uint32_t __x_region_end__[];
rt_mpu_region_set(static_region_start + 0, (uintptr_t)__x_region__,
(uintptr_t)__x_region_end__ - (uintptr_t)__x_region__,
RT_MPU_ATTR_M_X_LOCKED | RT_MPU_ATTR_NAPOT);
csrs(CSR_MSECCFG, MSECCFG_MML);
rt_mpu_region_set_attr(static_region_start + 0,
RT_MPU_ATTR_X_LOCKED | RT_MPU_ATTR_NAPOT);
extern const uint32_t __ro_region__[];
extern const uint32_t __ro_region_end__[];
rt_mpu_region_set(static_region_start + 1, (uintptr_t)__ro_region__,
(uintptr_t)__ro_region_end__ - (uintptr_t)__ro_region__,
RT_MPU_ATTR_RO_LOCKED | RT_MPU_ATTR_NAPOT);
extern const uint32_t __rw_region__[];
extern const uint32_t __rw_region_end__[];
rt_mpu_region_set(static_region_start + 2, (uintptr_t)__rw_region__,
(uintptr_t)__rw_region_end__ - (uintptr_t)__rw_region__,
RT_MPU_ATTR_RW | RT_MPU_ATTR_NAPOT);
#if !RT_MPU_TASK_REGIONS_ENABLE
extern const uint32_t __task_stack_region__[];
extern const uint32_t __task_stack_region_end__[];
rt_mpu_region_set(static_region_start + 3, (uintptr_t)__task_stack_region__,
(uintptr_t)__task_stack_region_end__ -
(uintptr_t)__task_stack_region__,
RT_MPU_ATTR_STACK);
#endif
extern const uint32_t __priv_rw_region__[];
extern const uint32_t __priv_rw_region_end__[];
rt_mpu_region_set(static_region_start + 4, (uintptr_t)__priv_rw_region__,
(uintptr_t)__priv_rw_region_end__ -
(uintptr_t)__priv_rw_region__,
RT_MPU_ATTR_M_RW_LOCKED | RT_MPU_ATTR_NAPOT);
extern const uint32_t __priv_ro_region__[];
extern const uint32_t __priv_ro_region_end__[];
rt_mpu_region_set(static_region_start + 5, (uintptr_t)__priv_ro_region__,
(uintptr_t)__priv_ro_region_end__ -
(uintptr_t)__priv_ro_region__,
RT_MPU_ATTR_M_RO_LOCKED | RT_MPU_ATTR_NAPOT);
rt_mpu_region_set(static_region_start + 6, CLINT_BASE, CLINT_SIZE,
RT_MPU_ATTR_M_RW_LOCKED | RT_MPU_ATTR_NAPOT);
csrw(CSR_MSECCFG, MSECCFG_MML | MSECCFG_MMWP);
__asm__("fence" ::: "memory");
mtime_set(0);
mtimecmp_set(TIMER_INCREMENT);
csrs(CSR_MIE, MIx_MSI | MIx_MTI);
}
#if RT_LOG_ENABLE
void rt_logf(const char *format, ...)
{
(void)format;
}
void rt_log_flush(void)
{
}
#endif