選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

SPI.h 45KB

10年前
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
  1. /*
  2. * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
  3. * Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
  4. * Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
  5. * SPI Master library for arduino.
  6. *
  7. * This file is free software; you can redistribute it and/or modify
  8. * it under the terms of either the GNU General Public License version 2
  9. * or the GNU Lesser General Public License version 2.1, both as
  10. * published by the Free Software Foundation.
  11. */
  12. #ifndef _SPI_H_INCLUDED
  13. #define _SPI_H_INCLUDED
  14. #include <Arduino.h>
  15. #if defined(__arm__) && defined(TEENSYDUINO)
  16. #if defined(__has_include) && __has_include(<EventResponder.h>)
  17. // SPI_HAS_TRANSFER_ASYNC - Defined to say that the SPI supports an ASYNC version
  18. // of the SPI_HAS_TRANSFER_BUF
  19. #define SPI_HAS_TRANSFER_ASYNC 1
  20. #include <DMAChannel.h>
  21. #include <EventResponder.h>
  22. #endif
  23. #endif
  24. // SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(),
  25. // usingInterrupt(), and SPISetting(clock, bitOrder, dataMode)
  26. #define SPI_HAS_TRANSACTION 1
  27. // Uncomment this line to add detection of mismatched begin/end transactions.
  28. // A mismatch occurs if other libraries fail to use SPI.endTransaction() for
  29. // each SPI.beginTransaction(). Connect a LED to this pin. The LED will turn
  30. // on if any mismatch is ever detected.
  31. //#define SPI_TRANSACTION_MISMATCH_LED 5
  32. // SPI_HAS_TRANSFER_BUF - is defined to signify that this library supports
  33. // a version of transfer which allows you to pass in both TX and RX buffer
  34. // pointers, either of which could be NULL
  35. #define SPI_HAS_TRANSFER_BUF 1
  36. #ifndef LSBFIRST
  37. #define LSBFIRST 0
  38. #endif
  39. #ifndef MSBFIRST
  40. #define MSBFIRST 1
  41. #endif
  42. #define SPI_MODE0 0x00
  43. #define SPI_MODE1 0x04
  44. #define SPI_MODE2 0x08
  45. #define SPI_MODE3 0x0C
  46. #define SPI_CLOCK_DIV4 0x00
  47. #define SPI_CLOCK_DIV16 0x01
  48. #define SPI_CLOCK_DIV64 0x02
  49. #define SPI_CLOCK_DIV128 0x03
  50. #define SPI_CLOCK_DIV2 0x04
  51. #define SPI_CLOCK_DIV8 0x05
  52. #define SPI_CLOCK_DIV32 0x06
  53. #define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
  54. #define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
  55. #define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
  56. /**********************************************************/
  57. /* 8 bit AVR-based boards */
  58. /**********************************************************/
  59. #if defined(__AVR__)
  60. // define SPI_AVR_EIMSK for AVR boards with external interrupt pins
  61. #if defined(EIMSK)
  62. #define SPI_AVR_EIMSK EIMSK
  63. #elif defined(GICR)
  64. #define SPI_AVR_EIMSK GICR
  65. #elif defined(GIMSK)
  66. #define SPI_AVR_EIMSK GIMSK
  67. #endif
  68. class SPISettings {
  69. public:
  70. SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  71. if (__builtin_constant_p(clock)) {
  72. init_AlwaysInline(clock, bitOrder, dataMode);
  73. } else {
  74. init_MightInline(clock, bitOrder, dataMode);
  75. }
  76. }
  77. SPISettings() {
  78. init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
  79. }
  80. private:
  81. void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  82. init_AlwaysInline(clock, bitOrder, dataMode);
  83. }
  84. void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
  85. __attribute__((__always_inline__)) {
  86. // Clock settings are defined as follows. Note that this shows SPI2X
  87. // inverted, so the bits form increasing numbers. Also note that
  88. // fosc/64 appears twice
  89. // SPR1 SPR0 ~SPI2X Freq
  90. // 0 0 0 fosc/2
  91. // 0 0 1 fosc/4
  92. // 0 1 0 fosc/8
  93. // 0 1 1 fosc/16
  94. // 1 0 0 fosc/32
  95. // 1 0 1 fosc/64
  96. // 1 1 0 fosc/64
  97. // 1 1 1 fosc/128
  98. // We find the fastest clock that is less than or equal to the
  99. // given clock rate. The clock divider that results in clock_setting
  100. // is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the
  101. // slowest (128 == 2 ^^ 7, so clock_div = 6).
  102. uint8_t clockDiv;
  103. // When the clock is known at compiletime, use this if-then-else
  104. // cascade, which the compiler knows how to completely optimize
  105. // away. When clock is not known, use a loop instead, which generates
  106. // shorter code.
  107. if (__builtin_constant_p(clock)) {
  108. if (clock >= F_CPU / 2) {
  109. clockDiv = 0;
  110. } else if (clock >= F_CPU / 4) {
  111. clockDiv = 1;
  112. } else if (clock >= F_CPU / 8) {
  113. clockDiv = 2;
  114. } else if (clock >= F_CPU / 16) {
  115. clockDiv = 3;
  116. } else if (clock >= F_CPU / 32) {
  117. clockDiv = 4;
  118. } else if (clock >= F_CPU / 64) {
  119. clockDiv = 5;
  120. } else {
  121. clockDiv = 6;
  122. }
  123. } else {
  124. uint32_t clockSetting = F_CPU / 2;
  125. clockDiv = 0;
  126. while (clockDiv < 6 && clock < clockSetting) {
  127. clockSetting /= 2;
  128. clockDiv++;
  129. }
  130. }
  131. // Compensate for the duplicate fosc/64
  132. if (clockDiv == 6)
  133. clockDiv = 7;
  134. // Invert the SPI2X bit
  135. clockDiv ^= 0x1;
  136. // Pack into the SPISettings class
  137. spcr = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) |
  138. (dataMode & SPI_MODE_MASK) | ((clockDiv >> 1) & SPI_CLOCK_MASK);
  139. spsr = clockDiv & SPI_2XCLOCK_MASK;
  140. }
  141. uint8_t spcr;
  142. uint8_t spsr;
  143. friend class SPIClass;
  144. };
  145. class SPIClass { // AVR
  146. public:
  147. // Initialize the SPI library
  148. static void begin();
  149. // If SPI is used from within an interrupt, this function registers
  150. // that interrupt with the SPI library, so beginTransaction() can
  151. // prevent conflicts. The input interruptNumber is the number used
  152. // with attachInterrupt. If SPI is used from a different interrupt
  153. // (eg, a timer), interruptNumber should be 255.
  154. static void usingInterrupt(uint8_t interruptNumber);
  155. // Before using SPI.transfer() or asserting chip select pins,
  156. // this function is used to gain exclusive access to the SPI bus
  157. // and configure the correct settings.
  158. inline static void beginTransaction(SPISettings settings) {
  159. if (interruptMode > 0) {
  160. #ifdef SPI_AVR_EIMSK
  161. if (interruptMode == 1) {
  162. interruptSave = SPI_AVR_EIMSK;
  163. SPI_AVR_EIMSK &= ~interruptMask;
  164. } else
  165. #endif
  166. {
  167. uint8_t tmp = SREG;
  168. cli();
  169. interruptSave = tmp;
  170. }
  171. }
  172. #ifdef SPI_TRANSACTION_MISMATCH_LED
  173. if (inTransactionFlag) {
  174. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  175. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  176. }
  177. inTransactionFlag = 1;
  178. #endif
  179. SPCR = settings.spcr;
  180. SPSR = settings.spsr;
  181. }
  182. // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
  183. inline static uint8_t transfer(uint8_t data) {
  184. SPDR = data;
  185. asm volatile("nop");
  186. while (!(SPSR & _BV(SPIF))) ; // wait
  187. return SPDR;
  188. }
  189. inline static uint16_t transfer16(uint16_t data) {
  190. union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out;
  191. in.val = data;
  192. if ((SPCR & _BV(DORD))) {
  193. SPDR = in.lsb;
  194. asm volatile("nop");
  195. while (!(SPSR & _BV(SPIF))) ;
  196. out.lsb = SPDR;
  197. SPDR = in.msb;
  198. asm volatile("nop");
  199. while (!(SPSR & _BV(SPIF))) ;
  200. out.msb = SPDR;
  201. } else {
  202. SPDR = in.msb;
  203. asm volatile("nop");
  204. while (!(SPSR & _BV(SPIF))) ;
  205. out.msb = SPDR;
  206. SPDR = in.lsb;
  207. asm volatile("nop");
  208. while (!(SPSR & _BV(SPIF))) ;
  209. out.lsb = SPDR;
  210. }
  211. return out.val;
  212. }
  213. inline static void transfer(void *buf, size_t count) {
  214. if (count == 0) return;
  215. uint8_t *p = (uint8_t *)buf;
  216. SPDR = *p;
  217. while (--count > 0) {
  218. uint8_t out = *(p + 1);
  219. while (!(SPSR & _BV(SPIF))) ;
  220. uint8_t in = SPDR;
  221. SPDR = out;
  222. *p++ = in;
  223. }
  224. while (!(SPSR & _BV(SPIF))) ;
  225. *p = SPDR;
  226. }
  227. static void setTransferWriteFill(uint8_t ch ) {_transferWriteFill = ch;}
  228. static void transfer(const void * buf, void * retbuf, uint32_t count);
  229. // After performing a group of transfers and releasing the chip select
  230. // signal, this function allows others to access the SPI bus
  231. inline static void endTransaction(void) {
  232. #ifdef SPI_TRANSACTION_MISMATCH_LED
  233. if (!inTransactionFlag) {
  234. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  235. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  236. }
  237. inTransactionFlag = 0;
  238. #endif
  239. if (interruptMode > 0) {
  240. #ifdef SPI_AVR_EIMSK
  241. if (interruptMode == 1) {
  242. SPI_AVR_EIMSK = interruptSave;
  243. } else
  244. #endif
  245. {
  246. SREG = interruptSave;
  247. }
  248. }
  249. }
  250. // Disable the SPI bus
  251. static void end();
  252. // This function is deprecated. New applications should use
  253. // beginTransaction() to configure SPI settings.
  254. inline static void setBitOrder(uint8_t bitOrder) {
  255. if (bitOrder == LSBFIRST) SPCR |= _BV(DORD);
  256. else SPCR &= ~(_BV(DORD));
  257. }
  258. // This function is deprecated. New applications should use
  259. // beginTransaction() to configure SPI settings.
  260. inline static void setDataMode(uint8_t dataMode) {
  261. SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
  262. }
  263. // This function is deprecated. New applications should use
  264. // beginTransaction() to configure SPI settings.
  265. inline static void setClockDivider(uint8_t clockDiv) {
  266. SPCR = (SPCR & ~SPI_CLOCK_MASK) | (clockDiv & SPI_CLOCK_MASK);
  267. SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((clockDiv >> 2) & SPI_2XCLOCK_MASK);
  268. }
  269. // These undocumented functions should not be used. SPI.transfer()
  270. // polls the hardware flag which is automatically cleared as the
  271. // AVR responds to SPI's interrupt
  272. inline static void attachInterrupt() { SPCR |= _BV(SPIE); }
  273. inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); }
  274. private:
  275. static uint8_t interruptMode; // 0=none, 1=mask, 2=global
  276. static uint8_t interruptMask; // which interrupts to mask
  277. static uint8_t interruptSave; // temp storage, to restore state
  278. #ifdef SPI_TRANSACTION_MISMATCH_LED
  279. static uint8_t inTransactionFlag;
  280. #endif
  281. static uint8_t _transferWriteFill;
  282. };
  283. /**********************************************************/
  284. /* 32 bit Teensy 3.x */
  285. /**********************************************************/
  286. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK)
  287. #define SPI_HAS_NOTUSINGINTERRUPT 1
  288. class SPISettings {
  289. public:
  290. SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  291. if (__builtin_constant_p(clock)) {
  292. init_AlwaysInline(clock, bitOrder, dataMode);
  293. } else {
  294. init_MightInline(clock, bitOrder, dataMode);
  295. }
  296. }
  297. SPISettings() {
  298. init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
  299. }
  300. private:
  301. void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  302. init_AlwaysInline(clock, bitOrder, dataMode);
  303. }
  304. void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
  305. __attribute__((__always_inline__)) {
  306. uint32_t t, c = SPI_CTAR_FMSZ(7);
  307. if (bitOrder == LSBFIRST) c |= SPI_CTAR_LSBFE;
  308. if (__builtin_constant_p(clock)) {
  309. if (clock >= F_BUS / 2) {
  310. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR
  311. | SPI_CTAR_CSSCK(0);
  312. } else if (clock >= F_BUS / 3) {
  313. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR
  314. | SPI_CTAR_CSSCK(0);
  315. } else if (clock >= F_BUS / 4) {
  316. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0);
  317. } else if (clock >= F_BUS / 5) {
  318. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR
  319. | SPI_CTAR_CSSCK(0);
  320. } else if (clock >= F_BUS / 6) {
  321. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0);
  322. } else if (clock >= F_BUS / 8) {
  323. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  324. } else if (clock >= F_BUS / 10) {
  325. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0);
  326. } else if (clock >= F_BUS / 12) {
  327. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  328. } else if (clock >= F_BUS / 16) {
  329. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
  330. } else if (clock >= F_BUS / 20) {
  331. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(0);
  332. } else if (clock >= F_BUS / 24) {
  333. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
  334. } else if (clock >= F_BUS / 32) {
  335. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(3);
  336. } else if (clock >= F_BUS / 40) {
  337. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
  338. } else if (clock >= F_BUS / 56) {
  339. t = SPI_CTAR_PBR(3) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
  340. } else if (clock >= F_BUS / 64) {
  341. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4);
  342. } else if (clock >= F_BUS / 96) {
  343. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4);
  344. } else if (clock >= F_BUS / 128) {
  345. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5);
  346. } else if (clock >= F_BUS / 192) {
  347. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5);
  348. } else if (clock >= F_BUS / 256) {
  349. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6);
  350. } else if (clock >= F_BUS / 384) {
  351. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6);
  352. } else if (clock >= F_BUS / 512) {
  353. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7);
  354. } else if (clock >= F_BUS / 640) {
  355. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6);
  356. } else { /* F_BUS / 768 */
  357. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7);
  358. }
  359. } else {
  360. for (uint32_t i=0; i<23; i++) {
  361. t = ctar_clock_table[i];
  362. if (clock >= F_BUS / ctar_div_table[i]) break;
  363. }
  364. }
  365. if (dataMode & 0x08) {
  366. c |= SPI_CTAR_CPOL;
  367. }
  368. if (dataMode & 0x04) {
  369. c |= SPI_CTAR_CPHA;
  370. t = (t & 0xFFFF0FFF) | ((t & 0xF000) >> 4);
  371. }
  372. ctar = c | t;
  373. }
  374. static const uint16_t ctar_div_table[23];
  375. static const uint32_t ctar_clock_table[23];
  376. uint32_t ctar;
  377. friend class SPIClass;
  378. };
  379. class SPIClass { // Teensy 3.x
  380. public:
  381. #if defined(__MK20DX128__) || defined(__MK20DX256__)
  382. static const uint8_t CNT_MISO_PINS = 2;
  383. static const uint8_t CNT_MOSI_PINS = 2;
  384. static const uint8_t CNT_SCK_PINS = 2;
  385. static const uint8_t CNT_CS_PINS = 9;
  386. #elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
  387. static const uint8_t CNT_MISO_PINS = 4;
  388. static const uint8_t CNT_MOSI_PINS = 4;
  389. static const uint8_t CNT_SCK_PINS = 3;
  390. static const uint8_t CNT_CS_PINS = 11;
  391. #endif
  392. typedef struct {
  393. volatile uint32_t &clock_gate_register;
  394. uint32_t clock_gate_mask;
  395. uint8_t queue_size;
  396. uint8_t spi_irq;
  397. uint32_t max_dma_count;
  398. uint8_t tx_dma_channel;
  399. uint8_t rx_dma_channel;
  400. void (*dma_rxisr)();
  401. uint8_t miso_pin[CNT_MISO_PINS];
  402. uint32_t miso_mux[CNT_MISO_PINS];
  403. uint8_t mosi_pin[CNT_MOSI_PINS];
  404. uint32_t mosi_mux[CNT_MOSI_PINS];
  405. uint8_t sck_pin[CNT_SCK_PINS];
  406. uint32_t sck_mux[CNT_SCK_PINS];
  407. uint8_t cs_pin[CNT_CS_PINS];
  408. uint32_t cs_mux[CNT_CS_PINS];
  409. uint8_t cs_mask[CNT_CS_PINS];
  410. } SPI_Hardware_t;
  411. static const SPI_Hardware_t spi0_hardware;
  412. static const SPI_Hardware_t spi1_hardware;
  413. static const SPI_Hardware_t spi2_hardware;
  414. enum DMAState { notAllocated, idle, active, completed};
  415. public:
  416. constexpr SPIClass(uintptr_t myport, uintptr_t myhardware)
  417. : port_addr(myport), hardware_addr(myhardware) {
  418. }
  419. // Initialize the SPI library
  420. void begin();
  421. // If SPI is to used from within an interrupt, this function registers
  422. // that interrupt with the SPI library, so beginTransaction() can
  423. // prevent conflicts. The input interruptNumber is the number used
  424. // with attachInterrupt. If SPI is used from a different interrupt
  425. // (eg, a timer), interruptNumber should be 255.
  426. void usingInterrupt(uint8_t n) {
  427. if (n == 3 || n == 4 || n == 24 || n == 33) {
  428. usingInterrupt(IRQ_PORTA);
  429. } else if (n == 0 || n == 1 || (n >= 16 && n <= 19) || n == 25 || n == 32) {
  430. usingInterrupt(IRQ_PORTB);
  431. } else if ((n >= 9 && n <= 13) || n == 15 || n == 22 || n == 23
  432. || (n >= 27 && n <= 30)) {
  433. usingInterrupt(IRQ_PORTC);
  434. } else if (n == 2 || (n >= 5 && n <= 8) || n == 14 || n == 20 || n == 21) {
  435. usingInterrupt(IRQ_PORTD);
  436. } else if (n == 26 || n == 31) {
  437. usingInterrupt(IRQ_PORTE);
  438. }
  439. }
  440. void usingInterrupt(IRQ_NUMBER_t interruptName);
  441. void notUsingInterrupt(IRQ_NUMBER_t interruptName);
  442. // Before using SPI.transfer() or asserting chip select pins,
  443. // this function is used to gain exclusive access to the SPI bus
  444. // and configure the correct settings.
  445. void beginTransaction(SPISettings settings) {
  446. if (interruptMasksUsed) {
  447. __disable_irq();
  448. if (interruptMasksUsed & 0x01) {
  449. interruptSave[0] = NVIC_ICER0 & interruptMask[0];
  450. NVIC_ICER0 = interruptSave[0];
  451. }
  452. #if NVIC_NUM_INTERRUPTS > 32
  453. if (interruptMasksUsed & 0x02) {
  454. interruptSave[1] = NVIC_ICER1 & interruptMask[1];
  455. NVIC_ICER1 = interruptSave[1];
  456. }
  457. #endif
  458. #if NVIC_NUM_INTERRUPTS > 64 && defined(NVIC_ISER2)
  459. if (interruptMasksUsed & 0x04) {
  460. interruptSave[2] = NVIC_ICER2 & interruptMask[2];
  461. NVIC_ICER2 = interruptSave[2];
  462. }
  463. #endif
  464. #if NVIC_NUM_INTERRUPTS > 96 && defined(NVIC_ISER3)
  465. if (interruptMasksUsed & 0x08) {
  466. interruptSave[3] = NVIC_ICER3 & interruptMask[3];
  467. NVIC_ICER3 = interruptSave[3];
  468. }
  469. #endif
  470. __enable_irq();
  471. }
  472. #ifdef SPI_TRANSACTION_MISMATCH_LED
  473. if (inTransactionFlag) {
  474. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  475. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  476. }
  477. inTransactionFlag = 1;
  478. #endif
  479. if (port().CTAR0 != settings.ctar) {
  480. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x3F);
  481. port().CTAR0 = settings.ctar;
  482. port().CTAR1 = settings.ctar| SPI_CTAR_FMSZ(8);
  483. port().MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x3F);
  484. }
  485. }
  486. // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
  487. uint8_t transfer(uint8_t data) {
  488. port().SR = SPI_SR_TCF;
  489. port().PUSHR = data;
  490. while (!(port().SR & SPI_SR_TCF)) ; // wait
  491. return port().POPR;
  492. }
  493. uint16_t transfer16(uint16_t data) {
  494. port().SR = SPI_SR_TCF;
  495. port().PUSHR = data | SPI_PUSHR_CTAS(1);
  496. while (!(port().SR & SPI_SR_TCF)) ; // wait
  497. return port().POPR;
  498. }
  499. void inline transfer(void *buf, size_t count) {transfer(buf, buf, count);}
  500. void setTransferWriteFill(uint8_t ch ) {_transferWriteFill = ch;}
  501. void transfer(const void * buf, void * retbuf, size_t count);
  502. // Asynch support (DMA )
  503. #ifdef SPI_HAS_TRANSFER_ASYNC
  504. bool transfer(const void *txBuffer, void *rxBuffer, size_t count, EventResponderRef event_responder);
  505. friend void _spi_dma_rxISR0(void);
  506. friend void _spi_dma_rxISR1(void);
  507. friend void _spi_dma_rxISR2(void);
  508. inline void dma_rxisr(void);
  509. #endif
  510. // After performing a group of transfers and releasing the chip select
  511. // signal, this function allows others to access the SPI bus
  512. void endTransaction(void) {
  513. #ifdef SPI_TRANSACTION_MISMATCH_LED
  514. if (!inTransactionFlag) {
  515. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  516. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  517. }
  518. inTransactionFlag = 0;
  519. #endif
  520. if (interruptMasksUsed) {
  521. if (interruptMasksUsed & 0x01) {
  522. NVIC_ISER0 = interruptSave[0];
  523. }
  524. #if NVIC_NUM_INTERRUPTS > 32
  525. if (interruptMasksUsed & 0x02) {
  526. NVIC_ISER1 = interruptSave[1];
  527. }
  528. #endif
  529. #if NVIC_NUM_INTERRUPTS > 64 && defined(NVIC_ISER2)
  530. if (interruptMasksUsed & 0x04) {
  531. NVIC_ISER2 = interruptSave[2];
  532. }
  533. #endif
  534. #if NVIC_NUM_INTERRUPTS > 96 && defined(NVIC_ISER3)
  535. if (interruptMasksUsed & 0x08) {
  536. NVIC_ISER3 = interruptSave[3];
  537. }
  538. #endif
  539. }
  540. }
  541. // Disable the SPI bus
  542. void end();
  543. // This function is deprecated. New applications should use
  544. // beginTransaction() to configure SPI settings.
  545. void setBitOrder(uint8_t bitOrder);
  546. // This function is deprecated. New applications should use
  547. // beginTransaction() to configure SPI settings.
  548. void setDataMode(uint8_t dataMode);
  549. // This function is deprecated. New applications should use
  550. // beginTransaction() to configure SPI settings.
  551. void setClockDivider(uint8_t clockDiv) {
  552. if (clockDiv == SPI_CLOCK_DIV2) {
  553. setClockDivider_noInline(SPISettings(12000000, MSBFIRST, SPI_MODE0).ctar);
  554. } else if (clockDiv == SPI_CLOCK_DIV4) {
  555. setClockDivider_noInline(SPISettings(4000000, MSBFIRST, SPI_MODE0).ctar);
  556. } else if (clockDiv == SPI_CLOCK_DIV8) {
  557. setClockDivider_noInline(SPISettings(2000000, MSBFIRST, SPI_MODE0).ctar);
  558. } else if (clockDiv == SPI_CLOCK_DIV16) {
  559. setClockDivider_noInline(SPISettings(1000000, MSBFIRST, SPI_MODE0).ctar);
  560. } else if (clockDiv == SPI_CLOCK_DIV32) {
  561. setClockDivider_noInline(SPISettings(500000, MSBFIRST, SPI_MODE0).ctar);
  562. } else if (clockDiv == SPI_CLOCK_DIV64) {
  563. setClockDivider_noInline(SPISettings(250000, MSBFIRST, SPI_MODE0).ctar);
  564. } else { /* clockDiv == SPI_CLOCK_DIV128 */
  565. setClockDivider_noInline(SPISettings(125000, MSBFIRST, SPI_MODE0).ctar);
  566. }
  567. }
  568. void setClockDivider_noInline(uint32_t clk);
  569. // These undocumented functions should not be used. SPI.transfer()
  570. // polls the hardware flag which is automatically cleared as the
  571. // AVR responds to SPI's interrupt
  572. void attachInterrupt() { }
  573. void detachInterrupt() { }
  574. // Teensy 3.x can use alternate pins for these 3 SPI signals.
  575. void setMOSI(uint8_t pin);
  576. void setMISO(uint8_t pin);
  577. void setSCK(uint8_t pin);
  578. // return true if "pin" has special chip select capability
  579. uint8_t pinIsChipSelect(uint8_t pin);
  580. bool pinIsMOSI(uint8_t pin);
  581. bool pinIsMISO(uint8_t pin);
  582. bool pinIsSCK(uint8_t pin);
  583. // return true if both pin1 and pin2 have independent chip select capability
  584. bool pinIsChipSelect(uint8_t pin1, uint8_t pin2);
  585. // configure a pin for chip select and return its SPI_MCR_PCSIS bitmask
  586. // setCS() is a special function, not intended for use from normal Arduino
  587. // programs/sketches. See the ILI3941_t3 library for an example.
  588. uint8_t setCS(uint8_t pin);
  589. private:
  590. KINETISK_SPI_t & port() { return *(KINETISK_SPI_t *)port_addr; }
  591. const SPI_Hardware_t & hardware() { return *(const SPI_Hardware_t *)hardware_addr; }
  592. void updateCTAR(uint32_t ctar);
  593. uintptr_t port_addr;
  594. uintptr_t hardware_addr;
  595. uint8_t miso_pin_index = 0;
  596. uint8_t mosi_pin_index = 0;
  597. uint8_t sck_pin_index = 0;
  598. uint8_t interruptMasksUsed = 0;
  599. uint32_t interruptMask[(NVIC_NUM_INTERRUPTS+31)/32] = {};
  600. uint32_t interruptSave[(NVIC_NUM_INTERRUPTS+31)/32] = {};
  601. #ifdef SPI_TRANSACTION_MISMATCH_LED
  602. uint8_t inTransactionFlag = 0;
  603. #endif
  604. uint8_t _transferWriteFill = 0;
  605. // DMA Support
  606. #ifdef SPI_HAS_TRANSFER_ASYNC
  607. bool initDMAChannels();
  608. DMAState _dma_state = DMAState::notAllocated;
  609. uint32_t _dma_count_remaining = 0; // How many bytes left to output after current DMA completes
  610. DMAChannel *_dmaTX = nullptr;
  611. DMAChannel *_dmaRX = nullptr;
  612. EventResponder *_dma_event_responder = nullptr;
  613. #endif
  614. };
  615. /**********************************************************/
  616. /* 32 bit Teensy-LC */
  617. /**********************************************************/
  618. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL)
  619. class SPISettings {
  620. public:
  621. SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  622. if (__builtin_constant_p(clock)) {
  623. init_AlwaysInline(clock, bitOrder, dataMode);
  624. } else {
  625. init_MightInline(clock, bitOrder, dataMode);
  626. }
  627. }
  628. SPISettings() {
  629. init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
  630. }
  631. private:
  632. void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  633. init_AlwaysInline(clock, bitOrder, dataMode);
  634. }
  635. void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
  636. __attribute__((__always_inline__)) {
  637. uint8_t c = SPI_C1_MSTR | SPI_C1_SPE;
  638. if (dataMode & 0x04) c |= SPI_C1_CPHA;
  639. if (dataMode & 0x08) c |= SPI_C1_CPOL;
  640. if (bitOrder == LSBFIRST) c |= SPI_C1_LSBFE;
  641. c1 = c;
  642. if (__builtin_constant_p(clock)) {
  643. if (clock >= F_BUS / 2) { c = SPI_BR_SPPR(0) | SPI_BR_SPR(0);
  644. } else if (clock >= F_BUS / 4) { c = SPI_BR_SPPR(1) | SPI_BR_SPR(0);
  645. } else if (clock >= F_BUS / 6) { c = SPI_BR_SPPR(2) | SPI_BR_SPR(0);
  646. } else if (clock >= F_BUS / 8) { c = SPI_BR_SPPR(3) | SPI_BR_SPR(0);
  647. } else if (clock >= F_BUS / 10) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(0);
  648. } else if (clock >= F_BUS / 12) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(0);
  649. } else if (clock >= F_BUS / 14) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(0);
  650. } else if (clock >= F_BUS / 16) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(0);
  651. } else if (clock >= F_BUS / 20) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(1);
  652. } else if (clock >= F_BUS / 24) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(1);
  653. } else if (clock >= F_BUS / 28) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(1);
  654. } else if (clock >= F_BUS / 32) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(1);
  655. } else if (clock >= F_BUS / 40) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(2);
  656. } else if (clock >= F_BUS / 48) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(2);
  657. } else if (clock >= F_BUS / 56) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(2);
  658. } else if (clock >= F_BUS / 64) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(2);
  659. } else if (clock >= F_BUS / 80) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(3);
  660. } else if (clock >= F_BUS / 96) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(3);
  661. } else if (clock >= F_BUS / 112) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(3);
  662. } else if (clock >= F_BUS / 128) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(3);
  663. } else if (clock >= F_BUS / 160) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(4);
  664. } else if (clock >= F_BUS / 192) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(4);
  665. } else if (clock >= F_BUS / 224) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(4);
  666. } else if (clock >= F_BUS / 256) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(4);
  667. } else if (clock >= F_BUS / 320) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(5);
  668. } else if (clock >= F_BUS / 384) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(5);
  669. } else if (clock >= F_BUS / 448) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(5);
  670. } else if (clock >= F_BUS / 512) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(5);
  671. } else if (clock >= F_BUS / 640) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(6);
  672. } else /* F_BUS / 768 */ { c = SPI_BR_SPPR(5) | SPI_BR_SPR(6);
  673. }
  674. } else {
  675. for (uint32_t i=0; i<30; i++) {
  676. c = br_clock_table[i];
  677. if (clock >= F_BUS / br_div_table[i]) break;
  678. }
  679. }
  680. br[0] = c;
  681. if (__builtin_constant_p(clock)) {
  682. if (clock >= (F_PLL/2) / 2) { c = SPI_BR_SPPR(0) | SPI_BR_SPR(0);
  683. } else if (clock >= (F_PLL/2) / 4) { c = SPI_BR_SPPR(1) | SPI_BR_SPR(0);
  684. } else if (clock >= (F_PLL/2) / 6) { c = SPI_BR_SPPR(2) | SPI_BR_SPR(0);
  685. } else if (clock >= (F_PLL/2) / 8) { c = SPI_BR_SPPR(3) | SPI_BR_SPR(0);
  686. } else if (clock >= (F_PLL/2) / 10) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(0);
  687. } else if (clock >= (F_PLL/2) / 12) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(0);
  688. } else if (clock >= (F_PLL/2) / 14) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(0);
  689. } else if (clock >= (F_PLL/2) / 16) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(0);
  690. } else if (clock >= (F_PLL/2) / 20) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(1);
  691. } else if (clock >= (F_PLL/2) / 24) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(1);
  692. } else if (clock >= (F_PLL/2) / 28) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(1);
  693. } else if (clock >= (F_PLL/2) / 32) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(1);
  694. } else if (clock >= (F_PLL/2) / 40) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(2);
  695. } else if (clock >= (F_PLL/2) / 48) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(2);
  696. } else if (clock >= (F_PLL/2) / 56) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(2);
  697. } else if (clock >= (F_PLL/2) / 64) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(2);
  698. } else if (clock >= (F_PLL/2) / 80) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(3);
  699. } else if (clock >= (F_PLL/2) / 96) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(3);
  700. } else if (clock >= (F_PLL/2) / 112) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(3);
  701. } else if (clock >= (F_PLL/2) / 128) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(3);
  702. } else if (clock >= (F_PLL/2) / 160) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(4);
  703. } else if (clock >= (F_PLL/2) / 192) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(4);
  704. } else if (clock >= (F_PLL/2) / 224) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(4);
  705. } else if (clock >= (F_PLL/2) / 256) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(4);
  706. } else if (clock >= (F_PLL/2) / 320) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(5);
  707. } else if (clock >= (F_PLL/2) / 384) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(5);
  708. } else if (clock >= (F_PLL/2) / 448) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(5);
  709. } else if (clock >= (F_PLL/2) / 512) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(5);
  710. } else if (clock >= (F_PLL/2) / 640) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(6);
  711. } else /* (F_PLL/2) / 768 */ { c = SPI_BR_SPPR(5) | SPI_BR_SPR(6);
  712. }
  713. } else {
  714. for (uint32_t i=0; i<30; i++) {
  715. c = br_clock_table[i];
  716. if (clock >= (F_PLL/2) / br_div_table[i]) break;
  717. }
  718. }
  719. br[1] = c;
  720. }
  721. static const uint8_t br_clock_table[30];
  722. static const uint16_t br_div_table[30];
  723. uint8_t c1, br[2];
  724. friend class SPIClass;
  725. };
  726. class SPIClass { // Teensy-LC
  727. public:
  728. static const uint8_t CNT_MISO_PINS = 2;
  729. static const uint8_t CNT_MMOSI_PINS = 2;
  730. static const uint8_t CNT_SCK_PINS = 2;
  731. static const uint8_t CNT_CS_PINS = 2;
  732. typedef struct {
  733. volatile uint32_t &clock_gate_register;
  734. uint32_t clock_gate_mask;
  735. uint8_t br_index;
  736. uint8_t tx_dma_channel;
  737. uint8_t rx_dma_channel;
  738. void (*dma_isr)();
  739. uint8_t miso_pin[CNT_MISO_PINS];
  740. uint32_t miso_mux[CNT_MISO_PINS];
  741. uint8_t mosi_pin[CNT_MMOSI_PINS];
  742. uint32_t mosi_mux[CNT_MMOSI_PINS];
  743. uint8_t sck_pin[CNT_SCK_PINS];
  744. uint32_t sck_mux[CNT_SCK_PINS];
  745. uint8_t cs_pin[CNT_CS_PINS];
  746. uint32_t cs_mux[CNT_CS_PINS];
  747. uint8_t cs_mask[CNT_CS_PINS];
  748. } SPI_Hardware_t;
  749. static const SPI_Hardware_t spi0_hardware;
  750. static const SPI_Hardware_t spi1_hardware;
  751. enum DMAState { notAllocated, idle, active, completed};
  752. public:
  753. constexpr SPIClass(uintptr_t myport, uintptr_t myhardware)
  754. : port_addr(myport), hardware_addr(myhardware) {
  755. }
  756. // Initialize the SPI library
  757. void begin();
  758. // If SPI is to used from within an interrupt, this function registers
  759. // that interrupt with the SPI library, so beginTransaction() can
  760. // prevent conflicts. The input interruptNumber is the number used
  761. // with attachInterrupt. If SPI is used from a different interrupt
  762. // (eg, a timer), interruptNumber should be 255.
  763. void usingInterrupt(uint8_t n) {
  764. if (n == 3 || n == 4) {
  765. usingInterrupt(IRQ_PORTA);
  766. } else if ((n >= 2 && n <= 15) || (n >= 20 && n <= 23)) {
  767. usingInterrupt(IRQ_PORTCD);
  768. }
  769. }
  770. void usingInterrupt(IRQ_NUMBER_t interruptName) {
  771. uint32_t n = (uint32_t)interruptName;
  772. if (n < NVIC_NUM_INTERRUPTS) interruptMask |= (1 << n);
  773. }
  774. void notUsingInterrupt(IRQ_NUMBER_t interruptName) {
  775. uint32_t n = (uint32_t)interruptName;
  776. if (n < NVIC_NUM_INTERRUPTS) interruptMask &= ~(1 << n);
  777. }
  778. // Before using SPI.transfer() or asserting chip select pins,
  779. // this function is used to gain exclusive access to the SPI bus
  780. // and configure the correct settings.
  781. void beginTransaction(SPISettings settings) {
  782. if (interruptMask) {
  783. __disable_irq();
  784. interruptSave = NVIC_ICER0 & interruptMask;
  785. NVIC_ICER0 = interruptSave;
  786. __enable_irq();
  787. }
  788. #ifdef SPI_TRANSACTION_MISMATCH_LED
  789. if (inTransactionFlag) {
  790. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  791. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  792. }
  793. inTransactionFlag = 1;
  794. #endif
  795. port().C1 = settings.c1;
  796. port().BR = settings.br[hardware().br_index];
  797. }
  798. // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
  799. uint8_t transfer(uint8_t data) {
  800. port().DL = data;
  801. while (!(port().S & SPI_S_SPRF)) ; // wait
  802. return port().DL;
  803. }
  804. uint16_t transfer16(uint16_t data) {
  805. port().C2 = SPI_C2_SPIMODE;
  806. port().S;
  807. port().DL = data;
  808. port().DH = data >> 8;
  809. while (!(port().S & SPI_S_SPRF)) ; // wait
  810. uint16_t r = port().DL | (port().DH << 8);
  811. port().C2 = 0;
  812. port().S;
  813. return r;
  814. }
  815. void transfer(void *buf, size_t count) {
  816. if (count == 0) return;
  817. uint8_t *p = (uint8_t *)buf;
  818. while (!(port().S & SPI_S_SPTEF)) ; // wait
  819. port().DL = *p;
  820. while (--count > 0) {
  821. uint8_t out = *(p + 1);
  822. while (!(port().S & SPI_S_SPTEF)) ; // wait
  823. __disable_irq();
  824. port().DL = out;
  825. while (!(port().S & SPI_S_SPRF)) ; // wait
  826. uint8_t in = port().DL;
  827. __enable_irq();
  828. *p++ = in;
  829. }
  830. while (!(port().S & SPI_S_SPRF)) ; // wait
  831. *p = port().DL;
  832. }
  833. void setTransferWriteFill(uint8_t ch ) {_transferWriteFill = ch;}
  834. void transfer(const void * buf, void * retbuf, size_t count);
  835. // Asynch support (DMA )
  836. #ifdef SPI_HAS_TRANSFER_ASYNC
  837. bool transfer(const void *txBuffer, void *rxBuffer, size_t count, EventResponderRef event_responder);
  838. friend void _spi_dma_rxISR0(void);
  839. friend void _spi_dma_rxISR1(void);
  840. inline void dma_isr(void);
  841. #endif
  842. // After performing a group of transfers and releasing the chip select
  843. // signal, this function allows others to access the SPI bus
  844. void endTransaction(void) {
  845. #ifdef SPI_TRANSACTION_MISMATCH_LED
  846. if (!inTransactionFlag) {
  847. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  848. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  849. }
  850. inTransactionFlag = 0;
  851. #endif
  852. if (interruptMask) {
  853. NVIC_ISER0 = interruptSave;
  854. }
  855. }
  856. // Disable the SPI bus
  857. void end();
  858. // This function is deprecated. New applications should use
  859. // beginTransaction() to configure SPI settings.
  860. void setBitOrder(uint8_t bitOrder) {
  861. uint8_t c = port().C1 | SPI_C1_SPE;
  862. if (bitOrder == LSBFIRST) c |= SPI_C1_LSBFE;
  863. else c &= ~SPI_C1_LSBFE;
  864. port().C1 = c;
  865. }
  866. // This function is deprecated. New applications should use
  867. // beginTransaction() to configure SPI settings.
  868. void setDataMode(uint8_t dataMode) {
  869. uint8_t c = port().C1 | SPI_C1_SPE;
  870. if (dataMode & 0x04) c |= SPI_C1_CPHA;
  871. else c &= ~SPI_C1_CPHA;
  872. if (dataMode & 0x08) c |= SPI_C1_CPOL;
  873. else c &= ~SPI_C1_CPOL;
  874. port().C1 = c;
  875. }
  876. // This function is deprecated. New applications should use
  877. // beginTransaction() to configure SPI settings.
  878. void setClockDivider(uint8_t clockDiv) {
  879. unsigned int i = hardware().br_index;
  880. if (clockDiv == SPI_CLOCK_DIV2) {
  881. port().BR = (SPISettings(12000000, MSBFIRST, SPI_MODE0).br[i]);
  882. } else if (clockDiv == SPI_CLOCK_DIV4) {
  883. port().BR = (SPISettings(4000000, MSBFIRST, SPI_MODE0).br[i]);
  884. } else if (clockDiv == SPI_CLOCK_DIV8) {
  885. port().BR = (SPISettings(2000000, MSBFIRST, SPI_MODE0).br[i]);
  886. } else if (clockDiv == SPI_CLOCK_DIV16) {
  887. port().BR = (SPISettings(1000000, MSBFIRST, SPI_MODE0).br[i]);
  888. } else if (clockDiv == SPI_CLOCK_DIV32) {
  889. port().BR = (SPISettings(500000, MSBFIRST, SPI_MODE0).br[i]);
  890. } else if (clockDiv == SPI_CLOCK_DIV64) {
  891. port().BR = (SPISettings(250000, MSBFIRST, SPI_MODE0).br[i]);
  892. } else { /* clockDiv == SPI_CLOCK_DIV128 */
  893. port().BR = (SPISettings(125000, MSBFIRST, SPI_MODE0).br[i]);
  894. }
  895. }
  896. // These undocumented functions should not be used. SPI.transfer()
  897. // polls the hardware flag which is automatically cleared as the
  898. // AVR responds to SPI's interrupt
  899. void attachInterrupt() { }
  900. void detachInterrupt() { }
  901. // Teensy LC can use alternate pins for these 3 SPI signals.
  902. void setMOSI(uint8_t pin);
  903. void setMISO(uint8_t pin);
  904. void setSCK(uint8_t pin);
  905. // return true if "pin" has special chip select capability
  906. bool pinIsChipSelect(uint8_t pin);
  907. bool pinIsMOSI(uint8_t pin);
  908. bool pinIsMISO(uint8_t pin);
  909. bool pinIsSCK(uint8_t pin);
  910. // return true if both pin1 and pin2 have independent chip select capability
  911. bool pinIsChipSelect(uint8_t pin1, uint8_t pin2) { return false; }
  912. // configure a pin for chip select and return its SPI_MCR_PCSIS bitmask
  913. // setCS() is a special function, not intended for use from normal Arduino
  914. // programs/sketches. See the ILI3941_t3 library for an example.
  915. uint8_t setCS(uint8_t pin);
  916. private:
  917. KINETISL_SPI_t & port() { return *(KINETISL_SPI_t *)port_addr; }
  918. const SPI_Hardware_t & hardware() { return *(const SPI_Hardware_t *)hardware_addr; }
  919. uintptr_t port_addr;
  920. uintptr_t hardware_addr;
  921. uint32_t interruptMask = 0;
  922. uint32_t interruptSave = 0;
  923. uint8_t mosi_pin_index = 0;
  924. uint8_t miso_pin_index = 0;
  925. uint8_t sck_pin_index = 0;
  926. #ifdef SPI_TRANSACTION_MISMATCH_LED
  927. uint8_t inTransactionFlag = 0;
  928. #endif
  929. uint8_t _transferWriteFill = 0;
  930. #ifdef SPI_HAS_TRANSFER_ASYNC
  931. // DMA Support
  932. bool initDMAChannels();
  933. DMAState _dma_state = DMAState::notAllocated;
  934. uint32_t _dma_count_remaining = 0; // How many bytes left to output after current DMA completes
  935. DMAChannel *_dmaTX = nullptr;
  936. DMAChannel *_dmaRX = nullptr;
  937. EventResponder *_dma_event_responder = nullptr;
  938. #endif
  939. };
  940. /**********************************************************/
  941. /* 32 bit Teensy 4.x */
  942. /**********************************************************/
  943. #elif defined(__arm__) && defined(TEENSYDUINO) && (defined(__IMXRT1052__) || defined(__IMXRT1062__))
  944. //#include "debug/printf.h"
  945. // TODO......
  946. #undef SPI_HAS_TRANSFER_ASYNC
  947. class SPISettings {
  948. public:
  949. SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  950. if (__builtin_constant_p(clock)) {
  951. init_AlwaysInline(clock, bitOrder, dataMode);
  952. } else {
  953. init_MightInline(clock, bitOrder, dataMode);
  954. }
  955. }
  956. SPISettings() {
  957. init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
  958. }
  959. private:
  960. void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  961. init_AlwaysInline(clock, bitOrder, dataMode);
  962. }
  963. void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
  964. __attribute__((__always_inline__)) {
  965. // TODO: make these implement settings - for now, just fixed config
  966. uint32_t d, div, clkhz = 528000000/7; // LPSPI peripheral clock
  967. if (clock == 0) clock =1;
  968. d= clkhz/clock;
  969. if (d && clkhz/d > clock) d++;
  970. if (d > 257) d= 257; // max div
  971. if (d > 2) {
  972. div = d-2;
  973. } else {
  974. div =0;
  975. }
  976. ccr = LPSPI_CCR_SCKDIV(div) | LPSPI_CCR_DBT(div/2);
  977. tcr = LPSPI_TCR_FRAMESZ(7); // TCR has polarity and bit order too
  978. }
  979. uint32_t ccr; // clock config, pg 2660 (RT1050 ref, rev 2)
  980. uint32_t tcr; // transmit command, pg 2664 (RT1050 ref, rev 2)
  981. friend class SPIClass;
  982. };
  983. class SPIClass { // Teensy 4
  984. public:
  985. static const uint8_t CNT_MISO_PINS = 1;
  986. static const uint8_t CNT_MOSI_PINS = 1;
  987. static const uint8_t CNT_SCK_PINS = 1;
  988. static const uint8_t CNT_CS_PINS = 1;
  989. typedef struct {
  990. volatile uint32_t &clock_gate_register;
  991. const uint32_t clock_gate_mask;
  992. const uint8_t miso_pin[CNT_MISO_PINS];
  993. const uint32_t miso_mux[CNT_MISO_PINS];
  994. const uint8_t mosi_pin[CNT_MOSI_PINS];
  995. const uint32_t mosi_mux[CNT_MOSI_PINS];
  996. const uint8_t sck_pin[CNT_SCK_PINS];
  997. const uint32_t sck_mux[CNT_SCK_PINS];
  998. const uint8_t cs_pin[CNT_CS_PINS];
  999. const uint32_t cs_mux[CNT_CS_PINS];
  1000. } SPI_Hardware_t;
  1001. public:
  1002. constexpr SPIClass(IMXRT_LPSPI_t *myport, const SPI_Hardware_t *myhardware)
  1003. : port(myport), hardware(myhardware) {
  1004. }
  1005. // Initialize the SPI library
  1006. void begin();
  1007. // If SPI is to used from within an interrupt, this function registers
  1008. // that interrupt with the SPI library, so beginTransaction() can
  1009. // prevent conflicts. The input interruptNumber is the number used
  1010. // with attachInterrupt. If SPI is used from a different interrupt
  1011. // (eg, a timer), interruptNumber should be 255.
  1012. /*void usingInterrupt(uint8_t n) {
  1013. if (n == 3 || n == 4 || n == 24 || n == 33) {
  1014. usingInterrupt(IRQ_PORTA);
  1015. } else if (n == 0 || n == 1 || (n >= 16 && n <= 19) || n == 25 || n == 32) {
  1016. usingInterrupt(IRQ_PORTB);
  1017. } else if ((n >= 9 && n <= 13) || n == 15 || n == 22 || n == 23
  1018. || (n >= 27 && n <= 30)) {
  1019. usingInterrupt(IRQ_PORTC);
  1020. } else if (n == 2 || (n >= 5 && n <= 8) || n == 14 || n == 20 || n == 21) {
  1021. usingInterrupt(IRQ_PORTD);
  1022. } else if (n == 26 || n == 31) {
  1023. usingInterrupt(IRQ_PORTE);
  1024. }
  1025. }*/
  1026. void usingInterrupt(IRQ_NUMBER_t interruptName);
  1027. void notUsingInterrupt(IRQ_NUMBER_t interruptName);
  1028. // Before using SPI.transfer() or asserting chip select pins,
  1029. // this function is used to gain exclusive access to the SPI bus
  1030. // and configure the correct settings.
  1031. void beginTransaction(SPISettings settings) {
  1032. if (interruptMasksUsed) {
  1033. __disable_irq();
  1034. if (interruptMasksUsed & 0x01) {
  1035. interruptSave[0] = NVIC_ICER0 & interruptMask[0];
  1036. NVIC_ICER0 = interruptSave[0];
  1037. }
  1038. if (interruptMasksUsed & 0x02) {
  1039. interruptSave[1] = NVIC_ICER1 & interruptMask[1];
  1040. NVIC_ICER1 = interruptSave[1];
  1041. }
  1042. if (interruptMasksUsed & 0x04) {
  1043. interruptSave[2] = NVIC_ICER2 & interruptMask[2];
  1044. NVIC_ICER2 = interruptSave[2];
  1045. }
  1046. if (interruptMasksUsed & 0x08) {
  1047. interruptSave[3] = NVIC_ICER3 & interruptMask[3];
  1048. NVIC_ICER3 = interruptSave[3];
  1049. }
  1050. if (interruptMasksUsed & 0x10) {
  1051. interruptSave[4] = NVIC_ICER4 & interruptMask[4];
  1052. NVIC_ICER4 = interruptSave[4];
  1053. }
  1054. __enable_irq();
  1055. }
  1056. #ifdef SPI_TRANSACTION_MISMATCH_LED
  1057. if (inTransactionFlag) {
  1058. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  1059. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  1060. }
  1061. inTransactionFlag = 1;
  1062. #endif
  1063. //printf("trans\n");
  1064. port->CR = 0;
  1065. port->CFGR1 = LPSPI_CFGR1_MASTER | LPSPI_CFGR1_SAMPLE;
  1066. port->CCR = settings.ccr;
  1067. port->TCR = settings.tcr;
  1068. //port->CCR = LPSPI_CCR_SCKDIV(4);
  1069. //port->TCR = LPSPI_TCR_FRAMESZ(7);
  1070. port->CR = LPSPI_CR_MEN;
  1071. }
  1072. // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
  1073. uint8_t transfer(uint8_t data) {
  1074. // TODO: check for space in fifo?
  1075. port->TDR = data;
  1076. while (1) {
  1077. uint32_t fifo = (port->FSR >> 16) & 0x1F;
  1078. if (fifo > 0) return port->RDR;
  1079. }
  1080. //port().SR = SPI_SR_TCF;
  1081. //port().PUSHR = data;
  1082. //while (!(port().SR & SPI_SR_TCF)) ; // wait
  1083. //return port().POPR;
  1084. }
  1085. uint16_t transfer16(uint16_t data) {
  1086. uint32_t tcr = port->TCR;
  1087. port->TCR = (tcr & 0xfffff000) | LPSPI_TCR_FRAMESZ(15); // turn on 16 bit mode
  1088. port->TDR = data; // output 16 bit data.
  1089. while ((port->RSR & LPSPI_RSR_RXEMPTY)) ; // wait while the RSR fifo is empty...
  1090. port->TCR = tcr; // restore back
  1091. return port->RDR;
  1092. }
  1093. void inline transfer(void *buf, size_t count) {transfer(buf, buf, count);}
  1094. void setTransferWriteFill(uint8_t ch ) {_transferWriteFill = ch;}
  1095. void transfer(const void * buf, void * retbuf, size_t count);
  1096. // Asynch support (DMA )
  1097. #ifdef SPI_HAS_TRANSFER_ASYNC
  1098. bool transfer(const void *txBuffer, void *rxBuffer, size_t count, EventResponderRef event_responder);
  1099. friend void _spi_dma_rxISR0(void);
  1100. friend void _spi_dma_rxISR1(void);
  1101. friend void _spi_dma_rxISR2(void);
  1102. inline void dma_rxisr(void);
  1103. #endif
  1104. // After performing a group of transfers and releasing the chip select
  1105. // signal, this function allows others to access the SPI bus
  1106. void endTransaction(void) {
  1107. #ifdef SPI_TRANSACTION_MISMATCH_LED
  1108. if (!inTransactionFlag) {
  1109. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  1110. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  1111. }
  1112. inTransactionFlag = 0;
  1113. #endif
  1114. if (interruptMasksUsed) {
  1115. if (interruptMasksUsed & 0x01) NVIC_ISER0 = interruptSave[0];
  1116. if (interruptMasksUsed & 0x02) NVIC_ISER1 = interruptSave[1];
  1117. if (interruptMasksUsed & 0x04) NVIC_ISER2 = interruptSave[2];
  1118. if (interruptMasksUsed & 0x08) NVIC_ISER3 = interruptSave[3];
  1119. if (interruptMasksUsed & 0x10) NVIC_ISER4 = interruptSave[4];
  1120. }
  1121. }
  1122. // Disable the SPI bus
  1123. void end();
  1124. // This function is deprecated. New applications should use
  1125. // beginTransaction() to configure SPI settings.
  1126. void setBitOrder(uint8_t bitOrder);
  1127. // This function is deprecated. New applications should use
  1128. // beginTransaction() to configure SPI settings.
  1129. void setDataMode(uint8_t dataMode);
  1130. // This function is deprecated. New applications should use
  1131. // beginTransaction() to configure SPI settings.
  1132. void setClockDivider(uint8_t clockDiv) {
  1133. if (clockDiv == SPI_CLOCK_DIV2) {
  1134. //setClockDivider_noInline(SPISettings(12000000, MSBFIRST, SPI_MODE0).ctar);
  1135. } else if (clockDiv == SPI_CLOCK_DIV4) {
  1136. //setClockDivider_noInline(SPISettings(4000000, MSBFIRST, SPI_MODE0).ctar);
  1137. } else if (clockDiv == SPI_CLOCK_DIV8) {
  1138. //setClockDivider_noInline(SPISettings(2000000, MSBFIRST, SPI_MODE0).ctar);
  1139. } else if (clockDiv == SPI_CLOCK_DIV16) {
  1140. //setClockDivider_noInline(SPISettings(1000000, MSBFIRST, SPI_MODE0).ctar);
  1141. } else if (clockDiv == SPI_CLOCK_DIV32) {
  1142. //setClockDivider_noInline(SPISettings(500000, MSBFIRST, SPI_MODE0).ctar);
  1143. } else if (clockDiv == SPI_CLOCK_DIV64) {
  1144. //setClockDivider_noInline(SPISettings(250000, MSBFIRST, SPI_MODE0).ctar);
  1145. } else { /* clockDiv == SPI_CLOCK_DIV128 */
  1146. //setClockDivider_noInline(SPISettings(125000, MSBFIRST, SPI_MODE0).ctar);
  1147. }
  1148. }
  1149. void setClockDivider_noInline(uint32_t clk);
  1150. // These undocumented functions should not be used. SPI.transfer()
  1151. // polls the hardware flag which is automatically cleared as the
  1152. // AVR responds to SPI's interrupt
  1153. void attachInterrupt() { }
  1154. void detachInterrupt() { }
  1155. // Teensy 3.x can use alternate pins for these 3 SPI signals.
  1156. void setMOSI(uint8_t pin);
  1157. void setMISO(uint8_t pin);
  1158. void setSCK(uint8_t pin);
  1159. // return true if "pin" has special chip select capability
  1160. uint8_t pinIsChipSelect(uint8_t pin);
  1161. bool pinIsMOSI(uint8_t pin);
  1162. bool pinIsMISO(uint8_t pin);
  1163. bool pinIsSCK(uint8_t pin);
  1164. // return true if both pin1 and pin2 have independent chip select capability
  1165. bool pinIsChipSelect(uint8_t pin1, uint8_t pin2);
  1166. // configure a pin for chip select and return its SPI_MCR_PCSIS bitmask
  1167. // setCS() is a special function, not intended for use from normal Arduino
  1168. // programs/sketches. See the ILI3941_t3 library for an example.
  1169. uint8_t setCS(uint8_t pin);
  1170. private:
  1171. //KINETISK_SPI_t & port() { return *(KINETISK_SPI_t *)port_addr; }
  1172. IMXRT_LPSPI_t * const port;
  1173. const SPI_Hardware_t * const hardware;
  1174. void updateCTAR(uint32_t ctar);
  1175. uint8_t miso_pin_index = 0;
  1176. uint8_t mosi_pin_index = 0;
  1177. uint8_t sck_pin_index = 0;
  1178. uint8_t interruptMasksUsed = 0;
  1179. uint32_t interruptMask[(NVIC_NUM_INTERRUPTS+31)/32] = {};
  1180. uint32_t interruptSave[(NVIC_NUM_INTERRUPTS+31)/32] = {};
  1181. #ifdef SPI_TRANSACTION_MISMATCH_LED
  1182. uint8_t inTransactionFlag = 0;
  1183. #endif
  1184. uint8_t _transferWriteFill = 0;
  1185. // DMA Support
  1186. #ifdef SPI_HAS_TRANSFER_ASYNC
  1187. bool initDMAChannels();
  1188. DMAState _dma_state = DMAState::notAllocated;
  1189. uint32_t _dma_count_remaining = 0; // How many bytes left to output after current DMA completes
  1190. DMAChannel *_dmaTX = nullptr;
  1191. DMAChannel *_dmaRX = nullptr;
  1192. EventResponder *_dma_event_responder = nullptr;
  1193. #endif
  1194. };
  1195. #endif
  1196. extern SPIClass SPI;
  1197. #if defined(__MKL26Z64__)
  1198. extern SPIClass SPI1;
  1199. #endif
  1200. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  1201. extern SPIClass SPI1;
  1202. extern SPIClass SPI2;
  1203. #endif
  1204. #endif