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.

760 lines
22KB

  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. void SPIClass::begin()
  24. {
  25. // Set SS to high so a connected chip will be "deselected" by default
  26. digitalWrite(SS, HIGH);
  27. // When the SS pin is set as OUTPUT, it can be used as
  28. // a general purpose output port (it doesn't influence
  29. // SPI operations).
  30. pinMode(SS, OUTPUT);
  31. // Warning: if the SS pin ever becomes a LOW INPUT then SPI
  32. // automatically switches to Slave, so the data direction of
  33. // the SS pin MUST be kept as OUTPUT.
  34. SPCR |= _BV(MSTR);
  35. SPCR |= _BV(SPE);
  36. // Set direction register for SCK and MOSI pin.
  37. // MISO pin automatically overrides to INPUT.
  38. // By doing this AFTER enabling SPI, we avoid accidentally
  39. // clocking in a single bit since the lines go directly
  40. // from "input" to SPI control.
  41. // http://code.google.com/p/arduino/issues/detail?id=888
  42. pinMode(SCK, OUTPUT);
  43. pinMode(MOSI, OUTPUT);
  44. }
  45. void SPIClass::end() {
  46. SPCR &= ~_BV(SPE);
  47. }
  48. // mapping of interrupt numbers to bits within SPI_AVR_EIMSK
  49. #if defined(__AVR_ATmega32U4__)
  50. #define SPI_INT0_MASK (1<<INT0)
  51. #define SPI_INT1_MASK (1<<INT1)
  52. #define SPI_INT2_MASK (1<<INT2)
  53. #define SPI_INT3_MASK (1<<INT3)
  54. #define SPI_INT4_MASK (1<<INT6)
  55. #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
  56. #define SPI_INT0_MASK (1<<INT0)
  57. #define SPI_INT1_MASK (1<<INT1)
  58. #define SPI_INT2_MASK (1<<INT2)
  59. #define SPI_INT3_MASK (1<<INT3)
  60. #define SPI_INT4_MASK (1<<INT4)
  61. #define SPI_INT5_MASK (1<<INT5)
  62. #define SPI_INT6_MASK (1<<INT6)
  63. #define SPI_INT7_MASK (1<<INT7)
  64. #elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
  65. #define SPI_INT0_MASK (1<<INT4)
  66. #define SPI_INT1_MASK (1<<INT5)
  67. #define SPI_INT2_MASK (1<<INT0)
  68. #define SPI_INT3_MASK (1<<INT1)
  69. #define SPI_INT4_MASK (1<<INT2)
  70. #define SPI_INT5_MASK (1<<INT3)
  71. #define SPI_INT6_MASK (1<<INT6)
  72. #define SPI_INT7_MASK (1<<INT7)
  73. #else
  74. #ifdef INT0
  75. #define SPI_INT0_MASK (1<<INT0)
  76. #endif
  77. #ifdef INT1
  78. #define SPI_INT1_MASK (1<<INT1)
  79. #endif
  80. #ifdef INT2
  81. #define SPI_INT2_MASK (1<<INT2)
  82. #endif
  83. #endif
  84. void SPIClass::usingInterrupt(uint8_t interruptNumber)
  85. {
  86. uint8_t stmp, mask;
  87. if (interruptMode > 1) return;
  88. stmp = SREG;
  89. noInterrupts();
  90. switch (interruptNumber) {
  91. #ifdef SPI_INT0_MASK
  92. case 0: mask = SPI_INT0_MASK; break;
  93. #endif
  94. #ifdef SPI_INT1_MASK
  95. case 1: mask = SPI_INT1_MASK; break;
  96. #endif
  97. #ifdef SPI_INT2_MASK
  98. case 2: mask = SPI_INT2_MASK; break;
  99. #endif
  100. #ifdef SPI_INT3_MASK
  101. case 3: mask = SPI_INT3_MASK; break;
  102. #endif
  103. #ifdef SPI_INT4_MASK
  104. case 4: mask = SPI_INT4_MASK; break;
  105. #endif
  106. #ifdef SPI_INT5_MASK
  107. case 5: mask = SPI_INT5_MASK; break;
  108. #endif
  109. #ifdef SPI_INT6_MASK
  110. case 6: mask = SPI_INT6_MASK; break;
  111. #endif
  112. #ifdef SPI_INT7_MASK
  113. case 7: mask = SPI_INT7_MASK; break;
  114. #endif
  115. default:
  116. interruptMode = 2;
  117. SREG = stmp;
  118. return;
  119. }
  120. interruptMode = 1;
  121. interruptMask |= mask;
  122. SREG = stmp;
  123. }
  124. /**********************************************************/
  125. /* 32 bit Teensy 3.x */
  126. /**********************************************************/
  127. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK)
  128. #if defined(__MK20DX128__) || defined(__MK20DX256__)
  129. void _spi_dma_rxISR0(void) {/*SPI.dma_rxisr();*/}
  130. const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = {
  131. SIM_SCGC6, SIM_SCGC6_SPI0, 4, IRQ_SPI0,
  132. 32767, DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX,
  133. _spi_dma_rxISR0,
  134. 12, 8,
  135. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  136. 11, 7,
  137. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  138. 13, 14,
  139. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  140. 10, 2, 9, 6, 20, 23, 21, 22, 15,
  141. 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),
  142. 0x1, 0x1, 0x2, 0x2, 0x4, 0x4, 0x8, 0x8, 0x10
  143. };
  144. SPIClass SPI((uintptr_t)&KINETISK_SPI0, (uintptr_t)&SPIClass::spi0_hardware);
  145. #elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
  146. void _spi_dma_rxISR0(void) {/*SPI.dma_rxisr();*/}
  147. void _spi_dma_rxISR1(void) {/*SPI1.dma_rxisr();*/}
  148. void _spi_dma_rxISR2(void) {/*SPI2.dma_rxisr();*/}
  149. const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = {
  150. SIM_SCGC6, SIM_SCGC6_SPI0, 4, IRQ_SPI0,
  151. 32767, DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX,
  152. _spi_dma_rxISR0,
  153. 12, 8, 39, 255,
  154. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0,
  155. 11, 7, 28, 255,
  156. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0,
  157. 13, 14, 27,
  158. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  159. 10, 2, 9, 6, 20, 23, 21, 22, 15, 26, 45,
  160. 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),
  161. 0x1, 0x1, 0x2, 0x2, 0x4, 0x4, 0x8, 0x8, 0x10, 0x1, 0x20
  162. };
  163. const SPIClass::SPI_Hardware_t SPIClass::spi1_hardware = {
  164. SIM_SCGC6, SIM_SCGC6_SPI1, 1, IRQ_SPI1,
  165. #if defined(__MK66FX1M0__)
  166. 32767, DMAMUX_SOURCE_SPI1_TX, DMAMUX_SOURCE_SPI1_RX,
  167. #else
  168. // T3.5 does not have good DMA support on 1 and 2
  169. 511, 0, DMAMUX_SOURCE_SPI1,
  170. #endif
  171. _spi_dma_rxISR1,
  172. 1, 5, 61, 59,
  173. PORT_PCR_MUX(2), PORT_PCR_MUX(7), PORT_PCR_MUX(2), PORT_PCR_MUX(7),
  174. 0, 21, 61, 59,
  175. PORT_PCR_MUX(2), PORT_PCR_MUX(7), PORT_PCR_MUX(7), PORT_PCR_MUX(2),
  176. 32, 20, 60,
  177. PORT_PCR_MUX(2), PORT_PCR_MUX(7), PORT_PCR_MUX(2),
  178. 6, 31, 58, 62, 63, 255, 255, 255, 255, 255, 255,
  179. 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,
  180. 0x1, 0x1, 0x2, 0x1, 0x4, 0, 0, 0, 0, 0, 0
  181. };
  182. const SPIClass::SPI_Hardware_t SPIClass::spi2_hardware = {
  183. SIM_SCGC3, SIM_SCGC3_SPI2, 1, IRQ_SPI2,
  184. #if defined(__MK66FX1M0__)
  185. 32767, DMAMUX_SOURCE_SPI2_TX, DMAMUX_SOURCE_SPI2_RX,
  186. #else
  187. // T3.5 does not have good DMA support on 1 and 2
  188. 511, 0, DMAMUX_SOURCE_SPI2,
  189. #endif
  190. _spi_dma_rxISR2,
  191. 45, 51, 255, 255,
  192. PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0, 0,
  193. 44, 52, 255, 255,
  194. PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0, 0,
  195. 46, 53, 255,
  196. PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0,
  197. 43, 54, 55, 255, 255, 255, 255, 255, 255, 255, 255,
  198. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0, 0, 0, 0, 0, 0, 0, 0,
  199. 0x1, 0x2, 0x1, 0, 0, 0, 0, 0, 0, 0, 0
  200. };
  201. SPIClass SPI((uintptr_t)&KINETISK_SPI0, (uintptr_t)&SPIClass::spi0_hardware);
  202. SPIClass SPI1((uintptr_t)&KINETISK_SPI1, (uintptr_t)&SPIClass::spi1_hardware);
  203. SPIClass SPI2((uintptr_t)&KINETISK_SPI2, (uintptr_t)&SPIClass::spi2_hardware);
  204. #endif
  205. void SPIClass::begin()
  206. {
  207. volatile uint32_t *reg;
  208. hardware().clock_gate_register |= hardware().clock_gate_mask;
  209. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  210. port().CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  211. port().CTAR1 = SPI_CTAR_FMSZ(15) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  212. port().MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
  213. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  214. *reg = hardware().mosi_mux[mosi_pin_index];
  215. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  216. *reg= hardware().miso_mux[miso_pin_index];
  217. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  218. *reg = hardware().sck_mux[sck_pin_index];
  219. }
  220. void SPIClass::end()
  221. {
  222. volatile uint32_t *reg;
  223. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  224. *reg = 0;
  225. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  226. *reg = 0;
  227. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  228. *reg = 0;
  229. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  230. }
  231. void SPIClass::usingInterrupt(IRQ_NUMBER_t interruptName)
  232. {
  233. uint32_t n = (uint32_t)interruptName;
  234. if (n >= NVIC_NUM_INTERRUPTS) return;
  235. //Serial.print("usingInterrupt ");
  236. //Serial.println(n);
  237. interruptMasksUsed |= (1 << (n >> 5));
  238. interruptMask[n >> 5] |= (1 << (n & 0x1F));
  239. //Serial.printf("interruptMasksUsed = %d\n", interruptMasksUsed);
  240. //Serial.printf("interruptMask[0] = %08X\n", interruptMask[0]);
  241. //Serial.printf("interruptMask[1] = %08X\n", interruptMask[1]);
  242. //Serial.printf("interruptMask[2] = %08X\n", interruptMask[2]);
  243. }
  244. void SPIClass::notUsingInterrupt(IRQ_NUMBER_t interruptName)
  245. {
  246. uint32_t n = (uint32_t)interruptName;
  247. if (n >= NVIC_NUM_INTERRUPTS) return;
  248. interruptMask[n >> 5] &= ~(1 << (n & 0x1F));
  249. if (interruptMask[n >> 5] == 0) {
  250. interruptMasksUsed &= ~(1 << (n >> 5));
  251. }
  252. }
  253. const uint16_t SPISettings::ctar_div_table[23] = {
  254. 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40,
  255. 56, 64, 96, 128, 192, 256, 384, 512, 640, 768
  256. };
  257. const uint32_t SPISettings::ctar_clock_table[23] = {
  258. SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  259. SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  260. SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  261. SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  262. SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  263. SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1),
  264. SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  265. SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1),
  266. SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  267. SPI_CTAR_PBR(2) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(0),
  268. SPI_CTAR_PBR(1) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  269. SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(3),
  270. SPI_CTAR_PBR(2) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  271. SPI_CTAR_PBR(3) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  272. SPI_CTAR_PBR(0) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4),
  273. SPI_CTAR_PBR(1) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4),
  274. SPI_CTAR_PBR(0) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5),
  275. SPI_CTAR_PBR(1) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5),
  276. SPI_CTAR_PBR(0) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  277. SPI_CTAR_PBR(1) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  278. SPI_CTAR_PBR(0) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7),
  279. SPI_CTAR_PBR(2) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  280. SPI_CTAR_PBR(1) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7)
  281. };
  282. void SPIClass::updateCTAR(uint32_t ctar)
  283. {
  284. if (port().CTAR0 != ctar) {
  285. uint32_t mcr = port().MCR;
  286. if (mcr & SPI_MCR_MDIS) {
  287. port().CTAR0 = ctar;
  288. port().CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  289. } else {
  290. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  291. port().CTAR0 = ctar;
  292. port().CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  293. port().MCR = mcr;
  294. }
  295. }
  296. }
  297. void SPIClass::setBitOrder(uint8_t bitOrder)
  298. {
  299. hardware().clock_gate_register |= hardware().clock_gate_mask;
  300. uint32_t ctar = port().CTAR0;
  301. if (bitOrder == LSBFIRST) {
  302. ctar |= SPI_CTAR_LSBFE;
  303. } else {
  304. ctar &= ~SPI_CTAR_LSBFE;
  305. }
  306. updateCTAR(ctar);
  307. }
  308. void SPIClass::setDataMode(uint8_t dataMode)
  309. {
  310. hardware().clock_gate_register |= hardware().clock_gate_mask;
  311. //uint32_t ctar = port().CTAR0;
  312. // TODO: implement with native code
  313. //SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
  314. }
  315. void SPIClass::setClockDivider_noInline(uint32_t clk)
  316. {
  317. hardware().clock_gate_register |= hardware().clock_gate_mask;
  318. uint32_t ctar = port().CTAR0;
  319. ctar &= (SPI_CTAR_CPOL | SPI_CTAR_CPHA | SPI_CTAR_LSBFE);
  320. if (ctar & SPI_CTAR_CPHA) {
  321. clk = (clk & 0xFFFF0FFF) | ((clk & 0xF000) >> 4);
  322. }
  323. ctar |= clk;
  324. updateCTAR(ctar);
  325. }
  326. uint8_t SPIClass::pinIsChipSelect(uint8_t pin)
  327. {
  328. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  329. if (pin == hardware().cs_pin[i]) return hardware().cs_mask[i];
  330. }
  331. return 0;
  332. }
  333. bool SPIClass::pinIsChipSelect(uint8_t pin1, uint8_t pin2)
  334. {
  335. uint8_t pin1_mask, pin2_mask;
  336. if ((pin1_mask = (uint8_t)pinIsChipSelect(pin1)) == 0) return false;
  337. if ((pin2_mask = (uint8_t)pinIsChipSelect(pin2)) == 0) return false;
  338. //Serial.printf("pinIsChipSelect %d %d %x %x\n\r", pin1, pin2, pin1_mask, pin2_mask);
  339. if ((pin1_mask & pin2_mask) != 0) return false;
  340. return true;
  341. }
  342. bool SPIClass::pinIsMOSI(uint8_t pin)
  343. {
  344. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  345. if (pin == hardware().mosi_pin[i]) return true;
  346. }
  347. return false;
  348. }
  349. bool SPIClass::pinIsMISO(uint8_t pin)
  350. {
  351. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  352. if (pin == hardware().miso_pin[i]) return true;
  353. }
  354. return false;
  355. }
  356. bool SPIClass::pinIsSCK(uint8_t pin)
  357. {
  358. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  359. if (pin == hardware().sck_pin[i]) return true;
  360. }
  361. return false;
  362. }
  363. // setCS() is not intended for use from normal Arduino programs/sketches.
  364. uint8_t SPIClass::setCS(uint8_t pin)
  365. {
  366. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  367. if (pin == hardware().cs_pin[i]) {
  368. volatile uint32_t *reg = portConfigRegister(pin);
  369. *reg = hardware().cs_mux[i];
  370. return hardware().cs_mask[i];
  371. }
  372. }
  373. return 0;
  374. }
  375. void SPIClass::setMOSI(uint8_t pin)
  376. {
  377. if (pin != hardware().mosi_pin[mosi_pin_index]) {
  378. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  379. if (pin == hardware().mosi_pin[i]) {
  380. if (hardware().clock_gate_register & hardware().clock_gate_mask) {
  381. volatile uint32_t *reg;
  382. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  383. *reg = 0;
  384. reg = portConfigRegister(hardware().mosi_pin[i]);
  385. *reg = hardware().mosi_mux[i];
  386. }
  387. mosi_pin_index = i;
  388. return;
  389. }
  390. }
  391. }
  392. }
  393. void SPIClass::setMISO(uint8_t pin)
  394. {
  395. if (pin != hardware().miso_pin[miso_pin_index]) {
  396. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  397. if (pin == hardware().miso_pin[i]) {
  398. if (hardware().clock_gate_register & hardware().clock_gate_mask) {
  399. volatile uint32_t *reg;
  400. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  401. *reg = 0;
  402. reg = portConfigRegister(hardware().miso_pin[i]);
  403. *reg = hardware().miso_mux[i];
  404. }
  405. miso_pin_index = i;
  406. return;
  407. }
  408. }
  409. }
  410. }
  411. void SPIClass::setSCK(uint8_t pin)
  412. {
  413. if (pin != hardware().sck_pin[sck_pin_index]) {
  414. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  415. if (pin == hardware().sck_pin[i]) {
  416. if (hardware().clock_gate_register & hardware().clock_gate_mask) {
  417. volatile uint32_t *reg;
  418. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  419. *reg = 0;
  420. reg = portConfigRegister(hardware().sck_pin[i]);
  421. *reg = hardware().sck_mux[i];
  422. }
  423. sck_pin_index = i;
  424. return;
  425. }
  426. }
  427. }
  428. }
  429. void SPIClass::transfer(void *buf, size_t count)
  430. {
  431. if (count == 0) return;
  432. uint8_t *p_write = (uint8_t *)buf;
  433. uint8_t *p_read = p_write;
  434. size_t count_read = count;
  435. bool lsbfirst = (port().CTAR0 & SPI_CTAR_LSBFE) ? true : false;
  436. uint32_t sr, full_mask;
  437. // Lets clear the reader queue
  438. port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
  439. // Now lets loop while we still have data to output
  440. if (count & 1) {
  441. if (count > 1)
  442. port().PUSHR = *p_write++ | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0);
  443. else
  444. port().PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
  445. count--;
  446. }
  447. full_mask = (hardware().queue_size-1) << 12;
  448. while (count > 0) {
  449. // Push out the next byte
  450. uint16_t w = (*p_write++) << 8;
  451. w |= *p_write++;
  452. if (lsbfirst) w = __builtin_bswap16(w);
  453. if (count == 2)
  454. port().PUSHR = w | SPI_PUSHR_CTAS(1);
  455. else
  456. port().PUSHR = w | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1);
  457. count -= 2; // how many bytes to output.
  458. // Make sure queue is not full before pushing next byte out
  459. do {
  460. sr = port().SR;
  461. if (sr & 0xF0) {
  462. uint16_t w = port().POPR; // Read any pending RX bytes in
  463. if (count_read & 1) {
  464. *p_read++ = w; // Read any pending RX bytes in
  465. count_read--;
  466. } else {
  467. if (lsbfirst) w = __builtin_bswap16(w);
  468. *p_read++ = w >> 8;
  469. *p_read++ = (w & 0xff);
  470. count_read -= 2;
  471. }
  472. }
  473. } while ((sr & (15 << 12)) > full_mask);
  474. }
  475. // now lets wait for all of the read bytes to be returned...
  476. while (count_read) {
  477. sr = port().SR;
  478. if (sr & 0xF0) {
  479. uint16_t w = port().POPR; // Read any pending RX bytes in
  480. if (count_read & 1) {
  481. *p_read++ = w; // Read any pending RX bytes in
  482. count_read--;
  483. } else {
  484. if (lsbfirst) w = __builtin_bswap16(w);
  485. *p_read++ = w >> 8;
  486. *p_read++ = (w & 0xff);
  487. count_read -= 2;
  488. }
  489. }
  490. }
  491. }
  492. /**********************************************************/
  493. /* 32 bit Teensy-LC */
  494. /**********************************************************/
  495. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL)
  496. void _spi_dma_rxISR0(void) {/*SPI.dma_rxisr();*/}
  497. const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = {
  498. SIM_SCGC4, SIM_SCGC4_SPI0,
  499. 0, // BR index 0
  500. DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX, _spi_dma_rxISR0,
  501. 12, 8,
  502. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  503. 11, 7,
  504. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  505. 13, 14,
  506. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  507. 10, 2,
  508. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  509. 0x1, 0x1
  510. };
  511. SPIClass SPI((uintptr_t)&KINETISL_SPI0, (uintptr_t)&SPIClass::spi0_hardware);
  512. void _spi_dma_rxISR1(void) {/*SPI1.dma_rxisr();*/}
  513. const SPIClass::SPI_Hardware_t SPIClass::spi1_hardware = {
  514. SIM_SCGC4, SIM_SCGC4_SPI1,
  515. 1, // BR index 1 in SPI Settings
  516. DMAMUX_SOURCE_SPI1_TX, DMAMUX_SOURCE_SPI1_RX, _spi_dma_rxISR1,
  517. 1, 5,
  518. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  519. 0, 21,
  520. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  521. 20, 255,
  522. PORT_PCR_MUX(2), 0,
  523. 6, 255,
  524. PORT_PCR_MUX(2), 0,
  525. 0x1, 0
  526. };
  527. SPIClass SPI1((uintptr_t)&KINETISL_SPI1, (uintptr_t)&SPIClass::spi1_hardware);
  528. void SPIClass::begin()
  529. {
  530. volatile uint32_t *reg;
  531. hardware().clock_gate_register |= hardware().clock_gate_mask;
  532. port().C1 = SPI_C1_SPE | SPI_C1_MSTR;
  533. port().C2 = 0;
  534. uint8_t tmp __attribute__((unused)) = port().S;
  535. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  536. *reg = hardware().mosi_mux[mosi_pin_index];
  537. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  538. *reg = hardware().miso_mux[miso_pin_index];
  539. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  540. *reg = hardware().sck_mux[sck_pin_index];
  541. }
  542. void SPIClass::end() {
  543. volatile uint32_t *reg;
  544. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  545. *reg = 0;
  546. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  547. *reg = 0;
  548. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  549. *reg = 0;
  550. port().C1 = 0;
  551. }
  552. const uint16_t SPISettings::br_div_table[30] = {
  553. 2, 4, 6, 8, 10, 12, 14, 16, 20, 24,
  554. 28, 32, 40, 48, 56, 64, 80, 96, 112, 128,
  555. 160, 192, 224, 256, 320, 384, 448, 512, 640, 768,
  556. };
  557. const uint8_t SPISettings::br_clock_table[30] = {
  558. SPI_BR_SPPR(0) | SPI_BR_SPR(0),
  559. SPI_BR_SPPR(1) | SPI_BR_SPR(0),
  560. SPI_BR_SPPR(2) | SPI_BR_SPR(0),
  561. SPI_BR_SPPR(3) | SPI_BR_SPR(0),
  562. SPI_BR_SPPR(4) | SPI_BR_SPR(0),
  563. SPI_BR_SPPR(5) | SPI_BR_SPR(0),
  564. SPI_BR_SPPR(6) | SPI_BR_SPR(0),
  565. SPI_BR_SPPR(7) | SPI_BR_SPR(0),
  566. SPI_BR_SPPR(4) | SPI_BR_SPR(1),
  567. SPI_BR_SPPR(5) | SPI_BR_SPR(1),
  568. SPI_BR_SPPR(6) | SPI_BR_SPR(1),
  569. SPI_BR_SPPR(7) | SPI_BR_SPR(1),
  570. SPI_BR_SPPR(4) | SPI_BR_SPR(2),
  571. SPI_BR_SPPR(5) | SPI_BR_SPR(2),
  572. SPI_BR_SPPR(6) | SPI_BR_SPR(2),
  573. SPI_BR_SPPR(7) | SPI_BR_SPR(2),
  574. SPI_BR_SPPR(4) | SPI_BR_SPR(3),
  575. SPI_BR_SPPR(5) | SPI_BR_SPR(3),
  576. SPI_BR_SPPR(6) | SPI_BR_SPR(3),
  577. SPI_BR_SPPR(7) | SPI_BR_SPR(3),
  578. SPI_BR_SPPR(4) | SPI_BR_SPR(4),
  579. SPI_BR_SPPR(5) | SPI_BR_SPR(4),
  580. SPI_BR_SPPR(6) | SPI_BR_SPR(4),
  581. SPI_BR_SPPR(7) | SPI_BR_SPR(4),
  582. SPI_BR_SPPR(4) | SPI_BR_SPR(5),
  583. SPI_BR_SPPR(5) | SPI_BR_SPR(5),
  584. SPI_BR_SPPR(6) | SPI_BR_SPR(5),
  585. SPI_BR_SPPR(7) | SPI_BR_SPR(5),
  586. SPI_BR_SPPR(4) | SPI_BR_SPR(6),
  587. SPI_BR_SPPR(5) | SPI_BR_SPR(6)
  588. };
  589. void SPIClass::setMOSI(uint8_t pin)
  590. {
  591. if (pin != hardware().mosi_pin[mosi_pin_index]) {
  592. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  593. if (pin == hardware().mosi_pin[i] ) {
  594. if (hardware().clock_gate_register & hardware().clock_gate_mask) {
  595. volatile uint32_t *reg;
  596. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  597. *reg = 0;
  598. reg = portConfigRegister(hardware().mosi_pin[i]);
  599. *reg = hardware().mosi_mux[i];
  600. }
  601. mosi_pin_index = i;
  602. return;
  603. }
  604. }
  605. }
  606. }
  607. void SPIClass::setMISO(uint8_t pin)
  608. {
  609. if (pin != hardware().miso_pin[miso_pin_index]) {
  610. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  611. if (pin == hardware().miso_pin[i] ) {
  612. if (hardware().clock_gate_register & hardware().clock_gate_mask) {
  613. volatile uint32_t *reg;
  614. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  615. *reg = 0;
  616. reg = portConfigRegister(hardware().miso_pin[i]);
  617. *reg = hardware().miso_mux[i];
  618. }
  619. miso_pin_index = i;
  620. return;
  621. }
  622. }
  623. }
  624. }
  625. void SPIClass::setSCK(uint8_t pin)
  626. {
  627. if (pin != hardware().sck_pin[sck_pin_index]) {
  628. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  629. if (pin == hardware().sck_pin[i] ) {
  630. if (hardware().clock_gate_register & hardware().clock_gate_mask) {
  631. volatile uint32_t *reg;
  632. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  633. *reg = 0;
  634. reg = portConfigRegister(hardware().sck_pin[i]);
  635. *reg = hardware().sck_mux[i];
  636. }
  637. sck_pin_index = i;
  638. return;
  639. }
  640. }
  641. }
  642. }
  643. bool SPIClass::pinIsChipSelect(uint8_t pin)
  644. {
  645. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  646. if (pin == hardware().cs_pin[i]) return hardware().cs_mask[i];
  647. }
  648. return 0;
  649. }
  650. bool SPIClass::pinIsMOSI(uint8_t pin)
  651. {
  652. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  653. if (pin == hardware().mosi_pin[i]) return true;
  654. }
  655. return false;
  656. }
  657. bool SPIClass::pinIsMISO(uint8_t pin)
  658. {
  659. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  660. if (pin == hardware().miso_pin[i]) return true;
  661. }
  662. return false;
  663. }
  664. bool SPIClass::pinIsSCK(uint8_t pin)
  665. {
  666. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  667. if (pin == hardware().sck_pin[i]) return true;
  668. }
  669. return false;
  670. }
  671. // setCS() is not intended for use from normal Arduino programs/sketches.
  672. uint8_t SPIClass::setCS(uint8_t pin)
  673. {
  674. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  675. if (pin == hardware().cs_pin[i]) {
  676. volatile uint32_t *reg = portConfigRegister(pin);
  677. *reg = hardware().cs_mux[i];
  678. return hardware().cs_mask[i];
  679. }
  680. }
  681. return 0;
  682. }
  683. #endif