#include "handlers.h"
#include <gic.h>
#include <rt/arch/coprocessor.h>
#include <rt/arch/mpu.h>
#include <rt/arch/semihosting.h>
#include <rt/arch/syscall.h>
#include <rt/cycle.h>
#include <rt/log.h>
#include <rt/panic.h>
#include <rt/stack.h>
#include <rt/start.h>
#include <rt/tick.h>
#include <rt/trace.h>
#include <rt/trap.h>
void rt_cycle_init(void)
{
}
uint32_t rt_cycle(void)
{
return (uint32_t)cntpct();
}
__attribute__((used)) RT_STACK(svc_stack, 1024);
__attribute__((used)) RT_STACK(irq_stack, 1024);
__attribute__((used)) RT_STACK(fiq_stack, 1024);
__attribute__((used)) RT_STACK(udf_stack, 1024);
__attribute__((used)) RT_STACK(abt_stack, 1024);
__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 dcache_invalidate_all(void)
{
uint32_t clidr_val = clidr();
for (unsigned level = 0; level < 7; ++level)
{
uint32_t ctype = (clidr_val >> (level * 3)) & 0x7;
if (ctype == 0)
{
break;
}
if (ctype == 1)
{
continue;
}
csselr_set(level << 1);
__asm__("isb" ::: "memory");
uint32_t ccsidr_val = ccsidr();
uint32_t line_size = (ccsidr_val & 0x7) + 4;
uint32_t assoc = ((ccsidr_val >> 3) & 0x3FF) + 1;
uint32_t num_sets = ((ccsidr_val >> 13) & 0x7FFF) + 1;
uint32_t way_shift = (uint32_t)__builtin_clz(assoc - 1);
uint32_t set_shift = line_size;
for (uint32_t way = 0; way < assoc; ++way)
{
for (uint32_t set = 0; set < num_sets; ++set)
{
uint32_t sw =
(way << way_shift) | (set << set_shift) | (level << 1);
dcisw_set(sw);
}
}
}
}
#define NUM_INTERRUPTS 1024
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverride-init"
void (*const gic_vector[NUM_INTERRUPTS])(void) = {
[0 ... NUM_INTERRUPTS - 1] = default_irq_handler,
[GIC_INTID_SYSCALL] = rt_syscall_irq_handler,
[GIC_INTID_TICK] = tick_irq_handler,
[GIC_INTID_GROUP0] = reserved_irq_handler,
[GIC_INTID_RESERVED] = reserved_irq_handler,
[GIC_INTID_NMI] = reserved_irq_handler,
[GIC_INTID_SPURIOUS] = spurious_irq_handler,
};
#pragma GCC diagnostic pop
void init(void);
void init(void)
{
iciallu_set(0);
dcache_invalidate_all();
bpiall_set(0);
__asm__("dsb; isb" ::: "memory");
uint32_t sctlr_flags = SCTLR_C | SCTLR_Z | SCTLR_I;
#ifdef __thumb__
sctlr_flags |= SCTLR_TE;
#endif
sctlr_oreq(sctlr_flags);
__asm__("dsb; isb" ::: "memory");
rt_mpu_attr_init();
rt_mpu_attr_set(0, RT_MPU_ATTR_WB_RWALLOC);
rt_mpu_attr_set(1, RT_MPU_ATTR_DEVICE_NGNRNE);
extern const uint32_t vector[];
extern const uint32_t __vector_size__[];
rt_mpu_region_set(0, (uintptr_t)vector, (size_t)__vector_size__,
RT_MPU_ATTR_RO | RT_MPU_ATTR_INDEX(0) |
RT_MPU_ATTR_ENABLE);
extern const uint32_t __ro_region__[];
extern const uint32_t __ro_region_size__[];
rt_mpu_region_set(1, (uintptr_t)__ro_region__, (size_t)__ro_region_size__,
RT_MPU_ATTR_RO | RT_MPU_ATTR_XN | RT_MPU_ATTR_INDEX(0) |
RT_MPU_ATTR_ENABLE);
extern const uint32_t __rx_region__[];
extern const uint32_t __rx_region_size__[];
rt_mpu_region_set(2, (uintptr_t)__rx_region__, (size_t)__rx_region_size__,
RT_MPU_ATTR_RO | RT_MPU_ATTR_INDEX(0) |
RT_MPU_ATTR_ENABLE);
extern const uint32_t __priv_rw_region__[];
extern const uint32_t __priv_rw_region_size__[];
rt_mpu_region_set(3, (uintptr_t)__priv_rw_region__,
(size_t)__priv_rw_region_size__,
RT_MPU_ATTR_RW_PRIV | RT_MPU_ATTR_XN |
RT_MPU_ATTR_INDEX(0) | RT_MPU_ATTR_ENABLE);
extern const uint32_t __rw_region__[];
extern const uint32_t __rw_region_size__[];
rt_mpu_region_set(4, (uintptr_t)__rw_region__, (size_t)__rw_region_size__,
RT_MPU_ATTR_RW | RT_MPU_ATTR_XN | RT_MPU_ATTR_INDEX(0) |
RT_MPU_ATTR_ENABLE);
#if !RT_MPU_TASK_REGIONS_ENABLE
extern const uint32_t __task_stack_region__[], __task_stack_region_size__[];
rt_mpu_region_set(5, (uintptr_t)__task_stack_region__,
(size_t)__task_stack_region_size__,
RT_MPU_ATTR_INDEX(0) | task_stack_priv_attr |
RT_MPU_ATTR_XN | RT_MPU_ATTR_PXN |
RT_MPU_ATTR_ENABLE);
#endif
rt_mpu_privileged_default_enable();
rt_mpu_enable();
GICD->ctlr = GICD_CTLR_ENABLE_GRP1;
GICR->rd.waker &= ~GICR_WAKER_PROCESSOR_SLEEP;
while (GICR->rd.waker & GICR_WAKER_CHILDREN_ASLEEP)
{
}
GICR->sgi.ipriorityr[GIC_INTID_SYSCALL] = GIC_PRIORITY_SYSCALL;
GICR->sgi.ipriorityr[GIC_INTID_TICK] = GIC_PRIORITY_TICK;
const uint32_t interrupts =
(UINT32_C(1) << GIC_INTID_SYSCALL) | (UINT32_C(1) << GIC_INTID_TICK);
GICR->sgi.igroupr0 = interrupts;
GICR->sgi.isenabler0 = interrupts;
icc_pmr_set(GIC_PRIORITY_IDLE);
icc_igrpen1_set(1);
cntp_cval_set(cntfrq() / UINT32_C(1000));
cntp_ctl_set(CNT_CTL_ENABLE);
}
#if RT_LOG_ENABLE
void rt_logf(const char *format, ...)
{
(void)format;
}
void rt_log_flush(void)
{
}
#endif