diff --git a/rtl.flist b/rtl.flist index 70b3a36..41f9b22 100644 --- a/rtl.flist +++ b/rtl.flist @@ -37,6 +37,7 @@ ../rtl/perips/rom.sv ../rtl/perips/timer.sv ../rtl/perips/uart.sv +../rtl/perips/machine_timer.sv ../rtl/sys_bus/obi_interconnect.sv ../rtl/sys_bus/obi_interconnect_master_sel.sv diff --git a/rtl/core/defines.sv b/rtl/core/defines.sv index 5aaadb1..acaec29 100644 --- a/rtl/core/defines.sv +++ b/rtl/core/defines.sv @@ -40,6 +40,9 @@ // UART `define UART_ADDR_MASK ~32'hffff `define UART_ADDR_BASE 32'h50000000 +// Machine Timer +`define MTIMER_ADDR_MASK ~32'hffff +`define MTIMER_ADDR_BASE 32'hA0000000 // SIM CTRL `define SIM_CTRL_ADDR_MASK ~32'hffff `define SIM_CTRL_ADDR_BASE 32'hE0000000 diff --git a/rtl/core/exception.sv b/rtl/core/exception.sv index fb85107..0f78b31 100644 --- a/rtl/core/exception.sv +++ b/rtl/core/exception.sv @@ -89,14 +89,14 @@ module exception ( localparam FAST_INT_OFFSET = 44; - localparam S_IDLE = 4'b0001; - localparam S_W_MEPC = 4'b0010; - localparam S_W_DCSR = 4'b0100; - localparam S_ASSERT = 4'b1000; - + localparam S_IDLE = 5'b00001; + localparam S_W_MEPC = 5'b00010; + localparam S_W_DCSR = 5'b00100; + localparam S_ASSERT = 5'b01000; + localparam S_W_MSTATUS = 5'b10000; reg debug_mode_d, debug_mode_q; - reg[3:0] state_d, state_q; + reg[4:0] state_d, state_q; reg[31:0] assert_addr_d, assert_addr_q; reg[31:0] return_addr_d, return_addr_q; reg csr_we; @@ -239,13 +239,13 @@ module exception ( case (state_q) S_IDLE: begin - if (int_or_exception_req) begin + if (int_or_exception_req & (!debug_mode_q)) begin csr_we = 1'b1; csr_waddr = {20'h0, `CSR_MCAUSE}; csr_wdata = int_or_exception_cause; assert_addr_d = mtvec_i + int_or_exception_offset; return_addr_d = inst_addr_i; - state_d = S_W_MEPC; + state_d = S_W_MSTATUS; end else if (debug_mode_req) begin debug_mode_d = 1'b1; if (enter_debug_cause_debugger_req | @@ -269,6 +269,9 @@ module exception ( end end else if (inst_mret_i) begin assert_addr_d = mepc_i; + csr_we = 1'b1; + csr_waddr = {20'h0, `CSR_MSTATUS}; + csr_wdata = {mstatus_i[31:4], 1'b1, mstatus_i[2:0]}; state_d = S_ASSERT; end else if (inst_dret_i) begin assert_addr_d = dpc_i; @@ -277,6 +280,13 @@ module exception ( end end + S_W_MSTATUS: begin + csr_we = 1'b1; + csr_waddr = {20'h0, `CSR_MSTATUS}; + csr_wdata = {mstatus_i[31:4], 1'b0, mstatus_i[2:0]}; + state_d = S_W_MEPC; + end + S_W_MEPC: begin csr_we = 1'b1; csr_waddr = {20'h0, `CSR_MEPC}; diff --git a/rtl/perips/gpio.sv b/rtl/perips/gpio.sv index 039e973..f0ca77b 100644 --- a/rtl/perips/gpio.sv +++ b/rtl/perips/gpio.sv @@ -46,8 +46,8 @@ module gpio( assign reg_ctrl = gpio_ctrl; assign reg_data = gpio_data; - wire wen = we_i & req_valid_i; - wire ren = (~we_i) & req_valid_i; + wire wen = we_i; + wire ren = (~we_i); wire write_reg_ctrl_en = wen & (addr_i[3:0] == GPIO_CTRL); wire write_reg_data_en = wen & (addr_i[3:0] == GPIO_DATA); diff --git a/rtl/perips/machine_timer.sv b/rtl/perips/machine_timer.sv new file mode 100644 index 0000000..2aded8b --- /dev/null +++ b/rtl/perips/machine_timer.sv @@ -0,0 +1,117 @@ + /* + Copyright 2021 Blue Liang, liangkangnan@163.com + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +module machine_timer( + + input wire clk, + input wire rst_n, + input wire[31:0] addr_i, + input wire[31:0] data_i, + input wire[3:0] sel_i, + input wire we_i, + output wire[31:0] data_o, + output wire irq_o + + ); + + localparam mtime_ctrl_reg = 4'h0; + localparam mtime_cmp_reg = 4'h4; + localparam mtime_count_reg = 4'h8; + + localparam start = 0; + localparam irq_pending = 1; + + reg[31:0] mtime_ctrl_d, mtime_ctrl_q; + reg[31:0] mtime_cmp_d, mtime_cmp_q; + reg[31:0] mtime_count_q; + reg data_q; + + wire[3:0] rw_addr = addr_i[3:0]; + wire w0 = we_i & sel_i[0]; + wire w1 = we_i & sel_i[1]; + wire w2 = we_i & sel_i[2]; + wire w3 = we_i & sel_i[3]; + + // write + always @ (*) begin + mtime_cmp_d = mtime_cmp_q; + mtime_ctrl_d = mtime_ctrl_q; + + case (rw_addr) + mtime_ctrl_reg: begin + if (w0) begin + mtime_ctrl_d[0] = data_i[0]; + mtime_ctrl_d[irq_pending] = mtime_ctrl_q & (~data_i[irq_pending]); + end + end + + mtime_cmp_reg: begin + if (w0) mtime_cmp_d[7:0] = data_i[7:0]; + if (w1) mtime_cmp_d[15:8] = data_i[15:8]; + if (w2) mtime_cmp_d[23:16] = data_i[23:16]; + if (w3) mtime_cmp_d[31:24] = data_i[31:24]; + end + + default:; + endcase + + if (mtime_count_q == mtime_cmp_q) begin + mtime_ctrl_d[irq_pending] = 1'b1; + end + end + + assign irq_o = mtime_ctrl_q[irq_pending] & mtime_ctrl_q[start]; + + // read + always @ (*) begin + data_q = 32'h0; + + case (rw_addr) + mtime_ctrl_reg: data_q = mtime_ctrl_q; + mtime_cmp_reg: data_q = mtime_cmp_q; + mtime_count_reg: data_q = mtime_count_q; + default:; + endcase + end + + assign data_o = data_q; + + always @ (posedge clk or negedge rst_n) begin + if (!rst_n) begin + mtime_ctrl_q <= 32'h0; + mtime_cmp_q <= 32'h0; + end else begin + mtime_ctrl_q <= mtime_ctrl_d; + mtime_cmp_q <= mtime_cmp_d; + end + end + + always @ (posedge clk or negedge rst_n) begin + if (!rst_n) begin + mtime_count_q <= 32'h0; + end else begin + if (mtime_ctrl_q[start]) begin + mtime_count_q <= mtime_count_q + 1'b1; + if (mtime_count_q == mtime_cmp_q) begin + mtime_count_q <= 32'h0; + end + end else begin + mtime_count_q <= 32'h0; + end + end + end + +endmodule diff --git a/rtl/perips/uart.sv b/rtl/perips/uart.sv index 20087a4..3c8d7ec 100644 --- a/rtl/perips/uart.sv +++ b/rtl/perips/uart.sv @@ -85,8 +85,8 @@ module uart( // UART接收数据寄存器,只读 reg[31:0] uart_rx; - wire wen = we_i & req_valid_i; - wire ren = (~we_i) & req_valid_i; + wire wen = we_i; + wire ren = (~we_i); wire write_reg_ctrl_en = wen & (addr_i[7:0] == UART_CTRL); wire write_reg_status_en = wen & (addr_i[7:0] == UART_STATUS); wire write_reg_baud_en = wen & (addr_i[7:0] == UART_BAUD); diff --git a/rtl/top/tinyriscv_soc_top.sv b/rtl/top/tinyriscv_soc_top.sv index a47850d..4597bc7 100644 --- a/rtl/top/tinyriscv_soc_top.sv +++ b/rtl/top/tinyriscv_soc_top.sv @@ -39,9 +39,9 @@ module tinyriscv_soc_top( localparam int MASTERS = 3; // Number of master ports `ifdef VERILATOR - localparam int SLAVES = 4; // Number of slave ports + localparam int SLAVES = 7; // Number of slave ports `else - localparam int SLAVES = 3; // Number of slave ports + localparam int SLAVES = 6; // Number of slave ports `endif // masters @@ -53,8 +53,11 @@ module tinyriscv_soc_top( localparam int Rom = 0; localparam int Ram = 1; localparam int JtagDevice = 2; + localparam int Mtimer = 3; + localparam int Gpio = 4; + localparam int Uart = 5; `ifdef VERILATOR - localparam int SimCtrl = 3; + localparam int SimCtrl = 6; `endif @@ -93,6 +96,12 @@ module tinyriscv_soc_top( wire debug_req; wire core_halted; + wire mtimer_irq; + + wire[1:0] io_in; + wire[31:0] gpio_ctrl; + wire[31:0] gpio_data; + assign halted_ind_pin = core_halted; tinyriscv_core #( @@ -120,7 +129,7 @@ module tinyriscv_soc_top( .data_err_i (1'b0), .irq_software_i (1'b0), - .irq_timer_i (1'b0), + .irq_timer_i (mtimer_irq), .irq_external_i (1'b0), .irq_fast_i (15'b0), @@ -129,7 +138,7 @@ module tinyriscv_soc_top( assign slave_addr_mask[Rom] = `ROM_ADDR_MASK; assign slave_addr_base[Rom] = `ROM_ADDR_BASE; - // 指令存储器 + // 1.指令存储器 rom #( .DP(`ROM_DEPTH) ) u_rom ( @@ -144,7 +153,7 @@ module tinyriscv_soc_top( assign slave_addr_mask[Ram] = `RAM_ADDR_MASK; assign slave_addr_base[Ram] = `RAM_ADDR_BASE; - // 数据存储器 + // 2.数据存储器 ram #( .DP(`RAM_DEPTH) ) u_ram ( @@ -157,17 +166,70 @@ module tinyriscv_soc_top( .data_o (slave_rdata[Ram]) ); + assign slave_addr_mask[Mtimer] = `MTIMER_ADDR_MASK; + assign slave_addr_base[Mtimer] = `MTIMER_ADDR_BASE; + // 3.机器定时器模块 + machine_timer u_machine_timer( + .clk (clk), + .rst_n (ndmreset_n), + .addr_i (slave_addr[Mtimer]), + .data_i (slave_wdata[Mtimer]), + .sel_i (slave_be[Mtimer]), + .we_i (slave_we[Mtimer]), + .data_o (slave_rdata[Mtimer]), + .irq_o (mtimer_irq) + ); + + // IO0 + assign gpio_pins[0] = (gpio_ctrl[1:0] == 2'b01)? gpio_data[0]: 1'bz; + assign io_in[0] = gpio_pins[0]; + // IO1 + assign gpio_pins[1] = (gpio_ctrl[3:2] == 2'b01)? gpio_data[1]: 1'bz; + assign io_in[1] = gpio_pins[1]; + + assign slave_addr_mask[Gpio] = `GPIO_ADDR_MASK; + assign slave_addr_base[Gpio] = `GPIO_ADDR_BASE; + // 4.GPIO模块 + gpio u_gpio( + .clk (clk), + .rst_n (ndmreset_n), + .addr_i (slave_addr[Gpio]), + .data_i (slave_wdata[Gpio]), + .sel_i (slave_be[Gpio]), + .we_i (slave_we[Gpio]), + .data_o (slave_rdata[Gpio]), + .io_pin_i(io_in), + .reg_ctrl(gpio_ctrl), + .reg_data(gpio_data) + ); + + assign slave_addr_mask[Uart] = `UART_ADDR_MASK; + assign slave_addr_base[Uart] = `UART_ADDR_BASE; + // 5.串口模块 + uart u_uart( + .clk (clk), + .rst_n (ndmreset_n), + .addr_i (slave_addr[Uart]), + .data_i (slave_wdata[Uart]), + .sel_i (slave_be[Uart]), + .we_i (slave_we[Uart]), + .data_o (slave_rdata[Uart]), + .tx_pin (uart_tx_pin), + .rx_pin (uart_rx_pin) + ); + `ifdef VERILATOR assign slave_addr_mask[SimCtrl] = `SIM_CTRL_ADDR_MASK; assign slave_addr_base[SimCtrl] = `SIM_CTRL_ADDR_BASE; + // 6.仿真控制模块 sim_ctrl u_sim_ctrl( - .clk_i(clk), - .rst_ni(ndmreset_n), - .req_i(), - .gnt_o(), - .addr_i(slave_addr[SimCtrl]), - .we_i(slave_we[SimCtrl]), - .be_i(slave_be[SimCtrl]), + .clk_i (clk), + .rst_ni (ndmreset_n), + .req_i (), + .gnt_o (), + .addr_i (slave_addr[SimCtrl]), + .we_i (slave_we[SimCtrl]), + .be_i (slave_be[SimCtrl]), .wdata_i(slave_wdata[SimCtrl]), .rdata_o(slave_rdata[SimCtrl]) ); diff --git a/sdk/bsp/.gitignore b/sdk/bsp/.gitignore index 4c37608..abff2c2 100644 --- a/sdk/bsp/.gitignore +++ b/sdk/bsp/.gitignore @@ -1,6 +1,6 @@ -# Object files -*.o -*.ko -*.obj -*.bin -*.dump +# Object files +*.o +*.ko +*.obj +*.bin +*.dump diff --git a/sdk/bsp/README.md b/sdk/bsp/README.md index 1e06469..ad4e723 100644 --- a/sdk/bsp/README.md +++ b/sdk/bsp/README.md @@ -1,3 +1,3 @@ -**include**: 公共头文件目录。 - +**include**: 公共头文件目录。 + **lib**: 公共函数目录。 \ No newline at end of file diff --git a/sdk/bsp/bsp.mk b/sdk/bsp/bsp.mk index c9dcaaf..03884ac 100644 --- a/sdk/bsp/bsp.mk +++ b/sdk/bsp/bsp.mk @@ -22,6 +22,7 @@ C_SRCS += $(BSP_DIR)/lib/utils.c C_SRCS += $(BSP_DIR)/lib/xprintf.c C_SRCS += $(BSP_DIR)/lib/uart.c C_SRCS += $(BSP_DIR)/lib/sim_ctrl.c +C_SRCS += $(BSP_DIR)/lib/machine_timer.c LINKER_SCRIPT := $(BSP_DIR)/link.lds diff --git a/sdk/bsp/include/machine_timer.h b/sdk/bsp/include/machine_timer.h new file mode 100644 index 0000000..29ec09d --- /dev/null +++ b/sdk/bsp/include/machine_timer.h @@ -0,0 +1,16 @@ +#ifndef _MACHINE_TIMER_H_ +#define _MACHINE_TIMER_H_ + +#define MTIMER_BASE (0xA0000000) +#define MTIMER_CTRL (MTIMER_BASE + (0x00)) +#define MTIMER_CMP (MTIMER_BASE + (0x04)) +#define MTIMER_COUNT (MTIMER_BASE + (0x08)) + +#define MTIMER_REG(addr) (*((volatile uint32_t *)addr)) + +void machine_timer_set_cmp_val(uint32_t val); +void machine_timer_enable(uint8_t en); +void machine_timer_irq_enable(uint8_t en); +void machine_timer_clear_irq_pending(); + +#endif diff --git a/sdk/bsp/include/trap_code.h b/sdk/bsp/include/trap_code.h index 05b416d..d46a1b0 100644 --- a/sdk/bsp/include/trap_code.h +++ b/sdk/bsp/include/trap_code.h @@ -1,19 +1,19 @@ -#ifndef _TRAP_CODE_H_ -#define _TRAP_CODE_H_ - -#define TRAP_USER_SW (0x80000000) -#define TRAP_MACH_SW (0x80000003) -#define TRAP_USER_TIMER (0x80000004) -#define TRAP_MACH_TIMER (0x80000007) -#define TRAP_USER_EXT (0x80000008) -#define TRAP_MACH_EXT (0x8000000B) -#define TRAP_INST_ADDR_MISA (0x00000000) -#define TRAP_ILLEGAL_INST (0x00000002) -#define TRAP_BREAKPOINT (0x00000003) -#define TRAP_LOAD_ADDR_MISA (0x00000004) -#define TRAP_STORE_ADDR_MISA (0x00000006) -#define TRAP_ECALL_U (0x00000008) -#define TRAP_ECALL_S (0x00000009) -#define TRAP_ECALL_M (0x0000000B) - -#endif +#ifndef _TRAP_CODE_H_ +#define _TRAP_CODE_H_ + +#define TRAP_USER_SW (0x80000000) +#define TRAP_MACH_SW (0x80000003) +#define TRAP_USER_TIMER (0x80000004) +#define TRAP_MACH_TIMER (0x80000007) +#define TRAP_USER_EXT (0x80000008) +#define TRAP_MACH_EXT (0x8000000B) +#define TRAP_INST_ADDR_MISA (0x00000000) +#define TRAP_ILLEGAL_INST (0x00000002) +#define TRAP_BREAKPOINT (0x00000003) +#define TRAP_LOAD_ADDR_MISA (0x00000004) +#define TRAP_STORE_ADDR_MISA (0x00000006) +#define TRAP_ECALL_U (0x00000008) +#define TRAP_ECALL_S (0x00000009) +#define TRAP_ECALL_M (0x0000000B) + +#endif diff --git a/sdk/bsp/include/utils.h b/sdk/bsp/include/utils.h index 6f8ac5d..2bd00f7 100644 --- a/sdk/bsp/include/utils.h +++ b/sdk/bsp/include/utils.h @@ -1,28 +1,33 @@ -#ifndef _UTILS_H_ -#define _UTILS_H_ - -#define CPU_FREQ_HZ (50000000) // 50MHz -#define CPU_FREQ_MHZ (50) // 50MHz - - -#define read_csr(reg) ({ unsigned long __tmp; \ - asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ - __tmp; }) - -#define write_csr(reg, val) ({ \ - if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ - asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ - else \ - asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) - - -#ifdef SIMULATION -#define set_test_pass() asm("li x27, 0x01") -#define set_test_fail() asm("li x27, 0x00") -#endif - - -uint64_t get_cycle_value(); -void busy_wait(uint32_t us); - -#endif +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#define CPU_FREQ_HZ (50000000) // 50MHz +#define CPU_FREQ_MHZ (50) // 50MHz + + +#define read_csr(reg) ({ unsigned long __tmp; \ + asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ + __tmp; }) + +#define write_csr(reg, val) ({ \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ + else \ + asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) + + +#ifdef SIMULATION +#define set_test_pass() asm("li x27, 0x01") +#define set_test_fail() asm("li x27, 0x00") +#endif + + +uint64_t get_cycle_value(); +void busy_wait(uint32_t us); + +void global_irq_enable(); +void global_irq_disable(); +void mtime_irq_enable(); +void mtime_irq_disable(); + +#endif diff --git a/sdk/bsp/include/xprintf.h b/sdk/bsp/include/xprintf.h index 5024dff..e94900a 100644 --- a/sdk/bsp/include/xprintf.h +++ b/sdk/bsp/include/xprintf.h @@ -1,19 +1,19 @@ -/*------------------------------------------------------------------------*/ -/* Universal string handler for user console interface (C)ChaN, 2011 */ -/*------------------------------------------------------------------------*/ - -#ifndef _XPRINTF_H_ -#define _XPRINTF_H_ - -#define _CR_CRLF 0 /* 1: Convert \n ==> \r\n in the output char */ - -#define xdev_out(func) xfunc_out = (void(*)(unsigned char))(func) -extern void (*xfunc_out)(unsigned char); -void xputc (char c); -void xputs (const char* str); -void xprintf (const char* fmt, ...); -#define DW_CHAR sizeof(char) -#define DW_SHORT sizeof(short) -#define DW_LONG sizeof(long) - -#endif +/*------------------------------------------------------------------------*/ +/* Universal string handler for user console interface (C)ChaN, 2011 */ +/*------------------------------------------------------------------------*/ + +#ifndef _XPRINTF_H_ +#define _XPRINTF_H_ + +#define _CR_CRLF 0 /* 1: Convert \n ==> \r\n in the output char */ + +#define xdev_out(func) xfunc_out = (void(*)(unsigned char))(func) +extern void (*xfunc_out)(unsigned char); +void xputc (char c); +void xputs (const char* str); +void xprintf (const char* fmt, ...); +#define DW_CHAR sizeof(char) +#define DW_SHORT sizeof(short) +#define DW_LONG sizeof(long) + +#endif diff --git a/sdk/bsp/lib/.gitignore b/sdk/bsp/lib/.gitignore index 4c37608..abff2c2 100644 --- a/sdk/bsp/lib/.gitignore +++ b/sdk/bsp/lib/.gitignore @@ -1,6 +1,6 @@ -# Object files -*.o -*.ko -*.obj -*.bin -*.dump +# Object files +*.o +*.ko +*.obj +*.bin +*.dump diff --git a/sdk/bsp/lib/machine_timer.c b/sdk/bsp/lib/machine_timer.c new file mode 100644 index 0000000..3e2ec00 --- /dev/null +++ b/sdk/bsp/lib/machine_timer.c @@ -0,0 +1,30 @@ +#include + +#include "../../bsp/include/machine_timer.h" +#include "../../bsp/include/utils.h" + +void machine_timer_set_cmp_val(uint32_t val) +{ + MTIMER_REG(MTIMER_CMP) = val; +} + +void machine_timer_enable(uint8_t en) +{ + if (en) + MTIMER_REG(MTIMER_CTRL) |= 1; + else + MTIMER_REG(MTIMER_CTRL) &= ~1; +} + +void machine_timer_irq_enable(uint8_t en) +{ + if (en) + mtime_irq_enable(); + else + mtime_irq_disable(); +} + +void machine_timer_clear_irq_pending() +{ + MTIMER_REG(MTIMER_CTRL) |= 1 << 1; +} diff --git a/sdk/bsp/lib/uart.c b/sdk/bsp/lib/uart.c index a5df712..0e9e124 100644 --- a/sdk/bsp/lib/uart.c +++ b/sdk/bsp/lib/uart.c @@ -1,29 +1,29 @@ -#include - -#include "../include/uart.h" -#include "../include/xprintf.h" - - -// send one char to uart -void uart_putc(uint8_t c) -{ - while (UART0_REG(UART0_STATUS) & 0x1); - UART0_REG(UART0_TXDATA) = c; -} - -// Block, get one char from uart. -uint8_t uart_getc() -{ - UART0_REG(UART0_STATUS) &= ~0x2; - while (!(UART0_REG(UART0_STATUS) & 0x2)); - return (UART0_REG(UART0_RXDATA) & 0xff); -} - -// 115200bps, 8 N 1 -void uart_init() -{ - // enable tx and rx - UART0_REG(UART0_CTRL) = 0x3; - - xdev_out(uart_putc); -} +#include + +#include "../include/uart.h" +#include "../include/xprintf.h" + + +// send one char to uart +void uart_putc(uint8_t c) +{ + while (UART0_REG(UART0_STATUS) & 0x1); + UART0_REG(UART0_TXDATA) = c; +} + +// Block, get one char from uart. +uint8_t uart_getc() +{ + UART0_REG(UART0_STATUS) &= ~0x2; + while (!(UART0_REG(UART0_STATUS) & 0x2)); + return (UART0_REG(UART0_RXDATA) & 0xff); +} + +// 115200bps, 8 N 1 +void uart_init() +{ + // enable tx and rx + UART0_REG(UART0_CTRL) = 0x3; + + xdev_out(uart_putc); +} diff --git a/sdk/bsp/lib/utils.c b/sdk/bsp/lib/utils.c index d3a0b52..15dfe1e 100644 --- a/sdk/bsp/lib/utils.c +++ b/sdk/bsp/lib/utils.c @@ -1,26 +1,46 @@ -#include - -#include "../include/utils.h" - - - -uint64_t get_cycle_value() -{ - uint64_t cycle; - - cycle = read_csr(cycle); - cycle += (uint64_t)(read_csr(cycleh)) << 32; - - return cycle; -} - -void busy_wait(uint32_t us) -{ - uint64_t tmp; - uint32_t count; - - count = us * CPU_FREQ_MHZ; - tmp = get_cycle_value(); - - while (get_cycle_value() < (tmp + count)); -} +#include + +#include "../include/utils.h" + + + +uint64_t get_cycle_value() +{ + uint64_t cycle; + + cycle = read_csr(cycle); + cycle += (uint64_t)(read_csr(cycleh)) << 32; + + return cycle; +} + +void busy_wait(uint32_t us) +{ + uint64_t tmp; + uint32_t count; + + count = us * CPU_FREQ_MHZ; + tmp = get_cycle_value(); + + while (get_cycle_value() < (tmp + count)); +} + +void global_irq_enable() +{ + asm volatile("csrs mstatus, %0\n" : : "r"(0x8)); +} + +void global_irq_disable() +{ + asm volatile("csrc mstatus, %0\n" : : "r"(0x8)); +} + +void mtime_irq_enable() +{ + asm volatile("csrs mie, %0\n" : : "r"(0x80)); +} + +void mtime_irq_disable() +{ + asm volatile("csrc mie, %0\n" : : "r"(0x80)); +} diff --git a/sdk/bsp/lib/xprintf.c b/sdk/bsp/lib/xprintf.c index 6e4b9b5..bdbdcdf 100644 --- a/sdk/bsp/lib/xprintf.c +++ b/sdk/bsp/lib/xprintf.c @@ -1,157 +1,157 @@ -/*------------------------------------------------------------------------/ -/ Universal string handler for user console interface -/-------------------------------------------------------------------------/ -/ -/ Copyright (C) 2011, ChaN, all right reserved. -/ -/ * This software is a free software and there is NO WARRANTY. -/ * No restriction on use. You can use, modify and redistribute it for -/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. -/ * Redistributions of source code must retain the above copyright notice. -/ -/-------------------------------------------------------------------------*/ - -#include "../include/xprintf.h" - -#include - - -void (*xfunc_out)(unsigned char); /* Pointer to the output stream */ -static char *outptr; - -/*----------------------------------------------*/ -/* Put a character */ -/*----------------------------------------------*/ - -void xputc (char c) -{ - if (_CR_CRLF && c == '\n') xputc('\r'); /* CR -> CRLF */ - - if (outptr) { - *outptr++ = (unsigned char)c; - return; - } - - if (xfunc_out) xfunc_out((unsigned char)c); -} - - -/*----------------------------------------------*/ -/* Put a null-terminated string */ -/*----------------------------------------------*/ - -void xputs ( /* Put a string to the default device */ - const char* str /* Pointer to the string */ -) -{ - while (*str) - xputc(*str++); -} - - -/*----------------------------------------------*/ -/* Formatted string output */ -/*----------------------------------------------*/ -/* xprintf("%d", 1234); "1234" - xprintf("%6d,%3d%%", -200, 5); " -200, 5%" - xprintf("%-6u", 100); "100 " - xprintf("%ld", 12345678L); "12345678" - xprintf("%04x", 0xA3); "00a3" - xprintf("%08LX", 0x123ABC); "00123ABC" - xprintf("%016b", 0x550F); "0101010100001111" - xprintf("%s", "String"); "String" - xprintf("%-4s", "abc"); "abc " - xprintf("%4s", "abc"); " abc" - xprintf("%c", 'a'); "a" - xprintf("%f", 10.0); -*/ - -static -void xvprintf ( - const char* fmt, /* Pointer to the format string */ - va_list arp /* Pointer to arguments */ -) -{ - unsigned int r, i, j, w, f; - unsigned long v; - char s[16], c, d, *p; - - - for (;;) { - c = *fmt++; /* Get a char */ - if (!c) break; /* End of format? */ - if (c != '%') { /* Pass through it if not a % sequense */ - xputc(c); continue; - } - f = 0; - c = *fmt++; /* Get first char of the sequense */ - if (c == '0') { /* Flag: '0' padded */ - f = 1; c = *fmt++; - } else { - if (c == '-') { /* Flag: left justified */ - f = 2; c = *fmt++; - } - } - for (w = 0; c >= '0' && c <= '9'; c = *fmt++) /* Minimum width */ - w = w * 10 + c - '0'; - if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ - f |= 4; c = *fmt++; - } - if (!c) break; /* End of format? */ - d = c; - if (d >= 'a') d -= 0x20; - switch (d) { /* Type is... */ - case 'S' : /* String */ - p = va_arg(arp, char*); - for (j = 0; p[j]; j++) ; - while (!(f & 2) && j++ < w) xputc(' '); - xputs(p); - while (j++ < w) xputc(' '); - continue; - case 'C' : /* Character */ - xputc((char)va_arg(arp, int)); continue; - case 'B' : /* Binary */ - r = 2; break; - case 'O' : /* Octal */ - r = 8; break; - case 'D' : /* Signed decimal */ - case 'U' : /* Unsigned decimal */ - r = 10; break; - case 'X' : /* Hexdecimal */ - r = 16; break; - default: /* Unknown type (passthrough) */ - xputc(c); continue; - } - - /* Get an argument and put it in numeral */ - v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int)); - if (d == 'D' && (v & 0x80000000)) { - v = 0 - v; - f |= 8; - } - i = 0; - do { - d = (char)(v % r); v /= r; - if (d > 9) d += (c == 'x') ? 0x27 : 0x07; - s[i++] = d + '0'; - } while (v && i < sizeof(s)); - if (f & 8) s[i++] = '-'; - j = i; d = (f & 1) ? '0' : ' '; - while (!(f & 2) && j++ < w) xputc(d); - do xputc(s[--i]); while(i); - while (j++ < w) xputc(' '); - } -} - -void xprintf ( /* Put a formatted string to the default device */ - const char* fmt, /* Pointer to the format string */ - ... /* Optional arguments */ -) -{ - va_list arp; - - - va_start(arp, fmt); - xvprintf(fmt, arp); - va_end(arp); -} +/*------------------------------------------------------------------------/ +/ Universal string handler for user console interface +/-------------------------------------------------------------------------/ +/ +/ Copyright (C) 2011, ChaN, all right reserved. +/ +/ * This software is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/-------------------------------------------------------------------------*/ + +#include "../include/xprintf.h" + +#include + + +void (*xfunc_out)(unsigned char); /* Pointer to the output stream */ +static char *outptr; + +/*----------------------------------------------*/ +/* Put a character */ +/*----------------------------------------------*/ + +void xputc (char c) +{ + if (_CR_CRLF && c == '\n') xputc('\r'); /* CR -> CRLF */ + + if (outptr) { + *outptr++ = (unsigned char)c; + return; + } + + if (xfunc_out) xfunc_out((unsigned char)c); +} + + +/*----------------------------------------------*/ +/* Put a null-terminated string */ +/*----------------------------------------------*/ + +void xputs ( /* Put a string to the default device */ + const char* str /* Pointer to the string */ +) +{ + while (*str) + xputc(*str++); +} + + +/*----------------------------------------------*/ +/* Formatted string output */ +/*----------------------------------------------*/ +/* xprintf("%d", 1234); "1234" + xprintf("%6d,%3d%%", -200, 5); " -200, 5%" + xprintf("%-6u", 100); "100 " + xprintf("%ld", 12345678L); "12345678" + xprintf("%04x", 0xA3); "00a3" + xprintf("%08LX", 0x123ABC); "00123ABC" + xprintf("%016b", 0x550F); "0101010100001111" + xprintf("%s", "String"); "String" + xprintf("%-4s", "abc"); "abc " + xprintf("%4s", "abc"); " abc" + xprintf("%c", 'a'); "a" + xprintf("%f", 10.0); +*/ + +static +void xvprintf ( + const char* fmt, /* Pointer to the format string */ + va_list arp /* Pointer to arguments */ +) +{ + unsigned int r, i, j, w, f; + unsigned long v; + char s[16], c, d, *p; + + + for (;;) { + c = *fmt++; /* Get a char */ + if (!c) break; /* End of format? */ + if (c != '%') { /* Pass through it if not a % sequense */ + xputc(c); continue; + } + f = 0; + c = *fmt++; /* Get first char of the sequense */ + if (c == '0') { /* Flag: '0' padded */ + f = 1; c = *fmt++; + } else { + if (c == '-') { /* Flag: left justified */ + f = 2; c = *fmt++; + } + } + for (w = 0; c >= '0' && c <= '9'; c = *fmt++) /* Minimum width */ + w = w * 10 + c - '0'; + if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ + f |= 4; c = *fmt++; + } + if (!c) break; /* End of format? */ + d = c; + if (d >= 'a') d -= 0x20; + switch (d) { /* Type is... */ + case 'S' : /* String */ + p = va_arg(arp, char*); + for (j = 0; p[j]; j++) ; + while (!(f & 2) && j++ < w) xputc(' '); + xputs(p); + while (j++ < w) xputc(' '); + continue; + case 'C' : /* Character */ + xputc((char)va_arg(arp, int)); continue; + case 'B' : /* Binary */ + r = 2; break; + case 'O' : /* Octal */ + r = 8; break; + case 'D' : /* Signed decimal */ + case 'U' : /* Unsigned decimal */ + r = 10; break; + case 'X' : /* Hexdecimal */ + r = 16; break; + default: /* Unknown type (passthrough) */ + xputc(c); continue; + } + + /* Get an argument and put it in numeral */ + v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int)); + if (d == 'D' && (v & 0x80000000)) { + v = 0 - v; + f |= 8; + } + i = 0; + do { + d = (char)(v % r); v /= r; + if (d > 9) d += (c == 'x') ? 0x27 : 0x07; + s[i++] = d + '0'; + } while (v && i < sizeof(s)); + if (f & 8) s[i++] = '-'; + j = i; d = (f & 1) ? '0' : ' '; + while (!(f & 2) && j++ < w) xputc(d); + do xputc(s[--i]); while(i); + while (j++ < w) xputc(' '); + } +} + +void xprintf ( /* Put a formatted string to the default device */ + const char* fmt, /* Pointer to the format string */ + ... /* Optional arguments */ +) +{ + va_list arp; + + + va_start(arp, fmt); + xvprintf(fmt, arp); + va_end(arp); +} diff --git a/sdk/examples/machine_timer/.gitignore b/sdk/examples/machine_timer/.gitignore new file mode 100644 index 0000000..927c74d --- /dev/null +++ b/sdk/examples/machine_timer/.gitignore @@ -0,0 +1,8 @@ +# Object files +*.o +*.ko +*.obj +*.bin +*.dump +*.mem +machine_timer diff --git a/sdk/examples/machine_timer/Makefile b/sdk/examples/machine_timer/Makefile new file mode 100644 index 0000000..920a657 --- /dev/null +++ b/sdk/examples/machine_timer/Makefile @@ -0,0 +1,20 @@ +RISCV_ARCH := rv32im +RISCV_ABI := ilp32 +RISCV_MCMODEL := medlow + + +TARGET = machine_timer + + +CFLAGS += -DSIMULATION +#CFLAGS += -Os +#ASM_SRCS += +#LDFLAGS += +#INCLUDES += -I. + +C_SRCS := \ + main.c \ + + +BSP_DIR = ../../bsp +include ../../bsp/bsp.mk diff --git a/sdk/examples/machine_timer/README.md b/sdk/examples/machine_timer/README.md new file mode 100644 index 0000000..e51e6fb --- /dev/null +++ b/sdk/examples/machine_timer/README.md @@ -0,0 +1 @@ +机器定时器(中断)例程。 \ No newline at end of file diff --git a/sdk/examples/machine_timer/main.c b/sdk/examples/machine_timer/main.c new file mode 100644 index 0000000..08f1e91 --- /dev/null +++ b/sdk/examples/machine_timer/main.c @@ -0,0 +1,55 @@ +#include + +#include "../../bsp/include/machine_timer.h" +#include "../../bsp/include/utils.h" +#include "../../bsp/include/gpio.h" + +static volatile uint32_t count; + +int main() +{ + count = 0; + +#ifdef SIMULATION + machine_timer_set_cmp_val(5000); // 100us period + machine_timer_clear_irq_pending(); + global_irq_enable(); + machine_timer_irq_enable(1); + machine_timer_enable(1); + + while (1) { + if (count == 3) { + machine_timer_enable(0); + // TODO: do something + set_test_pass(); + break; + } + } + + return 0; +#else + machine_timer_set_cmp_val(500000); // 10ms period + machine_timer_clear_irq_pending(); + global_irq_enable(); + machine_timer_irq_enable(1); + machine_timer_enable(1); + + GPIO_REG(GPIO_CTRL) |= 0x1; // set gpio0 output mode + + while (1) { + // 500ms + if (count == 50) { + count = 0; + GPIO_REG(GPIO_DATA) ^= 0x1; // toggle led + } + } +#endif +} + +void timer_irq_handler() __attribute__((interrupt)); +void timer_irq_handler() +{ + count++; + + machine_timer_clear_irq_pending(); +}