Interrupts.cpp 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #include "Interrupts.h"
  2. #include "CXfb.h"
  3. #define INTERRUPTS Nspire::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. static bool is_on = false;
  16. void INTERRUPTS::init()
  17. {
  18. is_on = true;
  19. interrupt_select_bkp = *interrupt_select;
  20. *interrupt_select = 0; // All IRQ for now
  21. interrupt_enable_bkp = *interrupt_enable;
  22. *interrupt_enable = INTERRUPT_MASK;
  23. *interrupt_enable_clear = ~(INTERRUPT_MASK);
  24. interrupt_pointer_bkp = *interrupt_pointer;
  25. *interrupt_pointer = (uint32_t) &isr;
  26. // Enable IRQ in the CPU
  27. asm(
  28. "mrs r1, cpsr \n\t"
  29. "bic r1, r1, #0x80 \n\t"
  30. "msr cpsr, r1"
  31. :
  32. :
  33. : "r1");
  34. }
  35. void INTERRUPTS::off()
  36. {
  37. if (!is_on)
  38. return;
  39. is_on = false;
  40. // Disable IRQ in the CPU
  41. asm(
  42. "mrs r1, cpsr \n\t"
  43. "orr r1, r1, #0x80 \n\t"
  44. "msr cpsr, r1"
  45. :
  46. :
  47. : "r1");
  48. *interrupt_select = interrupt_select_bkp;
  49. *interrupt_enable = interrupt_enable_bkp;
  50. *interrupt_enable_clear = ~(interrupt_enable_bkp);
  51. *interrupt_pointer = interrupt_pointer_bkp;
  52. }
  53. void __attribute__((interrupt("IRQ"))) INTERRUPTS::isr()
  54. {
  55. if (*irq_status & (1 << 21))
  56. Nspire::CXfb::vsync_isr();
  57. }