mirror of https://github.com/rusefi/ChibiOS.git
SPC5xx DSPI driver working on SPC563Mxx.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5766 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
036f60f497
commit
e9edd47802
|
@ -102,7 +102,7 @@ SPIDriver SPID4;
|
|||
*/
|
||||
static const edma_channel_config_t spi_dspi0_tx1_dma_config = {
|
||||
SPC5_DSPI0_TX1_DMA_DEV_ID, SPC5_SPI_DSPI0_DMA_PRIO, SPC5_SPI_DSPI0_DMA_IRQ_PRIO,
|
||||
NULL, spi_serve_dma_error_irq, &SPID1
|
||||
spi_serve_tx_irq, spi_serve_dma_error_irq, &SPID1
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -128,7 +128,7 @@ static const edma_channel_config_t spi_dspi0_rx_dma_config = {
|
|||
*/
|
||||
static const edma_channel_config_t spi_dspi1_tx1_dma_config = {
|
||||
SPC5_DSPI1_TX1_DMA_DEV_ID, SPC5_SPI_DSPI1_DMA_PRIO, SPC5_SPI_DSPI1_DMA_IRQ_PRIO,
|
||||
NULL, spi_serve_dma_error_irq, &SPID2
|
||||
spi_serve_tx_irq, spi_serve_dma_error_irq, &SPID2
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -154,7 +154,7 @@ static const edma_channel_config_t spi_dspi1_rx_dma_config = {
|
|||
*/
|
||||
static const edma_channel_config_t spi_dspi2_tx1_dma_config = {
|
||||
SPC5_DSPI2_TX1_DMA_DEV_ID, SPC5_SPI_DSPI2_DMA_PRIO, SPC5_SPI_DSPI2_DMA_IRQ_PRIO,
|
||||
NULL, spi_serve_dma_error_irq, &SPID3
|
||||
spi_serve_tx_irq, spi_serve_dma_error_irq, &SPID3
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -180,7 +180,7 @@ static const edma_channel_config_t spi_dspi2_rx_dma_config = {
|
|||
*/
|
||||
static const edma_channel_config_t spi_dspi3_tx1_dma_config = {
|
||||
SPC5_DSPI3_TX1_DMA_DEV_ID, SPC5_SPI_DSPI3_DMA_PRIO, SPC5_SPI_DSPI3_DMA_IRQ_PRIO,
|
||||
NULL, spi_serve_dma_error_irq, &SPID4
|
||||
spi_serve_tx_irq, spi_serve_dma_error_irq, &SPID4
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -204,6 +204,33 @@ static const edma_channel_config_t spi_dspi3_rx_dma_config = {
|
|||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Starts reception using DMA ignoring the received data.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to be exchanged
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static void spi_start_dma_rx_ignore(SPIDriver *spip, size_t n) {
|
||||
static uint32_t datasink;
|
||||
|
||||
edmaChannelSetup(spip->rx_channel, /* channel. */
|
||||
DSPI_POPR8_ADDRESS(spip), /* src. */
|
||||
&datasink, /* dst. */
|
||||
0, /* soff, do not advance. */
|
||||
0, /* doff, do not advance. */
|
||||
0, /* ssize, 16 bits transfers.*/
|
||||
0, /* dsize, 16 bits transfers.*/
|
||||
1, /* nbytes, always one. */
|
||||
n, /* iter. */
|
||||
0, /* slast. */
|
||||
0, /* dlast. */
|
||||
EDMA_TCD_MODE_DREQ | EDMA_TCD_MODE_INT_END); /* mode.*/
|
||||
|
||||
edmaChannelStart(spip->rx_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts reception using DMA for frames up to 8 bits.
|
||||
*
|
||||
|
@ -262,6 +289,42 @@ static void spi_start_dma_rx16(SPIDriver *spip,
|
|||
edmaChannelStart(spip->rx_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts transmission using DMA for frames up to 8 bits.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to be exchanged
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static void spi_start_dma_tx_ignore(SPIDriver *spip, size_t n) {
|
||||
|
||||
/* Preparing the TX intermediate buffer with the fixed part.*/
|
||||
spip->tx_intbuf = spip->config->pushr | (uint32_t)0xFFFF;
|
||||
|
||||
/* The first frame is pushed by the CPU, then the DMA is activated to
|
||||
send the following frames. This should reduce latency on the operation
|
||||
start.*/
|
||||
spip->dspi->PUSHR.R = spip->tx_last = spip->tx_intbuf;
|
||||
|
||||
/* Setting up TX1 DMA TCD parameters for 32 bits transfers.*/
|
||||
edmaChannelSetup(spip->tx1_channel, /* channel. */
|
||||
&spip->tx_intbuf, /* src. */
|
||||
&spip->dspi->PUSHR.R, /* dst. */
|
||||
0, /* soff, do not advance. */
|
||||
0, /* doff, do not advance. */
|
||||
2, /* ssize, 32 bits transfers.*/
|
||||
2, /* dsize, 32 bits transfers.*/
|
||||
4, /* nbytes, always four. */
|
||||
n - 2, /* iter. */
|
||||
0, /* slast, no source adjust. */
|
||||
0, /* dlast, no dest.adjust. */
|
||||
EDMA_TCD_MODE_DREQ | EDMA_TCD_MODE_INT_END); /* mode. */
|
||||
|
||||
/* Starting TX1 DMA channel.*/
|
||||
edmaChannelStart(spip->tx1_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts transmission using DMA for frames up to 8 bits.
|
||||
*
|
||||
|
@ -382,6 +445,27 @@ static void spi_start_dma_tx16(SPIDriver *spip,
|
|||
edmaChannelStart(spip->tx1_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts idle bits using FIFO pre-filling.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to be exchanged
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static void spi_tx_prefill_ignore(SPIDriver *spip, size_t n) {
|
||||
uint32_t cmd = spip->config->pushr;
|
||||
|
||||
do {
|
||||
if (--n == 0) {
|
||||
spip->dspi->PUSHR.R = (SPC5_PUSHR_EOQ | cmd | (uint32_t)0xFFFF) &
|
||||
~SPC5_PUSHR_CONT;
|
||||
break;
|
||||
}
|
||||
spip->dspi->PUSHR.R = cmd | (uint32_t)0xFFFF;
|
||||
} while (TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts transmission using FIFO pre-filling for frames up to 8 bits.
|
||||
*
|
||||
|
@ -442,7 +526,8 @@ static void spi_tx_prefill16(SPIDriver *spip,
|
|||
static void spi_serve_rx_irq(edma_channel_t channel, void *p) {
|
||||
SPIDriver *spip = (SPIDriver *)p;
|
||||
|
||||
(void)channel;
|
||||
/* Clearing RX channel state.*/
|
||||
edmaChannelStop(channel);
|
||||
|
||||
/* Stops the DSPI and clears the queues.*/
|
||||
spip->dspi->MCR.R = DSPI_MCR_ENFORCED_BITS | SPC5_MCR_HALT |
|
||||
|
@ -455,7 +540,7 @@ static void spi_serve_rx_irq(edma_channel_t channel, void *p) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Shared TX2 DMA events service routine.
|
||||
* @brief Shared TX1/TX2 DMA events service routine.
|
||||
*
|
||||
* @param[in] channel the channel number
|
||||
* @param[in] p parameter for the registered function
|
||||
|
@ -467,6 +552,10 @@ static void spi_serve_tx_irq(edma_channel_t channel, void *p) {
|
|||
|
||||
(void)channel;
|
||||
|
||||
/* Clearing TX channels state.*/
|
||||
edmaChannelStop(spip->tx1_channel);
|
||||
edmaChannelStop(spip->tx2_channel);
|
||||
|
||||
/* If the TX FIFO is full then the push of the last frame is delagated to
|
||||
an interrupt handler else it is performed immediately. Both conditions
|
||||
can be true depending on the SPI speed and ISR latency.*/
|
||||
|
@ -836,9 +925,22 @@ void spi_lld_unselect(SPIDriver *spip) {
|
|||
*/
|
||||
void spi_lld_ignore(SPIDriver *spip, size_t n) {
|
||||
|
||||
(void)spip;
|
||||
(void)n;
|
||||
/* Starting transfer.*/
|
||||
spip->dspi->SR.R = spip->dspi->SR.R;
|
||||
spip->dspi->MCR.R = DSPI_MCR_ENFORCED_BITS | spip->config->mcr;
|
||||
|
||||
/* Setting up the RX DMA channel.*/
|
||||
spi_start_dma_rx_ignore(spip, n);
|
||||
|
||||
if (n <= SPC5_DSPI_FIFO_DEPTH) {
|
||||
/* If the total transfer size is smaller than the TX FIFO size then
|
||||
the whole transmitted data is pushed here and the TX DMA is not
|
||||
activated.*/
|
||||
spi_tx_prefill_ignore(spip, n);
|
||||
}
|
||||
else {
|
||||
spi_start_dma_tx_ignore(spip, n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -909,10 +1011,36 @@ void spi_lld_exchange(SPIDriver *spip, size_t n,
|
|||
*/
|
||||
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
|
||||
|
||||
(void)spip;
|
||||
(void)n;
|
||||
(void)txbuf;
|
||||
/* Starting transfer.*/
|
||||
spip->dspi->SR.R = spip->dspi->SR.R;
|
||||
spip->dspi->MCR.R = DSPI_MCR_ENFORCED_BITS | spip->config->mcr;
|
||||
|
||||
/* Setting up the RX DMA channel.*/
|
||||
spi_start_dma_rx_ignore(spip, n);
|
||||
|
||||
/* DMAs require a different setup depending on the frame size.*/
|
||||
if (spip->dspi->CTAR[0].B.FMSZ < 8) {
|
||||
if (n <= SPC5_DSPI_FIFO_DEPTH) {
|
||||
/* If the total transfer size is smaller than the TX FIFO size then
|
||||
the whole transmitted data is pushed here and the TX DMA is not
|
||||
activated.*/
|
||||
spi_tx_prefill8(spip, n, txbuf);
|
||||
}
|
||||
else {
|
||||
spi_start_dma_tx8(spip, n, txbuf);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (n <= SPC5_DSPI_FIFO_DEPTH) {
|
||||
/* If the total transfer size is smaller than the TX FIFO size then
|
||||
the whole transmitted data is pushed here and the TX DMA is not
|
||||
activated.*/
|
||||
spi_tx_prefill16(spip, n, txbuf);
|
||||
}
|
||||
else {
|
||||
spi_start_dma_tx16(spip, n, txbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -930,10 +1058,29 @@ void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
|
|||
*/
|
||||
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
|
||||
|
||||
(void)spip;
|
||||
(void)n;
|
||||
(void)rxbuf;
|
||||
/* Starting transfer.*/
|
||||
spip->dspi->SR.R = spip->dspi->SR.R;
|
||||
spip->dspi->MCR.R = DSPI_MCR_ENFORCED_BITS | spip->config->mcr;
|
||||
|
||||
/* DMAs require a different setup depending on the frame size.*/
|
||||
if (spip->dspi->CTAR[0].B.FMSZ < 8) {
|
||||
/* Setting up the RX DMA channel.*/
|
||||
spi_start_dma_rx8(spip, n, rxbuf);
|
||||
}
|
||||
else {
|
||||
/* Setting up the RX DMA channel.*/
|
||||
spi_start_dma_rx16(spip, n, rxbuf);
|
||||
}
|
||||
|
||||
if (n <= SPC5_DSPI_FIFO_DEPTH) {
|
||||
/* If the total transfer size is smaller than the TX FIFO size then
|
||||
the whole transmitted data is pushed here and the TX DMA is not
|
||||
activated.*/
|
||||
spi_tx_prefill_ignore(spip, n);
|
||||
}
|
||||
else {
|
||||
spi_start_dma_tx_ignore(spip, n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -950,10 +1097,12 @@ void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
|
|||
*/
|
||||
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) {
|
||||
|
||||
(void)spip;
|
||||
(void)frame;
|
||||
|
||||
return 0;
|
||||
spip->dspi->MCR.R = DSPI_MCR_ENFORCED_BITS | spip->config->mcr;
|
||||
spip->dspi->PUSHR.R = (SPC5_PUSHR_EOQ | spip->config->pushr |
|
||||
(uint32_t)frame) & ~SPC5_PUSHR_CONT;
|
||||
while (!spip->dspi->SR.B.RFDF)
|
||||
;
|
||||
return (uint16_t)spip->dspi->POPR.R;
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_SPI */
|
||||
|
|
|
@ -1345,7 +1345,7 @@ edma_channel_t edmaChannelAllocate(const edma_channel_config_t *ccfg) {
|
|||
*/
|
||||
void edmaChannelRelease(edma_channel_t channel) {
|
||||
|
||||
chDbgCheck((channel < 0) && (channel >= SPC5_EDMA_NCHANNELS),
|
||||
chDbgCheck((channel >= 0) && (channel < SPC5_EDMA_NCHANNELS),
|
||||
"edmaChannelAllocate");
|
||||
chDbgAssert(channels[channel] != NULL,
|
||||
"edmaChannelRelease(), #1",
|
||||
|
|
|
@ -126,7 +126,6 @@ void spiStop(SPIDriver *spip) {
|
|||
chSysLock();
|
||||
chDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY),
|
||||
"spiStop(), #1", "invalid state");
|
||||
spi_lld_unselect(spip);
|
||||
spi_lld_stop(spip);
|
||||
spip->state = SPI_STOP;
|
||||
chSysUnlock();
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
#include "hal.h"
|
||||
|
||||
/*
|
||||
* Maximum speed SPI configuration (21MHz, CPHA=0, CPOL=0, MSb first).
|
||||
* Maximum speed SPI configuration.
|
||||
*/
|
||||
static const SPIConfig hs_spicfg = {
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
SPC5_MCR_PCSIS0, /* MCR. */
|
||||
SPC5_CTAR_CSSCK_DIV64 | SPC5_CTAR_ASC_DIV64 | SPC5_CTAR_FMSZ(8) |
|
||||
SPC5_CTAR_PBR_PRE2 | SPC5_CTAR_BR_DIV128, /* CTAR0. */
|
||||
SPC5_CTAR_CSSCK_DIV2 | SPC5_CTAR_ASC_DIV2 | SPC5_CTAR_FMSZ(8) |
|
||||
SPC5_CTAR_PBR_PRE2 | SPC5_CTAR_BR_DIV2, /* CTAR0. */
|
||||
SPC5_PUSHR_CONT | SPC5_PUSHR_PCS(0) /* PUSHR. */
|
||||
};
|
||||
|
||||
|
@ -37,8 +37,9 @@ static const SPIConfig ls_spicfg = {
|
|||
NULL,
|
||||
0,
|
||||
0,
|
||||
0, /* MCR. */
|
||||
SPC5_CTAR_FMSZ(8) | SPC5_CTAR_PBR_PRE2 | SPC5_CTAR_BR_DIV256, /* CTAR0. */
|
||||
SPC5_MCR_PCSIS0, /* MCR. */
|
||||
SPC5_CTAR_CSSCK_DIV64 | SPC5_CTAR_ASC_DIV64 | SPC5_CTAR_FMSZ(8) |
|
||||
SPC5_CTAR_PBR_PRE2 | SPC5_CTAR_BR_DIV256, /* CTAR0. */
|
||||
SPC5_PUSHR_CONT | SPC5_PUSHR_PCS(0) /* PUSHR. */
|
||||
};
|
||||
|
||||
|
@ -58,7 +59,7 @@ static msg_t spi_thread_1(void *p) {
|
|||
chRegSetThreadName("SPI thread 1");
|
||||
while (TRUE) {
|
||||
spiAcquireBus(&SPID2); /* Acquire ownership of the bus. */
|
||||
palSetPad(PORT11, P11_LED1); /* LED ON. */
|
||||
palClearPad(PORT11, P11_LED1); /* LED ON. */
|
||||
spiStart(&SPID2, &hs_spicfg); /* Setup transfer parameters. */
|
||||
spiSelect(&SPID2); /* Slave Select assertion. */
|
||||
spiExchange(&SPID2, 512,
|
||||
|
@ -79,7 +80,7 @@ static msg_t spi_thread_2(void *p) {
|
|||
chRegSetThreadName("SPI thread 2");
|
||||
while (TRUE) {
|
||||
spiAcquireBus(&SPID2); /* Acquire ownership of the bus. */
|
||||
palClearPad(PORT11, P11_LED1); /* LED OFF. */
|
||||
palSetPad(PORT11, P11_LED1); /* LED OFF. */
|
||||
spiStart(&SPID2, &ls_spicfg); /* Setup transfer parameters. */
|
||||
spiSelect(&SPID2); /* Slave Select assertion. */
|
||||
spiExchange(&SPID2, 512,
|
||||
|
@ -116,19 +117,33 @@ int main(void) {
|
|||
for (i = 0; i < sizeof(txbuf); i++)
|
||||
txbuf[i] = (uint8_t)i;
|
||||
|
||||
spiStart(&SPID2, &hs_spicfg);
|
||||
/* Starting driver for test.*/
|
||||
spiStart(&SPID2, &ls_spicfg);
|
||||
SIU.PCR[102].R = PAL_MODE_OUTPUT_ALTERNATE(1); /* SCK */
|
||||
SIU.PCR[103].R = PAL_MODE_OUTPUT_ALTERNATE(1); /* SIN */
|
||||
SIU.PCR[104].R = PAL_MODE_OUTPUT_ALTERNATE(1); /* SOUT */
|
||||
SIU.PCR[105].R = PAL_MODE_OUTPUT_ALTERNATE(1); /* PCS[0] */
|
||||
|
||||
spiExchange(&SPID2, 4, txbuf, rxbuf);
|
||||
spiExchange(&SPID2, 4, txbuf, rxbuf);
|
||||
spiExchange(&SPID2, 4, txbuf, rxbuf);
|
||||
/* Testing sending and receiving at the same time.*/
|
||||
spiExchange(&SPID2, 4, txbuf, rxbuf);
|
||||
spiExchange(&SPID2, 32, txbuf, rxbuf);
|
||||
spiExchange(&SPID2, 512, txbuf, rxbuf);
|
||||
#if 0
|
||||
|
||||
/* Testing clock pulses without data buffering.*/
|
||||
spiIgnore(&SPID2, 4);
|
||||
spiIgnore(&SPID2, 32);
|
||||
|
||||
/* Testing sending data ignoring incoming data.*/
|
||||
spiSend(&SPID2, 4, txbuf);
|
||||
spiSend(&SPID2, 32, txbuf);
|
||||
|
||||
/* Testing receiving data while sending idle bits (high level).*/
|
||||
spiReceive(&SPID2, 4, rxbuf);
|
||||
spiReceive(&SPID2, 32, rxbuf);
|
||||
|
||||
/* Testing stop procedure.*/
|
||||
spiStop(&SPID2);
|
||||
|
||||
/*
|
||||
* Starting the transmitter and receiver threads.
|
||||
*/
|
||||
|
@ -136,7 +151,7 @@ int main(void) {
|
|||
NORMALPRIO + 1, spi_thread_1, NULL);
|
||||
chThdCreateStatic(spi_thread_2_wa, sizeof(spi_thread_2_wa),
|
||||
NORMALPRIO + 1, spi_thread_2, NULL);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Normal main() thread activity, in this demo it does nothing.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue