From ac031627c80e385a8e52e73b8d27c4c308d297e0 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Thu, 14 Feb 2019 22:11:23 -0700 Subject: [PATCH] Update IME to be `u16` sized, avoid newtype_enum newtype_enum makes an enum, but an enum can be UB if it's no a valid bit pattern. We should avoid having registers mapped to enum types. --- examples/irq.rs | 2 +- src/bios.rs | 2 +- src/io/irq.rs | 25 ++++++++++++++++++------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/examples/irq.rs b/examples/irq.rs index 931ecc6..98a390b 100644 --- a/examples/irq.rs +++ b/examples/irq.rs @@ -44,7 +44,7 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { irq::set_irq_handler(irq_handler); // Enable all interrupts that are set in the IE register. - IME.write(IrqEnableSetting::UseIE); + IME.write(IrqEnableSetting::IRQ_YES); // Request that VBlank, HBlank and VCount will generate IRQs. const DISPLAY_SETTINGS: DisplayStatusSetting = DisplayStatusSetting::new() diff --git a/src/bios.rs b/src/bios.rs index 03f6c8e..a5f3b3b 100644 --- a/src/bios.rs +++ b/src/bios.rs @@ -204,7 +204,7 @@ pub fn interrupt_wait(ignore_current_flags: bool, target_flags: IrqFlags) { unsafe { asm!(/* ASM */ "swi 0x04" :/* OUT */ // none - :/* INP */ "{r0}"(ignore_current_flags), "{r1}"(target_flags.0) + :/* INP */ "{r0}"(ignore_current_flags), "{r1}"(target_flags) :/* CLO */ // none :/* OPT */ "volatile" ); diff --git a/src/io/irq.rs b/src/io/irq.rs index 2f3a9bb..a5cb63c 100644 --- a/src/io/irq.rs +++ b/src/io/irq.rs @@ -102,7 +102,8 @@ use super::*; newtype!( /// A newtype over all interrupt flags. - IrqFlags, pub u16 + IrqFlags, + u16 ); impl IrqFlags { @@ -140,13 +141,23 @@ pub const IE: VolAddress = unsafe { VolAddress::new(0x400_0200) }; /// when it is called. pub const IF: VolAddress = unsafe { VolAddress::new(0x400_0200) }; -newtype_enum! { +newtype! { /// Setting to control whether interrupts are enabled. - IrqEnableSetting = u32, - /// Disable all interrupts. - DisableAll = 0, - /// Enable interrupts according to the flags set in the [`IE`](irq::IE) register. - UseIE = 1, + IrqEnableSetting, u16 +} + +impl IrqEnableSetting { + phantom_fields! { + self.0: u16, + /// System-wide control for if interrupts of all kinds are enabled or not. + interrupts_enabled: 0, + } + + /// Yes, you want to have interrupts. + pub const IRQ_YES: Self = Self::new().with_interrupts_enabled(true); + + /// No, please do not have interrupts. + pub const IRQ_NO: Self = Self::new(); } /// Interrupt Master Enable Register. Read/Write.