Files
c_soft/riscv_cpu/timer.c

108 lines
2.0 KiB
C

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