Working check in of BASpiMemoryDMA for SPI0

master
Steve Lascos 7 years ago
parent c5383595c1
commit d3aa6667ce
  1. 52
      src/BASpiMemory.cpp
  2. 91
      src/BASpiMemory.h

@ -111,9 +111,9 @@ void BASpiMemory::write(size_t address, uint8_t data)
} }
// Single address write // Single address write
void BASpiMemory::write(size_t address, uint8_t *data, size_t numBytes) void BASpiMemory::write(size_t address, uint8_t *src, size_t numBytes)
{ {
uint8_t *dataPtr = data; uint8_t *dataPtr = src;
m_spi->beginTransaction(m_settings); m_spi->beginTransaction(m_settings);
digitalWrite(m_csPin, LOW); digitalWrite(m_csPin, LOW);
@ -157,9 +157,9 @@ void BASpiMemory::write16(size_t address, uint16_t data)
digitalWrite(m_csPin, HIGH); digitalWrite(m_csPin, HIGH);
} }
void BASpiMemory::write16(size_t address, uint16_t *data, size_t numWords) void BASpiMemory::write16(size_t address, uint16_t *src, size_t numWords)
{ {
uint16_t *dataPtr = data; uint16_t *dataPtr = src;
m_spi->beginTransaction(m_settings); m_spi->beginTransaction(m_settings);
digitalWrite(m_csPin, LOW); digitalWrite(m_csPin, LOW);
@ -208,9 +208,9 @@ uint8_t BASpiMemory::read(size_t address)
} }
void BASpiMemory::read(size_t address, uint8_t *data, size_t numBytes) void BASpiMemory::read(size_t address, uint8_t *dest, size_t numBytes)
{ {
uint8_t *dataPtr = data; uint8_t *dataPtr = dest;
m_spi->beginTransaction(m_settings); m_spi->beginTransaction(m_settings);
digitalWrite(m_csPin, LOW); digitalWrite(m_csPin, LOW);
@ -280,6 +280,8 @@ BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, size_t bufferSizeBytes)
// add 4 bytes to buffer for SPI CMD and 3 bytes of addresse // add 4 bytes to buffer for SPI CMD and 3 bytes of addresse
m_txBuffer = new uint8_t[bufferSizeBytes+4]; m_txBuffer = new uint8_t[bufferSizeBytes+4];
m_rxBuffer = new uint8_t[bufferSizeBytes+4]; m_rxBuffer = new uint8_t[bufferSizeBytes+4];
m_txTransfer = new DmaSpi::Transfer();
m_rxTransfer = new DmaSpi::Transfer();
} }
BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz, size_t bufferSizeBytes) BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz, size_t bufferSizeBytes)
@ -299,6 +301,8 @@ BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz, size_t
m_cs = new ActiveLowChipSelect(cs, m_settings); m_cs = new ActiveLowChipSelect(cs, m_settings);
m_txBuffer = new uint8_t[bufferSizeBytes+4]; m_txBuffer = new uint8_t[bufferSizeBytes+4];
m_rxBuffer = new uint8_t[bufferSizeBytes+4]; m_rxBuffer = new uint8_t[bufferSizeBytes+4];
m_txTransfer = new DmaSpi::Transfer();
m_rxTransfer = new DmaSpi::Transfer();
} }
BASpiMemoryDMA::~BASpiMemoryDMA() BASpiMemoryDMA::~BASpiMemoryDMA()
@ -306,6 +310,8 @@ BASpiMemoryDMA::~BASpiMemoryDMA()
delete m_cs; delete m_cs;
if (m_txBuffer) delete [] m_txBuffer; if (m_txBuffer) delete [] m_txBuffer;
if (m_rxBuffer) delete [] m_rxBuffer; if (m_rxBuffer) delete [] m_rxBuffer;
if (m_txTransfer) delete m_txTransfer;
if (m_rxTransfer) delete m_rxTransfer;
} }
void BASpiMemoryDMA::m_setSpiCmdAddr(int command, size_t address, uint8_t *dest) void BASpiMemoryDMA::m_setSpiCmdAddr(int command, size_t address, uint8_t *dest)
@ -355,12 +361,12 @@ void BASpiMemoryDMA::begin(void)
// SPI must build up a payload that starts the teh CMD/Address first. It will cycle // SPI must build up a payload that starts the teh CMD/Address first. It will cycle
// through the payloads in a circular buffer and use the transfer objects to check if they // through the payloads in a circular buffer and use the transfer objects to check if they
// are done before continuing. // are done before continuing.
void BASpiMemoryDMA::write(size_t address, uint8_t *data, size_t numBytes) void BASpiMemoryDMA::write(size_t address, uint8_t *src, size_t numBytes)
{ {
while ( m_txTransfer->busy()) {} // wait until not busy while ( m_txTransfer->busy()) {} // wait until not busy
uint16_t transferCount = numBytes + 4; // transfer must be increased by the SPI command and address uint16_t transferCount = numBytes + 4; // transfer must be increased by the SPI command and address
m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer); m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer);
memcpy(m_txBuffer+4, data, numBytes); memcpy(m_txBuffer+4, src, numBytes);
*m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs); *m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs);
m_spiDma->registerTransfer(*m_txTransfer); m_spiDma->registerTransfer(*m_txTransfer);
} }
@ -370,17 +376,18 @@ void BASpiMemoryDMA::zero(size_t address, size_t numBytes)
while ( m_txTransfer->busy()) {} while ( m_txTransfer->busy()) {}
uint16_t transferCount = numBytes + 4; uint16_t transferCount = numBytes + 4;
m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer); m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer);
*m_txTransfer = DmaSpi::Transfer(nullptr, transferCount, nullptr, 0, m_cs); memset(m_txBuffer+4, 0, numBytes);
*m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs);
m_spiDma->registerTransfer(*m_txTransfer); m_spiDma->registerTransfer(*m_txTransfer);
} }
void BASpiMemoryDMA::write16(size_t address, uint16_t *data, size_t numWords) void BASpiMemoryDMA::write16(size_t address, uint16_t *src, size_t numWords)
{ {
while ( m_txTransfer->busy()) {} while ( m_txTransfer->busy()) {}
size_t numBytes = sizeof(uint16_t)*numWords; size_t numBytes = sizeof(uint16_t)*numWords;
uint16_t transferCount = numBytes + 4; uint16_t transferCount = numBytes + 4;
m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer); m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer);
memcpy(m_txBuffer+4, data, numBytes); memcpy(m_txBuffer+4, src, numBytes);
*m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs); *m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs);
m_spiDma->registerTransfer(*m_txTransfer); m_spiDma->registerTransfer(*m_txTransfer);
} }
@ -402,7 +409,7 @@ void BASpiMemoryDMA::read(size_t address, uint8_t *dest, size_t numBytes)
while ( m_rxTransfer->busy()) {} while ( m_rxTransfer->busy()) {}
uint16_t transferCount = numBytes + 4; uint16_t transferCount = numBytes + 4;
m_setSpiCmdAddr(SPI_READ_CMD, address, m_rxBuffer); m_setSpiCmdAddr(SPI_READ_CMD, address, m_rxBuffer);
*m_rxTransfer = DmaSpi::Transfer(nullptr, transferCount, m_rxBuffer, 0, m_cs); *m_rxTransfer = DmaSpi::Transfer(m_rxBuffer, transferCount, m_rxBuffer, 0, m_cs);
m_spiDma->registerTransfer(*m_rxTransfer); m_spiDma->registerTransfer(*m_rxTransfer);
} }
@ -413,14 +420,29 @@ void BASpiMemoryDMA::read16(size_t address, uint16_t *dest, size_t numWords)
m_setSpiCmdAddr(SPI_READ_CMD, address, m_rxBuffer); m_setSpiCmdAddr(SPI_READ_CMD, address, m_rxBuffer);
size_t numBytes = sizeof(uint16_t)*numWords; size_t numBytes = sizeof(uint16_t)*numWords;
uint16_t transferCount = numBytes + 4; uint16_t transferCount = numBytes + 4;
*m_rxTransfer = DmaSpi::Transfer(nullptr, transferCount, m_rxBuffer, 0, m_cs); *m_rxTransfer = DmaSpi::Transfer(m_rxBuffer, transferCount, m_rxBuffer, 0, m_cs);
m_spiDma->registerTransfer(*m_rxTransfer); m_spiDma->registerTransfer(*m_rxTransfer);
} }
void BASpiMemoryDMA::readBufferContents(uint8_t *dest, size_t numBytes, size_t bufferOffset) bool BASpiMemoryDMA::isWriteBusy(void)
{
return m_txTransfer->busy();
}
bool BASpiMemoryDMA::isReadBusy(void)
{
return m_rxTransfer->busy();
}
void BASpiMemoryDMA::readBufferContents(uint16_t *dest, size_t numWords, size_t wordOffset)
{
readBufferContents(reinterpret_cast<uint8_t *>(dest), sizeof(uint16_t)*numWords, sizeof(uint16_t)*wordOffset);
}
void BASpiMemoryDMA::readBufferContents(uint8_t *dest, size_t numBytes, size_t byteOffset)
{ {
while (m_rxTransfer->busy()) {} // ensure transfer is complete while (m_rxTransfer->busy()) {} // ensure transfer is complete
memcpy(dest, m_rxBuffer+4+bufferOffset, numBytes); memcpy(dest, m_rxBuffer+4+byteOffset, numBytes);
} }
} /* namespace BAGuitar */ } /* namespace BAGuitar */

@ -49,25 +49,51 @@ public:
BASpiMemory(SpiDeviceId memDeviceId, uint32_t speedHz); BASpiMemory(SpiDeviceId memDeviceId, uint32_t speedHz);
virtual ~BASpiMemory(); virtual ~BASpiMemory();
/// initialize and configure the SPI peripheral
virtual void begin(); virtual void begin();
/// write a single data word to the specified address /// write a single 8-bit word to the specified address
/// @param address the address in the SPI RAM to write to /// @param address the address in the SPI RAM to write to
/// @param data the value to write /// @param data the value to write
void write(size_t address, uint8_t data); void write(size_t address, uint8_t data);
virtual void write(size_t address, uint8_t *data, size_t numBytes);
/// Write a block of 8-bit data to the specified address
/// @param address the address in the SPI RAM to write to
/// @param src pointer to the source data block
/// @param numBytes size of the data block in bytes
virtual void write(size_t address, uint8_t *src, size_t numBytes);
/// Write a block of zeros to the specified address
/// @param address the address in the SPI RAM to write to
/// @param numBytes size of the data block in bytes
virtual void zero(size_t address, size_t numBytes); virtual void zero(size_t address, size_t numBytes);
/// write a single 16-bit word to the specified address
/// @param address the address in the SPI RAM to write to
/// @param data the value to write
void write16(size_t address, uint16_t data); void write16(size_t address, uint16_t data);
virtual void write16(size_t address, uint16_t *data, size_t numWords);
/// Write a block of 16-bit data to the specified address
/// @param address the address in the SPI RAM to write to
/// @param src pointer to the source data block
/// @param numWords size of the data block in 16-bit words
virtual void write16(size_t address, uint16_t *src, size_t numWords);
/// Write a block of 16-bit zeros to the specified address
/// @param address the address in the SPI RAM to write to
/// @param numWords size of the data block in 16-bit words
virtual void zero16(size_t address, size_t numWords); virtual void zero16(size_t address, size_t numWords);
/// read a single 8-bit data word from the specified address /// read a single 8-bit data word from the specified address
/// @param address the address in the SPI RAM to read from /// @param address the address in the SPI RAM to read from
/// @return the data that was read /// @return the data that was read
uint8_t read(size_t address); uint8_t read(size_t address);
virtual void read(size_t address, uint8_t *data, size_t numBytes);
/// Read a block of 8-bit data from the specified address
/// @param address the address in the SPI RAM to write to
/// @param dest pointer to the destination
/// @param numBytes size of the data block in bytes
virtual void read(size_t address, uint8_t *dest, size_t numBytes);
/// read a single 16-bit data word from the specified address /// read a single 16-bit data word from the specified address
/// @param address the address in the SPI RAM to read from /// @param address the address in the SPI RAM to read from
@ -80,6 +106,8 @@ public:
/// @param numWords the number of 16-bit words to transfer /// @param numWords the number of 16-bit words to transfer
virtual void read16(size_t address, uint16_t *dest, size_t numWords); virtual void read16(size_t address, uint16_t *dest, size_t numWords);
/// Check if the class has been configured by a previous begin() call
/// @returns true if initialized, false if not yet initialized
bool isStarted() const { return m_started; } bool isStarted() const { return m_started; }
protected: protected:
@ -96,11 +124,13 @@ protected:
class BASpiMemoryDMA : public BASpiMemory { class BASpiMemoryDMA : public BASpiMemory {
public: public:
BASpiMemoryDMA() = delete; BASpiMemoryDMA() = delete;
/// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2). /// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2).
/// @details default is 20 Mhz /// @details default is 20 Mhz
/// @param memDeviceId specify which MEM to control with SpiDeviceId. /// @param memDeviceId specify which MEM to control with SpiDeviceId.
/// @param bufferSize size of buffer to store DMA transfers /// @param bufferSize size of buffer to store DMA transfers
BASpiMemoryDMA(SpiDeviceId memDeviceId, size_t bufferSizeBytes); BASpiMemoryDMA(SpiDeviceId memDeviceId, size_t bufferSizeBytes);
/// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2) /// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2)
/// @param memDeviceId specify which MEM to control with SpiDeviceId. /// @param memDeviceId specify which MEM to control with SpiDeviceId.
/// @param speedHz specify the desired speed in Hz. /// @param speedHz specify the desired speed in Hz.
@ -108,14 +138,35 @@ public:
BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz, size_t bufferSizeBytes); BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz, size_t bufferSizeBytes);
virtual ~BASpiMemoryDMA(); virtual ~BASpiMemoryDMA();
void write(size_t address, uint8_t *data, size_t numBytes) override; /// initialize and configure the SPI peripheral
void begin() override;
/// Write a block of 8-bit data to the specified address
/// @param address the address in the SPI RAM to write to
/// @param src pointer to the source data block
/// @param numBytes size of the data block in bytes
void write(size_t address, uint8_t *src, size_t numBytes) override;
/// Write a block of zeros to the specified address
/// @param address the address in the SPI RAM to write to
/// @param numBytes size of the data block in bytes
void zero(size_t address, size_t numBytes) override; void zero(size_t address, size_t numBytes) override;
void write16(size_t address, uint16_t *data, size_t numWords) override;
/// Write a block of 16-bit data to the specified address
/// @param address the address in the SPI RAM to write to
/// @param src pointer to the source data block
/// @param numWords size of the data block in 16-bit words
void write16(size_t address, uint16_t *src, size_t numWords) override;
/// Write a block of 16-bit zeros to the specified address
/// @param address the address in the SPI RAM to write to
/// @param numWords size of the data block in 16-bit words
void zero16(size_t address, size_t numWords) override; void zero16(size_t address, size_t numWords) override;
/// read a single 8-bit data word from the specified address /// Read a block of 8-bit data from the specified address
/// @param address the address in the SPI RAM to read from /// @param address the address in the SPI RAM to write to
/// @return the data that was read /// @param dest pointer to the destination
/// @param numBytes size of the data block in bytes
void read(size_t address, uint8_t *dest, size_t numBytes) override; void read(size_t address, uint8_t *dest, size_t numBytes) override;
/// read a block 16-bit data word from the specified address /// read a block 16-bit data word from the specified address
@ -124,9 +175,25 @@ public:
/// @param numWords the number of 16-bit words to transfer /// @param numWords the number of 16-bit words to transfer
void read16(size_t address, uint16_t *dest, size_t numWords) override; void read16(size_t address, uint16_t *dest, size_t numWords) override;
/// Check if a DMA write is in progress
void begin() override; /// @returns true if a write DMA is in progress, else false
void readBufferContents(uint8_t *dest, size_t numBytes, size_t bufferOffset = 0); bool isWriteBusy();
/// Check if a DMA read is in progress
/// @returns true if a read DMA is in progress, else false
bool isReadBusy();
/// Readout the 8-bit contents of the DMA storage buffer to the specified destination
/// @param dest pointer to the destination
/// @param numBytes number of bytes to read out
/// @param byteOffset, offset from the start of the DMA buffer in bytes to begin reading
void readBufferContents(uint8_t *dest, size_t numBytes, size_t byteOffset = 0);
/// Readout the 8-bit contents of the DMA storage buffer to the specified destination
/// @param dest pointer to the destination
/// @param numWords number of 16-bit words to read out
/// @param wordOffset, offset from the start of the DMA buffer in words to begin reading
void readBufferContents(uint16_t *dest, size_t numWords, size_t wordOffset = 0);
private: private:
AbstractDmaSpi<DmaSpi0, SPIClass, SPI> *m_spiDma = nullptr; AbstractDmaSpi<DmaSpi0, SPIClass, SPI> *m_spiDma = nullptr;

Loading…
Cancel
Save