TraSH/sim/xemu/perips/timer/timer.c

64 lines
1.5 KiB
C

/**
* @brief Define Peripheral Function
* @note
* @param name, peripheral name
* *inst_info, instruction information
* @retval MemoryMap_t*
*/
#define TIMER_REG_CR 0x00
#define TIMER_REG_SR 0x04
#define TIMER_REG_PSC 0x08
#define TIMER_REG_LOAD 0x0c
#define TIMER_REG_COUNT 0x10
int _timer(const char *name, InstInfo_t *inst_info)
{
MemoryMap_t *pm = _find_by_name(name);
if ( !pm ) {
return 0;
}
static uint32_t _timeup = 0;
if ( BIT(pm->memory->buf[TIMER_REG_CR/4], 0) ) // [0]: enbale
{
_timeup ++;
if ( 0 == pm->memory->buf[TIMER_REG_COUNT/4] ) {
pm->memory->buf[TIMER_REG_COUNT/4] = pm->memory->buf[TIMER_REG_LOAD/4];
}
if ( _timeup > pm->memory->buf[TIMER_REG_PSC/4] )
{
_timeup = 0;
pm->memory->buf[TIMER_REG_COUNT/4] --;
if ( 0 == pm->memory->buf[TIMER_REG_COUNT/4] ) {
_s_irq |= INT_IRQ_TIMER1;
}
}
} else {
_timeup = 0;
pm->memory->buf[TIMER_REG_COUNT/4] = 0;
}
if ( DATA_MASK(inst_info->mem_addr, 4, 28) != DATA_MASK(pm->address, 4, 28) ) {
return 0;
}
if ( inst_info->mem_we )
{
switch ( DATA_MASK(inst_info->mem_addr, 8, 0) )
{
case TIMER_REG_SR : {
pm->memory->buf[TIMER_REG_SR/4] &= ~SHIFT_L(BIT(inst_info->mem_data, 0), 0); // [0]: timing-up flag
break;
}
}
}
return 0;
}