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])
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Object files
|
# Object files
|
||||||
*.o
|
*.o
|
||||||
*.ko
|
*.ko
|
||||||
*.obj
|
*.obj
|
||||||
*.bin
|
*.bin
|
||||||
*.dump
|
*.dump
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
**include**: 公共头文件目录。
|
**include**: 公共头文件目录。
|
||||||
|
|
||||||
**lib**: 公共函数目录。
|
**lib**: 公共函数目录。
|
|
@ -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
|
|
@ -1,19 +1,19 @@
|
||||||
#ifndef _TRAP_CODE_H_
|
#ifndef _TRAP_CODE_H_
|
||||||
#define _TRAP_CODE_H_
|
#define _TRAP_CODE_H_
|
||||||
|
|
||||||
#define TRAP_USER_SW (0x80000000)
|
#define TRAP_USER_SW (0x80000000)
|
||||||
#define TRAP_MACH_SW (0x80000003)
|
#define TRAP_MACH_SW (0x80000003)
|
||||||
#define TRAP_USER_TIMER (0x80000004)
|
#define TRAP_USER_TIMER (0x80000004)
|
||||||
#define TRAP_MACH_TIMER (0x80000007)
|
#define TRAP_MACH_TIMER (0x80000007)
|
||||||
#define TRAP_USER_EXT (0x80000008)
|
#define TRAP_USER_EXT (0x80000008)
|
||||||
#define TRAP_MACH_EXT (0x8000000B)
|
#define TRAP_MACH_EXT (0x8000000B)
|
||||||
#define TRAP_INST_ADDR_MISA (0x00000000)
|
#define TRAP_INST_ADDR_MISA (0x00000000)
|
||||||
#define TRAP_ILLEGAL_INST (0x00000002)
|
#define TRAP_ILLEGAL_INST (0x00000002)
|
||||||
#define TRAP_BREAKPOINT (0x00000003)
|
#define TRAP_BREAKPOINT (0x00000003)
|
||||||
#define TRAP_LOAD_ADDR_MISA (0x00000004)
|
#define TRAP_LOAD_ADDR_MISA (0x00000004)
|
||||||
#define TRAP_STORE_ADDR_MISA (0x00000006)
|
#define TRAP_STORE_ADDR_MISA (0x00000006)
|
||||||
#define TRAP_ECALL_U (0x00000008)
|
#define TRAP_ECALL_U (0x00000008)
|
||||||
#define TRAP_ECALL_S (0x00000009)
|
#define TRAP_ECALL_S (0x00000009)
|
||||||
#define TRAP_ECALL_M (0x0000000B)
|
#define TRAP_ECALL_M (0x0000000B)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,28 +1,33 @@
|
||||||
#ifndef _UTILS_H_
|
#ifndef _UTILS_H_
|
||||||
#define _UTILS_H_
|
#define _UTILS_H_
|
||||||
|
|
||||||
#define CPU_FREQ_HZ (50000000) // 50MHz
|
#define CPU_FREQ_HZ (50000000) // 50MHz
|
||||||
#define CPU_FREQ_MHZ (50) // 50MHz
|
#define CPU_FREQ_MHZ (50) // 50MHz
|
||||||
|
|
||||||
|
|
||||||
#define read_csr(reg) ({ unsigned long __tmp; \
|
#define read_csr(reg) ({ unsigned long __tmp; \
|
||||||
asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
|
asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
|
||||||
__tmp; })
|
__tmp; })
|
||||||
|
|
||||||
#define write_csr(reg, val) ({ \
|
#define write_csr(reg, val) ({ \
|
||||||
if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
|
if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
|
||||||
asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
|
asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
|
||||||
else \
|
else \
|
||||||
asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
|
asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
|
||||||
|
|
||||||
|
|
||||||
#ifdef SIMULATION
|
#ifdef SIMULATION
|
||||||
#define set_test_pass() asm("li x27, 0x01")
|
#define set_test_pass() asm("li x27, 0x01")
|
||||||
#define set_test_fail() asm("li x27, 0x00")
|
#define set_test_fail() asm("li x27, 0x00")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
uint64_t get_cycle_value();
|
uint64_t get_cycle_value();
|
||||||
void busy_wait(uint32_t us);
|
void busy_wait(uint32_t us);
|
||||||
|
|
||||||
#endif
|
void global_irq_enable();
|
||||||
|
void global_irq_disable();
|
||||||
|
void mtime_irq_enable();
|
||||||
|
void mtime_irq_disable();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Universal string handler for user console interface (C)ChaN, 2011 */
|
/* Universal string handler for user console interface (C)ChaN, 2011 */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef _XPRINTF_H_
|
#ifndef _XPRINTF_H_
|
||||||
#define _XPRINTF_H_
|
#define _XPRINTF_H_
|
||||||
|
|
||||||
#define _CR_CRLF 0 /* 1: Convert \n ==> \r\n in the output char */
|
#define _CR_CRLF 0 /* 1: Convert \n ==> \r\n in the output char */
|
||||||
|
|
||||||
#define xdev_out(func) xfunc_out = (void(*)(unsigned char))(func)
|
#define xdev_out(func) xfunc_out = (void(*)(unsigned char))(func)
|
||||||
extern void (*xfunc_out)(unsigned char);
|
extern void (*xfunc_out)(unsigned char);
|
||||||
void xputc (char c);
|
void xputc (char c);
|
||||||
void xputs (const char* str);
|
void xputs (const char* str);
|
||||||
void xprintf (const char* fmt, ...);
|
void xprintf (const char* fmt, ...);
|
||||||
#define DW_CHAR sizeof(char)
|
#define DW_CHAR sizeof(char)
|
||||||
#define DW_SHORT sizeof(short)
|
#define DW_SHORT sizeof(short)
|
||||||
#define DW_LONG sizeof(long)
|
#define DW_LONG sizeof(long)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Object files
|
# Object files
|
||||||
*.o
|
*.o
|
||||||
*.ko
|
*.ko
|
||||||
*.obj
|
*.obj
|
||||||
*.bin
|
*.bin
|
||||||
*.dump
|
*.dump
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -1,29 +1,29 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "../include/uart.h"
|
#include "../include/uart.h"
|
||||||
#include "../include/xprintf.h"
|
#include "../include/xprintf.h"
|
||||||
|
|
||||||
|
|
||||||
// send one char to uart
|
// send one char to uart
|
||||||
void uart_putc(uint8_t c)
|
void uart_putc(uint8_t c)
|
||||||
{
|
{
|
||||||
while (UART0_REG(UART0_STATUS) & 0x1);
|
while (UART0_REG(UART0_STATUS) & 0x1);
|
||||||
UART0_REG(UART0_TXDATA) = c;
|
UART0_REG(UART0_TXDATA) = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block, get one char from uart.
|
// Block, get one char from uart.
|
||||||
uint8_t uart_getc()
|
uint8_t uart_getc()
|
||||||
{
|
{
|
||||||
UART0_REG(UART0_STATUS) &= ~0x2;
|
UART0_REG(UART0_STATUS) &= ~0x2;
|
||||||
while (!(UART0_REG(UART0_STATUS) & 0x2));
|
while (!(UART0_REG(UART0_STATUS) & 0x2));
|
||||||
return (UART0_REG(UART0_RXDATA) & 0xff);
|
return (UART0_REG(UART0_RXDATA) & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 115200bps, 8 N 1
|
// 115200bps, 8 N 1
|
||||||
void uart_init()
|
void uart_init()
|
||||||
{
|
{
|
||||||
// enable tx and rx
|
// enable tx and rx
|
||||||
UART0_REG(UART0_CTRL) = 0x3;
|
UART0_REG(UART0_CTRL) = 0x3;
|
||||||
|
|
||||||
xdev_out(uart_putc);
|
xdev_out(uart_putc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,46 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "../include/utils.h"
|
#include "../include/utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint64_t get_cycle_value()
|
uint64_t get_cycle_value()
|
||||||
{
|
{
|
||||||
uint64_t cycle;
|
uint64_t cycle;
|
||||||
|
|
||||||
cycle = read_csr(cycle);
|
cycle = read_csr(cycle);
|
||||||
cycle += (uint64_t)(read_csr(cycleh)) << 32;
|
cycle += (uint64_t)(read_csr(cycleh)) << 32;
|
||||||
|
|
||||||
return cycle;
|
return cycle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void busy_wait(uint32_t us)
|
void busy_wait(uint32_t us)
|
||||||
{
|
{
|
||||||
uint64_t tmp;
|
uint64_t tmp;
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
|
|
||||||
count = us * CPU_FREQ_MHZ;
|
count = us * CPU_FREQ_MHZ;
|
||||||
tmp = get_cycle_value();
|
tmp = get_cycle_value();
|
||||||
|
|
||||||
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));
|
||||||
|
}
|
||||||
|
|
|
@ -1,157 +1,157 @@
|
||||||
/*------------------------------------------------------------------------/
|
/*------------------------------------------------------------------------/
|
||||||
/ Universal string handler for user console interface
|
/ Universal string handler for user console interface
|
||||||
/-------------------------------------------------------------------------/
|
/-------------------------------------------------------------------------/
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2011, ChaN, all right reserved.
|
/ Copyright (C) 2011, ChaN, all right reserved.
|
||||||
/
|
/
|
||||||
/ * This software is a free software and there is NO WARRANTY.
|
/ * This software is a free software and there is NO WARRANTY.
|
||||||
/ * No restriction on use. You can use, modify and redistribute it for
|
/ * No restriction on use. You can use, modify and redistribute it for
|
||||||
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
|
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
|
||||||
/ * Redistributions of source code must retain the above copyright notice.
|
/ * Redistributions of source code must retain the above copyright notice.
|
||||||
/
|
/
|
||||||
/-------------------------------------------------------------------------*/
|
/-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "../include/xprintf.h"
|
#include "../include/xprintf.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
void (*xfunc_out)(unsigned char); /* Pointer to the output stream */
|
void (*xfunc_out)(unsigned char); /* Pointer to the output stream */
|
||||||
static char *outptr;
|
static char *outptr;
|
||||||
|
|
||||||
/*----------------------------------------------*/
|
/*----------------------------------------------*/
|
||||||
/* Put a character */
|
/* Put a character */
|
||||||
/*----------------------------------------------*/
|
/*----------------------------------------------*/
|
||||||
|
|
||||||
void xputc (char c)
|
void xputc (char c)
|
||||||
{
|
{
|
||||||
if (_CR_CRLF && c == '\n') xputc('\r'); /* CR -> CRLF */
|
if (_CR_CRLF && c == '\n') xputc('\r'); /* CR -> CRLF */
|
||||||
|
|
||||||
if (outptr) {
|
if (outptr) {
|
||||||
*outptr++ = (unsigned char)c;
|
*outptr++ = (unsigned char)c;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xfunc_out) xfunc_out((unsigned char)c);
|
if (xfunc_out) xfunc_out((unsigned char)c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*----------------------------------------------*/
|
/*----------------------------------------------*/
|
||||||
/* Put a null-terminated string */
|
/* Put a null-terminated string */
|
||||||
/*----------------------------------------------*/
|
/*----------------------------------------------*/
|
||||||
|
|
||||||
void xputs ( /* Put a string to the default device */
|
void xputs ( /* Put a string to the default device */
|
||||||
const char* str /* Pointer to the string */
|
const char* str /* Pointer to the string */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
while (*str)
|
while (*str)
|
||||||
xputc(*str++);
|
xputc(*str++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*----------------------------------------------*/
|
/*----------------------------------------------*/
|
||||||
/* Formatted string output */
|
/* Formatted string output */
|
||||||
/*----------------------------------------------*/
|
/*----------------------------------------------*/
|
||||||
/* xprintf("%d", 1234); "1234"
|
/* xprintf("%d", 1234); "1234"
|
||||||
xprintf("%6d,%3d%%", -200, 5); " -200, 5%"
|
xprintf("%6d,%3d%%", -200, 5); " -200, 5%"
|
||||||
xprintf("%-6u", 100); "100 "
|
xprintf("%-6u", 100); "100 "
|
||||||
xprintf("%ld", 12345678L); "12345678"
|
xprintf("%ld", 12345678L); "12345678"
|
||||||
xprintf("%04x", 0xA3); "00a3"
|
xprintf("%04x", 0xA3); "00a3"
|
||||||
xprintf("%08LX", 0x123ABC); "00123ABC"
|
xprintf("%08LX", 0x123ABC); "00123ABC"
|
||||||
xprintf("%016b", 0x550F); "0101010100001111"
|
xprintf("%016b", 0x550F); "0101010100001111"
|
||||||
xprintf("%s", "String"); "String"
|
xprintf("%s", "String"); "String"
|
||||||
xprintf("%-4s", "abc"); "abc "
|
xprintf("%-4s", "abc"); "abc "
|
||||||
xprintf("%4s", "abc"); " abc"
|
xprintf("%4s", "abc"); " abc"
|
||||||
xprintf("%c", 'a'); "a"
|
xprintf("%c", 'a'); "a"
|
||||||
xprintf("%f", 10.0); <xprintf lacks floating point support>
|
xprintf("%f", 10.0); <xprintf lacks floating point support>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static
|
static
|
||||||
void xvprintf (
|
void xvprintf (
|
||||||
const char* fmt, /* Pointer to the format string */
|
const char* fmt, /* Pointer to the format string */
|
||||||
va_list arp /* Pointer to arguments */
|
va_list arp /* Pointer to arguments */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
unsigned int r, i, j, w, f;
|
unsigned int r, i, j, w, f;
|
||||||
unsigned long v;
|
unsigned long v;
|
||||||
char s[16], c, d, *p;
|
char s[16], c, d, *p;
|
||||||
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
c = *fmt++; /* Get a char */
|
c = *fmt++; /* Get a char */
|
||||||
if (!c) break; /* End of format? */
|
if (!c) break; /* End of format? */
|
||||||
if (c != '%') { /* Pass through it if not a % sequense */
|
if (c != '%') { /* Pass through it if not a % sequense */
|
||||||
xputc(c); continue;
|
xputc(c); continue;
|
||||||
}
|
}
|
||||||
f = 0;
|
f = 0;
|
||||||
c = *fmt++; /* Get first char of the sequense */
|
c = *fmt++; /* Get first char of the sequense */
|
||||||
if (c == '0') { /* Flag: '0' padded */
|
if (c == '0') { /* Flag: '0' padded */
|
||||||
f = 1; c = *fmt++;
|
f = 1; c = *fmt++;
|
||||||
} else {
|
} else {
|
||||||
if (c == '-') { /* Flag: left justified */
|
if (c == '-') { /* Flag: left justified */
|
||||||
f = 2; c = *fmt++;
|
f = 2; c = *fmt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (w = 0; c >= '0' && c <= '9'; c = *fmt++) /* Minimum width */
|
for (w = 0; c >= '0' && c <= '9'; c = *fmt++) /* Minimum width */
|
||||||
w = w * 10 + c - '0';
|
w = w * 10 + c - '0';
|
||||||
if (c == 'l' || c == 'L') { /* Prefix: Size is long int */
|
if (c == 'l' || c == 'L') { /* Prefix: Size is long int */
|
||||||
f |= 4; c = *fmt++;
|
f |= 4; c = *fmt++;
|
||||||
}
|
}
|
||||||
if (!c) break; /* End of format? */
|
if (!c) break; /* End of format? */
|
||||||
d = c;
|
d = c;
|
||||||
if (d >= 'a') d -= 0x20;
|
if (d >= 'a') d -= 0x20;
|
||||||
switch (d) { /* Type is... */
|
switch (d) { /* Type is... */
|
||||||
case 'S' : /* String */
|
case 'S' : /* String */
|
||||||
p = va_arg(arp, char*);
|
p = va_arg(arp, char*);
|
||||||
for (j = 0; p[j]; j++) ;
|
for (j = 0; p[j]; j++) ;
|
||||||
while (!(f & 2) && j++ < w) xputc(' ');
|
while (!(f & 2) && j++ < w) xputc(' ');
|
||||||
xputs(p);
|
xputs(p);
|
||||||
while (j++ < w) xputc(' ');
|
while (j++ < w) xputc(' ');
|
||||||
continue;
|
continue;
|
||||||
case 'C' : /* Character */
|
case 'C' : /* Character */
|
||||||
xputc((char)va_arg(arp, int)); continue;
|
xputc((char)va_arg(arp, int)); continue;
|
||||||
case 'B' : /* Binary */
|
case 'B' : /* Binary */
|
||||||
r = 2; break;
|
r = 2; break;
|
||||||
case 'O' : /* Octal */
|
case 'O' : /* Octal */
|
||||||
r = 8; break;
|
r = 8; break;
|
||||||
case 'D' : /* Signed decimal */
|
case 'D' : /* Signed decimal */
|
||||||
case 'U' : /* Unsigned decimal */
|
case 'U' : /* Unsigned decimal */
|
||||||
r = 10; break;
|
r = 10; break;
|
||||||
case 'X' : /* Hexdecimal */
|
case 'X' : /* Hexdecimal */
|
||||||
r = 16; break;
|
r = 16; break;
|
||||||
default: /* Unknown type (passthrough) */
|
default: /* Unknown type (passthrough) */
|
||||||
xputc(c); continue;
|
xputc(c); continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get an argument and put it in numeral */
|
/* 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));
|
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)) {
|
if (d == 'D' && (v & 0x80000000)) {
|
||||||
v = 0 - v;
|
v = 0 - v;
|
||||||
f |= 8;
|
f |= 8;
|
||||||
}
|
}
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
d = (char)(v % r); v /= r;
|
d = (char)(v % r); v /= r;
|
||||||
if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
|
if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
|
||||||
s[i++] = d + '0';
|
s[i++] = d + '0';
|
||||||
} while (v && i < sizeof(s));
|
} while (v && i < sizeof(s));
|
||||||
if (f & 8) s[i++] = '-';
|
if (f & 8) s[i++] = '-';
|
||||||
j = i; d = (f & 1) ? '0' : ' ';
|
j = i; d = (f & 1) ? '0' : ' ';
|
||||||
while (!(f & 2) && j++ < w) xputc(d);
|
while (!(f & 2) && j++ < w) xputc(d);
|
||||||
do xputc(s[--i]); while(i);
|
do xputc(s[--i]); while(i);
|
||||||
while (j++ < w) xputc(' ');
|
while (j++ < w) xputc(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void xprintf ( /* Put a formatted string to the default device */
|
void xprintf ( /* Put a formatted string to the default device */
|
||||||
const char* fmt, /* Pointer to the format string */
|
const char* fmt, /* Pointer to the format string */
|
||||||
... /* Optional arguments */
|
... /* Optional arguments */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
va_list arp;
|
va_list arp;
|
||||||
|
|
||||||
|
|
||||||
va_start(arp, fmt);
|
va_start(arp, fmt);
|
||||||
xvprintf(fmt, arp);
|
xvprintf(fmt, arp);
|
||||||
va_end(arp);
|
va_end(arp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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