diff --git a/rt-thread/bsp/picorv32_blink/board.c b/rt-thread/bsp/picorv32_blink/board.c new file mode 100644 index 00000000..653c2aba --- /dev/null +++ b/rt-thread/bsp/picorv32_blink/board.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2020-2020, YuZhaorong + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-09 YuZhaorong the first version + */ + +#include +#include +#include + +#define TIMER_IRQ_VECTOR 0 +#define ECALL_IRQ_VECTOR 1 +#define SYSTEM_BUS_VECTOR 2 +#define SYSTEM_CORE_CLOCK 10000000l // 10 MHZ +// Holds the system core clock, which is the system clock +// frequency supplied to the SysTick timer and the processor +// core clock. +extern uint32_t riscv_timer(uint32_t time); +static uint32_t sys_timer_ticks = 0 ; +static uint32_t _riscv_time_config(rt_uint32_t ticks) +{ + sys_timer_ticks = ticks; + return riscv_timer(ticks); +} + +#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP) +#define RT_HEAP_SIZE 1024 +static uint32_t rt_heap[RT_HEAP_SIZE]; // heap default size: 4K(1024 * 4) +RT_WEAK void *rt_heap_begin_get(void) +{ + return rt_heap; +} + +RT_WEAK void *rt_heap_end_get(void) +{ + return rt_heap + RT_HEAP_SIZE; +} +#endif + +void riscv_timer_handler(int vector, void *param) +{ + riscv_timer(sys_timer_ticks); + rt_tick_increase(); + +} +void riscv_ecall_handler(int vector, void *param) +{ + +} +/** + * This function will initial your board. + */ +void rt_hw_board_init() +{ + + + + /* Call components board initial (use INIT_BOARD_EXPORT()) */ +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP) + rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get()); +#endif + + + /* System time Configuration */ + _riscv_time_config(SYSTEM_CORE_CLOCK / RT_TICK_PER_SECOND); + /*Register System timer interrupt function*/ + rt_hw_interrupt_init(); + rt_hw_interrupt_install(TIMER_IRQ_VECTOR,riscv_timer_handler,RT_NULL,"riscv_timer"); + rt_hw_interrupt_install(ECALL_IRQ_VECTOR,riscv_ecall_handler,RT_NULL,"riscv_ecall"); + rt_hw_interrupt_umask(ECALL_IRQ_VECTOR); +} + + diff --git a/rt-thread/bsp/picorv32_blink/buill/CMakeLists.txt b/rt-thread/bsp/picorv32_blink/buill/CMakeLists.txt new file mode 100644 index 00000000..9972b26a --- /dev/null +++ b/rt-thread/bsp/picorv32_blink/buill/CMakeLists.txt @@ -0,0 +1,101 @@ +# CMake 最低版本号要求 + +cmake_minimum_required (VERSION 3.1) + + + +ENABLE_LANGUAGE(ASM) +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR risc_v) + + +set(tools /opt/riscv32i) +set(LINKR_FILE ../src/sections.ld) +set(CMAKE_ASM_COMPILER ${tools}/bin/riscv32-unknown-elf-gcc) +set(CMAKE_C_COMPILER ${tools}/bin/riscv32-unknown-elf-gcc) +set(CMAKE_CXX_COMPILER ${tools}/bin/riscv32-unknown-elf-g++) +set(CMAKE_OBJCOPY ${tools}/bin/riscv32-unknown-elf-objcopy) +set(CMAKE_OBJDUMP ${tools}/bin/riscv32-unknown-elf-objdump) + +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) + +#CXXFLAGS = -MD -Os -Wall -std=c++11 +#CCFLAGS = -MD -Os -Wall +#LDFLAGS = -Wl,--gc-sections,--no-relax +#LDFLAGS = -ffunction-sections -Wl,--gc-sections +#LDLIBS = -ffunction-sections -fdata-sections + + + + + + +set(CMAKE_C_FLAGS "-MD -Os -Wall" ) + + +set(CMAKE_ASM_FLAGS "-nostdlib" ) +set(LD_FLAGS "-ffunction-sections -nostartfiles -Wl,--gc-sections") + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +set(ENABLE_EXPORTS True) +# 项目信息 + +set(PROJECT_NAME RISC_V) + +set(BIN_TARGET ${PROJECT_NAME}.bin) +set(HEX_TARGET ${PROJECT_NAME}.hex) +set(MAP_TARGET ${PROJECT_NAME}.map) +set(LSS_TARGET ${PROJECT_NAME}.asm) +set(TMP_TARGET ${PROJECT_NAME}.tmp) + +set(RISCV_SRC + ../src/start.S + ../board.c + ../src/main.c + ../../../libcpu/risc-v/picorv32/interrupt_gcc.S + ../../../libcpu/risc-v/picorv32/interrupt.c + ../../../libcpu/risc-v/picorv32/context_gcc.S + ../../../libcpu/risc-v/picorv32/cpuport.c + ../../../src/clock.c + ../../../src/components.c + ../../../src/cpu.c + ../../../src/idle.c + ../../../src/ipc.c + ../../../src/irq.c + ../../../src/kservice.c + ../../../src/mem.c + ../../../src/memheap.c + ../../../src/mempool.c + ../../../src/object.c + ../../../src/scheduler.c + ../../../src/slab.c + ../../../src/thread.c + ../../../src/timer.c + ) +# create binary & hex files and show size of resulting firmware image + +project (${PROJECT_NAME} ) + +include_directories(../../../libcpu/risc-v/picorv32 + ../ + ../../../include/ + ../../../include/libc/ + ./) + +# 指定生成目标 +add_executable(${PROJECT_NAME}.elf ${RISCV_SRC}) + +target_link_libraries(${PROJECT_NAME}.elf PRIVATE -T${LINKR_FILE} ${LD_FLAGS},-Map=${MAP_TARGET}) + +add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD + COMMAND echo "${PROJECT_NAME}.elf" + COMMAND ${CMAKE_OBJCOPY} -Obinary ${PROJECT_NAME}.elf ${BIN_TARGET} + COMMAND ${CMAKE_OBJCOPY} -O verilog ${PROJECT_NAME}.elf ${TMP_TARGET} + COMMAND ${CMAKE_OBJDUMP} -S ${PROJECT_NAME}.elf > ${LSS_TARGET} + COMMAND echo "${PROJECT_NAME}.elf" + COMMENT "Generating ${HEX_TARGET}, ${BIN_TARGET}") + + diff --git a/rt-thread/bsp/picorv32_blink/rtconfig.h b/rt-thread/bsp/picorv32_blink/rtconfig.h new file mode 100644 index 00000000..f03b804b --- /dev/null +++ b/rt-thread/bsp/picorv32_blink/rtconfig.h @@ -0,0 +1,156 @@ +/* RT-Thread config file */ + +#ifndef __RTTHREAD_CFG_H__ +#define __RTTHREAD_CFG_H__ + +#include + +#if defined(__CC_ARM) || defined(__CLANG_ARM) +#include "RTE_Components.h" + +#if defined(RTE_USING_FINSH) +#define RT_USING_FINSH +#endif //RTE_USING_FINSH + +#endif //(__CC_ARM) || (__CLANG_ARM) + +// <<< Use Configuration Wizard in Context Menu >>> +// Basic Configuration +// Maximal level of thread priority <8-256> +// Default: 32 +#define RT_THREAD_PRIORITY_MAX 8 +// OS tick per second +// Default: 1000 (1ms) +#define RT_TICK_PER_SECOND 100 +// Alignment size for CPU architecture data access +// Default: 4 +#define RT_ALIGN_SIZE 4 +// the max length of object name<2-16> +// Default: 8 +#define RT_NAME_MAX 8 +// Using RT-Thread components initialization +// Using RT-Thread components initialization +#define RT_USING_COMPONENTS_INIT +// + +#define RT_USING_USER_MAIN + +// the stack size of main thread<1-4086> +// Default: 512 +#define RT_MAIN_THREAD_STACK_SIZE 256 + +// + +// Debug Configuration +// enable kernel debug configuration +// Default: enable kernel debug configuration +//#define RT_DEBUG +// +// enable components initialization debug configuration<0-1> +// Default: 0 +#define RT_DEBUG_INIT 0 +// thread stack over flow detect +// Diable Thread stack over flow detect +//#define RT_USING_OVERFLOW_CHECK +// +// + +// Hook Configuration +// using hook +// using hook +//#define RT_USING_HOOK +// +// using idle hook +// using idle hook +//#define RT_USING_IDLE_HOOK +// +// +#define IDLE_THREAD_STACK_SIZE 128*4 +// Software timers Configuration +// Enables user timers +#define RT_USING_TIMER_SOFT 0 +#if RT_USING_TIMER_SOFT == 0 + #undef RT_USING_TIMER_SOFT +#endif +// The priority level of timer thread <0-31> +// Default: 4 +#define RT_TIMER_THREAD_PRIO 4 +// The stack size of timer thread <0-8192> +// Default: 512 +#define RT_TIMER_THREAD_STACK_SIZE 512 +// + +// IPC(Inter-process communication) Configuration +// Using Semaphore +// Using Semaphore +#define RT_USING_SEMAPHORE +// +// Using Mutex +// Using Mutex +//#define RT_USING_MUTEX +// +// Using Event +// Using Event +//#define RT_USING_EVENT +// +// Using MailBox +// Using MailBox +#define RT_USING_MAILBOX +// +// Using Message Queue +// Using Message Queue +//#define RT_USING_MESSAGEQUEUE +// +// + +// Memory Management Configuration +// Dynamic Heap Management +// Dynamic Heap Management +//#define RT_USING_HEAP +// +// using small memory +// using small memory +#define RT_USING_SMALL_MEM +// +// using tiny size of memory +// using tiny size of memory +//#define RT_USING_TINY_SIZE +// +// + +// Console Configuration +// Using console +// Using console +#define RT_USING_CONSOLE +// +// the buffer size of console <1-1024> +// the buffer size of console +// Default: 128 (128Byte) +#define RT_CONSOLEBUF_SIZE 128 +// + +#if defined(RT_USING_FINSH) + #define FINSH_USING_MSH + #define FINSH_USING_MSH_ONLY + // Finsh Configuration + // the priority of finsh thread <1-7> + // the priority of finsh thread + // Default: 6 + #define __FINSH_THREAD_PRIORITY 5 + #define FINSH_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 8 * __FINSH_THREAD_PRIORITY + 1) + // the stack of finsh thread <1-4096> + // the stack of finsh thread + // Default: 4096 (4096Byte) + #define FINSH_THREAD_STACK_SIZE 512 + // the history lines of finsh thread <1-32> + // the history lines of finsh thread + // Default: 5 + #define FINSH_HISTORY_LINES 1 + + #define FINSH_USING_SYMTAB + // +#endif + +// <<< end of configuration section >>> + +#endif diff --git a/rt-thread/bsp/picorv32_blink/src/main.c b/rt-thread/bsp/picorv32_blink/src/main.c new file mode 100644 index 00000000..410bc1aa --- /dev/null +++ b/rt-thread/bsp/picorv32_blink/src/main.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2006-2020, YuZhaorong + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-06 YuZhaorong + */ + +#include +#include + +#define TASK1_STACK_SIZE 512 +struct rt_thread task1={0}; +unsigned char task1_stack[TASK1_STACK_SIZE]={0}; + +#define TASK2_STACK_SIZE 512 +struct rt_thread task2={0}; +unsigned char task2_stack[TASK2_STACK_SIZE]={0}; +void m_putchar(const char ch) +{ + *(volatile int*)0x02000008= (int)ch; +} + +void rt_hw_console_output(const char *str) +{ + int i=0; + for(i=0;'\0' != str[i];i++) + { + m_putchar(str[i]); + } +} + +void thread_task1_entry(void* paramenter) +{ + while (1) + { + rt_kprintf("\r\n task1 runing...out A \r\n"); + rt_thread_delay(2); + } +} +void thread_task2_entry(void* paramenter) +{ + while (1) + { + rt_kprintf("\r\n task2 runing... out B \r\n"); + rt_thread_delay(3); + } +} +int main(void) +{ + rt_hw_interrupt_umask(0); // 注册定时器中断 + + + rt_kprintf("hello picorv32 world\r\n"); + + + rt_thread_init(&task1, "task1",thread_task1_entry, 0,(void*)task1_stack,TASK1_STACK_SIZE,4, 100); + rt_thread_startup(&task1); + + rt_thread_init(&task2, "task2",thread_task2_entry, 0,(void*)task2_stack,TASK2_STACK_SIZE,4, 100); + rt_thread_startup(&task2); + + while (1) + { + rt_thread_delay(500); + + } + return 0; +} diff --git a/rt-thread/bsp/picorv32_blink/src/sections.ld b/rt-thread/bsp/picorv32_blink/src/sections.ld new file mode 100644 index 00000000..d9e8aa54 --- /dev/null +++ b/rt-thread/bsp/picorv32_blink/src/sections.ld @@ -0,0 +1,62 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. +*/ + +/* starting address needs to be > 0 due to known bug in RISCV/GNU linker */ +MEMORY { + rom(rx) : ORIGIN = 0x00020000, LENGTH = 128k + ram(rwx) : ORIGIN = 0x00000000, LENGTH = 16k +} + +ENTRY(_pvstart); + +SECTIONS { + .init : { + . = ALIGN(4); + *(.text.entry); + }>rom + .interrupt 0x20400: { + . = ALIGN(4); + KEEP(*(.text.interrupt)); + + }>rom + .data : { + _data_lma = LOADADDR(.data); + _data = .; + __global_pointer$ = . ; + *(.data .data.* ) + *(.sdata .sdata.*) + *(COMMON) + . = ALIGN(4); + _edata = .; + } >ram AT>rom + + .bss : { + _bss_start = .; + *(.bss .bss.*) + *(.sbss .sbss.*) + . = ALIGN(4); + _bss_end = .; + _end = .; + } >ram + + .rom : { + . = ALIGN(4); + *(.text); + *(.stub .text.* .gnu.linkonce.t.*); + *(.rodata .rodata.*); + *(.*); + } > rom + + .stack ORIGIN(ram) + LENGTH(ram): + { + _riscv_sp = . ; + } >ram +} + + diff --git a/rt-thread/bsp/picorv32_blink/src/start.S b/rt-thread/bsp/picorv32_blink/src/start.S new file mode 100644 index 00000000..5f9f76c4 --- /dev/null +++ b/rt-thread/bsp/picorv32_blink/src/start.S @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2020-2020, YuZhaorong + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-06 YuZhaorong + */ +.section .text +.global _start +.global _pvstart +.global riscv_timer +.global riscv_maskirq +.global riscv_getirq +#include "custom_ops.S" +.section .text.entry +_pvstart: +/* zero-initialize all registers */ + addi x1, zero, 0 + addi x2, zero, 0 + addi x3, zero, 0 + addi x4, zero, 0 + addi x5, zero, 0 + addi x6, zero, 0 + addi x7, zero, 0 + addi x8, zero, 0 + addi x9, zero, 0 + addi x10, zero, 0 + addi x11, zero, 0 + addi x12, zero, 0 + addi x13, zero, 0 + addi x14, zero, 0 + addi x15, zero, 0 + addi x16, zero, 0 + addi x17, zero, 0 + addi x18, zero, 0 + addi x19, zero, 0 + addi x20, zero, 0 + addi x21, zero, 0 + addi x22, zero, 0 + addi x23, zero, 0 + addi x24, zero, 0 + addi x25, zero, 0 + addi x26, zero, 0 + addi x27, zero, 0 + addi x28, zero, 0 + addi x29, zero, 0 + addi x30, zero, 0 + addi x31, zero, 0 + +/* set stack pointer */ + + lui sp, %hi(_riscv_sp) + addi sp, sp, %lo(_riscv_sp) + +/* (stack is aligned to 16 bytes in riscv calling convention) */ + addi sp,sp,-16 + sw zero,0(sp) + sw zero,4(sp) + sw zero,8(sp) + sw zero,12(sp) +// picorv32_waitirq_insn(zero) + picorv32_maskirq_insn(zero, zero) + j _start + ebreak + + +_start: +# Initialize global pointer +1: auipc gp, %pcrel_hi(__global_pointer$) + addi gp, gp, %pcrel_lo(1b) +# Clear the bss segment + la a0, _edata + la a1, _end +_bss_init: + addi a0,a0,4 + sw zero,-4(a0) + bgeu a1,a0,_bss_init + +# Init the data segment + la a0, _data + la a1, _edata + la a2, _data_lma +_data_init: + addi a2,a2,4 + lw a5,-4(a2) + addi a0,a0,4 + sw a5,-4(a0) + bgeu a1,a0,_data_init +# call entry + li a0, 0 + call entry + ebreak + +riscv_maskirq: + picorv32_maskirq_insn(a0, a0) + ret +riscv_timer: + picorv32_timer_insn(a0, a0) + ret +riscv_getirq: + picorv32_getq_insn(a0, q1) + ret + diff --git a/rt-thread/libcpu/risc-v/picorv32/context_gcc.S b/rt-thread/libcpu/risc-v/picorv32/context_gcc.S new file mode 100644 index 00000000..b3a3f188 --- /dev/null +++ b/rt-thread/libcpu/risc-v/picorv32/context_gcc.S @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020-2020, YuZhaorong + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020/06/13 YuZhaorong + */ + + +#include "custom_ops.S" +#define LOAD lw +#define REGBYTES 4 +/* + * void rt_hw_context_switch_to(rt_ubase_t to); + * a0 --> to + */ +.globl rt_hw_context_switch_to +rt_hw_context_switch_to: + LOAD sp, (a0) + /* resw ra to mepc */ + LOAD tp, 0 * 4(sp) // 加载PC指针 到线程指针中 待用 + LOAD x1, 1 * REGBYTES(sp) /* x1 - ra - return address for jumps */ + + LOAD x5, 5 * REGBYTES(sp) + LOAD x6, 6 * REGBYTES(sp) + LOAD x7, 7 * REGBYTES(sp) + LOAD x8, 8 * REGBYTES(sp) + LOAD x9, 9 * REGBYTES(sp) + LOAD x10, 10 * REGBYTES(sp) + LOAD x11, 11 * REGBYTES(sp) + LOAD x12, 12 * REGBYTES(sp) + LOAD x13, 13 * REGBYTES(sp) + LOAD x14, 14 * REGBYTES(sp) + LOAD x15, 15 * REGBYTES(sp) + LOAD x16, 16 * REGBYTES(sp) + LOAD x17, 17 * REGBYTES(sp) + LOAD x18, 18 * REGBYTES(sp) + LOAD x19, 19 * REGBYTES(sp) + LOAD x20, 20 * REGBYTES(sp) + LOAD x21, 21 * REGBYTES(sp) + LOAD x22, 22 * REGBYTES(sp) + LOAD x23, 23 * REGBYTES(sp) + LOAD x24, 24 * REGBYTES(sp) + LOAD x25, 25 * REGBYTES(sp) + LOAD x26, 26 * REGBYTES(sp) + LOAD x27, 27 * REGBYTES(sp) + LOAD x28, 28 * REGBYTES(sp) + LOAD x29, 29 * REGBYTES(sp) + LOAD x30, 30 * REGBYTES(sp) + LOAD x31, 31 * REGBYTES(sp) + + addi sp, sp, 32 * REGBYTES + jr tp // 跳转至线程指针 diff --git a/rt-thread/libcpu/risc-v/picorv32/cpuport.c b/rt-thread/libcpu/risc-v/picorv32/cpuport.c new file mode 100644 index 00000000..8ef24873 --- /dev/null +++ b/rt-thread/libcpu/risc-v/picorv32/cpuport.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/10/28 Bernard The unify RISC-V porting code. + * 2020/06/05 YuZhaorong + */ + +#include +#include +#include "cpuport.h" + +volatile rt_ubase_t rt_interrupt_from_thread = 0; +volatile rt_ubase_t rt_interrupt_to_thread = 0; +volatile rt_uint32_t rt_thread_switch_interrupt_flag = 0; +volatile rt_uint32_t rt_hw_context_switch_flag = 0; +unsigned int riscv_maskirq(unsigned int maskirq); +struct rt_hw_stack_frame +{ + rt_ubase_t epc; /* epc - epc - program counter */ + rt_ubase_t ra; /* x1 - ra - return address for jumps */ + rt_ubase_t mstatus; /* - machine status register */ + rt_ubase_t gp; /* x3 - gp - global pointer */ + rt_ubase_t tp; /* x4 - tp - thread pointer */ + rt_ubase_t t0; /* x5 - t0 - temporary register 0 */ + rt_ubase_t t1; /* x6 - t1 - temporary register 1 */ + rt_ubase_t t2; /* x7 - t2 - temporary register 2 */ + rt_ubase_t s0_fp; /* x8 - s0/fp - saved register 0 or frame pointer */ + rt_ubase_t s1; /* x9 - s1 - saved register 1 */ + rt_ubase_t a0; /* x10 - a0 - return value or function argument 0 */ + rt_ubase_t a1; /* x11 - a1 - return value or function argument 1 */ + rt_ubase_t a2; /* x12 - a2 - function argument 2 */ + rt_ubase_t a3; /* x13 - a3 - function argument 3 */ + rt_ubase_t a4; /* x14 - a4 - function argument 4 */ + rt_ubase_t a5; /* x15 - a5 - function argument 5 */ + rt_ubase_t a6; /* x16 - a6 - function argument 6 */ + rt_ubase_t a7; /* x17 - s7 - function argument 7 */ + rt_ubase_t s2; /* x18 - s2 - saved register 2 */ + rt_ubase_t s3; /* x19 - s3 - saved register 3 */ + rt_ubase_t s4; /* x20 - s4 - saved register 4 */ + rt_ubase_t s5; /* x21 - s5 - saved register 5 */ + rt_ubase_t s6; /* x22 - s6 - saved register 6 */ + rt_ubase_t s7; /* x23 - s7 - saved register 7 */ + rt_ubase_t s8; /* x24 - s8 - saved register 8 */ + rt_ubase_t s9; /* x25 - s9 - saved register 9 */ + rt_ubase_t s10; /* x26 - s10 - saved register 10 */ + rt_ubase_t s11; /* x27 - s11 - saved register 11 */ + rt_ubase_t t3; /* x28 - t3 - temporary register 3 */ + rt_ubase_t t4; /* x29 - t4 - temporary register 4 */ + rt_ubase_t t5; /* x30 - t5 - temporary register 5 */ + rt_ubase_t t6; /* x31 - t6 - temporary register 6 */ +}; + +/** + * This function will initialize thread stack + * + * @param tentry the entry of thread + * @param parameter the parameter of entry + * @param stack_addr the beginning stack address + * @param texit the function will be called when thread exit + * + * @return stack address + */ +rt_uint8_t *rt_hw_stack_init(void *tentry, + void *parameter, + rt_uint8_t *stack_addr, + void *texit) +{ + struct rt_hw_stack_frame *frame; + rt_uint8_t *stk; + int i; + + stk = stack_addr + sizeof(rt_ubase_t); + stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES); + stk -= sizeof(struct rt_hw_stack_frame); + + frame = (struct rt_hw_stack_frame *)stk; + + for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++) + { + ((rt_ubase_t *)frame)[i] = 0xdeadbeef; + } + + frame->ra = (rt_ubase_t)texit; + frame->a0 = (rt_ubase_t)parameter; + frame->epc = (rt_ubase_t)tentry; + + /* force to machine mode(MPP=11) and set MPIE to 1 */ + frame->mstatus = 0x00007880; + + return stk; +} + +/* + * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to); + */ + +void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to) +{ + if (rt_thread_switch_interrupt_flag == 0) + rt_interrupt_from_thread = from; + + rt_interrupt_to_thread = to; + rt_thread_switch_interrupt_flag = 1; + + return ; +} + +void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to) +{ + if (rt_thread_switch_interrupt_flag == 0) + rt_interrupt_from_thread = from; + + rt_interrupt_to_thread = to; + rt_thread_switch_interrupt_flag = 1; + rt_hw_context_switch_flag=1 ; + return ; +} + +rt_base_t rt_hw_interrupt_disable(void) +{ + return riscv_maskirq(0xffffffff); +} +void rt_hw_interrupt_enable(rt_base_t level) +{ + riscv_maskirq(level); + + if(rt_hw_context_switch_flag) + { + rt_hw_context_switch_flag =0; + if((level & 0x0002)==0) + { + /* 判断是否要触发系统中断*/ + if(rt_thread_switch_interrupt_flag) + { + __asm("ecall"); + } + } + } + return; +} + +/** shutdown CPU */ +void rt_hw_cpu_shutdown() +{ + rt_uint32_t level; + rt_kprintf("shutdown...\n"); + + level = rt_hw_interrupt_disable(); + while (level) + { + RT_ASSERT(0); + } +} diff --git a/rt-thread/libcpu/risc-v/picorv32/cpuport.h b/rt-thread/libcpu/risc-v/picorv32/cpuport.h new file mode 100644 index 00000000..95268732 --- /dev/null +++ b/rt-thread/libcpu/risc-v/picorv32/cpuport.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-03 Bernard The first version + */ + +#ifndef CPUPORT_H__ +#define CPUPORT_H__ + +#include + +/* bytes of register width */ +#ifdef ARCH_CPU_64BIT +#define STORE sd +#define LOAD ld +#define REGBYTES 8 +#else +#define STORE sw +#define LOAD lw +#define REGBYTES 4 +#endif + +#endif diff --git a/rt-thread/libcpu/risc-v/picorv32/custom_ops.S b/rt-thread/libcpu/risc-v/picorv32/custom_ops.S new file mode 100644 index 00000000..71889b9e --- /dev/null +++ b/rt-thread/libcpu/risc-v/picorv32/custom_ops.S @@ -0,0 +1,102 @@ +// This is free and unencumbered software released into the public domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. + +#define regnum_q0 0 +#define regnum_q1 1 +#define regnum_q2 2 +#define regnum_q3 3 + +#define regnum_x0 0 +#define regnum_x1 1 +#define regnum_x2 2 +#define regnum_x3 3 +#define regnum_x4 4 +#define regnum_x5 5 +#define regnum_x6 6 +#define regnum_x7 7 +#define regnum_x8 8 +#define regnum_x9 9 +#define regnum_x10 10 +#define regnum_x11 11 +#define regnum_x12 12 +#define regnum_x13 13 +#define regnum_x14 14 +#define regnum_x15 15 +#define regnum_x16 16 +#define regnum_x17 17 +#define regnum_x18 18 +#define regnum_x19 19 +#define regnum_x20 20 +#define regnum_x21 21 +#define regnum_x22 22 +#define regnum_x23 23 +#define regnum_x24 24 +#define regnum_x25 25 +#define regnum_x26 26 +#define regnum_x27 27 +#define regnum_x28 28 +#define regnum_x29 29 +#define regnum_x30 30 +#define regnum_x31 31 + +#define regnum_zero 0 +#define regnum_ra 1 +#define regnum_sp 2 +#define regnum_gp 3 +#define regnum_tp 4 +#define regnum_t0 5 +#define regnum_t1 6 +#define regnum_t2 7 +#define regnum_s0 8 +#define regnum_s1 9 +#define regnum_a0 10 +#define regnum_a1 11 +#define regnum_a2 12 +#define regnum_a3 13 +#define regnum_a4 14 +#define regnum_a5 15 +#define regnum_a6 16 +#define regnum_a7 17 +#define regnum_s2 18 +#define regnum_s3 19 +#define regnum_s4 20 +#define regnum_s5 21 +#define regnum_s6 22 +#define regnum_s7 23 +#define regnum_s8 24 +#define regnum_s9 25 +#define regnum_s10 26 +#define regnum_s11 27 +#define regnum_t3 28 +#define regnum_t4 29 +#define regnum_t5 30 +#define regnum_t6 31 + +// x8 is s0 and also fp +#define regnum_fp 8 + +#define r_type_insn(_f7, _rs2, _rs1, _f3, _rd, _opc) \ +.word (((_f7) << 25) | ((_rs2) << 20) | ((_rs1) << 15) | ((_f3) << 12) | ((_rd) << 7) | ((_opc) << 0)) + +#define picorv32_getq_insn(_rd, _qs) \ +r_type_insn(0b0000000, 0, regnum_ ## _qs, 0b100, regnum_ ## _rd, 0b0001011) + +#define picorv32_setq_insn(_qd, _rs) \ +r_type_insn(0b0000001, 0, regnum_ ## _rs, 0b010, regnum_ ## _qd, 0b0001011) + +#define picorv32_retirq_insn() \ +r_type_insn(0b0000010, 0, 0, 0b000, 0, 0b0001011) + +#define picorv32_maskirq_insn(_rd, _rs) \ +r_type_insn(0b0000011, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011) + +#define picorv32_waitirq_insn(_rd) \ +r_type_insn(0b0000100, 0, 0, 0b100, regnum_ ## _rd, 0b0001011) + +#define picorv32_timer_insn(_rd, _rs) \ +r_type_insn(0b0000101, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011) + diff --git a/rt-thread/libcpu/risc-v/picorv32/interrupt.c b/rt-thread/libcpu/risc-v/picorv32/interrupt.c new file mode 100644 index 00000000..1977a815 --- /dev/null +++ b/rt-thread/libcpu/risc-v/picorv32/interrupt.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/10/01 Bernard The first version + * 2020-06-06 YuZhaorong add PicoRV32 + */ + +#include +#define IRQN_MAX 32 +#define MAX_HANDLERS IRQN_MAX + +static struct rt_irq_desc irq_desc[MAX_HANDLERS]={0}; +static rt_base_t irq_mask = 0 ; +static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param) +{ + rt_kprintf("UN-handled interrupt %d occurred!!!\n", vector); + return RT_NULL; +} + +/** + * This function will initialize hardware interrupt + */ +void rt_hw_interrupt_init(void) +{ + int idx; + irq_mask = rt_hw_interrupt_disable(); + irq_mask = 0xFFFFFFFF; + for (idx = 0; idx < MAX_HANDLERS; idx++) + { + irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle; + irq_desc[idx].param = RT_NULL; +#ifdef RT_USING_INTERRUPT_INFO + rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default"); + irq_desc[idx].counter = 0; +#endif + } + + rt_hw_interrupt_enable(irq_mask); + /* Enable machine external interrupts. */ +} + + +/** + * This function will mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_mask(int vector) +{ + rt_base_t irq_level; + + if(vector < MAX_HANDLERS) + { + irq_level = rt_hw_interrupt_disable(); + irq_level |= 0x01<< vector; + rt_hw_interrupt_enable(irq_level); + } + +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + rt_base_t irq_level; + + if(vector < MAX_HANDLERS) + { + irq_level = rt_hw_interrupt_disable(); + irq_level &= ~( 0x01l << vector); + rt_hw_interrupt_enable( irq_level ); + } +} + +/** + * This function will install a interrupt service routine to a interrupt. + * @param vector the interrupt number + * @param new_handler the interrupt service routine to be installed + * @param old_handler the old interrupt service routine + */ +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name) +{ + rt_isr_handler_t old_handler = RT_NULL; + + if(vector < MAX_HANDLERS) + { + old_handler = irq_desc[vector].handler; + if (handler != RT_NULL) + { + irq_desc[vector].handler = (rt_isr_handler_t)handler; + irq_desc[vector].param = param; +#ifdef RT_USING_INTERRUPT_INFO + rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name); + irq_desc[vector].counter = 0; +#endif + } + } + + return old_handler; +} + + + +unsigned int *irq(unsigned int *regs, unsigned int irqs) +{ + int int_num; + for(int_num = 0; int_num < MAX_HANDLERS; int_num++) + { + if( (0x1 & (irqs>>int_num))== 1 ) + { + if (irq_desc[int_num].handler) + { + irq_desc[int_num].handler(int_num, irq_desc[int_num].param); + } + } + + } + return regs; +} + + + diff --git a/rt-thread/libcpu/risc-v/picorv32/interrupt_gcc.S b/rt-thread/libcpu/risc-v/picorv32/interrupt_gcc.S new file mode 100644 index 00000000..b28ee73d --- /dev/null +++ b/rt-thread/libcpu/risc-v/picorv32/interrupt_gcc.S @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2020-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-06 YuZhaorong add PicoRV32 + */ + + +#include "custom_ops.S" +.global irq +.global irq_entry +#define REGBYTES 4 +.section .text.interrupt +.balign 16 +irq_entry: + /* save registers */ + addi sp, sp, -32 * REGBYTES + + picorv32_setq_insn(q2, x1) + + picorv32_getq_insn(x1, q0) + + sw x1, 0*REGBYTES(sp) // 保存 epc 指针 + + picorv32_getq_insn(x1, q2) // 保存 return address + sw x1, 1 * REGBYTES(sp) + + sw x5, 5 * REGBYTES(sp) + sw x6, 6 * REGBYTES(sp) + sw x7, 7 * REGBYTES(sp) + sw x8, 8 * REGBYTES(sp) + sw x9, 9 * REGBYTES(sp) + sw x10, 10 * REGBYTES(sp) + sw x11, 11 * REGBYTES(sp) + sw x12, 12 * REGBYTES(sp) + sw x13, 13 * REGBYTES(sp) + sw x14, 14 * REGBYTES(sp) + sw x15, 15 * REGBYTES(sp) + sw x16, 16 * REGBYTES(sp) + sw x17, 17 * REGBYTES(sp) + sw x18, 18 * REGBYTES(sp) + sw x19, 19 * REGBYTES(sp) + sw x20, 20 * REGBYTES(sp) + sw x21, 21 * REGBYTES(sp) + sw x22, 22 * REGBYTES(sp) + sw x23, 23 * REGBYTES(sp) + sw x24, 24 * REGBYTES(sp) + sw x25, 25 * REGBYTES(sp) + sw x26, 26 * REGBYTES(sp) + sw x27, 27 * REGBYTES(sp) + sw x28, 28 * REGBYTES(sp) + sw x29, 29 * REGBYTES(sp) + sw x30, 30 * REGBYTES(sp) + sw x31, 31 * REGBYTES(sp) + + picorv32_setq_insn(q3, x2) // 保存sp 至q3 寄存器 + + + /* switch to interrupt stack */ + la sp , irq_stack // 加载 irq 堆栈 + + /* interrupt handle */ + call rt_interrupt_enter + /* call interrupt handler C function */ + picorv32_getq_insn(a1, q1) + // call to C function + jal ra, irq + + call rt_interrupt_leave + + /* switch to from thread stack */ + picorv32_getq_insn(sp, q3) + /* need to switch new thread */ + la s0, rt_thread_switch_interrupt_flag + lw s2, 0(s0) + beqz s2, rt_hw_context_switch_interrupt_exit + /* clear switch interrupt flag */ + sw zero, 0(s0) + + + la s0, rt_interrupt_from_thread + lw s1, 0(s0) + sw sp, 0(s1) + + la s0, rt_interrupt_to_thread + lw s1, 0(s0) + lw sp, 0(s1) + + lw a0, 0 * REGBYTES(sp) + picorv32_setq_insn(q0, a0) + +/* restore registers */ +rt_hw_context_switch_interrupt_exit: + + + lw x1, 0 * REGBYTES(sp) + picorv32_setq_insn(q0, x1) + + lw x1, 1 * REGBYTES(sp) + picorv32_setq_insn(q2, x1) + + lw x5, 5 * REGBYTES(sp) + lw x6, 6 * REGBYTES(sp) + lw x7, 7 * REGBYTES(sp) + lw x8, 8 * REGBYTES(sp) + lw x9, 9 * REGBYTES(sp) + lw x10, 10 * REGBYTES(sp) + lw x11, 11 * REGBYTES(sp) + lw x12, 12 * REGBYTES(sp) + lw x13, 13 * REGBYTES(sp) + lw x14, 14 * REGBYTES(sp) + lw x15, 15 * REGBYTES(sp) + lw x16, 16 * REGBYTES(sp) + lw x17, 17 * REGBYTES(sp) + lw x18, 18 * REGBYTES(sp) + lw x19, 19 * REGBYTES(sp) + lw x20, 20 * REGBYTES(sp) + lw x21, 21 * REGBYTES(sp) + lw x22, 22 * REGBYTES(sp) + lw x23, 23 * REGBYTES(sp) + lw x24, 24 * REGBYTES(sp) + lw x25, 25 * REGBYTES(sp) + lw x26, 26 * REGBYTES(sp) + lw x27, 27 * REGBYTES(sp) + lw x28, 28 * REGBYTES(sp) + lw x29, 29 * REGBYTES(sp) + lw x30, 30 * REGBYTES(sp) + lw x31, 31 * REGBYTES(sp) + + picorv32_getq_insn(x1, q2) + + addi sp, sp, 32 * REGBYTES + + picorv32_retirq_insn() + +.section .data +irq_regs: + // registers are saved to this memory region during interrupt handling + // the program counter is saved as register 0 + .fill 32,4 + + // stack for the interrupt handler + .fill 128,4 +irq_stack: +