mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
Improved MPcore interrupt handler
This commit is contained in:
parent
e36b2c347f
commit
930b646008
12
Makefile
12
Makefile
@ -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
15
common/arm.h
Normal 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)
|
@ -7,6 +7,7 @@
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define BIT(x) (1<<(x))
|
||||
|
||||
|
@ -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 $@ $<
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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_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
29
screeninit/source/irq.s
Normal 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
|
@ -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) {
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user