Interrupts.cpp 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  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) return;
  38. is_on = false;
  39. // Disable IRQ in the CPU
  40. asm(
  41. "mrs r1, cpsr \n\t"
  42. "orr r1, r1, #0x80 \n\t"
  43. "msr cpsr, r1"
  44. :
  45. :
  46. : "r1");
  47. *interrupt_select = interrupt_select_bkp;
  48. *interrupt_enable = interrupt_enable_bkp;
  49. *interrupt_enable_clear = ~(interrupt_enable_bkp);
  50. *interrupt_pointer = interrupt_pointer_bkp;
  51. }
  52. void __attribute__((interrupt("IRQ"))) INTERRUPTS::isr()
  53. {
  54. if (*irq_status & (1 << 21))
  55. Nspire::CXfb::vsync_isr();
  56. }