Improved MPcore interrupt handler

This commit is contained in:
Wolfvak 2017-08-08 23:04:17 -03:00 committed by d0k3
parent e36b2c347f
commit 930b646008
11 changed files with 106 additions and 78 deletions

View File

@ -28,13 +28,12 @@ INCLUDES := common source source/common source/font source/filesys source/crypto
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -mthumb -mthumb-interwork -flto
ARCH := -DARM9 -march=armv5te -mthumb -mthumb-interwork -flto
CFLAGS := -g -Wall -Wextra -Wpedantic -Wcast-align -Wno-main -O2\
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math -std=gnu11\
$(ARCH)
CFLAGS += $(INCLUDE) -DARM9
ASFLAGS := $(ARCH) -g -x assembler-with-cpp $(INCLUDE)
CFLAGS := $(ARCH) -g -Wall -Wextra -Wpedantic -Wcast-align -Wno-main -O2 \
-mtune=arm946e-s -fomit-frame-pointer -ffast-math -std=gnu11 \
$(INCLUDE)
CFLAGS += -DBUILD_NAME="\"$(TARGET) (`date +'%Y/%m/%d'`)\""
@ -64,7 +63,6 @@ endif
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
ASFLAGS := -g $(ARCH)
LDFLAGS = -T../link.ld -nostartfiles -g $(ARCH) -Wl,-Map,$(TARGET).map
LIBS :=

15
common/arm.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
/* Status Register flags */
#define SR_USR_MODE (0x10)
#define SR_FIQ_MODE (0x11)
#define SR_IRQ_MODE (0x12)
#define SR_SVC_MODE (0x13)
#define SR_ABT_MODE (0x17)
#define SR_UND_MODE (0x1B)
#define SR_SYS_MODE (0x1F)
#define SR_PMODE_MASK (0x1F)
#define SR_THUMB (1 << 5)
#define SR_FIQ (1 << 6)
#define SR_IRQ (1 << 7)

View File

@ -7,6 +7,7 @@
#endif
#include <stdint.h>
#include <stddef.h>
#define BIT(x) (1<<(x))

View File

@ -12,10 +12,12 @@ dir_source := source
dir_build := build
dir_out := ../$(dir_build)
ASFLAGS := -mcpu=mpcore -mfloat-abi=soft
CFLAGS := -DARM11 -Wall -Wextra -MMD -MP -marm -mno-thumb-interwork \
$(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math \
-I$(dir_source) -I../common
ARCH := -DARM11 -mcpu=mpcore -mfloat-abi=soft -marm -mno-thumb-interwork
INCLUDE := -I$(dir_source) -I../common
ASFLAGS := $(ARCH) -x assembler-with-cpp $(INCLUDE)
CFLAGS := $(ARCH) -Wall -Wextra -MMD -MP -fno-builtin \
-std=c11 -O2 -flto -ffast-math -Wno-main $(INCLUDE)
LDFLAGS := -nostdlib -nostartfiles
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
@ -37,8 +39,8 @@ $(dir_out)/$(name).elf: $(objects)
$(dir_build)/%.o: $(dir_source)/%.c
@mkdir -p "$(@D)"
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(CC) -c $(CFLAGS) -o $@ $<
$(dir_build)/%.o: $(dir_source)/%.s
@mkdir -p "$(@D)"
$(COMPILE.s) $(OUTPUT_OPTION) $<
$(CC) -c $(ASFLAGS) -o $@ $<

View File

@ -6,13 +6,12 @@ SECTIONS
{
. = 0x1FF80000;
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.text : ALIGN(4) { *(.text.boot) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
.bss : ALIGN(4) { __bss_start = .; *(.bss*); __bss_end = .; }
. = ALIGN(4);
__irq_stack = 0x1FFFF800;
__prg_stack = 0x1FFFF400;
__stack_top = 0x1FFFF800;
}

View File

@ -3,10 +3,12 @@
.section .text.boot
.arm
#include <arm.h>
.global __boot
__boot:
@ Disable interrupts and switch to IRQ
cpsid aif, #0x12
cpsid aif, #(SR_SVC_MODE)
@ Writeback and invalidate caches
mov r0, #0
@ -14,11 +16,7 @@ __boot:
mcr p15, 0, r0, c7, c14, 0
mcr p15, 0, r0, c7, c10, 4
ldr sp, =__irq_stack
@ Switch to SVC
cpsid aif, #0x13
ldr sp, =__prg_stack
ldr sp, =__stack_top
@ Reset values
ldr r0, =0x00054078

View File

@ -10,18 +10,17 @@
#define IRQ_BASE ((vu32*)0x1FFFFFA0)
irq_handler handler_table[MAX_IRQ];
extern void (*main_irq_handler)(void);
void __attribute__((interrupt("IRQ"))) gic_irq_handler(void)
irq_handler GIC_AckIRQ(void)
{
u32 xrq, ss;
CPU_EnterCritical(&ss);
xrq = *GIC_IRQACK;
u32 xrq = *GIC_IRQACK;
irq_handler ret = NULL;
if (xrq < MAX_IRQ && handler_table[xrq]) {
(handler_table[xrq])(xrq);
}
ret = handler_table[xrq];
*GIC_IRQEND = xrq;
CPU_LeaveCritical(&ss);
return;
}
return ret;
}
void GIC_Configure(u32 irq_id, irq_handler hndl)
@ -35,23 +34,30 @@ void GIC_Configure(u32 irq_id, irq_handler hndl)
void GIC_Reset(void)
{
*DIC_CONTROL = 0;
*GIC_CONTROL = 0;
*GIC_PRIOMASK = ~0;
for (int i = 0; i < (BIT(9)-1); i++) {
*GIC_IRQEND |= i;
*GIC_PRIOMASK = ~0;
for (int i = 0; i < 0x80; i++) {
*GIC_IRQEND = i;
}
*DIC_CONTROL = 0;
for (int i = 0; i < (0x20/4); i++) {
DIC_CLRENABLE[i] = ~0;
DIC_PRIORITY[i] = 0;
}
*DIC_CONTROL = 1;
*GIC_CONTROL = 1;
while(*GIC_PENDING != SPURIOUS_IRQ) {
for (int i=0; i < (0x20/4); i++) {
DIC_CLRPENDING[i] = ~0;
}
}
IRQ_BASE[1] = (u32)gic_irq_handler;
IRQ_BASE[1] = (u32)&main_irq_handler;
IRQ_BASE[0] = 0xE51FF004;
*GIC_CONTROL = 1;
*DIC_CONTROL = 1;
return;
}

View File

@ -6,51 +6,29 @@
#pragma once
#include <types.h>
typedef void (*irq_handler)(u32);
typedef void (*irq_handler)(void);
#define MAX_IRQ (0x80)
#define SPURIOUS_IRQ (1023)
#define GIC_BASE (0x17E00100)
#define DIC_BASE (0x17E01000)
/* Setting bit 0 enables the GIC */
#define GIC_CONTROL ((vu32*)(GIC_BASE + 0x00))
/* Bits [7:0] control the min priority accepted */
#define GIC_PRIOMASK ((vu32*)(GIC_BASE + 0x04))
/* When an IRQ occurrs, this register holds the IRQ ID */
#define GIC_IRQACK ((vu32*)(GIC_BASE + 0x0C))
/* Write the IRQ ID here to acknowledge it */
#define GIC_IRQEND ((vu32*)(GIC_BASE + 0x10))
#define GIC_PENDING ((vu32*)(GIC_BASE + 0x18))
/* Setting bit 0 enables the DIC */
#define DIC_CONTROL ((vu32*)(DIC_BASE + 0x000))
/*
Write here to enable an IRQ ID
The register address is DIC_SETENABLE + (N/32)*4 and its
corresponding bit index is (N%32)
*/
#define DIC_SETENABLE ((vu32*)(DIC_BASE + 0x100))
/* same as above but disables the IRQ */
#define DIC_CLRENABLE ((vu32*)(DIC_BASE + 0x180))
/* sets the IRQ priority */
#define DIC_SETPENDING ((vu32*)(DIC_BASE + 0x200))
#define DIC_CLRPENDING ((vu32*)(DIC_BASE + 0x280))
#define DIC_PRIORITY ((vu32*)(DIC_BASE + 0x400))
/* specifies which CPUs are allowed to be forwarded the IRQ */
#define DIC_PROCTGT ((vu8*)(DIC_BASE + 0x800))
/*
each irq has 2 bits assigned
bit 0 = 0: uses 1-N model
1: uses N-N model
bit 1 = 0: level high active
1: rising edge sensitive
*/
#define DIC_PROCTGT ((vu8*) (DIC_BASE + 0x800))
#define DIC_CFGREG ((vu32*)(DIC_BASE + 0xC00))
void gic_irq_handler(void);
void GIC_Configure(u32 irq_id, irq_handler hndl);
void GIC_Reset(void);

29
screeninit/source/irq.s Normal file
View File

@ -0,0 +1,29 @@
.section .text
.arm
#include <arm.h>
.global main_irq_handler
.type main_irq_handler, %function
main_irq_handler:
sub lr, lr, #4 @ Fix return address
srsdb sp!, #(SR_SVC_MODE) @ Store IRQ mode LR and SPSR on the SVC stack
cps #(SR_SVC_MODE) @ Switch to SVC mode
push {r0-r3,r12} @ Preserve registers
and r1, sp, #4
sub sp, sp, r1 @ Word-align stack
push {r1,lr}
bl GIC_AckIRQ @ Acknowledge interrupt, get handler address
cmp r0, #0
beq .Lskip_irq
cpsie i
blx r0 @ Branch to interrupt handler with IRQs enabled
cpsid i
.Lskip_irq:
pop {r1,lr}
add sp, sp, r1 @ Restore stack pointer
pop {r0-r3,lr} @ Restore registers
rfeia sp! @ Return From Exception

View File

@ -133,7 +133,7 @@ void set_brightness(u8 brightness)
*(vu32 *)0x10202A40 = brightness;
}
void pxi_interrupt_handler(__attribute__((unused)) u32 xrq_n)
void pxi_interrupt_handler(void)
{
u8 msg = PXI_GetRemote();
switch(msg) {

View File

@ -2,11 +2,13 @@
.align 4
.arm
#include <arm.h>
@ make sure not to clobber r0-r2
.global _start
_start:
@ Switch to supervisor mode and disable interrupts
msr cpsr_c, #0xD3
msr cpsr_c, #(SR_SVC_MODE | SR_IRQ | SR_FIQ)
@ Short delay (not always necessary, just in case)
mov r3, #0x40000