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