SPI improvements: non-DMA block read + added DMA transfer functions

This commit is contained in:
stevstrong 2017-05-11 00:05:08 +02:00
parent fc0ee24184
commit bd3fb68a5e
4 changed files with 169 additions and 116 deletions

View File

@ -117,33 +117,16 @@ void dma_detach_interrupt(dma_dev *dev, dma_stream stream) {
dev->handlers[stream].handler = NULL;
}
const uint8 dma_isr_bits_shift[] = { 0, 6, 16, 22};
uint8 dma_get_isr_bits(dma_dev *dev, dma_stream stream) {
if ( stream&0xFC ) return ((dev->regs->HISR)>>dma_isr_bits_shift[stream&0x03]) & 0x3d;
else return ((dev->regs->LISR)>>dma_isr_bits_shift[stream&0x03]) & 0x3d;
}
void dma_clear_isr_bits(dma_dev *dev, dma_stream stream) {
switch (stream) {
case 0:
dev->regs->LIFCR|=0x0000003d;
break;
case 1:
dev->regs->LIFCR|=0x00000f40;
break;
case 2:
dev->regs->LIFCR|=0x003d0000;
break;
case 3:
dev->regs->LIFCR|=0x0f400000;
break;
case 4:
dev->regs->HIFCR|=0x0000003d;
break;
case 5:
dev->regs->HIFCR|=0x00000f40;
break;
case 6:
dev->regs->HIFCR|=0x003d0000;
break;
case 7:
dev->regs->HIFCR|=0x0f400000;
break;
}
if ( stream&0xFC ) dev->regs->HIFCR = (uint32)0x0000003d << dma_isr_bits_shift[stream&0x03];
else dev->regs->LIFCR = (uint32)0x0000003d << dma_isr_bits_shift[stream&0x03];
}
/*

View File

@ -25,7 +25,7 @@
*****************************************************************************/
/**
* @file dma.h
* @file dmaF4.h
*
* @author Marti Bolivar <mbolivar@leaflabs.com>;
* Original implementation by Michael Hope
@ -84,7 +84,7 @@ typedef struct dma_reg_map {
* Register bit definitions
*/
/* Channel configuration register */
/* Stream configuration register */
#define DMA_CR_CH0 (0x0 << 25)
#define DMA_CR_CH1 (0x1 << 25)
@ -136,6 +136,25 @@ typedef struct dma_reg_map {
#define DMA_CR_DMEIE (0x1 << 1)
#define DMA_CR_EN (0x1)
typedef enum dma_channel {
DMA_CH0 = DMA_CR_CH0, /**< Channel 0 */
DMA_CH1 = DMA_CR_CH1, /**< Channel 1 */
DMA_CH2 = DMA_CR_CH2, /**< Channel 2 */
DMA_CH3 = DMA_CR_CH3, /**< Channel 3 */
DMA_CH4 = DMA_CR_CH4, /**< Channel 4 */
DMA_CH5 = DMA_CR_CH5, /**< Channel 5 */
DMA_CH6 = DMA_CR_CH6, /**< Channel 6 */
DMA_CH7 = DMA_CR_CH7, /**< Channel 7 */
} dma_channel;
/* Device interrupt status register flags */
#define DMA_ISR_TCIF (1 << 5)
#define DMA_ISR_HTIF (1 << 4)
#define DMA_ISR_TEIF (1 << 3)
#define DMA_ISR_DMEIF (1 << 2)
#define DMA_ISR_FEIF (1 << 0)
/*
* Devices
*/
@ -166,25 +185,35 @@ extern dma_dev *DMA2;
* Convenience functions
*/
void dma_init(dma_dev *dev);
extern void dma_init(dma_dev *dev);
/** Flags for DMA transfer configuration. */
typedef enum dma_mode_flags {
DMA_MEM_2_MEM = 1 << 14, /**< Memory to memory mode */
DMA_MINC_MODE = 1 << 7, /**< Auto-increment memory address */
DMA_PINC_MODE = 1 << 6, /**< Auto-increment peripheral address */
DMA_CIRC_MODE = 1 << 5, /**< Circular mode */
DMA_FROM_MEM = 1 << 4, /**< Read from memory to peripheral */
DMA_TRNS_ERR = 1 << 3, /**< Interrupt on transfer error */
DMA_HALF_TRNS = 1 << 2, /**< Interrupt on half-transfer */
DMA_TRNS_CMPLT = 1 << 1 /**< Interrupt on transfer completion */
DMA_MEM_BUF_0 = DMA_CR_CT0, /**< Current memory target buffer 0 */
DMA_MEM_BUF_1 = DMA_CR_CT1, /**< Current memory target buffer 1 */
DMA_DBL_BUF_MODE = DMA_CR_DBM, /**< Current memory double buffer mode */
DMA_PINC_OFFSET = DMA_CR_PINCOS, /**< Peripheral increment offset size */
DMA_MINC_MODE = DMA_CR_MINC, /**< Memory increment mode */
DMA_PINC_MODE = DMA_CR_PINC, /**< Peripheral increment mode */
DMA_CIRC_MODE = DMA_CR_CIRC, /**< Memory Circular mode */
DMA_FROM_PER = DMA_CR_DIR_P2M, /**< Read from memory to peripheral */
DMA_FROM_MEM = DMA_CR_DIR_M2P, /**< Read from memory to peripheral */
DMA_MEM_TO_MEM = DMA_CR_DIR_M2M, /**< Read from memory to memory */
DMA_PERIF_CTRL = DMA_CR_PFCTRL, /**< Peripheral flow controller */
DMA_PRIO_MEDIUM = DMA_CR_PL_MEDIUM, /**< Medium priority */
DMA_PRIO_HIGH = DMA_CR_PL_HIGH, /**< High priority */
DMA_PRIO_VERY_HIGH = DMA_CR_PL_VERY_HIGH, /**< Very high priority */
DMA_TRNS_CMPLT = DMA_CR_TCIE, /**< Interrupt on transfer completion */
DMA_TRNS_HALF = DMA_CR_HTIE, /**< Interrupt on half-transfer */
DMA_TRNS_ERR = DMA_CR_TEIE, /**< Interrupt on transfer error */
DMA_DIR_MODE_ERR = DMA_CR_DMEIE /**< Interrupt on direct mode error */
} dma_mode_flags;
/** Source and destination transfer sizes. */
typedef enum dma_xfer_size {
DMA_SIZE_8BITS = 0, /**< 8-bit transfers */
DMA_SIZE_16BITS = 1, /**< 16-bit transfers */
DMA_SIZE_32BITS = 2 /**< 32-bit transfers */
DMA_SIZE_8BITS = ( DMA_CR_MSIZE_8BITS|DMA_CR_PSIZE_8BITS ), /**< 8-bit transfers */
DMA_SIZE_16BITS = (DMA_CR_MSIZE_16BITS|DMA_CR_PSIZE_16BITS), /**< 16-bit transfers */
DMA_SIZE_32BITS = (DMA_CR_MSIZE_32BITS|DMA_CR_PSIZE_32BITS) /**< 32-bit transfers */
} dma_xfer_size;
/** DMA channel */
@ -201,17 +230,17 @@ typedef enum dma_stream {
static inline void dma_setup_transfer(dma_dev *dev,
dma_stream stream,
dma_channel channel,
dma_xfer_size trx_size,
__io void *peripheral_address,
__io void *memory_address0,
__io void *memory_address1,
uint32 flags,
uint32 fifo_flags) {
uint32 flags) {
dev->regs->STREAM[stream].CR &= ~DMA_CR_EN; // disable
dev->regs->STREAM[stream].PAR = (uint32)peripheral_address;
dev->regs->STREAM[stream].M0AR = (uint32)memory_address0;
dev->regs->STREAM[stream].M1AR = (uint32)memory_address1;
dev->regs->STREAM[stream].FCR = fifo_flags & 0x87; // mask out reserved bits
dev->regs->STREAM[stream].CR = flags & 0x0feffffe; // mask out reserved and enable
dev->regs->STREAM[stream].CR = ((flags|channel|trx_size) & 0x0feffffe); // mask out reserved and enable
}
static inline void dma_set_num_transfers(dma_dev *dev,
@ -220,6 +249,12 @@ static inline void dma_set_num_transfers(dma_dev *dev,
dev->regs->STREAM[stream].NDTR = num_transfers;
}
static inline void dma_set_fifo_flags(dma_dev *dev,
dma_stream stream,
uint8 fifo_flags) {
dev->regs->STREAM[stream].FCR = fifo_flags & 0x87; // mask out reserved bits
}
void dma_attach_interrupt(dma_dev *dev,
dma_stream stream,
void (*handler)(void));
@ -232,6 +267,7 @@ static inline void dma_enable(dma_dev *dev, dma_stream stream) {
static inline void dma_disable(dma_dev *dev, dma_stream stream) {
dev->regs->STREAM[stream].CR &= ~DMA_CR_EN;
while (dev->regs->STREAM[stream].CR & DMA_CR_EN); // wait till EN bit is reset, see AN4031, chapter 4.1
}
/**

View File

@ -40,6 +40,8 @@
#include "wirish.h"
#include "boards.h"
#define DMA_TIMEOUT 100
#if CYCLES_PER_MICROSECOND != 168
/* TODO [0.2.0?] something smarter than this */
#warning "Unexpected clock speed; SPI frequency calculation will be incorrect"
@ -115,27 +117,37 @@ SPIClass::SPIClass(uint32 spi_num) {
// Init things specific to each SPI device
// clock divider setup is a bit of hack, and needs to be improved at a later date.
/*****************************************************************************/
// DMA / Channel / Stream
// Rx Tx
// SPI1: 2 / 3 / 0 (2) - 2 / 3 / 3 (5)
// SPI2: 1 / 0 / 3 - 1 / 0 / 4
// SPI3: 1 / 0 / 0 (2) - 1 / 0 / 5 (7)
/*****************************************************************************/
_settings[0].spi_d = SPI1;
_settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock);
#ifdef SPI_DMA
_settings[0].spiDmaDev = DMA1;
_settings[0].spiTxDmaChannel = DMA_CH3;
_settings[0].spiRxDmaChannel = DMA_CH2;
_settings[0].spiDmaDev = DMA2;
_settings[0].spiDmaChannel = DMA_CH3;
_settings[0].spiRxDmaStream = DMA_STREAM0; // alternative: DMA_STREAM2
_settings[0].spiTxDmaStream = DMA_STREAM3; // alternative: DMA_STREAM5
#endif
_settings[1].spi_d = SPI2;
_settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock);
#ifdef SPI_DMA
_settings[1].spiDmaDev = DMA1;
_settings[1].spiTxDmaChannel = DMA_CH5;
_settings[1].spiRxDmaChannel = DMA_CH4;
_settings[1].spiDmaChannel = DMA_CH0;
_settings[1].spiRxDmaStream = DMA_STREAM3; // alternative: -
_settings[1].spiTxDmaStream = DMA_STREAM4; // alternative: -
#endif
#if BOARD_NR_SPI >= 3
_settings[2].spi_d = SPI3;
_settings[2].clockDivider = determine_baud_rate(_settings[2].spi_d, _settings[2].clock);
#ifdef SPI_DMA
_settings[2].spiDmaDev = DMA2;
_settings[2].spiTxDmaChannel = DMA_CH2;
_settings[2].spiRxDmaChannel = DMA_CH1;
_settings[2].spiDmaDev = DMA1;
_settings[2].spiDmaChannel = DMA_CH0;
_settings[2].spiRxDmaStream = DMA_STREAM0; // alternative: DMA_STREAM2
_settings[2].spiTxDmaStream = DMA_STREAM5; // alternative: DMA_STREAM7
#endif
#endif
@ -265,9 +277,6 @@ void SPIClass::beginTransaction(uint8_t pin, SPISettings settings)
#ifdef SPI_DEBUG
Serial.println("SPIClass::beginTransaction");
#endif
//_SSPin=pin;
//pinMode(_SSPin,OUTPUT);
//digitalWrite(_SSPin,LOW);
setBitOrder(settings.bitOrder);
setDataMode(settings.dataMode);
setDataSize(settings.dataSize);
@ -321,14 +330,23 @@ uint16 SPIClass::read(void)
void SPIClass::read(uint8 *buf, uint32 len)
{
spi_rx_reg(_currentSetting->spi_d); // clear the RX buffer in case a byte is waiting on it.
if ( len == 0 ) return;
spi_rx_reg(_currentSetting->spi_d); // clear the RX buffer in case a byte is waiting on it.
spi_reg_map * regs = _currentSetting->spi_d->regs;
// start sequence
while ( (len--)>0) {
regs->DR = 0x00FF; // " write the data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
while ( (regs->SR & SPI_SR_RXNE)==0 ) ; // wait till data is available in the Rx register
*buf++ = (uint8)(regs->DR); // read and store the received byte
}
// start sequence: write byte 0
regs->DR = 0x00FF; // write the first byte
// main loop
while ( (--len) ) {
while( !(regs->SR & SPI_SR_TXE) ); // wait for TXE flag
noInterrupts(); // go atomic level - avoid interrupts to surely get the previously received data
regs->DR = 0x00FF; // write the next data item to be transmitted into the SPI_DR register. This clears the TXE flag.
while ( !(regs->SR & SPI_SR_RXNE) ); // wait till data is available in the DR register
*buf++ = (uint8)(regs->DR); // read and store the received byte. This clears the RXNE flag.
interrupts(); // let systick do its job
}
// read remaining last byte
while ( !(regs->SR & SPI_SR_RXNE) ); // wait till data is available in the Rx register
*buf++ = (uint8)(regs->DR); // read and store the received byte
}
void SPIClass::write(uint16 data)
@ -393,47 +411,66 @@ uint16_t SPIClass::transfer16(uint16_t wr_data) const
uint8 SPIClass::dmaTransfer(void * transmitBuf, void * receiveBuf, uint16 length)
{
if (length == 0) return 0;
uint8 b = 0;
spi_rx_reg(_currentSetting->spi_d); //Clear the RX buffer in case a byte is waiting on it.
// dma1_ch3_Active=true;
dma_init(_currentSetting->spiDmaDev);
// dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event);
// RX
spi_rx_dma_enable(_currentSetting->spi_d);
dma_xfer_size dma_bit_size = (_currentSetting->dataSize==SPI_DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS;
dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size,
receiveBuf, dma_bit_size, (DMA_MINC_MODE | DMA_TRNS_CMPLT));// receive buffer DMA
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, length);
dma_setup_transfer( _currentSetting->spiDmaDev,
_currentSetting->spiRxDmaStream,
_currentSetting->spiDmaChannel,
dma_bit_size,
&_currentSetting->spi_d->regs->DR, // peripheral address
receiveBuf, // memory bank 0 address
NULL, // memory bank 1 address
(DMA_MINC_MODE | DMA_FROM_PER | DMA_PRIO_VERY_HIGH) // flags
);
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream, length);
dma_set_fifo_flags(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream, 0);
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream);
// TX
uint32 flags = (DMA_MINC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT);
spi_tx_dma_enable(_currentSetting->spi_d);
uint32 flags = (DMA_MINC_MODE | DMA_FROM_MEM); // | DMA_TRNS_CMPLT);
if ( transmitBuf==0 ) {
static uint8_t ff = 0XFF;
transmitBuf = &ff;
flags ^= DMA_MINC_MODE; // remove increment mode
flags &= ~((uint32)DMA_MINC_MODE); // remove increment mode
}
dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size,
transmitBuf, dma_bit_size, flags);// Transmit buffer DMA
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length);
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel);// enable receive
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit
dma_setup_transfer( _currentSetting->spiDmaDev,
_currentSetting->spiTxDmaStream,
_currentSetting->spiDmaChannel,
dma_bit_size,
&_currentSetting->spi_d->regs->DR, // peripheral address
transmitBuf, // memory bank 0 address
NULL, // memory bank 1 address
flags
);
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream, length);
dma_set_fifo_flags(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream, 0);
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);
// software enable sequence, see AN4031, chapter 4.3
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream);// enable receive
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);// enable transmit
spi_rx_reg(_currentSetting->spi_d); //Clear the RX buffer in case a byte is waiting on it.
spi_rx_dma_enable(_currentSetting->spi_d);
spi_tx_dma_enable(_currentSetting->spi_d); // must be the last enable to avoid DMA error flag
uint32_t m = millis();
while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & DMA_ISR_TCIF1)==0) {//Avoid interrupts and just loop waiting for the flag to be set.
while ((b = dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream) & DMA_ISR_TCIF)==0 ) {// wait for completion flag to be set
if ( b&(DMA_ISR_TEIF|DMA_ISR_DMEIF|DMA_ISR_FEIF) ) { b = 1; break; } // break on any error flag
if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; }
}
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
if (b & DMA_ISR_TCIF) b = 0;
while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel);
spi_rx_dma_disable(_currentSetting->spi_d); // And disable generation of DMA request from the SPI port so other peripherals can use the channels
// software disable sequence, see AN4031, chapter 4.1
spi_tx_dma_disable(_currentSetting->spi_d);
//uint16 x = spi_rx_reg(_currentSetting->spi_d); // dummy read, needed, don't remove!
spi_rx_dma_disable(_currentSetting->spi_d);
dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream);
dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);
return b;
}
@ -446,28 +483,36 @@ uint8 SPIClass::dmaTransfer(void * transmitBuf, void * receiveBuf, uint16 length
uint8 SPIClass::dmaSend(void * transmitBuf, uint16 length, bool minc)
{
if (length == 0) return 0;
uint32 flags = ( (DMA_MINC_MODE*minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT);
uint8 b = 0;
dma_init(_currentSetting->spiDmaDev);
// TX
spi_tx_dma_enable(_currentSetting->spi_d);
dma_xfer_size dma_bit_size = (_currentSetting->dataSize==SPI_DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS;
dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size,
transmitBuf, dma_bit_size, flags);// Transmit buffer DMA
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length);
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit
dma_setup_transfer( _currentSetting->spiDmaDev,
_currentSetting->spiTxDmaStream,
_currentSetting->spiDmaChannel,
dma_bit_size,
&_currentSetting->spi_d->regs->DR, // peripheral address
transmitBuf, // memory bank 0 address
NULL, // memory bank 1 address
( (DMA_MINC_MODE*minc) | DMA_FROM_MEM ) //| DMA_TRNS_CMPLT ) // flags
);// Transmit buffer DMA
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream, length);
dma_set_fifo_flags(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream, 0);
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);// enable transmit
spi_tx_dma_enable(_currentSetting->spi_d);
uint32_t m = millis();
while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & DMA_ISR_TCIF1)==0) {//Avoid interrupts and just loop waiting for the flag to be set.
while ((b = dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream) & DMA_ISR_TCIF)==0 ) {// wait for completion flag to be set
if ( b&(DMA_ISR_TEIF|DMA_ISR_DMEIF|DMA_ISR_FEIF) ) { b = 1; break; } // break on any error flag
if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; }
}
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
}
if (b & DMA_ISR_TCIF) b = 0;
while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
spi_tx_dma_disable(_currentSetting->spi_d);
//uint16 x = spi_rx_reg(_currentSetting->spi_d); // dummy read, needed, don't remove!
dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);
return b;
}
#endif
@ -507,18 +552,13 @@ uint8 SPIClass::nssPin(void) {
*/
uint8 SPIClass::send(uint8 data) {
uint8 buf[] = {data};
return this->send(buf, 1);
this->write(data);
return 1;
}
uint8 SPIClass::send(uint8 *buf, uint32 len) {
uint32 txed = 0;
uint8 ret = 0;
while (txed < len) {
this->write(buf[txed++]);
ret = this->read();
}
return ret;
this->write(buf, len);
return len;
}
uint8 SPIClass::recv(void) {
@ -640,4 +680,3 @@ static spi_baud_rate determine_baud_rate(spi_dev *dev, uint32_t freq) {
//SPIClass SPI(3);

View File

@ -42,6 +42,8 @@
#include <libmaple/dma.h>
#include <wirish.h>
#define SPI_DMA
// SPI_HAS_TRANSACTION means SPI has
// - beginTransaction()
// - endTransaction()
@ -135,19 +137,18 @@ private:
uint32_t dataSize;
spi_dev *spi_d;
//uint8_t _SSPin;
uint32_t clockDivider;
#ifdef SPI_DMA
dma_channel spiRxDmaChannel, spiTxDmaChannel;
dma_dev* spiDmaDev;
dma_channel spiDmaChannel;
dma_stream spiRxDmaStream, spiTxDmaStream;
#endif
friend class SPIClass;
};
/**
* @brief Wirish SPI interface.
*
@ -157,18 +158,11 @@ private:
class SPIClass {
public:
/**
* @param spiPortNumber Number of the SPI port to manage.
*/
SPIClass(uint32 spiPortNumber);
/*
* Set up/tear down
*/
/**
* @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0).
@ -396,5 +390,6 @@ private:
*/
};
extern SPIClass SPI;
#endif