mirror of
https://github.com/eclipse-threadx/threadx.git
synced 2026-10-06 06:59:08 +08:00
riscv : add riscv qemu virt support and fix fs bit error in mstatus
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# Toolchain settings
|
||||
set(CMAKE_C_COMPILER riscv64-unknown-elf-gcc)
|
||||
set(CMAKE_CXX_COMPILER riscv64-unknown-elf-g++)
|
||||
set(AS riscv64-unknown-elf-as)
|
||||
set(AR riscv64-unknown-elf-ar)
|
||||
set(OBJCOPY riscv64-unknown-elf-objcopy)
|
||||
set(OBJDUMP riscv64-unknown-elf-objdump)
|
||||
set(SIZE riscv64-unknown-elf-size)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
|
||||
# this makes the test compiles use static library option so that we don't need to pre-set linker flags and scripts
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CFLAGS}" CACHE INTERNAL "c compiler flags")
|
||||
set(CMAKE_CXX_FLAGS "${CXXFLAGS}" CACHE INTERNAL "cxx compiler flags")
|
||||
set(CMAKE_ASM_FLAGS "${ASFLAGS} -D__ASSEMBLER__" CACHE INTERNAL "asm compiler flags")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${LDFLAGS}" CACHE INTERNAL "exe link flags")
|
||||
|
||||
SET(CMAKE_C_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "c debug compiler flags")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "cxx debug compiler flags")
|
||||
SET(CMAKE_ASM_FLAGS_DEBUG "-g -ggdb3" CACHE INTERNAL "asm debug compiler flags")
|
||||
|
||||
SET(CMAKE_C_FLAGS_RELEASE "-O3" CACHE INTERNAL "c release compiler flags")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE INTERNAL "cxx release compiler flags")
|
||||
SET(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm release compiler flags")
|
||||
@@ -0,0 +1,12 @@
|
||||
# Name of the target
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR risc-v64)
|
||||
|
||||
set(THREADX_ARCH "risc-v64")
|
||||
set(THREADX_TOOLCHAIN "gnu")
|
||||
set(ARCH_FLAGS "-g -march=rv64gc -mabi=lp64d -mcmodel=medany")
|
||||
set(CFLAGS "${ARCH_FLAGS}")
|
||||
set(ASFLAGS "${ARCH_FLAGS}")
|
||||
set(LDFLAGS "${ARCH_FLAGS}")
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/riscv64-unknown-elf.cmake)
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
# {{BEGIN_TARGET_SOURCES}}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.c
|
||||
# {{END_TARGET_SOURCES}}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "plic.h"
|
||||
#include "hwtimer.h"
|
||||
#include "uart.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void *memset(const void *des, int c,size_t n)
|
||||
{
|
||||
if((des == NULL) || n <=0)
|
||||
return (void*)des;
|
||||
char* t = (char*)des;
|
||||
int i;
|
||||
for(i=0;i<n;i++)
|
||||
t[i]=c;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
int ret;
|
||||
ret = plic_init();
|
||||
if(ret)
|
||||
return ret;
|
||||
ret = uart_init();
|
||||
if(ret)
|
||||
return ret;
|
||||
ret = hwtimer_init();
|
||||
if(ret)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
pushd ../../../../../
|
||||
cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/riscv64_gnu.cmake .
|
||||
cmake --build ./build/
|
||||
popd
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,58 @@
|
||||
|
||||
.section .text
|
||||
.align 4
|
||||
.global _start
|
||||
.extern main
|
||||
.extern _sysstack_start
|
||||
.extern _bss_start
|
||||
.extern _bss_end
|
||||
_start:
|
||||
csrr t0, mhartid
|
||||
bne t0, zero, 1f
|
||||
li x1, 0
|
||||
li x2, 0
|
||||
li x3, 0
|
||||
li x4, 0
|
||||
li x5, 0
|
||||
li x6, 0
|
||||
li x7, 0
|
||||
li x8, 0
|
||||
li x9, 0
|
||||
li x10, 0
|
||||
li x11, 0
|
||||
li x12, 0
|
||||
li x13, 0
|
||||
li x14, 0
|
||||
li x15, 0
|
||||
li x16, 0
|
||||
li x17, 0
|
||||
li x18, 0
|
||||
li x19, 0
|
||||
li x20, 0
|
||||
li x21, 0
|
||||
li x22, 0
|
||||
li x23, 0
|
||||
li x24, 0
|
||||
li x25, 0
|
||||
li x26, 0
|
||||
li x27, 0
|
||||
li x28, 0
|
||||
li x29, 0
|
||||
li x30, 0
|
||||
li x31, 0
|
||||
la t0, _sysstack_start
|
||||
li t1, 0x1000
|
||||
add sp, t0, t1
|
||||
la t0, _bss_start
|
||||
la t1, _bss_end
|
||||
_bss_clean_start:
|
||||
bgeu t0, t1, _bss_clean_end
|
||||
sb zero, 0(t0)
|
||||
addi t0, t0, 1
|
||||
j _bss_clean_start
|
||||
_bss_clean_end:
|
||||
call main
|
||||
1:
|
||||
/* todo smp */
|
||||
wfi
|
||||
j 1b
|
||||
@@ -0,0 +1,25 @@
|
||||
#include "tx_port.h"
|
||||
#include "csr.h"
|
||||
#include "hwtimer.h"
|
||||
|
||||
#define CLINT (0x02000000L)
|
||||
#define CLINT_TIME (CLINT+0xBFF8)
|
||||
#define CLINT_TIMECMP(hart_id) (CLINT+0x4000+8*(hart_id))
|
||||
|
||||
|
||||
int hwtimer_init(void)
|
||||
{
|
||||
int hart = riscv_get_core();
|
||||
uint64_t time = *((uint64_t*)CLINT_TIME);
|
||||
*((uint64_t*)CLINT_TIMECMP(hart)) = time + TICKNUM_PER_TIMER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hwtimer_handler(void)
|
||||
{
|
||||
int hart = riscv_get_core();
|
||||
uint64_t time = *((uint64_t*)CLINT_TIME);
|
||||
*((uint64_t*)CLINT_TIMECMP(hart)) = time + TICKNUM_PER_TIMER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef RISCV_HWTIMER_H
|
||||
#define RISCV_HWTIMER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define TICKNUM_PER_SECOND 10000000
|
||||
#define TICKNUM_PER_TIMER (TICKNUM_PER_SECOND / 10)
|
||||
|
||||
int hwtimer_init(void);
|
||||
|
||||
int hwtimer_handler(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY( _start )
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/*
|
||||
* ensure that entry.S / _entry is at 0x80000000,
|
||||
* where qemu's -kernel jumps.
|
||||
*/
|
||||
. = 0x80000000;
|
||||
|
||||
.text : {
|
||||
*(.text .text.*)
|
||||
. = ALIGN(0x1000);
|
||||
PROVIDE(etext = .);
|
||||
}
|
||||
|
||||
.rodata : {
|
||||
. = ALIGN(16);
|
||||
*(.srodata .srodata.*) /* do not need to distinguish this from .rodata */
|
||||
. = ALIGN(16);
|
||||
*(.rodata .rodata.*)
|
||||
}
|
||||
|
||||
.data : {
|
||||
. = ALIGN(16);
|
||||
*(.sdata .sdata.*) /* do not need to distinguish this from .data */
|
||||
. = ALIGN(16);
|
||||
*(.data .data.*)
|
||||
}
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(16);
|
||||
_bss_start = .;
|
||||
*(.sbss .sbss.*) /* do not need to distinguish this from .bss */
|
||||
. = ALIGN(16);
|
||||
*(.bss .bss.*)
|
||||
_bss_end = .;
|
||||
}
|
||||
|
||||
.stack : {
|
||||
. = ALIGN(4096);
|
||||
_sysstack_start = .;
|
||||
. += 0x1000;
|
||||
_sysstack_end = .;
|
||||
}
|
||||
|
||||
PROVIDE(_end = .);
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "plic.h"
|
||||
#include <stddef.h>
|
||||
irq_callback callbacks[MAX_CALLBACK_NUM];
|
||||
|
||||
void plic_irq_enable(int irqno)
|
||||
{
|
||||
int hart = riscv_get_core();
|
||||
*(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) | (1 << irqno));
|
||||
return;
|
||||
}
|
||||
|
||||
void plic_irq_disable(int irqno)
|
||||
{
|
||||
int hart = riscv_get_core();
|
||||
*(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) & (~(1 << irqno)));
|
||||
return;
|
||||
}
|
||||
|
||||
void plic_prio_set(int irqno, int prio)
|
||||
{
|
||||
PLIC_SET_PRIO(irqno, prio);
|
||||
}
|
||||
|
||||
int plic_prio_get(int irqno)
|
||||
{
|
||||
return PLIC_GET_PRIO(irqno);
|
||||
}
|
||||
|
||||
int plic_register_callback(int irqno, irq_callback callback)
|
||||
{
|
||||
if(!(irqno >=0 && irqno < MAX_CALLBACK_NUM))
|
||||
return -1;
|
||||
callbacks[irqno] = callback;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plic_unregister_callback(int irqno)
|
||||
{
|
||||
return plic_register_callback(irqno, NULL);
|
||||
}
|
||||
|
||||
int plic_init(void)
|
||||
{
|
||||
for(int i=0;i<MAX_CALLBACK_NUM;i++)
|
||||
{
|
||||
callbacks[i] = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plic_claim(void)
|
||||
{
|
||||
int hart = riscv_get_core();
|
||||
return (*(uint32_t*)PLIC_MCLAIM(hart));
|
||||
}
|
||||
|
||||
void plic_complete(int irqno)
|
||||
{
|
||||
int hart = riscv_get_core();
|
||||
*(uint32_t*)(PLIC_MCOMPLETE(hart)) = (uint32_t)irqno;
|
||||
return;
|
||||
}
|
||||
|
||||
int plic_irq_intr(void)
|
||||
{
|
||||
int ret = -1;
|
||||
int irqno = plic_claim();
|
||||
if(callbacks[irqno] != NULL)
|
||||
ret = (callbacks[irqno])(irqno);
|
||||
plic_complete(irqno);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifndef RISCV_PLIC_H
|
||||
#define RISCV_PLIC_H
|
||||
|
||||
#include "csr.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define PLIC 0x0c000000L
|
||||
#define PLIC_PRIORITY (PLIC + 0x0)
|
||||
#define PLIC_PENDING (PLIC + 0x1000)
|
||||
#define PLIC_MENABLE(hart) (PLIC + 0x2000 + (hart)*0x100)
|
||||
#define PLIC_SENABLE(hart) (PLIC + 0x2080 + (hart)*0x100)
|
||||
#define PLIC_MPRIORITY(hart) (PLIC + 0x200000 + (hart)*0x2000)
|
||||
#define PLIC_SPRIORITY(hart) (PLIC + 0x201000 + (hart)*0x2000)
|
||||
#define PLIC_MCLAIM(hart) (PLIC + 0x200004 + (hart)*0x2000)
|
||||
#define PLIC_SCLAIM(hart) (PLIC + 0x201004 + (hart)*0x2000)
|
||||
#define PLIC_MCOMPLETE(hart) (PLIC + 0x200004 + (hart)*0x2000)
|
||||
#define PLIC_SCOMPLETE(hart) (PLIC + 0x201004 + (hart)*0x2000)
|
||||
|
||||
|
||||
#define PLIC_GET_PRIO(irqno) (*(uint32_t *)(PLIC_PRIORITY + (irqno)*4))
|
||||
#define PLIC_SET_PRIO(irqno, prio) (*(uint32_t *)(PLIC_PRIORITY + (irqno)*4) = (prio))
|
||||
|
||||
#define MAX_CALLBACK_NUM 128
|
||||
typedef int (*irq_callback)(int irqno);
|
||||
|
||||
void plic_irq_enable(int irqno);
|
||||
void plic_irq_disable(int irqno);
|
||||
int plic_prio_get(int irqno);
|
||||
void plic_prio_set(int irqno, int prio);
|
||||
int plic_register_callback(int irqno, irq_callback callback);
|
||||
int plic_unregister_callback(int irqno);
|
||||
int plic_init(void);
|
||||
int plic_claim(void);
|
||||
void plic_complete(int irqno);
|
||||
|
||||
int plic_irq_intr(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "csr.h"
|
||||
#include <stdint.h>
|
||||
#include "uart.h"
|
||||
#include "hwtimer.h"
|
||||
#include "plic.h"
|
||||
#include <tx_port.h>
|
||||
#include <tx_api.h>
|
||||
|
||||
#define OS_IS_INTERUPT(mcause) (mcause & 0x8000000000000000ull)
|
||||
#define OS_IS_EXCEPTION(mcause) (~(OS_IS_INTERUPT))
|
||||
#define OS_IS_TICK_INT(mcause) (mcause == 0x8000000000000007ull)
|
||||
#define OS_IS_SOFT_INT(mcause) (mcause == 0x8000000000000003ull)
|
||||
#define OS_IS_EXT_INT(mcause) (mcause == 0x800000000000000bull)
|
||||
#define OS_IS_TRAP_USER(mcause) (mcause == 0x000000000000000bull)
|
||||
extern void _tx_timer_interrupt(void);
|
||||
|
||||
void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval)
|
||||
{
|
||||
if(OS_IS_INTERUPT(mcause))
|
||||
{
|
||||
if(OS_IS_TICK_INT(mcause))
|
||||
{
|
||||
hwtimer_handler();
|
||||
_tx_timer_interrupt();
|
||||
}
|
||||
else if(OS_IS_EXT_INT(mcause))
|
||||
{
|
||||
int ret = plic_irq_intr();
|
||||
if(ret)
|
||||
{
|
||||
puts("[INTERRUPT]: handler irq error!");
|
||||
while(1) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("[INTERRUPT]: now can't deal with the interrupt!");
|
||||
while(1) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("[EXCEPTION] : Unkown Error!!");
|
||||
while(1) ;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
#include "csr.h"
|
||||
#include "tx_port.h"
|
||||
|
||||
.section .text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* trap_entry RISC-V64/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Jer6y , luojun@oerv.isrc.iscas.ac.cn */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for riscv processor trap handle */
|
||||
/* It will do the contex save and call c trap_handler and do contex */
|
||||
/* load */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* trap_handler */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* hardware exception */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-25-2024 Jerry Luo */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Initialize */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
.global trap_entry
|
||||
.extern trap_handler
|
||||
.extern _tx_thread_context_restore
|
||||
trap_entry:
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
addi sp, sp, -65*REGBYTES // Allocate space for all registers - with floating point enabled
|
||||
#else
|
||||
addi sp, sp, -32*REGBYTES // Allocate space for all registers - without floating point enabled
|
||||
#endif
|
||||
|
||||
STORE x1, 28*REGBYTES(sp) // Store RA, 28*REGBYTES(because call will override ra [ra is a calle register in riscv])
|
||||
|
||||
call _tx_thread_context_save
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
csrr a2, mtval
|
||||
addi sp, sp, -8
|
||||
sd ra, 0(sp)
|
||||
call trap_handler
|
||||
ld ra, 0(sp)
|
||||
addi sp, sp, 8
|
||||
call _tx_thread_context_restore
|
||||
// it will nerver return
|
||||
_err:
|
||||
wfi
|
||||
j _err
|
||||
.section .text
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_initialize_low_level RISC-V64/GNU */
|
||||
/* 6.2.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for any low-level processor */
|
||||
/* initialization, including setting up interrupt vectors, setting */
|
||||
/* up a periodic timer interrupt source, saving the system stack */
|
||||
/* pointer for use in ISR processing later, and finding the first */
|
||||
/* available RAM memory address for tx_application_define. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 03-08-2023 Scott Larson Initial Version 6.2.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_initialize_low_level(VOID)
|
||||
{ */
|
||||
.global _tx_initialize_low_level
|
||||
.weak _tx_initialize_low_level
|
||||
.extern _end
|
||||
.extern board_init
|
||||
_tx_initialize_low_level:
|
||||
sd sp, _tx_thread_system_stack_ptr, t0 // Save system stack pointer
|
||||
|
||||
la t0, _end // Pickup first free address
|
||||
sd t0, _tx_initialize_unused_memory, t1 // Save unused memory address
|
||||
li t0, MSTATUS_MIE
|
||||
csrrc zero, mstatus, t0 // clear MSTATUS_MIE bit
|
||||
li t0, (MSTATUS_MPP_M | MSTATUS_MPIE )
|
||||
csrrs zero, mstatus, t0 // set MSTATUS_MPP, MPIE bit
|
||||
li t0, (MIE_MTIE | MIE_MSIE | MIE_MEIE)
|
||||
csrrs zero, mie, t0 // set mie
|
||||
#ifdef __riscv_flen
|
||||
li t0, MSTATUS_FS
|
||||
csrrs zero, mstatus, t0 // set MSTATUS_FS bit to open f/d isa in riscv
|
||||
fscsr x0
|
||||
#endif
|
||||
addi sp, sp, -8
|
||||
sd ra, 0(sp)
|
||||
call board_init
|
||||
ld ra, 0(sp)
|
||||
addi sp, sp, 8
|
||||
la t0, trap_entry
|
||||
csrw mtvec, t0
|
||||
ret
|
||||
@@ -0,0 +1,100 @@
|
||||
#include "uart.h"
|
||||
#include "csr.h"
|
||||
#include "plic.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// the UART control registers are memory-mapped
|
||||
// at address UART0. this macro returns the
|
||||
// address of one of the registers.
|
||||
#define Reg(reg) ((volatile unsigned char *)(UART0 + (reg)))
|
||||
|
||||
// the UART control registers.
|
||||
// some have different meanings for
|
||||
// read vs write.
|
||||
// see http://byterunner.com/16550.html
|
||||
#define RHR 0 // receive holding register (for input bytes)
|
||||
#define THR 0 // transmit holding register (for output bytes)
|
||||
#define IER 1 // interrupt enable register
|
||||
#define IER_RX_ENABLE (1<<0)
|
||||
#define IER_TX_ENABLE (1<<1)
|
||||
#define FCR 2 // FIFO control register
|
||||
#define FCR_FIFO_ENABLE (1<<0)
|
||||
#define FCR_FIFO_CLEAR (3<<1) // clear the content of the two FIFOs
|
||||
#define ISR 2 // interrupt status register
|
||||
#define LCR 3 // line control register
|
||||
#define LCR_EIGHT_BITS (3<<0)
|
||||
#define LCR_BAUD_LATCH (1<<7) // special mode to set baud rate
|
||||
#define LSR 5 // line status register
|
||||
#define LSR_RX_READY (1<<0) // input is waiting to be read from RHR
|
||||
#define LSR_TX_IDLE (1<<5) // THR can accept another character to send
|
||||
|
||||
#define ReadReg(reg) (*(Reg(reg)))
|
||||
#define WriteReg(reg, v) (*(Reg(reg)) = (v))
|
||||
|
||||
int uart_init(void)
|
||||
{
|
||||
// disable interrupts.
|
||||
WriteReg(IER, 0x00);
|
||||
|
||||
// special mode to set baud rate.
|
||||
WriteReg(LCR, LCR_BAUD_LATCH);
|
||||
|
||||
// LSB for baud rate of 38.4K.
|
||||
WriteReg(0, 0x03);
|
||||
|
||||
// MSB for baud rate of 38.4K.
|
||||
WriteReg(1, 0x00);
|
||||
|
||||
// leave set-baud mode,
|
||||
// and set word length to 8 bits, no parity.
|
||||
WriteReg(LCR, LCR_EIGHT_BITS);
|
||||
|
||||
// reset and enable FIFOs.
|
||||
WriteReg(FCR, FCR_FIFO_ENABLE | FCR_FIFO_CLEAR);
|
||||
|
||||
// enable transmit and receive interrupts.
|
||||
// WriteReg(IER, IER_TX_ENABLE | IER_RX_ENABLE);
|
||||
|
||||
//enable UART0 in PLIC
|
||||
plic_irq_enable(UART0_IRQ);
|
||||
|
||||
//set UART0 priority in PLIC
|
||||
plic_prio_set(UART0_IRQ, 1);
|
||||
|
||||
//register callback for UART0
|
||||
//plic_register_callback(UART0_IRQ, uart_intr);
|
||||
puts("[UART0] : Uart Init Done, this is Test output!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void uart_putc_nolock(int ch)
|
||||
{
|
||||
// wait for Transmit Holding Empty to be set in LSR.
|
||||
while((ReadReg(LSR) & LSR_TX_IDLE) == 0)
|
||||
;
|
||||
WriteReg(THR, ch);
|
||||
return;
|
||||
}
|
||||
|
||||
int uart_putc(int ch)
|
||||
{
|
||||
int intr_enable = riscv_mintr_get();
|
||||
riscv_mintr_off();
|
||||
uart_putc_nolock(ch);
|
||||
riscv_mintr_restore(intr_enable);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uart_puts(const char* str)
|
||||
{
|
||||
int i;
|
||||
int intr_enable = riscv_mintr_get();
|
||||
riscv_mintr_off();
|
||||
for(i=0;str[i]!=0;i++)
|
||||
{
|
||||
uart_putc_nolock(str[i]);
|
||||
}
|
||||
uart_putc_nolock('\n');
|
||||
riscv_mintr_restore(intr_enable);
|
||||
return i;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Microsoft Corporation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef RISCV_UART_H
|
||||
#define RISCV_UART_H
|
||||
|
||||
#define UART0 0x10000000L
|
||||
#define UART0_IRQ 10
|
||||
|
||||
#define puts uart_puts
|
||||
int uart_init(void);
|
||||
int uart_putc(int ch);
|
||||
int uart_puts(const char* str);
|
||||
#endif
|
||||
@@ -69,6 +69,7 @@ __tx_free_memory_start:
|
||||
/* VOID _tx_initialize_low_level(VOID)
|
||||
{ */
|
||||
.global _tx_initialize_low_level
|
||||
.weak _tx_initialize_low_level
|
||||
_tx_initialize_low_level:
|
||||
sd sp, _tx_thread_system_stack_ptr, t0 // Save system stack pointer
|
||||
|
||||
|
||||
@@ -149,6 +149,10 @@ _tx_thread_context_restore:
|
||||
LOAD t0, 30*REGBYTES(sp) // Recover mepc
|
||||
csrw mepc, t0 // Setup mepc
|
||||
li t0, 0x1880 // Prepare MPIP
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
li t1, 1<<13
|
||||
or t0, t1, t0
|
||||
#endif
|
||||
csrw mstatus, t0 // Enable MPIP
|
||||
|
||||
LOAD x1, 28*REGBYTES(sp) // Recover RA
|
||||
@@ -259,6 +263,10 @@ _tx_thread_no_preempt_restore:
|
||||
LOAD t0, 240(sp) // Recover mepc
|
||||
csrw mepc, t0 // Setup mepc
|
||||
li t0, 0x1880 // Prepare MPIP
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
li t1, 1<<13
|
||||
or t0, t1, t0
|
||||
#endif
|
||||
csrw mstatus, t0 // Enable MPIP
|
||||
|
||||
LOAD x1, 28*REGBYTES(sp) // Recover RA
|
||||
|
||||
@@ -201,6 +201,10 @@ _tx_thread_schedule_loop:
|
||||
LOAD t0, 30*REGBYTES(sp) // Recover mepc
|
||||
csrw mepc, t0 // Store mepc
|
||||
li t0, 0x1880 // Prepare MPIP
|
||||
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
|
||||
li t1, 1<<13
|
||||
or t0, t1, t0
|
||||
#endif
|
||||
csrw mstatus, t0 // Enable MPIP
|
||||
|
||||
LOAD x1, 28*REGBYTES(sp) // Recover RA
|
||||
|
||||
Reference in New Issue
Block a user