108 lines
2.0 KiB
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;
|
|
}
|
|
|
|
|