添加timer外设
1.解决while(1)执行异常的问题
This commit is contained in:
46
cpu/riscv.c
46
cpu/riscv.c
@@ -1,12 +1,15 @@
|
||||
|
||||
#include "riscv.h"
|
||||
#include "debug.h"
|
||||
#include "print.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "errno.h"
|
||||
#include "string.h"
|
||||
|
||||
// cpu外设
|
||||
#include "print.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include "../main.h"
|
||||
|
||||
#define device_write(riscv,addr,value) \
|
||||
@@ -194,30 +197,35 @@ void ins_auipc(riscv_t* riscv, int imm, int rd) {
|
||||
void ins_beq(riscv_t* riscv, int rs2, int rs1, int imm) {
|
||||
if (riscv->reg[rs1] == riscv->reg[rs2]) {
|
||||
riscv->pc += imm;
|
||||
riscv->pc_modify = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ins_bge(riscv_t* riscv, int rs2, int rs1, int imm) {
|
||||
if ((int)riscv->reg[rs1] >= (int)riscv->reg[rs2]) {
|
||||
riscv->pc += imm;
|
||||
riscv->pc_modify = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ins_bgeu(riscv_t* riscv, int rs2, int rs1, int imm) {
|
||||
if (riscv->reg[rs1] >= riscv->reg[rs2]) {
|
||||
riscv->pc += imm;
|
||||
riscv->pc_modify = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ins_blt(riscv_t* riscv, int rs2, int rs1, int imm) {
|
||||
if ((int)riscv->reg[rs1] < (int)riscv->reg[rs2]) {
|
||||
riscv->pc += imm;
|
||||
riscv->pc_modify = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ins_bltu(riscv_t* riscv, int rs2, int rs1, int imm) {
|
||||
if (riscv->reg[rs1] < riscv->reg[rs2]) {
|
||||
riscv->pc += imm;
|
||||
riscv->pc_modify = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,6 +233,7 @@ void ins_bne(riscv_t* riscv, int rs2, int rs1, int imm) {
|
||||
// printf("bne %d %d imm=%08x\n", rs2, rs1, imm);
|
||||
if (riscv->reg[rs1] != riscv->reg[rs2]) {
|
||||
riscv->pc += imm;
|
||||
riscv->pc_modify = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,6 +285,7 @@ void ins_ebreak(riscv_t* riscv) {
|
||||
void ins_jal(riscv_t* riscv, int imm, int rd) {
|
||||
riscv->reg[rd] = riscv->pc + 4;
|
||||
riscv->pc += imm;
|
||||
riscv->pc_modify = 1;
|
||||
}
|
||||
|
||||
void ins_jalr(riscv_t* riscv, int rs1, int imm, int rd) {
|
||||
@@ -283,6 +293,7 @@ void ins_jalr(riscv_t* riscv, int rs1, int imm, int rd) {
|
||||
t = riscv->pc + 4;
|
||||
riscv->pc = (riscv->reg[rs1] + imm) & (~1);
|
||||
riscv->reg[rd] = t;
|
||||
riscv->pc_modify = 1;
|
||||
}
|
||||
|
||||
void ins_lb(riscv_t* riscv, int rs1, int imm, int rd) {
|
||||
@@ -335,6 +346,7 @@ void ins_lui(riscv_t* riscv, int imm, int rd) {
|
||||
|
||||
void ins_mret(riscv_t* riscv) {
|
||||
riscv->pc = riscv->mepc;
|
||||
riscv->pc_modify = 1;
|
||||
if (riscv->mstatus & MSTATUS_MPIE) {
|
||||
riscv->mstatus &= ~MSTATUS_MPIE;
|
||||
riscv->mstatus |= MSTATUS_MIE;
|
||||
@@ -692,12 +704,33 @@ int riscv_register_device(riscv_t* riscv, const device_t* device) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 跑外设(执行外设逻辑,设置中断等)
|
||||
int riscv_device_run(riscv_t* riscv) {
|
||||
for (int i = 0;i < riscv->device_num;i++) {
|
||||
if (riscv->device_list[i] && riscv->device_list[i]->run) {
|
||||
riscv->device_list[i]->run(riscv, riscv->device_list[i]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 外设初始化
|
||||
int riscv_device_init(riscv_t* riscv) {
|
||||
for (int i = 0;i < riscv->device_num;i++) {
|
||||
if (riscv->device_list[i] && riscv->device_list[i]->init) {
|
||||
riscv->device_list[i]->init(riscv->device_list[i]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int riscv_init(riscv_t* riscv, uint32_t* rom, uint32_t rom_addr_base, uint32_t rom_size) {
|
||||
riscv->rom = rom;
|
||||
riscv->rom_size = rom_size;
|
||||
riscv->rom_addr_base = rom_addr_base;
|
||||
riscv->pc = riscv->rom_addr_base;
|
||||
riscv->pc_modify = 0;
|
||||
riscv->ra = 0xffffffff;
|
||||
return 0;
|
||||
}
|
||||
@@ -708,6 +741,7 @@ int riscv_enter_trap(riscv_t* riscv, int is_interrupt, int irq_num) {
|
||||
riscv->mepc = riscv->pc;
|
||||
riscv->mcause = (is_interrupt << 31) | irq_num;
|
||||
riscv->pc = riscv->mtvec;
|
||||
riscv->pc_modify = 1;
|
||||
// 禁用全局中断
|
||||
if (riscv->mstatus & MSTATUS_MIE) {
|
||||
riscv->mstatus &= ~MSTATUS_MIE;
|
||||
@@ -745,7 +779,6 @@ int riscv_irq_check(riscv_t* riscv) {
|
||||
|
||||
int riscv_run(riscv_t* riscv) {
|
||||
int ret = 0;
|
||||
uint32_t pc;
|
||||
while (1) {
|
||||
if (riscv->pc == 0xfffffffe && riscv->ra == 0xffffffff) {
|
||||
break;
|
||||
@@ -763,17 +796,20 @@ int riscv_run(riscv_t* riscv) {
|
||||
}
|
||||
uint32_t instr = riscv->rom[(riscv->pc - riscv->rom_addr_base) >> 2];
|
||||
// printf("pc: %08x instr: %08x\n", riscv->pc, instr);
|
||||
pc = riscv->pc;
|
||||
ret = riscv_decode(riscv, instr);
|
||||
riscv->zero = 0;
|
||||
// 如果指令修改了pc,则以修改后的为准,如果pc未被修改,则继续执行下一条指令
|
||||
if (riscv->pc == pc) {
|
||||
if (!riscv->pc_modify) {
|
||||
riscv->pc += 4;
|
||||
} else {
|
||||
// printf("pc modify=1\n");
|
||||
riscv->pc_modify = 0;
|
||||
}
|
||||
if (riscv->exc_code > 0) {
|
||||
riscv_enter_trap(riscv, 0, riscv->exc_code);
|
||||
riscv->exc_code = 0;
|
||||
}
|
||||
riscv_device_run(riscv);
|
||||
riscv_irq_check(riscv);
|
||||
// riscv_print(riscv);
|
||||
if(ret){
|
||||
@@ -843,7 +879,9 @@ int thread_fun(void* t)
|
||||
fclose(file);
|
||||
|
||||
riscv_register_device(&riscv, print_dev());
|
||||
riscv_register_device(&riscv, timer_dev());
|
||||
riscv_init(&riscv, riscv.rom, 0x80000000, riscv.rom_size);
|
||||
riscv_device_init(&riscv);
|
||||
riscv_run(&riscv);
|
||||
|
||||
return 0;
|
||||
|
10
cpu/riscv.h
10
cpu/riscv.h
@@ -182,14 +182,17 @@
|
||||
#define DEVICE_MAX_NUM 16
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct riscv_t;
|
||||
typedef struct device_t{
|
||||
uint32_t addr;
|
||||
uint32_t size;
|
||||
uint32_t (*read)(uint32_t addr);
|
||||
void (*write)(uint32_t addr,uint32_t data);
|
||||
void (*write)(uint32_t addr, uint32_t data);
|
||||
void (*run)(struct riscv_t *riscv,const struct device_t* device);
|
||||
void (*init)(const struct device_t* device);
|
||||
}device_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct riscv_t{
|
||||
uint32_t mem[MEM_SIZE];
|
||||
const device_t* device_list[DEVICE_MAX_NUM];
|
||||
uint32_t device_num;
|
||||
@@ -197,6 +200,7 @@ typedef struct {
|
||||
uint32_t rom_size;
|
||||
uint32_t rom_addr_base;
|
||||
uint32_t pc;
|
||||
uint32_t pc_modify;// pc 指针已经被修改 不要自动递增
|
||||
int32_t exc_code;
|
||||
uint32_t reg[32];
|
||||
uint32_t csrs[4096];
|
||||
|
107
cpu/timer.c
Normal file
107
cpu/timer.c
Normal file
@@ -0,0 +1,107 @@
|
||||
|
||||
#include "stdio.h"
|
||||
#include "sys/time.h"
|
||||
#include "errno.h"
|
||||
#include "pthread.h"
|
||||
#include "timer.h"
|
||||
|
||||
|
||||
#define BASE_ADDR 0x40001000
|
||||
#define SIZE 0x4
|
||||
|
||||
|
||||
void milliseconds_sleep(unsigned long mSec){
|
||||
struct timeval tv;
|
||||
tv.tv_sec=mSec/1000;
|
||||
tv.tv_usec=(mSec%1000)*1000;
|
||||
int err;
|
||||
do{
|
||||
err=select(0,NULL,NULL,NULL,&tv);
|
||||
}while(err<0 && errno==EINTR);
|
||||
}
|
||||
|
||||
#define dev_wr(addr) g_map[(addr-BASE_ADDR) >> 2]
|
||||
#define dev_wrb(addr) ((uint8_t *)g_map)[(addr-BASE_ADDR)]
|
||||
#define dev_wrh(addr) ((uint16_t *)g_map)[(addr-BASE_ADDR) >> 1]
|
||||
|
||||
|
||||
|
||||
static uint32_t g_map[1];
|
||||
|
||||
|
||||
static uint32_t read(uint32_t addr) {
|
||||
if (!(addr & 0x3)) {
|
||||
return dev_wr(addr);
|
||||
} else if (!(addr & 0x1)) {
|
||||
return dev_wrh(addr);
|
||||
} else {
|
||||
return dev_wrb(addr);
|
||||
}
|
||||
}
|
||||
|
||||
static void write(uint32_t addr, uint32_t data) {
|
||||
// printf("print: write data=%x\n", data);
|
||||
if (!(addr & 0x3)) {
|
||||
dev_wr(addr) = data;
|
||||
} else if (!(addr & 0x1)) {
|
||||
dev_wrh(addr) = data;
|
||||
} else {
|
||||
dev_wrb(addr) = data;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint32_t ins_count;
|
||||
pthread_mutex_t lock; /* 互斥锁定义 */
|
||||
} mtimer_t;
|
||||
|
||||
static mtimer_t g_self;
|
||||
|
||||
static void run(riscv_t *riscv, const struct device_t* device) {
|
||||
int irq = 0;
|
||||
// printf("timer_run...\n");
|
||||
pthread_mutex_lock(&g_self.lock);
|
||||
dev_wr(BASE_ADDR) += g_self.ins_count;
|
||||
if (g_self.ins_count) {
|
||||
irq = 1;
|
||||
}
|
||||
g_self.ins_count = 0;
|
||||
pthread_mutex_unlock(&g_self.lock);
|
||||
if (irq) {
|
||||
riscv->mip |= MIP_MTIP;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *timer_thread(void *arg) {
|
||||
while (1) {
|
||||
milliseconds_sleep(1000);
|
||||
pthread_mutex_lock(&g_self.lock);
|
||||
g_self.ins_count++;
|
||||
pthread_mutex_unlock(&g_self.lock);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void init(const struct device_t* device) {
|
||||
pthread_t tid;
|
||||
pthread_mutex_init(&g_self.lock, NULL);
|
||||
dev_wr(BASE_ADDR) = 0x0;
|
||||
pthread_create(&tid, NULL, timer_thread, NULL);
|
||||
}
|
||||
|
||||
const static device_t g_timer = {
|
||||
.addr = BASE_ADDR,
|
||||
.size = SIZE,
|
||||
.read = read,
|
||||
.write = write,
|
||||
.run = run,
|
||||
.init = init,
|
||||
};
|
||||
|
||||
|
||||
const device_t* timer_dev() {
|
||||
return &g_timer;
|
||||
}
|
||||
|
||||
|
9
cpu/timer.h
Normal file
9
cpu/timer.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef timer_h__
|
||||
#define timer_h__
|
||||
|
||||
#include "riscv.h"
|
||||
|
||||
|
||||
const device_t* timer_dev();
|
||||
|
||||
#endif
|
@@ -66,7 +66,7 @@ void trap_entry(uint32_t irq_num, stack_context *stack) {
|
||||
my_printf("x31(t6): %08x\n", stack->t6);
|
||||
my_printf("mstatus: %08x\n", stack->mstatus);
|
||||
my_printf("mepc: %08x\n", stack->mepc);
|
||||
my_printf("mtval: %08x\n", read_csr(mtval));
|
||||
// my_printf("mtval: %08x\n", read_csr(mtval));
|
||||
|
||||
// 函数调用错误,直接跳过这个函数
|
||||
if(irq_num==1){
|
||||
|
Reference in New Issue
Block a user