Skip to content
This repository has been archived by the owner on Oct 24, 2023. It is now read-only.

Commit

Permalink
Merge branch 'isr-refactor'
Browse files Browse the repository at this point in the history
  • Loading branch information
LunarLambda committed Jun 10, 2023
2 parents 2117d99 + 4e7a70e commit 7aaf252
Show file tree
Hide file tree
Showing 14 changed files with 194 additions and 381 deletions.
2 changes: 0 additions & 2 deletions examples/template/src/main.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#include <seven/version.h>
#include <seven/hw/video/prelude.h>
#include <seven/hw/video/bg_bitmap.h>
#include <seven/hw/video/color_constants.h>

libsevenEmitVersionString();

int main(void)
{
Expand Down
3 changes: 2 additions & 1 deletion examples/vsync/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ int main(void)
{
// Set up the necessary interrupt handling
irqInitDefault();
irqEnableFull(IRQ_VBLANK);
irqEnable(IRQ_VBLANK);
irqHandlerSet(IRQ_VBLANK, vblank_callback);

// Clear the force-blank bit
REG_DISPCNT = 0;
REG_DISPSTAT = LCD_VBLANK_IRQ_ENABLE;

while (1)
{
Expand Down
43 changes: 18 additions & 25 deletions libseven/include/seven/attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,26 @@

#include <seven/base.h>

#define _LIBSEVEN_SECCOUNT _LIBSEVEN_STR2(__COUNTER__)
#define _LIBSEVEN_COUNTER _LIBSEVEN_STR2(__COUNTER__)

#define PACKED __attribute__((__packed__))
#define ALIGN(n) __attribute__((__aligned__(n)))
#define NORETURN __attribute__((__noreturn__))
#define NOINLINE __attribute__((__noinline__))
#define ARM_CODE __attribute__((__target__("arm"))) NOINLINE
#define THUMB_CODE __attribute__((__target__("thumb"))) NOINLINE
#define ALIGN(n) __attribute__((__aligned__(n)))
#define ARM_CODE __attribute__((__target__("arm"))) NOINLINE
#define NOINLINE __attribute__((__noinline__))
#define NORETURN __attribute__((__noreturn__))
#define PACKED __attribute__((__packed__))
#define SECTION(name) __attribute__((__section__(name)))
#define THUMB_CODE __attribute__((__target__("thumb"))) NOINLINE

#define SECTION(name) __attribute__((__section__(name)))
#define IWRAM_CODE SECTION(".iwram.text." _LIBSEVEN_COUNTER) NOINLINE
#define IWRAM_DATA SECTION(".iwram.data." _LIBSEVEN_COUNTER)

#define IWRAM_SECTION(suffix) SECTION(".iwram" suffix)
#define IWRAM_OVERLAY(number) SECTION(".iwram" #number)
#define EWRAM_CODE SECTION(".ewram.text." _LIBSEVEN_COUNTER) NOINLINE
#define EWRAM_DATA SECTION(".ewram.data." _LIBSEVEN_COUNTER)

#define IWRAM_CODE IWRAM_SECTION(".text." _LIBSEVEN_SECCOUNT) NOINLINE
#define IWRAM_DATA IWRAM_SECTION(".data." _LIBSEVEN_SECCOUNT)

#define EWRAM_SECTION(suffix) SECTION(".ewram" suffix)
#define EWRAM_OVERLAY(number) SECTION(".ewram" #number)

#define EWRAM_CODE EWRAM_SECTION(".text." _LIBSEVEN_SECCOUNT) NOINLINE
#define EWRAM_DATA EWRAM_SECTION(".data." _LIBSEVEN_SECCOUNT)

#ifndef _LIBSEVEN_NOCOMPATIBLE
#define IWRAM_BSS SECTION(".bss." _LIBSEVEN_SECCOUNT)
#define EWRAM_BSS SECTION(".sbss." _LIBSEVEN_SECCOUNT)
#ifdef LIBSEVEN_COMPATIBLE
#define IWRAM_BSS SECTION(".bss." _LIBSEVEN_COUNTER)
#define EWRAM_BSS SECTION(".sbss." _LIBSEVEN_COUNTER)
#else
#define IWRAM_BSS SECTION(".iwram_bss." _LIBSEVEN_SECCOUNT)
#define EWRAM_BSS SECTION(".ewram_bss." _LIBSEVEN_SECCOUNT)
#endif /* !_LIBSEVEN_NOCOMPATIBLE */
#define IWRAM_BSS SECTION(".iwram_bss." _LIBSEVEN_COUNTER)
#define EWRAM_BSS SECTION(".ewram_bss." _LIBSEVEN_COUNTER)
#endif /* LIBSEVEN_COMPATIBLE */
8 changes: 5 additions & 3 deletions libseven/include/seven/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
#define _LIBSEVEN_STR(s) #s
#define _LIBSEVEN_STR2(s) _LIBSEVEN_STR(s)

#define _LIBSEVEN_TARGET_ARM __attribute__((__target__("arm"), __noinline__))
#define _LIBSEVEN_NOINLINE __attribute__((__noinline__))
#define _LIBSEVEN_NORETURN __attribute__((__noreturn__))
#define _LIBSEVEN_ALIGN4 __attribute__((__aligned__(4)))
#define _LIBSEVEN_ALIGNED __attribute__((__aligned__(4)))

#define LIBSEVEN_VERSION_MAJOR 0
#define LIBSEVEN_VERSION_MINOR 17
#define LIBSEVEN_VERSION_PATCH 2
#define LIBSEVEN_VERSION_MINOR 18
#define LIBSEVEN_VERSION_PATCH 0

#define LIBSEVEN_VERSION \
_LIBSEVEN_STR2(LIBSEVEN_VERSION_MAJOR) "." \
Expand Down
44 changes: 19 additions & 25 deletions libseven/include/seven/hw/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@

_LIBSEVEN_EXTERN_C

// Attribute for compiling functions in a way that is suitable for ISRs.
//
#define ISR_FUNCTION IWRAM_CODE ARM_CODE

// Interrupt Enable
//
#define REG_IE VOLADDR(0x04000200, uint16_t)
Expand All @@ -28,11 +24,14 @@ _LIBSEVEN_EXTERN_C

// Interrupt Service Routine Function Pointer
//
#define MEM_ISR MEMADDR(0x03FFFFFC, IsrFn*)
#define MEM_ISR VOLADDR(0x03FFFFFC, IsrFn*)

// Interrupt Flags used by BIOS
#define MEM_IFBIOS VOLADDR(0x03FFFFF8, uint16_t)

// IRQ bitflags
//
enum IRQ
enum IRQFlag
{
IRQ_VBLANK = BIT(0),
IRQ_HBLANK = BIT(1),
Expand All @@ -57,7 +56,7 @@ enum IRQGroup
IRQS_BLANK = IRQ_VBLANK | IRQ_HBLANK,
IRQS_TIMER = IRQ_TIMER_0 | IRQ_TIMER_1 | IRQ_TIMER_2 | IRQ_TIMER_3,
IRQS_DMA = IRQ_DMA_0 | IRQ_DMA_1 | IRQ_DMA_2 | IRQ_DMA_3,
// IRQs in this group can wake up the GBA from a svcStop() call.
// IRQs in this group can wake up the GBA from biosStop().
IRQS_EXTERNAL = IRQ_SERIAL | IRQ_KEYPAD | IRQ_CARTRIDGE,
IRQS_ALL = BITS(14),
};
Expand Down Expand Up @@ -101,17 +100,13 @@ extern void irqInit(IsrFn *isr);
// Initialize interrupt handling using a handler system.
//
// Used with the irqHandler* functions.
// Supports nesting by calling irqUnmask() inside a handler.
extern void irqInitDefault(void);

// Initialize interrupt handling using a single handler function.
// Initialize interrupt handling using an optional, single handler function.
//
extern void irqInitSimple(IrqHandlerFn *fn);

// Initialize interrupt handling using a stub handler
// that only acknowledges the IRQs and returns.
//
// This is enough for the BIOS interrupt wait functions to work.
extern void irqInitStub(void);
// Does not support nesting by default.
extern void irqInitMinimal(IrqHandlerFn *fn);

// Set the handler associated with the specified irq.
//
Expand All @@ -138,17 +133,16 @@ extern uint16_t irqEnable(uint16_t irqs);
// Returns the old value of the IE register.
extern uint16_t irqDisable(uint16_t irqs);

// Enable the specified IRQs and IRQ enable bits in the respective IO registers.
//
// Returns the old value of the IE register.
extern uint16_t irqEnableFull(uint16_t irqs);
// Calls a function with IRQs disabled, passing data as an argument.
extern void irqFree(void (*f)(void *), void *arg);

// Disable the specified IRQs and IRQ enable bits in the respective IO registers.
//
// Returns the old value of the IE register.
extern uint16_t irqDisableFull(uint16_t irqs);
// Mask IRQs at the CPU level.
extern void irqMask(void);

// Calls a function with IRQs disabled, passing data as an argument.
extern void irqFree(void (*f)(void*), void *arg);
// Unmask IRQs at the CPU level. Used for enabling nested interrupts.
extern void irqUnmask(void);

// Returns whether IRQs are masked at the CPU level.
extern bool irqMasked(void);

_LIBSEVEN_EXTERN_C_END
4 changes: 2 additions & 2 deletions libseven/include/seven/hw/video/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ struct Matrix
int16_t vdx; // vertical shearing factor
int16_t hdy; // horizontal shearing factor
int16_t vdy; // vertical scaling factor
} _LIBSEVEN_ALIGN4;
} _LIBSEVEN_ALIGNED;

struct Object
{
uint16_t attr0;
uint16_t attr1;
uint16_t attr2;
uint16_t _reserved;
} _LIBSEVEN_ALIGN4;
} _LIBSEVEN_ALIGNED;

_LIBSEVEN_EXTERN_C_END
4 changes: 2 additions & 2 deletions libseven/include/seven/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ typedef uintptr_t uptr;
#define USIZE_BITS (CHAR_BIT * sizeof(usize))
#define UPTR_BITS (CHAR_BIT * sizeof(uptr))

#ifndef _LIBSEVEN_NOCOMPATIBLE
#ifdef LIBSEVEN_COMPATIBLE

typedef i8 s8;
typedef i16 s16;
Expand Down Expand Up @@ -96,4 +96,4 @@ typedef iptr sptr;
#define SSIZE_BITS ISIZE_BITS
#define SPTR_BITS IPTR_BITS

#endif /* !_LIBSEVEN_NOCOMPATIBLE */
#endif /* LIBSEVEN_COMPATIBLE */
18 changes: 0 additions & 18 deletions libseven/include/seven/version.h

This file was deleted.

68 changes: 52 additions & 16 deletions libseven/src/hw/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@
#include <seven/hw/irq.h>

extern IsrFn isrDefault;
extern IsrFn isrSimple;
extern IsrFn isrStub;

extern IrqHandlerFn* ISR_SIMPLE_HANDLER;
extern IrqHandlerFn* ISR_DEFAULT_HANDLERS[16];
extern IsrFn isrMinimal;

// Mark these as volatile because LTO cannot verify that isrDefault/isrMinimal
// is called because it's invoked indirectly through the hardware.
//
// This means LTO will consider calls to irqSetHandler and similar to be dead
// accesses, and remove them entirely
//
// For our purposes, writing these does produce a side effect, so volatile is
// actually the semantically correct option here.
extern IrqHandlerFn * volatile ISR_MINIMAL_HANDLER;
extern IrqHandlerFn * volatile ISR_DEFAULT_HANDLERS[16];

extern void irqInit(IsrFn *isr)
{
Expand All @@ -23,7 +30,6 @@ extern void irqInit(IsrFn *isr)
MEM_ISR = isr;

REG_IME = 1;
return;
}

extern void irqInitDefault(void)
Expand All @@ -38,18 +44,13 @@ extern void irqInitDefault(void)
irqInit(isrDefault);
}

extern void irqInitSimple(IrqHandlerFn *handler)
extern void irqInitMinimal(IrqHandlerFn *handler)
{
REG_IME = 0;

ISR_SIMPLE_HANDLER = handler;

irqInit(isrSimple);
}
ISR_MINIMAL_HANDLER = handler;

extern void irqInitStub(void)
{
irqInit(isrStub);
irqInit(isrMinimal);
}

extern bool irqHandlerSet(uint16_t irq, IrqHandlerFn *fn)
Expand Down Expand Up @@ -118,14 +119,49 @@ extern uint16_t irqDisable(uint16_t irqs)
return old;
}

extern void irqFree(void (*f)(void*), void *arg)
extern void irqFree(void (*f)(void *), void *arg)
{
uint32_t ime = REG_IME;
REG_IME = 0;

f(arg);

REG_IME = ime;
}

_LIBSEVEN_TARGET_ARM extern void irqMask(void)
{
__asm__ volatile
(
"mrs r0, cpsr\n"
"orr r0, r0, 0x80\n"
"msr cpsr_c, r0\n"
::: "r0"
);
}

_LIBSEVEN_TARGET_ARM extern void irqUnmask(void)
{
__asm__ volatile
(
"mrs r0, cpsr\n"
"bic r0, r0, 0x80\n"
"msr cpsr_c, r0\n"
::: "r0"
);
}

_LIBSEVEN_TARGET_ARM extern bool irqMasked(void)
{
bool masked;

__asm__ volatile
(
"mrs %0, cpsr\n"
"lsr %0, %0, 7\n"
"and %0, %0, 1\n"
: "=r"(masked)
);

return;
return masked;
}
Loading

0 comments on commit 7aaf252

Please sign in to comment.