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.

107 line
2.5KB

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