Interrupts.cpp 1.9 KB

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