parent
5811bdde13
commit
6e466fbbf7
|
@ -37,6 +37,7 @@
|
||||||
../rtl/perips/rom.sv
|
../rtl/perips/rom.sv
|
||||||
../rtl/perips/timer.sv
|
../rtl/perips/timer.sv
|
||||||
../rtl/perips/uart.sv
|
../rtl/perips/uart.sv
|
||||||
|
../rtl/perips/machine_timer.sv
|
||||||
|
|
||||||
../rtl/sys_bus/obi_interconnect.sv
|
../rtl/sys_bus/obi_interconnect.sv
|
||||||
../rtl/sys_bus/obi_interconnect_master_sel.sv
|
../rtl/sys_bus/obi_interconnect_master_sel.sv
|
||||||
|
|
|
@ -40,6 +40,9 @@
|
||||||
// UART
|
// UART
|
||||||
`define UART_ADDR_MASK ~32'hffff
|
`define UART_ADDR_MASK ~32'hffff
|
||||||
`define UART_ADDR_BASE 32'h50000000
|
`define UART_ADDR_BASE 32'h50000000
|
||||||
|
// Machine Timer
|
||||||
|
`define MTIMER_ADDR_MASK ~32'hffff
|
||||||
|
`define MTIMER_ADDR_BASE 32'hA0000000
|
||||||
// SIM CTRL
|
// SIM CTRL
|
||||||
`define SIM_CTRL_ADDR_MASK ~32'hffff
|
`define SIM_CTRL_ADDR_MASK ~32'hffff
|
||||||
`define SIM_CTRL_ADDR_BASE 32'hE0000000
|
`define SIM_CTRL_ADDR_BASE 32'hE0000000
|
||||||
|
|
|
@ -89,14 +89,14 @@ module exception (
|
||||||
localparam FAST_INT_OFFSET = 44;
|
localparam FAST_INT_OFFSET = 44;
|
||||||
|
|
||||||
|
|
||||||
localparam S_IDLE = 4'b0001;
|
localparam S_IDLE = 5'b00001;
|
||||||
localparam S_W_MEPC = 4'b0010;
|
localparam S_W_MEPC = 5'b00010;
|
||||||
localparam S_W_DCSR = 4'b0100;
|
localparam S_W_DCSR = 5'b00100;
|
||||||
localparam S_ASSERT = 4'b1000;
|
localparam S_ASSERT = 5'b01000;
|
||||||
|
localparam S_W_MSTATUS = 5'b10000;
|
||||||
|
|
||||||
reg debug_mode_d, debug_mode_q;
|
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] assert_addr_d, assert_addr_q;
|
||||||
reg[31:0] return_addr_d, return_addr_q;
|
reg[31:0] return_addr_d, return_addr_q;
|
||||||
reg csr_we;
|
reg csr_we;
|
||||||
|
@ -239,13 +239,13 @@ module exception (
|
||||||
|
|
||||||
case (state_q)
|
case (state_q)
|
||||||
S_IDLE: begin
|
S_IDLE: begin
|
||||||
if (int_or_exception_req) begin
|
if (int_or_exception_req & (!debug_mode_q)) begin
|
||||||
csr_we = 1'b1;
|
csr_we = 1'b1;
|
||||||
csr_waddr = {20'h0, `CSR_MCAUSE};
|
csr_waddr = {20'h0, `CSR_MCAUSE};
|
||||||
csr_wdata = int_or_exception_cause;
|
csr_wdata = int_or_exception_cause;
|
||||||
assert_addr_d = mtvec_i + int_or_exception_offset;
|
assert_addr_d = mtvec_i + int_or_exception_offset;
|
||||||
return_addr_d = inst_addr_i;
|
return_addr_d = inst_addr_i;
|
||||||
state_d = S_W_MEPC;
|
state_d = S_W_MSTATUS;
|
||||||
end else if (debug_mode_req) begin
|
end else if (debug_mode_req) begin
|
||||||
debug_mode_d = 1'b1;
|
debug_mode_d = 1'b1;
|
||||||
if (enter_debug_cause_debugger_req |
|
if (enter_debug_cause_debugger_req |
|
||||||
|
@ -269,6 +269,9 @@ module exception (
|
||||||
end
|
end
|
||||||
end else if (inst_mret_i) begin
|
end else if (inst_mret_i) begin
|
||||||
assert_addr_d = mepc_i;
|
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;
|
state_d = S_ASSERT;
|
||||||
end else if (inst_dret_i) begin
|
end else if (inst_dret_i) begin
|
||||||
assert_addr_d = dpc_i;
|
assert_addr_d = dpc_i;
|
||||||
|
@ -277,6 +280,13 @@ module exception (
|
||||||
end
|
end
|
||||||
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
|
S_W_MEPC: begin
|
||||||
csr_we = 1'b1;
|
csr_we = 1'b1;
|
||||||
csr_waddr = {20'h0, `CSR_MEPC};
|
csr_waddr = {20'h0, `CSR_MEPC};
|
||||||
|
|
|
@ -46,8 +46,8 @@ module gpio(
|
||||||
assign reg_ctrl = gpio_ctrl;
|
assign reg_ctrl = gpio_ctrl;
|
||||||
assign reg_data = gpio_data;
|
assign reg_data = gpio_data;
|
||||||
|
|
||||||
wire wen = we_i & req_valid_i;
|
wire wen = we_i;
|
||||||
wire ren = (~we_i) & req_valid_i;
|
wire ren = (~we_i);
|
||||||
wire write_reg_ctrl_en = wen & (addr_i[3:0] == GPIO_CTRL);
|
wire write_reg_ctrl_en = wen & (addr_i[3:0] == GPIO_CTRL);
|
||||||
wire write_reg_data_en = wen & (addr_i[3:0] == GPIO_DATA);
|
wire write_reg_data_en = wen & (addr_i[3:0] == GPIO_DATA);
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -85,8 +85,8 @@ module uart(
|
||||||
// UART接收数据寄存器,只读
|
// UART接收数据寄存器,只读
|
||||||
reg[31:0] uart_rx;
|
reg[31:0] uart_rx;
|
||||||
|
|
||||||
wire wen = we_i & req_valid_i;
|
wire wen = we_i;
|
||||||
wire ren = (~we_i) & req_valid_i;
|
wire ren = (~we_i);
|
||||||
wire write_reg_ctrl_en = wen & (addr_i[7:0] == UART_CTRL);
|
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_status_en = wen & (addr_i[7:0] == UART_STATUS);
|
||||||
wire write_reg_baud_en = wen & (addr_i[7:0] == UART_BAUD);
|
wire write_reg_baud_en = wen & (addr_i[7:0] == UART_BAUD);
|
||||||
|
|
|
@ -39,9 +39,9 @@ module tinyriscv_soc_top(
|
||||||
|
|
||||||
localparam int MASTERS = 3; // Number of master ports
|
localparam int MASTERS = 3; // Number of master ports
|
||||||
`ifdef VERILATOR
|
`ifdef VERILATOR
|
||||||
localparam int SLAVES = 4; // Number of slave ports
|
localparam int SLAVES = 7; // Number of slave ports
|
||||||
`else
|
`else
|
||||||
localparam int SLAVES = 3; // Number of slave ports
|
localparam int SLAVES = 6; // Number of slave ports
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
// masters
|
// masters
|
||||||
|
@ -53,8 +53,11 @@ module tinyriscv_soc_top(
|
||||||
localparam int Rom = 0;
|
localparam int Rom = 0;
|
||||||
localparam int Ram = 1;
|
localparam int Ram = 1;
|
||||||
localparam int JtagDevice = 2;
|
localparam int JtagDevice = 2;
|
||||||
|
localparam int Mtimer = 3;
|
||||||
|
localparam int Gpio = 4;
|
||||||
|
localparam int Uart = 5;
|
||||||
`ifdef VERILATOR
|
`ifdef VERILATOR
|
||||||
localparam int SimCtrl = 3;
|
localparam int SimCtrl = 6;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,6 +96,12 @@ module tinyriscv_soc_top(
|
||||||
wire debug_req;
|
wire debug_req;
|
||||||
wire core_halted;
|
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;
|
assign halted_ind_pin = core_halted;
|
||||||
|
|
||||||
tinyriscv_core #(
|
tinyriscv_core #(
|
||||||
|
@ -120,7 +129,7 @@ module tinyriscv_soc_top(
|
||||||
.data_err_i (1'b0),
|
.data_err_i (1'b0),
|
||||||
|
|
||||||
.irq_software_i (1'b0),
|
.irq_software_i (1'b0),
|
||||||
.irq_timer_i (1'b0),
|
.irq_timer_i (mtimer_irq),
|
||||||
.irq_external_i (1'b0),
|
.irq_external_i (1'b0),
|
||||||
.irq_fast_i (15'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_mask[Rom] = `ROM_ADDR_MASK;
|
||||||
assign slave_addr_base[Rom] = `ROM_ADDR_BASE;
|
assign slave_addr_base[Rom] = `ROM_ADDR_BASE;
|
||||||
// 指令存储器
|
// 1.指令存储器
|
||||||
rom #(
|
rom #(
|
||||||
.DP(`ROM_DEPTH)
|
.DP(`ROM_DEPTH)
|
||||||
) u_rom (
|
) u_rom (
|
||||||
|
@ -144,7 +153,7 @@ module tinyriscv_soc_top(
|
||||||
|
|
||||||
assign slave_addr_mask[Ram] = `RAM_ADDR_MASK;
|
assign slave_addr_mask[Ram] = `RAM_ADDR_MASK;
|
||||||
assign slave_addr_base[Ram] = `RAM_ADDR_BASE;
|
assign slave_addr_base[Ram] = `RAM_ADDR_BASE;
|
||||||
// 数据存储器
|
// 2.数据存储器
|
||||||
ram #(
|
ram #(
|
||||||
.DP(`RAM_DEPTH)
|
.DP(`RAM_DEPTH)
|
||||||
) u_ram (
|
) u_ram (
|
||||||
|
@ -157,17 +166,70 @@ module tinyriscv_soc_top(
|
||||||
.data_o (slave_rdata[Ram])
|
.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
|
`ifdef VERILATOR
|
||||||
assign slave_addr_mask[SimCtrl] = `SIM_CTRL_ADDR_MASK;
|
assign slave_addr_mask[SimCtrl] = `SIM_CTRL_ADDR_MASK;
|
||||||
assign slave_addr_base[SimCtrl] = `SIM_CTRL_ADDR_BASE;
|
assign slave_addr_base[SimCtrl] = `SIM_CTRL_ADDR_BASE;
|
||||||
|
// 6.仿真控制模块
|
||||||
sim_ctrl u_sim_ctrl(
|
sim_ctrl u_sim_ctrl(
|
||||||
.clk_i(clk),
|
.clk_i (clk),
|
||||||
.rst_ni(ndmreset_n),
|
.rst_ni (ndmreset_n),
|
||||||
.req_i(),
|
.req_i (),
|
||||||
.gnt_o(),
|
.gnt_o (),
|
||||||
.addr_i(slave_addr[SimCtrl]),
|
.addr_i (slave_addr[SimCtrl]),
|
||||||
.we_i(slave_we[SimCtrl]),
|
.we_i (slave_we[SimCtrl]),
|
||||||
.be_i(slave_be[SimCtrl]),
|
.be_i (slave_be[SimCtrl]),
|
||||||
.wdata_i(slave_wdata[SimCtrl]),
|
.wdata_i(slave_wdata[SimCtrl]),
|
||||||
.rdata_o(slave_rdata[SimCtrl])
|
.rdata_o(slave_rdata[SimCtrl])
|
||||||
);
|
);
|
||||||
|
|
|
@ -22,6 +22,7 @@ C_SRCS += $(BSP_DIR)/lib/utils.c
|
||||||
C_SRCS += $(BSP_DIR)/lib/xprintf.c
|
C_SRCS += $(BSP_DIR)/lib/xprintf.c
|
||||||
C_SRCS += $(BSP_DIR)/lib/uart.c
|
C_SRCS += $(BSP_DIR)/lib/uart.c
|
||||||
C_SRCS += $(BSP_DIR)/lib/sim_ctrl.c
|
C_SRCS += $(BSP_DIR)/lib/sim_ctrl.c
|
||||||
|
C_SRCS += $(BSP_DIR)/lib/machine_timer.c
|
||||||
|
|
||||||
LINKER_SCRIPT := $(BSP_DIR)/link.lds
|
LINKER_SCRIPT := $(BSP_DIR)/link.lds
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -25,4 +25,9 @@
|
||||||
uint64_t get_cycle_value();
|
uint64_t get_cycle_value();
|
||||||
void busy_wait(uint32_t us);
|
void busy_wait(uint32_t us);
|
||||||
|
|
||||||
|
void global_irq_enable();
|
||||||
|
void global_irq_disable();
|
||||||
|
void mtime_irq_enable();
|
||||||
|
void mtime_irq_disable();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -24,3 +24,23 @@ void busy_wait(uint32_t us)
|
||||||
|
|
||||||
while (get_cycle_value() < (tmp + count));
|
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));
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Object files
|
||||||
|
*.o
|
||||||
|
*.ko
|
||||||
|
*.obj
|
||||||
|
*.bin
|
||||||
|
*.dump
|
||||||
|
*.mem
|
||||||
|
machine_timer
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
机器定时器(中断)例程。
|
|
@ -0,0 +1,55 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
Loading…
Reference in New Issue