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 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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. }