| 
															 | 
															 | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															#ifdef SPI_TRANSACTION_MISMATCH_LED | 
															 | 
															 | 
															#ifdef SPI_TRANSACTION_MISMATCH_LED | 
														
														
													
														
															 | 
															 | 
															uint8_t SPIClass::inTransactionFlag = 0; | 
															 | 
															 | 
															uint8_t SPIClass::inTransactionFlag = 0; | 
														
														
													
														
															 | 
															 | 
															#endif | 
															 | 
															 | 
															#endif | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															uint8_t SPIClass::_transferWriteFill = 0; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															void SPIClass::begin() | 
															 | 
															 | 
															void SPIClass::begin() | 
														
														
													
														
															 | 
															 | 
															{ | 
															 | 
															 | 
															{ | 
														
														
													
												
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																SREG = stmp; | 
															 | 
															 | 
																SREG = stmp; | 
														
														
													
														
															 | 
															 | 
															} | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void SPIClass::transfer(const void * buf, void * retbuf, uint32_t count) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (count == 0) return; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																const uint8_t *p = (const uint8_t *)buf; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																uint8_t *pret = (uint8_t *)retbuf; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																uint8_t in; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																uint8_t out = p ? *p++ : _transferWriteFill; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																SPDR = out; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																while (--count > 0) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	if (p) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		out = *p++; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	while (!(SPSR & _BV(SPIF))) ; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	in = SPDR; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	SPDR = out; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	if (pret)*pret++ = in; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																while (!(SPSR & _BV(SPIF))) ; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																in = SPDR; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (pret)*pret = in; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															/**********************************************************/ | 
															 | 
															 | 
															/**********************************************************/ | 
														
														
													
														
															 | 
															 | 
															/*     32 bit Teensy 3.x				  */ | 
															 | 
															 | 
															/*     32 bit Teensy 3.x				  */ | 
														
														
													
														
															 | 
															 | 
															/**********************************************************/ | 
															 | 
															 | 
															/**********************************************************/ | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															#elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK) | 
															 | 
															 | 
															#elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#if defined(KINETISK) && defined( SPI_HAS_TRANSFER_ASYNC) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#ifndef TRANSFER_COUNT_FIXED | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															inline void DMAChanneltransferCount(DMAChannel * dmac, unsigned int len) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// note does no validation of length... | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																DMABaseClass::TCD_t *tcd = dmac->TCD; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (!(tcd->BITER & DMA_TCD_BITER_ELINK)) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	tcd->BITER = len & 0x7fff; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	tcd->BITER = (tcd->BITER & 0xFE00) | (len & 0x1ff); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																tcd->CITER = tcd->BITER;  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#else  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															inline void DMAChanneltransferCount(DMAChannel * dmac, unsigned int len) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																dmac->transferCount(len); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#endif | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#endif | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															#if defined(__MK20DX128__) || defined(__MK20DX256__) | 
															 | 
															 | 
															#if defined(__MK20DX128__) || defined(__MK20DX256__) | 
														
														
													
														
															 | 
															 | 
															void _spi_dma_rxISR0(void) {/*SPI.dma_rxisr();*/} | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#ifdef SPI_HAS_TRANSFER_ASYNC | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void _spi_dma_rxISR0(void) {SPI.dma_rxisr();} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#else | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void _spi_dma_rxISR0(void) {;} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#endif | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = { | 
															 | 
															 | 
															const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = { | 
														
														
													
														
															 | 
															 | 
																SIM_SCGC6, SIM_SCGC6_SPI0, 4, IRQ_SPI0, | 
															 | 
															 | 
																SIM_SCGC6, SIM_SCGC6_SPI0, 4, IRQ_SPI0, | 
														
														
													
														
															 | 
															 | 
																32767, DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX, | 
															 | 
															 | 
																32767, DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX, | 
														
														
													
												
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															SPIClass SPI((uintptr_t)&KINETISK_SPI0, (uintptr_t)&SPIClass::spi0_hardware); | 
															 | 
															 | 
															SPIClass SPI((uintptr_t)&KINETISK_SPI0, (uintptr_t)&SPIClass::spi0_hardware); | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) | 
															 | 
															 | 
															#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) | 
														
														
													
														
															 | 
															 | 
															void _spi_dma_rxISR0(void) {/*SPI.dma_rxisr();*/} | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															void _spi_dma_rxISR1(void) {/*SPI1.dma_rxisr();*/} | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															void _spi_dma_rxISR2(void) {/*SPI2.dma_rxisr();*/} | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#ifdef SPI_HAS_TRANSFER_ASYNC | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void _spi_dma_rxISR0(void) {SPI.dma_rxisr();} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void _spi_dma_rxISR1(void) {SPI1.dma_rxisr();} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void _spi_dma_rxISR2(void) {SPI2.dma_rxisr();} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#else | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void _spi_dma_rxISR0(void) {;} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void _spi_dma_rxISR1(void) {;} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void _spi_dma_rxISR2(void) {;} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#endif | 
														
														
													
														
															 | 
															 | 
															const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = { | 
															 | 
															 | 
															const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = { | 
														
														
													
														
															 | 
															 | 
																SIM_SCGC6, SIM_SCGC6_SPI0, 4, IRQ_SPI0, | 
															 | 
															 | 
																SIM_SCGC6, SIM_SCGC6_SPI0, 4, IRQ_SPI0, | 
														
														
													
														
															 | 
															 | 
																32767, DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX, | 
															 | 
															 | 
																32767, DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX, | 
														
														
													
												
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																} | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															} | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															void SPIClass::transfer(void *buf, size_t count) | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void SPIClass::transfer(const void * buf, void * retbuf, size_t count) | 
														
														
													
														
															 | 
															 | 
															{ | 
															 | 
															 | 
															{ | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
																if (count == 0) return; | 
															 | 
															 | 
																if (count == 0) return; | 
														
														
													
														
															 | 
															 | 
																uint8_t *p_write = (uint8_t *)buf; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																uint8_t *p_read = p_write; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																size_t count_read = count; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																bool lsbfirst = (port().CTAR0 & SPI_CTAR_LSBFE) ? true : false; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																uint32_t sr, full_mask; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																// Lets clear the reader queue | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F); | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																// Now lets loop while we still have data to output | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																if (count & 1) { | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	if (count > 1) | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																		port().PUSHR = *p_write++ | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0); | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	else | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																		port().PUSHR = *p_write++ | SPI_PUSHR_CTAS(0); | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	count--; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																} | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																full_mask = (hardware().queue_size-1) << 12; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																while (count > 0) { | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	// Push out the next byte | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	uint16_t w = (*p_write++) << 8; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	w |= *p_write++; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	if (lsbfirst) w = __builtin_bswap16(w); | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	if (count == 2) | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																		port().PUSHR = w | SPI_PUSHR_CTAS(1); | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	else	 | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																		port().PUSHR = w | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1); | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	count -= 2; // how many bytes to output. | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	// Make sure queue is not full before pushing next byte out | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	do { | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (!(port().CTAR0 & SPI_CTAR_LSBFE)) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// We are doing the standard MSB order | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	const uint8_t *p_write = (const uint8_t *)buf; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	uint8_t *p_read = (uint8_t *)retbuf; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	size_t count_read = count; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// Lets clear the reader queue | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	uint32_t sr; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// Now lets loop while we still have data to output | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	if (count & 1) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	    if (p_write) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			if (count > 1) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				port().PUSHR = *p_write++ | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			else | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				port().PUSHR = *p_write++ | SPI_PUSHR_CTAS(0); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			if (count > 1) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				port().PUSHR = _transferWriteFill | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			else | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				port().PUSHR = _transferWriteFill | SPI_PUSHR_CTAS(0); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		count--; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																    uint16_t w =  (uint16_t)(_transferWriteFill << 8) | _transferWriteFill; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	while (count > 0) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		// Push out the next byte;  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	    if (p_write) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	    	w = (*p_write++) << 8; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			w |= *p_write++; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	    } | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	    uint16_t queue_full_status_mask = (hardware().queue_size-1) << 12; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		if (count == 2) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			port().PUSHR = w | SPI_PUSHR_CTAS(1); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		else	 | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			port().PUSHR = w | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		count -= 2; // how many bytes to output. | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		// Make sure queue is not full before pushing next byte out | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		do { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			sr = port().SR; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			if (sr & 0xF0)  { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				uint16_t w = port().POPR;  // Read any pending RX bytes in | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				if (count_read & 1) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					if (p_read) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																						*p_read++ = w;  // Read any pending RX bytes in | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					}  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					count_read--; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					if (p_read) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																						*p_read++ = w >> 8; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																						*p_read++ = (w & 0xff); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					count_read -= 2; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		} while ((sr & (15 << 12)) > queue_full_status_mask); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// now lets wait for all of the read bytes to be returned... | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	while (count_read) { | 
														
														
													
														
															 | 
															 | 
																		sr = port().SR; | 
															 | 
															 | 
																		sr = port().SR; | 
														
														
													
														
															 | 
															 | 
																		if (sr & 0xF0)  { | 
															 | 
															 | 
																		if (sr & 0xF0)  { | 
														
														
													
														
															 | 
															 | 
																			uint16_t w = port().POPR;  // Read any pending RX bytes in | 
															 | 
															 | 
																			uint16_t w = port().POPR;  // Read any pending RX bytes in | 
														
														
													
														
															 | 
															 | 
																			if (count_read & 1) { | 
															 | 
															 | 
																			if (count_read & 1) { | 
														
														
													
														
															 | 
															 | 
																				*p_read++ = w;  // Read any pending RX bytes in | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				if (p_read) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					*p_read++ = w;  // Read any pending RX bytes in | 
														
														
													
														
															 | 
															 | 
																				count_read--; | 
															 | 
															 | 
																				count_read--; | 
														
														
													
														
															 | 
															 | 
																			} else { | 
															 | 
															 | 
																			} else { | 
														
														
													
														
															 | 
															 | 
																				if (lsbfirst) w = __builtin_bswap16(w); | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																				*p_read++ = w >> 8; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																				*p_read++ = (w & 0xff); | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				if (p_read) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					*p_read++ = w >> 8; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					*p_read++ = (w & 0xff); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				} | 
														
														
													
														
															 | 
															 | 
																				count_read -= 2; | 
															 | 
															 | 
																				count_read -= 2; | 
														
														
													
														
															 | 
															 | 
																			} | 
															 | 
															 | 
																			} | 
														
														
													
														
															 | 
															 | 
																		} | 
															 | 
															 | 
																		} | 
														
														
													
														
															 | 
															 | 
																	} while ((sr & (15 << 12)) > full_mask); | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// We are doing the less ofen LSB mode | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	const uint8_t *p_write = (const uint8_t *)buf; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	uint8_t *p_read = (uint8_t *)retbuf; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	size_t count_read = count; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// Lets clear the reader queue | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	uint32_t sr; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// Now lets loop while we still have data to output | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	if (count & 1) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	    if (p_write) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			if (count > 1) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				port().PUSHR = *p_write++ | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			else | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				port().PUSHR = *p_write++ | SPI_PUSHR_CTAS(0); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			if (count > 1) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				port().PUSHR = _transferWriteFill | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			else | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				port().PUSHR = _transferWriteFill | SPI_PUSHR_CTAS(0); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		count--; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																    uint16_t w = _transferWriteFill; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	while (count > 0) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		// Push out the next byte;  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	    if (p_write) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			w = *p_write++; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	    	w |= ((*p_write++) << 8); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	    } | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	    uint16_t queue_full_status_mask = (hardware().queue_size-1) << 12; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		if (count == 2) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			port().PUSHR = w | SPI_PUSHR_CTAS(1); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		else	 | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			port().PUSHR = w | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		count -= 2; // how many bytes to output. | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		// Make sure queue is not full before pushing next byte out | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		do { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			sr = port().SR; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			if (sr & 0xF0)  { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				uint16_t w = port().POPR;  // Read any pending RX bytes in | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				if (count_read & 1) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					if (p_read) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																						*p_read++ = w;  // Read any pending RX bytes in | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					}  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					count_read--; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					if (p_read) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																						*p_read++ = (w & 0xff); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																						*p_read++ = w >> 8; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					count_read -= 2; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		} while ((sr & (15 << 12)) > queue_full_status_mask); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// now lets wait for all of the read bytes to be returned... | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	while (count_read) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		sr = port().SR; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		if (sr & 0xF0)  { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			uint16_t w = port().POPR;  // Read any pending RX bytes in | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			if (count_read & 1) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				if (p_read) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					*p_read++ = w;  // Read any pending RX bytes in | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				count_read--; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				if (p_read) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					*p_read++ = (w & 0xff); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																					*p_read++ = w >> 8; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																				count_read -= 2; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//============================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															// ASYNCH Support | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//============================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//========================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															// Try Transfer using DMA. | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//========================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#ifdef SPI_HAS_TRANSFER_ASYNC | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															static uint8_t bit_bucket; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#define dontInterruptAtCompletion(dmac) (dmac)->TCD->CSR &= ~DMA_TCD_CSR_INTMAJOR | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//========================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															// Init the DMA channels | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//========================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															bool SPIClass::initDMAChannels() { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// Allocate our channels.  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaTX = new DMAChannel(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (_dmaTX == nullptr) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	return false; | 
														
														
													
														
															 | 
															 | 
																} | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
																// now lets wait for all of the read bytes to be returned... | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																while (count_read) { | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	sr = port().SR; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																	if (sr & 0xF0)  { | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																		uint16_t w = port().POPR;  // Read any pending RX bytes in | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																		if (count_read & 1) { | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																			*p_read++ = w;  // Read any pending RX bytes in | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																			count_read--; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																		} else { | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																			if (lsbfirst) w = __builtin_bswap16(w); | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																			*p_read++ = w >> 8; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																			*p_read++ = (w & 0xff); | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																			count_read -= 2; | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX = new DMAChannel(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (_dmaRX == nullptr) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	delete _dmaTX; // release it | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaTX = nullptr;  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	return false; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// Let's setup the RX chain | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->disable(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->source((volatile uint8_t&)port().POPR); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->disableOnCompletion(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->triggerAtHardwareEvent(hardware().rx_dma_channel); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->attachInterrupt(hardware().dma_rxisr); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->interruptAtCompletion(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// We may be using settings chain here so lets set it up.  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// Now lets setup TX chain.  Note if trigger TX is not set | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// we need to have the RX do it for us. | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaTX->disable(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaTX->destination((volatile uint8_t&)port().PUSHR); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaTX->disableOnCompletion(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (hardware().tx_dma_channel) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaTX->triggerAtHardwareEvent(hardware().tx_dma_channel); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//		Serial.printf("SPI InitDMA tx triger by RX: %x\n", (uint32_t)_dmaRX); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																    _dmaTX->triggerAtTransfersOf(*_dmaRX); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dma_state = DMAState::idle;  // Should be first thing set! | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																return true; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//========================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															// Main Aync Transfer function | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//========================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															bool SPIClass::transfer(const void *buf, void *retbuf, size_t count, EventResponderRef event_responder) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																uint8_t dma_first_byte; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (_dma_state == DMAState::notAllocated) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	if (!initDMAChannels()) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		return false; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (_dma_state == DMAState::active) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	return false; // already active | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																event_responder.clearEvent();	// Make sure it is not set yet | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (count < 2) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// Use non-async version to simplify cases... | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	transfer(buf, retbuf, count); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	event_responder.triggerEvent(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	return true; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// Now handle the cases where the count > then how many we can output in one DMA request | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (count > hardware().max_dma_count) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dma_count_remaining = count - hardware().max_dma_count; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	count = hardware().max_dma_count; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dma_count_remaining = 0; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// Now See if caller passed in a source buffer.  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaTX->TCD->ATTR_DST = 0;		// Make sure set for 8 bit mode | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																uint8_t *write_data = (uint8_t*) buf; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (buf) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	dma_first_byte = *write_data; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaTX->sourceBuffer((uint8_t*)write_data+1, count-1);   | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaTX->TCD->SLAST = 0;	// Finish with it pointing to next location | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	dma_first_byte = _transferWriteFill; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaTX->source((uint8_t&)_transferWriteFill);   // maybe have setable value | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	DMAChanneltransferCount(_dmaTX, count-1); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																}	 | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (retbuf) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// On T3.5 must handle SPI1/2 differently as only one DMA channel | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaRX->TCD->ATTR_SRC = 0;		//Make sure set for 8 bit mode... | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaRX->destinationBuffer((uint8_t*)retbuf, count); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaRX->TCD->DLASTSGA = 0;		// At end point after our bufffer | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		// Write  only mode | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaRX->TCD->ATTR_SRC = 0;		//Make sure set for 8 bit mode... | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaRX->destination((uint8_t&)bit_bucket); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	DMAChanneltransferCount(_dmaRX, count); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dma_event_responder = &event_responder; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// Now try to start it? | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// Setup DMA main object | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																yield(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_CLR_TXF | SPI_MCR_PCSIS(0x1F); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																port().SR = 0xFF0F0000; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// Lets try to output the first byte to make sure that we are in 8 bit mode... | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																port().PUSHR = dma_first_byte | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;	 | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (hardware().tx_dma_channel) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	port().RSER =  SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS | SPI_RSER_TFFF_RE | SPI_RSER_TFFF_DIRS; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaRX->enable(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// Get the initial settings.  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaTX->enable(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	//T3.5 SP1 and SPI2 - TX is not triggered by SPI but by RX... | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	port().RSER =  SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS ; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																    _dmaTX->triggerAtTransfersOf(*_dmaRX); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaTX->enable(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaRX->enable(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dma_state = DMAState::active; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																return true; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//------------------------------------------------------------------------- | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															// DMA RX ISR | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//------------------------------------------------------------------------- | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void SPIClass::dma_rxisr(void) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->clearInterrupt(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaTX->clearComplete(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->clearComplete(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																uint8_t should_reenable_tx = true;	// should we re-enable TX maybe not if count will be 0... | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (_dma_count_remaining) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// What do I need to do to start it back up again... | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// We will use the BITR/CITR from RX as TX may have prefed some stuff | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	if (_dma_count_remaining > hardware().max_dma_count) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		_dma_count_remaining -= hardware().max_dma_count; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		DMAChanneltransferCount(_dmaTX, _dma_count_remaining-1); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		DMAChanneltransferCount(_dmaRX, _dma_count_remaining); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		if (_dma_count_remaining == 1) should_reenable_tx = false; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		_dma_count_remaining = 0; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// In some cases we need to again start the TX manually to get it to work... | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	if (_dmaTX->TCD->SADDR == &_transferWriteFill) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		if (port().CTAR0  & SPI_CTAR_FMSZ(8)) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			port().PUSHR = (_transferWriteFill | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		} else  { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			port().PUSHR = (_transferWriteFill | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		if (port().CTAR0  & SPI_CTAR_FMSZ(8)) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			// 16 bit mode | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			uint16_t w = *((uint16_t*)_dmaTX->TCD->SADDR); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			_dmaTX->TCD->SADDR = (volatile uint8_t*)(_dmaTX->TCD->SADDR) + 2; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			port().PUSHR = (w | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		} else  { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			uint8_t w = *((uint8_t*)_dmaTX->TCD->SADDR); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			_dmaTX->TCD->SADDR = (volatile uint8_t*)(_dmaTX->TCD->SADDR) + 1; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																			port().PUSHR = (w | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT); | 
														
														
													
														
															 | 
															 | 
																		} | 
															 | 
															 | 
																		} | 
														
														
													
														
															 | 
															 | 
																	} | 
															 | 
															 | 
																	} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaRX->enable(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	if (should_reenable_tx) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		_dmaTX->enable(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	port().RSER = 0; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	//port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);  // clear out the queue | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	port().SR = 0xFF0F0000; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	port().CTAR0  &= ~(SPI_CTAR_FMSZ(8)); 	// Hack restore back to 8 bits | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dma_state = DMAState::completed;   // set back to 1 in case our call wants to start up dma again | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dma_event_responder->triggerEvent(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
																} | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															} | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#endif // SPI_HAS_TRANSFER_ASYNC | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															/**********************************************************/ | 
															 | 
															 | 
															/**********************************************************/ | 
														
														
													
												
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															#elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL) | 
															 | 
															 | 
															#elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL) | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															void _spi_dma_rxISR0(void) {/*SPI.dma_rxisr();*/} | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#ifdef SPI_HAS_TRANSFER_ASYNC | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void _spi_dma_rxISR0(void) {SPI.dma_isr();} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void _spi_dma_rxISR1(void) {SPI1.dma_isr();} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#else | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void _spi_dma_rxISR0(void) {;} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void _spi_dma_rxISR1(void) {;} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#endif | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = { | 
															 | 
															 | 
															const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = { | 
														
														
													
														
															 | 
															 | 
																SIM_SCGC4, SIM_SCGC4_SPI0, | 
															 | 
															 | 
																SIM_SCGC4, SIM_SCGC4_SPI0, | 
														
														
													
														
															 | 
															 | 
																0, // BR index 0 | 
															 | 
															 | 
																0, // BR index 0 | 
														
														
													
												
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															}; | 
															 | 
															 | 
															}; | 
														
														
													
														
															 | 
															 | 
															SPIClass SPI((uintptr_t)&KINETISL_SPI0, (uintptr_t)&SPIClass::spi0_hardware); | 
															 | 
															 | 
															SPIClass SPI((uintptr_t)&KINETISL_SPI0, (uintptr_t)&SPIClass::spi0_hardware); | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															void _spi_dma_rxISR1(void) {/*SPI1.dma_rxisr();*/} | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															const SPIClass::SPI_Hardware_t SPIClass::spi1_hardware = { | 
															 | 
															 | 
															const SPIClass::SPI_Hardware_t SPIClass::spi1_hardware = { | 
														
														
													
														
															 | 
															 | 
																SIM_SCGC4, SIM_SCGC4_SPI1, | 
															 | 
															 | 
																SIM_SCGC4, SIM_SCGC4_SPI1, | 
														
														
													
														
															 | 
															 | 
																1, // BR index 1 in SPI Settings | 
															 | 
															 | 
																1, // BR index 1 in SPI Settings | 
														
														
													
												
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
																return 0; | 
															 | 
															 | 
																return 0; | 
														
														
													
														
															 | 
															 | 
															} | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void SPIClass::transfer(const void * buf, void * retbuf, size_t count) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (count == 0) return; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																const uint8_t *p = (const uint8_t *)buf; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																uint8_t *pret = (uint8_t *)retbuf; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																uint8_t in; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																while (!(port().S & SPI_S_SPTEF)) ; // wait | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																uint8_t out = p ? *p++ : _transferWriteFill; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																port().DL = out; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																while (--count > 0) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	if (p) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		out = *p++; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	while (!(port().S & SPI_S_SPTEF)) ; // wait | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	__disable_irq(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	port().DL = out; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	while (!(port().S & SPI_S_SPRF)) ; // wait | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	in = port().DL; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	__enable_irq(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	if (pret)*pret++ = in; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																while (!(port().S & SPI_S_SPRF)) ; // wait | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																in = port().DL; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (pret)*pret = in; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//============================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															// ASYNCH Support | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//============================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//========================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															// Try Transfer using DMA. | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//========================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#ifdef SPI_HAS_TRANSFER_ASYNC | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															static uint8_t      _dma_dummy_rx; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															void SPIClass::dma_isr(void) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																//  Serial.println("_spi_dma_rxISR"); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->clearInterrupt(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																port().C2 = 0; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																uint8_t tmp __attribute__((unused)) = port().S; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaTX->clearComplete(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->clearComplete(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dma_state = DMAState::completed;   // set back to 1 in case our call wants to start up dma again | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dma_event_responder->triggerEvent(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															bool SPIClass::initDMAChannels() { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																//Serial.println("First dma call"); Serial.flush(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaTX = new DMAChannel(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (_dmaTX == nullptr) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	return false; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaTX->disable(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaTX->destination((volatile uint8_t&)port().DL); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaTX->disableOnCompletion(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaTX->triggerAtHardwareEvent(hardware().tx_dma_channel); | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															#endif | 
															 | 
															 | 
															 | 
														
														
													
														
															 | 
															 | 
															
  | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX = new DMAChannel(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (_dmaRX == NULL) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	delete _dmaTX; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaRX = nullptr; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	return false; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->disable(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->source((volatile uint8_t&)port().DL); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->disableOnCompletion(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->triggerAtHardwareEvent(hardware().rx_dma_channel); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->attachInterrupt(hardware().dma_isr); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->interruptAtCompletion(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dma_state = DMAState::idle;  // Should be first thing set! | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																//Serial.println("end First dma call"); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																return true; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//========================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															// Main Aync Transfer function | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															//========================================================================= | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															bool SPIClass::transfer(const void *buf, void *retbuf, size_t count, EventResponderRef event_responder) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (_dma_state == DMAState::notAllocated) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	if (!initDMAChannels()) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																		return false; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															   | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (_dma_state == DMAState::active) | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	return false; // already active | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																event_responder.clearEvent();	// Make sure it is not set yet | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (count < 2) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	// Use non-async version to simplify cases... | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	transfer(buf, retbuf, count); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	event_responder.triggerEvent(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	return true; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																//_dmaTX->destination((volatile uint8_t&)port().DL); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																//_dmaRX->source((volatile uint8_t&)port().DL); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaTX->CFG->DCR = (_dmaTX->CFG->DCR & ~DMA_DCR_DSIZE(3)) | DMA_DCR_DSIZE(1); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dmaRX->CFG->DCR = (_dmaRX->CFG->DCR & ~DMA_DCR_SSIZE(3)) | DMA_DCR_SSIZE(1);  // 8 bit transfer | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// Now see if the user passed in TX buffer to send. | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																uint8_t first_char; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (buf) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	uint8_t *data_out = (uint8_t*)buf; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	first_char = *data_out++; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaTX->sourceBuffer(data_out, count-1); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	first_char = (_transferWriteFill & 0xff); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaTX->source((uint8_t&)_transferWriteFill);   // maybe have setable value | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaTX->transferCount(count-1); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																if (retbuf) { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaRX->destinationBuffer((uint8_t*)retbuf, count); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} else { | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaRX->destination(_dma_dummy_rx);    // NULL ? | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																	_dmaRX->transferCount(count); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																_dma_event_responder = &event_responder; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																//Serial.println("Before DMA C2"); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// Try pushing the first character | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															    while (!(port().S & SPI_S_SPTEF)); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															    port().DL = first_char; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																port().C2 |= SPI_C2_TXDMAE | SPI_C2_RXDMAE; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																// Now  make sure SPI is enabled.  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
																port().C1 |= SPI_C1_SPE; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															       | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															    _dmaRX->enable(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															    _dmaTX->enable(); | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															    _dma_state = DMAState::active; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															    return true; | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															} | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#endif //SPI_HAS_TRANSFER_ASYNC | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															
  | 
														
														
													
														
															 | 
															 | 
															 | 
															 | 
															 | 
															#endif |