38,8 → 38,8 |
#include <arch/memstr.h> |
#include <arch/regutils.h> |
#include <interrupt.h> |
#include <arch/drivers/gxemul.h> |
|
|
#define PREFETCH_OFFSET 0x8 |
#define BRANCH_OPCODE 0xea000000 |
#define LDR_OPCODE 0xe59ff000 |
47,21 → 47,7 |
#define EXC_VECTORS_SIZE 0x20 |
#define EXC_VECTORS 0x8 |
|
/* GXEmul interrupt controller macros |
TODO might go to drivers/ together with servicing functions |
*/ |
/* IRQ Controller device is added in a special premium gxemul |
* edition at www.ms.mff.cuni.cz/~stepp3am/mygxemul-0.4.4.1.tar.gz |
* :) |
*/ |
#define IRQ_CONTROLLER_CAUSE 0x0000000016000000 |
#define IRQ_CONTROLLER_MAX_IRQ 8 |
|
/* IRQs */ |
#define CONSOLE_IRQ 2 |
#define TIMER_IRQ 4 |
|
|
#define SAVE_REGS_TO_STACK \ |
asm("stmfd sp!, {r0-r12, sp, lr}"); \ |
asm("mrs r14, spsr"); \ |
157,15 → 143,22 |
*/ |
static void irq_exception(int exc_no, istate_t* istate) |
{ |
/* TODO this will call interrupt dispatching routine |
* |
*/ |
|
uint32_t sources = *(uint32_t*) IRQ_CONTROLLER_CAUSE; |
uint32_t sources = gxemul_irqc_get_sources(); |
int i = 0; |
int noirq = 1; |
for (; i < IRQ_CONTROLLER_MAX_IRQ; i++) { |
for (; i < GXEMUL_IRQC_MAX_IRQ; i++) { |
if (sources & (1 << i)) { |
irq_t *irq = irq_dispatch_and_lock(i); |
if (irq) { |
/* The IRQ handler was found. */ |
irq->handler(irq, irq->arg); |
spinlock_unlock(&irq->lock); |
} else { |
/* Spurious interrupt.*/ |
aux_printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, i); |
} |
} |
} |
/* TODO remove after testing the above code |
noirq = 0; |
if (i == CONSOLE_IRQ) { |
char readchar = *(char*)0x10000000; |
179,7 → 172,7 |
} |
else if (i == TIMER_IRQ) { |
aux_printf("\n.\n"); |
/* acknowledge */ |
//acknowledge |
*(uint32_t*)0x15000110 = 0; |
} |
} |
186,7 → 179,7 |
} |
|
if (noirq) |
aux_puts("IRQ exception without source\n"); |
aux_puts("IRQ exception without source\n");*/ |
} |
|
/** Fills exception vectors with appropriate exception handlers. |
215,9 → 208,15 |
(unsigned*)EXC_FIQ_VEC); |
} |
|
/** Registers exceptions and their handlers to kernel exception dispatcher. */ |
/** Initializes exception handling. |
* |
* Installs low-level exception handlers and then registers |
* exceptions and their handlers to kernel exception dispatcher. |
*/ |
void exception_init(void) |
{ |
install_exception_handlers(); |
|
exc_register(EXC_IRQ, "interrupt", (iroutine) irq_exception); |
/* TODO add next */ |
} |
232,6 → 231,10 |
); |
asm("ldr sp, =irq_stack"); |
current_status_reg_control_write( cspr); |
|
/* TODO if you want to test other exceptions than IRQ, |
make stack analogous to irq_stack (in start.S), |
and then set stack pointer here */ |
} |
|
/** @} |