My Marlin configs for Fabrikator Mini and CTC i3 Pro B
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.

SPI.h 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /******************************************************************************
  2. * The MIT License
  3. *
  4. * Copyright (c) 2010 Perry Hung.
  5. *
  6. * Permission is hereby granted, free of charge, to any person
  7. * obtaining a copy of this software and associated documentation
  8. * files (the "Software"), to deal in the Software without
  9. * restriction, including without limitation the rights to use, copy,
  10. * modify, merge, publish, distribute, sublicense, and/or sell copies
  11. * of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  21. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  22. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  23. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  24. * SOFTWARE.
  25. *****************************************************************************/
  26. #pragma once
  27. #include <libmaple/libmaple_types.h>
  28. #include <libmaple/spi.h>
  29. #include <libmaple/dma.h>
  30. #include <boards.h>
  31. #include <stdint.h>
  32. #include <wirish.h>
  33. // SPI_HAS_TRANSACTION means SPI has
  34. // - beginTransaction()
  35. // - endTransaction()
  36. // - usingInterrupt()
  37. // - SPISetting(clock, bitOrder, dataMode)
  38. //#define SPI_HAS_TRANSACTION
  39. #define SPI_CLOCK_DIV2 SPI_BAUD_PCLK_DIV_2
  40. #define SPI_CLOCK_DIV4 SPI_BAUD_PCLK_DIV_4
  41. #define SPI_CLOCK_DIV8 SPI_BAUD_PCLK_DIV_8
  42. #define SPI_CLOCK_DIV16 SPI_BAUD_PCLK_DIV_16
  43. #define SPI_CLOCK_DIV32 SPI_BAUD_PCLK_DIV_32
  44. #define SPI_CLOCK_DIV64 SPI_BAUD_PCLK_DIV_64
  45. #define SPI_CLOCK_DIV128 SPI_BAUD_PCLK_DIV_128
  46. #define SPI_CLOCK_DIV256 SPI_BAUD_PCLK_DIV_256
  47. /*
  48. * Roger Clark. 20150106
  49. * Commented out redundant AVR defined
  50. *
  51. #define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
  52. #define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
  53. #define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
  54. // define SPI_AVR_EIMSK for AVR boards with external interrupt pins
  55. #ifdef EIMSK
  56. #define SPI_AVR_EIMSK EIMSK
  57. #elif defined(GICR)
  58. #define SPI_AVR_EIMSK GICR
  59. #elif defined(GIMSK)
  60. #define SPI_AVR_EIMSK GIMSK
  61. #endif
  62. */
  63. #ifndef STM32_LSBFIRST
  64. #define STM32_LSBFIRST 0
  65. #endif
  66. #ifndef STM32_MSBFIRST
  67. #define STM32_MSBFIRST 1
  68. #endif
  69. // PC13 or PA4
  70. #define BOARD_SPI_DEFAULT_SS PA4
  71. //#define BOARD_SPI_DEFAULT_SS PC13
  72. #define SPI_MODE0 SPI_MODE_0
  73. #define SPI_MODE1 SPI_MODE_1
  74. #define SPI_MODE2 SPI_MODE_2
  75. #define SPI_MODE3 SPI_MODE_3
  76. #define DATA_SIZE_8BIT SPI_CR1_DFF_8_BIT
  77. #define DATA_SIZE_16BIT SPI_CR1_DFF_16_BIT
  78. typedef enum {
  79. SPI_STATE_IDLE,
  80. SPI_STATE_READY,
  81. SPI_STATE_RECEIVE,
  82. SPI_STATE_TRANSMIT,
  83. SPI_STATE_TRANSFER
  84. } spi_mode_t;
  85. class SPISettings {
  86. public:
  87. SPISettings(uint32_t inClock, BitOrder inBitOrder, uint8_t inDataMode) {
  88. if (__builtin_constant_p(inClock))
  89. init_AlwaysInline(inClock, inBitOrder, inDataMode, DATA_SIZE_8BIT);
  90. else
  91. init_MightInline(inClock, inBitOrder, inDataMode, DATA_SIZE_8BIT);
  92. }
  93. SPISettings(uint32_t inClock, BitOrder inBitOrder, uint8_t inDataMode, uint32_t inDataSize) {
  94. if (__builtin_constant_p(inClock))
  95. init_AlwaysInline(inClock, inBitOrder, inDataMode, inDataSize);
  96. else
  97. init_MightInline(inClock, inBitOrder, inDataMode, inDataSize);
  98. }
  99. SPISettings(uint32_t inClock) {
  100. if (__builtin_constant_p(inClock))
  101. init_AlwaysInline(inClock, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT);
  102. else
  103. init_MightInline(inClock, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT);
  104. }
  105. SPISettings() {
  106. init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT);
  107. }
  108. private:
  109. void init_MightInline(uint32_t inClock, BitOrder inBitOrder, uint8_t inDataMode, uint32_t inDataSize) {
  110. init_AlwaysInline(inClock, inBitOrder, inDataMode, inDataSize);
  111. }
  112. void init_AlwaysInline(uint32_t inClock, BitOrder inBitOrder, uint8_t inDataMode, uint32_t inDataSize) __attribute__((__always_inline__)) {
  113. clock = inClock;
  114. bitOrder = inBitOrder;
  115. dataMode = inDataMode;
  116. dataSize = inDataSize;
  117. //state = SPI_STATE_IDLE;
  118. }
  119. uint32_t clock;
  120. uint32_t dataSize;
  121. uint32_t clockDivider;
  122. BitOrder bitOrder;
  123. uint8_t dataMode;
  124. uint8_t _SSPin;
  125. volatile spi_mode_t state;
  126. spi_dev *spi_d;
  127. dma_channel spiRxDmaChannel, spiTxDmaChannel;
  128. dma_dev* spiDmaDev;
  129. void (*receiveCallback)() = NULL;
  130. void (*transmitCallback)() = NULL;
  131. friend class SPIClass;
  132. };
  133. /*
  134. * Kept for compat.
  135. */
  136. static const uint8_t ff = 0xFF;
  137. /**
  138. * @brief Wirish SPI interface.
  139. *
  140. * This implementation uses software slave management, so the caller
  141. * is responsible for controlling the slave select line.
  142. */
  143. class SPIClass {
  144. public:
  145. /**
  146. * @param spiPortNumber Number of the SPI port to manage.
  147. */
  148. SPIClass(uint32_t spiPortNumber);
  149. /**
  150. * @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0).
  151. */
  152. void begin();
  153. /**
  154. * @brief Turn on a SPI port and set its GPIO pin modes for use as a slave.
  155. *
  156. * SPI port is enabled in full duplex mode, with software slave management.
  157. *
  158. * @param bitOrder Either LSBFIRST (little-endian) or MSBFIRST(big-endian)
  159. * @param mode SPI mode to use
  160. */
  161. void beginSlave(uint32_t bitOrder, uint32_t mode);
  162. /**
  163. * @brief Equivalent to beginSlave(MSBFIRST, 0).
  164. */
  165. void beginSlave();
  166. /**
  167. * @brief Disables the SPI port, but leaves its GPIO pin modes unchanged.
  168. */
  169. void end();
  170. void beginTransaction(const SPISettings &settings) { beginTransaction(BOARD_SPI_DEFAULT_SS, settings); }
  171. void beginTransaction(uint8_t pin, const SPISettings &settings);
  172. void endTransaction();
  173. void beginTransactionSlave(const SPISettings &settings);
  174. void setClockDivider(uint32_t clockDivider);
  175. void setBitOrder(BitOrder bitOrder);
  176. void setDataMode(uint8_t dataMode);
  177. // SPI Configuration methods
  178. void attachInterrupt();
  179. void detachInterrupt();
  180. /* Victor Perez. Added to change datasize from 8 to 16 bit modes on the fly.
  181. * Input parameter should be SPI_CR1_DFF set to 0 or 1 on a 32bit word.
  182. * Requires an added function spi_data_size on STM32F1 / cores / maple / libmaple / spi.c
  183. */
  184. void setDataSize(uint32_t ds);
  185. uint32_t getDataSize() { return _currentSetting->dataSize; }
  186. /* Victor Perez 2017. Added to set and clear callback functions for callback
  187. * on DMA transfer completion.
  188. * onReceive used to set the callback in case of dmaTransfer (tx/rx), once rx is completed
  189. * onTransmit used to set the callback in case of dmaSend (tx only). That function
  190. * will NOT be called in case of TX/RX
  191. */
  192. void onReceive(void(*)());
  193. void onTransmit(void(*)());
  194. /*
  195. * I/O
  196. */
  197. /**
  198. * @brief Return the next unread byte/word.
  199. *
  200. * If there is no unread byte/word waiting, this function will block
  201. * until one is received.
  202. */
  203. uint16_t read();
  204. /**
  205. * @brief Read length bytes, storing them into buffer.
  206. * @param buffer Buffer to store received bytes into.
  207. * @param length Number of bytes to store in buffer. This
  208. * function will block until the desired number of
  209. * bytes have been read.
  210. */
  211. void read(uint8_t *buffer, uint32_t length);
  212. /**
  213. * @brief Transmit one byte/word.
  214. * @param data to transmit.
  215. */
  216. void write(uint16_t data);
  217. void write16(uint16_t data); // write 2 bytes in 8 bit mode (DFF=0)
  218. /**
  219. * @brief Transmit one byte/word a specified number of times.
  220. * @param data to transmit.
  221. */
  222. void write(uint16_t data, uint32_t n);
  223. /**
  224. * @brief Transmit multiple bytes/words.
  225. * @param buffer Bytes/words to transmit.
  226. * @param length Number of bytes/words in buffer to transmit.
  227. */
  228. void write(const void * buffer, uint32_t length);
  229. /**
  230. * @brief Transmit a byte, then return the next unread byte.
  231. *
  232. * This function transmits before receiving.
  233. *
  234. * @param data Byte to transmit.
  235. * @return Next unread byte.
  236. */
  237. uint8_t transfer(uint8_t data) const;
  238. uint16_t transfer16(uint16_t data) const;
  239. /**
  240. * @brief Sets up a DMA Transfer for "length" bytes.
  241. * The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting.
  242. *
  243. * This function transmits and receives to buffers.
  244. *
  245. * @param transmitBuf buffer Bytes to transmit. If passed as 0, it sends FF repeatedly for "length" bytes
  246. * @param receiveBuf buffer Bytes to save received data.
  247. * @param length Number of bytes in buffer to transmit.
  248. */
  249. uint8_t dmaTransfer(const void * transmitBuf, void * receiveBuf, uint16_t length);
  250. void dmaTransferSet(const void *transmitBuf, void *receiveBuf);
  251. uint8_t dmaTransferRepeat(uint16_t length);
  252. /**
  253. * @brief Sets up a DMA Transmit for SPI 8 or 16 bit transfer mode.
  254. * The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting.
  255. *
  256. * This function only transmits and does not care about the RX fifo.
  257. *
  258. * @param data buffer half words to transmit,
  259. * @param length Number of bytes in buffer to transmit.
  260. * @param minc Set to use Memory Increment mode, clear to use Circular mode.
  261. */
  262. uint8_t dmaSend(const void * transmitBuf, uint16_t length, bool minc = 1);
  263. void dmaSendSet(const void * transmitBuf, bool minc);
  264. uint8_t dmaSendRepeat(uint16_t length);
  265. uint8_t dmaSendAsync(const void * transmitBuf, uint16_t length, bool minc = 1);
  266. /*
  267. * Pin accessors
  268. */
  269. /**
  270. * @brief Return the number of the MISO (master in, slave out) pin
  271. */
  272. uint8_t misoPin();
  273. /**
  274. * @brief Return the number of the MOSI (master out, slave in) pin
  275. */
  276. uint8_t mosiPin();
  277. /**
  278. * @brief Return the number of the SCK (serial clock) pin
  279. */
  280. uint8_t sckPin();
  281. /**
  282. * @brief Return the number of the NSS (slave select) pin
  283. */
  284. uint8_t nssPin();
  285. /* Escape hatch */
  286. /**
  287. * @brief Get a pointer to the underlying libmaple spi_dev for
  288. * this HardwareSPI instance.
  289. */
  290. spi_dev* c_dev() { return _currentSetting->spi_d; }
  291. spi_dev* dev() { return _currentSetting->spi_d; }
  292. /**
  293. * @brief Sets the number of the SPI peripheral to be used by
  294. * this HardwareSPI instance.
  295. *
  296. * @param spi_num Number of the SPI port. 1-2 in low density devices
  297. * or 1-3 in high density devices.
  298. */
  299. void setModule(int spi_num) {
  300. _currentSetting = &_settings[spi_num - 1];// SPI channels are called 1 2 and 3 but the array is zero indexed
  301. }
  302. /* -- The following methods are deprecated --------------------------- */
  303. /**
  304. * @brief Deprecated.
  305. *
  306. * Use HardwareSPI::transfer() instead.
  307. *
  308. * @see HardwareSPI::transfer()
  309. */
  310. uint8_t send(uint8_t data);
  311. /**
  312. * @brief Deprecated.
  313. *
  314. * Use HardwareSPI::write() in combination with
  315. * HardwareSPI::read() (or HardwareSPI::transfer()) instead.
  316. *
  317. * @see HardwareSPI::write()
  318. * @see HardwareSPI::read()
  319. * @see HardwareSPI::transfer()
  320. */
  321. uint8_t send(uint8_t *data, uint32_t length);
  322. /**
  323. * @brief Deprecated.
  324. *
  325. * Use HardwareSPI::read() instead.
  326. *
  327. * @see HardwareSPI::read()
  328. */
  329. uint8_t recv();
  330. private:
  331. SPISettings _settings[BOARD_NR_SPI];
  332. SPISettings *_currentSetting;
  333. void updateSettings();
  334. /*
  335. * Functions added for DMA transfers with Callback.
  336. * Experimental.
  337. */
  338. void EventCallback();
  339. #if BOARD_NR_SPI >= 1
  340. static void _spi1EventCallback();
  341. #endif
  342. #if BOARD_NR_SPI >= 2
  343. static void _spi2EventCallback();
  344. #endif
  345. #if BOARD_NR_SPI >= 3
  346. static void _spi3EventCallback();
  347. #endif
  348. /*
  349. spi_dev *spi_d;
  350. uint8_t _SSPin;
  351. uint32_t clockDivider;
  352. uint8_t dataMode;
  353. BitOrder bitOrder;
  354. */
  355. };
  356. /**
  357. * @brief Wait until TXE (tx empty) flag is set and BSY (busy) flag unset.
  358. */
  359. static inline void waitSpiTxEnd(spi_dev *spi_d) {
  360. while (spi_is_tx_empty(spi_d) == 0) { /* nada */ } // wait until TXE=1
  361. while (spi_is_busy(spi_d) != 0) { /* nada */ } // wait until BSY=0
  362. }
  363. extern SPIClass SPI;