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.

1252 lines
36KB

  1. /*
  2. * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
  3. * SPI Master library for arduino.
  4. *
  5. * This file is free software; you can redistribute it and/or modify
  6. * it under the terms of either the GNU General Public License version 2
  7. * or the GNU Lesser General Public License version 2.1, both as
  8. * published by the Free Software Foundation.
  9. */
  10. #include "SPI.h"
  11. #include "pins_arduino.h"
  12. /**********************************************************/
  13. /* 8 bit AVR-based boards */
  14. /**********************************************************/
  15. #if defined(__AVR__)
  16. SPIClass SPI;
  17. uint8_t SPIClass::interruptMode = 0;
  18. uint8_t SPIClass::interruptMask = 0;
  19. uint8_t SPIClass::interruptSave = 0;
  20. #ifdef SPI_TRANSACTION_MISMATCH_LED
  21. uint8_t SPIClass::inTransactionFlag = 0;
  22. #endif
  23. uint8_t SPIClass::_transferWriteFill = 0;
  24. void SPIClass::begin()
  25. {
  26. // Set SS to high so a connected chip will be "deselected" by default
  27. digitalWrite(SS, HIGH);
  28. // When the SS pin is set as OUTPUT, it can be used as
  29. // a general purpose output port (it doesn't influence
  30. // SPI operations).
  31. pinMode(SS, OUTPUT);
  32. // Warning: if the SS pin ever becomes a LOW INPUT then SPI
  33. // automatically switches to Slave, so the data direction of
  34. // the SS pin MUST be kept as OUTPUT.
  35. SPCR |= _BV(MSTR);
  36. SPCR |= _BV(SPE);
  37. // Set direction register for SCK and MOSI pin.
  38. // MISO pin automatically overrides to INPUT.
  39. // By doing this AFTER enabling SPI, we avoid accidentally
  40. // clocking in a single bit since the lines go directly
  41. // from "input" to SPI control.
  42. // http://code.google.com/p/arduino/issues/detail?id=888
  43. pinMode(SCK, OUTPUT);
  44. pinMode(MOSI, OUTPUT);
  45. }
  46. void SPIClass::end() {
  47. SPCR &= ~_BV(SPE);
  48. }
  49. // mapping of interrupt numbers to bits within SPI_AVR_EIMSK
  50. #if defined(__AVR_ATmega32U4__)
  51. #define SPI_INT0_MASK (1<<INT0)
  52. #define SPI_INT1_MASK (1<<INT1)
  53. #define SPI_INT2_MASK (1<<INT2)
  54. #define SPI_INT3_MASK (1<<INT3)
  55. #define SPI_INT4_MASK (1<<INT6)
  56. #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
  57. #define SPI_INT0_MASK (1<<INT0)
  58. #define SPI_INT1_MASK (1<<INT1)
  59. #define SPI_INT2_MASK (1<<INT2)
  60. #define SPI_INT3_MASK (1<<INT3)
  61. #define SPI_INT4_MASK (1<<INT4)
  62. #define SPI_INT5_MASK (1<<INT5)
  63. #define SPI_INT6_MASK (1<<INT6)
  64. #define SPI_INT7_MASK (1<<INT7)
  65. #elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
  66. #define SPI_INT0_MASK (1<<INT4)
  67. #define SPI_INT1_MASK (1<<INT5)
  68. #define SPI_INT2_MASK (1<<INT0)
  69. #define SPI_INT3_MASK (1<<INT1)
  70. #define SPI_INT4_MASK (1<<INT2)
  71. #define SPI_INT5_MASK (1<<INT3)
  72. #define SPI_INT6_MASK (1<<INT6)
  73. #define SPI_INT7_MASK (1<<INT7)
  74. #else
  75. #ifdef INT0
  76. #define SPI_INT0_MASK (1<<INT0)
  77. #endif
  78. #ifdef INT1
  79. #define SPI_INT1_MASK (1<<INT1)
  80. #endif
  81. #ifdef INT2
  82. #define SPI_INT2_MASK (1<<INT2)
  83. #endif
  84. #endif
  85. void SPIClass::usingInterrupt(uint8_t interruptNumber)
  86. {
  87. uint8_t stmp, mask;
  88. if (interruptMode > 1) return;
  89. stmp = SREG;
  90. noInterrupts();
  91. switch (interruptNumber) {
  92. #ifdef SPI_INT0_MASK
  93. case 0: mask = SPI_INT0_MASK; break;
  94. #endif
  95. #ifdef SPI_INT1_MASK
  96. case 1: mask = SPI_INT1_MASK; break;
  97. #endif
  98. #ifdef SPI_INT2_MASK
  99. case 2: mask = SPI_INT2_MASK; break;
  100. #endif
  101. #ifdef SPI_INT3_MASK
  102. case 3: mask = SPI_INT3_MASK; break;
  103. #endif
  104. #ifdef SPI_INT4_MASK
  105. case 4: mask = SPI_INT4_MASK; break;
  106. #endif
  107. #ifdef SPI_INT5_MASK
  108. case 5: mask = SPI_INT5_MASK; break;
  109. #endif
  110. #ifdef SPI_INT6_MASK
  111. case 6: mask = SPI_INT6_MASK; break;
  112. #endif
  113. #ifdef SPI_INT7_MASK
  114. case 7: mask = SPI_INT7_MASK; break;
  115. #endif
  116. default:
  117. interruptMode = 2;
  118. SREG = stmp;
  119. return;
  120. }
  121. interruptMode = 1;
  122. interruptMask |= mask;
  123. SREG = stmp;
  124. }
  125. void SPIClass::transfer(const void * buf, void * retbuf, uint32_t count) {
  126. if (count == 0) return;
  127. const uint8_t *p = (const uint8_t *)buf;
  128. uint8_t *pret = (uint8_t *)retbuf;
  129. uint8_t in;
  130. uint8_t out = p ? *p++ : _transferWriteFill;
  131. SPDR = out;
  132. while (--count > 0) {
  133. if (p) {
  134. out = *p++;
  135. }
  136. while (!(SPSR & _BV(SPIF))) ;
  137. in = SPDR;
  138. SPDR = out;
  139. if (pret)*pret++ = in;
  140. }
  141. while (!(SPSR & _BV(SPIF))) ;
  142. in = SPDR;
  143. if (pret)*pret = in;
  144. }
  145. /**********************************************************/
  146. /* 32 bit Teensy 3.x */
  147. /**********************************************************/
  148. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK)
  149. #if defined(KINETISK) && defined( SPI_HAS_TRANSFER_ASYNC)
  150. #ifndef TRANSFER_COUNT_FIXED
  151. inline void DMAChanneltransferCount(DMAChannel * dmac, unsigned int len) {
  152. // note does no validation of length...
  153. DMABaseClass::TCD_t *tcd = dmac->TCD;
  154. if (!(tcd->BITER & DMA_TCD_BITER_ELINK)) {
  155. tcd->BITER = len & 0x7fff;
  156. } else {
  157. tcd->BITER = (tcd->BITER & 0xFE00) | (len & 0x1ff);
  158. }
  159. tcd->CITER = tcd->BITER;
  160. }
  161. #else
  162. inline void DMAChanneltransferCount(DMAChannel * dmac, unsigned int len) {
  163. dmac->transferCount(len);
  164. }
  165. #endif
  166. #endif
  167. #if defined(__MK20DX128__) || defined(__MK20DX256__)
  168. #ifdef SPI_HAS_TRANSFER_ASYNC
  169. void _spi_dma_rxISR0(void) {SPI.dma_rxisr();}
  170. #else
  171. void _spi_dma_rxISR0(void) {;}
  172. #endif
  173. const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = {
  174. SIM_SCGC6, SIM_SCGC6_SPI0, 4, IRQ_SPI0,
  175. 32767, DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX,
  176. _spi_dma_rxISR0,
  177. 12, 8,
  178. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  179. 11, 7,
  180. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  181. 13, 14,
  182. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  183. 10, 2, 9, 6, 20, 23, 21, 22, 15,
  184. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  185. 0x1, 0x1, 0x2, 0x2, 0x4, 0x4, 0x8, 0x8, 0x10
  186. };
  187. SPIClass SPI((uintptr_t)&KINETISK_SPI0, (uintptr_t)&SPIClass::spi0_hardware);
  188. #elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
  189. #ifdef SPI_HAS_TRANSFER_ASYNC
  190. void _spi_dma_rxISR0(void) {SPI.dma_rxisr();}
  191. void _spi_dma_rxISR1(void) {SPI1.dma_rxisr();}
  192. void _spi_dma_rxISR2(void) {SPI2.dma_rxisr();}
  193. #else
  194. void _spi_dma_rxISR0(void) {;}
  195. void _spi_dma_rxISR1(void) {;}
  196. void _spi_dma_rxISR2(void) {;}
  197. #endif
  198. const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = {
  199. SIM_SCGC6, SIM_SCGC6_SPI0, 4, IRQ_SPI0,
  200. 32767, DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX,
  201. _spi_dma_rxISR0,
  202. 12, 8, 39, 255,
  203. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0,
  204. 11, 7, 28, 255,
  205. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0,
  206. 13, 14, 27,
  207. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  208. 10, 2, 9, 6, 20, 23, 21, 22, 15, 26, 45,
  209. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(3),
  210. 0x1, 0x1, 0x2, 0x2, 0x4, 0x4, 0x8, 0x8, 0x10, 0x1, 0x20
  211. };
  212. const SPIClass::SPI_Hardware_t SPIClass::spi1_hardware = {
  213. SIM_SCGC6, SIM_SCGC6_SPI1, 1, IRQ_SPI1,
  214. #if defined(__MK66FX1M0__)
  215. 32767, DMAMUX_SOURCE_SPI1_TX, DMAMUX_SOURCE_SPI1_RX,
  216. #else
  217. // T3.5 does not have good DMA support on 1 and 2
  218. 511, 0, DMAMUX_SOURCE_SPI1,
  219. #endif
  220. _spi_dma_rxISR1,
  221. 1, 5, 61, 59,
  222. PORT_PCR_MUX(2), PORT_PCR_MUX(7), PORT_PCR_MUX(2), PORT_PCR_MUX(7),
  223. 0, 21, 61, 59,
  224. PORT_PCR_MUX(2), PORT_PCR_MUX(7), PORT_PCR_MUX(7), PORT_PCR_MUX(2),
  225. 32, 20, 60,
  226. PORT_PCR_MUX(2), PORT_PCR_MUX(7), PORT_PCR_MUX(2),
  227. 6, 31, 58, 62, 63, 255, 255, 255, 255, 255, 255,
  228. PORT_PCR_MUX(7), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0, 0, 0, 0, 0, 0,
  229. 0x1, 0x1, 0x2, 0x1, 0x4, 0, 0, 0, 0, 0, 0
  230. };
  231. const SPIClass::SPI_Hardware_t SPIClass::spi2_hardware = {
  232. SIM_SCGC3, SIM_SCGC3_SPI2, 1, IRQ_SPI2,
  233. #if defined(__MK66FX1M0__)
  234. 32767, DMAMUX_SOURCE_SPI2_TX, DMAMUX_SOURCE_SPI2_RX,
  235. #else
  236. // T3.5 does not have good DMA support on 1 and 2
  237. 511, 0, DMAMUX_SOURCE_SPI2,
  238. #endif
  239. _spi_dma_rxISR2,
  240. 45, 51, 255, 255,
  241. PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0, 0,
  242. 44, 52, 255, 255,
  243. PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0, 0,
  244. 46, 53, 255,
  245. PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0,
  246. 43, 54, 55, 255, 255, 255, 255, 255, 255, 255, 255,
  247. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0, 0, 0, 0, 0, 0, 0, 0,
  248. 0x1, 0x2, 0x1, 0, 0, 0, 0, 0, 0, 0, 0
  249. };
  250. SPIClass SPI((uintptr_t)&KINETISK_SPI0, (uintptr_t)&SPIClass::spi0_hardware);
  251. SPIClass SPI1((uintptr_t)&KINETISK_SPI1, (uintptr_t)&SPIClass::spi1_hardware);
  252. SPIClass SPI2((uintptr_t)&KINETISK_SPI2, (uintptr_t)&SPIClass::spi2_hardware);
  253. #endif
  254. void SPIClass::begin()
  255. {
  256. volatile uint32_t *reg;
  257. hardware().clock_gate_register |= hardware().clock_gate_mask;
  258. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  259. port().CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  260. port().CTAR1 = SPI_CTAR_FMSZ(15) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  261. port().MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
  262. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  263. *reg = hardware().mosi_mux[mosi_pin_index];
  264. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  265. *reg= hardware().miso_mux[miso_pin_index];
  266. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  267. *reg = hardware().sck_mux[sck_pin_index];
  268. }
  269. void SPIClass::end()
  270. {
  271. volatile uint32_t *reg;
  272. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  273. *reg = 0;
  274. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  275. *reg = 0;
  276. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  277. *reg = 0;
  278. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  279. }
  280. void SPIClass::usingInterrupt(IRQ_NUMBER_t interruptName)
  281. {
  282. uint32_t n = (uint32_t)interruptName;
  283. if (n >= NVIC_NUM_INTERRUPTS) return;
  284. //Serial.print("usingInterrupt ");
  285. //Serial.println(n);
  286. interruptMasksUsed |= (1 << (n >> 5));
  287. interruptMask[n >> 5] |= (1 << (n & 0x1F));
  288. //Serial.printf("interruptMasksUsed = %d\n", interruptMasksUsed);
  289. //Serial.printf("interruptMask[0] = %08X\n", interruptMask[0]);
  290. //Serial.printf("interruptMask[1] = %08X\n", interruptMask[1]);
  291. //Serial.printf("interruptMask[2] = %08X\n", interruptMask[2]);
  292. }
  293. void SPIClass::notUsingInterrupt(IRQ_NUMBER_t interruptName)
  294. {
  295. uint32_t n = (uint32_t)interruptName;
  296. if (n >= NVIC_NUM_INTERRUPTS) return;
  297. interruptMask[n >> 5] &= ~(1 << (n & 0x1F));
  298. if (interruptMask[n >> 5] == 0) {
  299. interruptMasksUsed &= ~(1 << (n >> 5));
  300. }
  301. }
  302. const uint16_t SPISettings::ctar_div_table[23] = {
  303. 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40,
  304. 56, 64, 96, 128, 192, 256, 384, 512, 640, 768
  305. };
  306. const uint32_t SPISettings::ctar_clock_table[23] = {
  307. SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  308. SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  309. SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  310. SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  311. SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  312. SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1),
  313. SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  314. SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1),
  315. SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  316. SPI_CTAR_PBR(2) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(0),
  317. SPI_CTAR_PBR(1) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  318. SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(3),
  319. SPI_CTAR_PBR(2) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  320. SPI_CTAR_PBR(3) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  321. SPI_CTAR_PBR(0) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4),
  322. SPI_CTAR_PBR(1) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4),
  323. SPI_CTAR_PBR(0) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5),
  324. SPI_CTAR_PBR(1) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5),
  325. SPI_CTAR_PBR(0) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  326. SPI_CTAR_PBR(1) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  327. SPI_CTAR_PBR(0) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7),
  328. SPI_CTAR_PBR(2) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  329. SPI_CTAR_PBR(1) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7)
  330. };
  331. void SPIClass::updateCTAR(uint32_t ctar)
  332. {
  333. if (port().CTAR0 != ctar) {
  334. uint32_t mcr = port().MCR;
  335. if (mcr & SPI_MCR_MDIS) {
  336. port().CTAR0 = ctar;
  337. port().CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  338. } else {
  339. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  340. port().CTAR0 = ctar;
  341. port().CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  342. port().MCR = mcr;
  343. }
  344. }
  345. }
  346. void SPIClass::setBitOrder(uint8_t bitOrder)
  347. {
  348. hardware().clock_gate_register |= hardware().clock_gate_mask;
  349. uint32_t ctar = port().CTAR0;
  350. if (bitOrder == LSBFIRST) {
  351. ctar |= SPI_CTAR_LSBFE;
  352. } else {
  353. ctar &= ~SPI_CTAR_LSBFE;
  354. }
  355. updateCTAR(ctar);
  356. }
  357. void SPIClass::setDataMode(uint8_t dataMode)
  358. {
  359. hardware().clock_gate_register |= hardware().clock_gate_mask;
  360. //uint32_t ctar = port().CTAR0;
  361. // TODO: implement with native code
  362. //SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
  363. }
  364. void SPIClass::setClockDivider_noInline(uint32_t clk)
  365. {
  366. hardware().clock_gate_register |= hardware().clock_gate_mask;
  367. uint32_t ctar = port().CTAR0;
  368. ctar &= (SPI_CTAR_CPOL | SPI_CTAR_CPHA | SPI_CTAR_LSBFE);
  369. if (ctar & SPI_CTAR_CPHA) {
  370. clk = (clk & 0xFFFF0FFF) | ((clk & 0xF000) >> 4);
  371. }
  372. ctar |= clk;
  373. updateCTAR(ctar);
  374. }
  375. uint8_t SPIClass::pinIsChipSelect(uint8_t pin)
  376. {
  377. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  378. if (pin == hardware().cs_pin[i]) return hardware().cs_mask[i];
  379. }
  380. return 0;
  381. }
  382. bool SPIClass::pinIsChipSelect(uint8_t pin1, uint8_t pin2)
  383. {
  384. uint8_t pin1_mask, pin2_mask;
  385. if ((pin1_mask = (uint8_t)pinIsChipSelect(pin1)) == 0) return false;
  386. if ((pin2_mask = (uint8_t)pinIsChipSelect(pin2)) == 0) return false;
  387. //Serial.printf("pinIsChipSelect %d %d %x %x\n\r", pin1, pin2, pin1_mask, pin2_mask);
  388. if ((pin1_mask & pin2_mask) != 0) return false;
  389. return true;
  390. }
  391. bool SPIClass::pinIsMOSI(uint8_t pin)
  392. {
  393. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  394. if (pin == hardware().mosi_pin[i]) return true;
  395. }
  396. return false;
  397. }
  398. bool SPIClass::pinIsMISO(uint8_t pin)
  399. {
  400. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  401. if (pin == hardware().miso_pin[i]) return true;
  402. }
  403. return false;
  404. }
  405. bool SPIClass::pinIsSCK(uint8_t pin)
  406. {
  407. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  408. if (pin == hardware().sck_pin[i]) return true;
  409. }
  410. return false;
  411. }
  412. // setCS() is not intended for use from normal Arduino programs/sketches.
  413. uint8_t SPIClass::setCS(uint8_t pin)
  414. {
  415. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  416. if (pin == hardware().cs_pin[i]) {
  417. volatile uint32_t *reg = portConfigRegister(pin);
  418. *reg = hardware().cs_mux[i];
  419. return hardware().cs_mask[i];
  420. }
  421. }
  422. return 0;
  423. }
  424. void SPIClass::setMOSI(uint8_t pin)
  425. {
  426. if (pin != hardware().mosi_pin[mosi_pin_index]) {
  427. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  428. if (pin == hardware().mosi_pin[i]) {
  429. if (hardware().clock_gate_register & hardware().clock_gate_mask) {
  430. volatile uint32_t *reg;
  431. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  432. *reg = 0;
  433. reg = portConfigRegister(hardware().mosi_pin[i]);
  434. *reg = hardware().mosi_mux[i];
  435. }
  436. mosi_pin_index = i;
  437. return;
  438. }
  439. }
  440. }
  441. }
  442. void SPIClass::setMISO(uint8_t pin)
  443. {
  444. if (pin != hardware().miso_pin[miso_pin_index]) {
  445. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  446. if (pin == hardware().miso_pin[i]) {
  447. if (hardware().clock_gate_register & hardware().clock_gate_mask) {
  448. volatile uint32_t *reg;
  449. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  450. *reg = 0;
  451. reg = portConfigRegister(hardware().miso_pin[i]);
  452. *reg = hardware().miso_mux[i];
  453. }
  454. miso_pin_index = i;
  455. return;
  456. }
  457. }
  458. }
  459. }
  460. void SPIClass::setSCK(uint8_t pin)
  461. {
  462. if (pin != hardware().sck_pin[sck_pin_index]) {
  463. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  464. if (pin == hardware().sck_pin[i]) {
  465. if (hardware().clock_gate_register & hardware().clock_gate_mask) {
  466. volatile uint32_t *reg;
  467. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  468. *reg = 0;
  469. reg = portConfigRegister(hardware().sck_pin[i]);
  470. *reg = hardware().sck_mux[i];
  471. }
  472. sck_pin_index = i;
  473. return;
  474. }
  475. }
  476. }
  477. }
  478. void SPIClass::transfer(const void * buf, void * retbuf, size_t count)
  479. {
  480. if (count == 0) return;
  481. if (!(port().CTAR0 & SPI_CTAR_LSBFE)) {
  482. // We are doing the standard MSB order
  483. const uint8_t *p_write = (const uint8_t *)buf;
  484. uint8_t *p_read = (uint8_t *)retbuf;
  485. size_t count_read = count;
  486. // Lets clear the reader queue
  487. port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
  488. uint32_t sr;
  489. // Now lets loop while we still have data to output
  490. if (count & 1) {
  491. if (p_write) {
  492. if (count > 1)
  493. port().PUSHR = *p_write++ | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0);
  494. else
  495. port().PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
  496. } else {
  497. if (count > 1)
  498. port().PUSHR = _transferWriteFill | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0);
  499. else
  500. port().PUSHR = _transferWriteFill | SPI_PUSHR_CTAS(0);
  501. }
  502. count--;
  503. }
  504. uint16_t w = (uint16_t)(_transferWriteFill << 8) | _transferWriteFill;
  505. while (count > 0) {
  506. // Push out the next byte;
  507. if (p_write) {
  508. w = (*p_write++) << 8;
  509. w |= *p_write++;
  510. }
  511. uint16_t queue_full_status_mask = (hardware().queue_size-1) << 12;
  512. if (count == 2)
  513. port().PUSHR = w | SPI_PUSHR_CTAS(1);
  514. else
  515. port().PUSHR = w | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1);
  516. count -= 2; // how many bytes to output.
  517. // Make sure queue is not full before pushing next byte out
  518. do {
  519. sr = port().SR;
  520. if (sr & 0xF0) {
  521. uint16_t w = port().POPR; // Read any pending RX bytes in
  522. if (count_read & 1) {
  523. if (p_read) {
  524. *p_read++ = w; // Read any pending RX bytes in
  525. }
  526. count_read--;
  527. } else {
  528. if (p_read) {
  529. *p_read++ = w >> 8;
  530. *p_read++ = (w & 0xff);
  531. }
  532. count_read -= 2;
  533. }
  534. }
  535. } while ((sr & (15 << 12)) > queue_full_status_mask);
  536. }
  537. // now lets wait for all of the read bytes to be returned...
  538. while (count_read) {
  539. sr = port().SR;
  540. if (sr & 0xF0) {
  541. uint16_t w = port().POPR; // Read any pending RX bytes in
  542. if (count_read & 1) {
  543. if (p_read)
  544. *p_read++ = w; // Read any pending RX bytes in
  545. count_read--;
  546. } else {
  547. if (p_read) {
  548. *p_read++ = w >> 8;
  549. *p_read++ = (w & 0xff);
  550. }
  551. count_read -= 2;
  552. }
  553. }
  554. }
  555. } else {
  556. // We are doing the less ofen LSB mode
  557. const uint8_t *p_write = (const uint8_t *)buf;
  558. uint8_t *p_read = (uint8_t *)retbuf;
  559. size_t count_read = count;
  560. // Lets clear the reader queue
  561. port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
  562. uint32_t sr;
  563. // Now lets loop while we still have data to output
  564. if (count & 1) {
  565. if (p_write) {
  566. if (count > 1)
  567. port().PUSHR = *p_write++ | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0);
  568. else
  569. port().PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
  570. } else {
  571. if (count > 1)
  572. port().PUSHR = _transferWriteFill | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0);
  573. else
  574. port().PUSHR = _transferWriteFill | SPI_PUSHR_CTAS(0);
  575. }
  576. count--;
  577. }
  578. uint16_t w = _transferWriteFill;
  579. while (count > 0) {
  580. // Push out the next byte;
  581. if (p_write) {
  582. w = *p_write++;
  583. w |= ((*p_write++) << 8);
  584. }
  585. uint16_t queue_full_status_mask = (hardware().queue_size-1) << 12;
  586. if (count == 2)
  587. port().PUSHR = w | SPI_PUSHR_CTAS(1);
  588. else
  589. port().PUSHR = w | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1);
  590. count -= 2; // how many bytes to output.
  591. // Make sure queue is not full before pushing next byte out
  592. do {
  593. sr = port().SR;
  594. if (sr & 0xF0) {
  595. uint16_t w = port().POPR; // Read any pending RX bytes in
  596. if (count_read & 1) {
  597. if (p_read) {
  598. *p_read++ = w; // Read any pending RX bytes in
  599. }
  600. count_read--;
  601. } else {
  602. if (p_read) {
  603. *p_read++ = (w & 0xff);
  604. *p_read++ = w >> 8;
  605. }
  606. count_read -= 2;
  607. }
  608. }
  609. } while ((sr & (15 << 12)) > queue_full_status_mask);
  610. }
  611. // now lets wait for all of the read bytes to be returned...
  612. while (count_read) {
  613. sr = port().SR;
  614. if (sr & 0xF0) {
  615. uint16_t w = port().POPR; // Read any pending RX bytes in
  616. if (count_read & 1) {
  617. if (p_read)
  618. *p_read++ = w; // Read any pending RX bytes in
  619. count_read--;
  620. } else {
  621. if (p_read) {
  622. *p_read++ = (w & 0xff);
  623. *p_read++ = w >> 8;
  624. }
  625. count_read -= 2;
  626. }
  627. }
  628. }
  629. }
  630. }
  631. //=============================================================================
  632. // ASYNCH Support
  633. //=============================================================================
  634. //=========================================================================
  635. // Try Transfer using DMA.
  636. //=========================================================================
  637. #ifdef SPI_HAS_TRANSFER_ASYNC
  638. static uint8_t bit_bucket;
  639. #define dontInterruptAtCompletion(dmac) (dmac)->TCD->CSR &= ~DMA_TCD_CSR_INTMAJOR
  640. //=========================================================================
  641. // Init the DMA channels
  642. //=========================================================================
  643. bool SPIClass::initDMAChannels() {
  644. // Allocate our channels.
  645. _dmaTX = new DMAChannel();
  646. if (_dmaTX == nullptr) {
  647. return false;
  648. }
  649. _dmaRX = new DMAChannel();
  650. if (_dmaRX == nullptr) {
  651. delete _dmaTX; // release it
  652. _dmaTX = nullptr;
  653. return false;
  654. }
  655. // Let's setup the RX chain
  656. _dmaRX->disable();
  657. _dmaRX->source((volatile uint8_t&)port().POPR);
  658. _dmaRX->disableOnCompletion();
  659. _dmaRX->triggerAtHardwareEvent(hardware().rx_dma_channel);
  660. _dmaRX->attachInterrupt(hardware().dma_rxisr);
  661. _dmaRX->interruptAtCompletion();
  662. // We may be using settings chain here so lets set it up.
  663. // Now lets setup TX chain. Note if trigger TX is not set
  664. // we need to have the RX do it for us.
  665. _dmaTX->disable();
  666. _dmaTX->destination((volatile uint8_t&)port().PUSHR);
  667. _dmaTX->disableOnCompletion();
  668. if (hardware().tx_dma_channel) {
  669. _dmaTX->triggerAtHardwareEvent(hardware().tx_dma_channel);
  670. } else {
  671. // Serial.printf("SPI InitDMA tx triger by RX: %x\n", (uint32_t)_dmaRX);
  672. _dmaTX->triggerAtTransfersOf(*_dmaRX);
  673. }
  674. _dma_state = DMAState::idle; // Should be first thing set!
  675. return true;
  676. }
  677. //=========================================================================
  678. // Main Aync Transfer function
  679. //=========================================================================
  680. bool SPIClass::transfer(const void *buf, void *retbuf, size_t count, EventResponderRef event_responder) {
  681. uint8_t dma_first_byte;
  682. if (_dma_state == DMAState::notAllocated) {
  683. if (!initDMAChannels())
  684. return false;
  685. }
  686. if (_dma_state == DMAState::active)
  687. return false; // already active
  688. event_responder.clearEvent(); // Make sure it is not set yet
  689. if (count < 2) {
  690. // Use non-async version to simplify cases...
  691. transfer(buf, retbuf, count);
  692. event_responder.triggerEvent();
  693. return true;
  694. }
  695. // Now handle the cases where the count > then how many we can output in one DMA request
  696. if (count > hardware().max_dma_count) {
  697. _dma_count_remaining = count - hardware().max_dma_count;
  698. count = hardware().max_dma_count;
  699. } else {
  700. _dma_count_remaining = 0;
  701. }
  702. // Now See if caller passed in a source buffer.
  703. _dmaTX->TCD->ATTR_DST = 0; // Make sure set for 8 bit mode
  704. uint8_t *write_data = (uint8_t*) buf;
  705. if (buf) {
  706. dma_first_byte = *write_data;
  707. _dmaTX->sourceBuffer((uint8_t*)write_data+1, count-1);
  708. _dmaTX->TCD->SLAST = 0; // Finish with it pointing to next location
  709. } else {
  710. dma_first_byte = _transferWriteFill;
  711. _dmaTX->source((uint8_t&)_transferWriteFill); // maybe have setable value
  712. DMAChanneltransferCount(_dmaTX, count-1);
  713. }
  714. if (retbuf) {
  715. // On T3.5 must handle SPI1/2 differently as only one DMA channel
  716. _dmaRX->TCD->ATTR_SRC = 0; //Make sure set for 8 bit mode...
  717. _dmaRX->destinationBuffer((uint8_t*)retbuf, count);
  718. _dmaRX->TCD->DLASTSGA = 0; // At end point after our bufffer
  719. } else {
  720. // Write only mode
  721. _dmaRX->TCD->ATTR_SRC = 0; //Make sure set for 8 bit mode...
  722. _dmaRX->destination((uint8_t&)bit_bucket);
  723. DMAChanneltransferCount(_dmaRX, count);
  724. }
  725. _dma_event_responder = &event_responder;
  726. // Now try to start it?
  727. // Setup DMA main object
  728. yield();
  729. port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_CLR_TXF | SPI_MCR_PCSIS(0x1F);
  730. port().SR = 0xFF0F0000;
  731. // Lets try to output the first byte to make sure that we are in 8 bit mode...
  732. port().PUSHR = dma_first_byte | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;
  733. if (hardware().tx_dma_channel) {
  734. port().RSER = SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS | SPI_RSER_TFFF_RE | SPI_RSER_TFFF_DIRS;
  735. _dmaRX->enable();
  736. // Get the initial settings.
  737. _dmaTX->enable();
  738. } else {
  739. //T3.5 SP1 and SPI2 - TX is not triggered by SPI but by RX...
  740. port().RSER = SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS ;
  741. _dmaTX->triggerAtTransfersOf(*_dmaRX);
  742. _dmaTX->enable();
  743. _dmaRX->enable();
  744. }
  745. _dma_state = DMAState::active;
  746. return true;
  747. }
  748. //-------------------------------------------------------------------------
  749. // DMA RX ISR
  750. //-------------------------------------------------------------------------
  751. void SPIClass::dma_rxisr(void) {
  752. _dmaRX->clearInterrupt();
  753. _dmaTX->clearComplete();
  754. _dmaRX->clearComplete();
  755. uint8_t should_reenable_tx = true; // should we re-enable TX maybe not if count will be 0...
  756. if (_dma_count_remaining) {
  757. // What do I need to do to start it back up again...
  758. // We will use the BITR/CITR from RX as TX may have prefed some stuff
  759. if (_dma_count_remaining > hardware().max_dma_count) {
  760. _dma_count_remaining -= hardware().max_dma_count;
  761. } else {
  762. DMAChanneltransferCount(_dmaTX, _dma_count_remaining-1);
  763. DMAChanneltransferCount(_dmaRX, _dma_count_remaining);
  764. if (_dma_count_remaining == 1) should_reenable_tx = false;
  765. _dma_count_remaining = 0;
  766. }
  767. // In some cases we need to again start the TX manually to get it to work...
  768. if (_dmaTX->TCD->SADDR == &_transferWriteFill) {
  769. if (port().CTAR0 & SPI_CTAR_FMSZ(8)) {
  770. port().PUSHR = (_transferWriteFill | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT);
  771. } else {
  772. port().PUSHR = (_transferWriteFill | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT);
  773. }
  774. } else {
  775. if (port().CTAR0 & SPI_CTAR_FMSZ(8)) {
  776. // 16 bit mode
  777. uint16_t w = *((uint16_t*)_dmaTX->TCD->SADDR);
  778. _dmaTX->TCD->SADDR = (volatile uint8_t*)(_dmaTX->TCD->SADDR) + 2;
  779. port().PUSHR = (w | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT);
  780. } else {
  781. uint8_t w = *((uint8_t*)_dmaTX->TCD->SADDR);
  782. _dmaTX->TCD->SADDR = (volatile uint8_t*)(_dmaTX->TCD->SADDR) + 1;
  783. port().PUSHR = (w | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT);
  784. }
  785. }
  786. _dmaRX->enable();
  787. if (should_reenable_tx)
  788. _dmaTX->enable();
  789. } else {
  790. port().RSER = 0;
  791. //port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F); // clear out the queue
  792. port().SR = 0xFF0F0000;
  793. port().CTAR0 &= ~(SPI_CTAR_FMSZ(8)); // Hack restore back to 8 bits
  794. _dma_state = DMAState::completed; // set back to 1 in case our call wants to start up dma again
  795. _dma_event_responder->triggerEvent();
  796. }
  797. }
  798. #endif // SPI_HAS_TRANSFER_ASYNC
  799. /**********************************************************/
  800. /* 32 bit Teensy-LC */
  801. /**********************************************************/
  802. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL)
  803. #ifdef SPI_HAS_TRANSFER_ASYNC
  804. void _spi_dma_rxISR0(void) {SPI.dma_isr();}
  805. void _spi_dma_rxISR1(void) {SPI1.dma_isr();}
  806. #else
  807. void _spi_dma_rxISR0(void) {;}
  808. void _spi_dma_rxISR1(void) {;}
  809. #endif
  810. const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = {
  811. SIM_SCGC4, SIM_SCGC4_SPI0,
  812. 0, // BR index 0
  813. DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX, _spi_dma_rxISR0,
  814. 12, 8,
  815. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  816. 11, 7,
  817. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  818. 13, 14,
  819. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  820. 10, 2,
  821. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  822. 0x1, 0x1
  823. };
  824. SPIClass SPI((uintptr_t)&KINETISL_SPI0, (uintptr_t)&SPIClass::spi0_hardware);
  825. const SPIClass::SPI_Hardware_t SPIClass::spi1_hardware = {
  826. SIM_SCGC4, SIM_SCGC4_SPI1,
  827. 1, // BR index 1 in SPI Settings
  828. DMAMUX_SOURCE_SPI1_TX, DMAMUX_SOURCE_SPI1_RX, _spi_dma_rxISR1,
  829. 1, 5,
  830. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  831. 0, 21,
  832. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  833. 20, 255,
  834. PORT_PCR_MUX(2), 0,
  835. 6, 255,
  836. PORT_PCR_MUX(2), 0,
  837. 0x1, 0
  838. };
  839. SPIClass SPI1((uintptr_t)&KINETISL_SPI1, (uintptr_t)&SPIClass::spi1_hardware);
  840. void SPIClass::begin()
  841. {
  842. volatile uint32_t *reg;
  843. hardware().clock_gate_register |= hardware().clock_gate_mask;
  844. port().C1 = SPI_C1_SPE | SPI_C1_MSTR;
  845. port().C2 = 0;
  846. uint8_t tmp __attribute__((unused)) = port().S;
  847. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  848. *reg = hardware().mosi_mux[mosi_pin_index];
  849. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  850. *reg = hardware().miso_mux[miso_pin_index];
  851. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  852. *reg = hardware().sck_mux[sck_pin_index];
  853. }
  854. void SPIClass::end() {
  855. volatile uint32_t *reg;
  856. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  857. *reg = 0;
  858. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  859. *reg = 0;
  860. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  861. *reg = 0;
  862. port().C1 = 0;
  863. }
  864. const uint16_t SPISettings::br_div_table[30] = {
  865. 2, 4, 6, 8, 10, 12, 14, 16, 20, 24,
  866. 28, 32, 40, 48, 56, 64, 80, 96, 112, 128,
  867. 160, 192, 224, 256, 320, 384, 448, 512, 640, 768,
  868. };
  869. const uint8_t SPISettings::br_clock_table[30] = {
  870. SPI_BR_SPPR(0) | SPI_BR_SPR(0),
  871. SPI_BR_SPPR(1) | SPI_BR_SPR(0),
  872. SPI_BR_SPPR(2) | SPI_BR_SPR(0),
  873. SPI_BR_SPPR(3) | SPI_BR_SPR(0),
  874. SPI_BR_SPPR(4) | SPI_BR_SPR(0),
  875. SPI_BR_SPPR(5) | SPI_BR_SPR(0),
  876. SPI_BR_SPPR(6) | SPI_BR_SPR(0),
  877. SPI_BR_SPPR(7) | SPI_BR_SPR(0),
  878. SPI_BR_SPPR(4) | SPI_BR_SPR(1),
  879. SPI_BR_SPPR(5) | SPI_BR_SPR(1),
  880. SPI_BR_SPPR(6) | SPI_BR_SPR(1),
  881. SPI_BR_SPPR(7) | SPI_BR_SPR(1),
  882. SPI_BR_SPPR(4) | SPI_BR_SPR(2),
  883. SPI_BR_SPPR(5) | SPI_BR_SPR(2),
  884. SPI_BR_SPPR(6) | SPI_BR_SPR(2),
  885. SPI_BR_SPPR(7) | SPI_BR_SPR(2),
  886. SPI_BR_SPPR(4) | SPI_BR_SPR(3),
  887. SPI_BR_SPPR(5) | SPI_BR_SPR(3),
  888. SPI_BR_SPPR(6) | SPI_BR_SPR(3),
  889. SPI_BR_SPPR(7) | SPI_BR_SPR(3),
  890. SPI_BR_SPPR(4) | SPI_BR_SPR(4),
  891. SPI_BR_SPPR(5) | SPI_BR_SPR(4),
  892. SPI_BR_SPPR(6) | SPI_BR_SPR(4),
  893. SPI_BR_SPPR(7) | SPI_BR_SPR(4),
  894. SPI_BR_SPPR(4) | SPI_BR_SPR(5),
  895. SPI_BR_SPPR(5) | SPI_BR_SPR(5),
  896. SPI_BR_SPPR(6) | SPI_BR_SPR(5),
  897. SPI_BR_SPPR(7) | SPI_BR_SPR(5),
  898. SPI_BR_SPPR(4) | SPI_BR_SPR(6),
  899. SPI_BR_SPPR(5) | SPI_BR_SPR(6)
  900. };
  901. void SPIClass::setMOSI(uint8_t pin)
  902. {
  903. if (pin != hardware().mosi_pin[mosi_pin_index]) {
  904. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  905. if (pin == hardware().mosi_pin[i] ) {
  906. if (hardware().clock_gate_register & hardware().clock_gate_mask) {
  907. volatile uint32_t *reg;
  908. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  909. *reg = 0;
  910. reg = portConfigRegister(hardware().mosi_pin[i]);
  911. *reg = hardware().mosi_mux[i];
  912. }
  913. mosi_pin_index = i;
  914. return;
  915. }
  916. }
  917. }
  918. }
  919. void SPIClass::setMISO(uint8_t pin)
  920. {
  921. if (pin != hardware().miso_pin[miso_pin_index]) {
  922. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  923. if (pin == hardware().miso_pin[i] ) {
  924. if (hardware().clock_gate_register & hardware().clock_gate_mask) {
  925. volatile uint32_t *reg;
  926. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  927. *reg = 0;
  928. reg = portConfigRegister(hardware().miso_pin[i]);
  929. *reg = hardware().miso_mux[i];
  930. }
  931. miso_pin_index = i;
  932. return;
  933. }
  934. }
  935. }
  936. }
  937. void SPIClass::setSCK(uint8_t pin)
  938. {
  939. if (pin != hardware().sck_pin[sck_pin_index]) {
  940. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  941. if (pin == hardware().sck_pin[i] ) {
  942. if (hardware().clock_gate_register & hardware().clock_gate_mask) {
  943. volatile uint32_t *reg;
  944. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  945. *reg = 0;
  946. reg = portConfigRegister(hardware().sck_pin[i]);
  947. *reg = hardware().sck_mux[i];
  948. }
  949. sck_pin_index = i;
  950. return;
  951. }
  952. }
  953. }
  954. }
  955. bool SPIClass::pinIsChipSelect(uint8_t pin)
  956. {
  957. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  958. if (pin == hardware().cs_pin[i]) return hardware().cs_mask[i];
  959. }
  960. return 0;
  961. }
  962. bool SPIClass::pinIsMOSI(uint8_t pin)
  963. {
  964. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  965. if (pin == hardware().mosi_pin[i]) return true;
  966. }
  967. return false;
  968. }
  969. bool SPIClass::pinIsMISO(uint8_t pin)
  970. {
  971. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  972. if (pin == hardware().miso_pin[i]) return true;
  973. }
  974. return false;
  975. }
  976. bool SPIClass::pinIsSCK(uint8_t pin)
  977. {
  978. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  979. if (pin == hardware().sck_pin[i]) return true;
  980. }
  981. return false;
  982. }
  983. // setCS() is not intended for use from normal Arduino programs/sketches.
  984. uint8_t SPIClass::setCS(uint8_t pin)
  985. {
  986. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  987. if (pin == hardware().cs_pin[i]) {
  988. volatile uint32_t *reg = portConfigRegister(pin);
  989. *reg = hardware().cs_mux[i];
  990. return hardware().cs_mask[i];
  991. }
  992. }
  993. return 0;
  994. }
  995. void SPIClass::transfer(const void * buf, void * retbuf, size_t count) {
  996. if (count == 0) return;
  997. const uint8_t *p = (const uint8_t *)buf;
  998. uint8_t *pret = (uint8_t *)retbuf;
  999. uint8_t in;
  1000. while (!(port().S & SPI_S_SPTEF)) ; // wait
  1001. uint8_t out = p ? *p++ : _transferWriteFill;
  1002. port().DL = out;
  1003. while (--count > 0) {
  1004. if (p) {
  1005. out = *p++;
  1006. }
  1007. while (!(port().S & SPI_S_SPTEF)) ; // wait
  1008. __disable_irq();
  1009. port().DL = out;
  1010. while (!(port().S & SPI_S_SPRF)) ; // wait
  1011. in = port().DL;
  1012. __enable_irq();
  1013. if (pret)*pret++ = in;
  1014. }
  1015. while (!(port().S & SPI_S_SPRF)) ; // wait
  1016. in = port().DL;
  1017. if (pret)*pret = in;
  1018. }
  1019. //=============================================================================
  1020. // ASYNCH Support
  1021. //=============================================================================
  1022. //=========================================================================
  1023. // Try Transfer using DMA.
  1024. //=========================================================================
  1025. #ifdef SPI_HAS_TRANSFER_ASYNC
  1026. static uint8_t _dma_dummy_rx;
  1027. void SPIClass::dma_isr(void) {
  1028. // Serial.println("_spi_dma_rxISR");
  1029. _dmaRX->clearInterrupt();
  1030. port().C2 = 0;
  1031. uint8_t tmp __attribute__((unused)) = port().S;
  1032. _dmaTX->clearComplete();
  1033. _dmaRX->clearComplete();
  1034. _dma_state = DMAState::completed; // set back to 1 in case our call wants to start up dma again
  1035. _dma_event_responder->triggerEvent();
  1036. }
  1037. bool SPIClass::initDMAChannels() {
  1038. //Serial.println("First dma call"); Serial.flush();
  1039. _dmaTX = new DMAChannel();
  1040. if (_dmaTX == nullptr) {
  1041. return false;
  1042. }
  1043. _dmaTX->disable();
  1044. _dmaTX->destination((volatile uint8_t&)port().DL);
  1045. _dmaTX->disableOnCompletion();
  1046. _dmaTX->triggerAtHardwareEvent(hardware().tx_dma_channel);
  1047. _dmaRX = new DMAChannel();
  1048. if (_dmaRX == NULL) {
  1049. delete _dmaTX;
  1050. _dmaRX = nullptr;
  1051. return false;
  1052. }
  1053. _dmaRX->disable();
  1054. _dmaRX->source((volatile uint8_t&)port().DL);
  1055. _dmaRX->disableOnCompletion();
  1056. _dmaRX->triggerAtHardwareEvent(hardware().rx_dma_channel);
  1057. _dmaRX->attachInterrupt(hardware().dma_isr);
  1058. _dmaRX->interruptAtCompletion();
  1059. _dma_state = DMAState::idle; // Should be first thing set!
  1060. //Serial.println("end First dma call");
  1061. return true;
  1062. }
  1063. //=========================================================================
  1064. // Main Aync Transfer function
  1065. //=========================================================================
  1066. bool SPIClass::transfer(const void *buf, void *retbuf, size_t count, EventResponderRef event_responder) {
  1067. if (_dma_state == DMAState::notAllocated) {
  1068. if (!initDMAChannels()) {
  1069. return false;
  1070. }
  1071. }
  1072. if (_dma_state == DMAState::active)
  1073. return false; // already active
  1074. event_responder.clearEvent(); // Make sure it is not set yet
  1075. if (count < 2) {
  1076. // Use non-async version to simplify cases...
  1077. transfer(buf, retbuf, count);
  1078. event_responder.triggerEvent();
  1079. return true;
  1080. }
  1081. //_dmaTX->destination((volatile uint8_t&)port().DL);
  1082. //_dmaRX->source((volatile uint8_t&)port().DL);
  1083. _dmaTX->CFG->DCR = (_dmaTX->CFG->DCR & ~DMA_DCR_DSIZE(3)) | DMA_DCR_DSIZE(1);
  1084. _dmaRX->CFG->DCR = (_dmaRX->CFG->DCR & ~DMA_DCR_SSIZE(3)) | DMA_DCR_SSIZE(1); // 8 bit transfer
  1085. // Now see if the user passed in TX buffer to send.
  1086. uint8_t first_char;
  1087. if (buf) {
  1088. uint8_t *data_out = (uint8_t*)buf;
  1089. first_char = *data_out++;
  1090. _dmaTX->sourceBuffer(data_out, count-1);
  1091. } else {
  1092. first_char = (_transferWriteFill & 0xff);
  1093. _dmaTX->source((uint8_t&)_transferWriteFill); // maybe have setable value
  1094. _dmaTX->transferCount(count-1);
  1095. }
  1096. if (retbuf) {
  1097. _dmaRX->destinationBuffer((uint8_t*)retbuf, count);
  1098. } else {
  1099. _dmaRX->destination(_dma_dummy_rx); // NULL ?
  1100. _dmaRX->transferCount(count);
  1101. }
  1102. _dma_event_responder = &event_responder;
  1103. //Serial.println("Before DMA C2");
  1104. // Try pushing the first character
  1105. while (!(port().S & SPI_S_SPTEF));
  1106. port().DL = first_char;
  1107. port().C2 |= SPI_C2_TXDMAE | SPI_C2_RXDMAE;
  1108. // Now make sure SPI is enabled.
  1109. port().C1 |= SPI_C1_SPE;
  1110. _dmaRX->enable();
  1111. _dmaTX->enable();
  1112. _dma_state = DMAState::active;
  1113. return true;
  1114. }
  1115. #endif //SPI_HAS_TRANSFER_ASYNC
  1116. #endif