Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

718 lines
20KB

  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. mosi_pin_index = i;
  381. return;
  382. }
  383. }
  384. }
  385. }
  386. void SPIClass::setMISO(uint8_t pin)
  387. {
  388. if (pin != hardware().miso_pin[miso_pin_index]) {
  389. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  390. if (pin == hardware().miso_pin[i]) {
  391. miso_pin_index = i;
  392. return;
  393. }
  394. }
  395. }
  396. }
  397. void SPIClass::setSCK(uint8_t pin)
  398. {
  399. if (pin != hardware().sck_pin[sck_pin_index]) {
  400. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  401. if (pin == hardware().sck_pin[i]) {
  402. sck_pin_index = i;
  403. return;
  404. }
  405. }
  406. }
  407. }
  408. void SPIClass::transfer(void *buf, size_t count)
  409. {
  410. if (count == 0) return;
  411. uint8_t *p_write = (uint8_t *)buf;
  412. uint8_t *p_read = p_write;
  413. size_t count_read = count;
  414. bool lsbfirst = (port().CTAR0 & SPI_CTAR_LSBFE) ? true : false;
  415. uint32_t sr, full_mask;
  416. // Lets clear the reader queue
  417. port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
  418. // Now lets loop while we still have data to output
  419. if (count & 1) {
  420. if (count > 1)
  421. port().PUSHR = *p_write++ | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0);
  422. else
  423. port().PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
  424. count--;
  425. }
  426. full_mask = (hardware().queue_size-1) << 12;
  427. while (count > 0) {
  428. // Push out the next byte
  429. uint16_t w = (*p_write++) << 8;
  430. w |= *p_write++;
  431. if (lsbfirst) w = __builtin_bswap16(w);
  432. if (count == 2)
  433. port().PUSHR = w | SPI_PUSHR_CTAS(1);
  434. else
  435. port().PUSHR = w | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1);
  436. count -= 2; // how many bytes to output.
  437. // Make sure queue is not full before pushing next byte out
  438. do {
  439. sr = port().SR;
  440. if (sr & 0xF0) {
  441. uint16_t w = port().POPR; // Read any pending RX bytes in
  442. if (count_read & 1) {
  443. *p_read++ = w; // Read any pending RX bytes in
  444. count_read--;
  445. } else {
  446. if (lsbfirst) w = __builtin_bswap16(w);
  447. *p_read++ = w >> 8;
  448. *p_read++ = (w & 0xff);
  449. count_read -= 2;
  450. }
  451. }
  452. } while ((sr & (15 << 12)) > full_mask);
  453. }
  454. // now lets wait for all of the read bytes to be returned...
  455. while (count_read) {
  456. sr = port().SR;
  457. if (sr & 0xF0) {
  458. uint16_t w = port().POPR; // Read any pending RX bytes in
  459. if (count_read & 1) {
  460. *p_read++ = w; // Read any pending RX bytes in
  461. count_read--;
  462. } else {
  463. if (lsbfirst) w = __builtin_bswap16(w);
  464. *p_read++ = w >> 8;
  465. *p_read++ = (w & 0xff);
  466. count_read -= 2;
  467. }
  468. }
  469. }
  470. }
  471. /**********************************************************/
  472. /* 32 bit Teensy-LC */
  473. /**********************************************************/
  474. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL)
  475. void _spi_dma_rxISR0(void) {/*SPI.dma_rxisr();*/}
  476. const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = {
  477. SIM_SCGC4, SIM_SCGC4_SPI0,
  478. 0, // BR index 0
  479. DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX, _spi_dma_rxISR0,
  480. 12, 8,
  481. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  482. 11, 7,
  483. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  484. 13, 14,
  485. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  486. 10, 2,
  487. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  488. 0x1, 0x1
  489. };
  490. SPIClass SPI((uintptr_t)&KINETISL_SPI0, (uintptr_t)&SPIClass::spi0_hardware);
  491. void _spi_dma_rxISR1(void) {/*SPI1.dma_rxisr();*/}
  492. const SPIClass::SPI_Hardware_t SPIClass::spi1_hardware = {
  493. SIM_SCGC4, SIM_SCGC4_SPI1,
  494. 1, // BR index 1 in SPI Settings
  495. DMAMUX_SOURCE_SPI1_TX, DMAMUX_SOURCE_SPI1_RX, _spi_dma_rxISR1,
  496. 1, 5,
  497. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  498. 0, 21,
  499. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  500. 20, 255,
  501. PORT_PCR_MUX(2), 0,
  502. 6, 255,
  503. PORT_PCR_MUX(2), 0,
  504. 0x1, 0
  505. };
  506. SPIClass SPI1((uintptr_t)&KINETISL_SPI1, (uintptr_t)&SPIClass::spi1_hardware);
  507. void SPIClass::begin()
  508. {
  509. volatile uint32_t *reg;
  510. hardware().clock_gate_register |= hardware().clock_gate_mask;
  511. port().C1 = SPI_C1_SPE | SPI_C1_MSTR;
  512. port().C2 = 0;
  513. uint8_t tmp __attribute__((unused)) = port().S;
  514. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  515. *reg = hardware().mosi_mux[mosi_pin_index];
  516. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  517. *reg = hardware().miso_mux[miso_pin_index];
  518. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  519. *reg = hardware().sck_mux[sck_pin_index];
  520. }
  521. void SPIClass::end() {
  522. volatile uint32_t *reg;
  523. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  524. *reg = 0;
  525. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  526. *reg = 0;
  527. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  528. *reg = 0;
  529. port().C1 = 0;
  530. }
  531. const uint16_t SPISettings::br_div_table[30] = {
  532. 2, 4, 6, 8, 10, 12, 14, 16, 20, 24,
  533. 28, 32, 40, 48, 56, 64, 80, 96, 112, 128,
  534. 160, 192, 224, 256, 320, 384, 448, 512, 640, 768,
  535. };
  536. const uint8_t SPISettings::br_clock_table[30] = {
  537. SPI_BR_SPPR(0) | SPI_BR_SPR(0),
  538. SPI_BR_SPPR(1) | SPI_BR_SPR(0),
  539. SPI_BR_SPPR(2) | SPI_BR_SPR(0),
  540. SPI_BR_SPPR(3) | SPI_BR_SPR(0),
  541. SPI_BR_SPPR(4) | SPI_BR_SPR(0),
  542. SPI_BR_SPPR(5) | SPI_BR_SPR(0),
  543. SPI_BR_SPPR(6) | SPI_BR_SPR(0),
  544. SPI_BR_SPPR(7) | SPI_BR_SPR(0),
  545. SPI_BR_SPPR(4) | SPI_BR_SPR(1),
  546. SPI_BR_SPPR(5) | SPI_BR_SPR(1),
  547. SPI_BR_SPPR(6) | SPI_BR_SPR(1),
  548. SPI_BR_SPPR(7) | SPI_BR_SPR(1),
  549. SPI_BR_SPPR(4) | SPI_BR_SPR(2),
  550. SPI_BR_SPPR(5) | SPI_BR_SPR(2),
  551. SPI_BR_SPPR(6) | SPI_BR_SPR(2),
  552. SPI_BR_SPPR(7) | SPI_BR_SPR(2),
  553. SPI_BR_SPPR(4) | SPI_BR_SPR(3),
  554. SPI_BR_SPPR(5) | SPI_BR_SPR(3),
  555. SPI_BR_SPPR(6) | SPI_BR_SPR(3),
  556. SPI_BR_SPPR(7) | SPI_BR_SPR(3),
  557. SPI_BR_SPPR(4) | SPI_BR_SPR(4),
  558. SPI_BR_SPPR(5) | SPI_BR_SPR(4),
  559. SPI_BR_SPPR(6) | SPI_BR_SPR(4),
  560. SPI_BR_SPPR(7) | SPI_BR_SPR(4),
  561. SPI_BR_SPPR(4) | SPI_BR_SPR(5),
  562. SPI_BR_SPPR(5) | SPI_BR_SPR(5),
  563. SPI_BR_SPPR(6) | SPI_BR_SPR(5),
  564. SPI_BR_SPPR(7) | SPI_BR_SPR(5),
  565. SPI_BR_SPPR(4) | SPI_BR_SPR(6),
  566. SPI_BR_SPPR(5) | SPI_BR_SPR(6)
  567. };
  568. void SPIClass::setMOSI(uint8_t pin)
  569. {
  570. if (pin != hardware().mosi_pin[mosi_pin_index]) {
  571. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  572. if (pin == hardware().mosi_pin[i] ) {
  573. mosi_pin_index = i;
  574. return;
  575. }
  576. }
  577. }
  578. }
  579. void SPIClass::setMISO(uint8_t pin)
  580. {
  581. if (pin != hardware().miso_pin[miso_pin_index]) {
  582. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  583. if (pin == hardware().miso_pin[i] ) {
  584. miso_pin_index = i;
  585. return;
  586. }
  587. }
  588. }
  589. }
  590. void SPIClass::setSCK(uint8_t pin)
  591. {
  592. if (pin != hardware().sck_pin[sck_pin_index]) {
  593. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  594. if (pin == hardware().sck_pin[i] ) {
  595. sck_pin_index = i;
  596. return;
  597. }
  598. }
  599. }
  600. }
  601. bool SPIClass::pinIsChipSelect(uint8_t pin)
  602. {
  603. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  604. if (pin == hardware().cs_pin[i]) return hardware().cs_mask[i];
  605. }
  606. return 0;
  607. }
  608. bool SPIClass::pinIsMOSI(uint8_t pin)
  609. {
  610. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  611. if (pin == hardware().mosi_pin[i]) return true;
  612. }
  613. return false;
  614. }
  615. bool SPIClass::pinIsMISO(uint8_t pin)
  616. {
  617. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  618. if (pin == hardware().miso_pin[i]) return true;
  619. }
  620. return false;
  621. }
  622. bool SPIClass::pinIsSCK(uint8_t pin)
  623. {
  624. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  625. if (pin == hardware().sck_pin[i]) return true;
  626. }
  627. return false;
  628. }
  629. // setCS() is not intended for use from normal Arduino programs/sketches.
  630. uint8_t SPIClass::setCS(uint8_t pin)
  631. {
  632. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  633. if (pin == hardware().cs_pin[i]) {
  634. volatile uint32_t *reg = portConfigRegister(pin);
  635. *reg = hardware().cs_mux[i];
  636. return hardware().cs_mask[i];
  637. }
  638. }
  639. return 0;
  640. }
  641. #endif