Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

194 lines
4.4KB

  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. }