Merge branch 'stevstrong-F1_SPI_development'

This commit is contained in:
Roger Clark 2017-06-06 21:03:33 +10:00
commit 8423fb9807
8 changed files with 180 additions and 227 deletions

2
.gitignore vendored
View File

@ -7,3 +7,5 @@ other/maple-bootloader/build
other/maple-bootloader/*~
*.o
tools/src/stm32flash_serial/src/parsers/parsers.a
*.bak
*.1

View File

@ -341,7 +341,6 @@ void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *addr) {
* @see dma_attach_interrupt()
* @see dma_enable()
*/
__deprecated
void dma_setup_transfer(dma_dev *dev,
dma_channel channel,
__io void *peripheral_address,

View File

@ -84,7 +84,7 @@ void spi_slave_enable(spi_dev *dev, spi_mode mode, uint32 flags) {
}
/**
* @brief Nonblocking SPI transmit.
* @brief Blocking SPI transmit.
* @param dev SPI port to use for transmission
* @param buf Buffer to transmit. The sizeof buf's elements are
* inferred from dev's data frame format (i.e., are
@ -93,15 +93,21 @@ void spi_slave_enable(spi_dev *dev, spi_mode mode, uint32 flags) {
* @return Number of elements transmitted.
*/
uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len) {
uint32 txed = 0;
uint8 byte_frame = spi_dff(dev) == SPI_DFF_8_BIT;
while (spi_is_tx_empty(dev) && (txed < len)) {
if (byte_frame) {
dev->regs->DR = ((const uint8*)buf)[txed++];
} else {
dev->regs->DR = ((const uint16*)buf)[txed++];
}
}
uint32 txed = len;
spi_reg_map *regs = dev->regs;
if ( spi_dff(dev) == SPI_DFF_8_BIT ) {
const uint8 * dp8 = (const uint8*)buf;
while ( len-- ) {
while ( (regs->SR & SPI_SR_TXE)==0 ) ; //while ( spi_is_tx_empty(dev)==0 ); // wait Tx to be empty
regs->DR = *dp8++;
}
} else {
const uint16 * dp16 = (const uint16*)buf;
while ( len-- ) {
while ( (regs->SR & SPI_SR_TXE)==0 ) ; //while ( spi_is_tx_empty(dev)==0 ); // wait Tx to be empty
regs->DR = *dp16++;
}
}
return txed;
}

View File

@ -36,7 +36,7 @@ Adafruit_ILI9341_STM::Adafruit_ILI9341_STM(int8_t cs, int8_t dc, int8_t rst) : A
}
void Adafruit_ILI9341_STM::spiwrite(uint8_t c) {
void Adafruit_ILI9341_STM::spiwrite(uint16_t c) {
//Serial.print("0x"); Serial.print(c, HEX); Serial.print(", ");
@ -178,10 +178,7 @@ void Adafruit_ILI9341_STM::begin(void) {
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
#elif defined (__STM32F1__)
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV2);
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
SPI.beginTransaction(SPISettings(36000000));
#elif defined (__arm__)
SPI.begin();
@ -335,6 +332,7 @@ void Adafruit_ILI9341_STM::begin(void) {
if (hwSPI) spi_begin();
writecommand(ILI9341_DISPON); //Display on
if (hwSPI) spi_end();
if (hwSPI) SPI.setDataSize(SPI_CR1_DFF);
}
@ -345,18 +343,14 @@ void Adafruit_ILI9341_STM::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1,
writecommand(ILI9341_CASET); // Column addr set
*dcport |= dcpinmask;
*csport &= ~cspinmask;
SPI.setDataSize (SPI_CR1_DFF);
SPI.write(x0);
SPI.write(x1);
// SPI.setDataSize (0);
writecommand(ILI9341_PASET); // Row addr set
*dcport |= dcpinmask;
*csport &= ~cspinmask;
// SPI.setDataSize (SPI_CR1_DFF);
SPI.write(y0);
SPI.write(y1);
SPI.setDataSize (0);
writecommand(ILI9341_RAMWR); // write to RAM
@ -385,7 +379,6 @@ void Adafruit_ILI9341_STM::pushColor(uint16_t color) {
//digitalWrite(_cs, LOW);
*csport &= ~cspinmask;
spiwrite(color >> 8);
spiwrite(color);
*csport |= cspinmask;
@ -403,7 +396,6 @@ void Adafruit_ILI9341_STM::drawPixel(int16_t x, int16_t y, uint16_t color) {
*dcport |= dcpinmask;
*csport &= ~cspinmask;
spiwrite(color >> 8);
spiwrite(color);
*csport |= cspinmask;
@ -431,10 +423,8 @@ void Adafruit_ILI9341_STM::drawFastVLine(int16_t x, int16_t y, int16_t h,
*csport &= ~cspinmask;
#if defined (__STM32F1__)
SPI.setDataSize (SPI_CR1_DFF); // Set SPI 16bit mode
lineBuffer[0] = color;
SPI.dmaSend(lineBuffer, h, 0);
SPI.setDataSize (0);
#else
uint8_t hi = color >> 8, lo = color;
while (h--) {
@ -464,10 +454,8 @@ void Adafruit_ILI9341_STM::drawFastHLine(int16_t x, int16_t y, int16_t w,
*csport &= ~cspinmask;
#if defined (__STM32F1__)
SPI.setDataSize (SPI_CR1_DFF); // Set spi 16bit mode
lineBuffer[0] = color;
SPI.dmaSend(lineBuffer, w, 0);
SPI.setDataSize (0);
#else
uint8_t hi = color >> 8, lo = color;
while (w--) {
@ -485,11 +473,9 @@ void Adafruit_ILI9341_STM::fillScreen(uint16_t color) {
setAddrWindow(0, 0, _width - 1, _height - 1);
*dcport |= dcpinmask;
*csport &= ~cspinmask;
SPI.setDataSize (SPI_CR1_DFF); // Set spi 16bit mode
lineBuffer[0] = color;
SPI.dmaSend(lineBuffer, (65535), 0);
SPI.dmaSend(lineBuffer, ((_width * _height) - 65535), 0);
SPI.setDataSize (0);
#else
fillRect(0, 0, _width, _height, color);
@ -515,7 +501,6 @@ void Adafruit_ILI9341_STM::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
*dcport |= dcpinmask;
*csport &= ~cspinmask;
#if defined (__STM32F1__)
SPI.setDataSize (SPI_CR1_DFF); // Set spi 16bit mode
lineBuffer[0] = color;
if (w*h <= 65535) {
SPI.dmaSend(lineBuffer, (w*h), 0);
@ -524,7 +509,6 @@ void Adafruit_ILI9341_STM::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
SPI.dmaSend(lineBuffer, (65535), 0);
SPI.dmaSend(lineBuffer, ((w*h) - 65535), 0);
}
SPI.setDataSize (0);
#else
uint8_t hi = color >> 8, lo = color;
for(y=h; y>0; y--)
@ -672,6 +656,7 @@ uint16_t Adafruit_ILI9341_STM::color565(uint8_t r, uint8_t g, uint8_t b) {
void Adafruit_ILI9341_STM::setRotation(uint8_t m) {
if (hwSPI) spi_begin();
if (hwSPI) SPI.setDataSize(0);
writecommand(ILI9341_MADCTL);
rotation = m % 4; // can't be higher than 3
switch (rotation) {
@ -696,6 +681,7 @@ void Adafruit_ILI9341_STM::setRotation(uint8_t m) {
_height = ILI9341_TFTWIDTH;
break;
}
if (hwSPI) SPI.setDataSize(SPI_CR1_DFF);
if (hwSPI) spi_end();
}

View File

@ -11,6 +11,10 @@ This library has been modified for the Maple Mini
#include <Adafruit_GFX_AS.h>
#include <avr/pgmspace.h>
#ifndef swap
#define swap(a, b) { int16_t t = a; a = b; b = t; }
#endif
#define ILI9341_TFTWIDTH 240
#define ILI9341_TFTHEIGHT 320
@ -125,7 +129,7 @@ class Adafruit_ILI9341_STM : public Adafruit_GFX {
void dummyclock(void);
*/
void spiwrite(uint8_t),
void spiwrite(uint16_t),
writecommand(uint8_t c),
writedata(uint8_t d),
commandList(uint8_t *addr);

View File

@ -41,6 +41,8 @@
#include "boards.h"
//#include "HardwareSerial.h"
/** Time in ms for DMA receive timeout */
#define DMA_TIMEOUT 100
#if CYCLES_PER_MICROSECOND != 72
/* TODO [0.2.0?] something smarter than this */
@ -133,9 +135,8 @@ SPIClass::SPIClass(uint32 spi_num) {
_settings[2].spiDmaDev = DMA2;
_settings[2].spiTxDmaChannel = DMA_CH2;
_settings[2].spiRxDmaChannel = DMA_CH1;
#endif
//pinMode(BOARD_SPI_DEFAULT_SS,OUTPUT);
#endif
}
/*
@ -158,7 +159,7 @@ void SPIClass::begin(void) {
void SPIClass::beginSlave(void) {
spi_init(_currentSetting->spi_d);
configure_gpios(_currentSetting->spi_d, 0);
uint32 flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize | SPI_SW_SLAVE);
uint32 flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize | SPI_RX_ONLY);
#ifdef SPI_DEBUG
Serial.print("spi_slave_enable("); Serial.print(_currentSetting->dataMode); Serial.print(","); Serial.print(flags); Serial.println(")");
#endif
@ -212,8 +213,10 @@ void SPIClass::setBitOrder(BitOrder bitOrder)
void SPIClass::setDataSize(uint32 datasize)
{
_currentSetting->dataSize = datasize;
uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_DFF);
_currentSetting->spi_d->regs->CR1 = cr1 | (datasize & SPI_CR1_DFF);
uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_DFF);
uint8 en = spi_is_enabled(_currentSetting->spi_d);
spi_peripheral_disable(_currentSetting->spi_d);
_currentSetting->spi_d->regs->CR1 = cr1 | (datasize & SPI_CR1_DFF) | en;
}
void SPIClass::setDataMode(uint8_t dataMode)
@ -256,9 +259,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);
@ -304,138 +304,134 @@ void SPIClass::endTransaction(void)
* I/O
*/
uint8 SPIClass::read(void) {
uint8 buf[1];
this->read(buf, 1);
return buf[0];
uint16 SPIClass::read(void)
{
while ( spi_is_rx_nonempty(_currentSetting->spi_d)==0 ) ;
return (uint16)spi_rx_reg(_currentSetting->spi_d);
}
void SPIClass::read(uint8 *buf, uint32 len) {
uint32 rxed = 0;
while (rxed < len) {
while (!spi_is_rx_nonempty(_currentSetting->spi_d))
;
buf[rxed++] = (uint8)spi_rx_reg(_currentSetting->spi_d);
}
void SPIClass::read(uint8 *buf, uint32 len)
{
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: 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) {
// this->write(&data, 1);
void SPIClass::write(uint16 data)
{
/* Added for 16bit data Victor Perez. Roger Clark
* Improved speed by just directly writing the single byte to the SPI data reg and wait for completion, * by taking the Tx code from transfer(byte)
* The original method, of calling write(*data, length) .
* Improved speed by just directly writing the single byte to the SPI data reg and wait for completion,
* by taking the Tx code from transfer(byte)
* This almost doubles the speed of this function.
*/
spi_tx_reg(_currentSetting->spi_d, data); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
spi_tx_reg(_currentSetting->spi_d, data); // write the data to be transmitted into the SPI_DR register (this clears the TXE flag)
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."
}
//void SPIClass::write(uint8 byte) {
// this->write(&byte, 1);
/* Roger Clark
* Improved speed by just directly writing the single byte to the SPI data reg and wait for completion, * by taking the Tx code from transfer(byte)
* The original method, of calling write(*data, length) .
* This almost doubles the speed of this function.
*/
// spi_tx_reg(_currentSetting->spi_d, byte); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
// 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."
//}
void SPIClass::write(const uint8 *data, uint32 length) {
uint32 txed = 0;
while (txed < length) {
txed += spi_tx(_currentSetting->spi_d, data + txed, length - txed);
}
while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "4. After writing the last data item into the SPI_DR register, wait until TXE=1 ..."
while (spi_is_busy(_currentSetting->spi_d) != 0); // "... then wait until BSY=0, this indicates that the transmission of the last data is complete."
// taken from SdSpiSTM32F1.cpp - Victor's lib, and adapted to support device selection
if (spi_is_rx_nonempty(_currentSetting->spi_d)) {
uint8_t b = spi_rx_reg(_currentSetting->spi_d);
void SPIClass::write(uint16 data, uint32 n)
{
// Added by stevstrong: Repeatedly send same data by the specified number of times
spi_reg_map * regs = _currentSetting->spi_d->regs;
while ( (n--)>0 ) {
regs->DR = data; // write the data to be transmitted into the SPI_DR register (this clears the TXE flag)
while ( (regs->SR & SPI_SR_TXE)==0 ) ; // wait till Tx empty
}
while ( (regs->SR & SPI_SR_BSY) != 0); // wait until BSY=0 before returning
}
uint16_t SPIClass::transfer16(uint16_t wr_data) const {
spi_tx_reg(_currentSetting->spi_d, wr_data); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
while (spi_is_rx_nonempty(_currentSetting->spi_d) == 0); // "4. Wait until RXNE=1 ..."
uint16_t rd_data = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data."
// 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."
return rd_data;
void SPIClass::write(void *data, uint32 length)
{
spi_dev * spi_d = _currentSetting->spi_d;
spi_tx(spi_d, (void*)data, length); // data can be array of bytes or words
while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
}
uint8 SPIClass::transfer(uint8 byte) const {
spi_tx_reg(_currentSetting->spi_d, byte); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
while (spi_is_rx_nonempty(_currentSetting->spi_d) == 0); // "4. Wait until RXNE=1 ..."
uint8 b = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data."
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."
return b;
uint8 SPIClass::transfer(uint8 byte) const
{
spi_dev * spi_d = _currentSetting->spi_d;
spi_rx_reg(spi_d); // read any previous data
spi_tx_reg(spi_d, byte); // Write the data item to be transmitted into the SPI_DR register
while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
return (uint8)spi_rx_reg(spi_d); // "... and read the last received data."
}
uint16_t SPIClass::transfer16(uint16_t wr_data) const
{
spi_dev * spi_d = _currentSetting->spi_d;
spi_rx_reg(spi_d); // read any previous data
spi_tx_reg(spi_d, wr_data); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
return (uint16)spi_rx_reg(spi_d); // "... and read the last received data."
}
/* Roger Clark and Victor Perez, 2015
* Performs a DMA SPI transfer with at least a receive buffer.
* If a TX buffer is not provided, FF is sent over and over for the lenght of the transfer.
* On exit TX buffer is not modified, and RX buffer cotains the received data.
* If a TX buffer is not provided, FF is sent over and over for the length of the transfer.
* On exit TX buffer is not modified, and RX buffer contains the received data.
* Still in progress.
*/
uint8 SPIClass::dmaTransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint16 length) {
uint8 SPIClass::dmaTransfer(void * transmitBuf, void * receiveBuf, uint16 length)
{
if (length == 0) return 0;
uint8 b = 0;
if (spi_is_rx_nonempty(_currentSetting->spi_d) == 1) b = 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_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_8BITS,
receiveBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_TRNS_CMPLT));// receive buffer DMA
dma_xfer_size dma_bit_size = (_currentSetting->dataSize==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));// receive buffer DMA
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, length);
// TX
spi_tx_dma_enable(_currentSetting->spi_d);
if (!transmitBuf) {
static uint8_t ff = 0XFF;
transmitBuf = &ff;
dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_8BITS,
transmitBuf, DMA_SIZE_8BITS, (DMA_FROM_MEM | DMA_TRNS_CMPLT));// Transmit FF repeatedly
}
else {
dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_8BITS,
transmitBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT));// 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
// while (dma1_ch3_Active);
// if (receiveBuf) {
uint32_t m = millis();
while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & 0x2)==0) {//Avoid interrupts and just loop waiting for the flag to be set.
if ((millis() - m) > 100) {
// dma1_ch3_Active = 0;
b = 2;
break;
}
}
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
// }
// TX
uint32 flags = (DMA_MINC_MODE | DMA_FROM_MEM);
if ( transmitBuf==0 ) {
static uint8_t ff = 0XFF;
transmitBuf = &ff;
flags ^= 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_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// 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.
//delayMicroseconds(10);
if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; }
}
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
spi_tx_dma_disable(_currentSetting->spi_d);
if (spi_is_rx_nonempty(_currentSetting->spi_d) != 0){; // "4. Wait until RXNE=1 ..."
uint8 x = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data."
}
spi_rx_dma_disable(_currentSetting->spi_d); // And disable generation of DMA request from the SPI port so other peripherals can use the channels
dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel);
return b;
}
@ -443,66 +439,36 @@ uint8 SPIClass::dmaTransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint16 length
* Performs a DMA SPI send using a TX buffer.
* On exit TX buffer is not modified.
* Still in progress.
* 2016 - stevstrong - reworked to automatically detect bit size from SPI setting
*/
uint8 SPIClass::dmaSend(uint8 *transmitBuf, uint16 length, bool minc) {
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);
uint32 flags = ( (DMA_MINC_MODE*minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT);
uint8 b = 0;
// dma1_ch3_Active=true;
dma_init(_currentSetting->spiDmaDev);
// dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event);
// TX
spi_tx_dma_enable(_currentSetting->spi_d);
dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_8BITS,
transmitBuf, DMA_SIZE_8BITS, flags);// Transmit buffer DMA
dma_xfer_size dma_bit_size = (_currentSetting->dataSize==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
// while (dma1_ch3_Active);
while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & 0x2)==0); //Avoid interrupts and just loop waiting for the flag to be set.
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// 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.
//delayMicroseconds(10);
if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; }
}
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);
if (spi_is_rx_nonempty(_currentSetting->spi_d) != 0){; // "4. Wait until RXNE=1 ..."
uint8 x = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data."
}
return b;
}
uint8 SPIClass::dmaSend(uint16 *transmitBuf, uint16 length, bool minc) {
if (length == 0) return 0;
uint32 flags = ((DMA_MINC_MODE * minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT);
uint8 b;
dma1_ch3_Active=true;
dma_init(_currentSetting->spiDmaDev);
// dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event);
// TX
spi_tx_dma_enable(_currentSetting->spi_d);
dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_16BITS,
transmitBuf, DMA_SIZE_16BITS, flags);// Transmit buffer DMA
dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length);
dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit
// while (dma1_ch3_Active);
while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & 0x2)==0); //Avoid interrupts and just loop waiting for the flag to be set.
dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);
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);
if (spi_is_rx_nonempty(_currentSetting->spi_d) != 0){; // "4. Wait until RXNE=1 ..."
b = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data."
}
return b;
return b;
}
void SPIClass::attachInterrupt(void) {
// Should be enableInterrupt()
}
@ -536,18 +502,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) {

View File

@ -115,6 +115,13 @@ public:
init_MightInline(clock, bitOrder, dataMode, dataSize);
}
}
SPISettings(uint32_t clock) {
if (__builtin_constant_p(clock)) {
init_AlwaysInline(clock, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT);
} else {
init_MightInline(clock, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT);
}
}
SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT); }
private:
void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) {
@ -216,40 +223,40 @@ public:
*/
/**
* @brief Return the next unread byte.
* @brief Return the next unread byte/word.
*
* If there is no unread byte waiting, this function will block
* If there is no unread byte/word waiting, this function will block
* until one is received.
*/
uint8 read(void);
uint16 read(void);
/**
* @brief Read length bytes, storing them into buffer.
* @param buffer Buffer to store received bytes into.
* @param length Number of bytes to store in buffer. This
* @param length Number of bytes to store in buffer. This
* function will block until the desired number of
* bytes have been read.
*/
void read(uint8 *buffer, uint32 length);
/**
* @brief Transmit a byte.
* @param data Byte to transmit.
*/
// void write(uint8 data);
/**
* @brief Transmit a half word.
* @brief Transmit one byte/word.
* @param data to transmit.
*/
void write(uint16 data);
/**
* @brief Transmit multiple bytes.
* @param buffer Bytes to transmit.
* @param length Number of bytes in buffer to transmit.
* @brief Transmit one byte/word a specified number of times.
* @param data to transmit.
*/
void write(const uint8 *buffer, uint32 length);
void write(uint16 data, uint32 n);
/**
* @brief Transmit multiple bytes/words.
* @param buffer Bytes/words to transmit.
* @param length Number of bytes/words in buffer to transmit.
*/
void write(void * buffer, uint32 length);
/**
* @brief Transmit a byte, then return the next unread byte.
@ -264,6 +271,7 @@ public:
/**
* @brief Sets up a DMA Transfer for "length" bytes.
* The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting.
*
* This function transmits and receives to buffers.
*
@ -271,30 +279,18 @@ public:
* @param receiveBuf buffer Bytes to save received data.
* @param length Number of bytes in buffer to transmit.
*/
uint8 dmaTransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint16 length);
uint8 dmaTransfer(void * transmitBuf, void * receiveBuf, uint16 length);
/**
* @brief Sets up a DMA Transmit for bytes.
* @brief Sets up a DMA Transmit for SPI 8 or 16 bit transfer mode.
* The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting.
*
* This function transmits and does not care about the RX fifo.
*
* @param transmitBuf buffer Bytes to transmit,
* @param length Number of bytes in buffer to transmit.
* @param minc Set to use Memory Increment mode, clear to use Circular mode.
*/
uint8 dmaSend(uint8 *transmitBuf, uint16 length, bool minc = 1);
/**
* @brief Sets up a DMA Transmit for half words.
* SPI PERFIPHERAL MUST BE SET TO 16 BIT MODE BEFORE
*
* This function transmits and does not care about the RX fifo.
* This function only transmits and does not care about the RX fifo.
*
* @param data buffer half words to transmit,
* @param length Number of bytes in buffer to transmit.
* @param minc Set to use Memory Increment mode (default if blank), clear to use Circular mode.
*/
uint8 dmaSend(uint16 *transmitBuf, uint16 length, bool minc = 1);
uint8 dmaSend(void * transmitBuf, uint16 length, bool minc = 1);
/*
* Pin accessors

View File

@ -559,7 +559,6 @@ typedef enum dma_mode_flags {
*
* (It's not possible to fully configure a DMA stream on F2 with just
* this information, so this interface is too tied to the F1.) */
__deprecated
void dma_setup_transfer(dma_dev *dev,
dma_channel channel,
__io void *peripheral_address,