From d3aa6667ceb2cc6241e739fcb455ac74fa68a144 Mon Sep 17 00:00:00 2001 From: Steve Lascos Date: Sat, 10 Feb 2018 12:41:16 -0500 Subject: [PATCH] Working check in of BASpiMemoryDMA for SPI0 --- src/BASpiMemory.cpp | 52 ++++++++++++++++++-------- src/BASpiMemory.h | 91 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 116 insertions(+), 27 deletions(-) diff --git a/src/BASpiMemory.cpp b/src/BASpiMemory.cpp index 0d9d1fd..e970940 100644 --- a/src/BASpiMemory.cpp +++ b/src/BASpiMemory.cpp @@ -111,9 +111,9 @@ void BASpiMemory::write(size_t address, uint8_t data) } // 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); digitalWrite(m_csPin, LOW); @@ -157,9 +157,9 @@ void BASpiMemory::write16(size_t address, uint16_t data) 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); 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); 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 m_txBuffer = 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) @@ -299,6 +301,8 @@ BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz, size_t m_cs = new ActiveLowChipSelect(cs, m_settings); m_txBuffer = new uint8_t[bufferSizeBytes+4]; m_rxBuffer = new uint8_t[bufferSizeBytes+4]; + m_txTransfer = new DmaSpi::Transfer(); + m_rxTransfer = new DmaSpi::Transfer(); } BASpiMemoryDMA::~BASpiMemoryDMA() @@ -306,6 +310,8 @@ BASpiMemoryDMA::~BASpiMemoryDMA() delete m_cs; if (m_txBuffer) delete [] m_txBuffer; 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) @@ -355,12 +361,12 @@ void BASpiMemoryDMA::begin(void) // 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 // 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 uint16_t transferCount = numBytes + 4; // transfer must be increased by the SPI command and address 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_spiDma->registerTransfer(*m_txTransfer); } @@ -370,17 +376,18 @@ void BASpiMemoryDMA::zero(size_t address, size_t numBytes) while ( m_txTransfer->busy()) {} uint16_t transferCount = numBytes + 4; 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); } -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()) {} size_t numBytes = sizeof(uint16_t)*numWords; uint16_t transferCount = numBytes + 4; 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_spiDma->registerTransfer(*m_txTransfer); } @@ -402,7 +409,7 @@ void BASpiMemoryDMA::read(size_t address, uint8_t *dest, size_t numBytes) while ( m_rxTransfer->busy()) {} uint16_t transferCount = numBytes + 4; 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); } @@ -413,14 +420,29 @@ void BASpiMemoryDMA::read16(size_t address, uint16_t *dest, size_t numWords) m_setSpiCmdAddr(SPI_READ_CMD, address, m_rxBuffer); size_t numBytes = sizeof(uint16_t)*numWords; 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); } -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(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 - memcpy(dest, m_rxBuffer+4+bufferOffset, numBytes); + memcpy(dest, m_rxBuffer+4+byteOffset, numBytes); } } /* namespace BAGuitar */ diff --git a/src/BASpiMemory.h b/src/BASpiMemory.h index fa7e3d1..5fb58f8 100644 --- a/src/BASpiMemory.h +++ b/src/BASpiMemory.h @@ -49,25 +49,51 @@ public: BASpiMemory(SpiDeviceId memDeviceId, uint32_t speedHz); virtual ~BASpiMemory(); + /// initialize and configure the SPI peripheral 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 data the value to write 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); + /// 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); - 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); /// read a single 8-bit data word from the specified address /// @param address the address in the SPI RAM to read from /// @return the data that was read 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 /// @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 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; } protected: @@ -96,11 +124,13 @@ protected: class BASpiMemoryDMA : public BASpiMemory { public: BASpiMemoryDMA() = delete; + /// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2). /// @details default is 20 Mhz /// @param memDeviceId specify which MEM to control with SpiDeviceId. /// @param bufferSize size of buffer to store DMA transfers BASpiMemoryDMA(SpiDeviceId memDeviceId, size_t bufferSizeBytes); + /// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2) /// @param memDeviceId specify which MEM to control with SpiDeviceId. /// @param speedHz specify the desired speed in Hz. @@ -108,14 +138,35 @@ public: BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz, size_t bufferSizeBytes); 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 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; - /// read a single 8-bit data word from the specified address - /// @param address the address in the SPI RAM to read from - /// @return the data that was read + /// 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 void read(size_t address, uint8_t *dest, size_t numBytes) override; /// 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 void read16(size_t address, uint16_t *dest, size_t numWords) override; - - void begin() override; - void readBufferContents(uint8_t *dest, size_t numBytes, size_t bufferOffset = 0); + /// Check if a DMA write is in progress + /// @returns true if a write DMA is in progress, else false + 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: AbstractDmaSpi *m_spiDma = nullptr;