Interrupts.cpp 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. #include "Interrupts.h"
  2. #include "Graphics.h"
  3. #define INTERRUPTS WalrusRPG::Interrupts
  4. #define INTERRUPT_CONTROLLER 0xDC000000
  5. volatile uint32_t *irq_status = (uint32_t *) (INTERRUPT_CONTROLLER + 0x0);
  6. volatile uint32_t *interrupt_select = (uint32_t *) (INTERRUPT_CONTROLLER + 0xC);
  7. uint32_t interrupt_select_bkp;
  8. volatile uint32_t *interrupt_enable = (uint32_t *) (INTERRUPT_CONTROLLER + 0x10);
  9. volatile uint32_t *interrupt_enable_clear = (uint32_t *) (INTERRUPT_CONTROLLER + 0x14);
  10. uint32_t interrupt_enable_bkp;
  11. volatile uint32_t *interrupt_pointer = (uint32_t *) 0x38;
  12. uint32_t interrupt_pointer_bkp;
  13. // Interrupt source 21 is the LCD
  14. #define INTERRUPT_MASK (1 << 21)
  15. void INTERRUPTS::init()
  16. {
  17. interrupt_select_bkp = *interrupt_select;
  18. *interrupt_select = 0; // All IRQ for now
  19. interrupt_enable_bkp = *interrupt_enable;
  20. *interrupt_enable = INTERRUPT_MASK;
  21. *interrupt_enable_clear = ~(INTERRUPT_MASK);
  22. interrupt_pointer_bkp = *interrupt_pointer;
  23. *interrupt_pointer = (uint32_t) &isr;
  24. // Enable IRQ in the CPU
  25. asm("mrs r1, cpsr \n\t"
  26. "bic r1, r1, #0x80 \n\t"
  27. "msr cpsr, r1"
  28. :
  29. :
  30. : "r1");
  31. }
  32. void INTERRUPTS::off()
  33. {
  34. // Disable IRQ in the CPU
  35. asm("mrs r1, cpsr \n\t"
  36. "orr r1, r1, #0x80 \n\t"
  37. "msr cpsr, r1"
  38. :
  39. :
  40. : "r1");
  41. *interrupt_select = interrupt_select_bkp;
  42. *interrupt_enable = interrupt_enable_bkp;
  43. *interrupt_enable_clear = ~(interrupt_enable_bkp);
  44. *interrupt_pointer = interrupt_pointer_bkp;
  45. }
  46. void __attribute__((interrupt("IRQ"))) INTERRUPTS::isr()
  47. {
  48. if (*irq_status & (1 << 21))
  49. WalrusRPG::Graphics::vsync_isr();
  50. }