cleans up moonlight dir

This commit is contained in:
2026-03-21 15:40:54 +01:00
parent ba1b9c44ee
commit 083565251e
20 changed files with 11 additions and 9 deletions

View File

@@ -0,0 +1,39 @@
#include "hwtimer.h"
#include "csr.h"
#include "platform.h"
#include "uart.h"
#include <stdio.h>
#include <stdarg.h>
// needed by picolibc/port.c
int uart_putc(int ch) {
int intr_enable = riscv_mintr_get();
riscv_mintr_off();
uart_write(uart, ch);
riscv_mintr_restore(intr_enable);
return 1;
}
int uart_getc(void) {
int intr_enable = riscv_mintr_get();
riscv_mintr_off();
int ch = uart_read(uart);
riscv_mintr_restore(intr_enable);
return ch;
}
int uart_init(void) {
puts("[UART0] : Uart Init Done, this is Test output!");
return 0;
};
int board_init(void) {
int ret;
ret = uart_init();
if(ret)
return ret;
ret = hwtimer_init();
if(ret)
return ret;
return 0;
}

128
port/moonlight/src/bootup.c Normal file
View File

@@ -0,0 +1,128 @@
/*
Simple C++ startup routine to setup CRT
SPDX-License-Identifier: Unlicense
(https://five-embeddev.com/ | http://www.shincbm.com/)
*/
#include <stdint.h>
#include <string.h>
#include <picotls.h>
#include <tx_port.h>
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C extern
#endif
// Generic C function pointer.
typedef void(*function_t)(void) ;
// These symbols are defined by the linker script.
// See linker.lds
EXTERN_C uint8_t __bss_start;
EXTERN_C uint8_t __bss_end;
EXTERN_C const uint8_t __data_source;
EXTERN_C uint8_t __data_start;
EXTERN_C uint8_t __data_end;
EXTERN_C const uint8_t __data_source;
EXTERN_C uint8_t __tbss_start;
EXTERN_C uintptr_t __tbss_size;
EXTERN_C const uint8_t __tdata_source;
EXTERN_C uint8_t __tls_base;
EXTERN_C uintptr_t __tdata_size;
EXTERN_C function_t __init_array_start;
EXTERN_C function_t __init_array_end;
EXTERN_C function_t __fini_array_start;
EXTERN_C function_t __fini_array_end;
// This function will be placed by the linker script according to the section
// Raw function 'called' by the CPU with no runtime.
EXTERN_C void _start(void) __attribute__ ((naked,section(".text.boot")));
// Entry and exit points as C functions.
EXTERN_C void _initialize(void) __attribute__ ((noreturn,section(".text.boot")));
EXTERN_C void _exit(int exit_code) __attribute__ ((noreturn,noinline,weak));
// Standard entry point, no arguments.
extern int main(void);
// The linker script will place this in the reset entry point.
// It will be 'called' with no stack or C runtime configuration.
// tp will not be initialized
void _start(void) {
// Setup SP and GP
// The locations are defined in the linker script
__asm__ volatile (
".option push;"
// The 'norelax' option is critical here.
// Without 'norelax' the global pointer will
// be loaded relative to the global pointer!
".option norelax;"
"la gp, __global_pointer$;"
".option pop;"
"la sp, _sp;"
#if defined(__riscv_zicsr)
"csrr t0, mhartid;"
#else
"li t0, 0;"
#endif
"la t1, __stack_size;"
"la t1, __stack_size;"
"la sp, _sp;"
// Loop incase M extension is not present
"1:;"
"beqz t0, 2f;"
"sub sp, sp, t1;"
"addi t0, t0, -1;"
"j 1b;"
"2:;"
#ifdef TX_THREAD_SMP_MAX_CORES
"call _tx_thread_smp_initialize_wait;"
#endif
"jal zero, _initialize;"
: /* output: none %0 */
: /* input: none */
: /* clobbers: none */);
// This point will not be executed, _initialize() will be called with no return.
}
// At this point we have a stack and global poiner, but no access to global variables.
void _initialize(void) {
// Init memory regions
// Clear the .bss section (global variables with no initial values)
memset((void*) &__bss_start, 0, (&__bss_end - &__bss_start));
// Initialize the .data section (global variables with initial values)
memcpy((void*)&__data_start, (const void*)&__data_source, (&__data_end - &__data_start));
// Clear the .tbss section (thread local variables with no initial values)
memset((void*) &__tbss_start, 0, __tbss_size);
// Initialize the .tls section (thread local variables with initial values)
memcpy((void*) &__tls_base, (const void*)&__tdata_source, __tdata_size);
// Call constructors
for (const function_t* entry=&__init_array_start;
entry < &__init_array_end;
++entry) {
(*entry)();
}
#ifdef __THREAD_LOCAL_STORAGE
_set_tls(__tls_base)
#endif
int rc = main();
// Call destructors
for (const function_t* entry=&__fini_array_start;
entry < &__fini_array_end;
++entry) {
(*entry)();
}
_exit(rc);
}
// This should never be called. Busy loop with the CPU in idle state.
void _exit(int exit_code) {
(void)exit_code;
// Halt
while (1) {
__asm__ volatile ("wfi");
}
}

View File

@@ -0,0 +1,83 @@
#include <stdint.h>
#include <stdio.h>
#include "riscv-traps.h"
#include "riscv-csr.h"
// Expect this to increment one time per second - inside exception handler, after each return of MTI handler.
static volatile uint64_t ecall_count = 0;
#ifdef NX_DEBUG
#define PUTS(STR) puts(STR)
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PUTS(STR)
#define PRINTF(...)
#endif
void exception(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) {
switch(mcause) {
case RISCV_EXCP_INSTRUCTION_ADDRESS_MISALIGNED: {
puts("[EXCEPTION] : Instruction address misaligned\n");
break;
}
case RISCV_EXCP_INSTRUCTION_ACCESS_FAULT: {
puts("[EXCEPTION] : Instruction access fault\n");
break;
}
case RISCV_EXCP_ILLEGAL_INSTRUCTION: {
puts("[EXCEPTION] : Illegal Instruction\n");
break;
}
case RISCV_EXCP_BREAKPOINT: {
puts("[EXCEPTION] : Breakpoint\n");
break;
}
case RISCV_EXCP_LOAD_ADDRESS_MISALIGNED: {
puts("[EXCEPTION] : Load address misaligned");
break;
}
case RISCV_EXCP_LOAD_ACCESS_FAULT: {
puts("[EXCEPTION] : Load access fault\n");
break;
}
case RISCV_EXCP_STORE_AMO_ADDRESS_MISALIGNED: {
puts("[EXCEPTION] : Store/AMO address misaligned");
break;
}
case RISCV_EXCP_STORE_AMO_ACCESS_FAULT: {
puts("[EXCEPTION] : Store/AMO access fault\n");
break;
}
case RISCV_EXCP_ENVIRONMENT_CALL_FROM_U_MODE: {
puts("[EXCEPTION] : Environment call from U-mode\n");
break;
}
case RISCV_EXCP_ENVIRONMENT_CALL_FROM_S_MODE: {
puts("[EXCEPTION] : Environment call from S-mode\n");
break;
}
case RISCV_EXCP_ENVIRONMENT_CALL_FROM_M_MODE: {
puts("[EXCEPTION] : Environment call from M-mode\n");
ecall_count++;
csr_write_mepc(mepc+4);
break;
}
case RISCV_EXCP_INSTRUCTION_PAGE_FAULT: {
puts("[EXCEPTION] : Instruction page fault\n");
break;
}
case RISCV_EXCP_LOAD_PAGE_FAULT: {
puts("[EXCEPTION] : Load page fault\n");
break;
}
case RISCV_EXCP_STORE_AMO_PAGE_FAULT: {
puts("[EXCEPTION] : Store/AMO page fault\n");
break;
}
default: {
printf("[EXCEPTION] : Unknown trap cause: %lu\n", mcause);
}
}
printf("[EXCEPTION] : PC: 0x%x\n", mepc);
printf("[EXCEPTION] : Addr: 0x%x\n", mtval);
while(1)
;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
#include "hwtimer.h"
#include "platform.h"
#include "riscv-traps.h"
#include <stdint.h>
#include <stdio.h>
#include <tx_api.h>
#include <tx_port.h>
#if __riscv_xlen == 64
#define INTERRUPT_BIT 0x8000000000000000ull
#else
#define INTERRUPT_BIT 0x80000000ull
#endif
#define OS_IS_INTERRUPT(mcause) (mcause & INTERRUPT_BIT)
#define OS_IS_TICK_INT(mcause) (mcause == (0x7 | INTERRUPT_BIT))
#define OS_IS_SOFT_INT(mcause) (mcause == (0x3 | INTERRUPT_BIT))
#define OS_IS_EXT_INT(mcause) (mcause == (0xb | INTERRUPT_BIT))
extern void _tx_timer_interrupt(void);
extern uintptr_t exception(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval);
void (*irq_handler[__riscv_xlen])();
int register_irq_handler(unsigned irq_num, void (*handler)()) {
if(irq_num<__riscv_xlen){
irq_handler[irq_num] = handler;
return 1;
}
return 0;
}
void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) {
if(OS_IS_INTERRUPT(mcause)) {
unsigned irq_id = mcause&(__riscv_xlen-1);
switch(irq_id){
case RISCV_INT_MTI:
#ifdef NX_DEBUG
printf("Timer interrupt being handled (pc=%lx)\n", mepc);
#endif
hwtimer_handler();
_tx_timer_interrupt();
break;
#ifdef TX_THREAD_SMP_INTER_CORE_INTERRUPT
case RISCV_INT_MSI:
set_aclint_msip(aclint, csr_read_mhartid(), 0);
break;
#endif
case RISCV_INT_MEI:
puts("[INTERRUPT]: handler ext irq error!\n");
while(1)
;
break;
default:
if(irq_handler[irq_id])
irq_handler[irq_id]();
else {
printf("[INTERRUPT]: Unkown Interrupt %d!!\n", mcause&0xff);
puts("[INTERRUPT]: now can't deal with the interrupt!\n");
while(1)
;
}
}
} else {
exception( mcause, mepc, mtval);
}
}

View File

@@ -0,0 +1,78 @@
/*
Baremetal main program with timer interrupt.
SPDX-License-Identifier: Unlicense
https://five-embeddev.com/
Tested with sifive-hifive-revb, but should not have any
dependencies to any particular implementation.
*/
// RISC-V CSR definitions and access classes
#include "riscv-csr.h"
#include "riscv-interrupt.h"
#include "hwtimer.h"
#include "vector_table.h"
extern void _tx_timer_interrupt(void);
// Machine mode interrupt service routine
// Global to hold current timestamp, written in MTI handler.
static volatile uint64_t timestamp = 0;
#define RISCV_MTVEC_MODE_VECTORED 1
int init_irq(void) {
// Global interrupt disable
csr_clr_bits_mstatus(MSTATUS_MIE_BIT_MASK);
csr_write_mie(0);
// Setup the IRQ handler entry point, set the mode to vectored
csr_write_mtvec((uint_xlen_t) riscv_mtvec_table | RISCV_MTVEC_MODE_VECTORED);
// Enable MIE.MTI
csr_set_bits_mie(MIE_MTI_BIT_MASK);
// Global interrupt enable
csr_set_bits_mstatus(MSTATUS_MIE_BIT_MASK);
// Setup timer for 1 second interval
hwtimer_init();
// Busy loop
do {
// Wait for timer interrupt
__asm__ volatile ("wfi");
// Try a synchronous exception.
__asm__ volatile ("ecall");
} while (1);
// Will not reach here
return 0;
}
#pragma GCC push_options
// Force the alignment for mtvec.BASE. A 'C' extension program could be aligned to to bytes.
#pragma GCC optimize ("align-functions=4")
// The 'riscv_mtvec_mti' function is added to the vector table by the vector_table.c
void riscv_mtvec_mti(void) {
hwtimer_handler();
_tx_timer_interrupt();
}
// The 'riscv_mtvec_exception' function is added to the vector table by the vector_table.c
// This function looks at the cause of the exception, if it is an 'ecall' instruction then increment a global counter.
void riscv_mtvec_exception(void) {
uint_xlen_t this_cause = csr_read_mcause();
uint_xlen_t this_pc = csr_read_mepc();
//uint_xlen_t this_value = csr_read_mtval();
switch (this_cause) {
case RISCV_EXCP_ENVIRONMENT_CALL_FROM_M_MODE:
ecall_count++;
// Make sure the return address is the instruction AFTER ecall
csr_write_mepc(this_pc+4);
break;
}
}
#pragma GCC pop_options

View File

@@ -0,0 +1,166 @@
/*
Baremetal main program with timer interrupt.
SPDX-License-Identifier: Unlicense
https://five-embeddev.com/
Tested with sifive-hifive-revb, but should not have any
dependencies to any particular implementation.
*/
// Makes use of GCC interrupt and weak reference/alias attributes
// https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
// https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html#RISC-V-Function-Attributes
// Vector table - not to be called.
void riscv_mtvec_table(void) __attribute__ ((naked, section(".text.mtvec_table") ,aligned(256)));
void riscv_stvec_table(void) __attribute__ ((naked, section(".text.stvec_table") ,aligned(256)));
void riscv_utvec_table(void) __attribute__ ((naked, section(".text.utvec_table") ,aligned(256)));
// Default "NOP" implementations
static void riscv_nop_machine(void) __attribute__ ((interrupt ("machine")) );
static void riscv_nop_supervisor(void) __attribute__ ((interrupt ("supervisor")) );
static void riscv_nop_user(void) __attribute__ ((interrupt ("user")) );
// Weak alias to the "NOP" implementations. If another function
void riscv_mtvec_exception(void) __attribute__ ((interrupt ("machine") , weak, alias("riscv_nop_machine") ));
void riscv_mtvec_msi(void) __attribute__ ((interrupt ("machine") , weak, alias("riscv_nop_machine") ));
void riscv_mtvec_mti(void) __attribute__ ((interrupt ("machine") , weak, alias("riscv_nop_machine") ));
void riscv_mtvec_mei(void) __attribute__ ((interrupt ("machine") , weak, alias("riscv_nop_machine") ));
void riscv_mtvec_ssi(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_machine") ));
void riscv_mtvec_sti(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_machine") ));
void riscv_mtvec_sei(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_machine") ));
void riscv_stvec_exception(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_supervisor") ));
void riscv_stvec_ssi(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_supervisor") ));
void riscv_stvec_sti(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_supervisor") ));
void riscv_stvec_sei(void) __attribute__ ((interrupt ("supervisor") , weak, alias("riscv_nop_supervisor") ));
void riscv_utvec_usi(void) __attribute__ ((interrupt ("user") , weak, alias("riscv_nop_user") ));
void riscv_utvec_uti(void) __attribute__ ((interrupt ("user") , weak, alias("riscv_nop_user") ));
void riscv_utvec_uei(void) __attribute__ ((interrupt ("user") , weak, alias("riscv_nop_user") ));
#ifndef VECTOR_TABLE_MTVEC_PLATFORM_INTS
void moonlight_mtvec_irq0(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq1(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq2(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq3(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq4(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq5(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq6(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq7(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq8(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq9(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq10(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq11(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq12(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq13(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq14(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
void moonlight_mtvec_irq15(void) __attribute__ ((interrupt ("machine"), weak, alias("riscv_nop_machine") ));
#endif // #ifndef VECTOR_TABLE_MTVEC_PLATFORM_INTS
#pragma GCC push_options
// Ensure the vector table is aligned.
// The bottom 4 bits of MTVEC are ignored - so align to 16 bytes
// Vector table. Do not call!
// Possible entries defined by mcause table
// http://five-embeddev.com/riscv-isa-manual/latest/machine.html#sec:mcause
//
// When vectored interrupts are enabled, interrupt cause 0, which
// corresponds to user-mode software interrupts, are vectored to the
// same location as synchronous exceptions. This ambiguity does not
// arise in practice, since user-mode software interrupts are either
// disabled or delegated to user mode.
void riscv_mtvec_table(void) {
__asm__ volatile (
".org riscv_mtvec_table + 0*4;"
"jal zero,riscv_mtvec_exception;" /* 0 */
".org riscv_mtvec_table + 1*4;"
"jal zero,riscv_mtvec_ssi;" /* 1 */
".org riscv_mtvec_table + 3*4;"
"jal zero,riscv_mtvec_msi;" /* 3 */
".org riscv_mtvec_table + 5*4;"
"jal zero,riscv_mtvec_sti;" /* 5 */
".org riscv_mtvec_table + 7*4;"
"jal zero,riscv_mtvec_mti;" /* 7 */
".org riscv_mtvec_table + 9*4;"
"jal zero,riscv_mtvec_sei;" /* 9 */
".org riscv_mtvec_table + 11*4;"
"jal zero,riscv_mtvec_mei;" /* 11 */
#ifndef VECTOR_TABLE_MTVEC_PLATFORM_INTS
".org riscv_mtvec_table + 16*4;"
"jal moonlight_mtvec_irq0;"
"jal moonlight_mtvec_irq1;"
"jal moonlight_mtvec_irq2;"
"jal moonlight_mtvec_irq3;"
"jal moonlight_mtvec_irq4;"
"jal moonlight_mtvec_irq5;"
"jal moonlight_mtvec_irq6;"
"jal moonlight_mtvec_irq7;"
"jal moonlight_mtvec_irq8;"
"jal moonlight_mtvec_irq9;"
"jal moonlight_mtvec_irq10;"
"jal moonlight_mtvec_irq11;"
"jal moonlight_mtvec_irq12;"
"jal moonlight_mtvec_irq13;"
"jal moonlight_mtvec_irq14;"
"jal moonlight_mtvec_irq15;"
#endif
: /* output: none */
: /* input : immediate */
: /* clobbers: none */
);
}
// Vector table. Do not call!
// See scause table for possible entries.
// http://five-embeddev.com/riscv-isa-manual/latest/supervisor.html#sec:scause
void riscv_stvec_table(void) {
__asm__ volatile (
".org riscv_stvec_table + 0*4;"
"jal zero,riscv_stvec_exception;" /* 0 */
".org riscv_stvec_table + 1*4;"
"jal zero,riscv_stvec_ssi;" /* 1 */
".org riscv_stvec_table + 5*4;"
"jal zero,riscv_stvec_sti;" /* 5 */
".org riscv_stvec_table + 9*4;"
"jal zero,riscv_stvec_sei;" /* 9 */
: /* output: none */
: /* input : immediate */
: /* clobbers: none */
);
}
// Vector table. Do not call!
void riscv_utvec_table(void) {
__asm__ volatile (
".org riscv_utvec_table + 0*4;"
"jal zero,riscv_utvec_usi;" /* 0 */
".org riscv_utvec_table + 4*4;"
"jal zero,riscv_utvec_uti;" /* 4 */
".org riscv_utvec_table + 8*4;"
"jal zero,riscv_utvec_uei;" /* 8 */
: /* output: none */
: /* input : immediate */
: /* clobbers: none */
);
}
// Ensure all ISR functions are aligned.
#pragma GCC optimize ("align-functions=4")
static void riscv_nop_machine(void) {
// Nop machine mode interrupt.
}
static void riscv_nop_supervisor(void) {
// Nop supervisor mode interrupt.
}
static void riscv_nop_user(void) {
// Nop user mode interrupt.
}
#pragma GCC pop_options