Teensy 4.1 core updated for C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
2.3KB

  1. #include "DMAChannel.h"
  2. // The channel allocation bitmask is accessible from "C" namespace,
  3. // so C-only code can reserve DMA channels
  4. uint16_t dma_channel_allocated_mask = 0;
  5. void DMAChannel::init(void)
  6. {
  7. uint32_t ch = 0;
  8. __disable_irq();
  9. while (1) {
  10. if (!(dma_channel_allocated_mask & (1 << ch))) {
  11. dma_channel_allocated_mask |= (1 << ch);
  12. __enable_irq();
  13. break;
  14. }
  15. if (++ch >= DMA_NUM_CHANNELS) {
  16. __enable_irq();
  17. TCD = (TCD_t *)0;
  18. channel = 16;
  19. return; // no more channels available
  20. // attempts to use this object will hardfault
  21. }
  22. }
  23. channel = ch;
  24. SIM_SCGC7 |= SIM_SCGC7_DMA;
  25. SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
  26. DMA_CR = DMA_CR_EMLM | DMA_CR_EDBG ; // minor loop mapping is available
  27. DMA_CERQ = ch;
  28. DMA_CERR = ch;
  29. DMA_CEEI = ch;
  30. DMA_CINT = ch;
  31. TCD = (TCD_t *)(0x40009000 + ch * 32);
  32. uint32_t *p = (uint32_t *)TCD;
  33. *p++ = 0;
  34. *p++ = 0;
  35. *p++ = 0;
  36. *p++ = 0;
  37. *p++ = 0;
  38. *p++ = 0;
  39. *p++ = 0;
  40. *p++ = 0;
  41. }
  42. void DMAChannel::release(void)
  43. {
  44. if (channel >= DMA_NUM_CHANNELS) return;
  45. DMA_CERQ = channel;
  46. __disable_irq();
  47. dma_channel_allocated_mask &= ~(1 << channel);
  48. __enable_irq();
  49. channel = 16;
  50. TCD = (TCD_t *)0;
  51. }
  52. static uint32_t priority(const DMAChannel &c)
  53. {
  54. uint32_t n;
  55. n = *(uint32_t *)((uint32_t)&DMA_DCHPRI3 + (c.channel & 0xFC));
  56. n = __builtin_bswap32(n);
  57. return (n >> ((c.channel & 0x03) << 3)) & 0x0F;
  58. }
  59. static void swap(DMAChannel &c1, DMAChannel &c2)
  60. {
  61. uint8_t c;
  62. DMABaseClass::TCD_t *t;
  63. c = c1.channel;
  64. c1.channel = c2.channel;
  65. c2.channel = c;
  66. t = c1.TCD;
  67. c1.TCD = c2.TCD;
  68. c2.TCD = t;
  69. }
  70. void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2)
  71. {
  72. if (priority(ch1) < priority(ch2)) swap(ch1, ch2);
  73. }
  74. void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2, DMAChannel &ch3)
  75. {
  76. if (priority(ch2) < priority(ch3)) swap(ch2, ch3);
  77. if (priority(ch1) < priority(ch2)) swap(ch1, ch2);
  78. if (priority(ch2) < priority(ch3)) swap(ch2, ch3);
  79. }
  80. void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2, DMAChannel &ch3, DMAChannel &ch4)
  81. {
  82. if (priority(ch3) < priority(ch4)) swap(ch3, ch4);
  83. if (priority(ch2) < priority(ch3)) swap(ch2, ch3);
  84. if (priority(ch1) < priority(ch2)) swap(ch1, ch2);
  85. if (priority(ch3) < priority(ch4)) swap(ch2, ch3);
  86. if (priority(ch2) < priority(ch3)) swap(ch1, ch2);
  87. if (priority(ch3) < priority(ch4)) swap(ch2, ch3);
  88. }