My Marlin configs for Fabrikator Mini and CTC i3 Pro B
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

MarlinSPI.cpp 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #include "../platforms.h"
  23. #if defined(HAL_STM32) && !defined(STM32H7xx)
  24. #include "MarlinSPI.h"
  25. static void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb, uint32_t dataSize) {
  26. spi_init(obj, speed, mode, msb);
  27. // spi_init set 8bit always
  28. // TODO: copy the code from spi_init and handle data size, to avoid double init always!!
  29. if (dataSize != SPI_DATASIZE_8BIT) {
  30. obj->handle.Init.DataSize = dataSize;
  31. HAL_SPI_Init(&obj->handle);
  32. __HAL_SPI_ENABLE(&obj->handle);
  33. }
  34. }
  35. void MarlinSPI::setClockDivider(uint8_t _div) {
  36. _speed = spi_getClkFreq(&_spi);// / _div;
  37. _clockDivider = _div;
  38. }
  39. void MarlinSPI::begin(void) {
  40. //TODO: only call spi_init if any parameter changed!!
  41. spi_init(&_spi, _speed, _dataMode, _bitOrder, _dataSize);
  42. }
  43. void MarlinSPI::setupDma(SPI_HandleTypeDef &_spiHandle, DMA_HandleTypeDef &_dmaHandle, uint32_t direction, bool minc) {
  44. _dmaHandle.Init.Direction = direction;
  45. _dmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
  46. _dmaHandle.Init.Mode = DMA_NORMAL;
  47. _dmaHandle.Init.Priority = DMA_PRIORITY_LOW;
  48. _dmaHandle.Init.MemInc = minc ? DMA_MINC_ENABLE : DMA_MINC_DISABLE;
  49. if (_dataSize == DATA_SIZE_8BIT) {
  50. _dmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  51. _dmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  52. }
  53. else {
  54. _dmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  55. _dmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  56. }
  57. #ifdef STM32F4xx
  58. _dmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  59. #endif
  60. // start DMA hardware
  61. // TODO: check if hardware is already enabled
  62. #ifdef SPI1_BASE
  63. if (_spiHandle.Instance == SPI1) {
  64. #ifdef STM32F1xx
  65. __HAL_RCC_DMA1_CLK_ENABLE();
  66. _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Channel3 : DMA1_Channel2;
  67. #elif defined(STM32F4xx)
  68. __HAL_RCC_DMA2_CLK_ENABLE();
  69. _dmaHandle.Init.Channel = DMA_CHANNEL_3;
  70. _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA2_Stream3 : DMA2_Stream0;
  71. #endif
  72. }
  73. #endif
  74. #ifdef SPI2_BASE
  75. if (_spiHandle.Instance == SPI2) {
  76. #ifdef STM32F1xx
  77. __HAL_RCC_DMA1_CLK_ENABLE();
  78. _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Channel5 : DMA1_Channel4;
  79. #elif defined(STM32F4xx)
  80. __HAL_RCC_DMA1_CLK_ENABLE();
  81. _dmaHandle.Init.Channel = DMA_CHANNEL_0;
  82. _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Stream4 : DMA1_Stream3;
  83. #endif
  84. }
  85. #endif
  86. #ifdef SPI3_BASE
  87. if (_spiHandle.Instance == SPI3) {
  88. #ifdef STM32F1xx
  89. __HAL_RCC_DMA2_CLK_ENABLE();
  90. _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA2_Channel2 : DMA2_Channel1;
  91. #elif defined(STM32F4xx)
  92. __HAL_RCC_DMA1_CLK_ENABLE();
  93. _dmaHandle.Init.Channel = DMA_CHANNEL_0;
  94. _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Stream5 : DMA1_Stream2;
  95. #endif
  96. }
  97. #endif
  98. HAL_DMA_Init(&_dmaHandle);
  99. }
  100. byte MarlinSPI::transfer(uint8_t _data) {
  101. uint8_t rxData = 0xFF;
  102. HAL_SPI_TransmitReceive(&_spi.handle, &_data, &rxData, 1, HAL_MAX_DELAY);
  103. return rxData;
  104. }
  105. __STATIC_INLINE void LL_SPI_EnableDMAReq_RX(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); }
  106. __STATIC_INLINE void LL_SPI_EnableDMAReq_TX(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); }
  107. uint8_t MarlinSPI::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length) {
  108. const uint8_t ff = 0xFF;
  109. //if (!LL_SPI_IsEnabled(_spi.handle)) // only enable if disabled
  110. __HAL_SPI_ENABLE(&_spi.handle);
  111. if (receiveBuf) {
  112. setupDma(_spi.handle, _dmaRx, DMA_PERIPH_TO_MEMORY, true);
  113. HAL_DMA_Start(&_dmaRx, (uint32_t)&(_spi.handle.Instance->DR), (uint32_t)receiveBuf, length);
  114. LL_SPI_EnableDMAReq_RX(_spi.handle.Instance); // Enable Rx DMA Request
  115. }
  116. // check for 2 lines transfer
  117. bool mincTransmit = true;
  118. if (transmitBuf == nullptr && _spi.handle.Init.Direction == SPI_DIRECTION_2LINES && _spi.handle.Init.Mode == SPI_MODE_MASTER) {
  119. transmitBuf = &ff;
  120. mincTransmit = false;
  121. }
  122. if (transmitBuf) {
  123. setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, mincTransmit);
  124. HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
  125. LL_SPI_EnableDMAReq_TX(_spi.handle.Instance); // Enable Tx DMA Request
  126. }
  127. if (transmitBuf) {
  128. HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
  129. HAL_DMA_Abort(&_dmaTx);
  130. HAL_DMA_DeInit(&_dmaTx);
  131. }
  132. // while ((_spi.handle.Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE) {}
  133. if (receiveBuf) {
  134. HAL_DMA_PollForTransfer(&_dmaRx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
  135. HAL_DMA_Abort(&_dmaRx);
  136. HAL_DMA_DeInit(&_dmaRx);
  137. }
  138. return 1;
  139. }
  140. uint8_t MarlinSPI::dmaSend(const void * transmitBuf, uint16_t length, bool minc) {
  141. setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, minc);
  142. HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
  143. __HAL_SPI_ENABLE(&_spi.handle);
  144. LL_SPI_EnableDMAReq_TX(_spi.handle.Instance); // Enable Tx DMA Request
  145. HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
  146. HAL_DMA_Abort(&_dmaTx);
  147. // DeInit objects
  148. HAL_DMA_DeInit(&_dmaTx);
  149. return 1;
  150. }
  151. #endif // HAL_STM32 && !STM32H7xx