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.

преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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. /****************************************************************/
  6. /** Teensy 3.0 & 3.1 **/
  7. /****************************************************************/
  8. #if defined(KINETISK)
  9. void DMAChannel::begin(bool force_initialization)
  10. {
  11. uint32_t ch = 0;
  12. __disable_irq();
  13. if (!force_initialization && TCD && channel < DMA_NUM_CHANNELS
  14. && (dma_channel_allocated_mask & (1 << channel))
  15. && (uint32_t)TCD == (uint32_t)(0x40009000 + channel * 32)) {
  16. // DMA channel already allocated
  17. __enable_irq();
  18. return;
  19. }
  20. while (1) {
  21. if (!(dma_channel_allocated_mask & (1 << ch))) {
  22. dma_channel_allocated_mask |= (1 << ch);
  23. __enable_irq();
  24. break;
  25. }
  26. if (++ch >= DMA_NUM_CHANNELS) {
  27. __enable_irq();
  28. TCD = (TCD_t *)0;
  29. channel = DMA_NUM_CHANNELS;
  30. return; // no more channels available
  31. // attempts to use this object will hardfault
  32. }
  33. }
  34. channel = ch;
  35. SIM_SCGC7 |= SIM_SCGC7_DMA;
  36. SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
  37. DMA_CR = DMA_CR_EMLM | DMA_CR_EDBG ; // minor loop mapping is available
  38. DMA_CERQ = ch;
  39. DMA_CERR = ch;
  40. DMA_CEEI = ch;
  41. DMA_CINT = ch;
  42. TCD = (TCD_t *)(0x40009000 + ch * 32);
  43. uint32_t *p = (uint32_t *)TCD;
  44. *p++ = 0;
  45. *p++ = 0;
  46. *p++ = 0;
  47. *p++ = 0;
  48. *p++ = 0;
  49. *p++ = 0;
  50. *p++ = 0;
  51. *p++ = 0;
  52. }
  53. void DMAChannel::release(void)
  54. {
  55. if (channel >= DMA_NUM_CHANNELS) return;
  56. DMA_CERQ = channel;
  57. __disable_irq();
  58. dma_channel_allocated_mask &= ~(1 << channel);
  59. __enable_irq();
  60. channel = 16;
  61. TCD = (TCD_t *)0;
  62. }
  63. static uint32_t priority(const DMAChannel &c)
  64. {
  65. uint32_t n;
  66. n = *(uint32_t *)((uint32_t)&DMA_DCHPRI3 + (c.channel & 0xFC));
  67. n = __builtin_bswap32(n);
  68. return (n >> ((c.channel & 0x03) << 3)) & 0x0F;
  69. }
  70. static void swap(DMAChannel &c1, DMAChannel &c2)
  71. {
  72. uint8_t c;
  73. DMABaseClass::TCD_t *t;
  74. c = c1.channel;
  75. c1.channel = c2.channel;
  76. c2.channel = c;
  77. t = c1.TCD;
  78. c1.TCD = c2.TCD;
  79. c2.TCD = t;
  80. }
  81. /****************************************************************/
  82. /** Teensy-LC **/
  83. /****************************************************************/
  84. #elif defined(KINETISL)
  85. void DMAChannel::begin(bool force_initialization)
  86. {
  87. uint32_t ch = 0;
  88. __disable_irq();
  89. if (!force_initialization && CFG && channel < DMA_NUM_CHANNELS
  90. && (dma_channel_allocated_mask & (1 << channel))
  91. && (uint32_t)CFG == (uint32_t)(0x40008100 + channel * 16)) {
  92. // DMA channel already allocated
  93. __enable_irq();
  94. return;
  95. }
  96. while (1) {
  97. if (!(dma_channel_allocated_mask & (1 << ch))) {
  98. dma_channel_allocated_mask |= (1 << ch);
  99. __enable_irq();
  100. break;
  101. }
  102. if (++ch >= DMA_NUM_CHANNELS) {
  103. __enable_irq();
  104. CFG = (CFG_t *)0;
  105. channel = DMA_NUM_CHANNELS;
  106. return; // no more channels available
  107. // attempts to use this object will hardfault
  108. }
  109. }
  110. channel = ch;
  111. SIM_SCGC7 |= SIM_SCGC7_DMA;
  112. SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
  113. CFG = (CFG_t *)(0x40008100 + ch * 16);
  114. CFG->DSR_BCR = DMA_DSR_BCR_DONE;
  115. CFG->DCR = DMA_DCR_CS;
  116. CFG->SAR = NULL;
  117. CFG->DAR = NULL;
  118. }
  119. void DMAChannel::release(void)
  120. {
  121. if (channel >= DMA_NUM_CHANNELS) return;
  122. CFG->DSR_BCR = DMA_DSR_BCR_DONE;
  123. __disable_irq();
  124. dma_channel_allocated_mask &= ~(1 << channel);
  125. __enable_irq();
  126. channel = 16;
  127. CFG = (CFG_t *)0;
  128. }
  129. static uint32_t priority(const DMAChannel &c)
  130. {
  131. return 3 - c.channel;
  132. }
  133. static void swap(DMAChannel &c1, DMAChannel &c2)
  134. {
  135. uint8_t c;
  136. DMABaseClass::CFG_t *t;
  137. c = c1.channel;
  138. c1.channel = c2.channel;
  139. c2.channel = c;
  140. t = c1.CFG;
  141. c1.CFG = c2.CFG;
  142. c2.CFG = t;
  143. }
  144. #endif
  145. void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2)
  146. {
  147. if (priority(ch1) < priority(ch2)) swap(ch1, ch2);
  148. }
  149. void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2, DMAChannel &ch3)
  150. {
  151. if (priority(ch2) < priority(ch3)) swap(ch2, ch3);
  152. if (priority(ch1) < priority(ch2)) swap(ch1, ch2);
  153. if (priority(ch2) < priority(ch3)) swap(ch2, ch3);
  154. }
  155. void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2, DMAChannel &ch3, DMAChannel &ch4)
  156. {
  157. if (priority(ch3) < priority(ch4)) swap(ch3, ch4);
  158. if (priority(ch2) < priority(ch3)) swap(ch2, ch3);
  159. if (priority(ch1) < priority(ch2)) swap(ch1, ch2);
  160. if (priority(ch3) < priority(ch4)) swap(ch2, ch3);
  161. if (priority(ch2) < priority(ch3)) swap(ch1, ch2);
  162. if (priority(ch3) < priority(ch4)) swap(ch2, ch3);
  163. }