Duet Ethernet now uses the PDC for SPI transfers

This commit is contained in:
David Crocker 2016-12-29 17:28:41 +00:00
parent f4f6ad3c61
commit 01d439ddb4
3 changed files with 37 additions and 66 deletions

View file

@ -36,7 +36,7 @@ const Port TELNET_PORT = 23;
const unsigned int TCP_MSS = 1460; const unsigned int TCP_MSS = 1460;
const size_t NetworkTransactionCount = 8; // number of NetworkTransactions to be used for network IO const size_t NetworkTransactionCount = 8; // number of NetworkTransactions to be used for network IO
const size_t NetworkBufferCount = 12; // number of 2K or 3K network buffers const size_t NetworkBufferCount = 16; // number of 2K or 3K network buffers
// Define the following to use 3K buffers on the W5500 for the HTTP sockets and smaller buffers for everything else // Define the following to use 3K buffers on the W5500 for the HTTP sockets and smaller buffers for everything else
// It doesn't seem to work, the chip keeps telling us that 1 byte is available. // It doesn't seem to work, the chip keeps telling us that 1 byte is available.

View file

@ -11,7 +11,7 @@
// Define exactly one of the following as 1, the other as zero // Define exactly one of the following as 1, the other as zero
// The PDC seems to be too slow to work reliably without getting transmit underruns, so we use the DMAC now. // The PDC seems to be too slow to work reliably without getting transmit underruns, so we use the DMAC now.
#define USE_PDC 0 // use peripheral DMA controller #define USE_PDC 1 // use peripheral DMA controller
#define USE_DMAC 0 // use general DMA controller #define USE_DMAC 0 // use general DMA controller
#if USE_PDC #if USE_PDC
@ -30,9 +30,11 @@ const unsigned int SpiPeripheralChannelId = 0; // we use NPCS0 as the slave se
#if USE_PDC #if USE_PDC
static Pdc *spi_pdc; static Pdc *spi_pdc;
static inline void spi_rx_dma_enable() static inline void spi_rx_dma_enable()
{ {
pdc_enable_transfer(spi_pdc, PERIPH_PTCR_RXTEN); pdc_enable_transfer(spi_pdc, PERIPH_PTCR_RXTEN);
pdc_enable_transfer(spi_pdc, PERIPH_PTCR_TXTEN); // we have to transmit in order to receive
} }
static inline void spi_tx_dma_enable() static inline void spi_tx_dma_enable()
@ -43,6 +45,7 @@ static inline void spi_tx_dma_enable()
static inline void spi_rx_dma_disable() static inline void spi_rx_dma_disable()
{ {
pdc_disable_transfer(spi_pdc, PERIPH_PTCR_RXTDIS); pdc_disable_transfer(spi_pdc, PERIPH_PTCR_RXTDIS);
pdc_disable_transfer(spi_pdc, PERIPH_PTCR_TXTDIS); // we have to transmit in order to receive
} }
static inline void spi_tx_dma_disable() static inline void spi_tx_dma_disable()
@ -52,23 +55,24 @@ static inline void spi_tx_dma_disable()
static bool spi_dma_check_rx_complete() static bool spi_dma_check_rx_complete()
{ {
return true; return pdc_read_rx_counter(spi_pdc) == 0;
} }
static void spi_tx_dma_setup(const TransactionBuffer *buf, uint32_t maxTransmitLength) static void spi_tx_dma_setup(const uint8_t *buf, uint32_t length)
{ {
pdc_packet_t pdc_spi_packet; pdc_packet_t pdc_spi_packet;
pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(buf); pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(buf);
pdc_spi_packet.ul_size = buf->PacketLength() * 4; // need length in bytes pdc_spi_packet.ul_size = length;
pdc_tx_init(spi_pdc, &pdc_spi_packet, NULL); pdc_tx_init(spi_pdc, &pdc_spi_packet, NULL);
} }
static void spi_rx_dma_setup(const TransactionBuffer *buf) static void spi_rx_dma_setup(uint8_t *buf, uint32_t length)
{ {
pdc_packet_t pdc_spi_packet; pdc_packet_t pdc_spi_packet;
pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(buf); pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(buf);
pdc_spi_packet.ul_size = TransactionBuffer::MaxReceiveBytes; pdc_spi_packet.ul_size = length;
pdc_rx_init(spi_pdc, &pdc_spi_packet, NULL); pdc_rx_init(spi_pdc, &pdc_spi_packet, NULL);
pdc_tx_init(spi_pdc, &pdc_spi_packet, NULL); // we have to transmit in order to receive
} }
#endif #endif
@ -152,51 +156,6 @@ static void spi_dma_disable()
spi_rx_dma_disable(); spi_rx_dma_disable();
} }
#if 0
/**
* \brief Set SPI slave transfer.
*/
static void spi_slave_dma_setup(bool dataToSend, bool allowReceive)
{
#if USE_PDC
pdc_disable_transfer(spi_pdc, PERIPH_PTCR_TXTDIS | PERIPH_PTCR_RXTDIS);
TransactionBuffer *outBufPointer = (dataToSend) ? &outBuffer : reinterpret_cast<TransactionBuffer*>(&dummyOutBuffer);
spi_tx_dma_setup(outBufPointer);
if (allowReceive)
{
outBufPointer->SetDataTaken();
spi_rx_dma_setup(&inBuffer);
pdc_enable_transfer(spi_pdc, PERIPH_PTCR_TXTEN | PERIPH_PTCR_RXTEN);
}
else
{
outBufPointer->ClearDataTaken();
pdc_enable_transfer(spi_pdc, PERIPH_PTCR_TXTEN);
}
#endif
#if USE_DMAC
spi_dma_disable();
TransactionBuffer *outBufPointer = (dataToSend) ? &outBuffer : reinterpret_cast<TransactionBuffer*>(&dummyOutBuffer);
if (allowReceive)
{
spi_rx_dma_setup(&inBuffer);
spi_rx_dma_enable();
// outBufPointer->SetDataTaken();
}
else
{
// outBufPointer->ClearDataTaken();
}
// spi_tx_dma_setup(outBufPointer, (dataToSend) ? TransactionBuffer::MaxTransferBytes : 4 * TransactionBuffer::headerDwords);
spi_tx_dma_enable();
#endif
}
#endif
#endif #endif
namespace WizSpi namespace WizSpi
@ -206,7 +165,7 @@ namespace WizSpi
{ {
#if USE_PDC #if USE_PDC
spi_pdc = spi_get_pdc_base(SPI); spi_pdc = spi_get_pdc_base(SPI);
// The PDCs are masters 2 and 3 and the SRAM is slave 0. Give the PDCs the highest priority. // The PDCs are masters 2 and 3 and the SRAM is slave 0. Give the receive PDCs the highest priority.
matrix_set_master_burst_type(0, MATRIX_ULBT_8_BEAT_BURST); matrix_set_master_burst_type(0, MATRIX_ULBT_8_BEAT_BURST);
matrix_set_slave_default_master_type(0, MATRIX_DEFMSTR_LAST_DEFAULT_MASTER); matrix_set_slave_default_master_type(0, MATRIX_DEFMSTR_LAST_DEFAULT_MASTER);
matrix_set_slave_priority(0, (3 << MATRIX_PRAS0_M2PR_Pos) | (3 << MATRIX_PRAS0_M3PR_Pos)); matrix_set_slave_priority(0, (3 << MATRIX_PRAS0_M2PR_Pos) | (3 << MATRIX_PRAS0_M3PR_Pos));
@ -402,6 +361,17 @@ namespace WizSpi
(void)SPI->SPI_RDR; // clear previous data (void)SPI->SPI_RDR; // clear previous data
} }
#if USE_PDC
spi_rx_dma_setup(rx_data, len);
spi_rx_dma_enable();
while (pdc_read_tx_counter(spi_pdc) != 0) { }
uint32_t timeout = SPI_TIMEOUT;
while (!spi_dma_check_rx_complete() && timeout != 0)
{
--timeout;
}
spi_rx_dma_disable();
#else
const uint32_t dOut = 0x000000FF; const uint32_t dOut = 0x000000FF;
SPI->SPI_TDR = dOut; // send first byte SPI->SPI_TDR = dOut; // send first byte
while (--len != 0) while (--len != 0)
@ -428,6 +398,7 @@ namespace WizSpi
} }
*rx_data++ = (uint8_t)SPI->SPI_RDR; // Get last byte from receive register *rx_data++ = (uint8_t)SPI->SPI_RDR; // Get last byte from receive register
#endif
} }
return SPI_OK; return SPI_OK;
} }
@ -435,24 +406,24 @@ namespace WizSpi
// Send some data // Send some data
spi_status_t SendBurst(const uint8_t* tx_data, size_t len) spi_status_t SendBurst(const uint8_t* tx_data, size_t len)
{ {
#if USE_PDC
spi_tx_dma_setup(tx_data, len);
spi_tx_dma_enable();
while (pdc_read_tx_counter(spi_pdc) != 0) { }
spi_tx_dma_disable();
#else
for (uint32_t i = 0; i < len; ++i) for (uint32_t i = 0; i < len; ++i)
{ {
uint32_t dOut = (uint32_t)*tx_data++; uint32_t dOut = (uint32_t)*tx_data++;
if (i + 1 == len)
{
dOut |= SPI_TDR_LASTXFER;
}
if (waitForTxReady()) if (waitForTxReady())
{ {
return SPI_ERROR_TIMEOUT; return SPI_ERROR_TIMEOUT;
} }
// Write to transmit register SPI->SPI_TDR = dOut; // write to transmit register
SPI->SPI_TDR = dOut;
(void)SPI->SPI_RDR; (void)SPI->SPI_RDR;
} }
#endif
return SPI_OK; return SPI_OK;
} }

View file

@ -14,7 +14,7 @@
#include "Libraries/Math/Matrix.h" #include "Libraries/Math/Matrix.h"
#ifdef DUET_NG #ifdef DUET_NG
const unsigned int DdaRingLength = 40; const unsigned int DdaRingLength = 30;
#else #else
// We are more memory-constrained on the SAM3X // We are more memory-constrained on the SAM3X
const unsigned int DdaRingLength = 20; const unsigned int DdaRingLength = 20;