add perips

Signed-off-by: liangkangnan <liangkangnan@163.com>
pull/4/head
liangkangnan 2021-05-14 21:00:57 +08:00
parent 5811bdde13
commit 6e466fbbf7
23 changed files with 666 additions and 317 deletions

View File

@ -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

View File

@ -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

View File

@ -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};

View File

@ -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);

117
rtl/perips/machine_timer.sv Normal file
View File

@ -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

View File

@ -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);

View File

@ -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])
);

12
sdk/bsp/.gitignore vendored
View File

@ -1,6 +1,6 @@
# Object files
*.o
*.ko
*.obj
*.bin
*.dump
# Object files
*.o
*.ko
*.obj
*.bin
*.dump

View File

@ -1,3 +1,3 @@
**include**: 公共头文件目录。
**include**: 公共头文件目录。
**lib**: 公共函数目录。

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,6 +1,6 @@
# Object files
*.o
*.ko
*.obj
*.bin
*.dump
# Object files
*.o
*.ko
*.obj
*.bin
*.dump

View File

@ -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;
}

View File

@ -1,29 +1,29 @@
#include <stdint.h>
#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 <stdint.h>
#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);
}

View File

@ -1,26 +1,46 @@
#include <stdint.h>
#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 <stdint.h>
#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));
}

View File

@ -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 <stdarg.h>
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); <xprintf lacks floating point support>
*/
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 <stdarg.h>
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); <xprintf lacks floating point support>
*/
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);
}

8
sdk/examples/machine_timer/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Object files
*.o
*.ko
*.obj
*.bin
*.dump
*.mem
machine_timer

View File

@ -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

View File

@ -0,0 +1 @@
机器定时器(中断)例程。

View File

@ -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();
}