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.

110 lines
2.6KB

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