git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5507 35acf78f-673a-0410-8e92-d51de3d6d3f4

This commit is contained in:
gdisirio 2013-03-27 11:54:40 +00:00
parent 0fc403c55a
commit 72fee26a32
4 changed files with 248 additions and 7 deletions

View File

@ -177,6 +177,15 @@ static const edma_channel_config_t spi_dspi3_rx_dma_config = {
/* Driver local functions. */
/*===========================================================================*/
/**
* @brief Starts eception 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
* @param[out] rxbuf the pointer to the receive buffer
*
* @notapi
*/
static void spi_start_dma_rx8(SPIDriver *spip,
size_t n,
uint8_t *rxbuf) {
@ -193,9 +202,19 @@ static void spi_start_dma_rx8(SPIDriver *spip,
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 16 bits.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be exchanged
* @param[out] rxbuf the pointer to the receive buffer
*
* @notapi
*/
static void spi_start_dma_rx16(SPIDriver *spip,
size_t n,
uint16_t *rxbuf) {
@ -212,23 +231,89 @@ static void spi_start_dma_rx16(SPIDriver *spip,
0, /* slast, no source adjust. */
0, /* dlast. */
EDMA_TCD_MODE_DREQ | EDMA_TCD_MODE_INT_END); /* mode.*/
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
* @param[in] txbuf the pointer to the transmit buffer
*
* @notapi
*/
static void spi_start_dma_tx8(SPIDriver *spip,
size_t n,
const uint8_t *txbuf) {
uint32_t cmd = spip->config->pushr & ~DSPI_PUSHR_EXCLUDED_BITS;
/* The first frame is pushed by the CPU, then the DMA is activated to
send the following frames.*/
spip->dspi->PUSHR.R = cmd | (uint32_t)*txbuf++;
/* Setting up TX DMA TCD parameters for 8 bits transfers.*/
edmaChannelSetup(spip->tx_channel, /* channel. */
txbuf, /* src. */
DSPI_PUSHR8_ADDRESS(spip), /* dst. */
1, /* soff, advance by 1. */
0, /* doff, do not advance. */
0, /* ssize, 8 bits transfers. */
0, /* dsize, 8 bits transfers. */
1, /* nbytes, always one. */
n - 1, /* iter. */
0, /* slast, no source adjust. */
0, /* dlast, no dest.adjust. */
EDMA_TCD_MODE_DREQ); /* mode. */
edmaChannelStart(spip->tx_channel);
}
/**
* @brief Starts transmission using DMA for frames up to 16 bits.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be exchanged
* @param[in] txbuf the pointer to the transmit buffer
*
* @notapi
*/
static void spi_start_dma_tx16(SPIDriver *spip,
size_t n,
const uint16_t *txbuf) {
uint32_t cmd = spip->config->pushr & ~DSPI_PUSHR_EXCLUDED_BITS;
/* The first frame is pushed by the CPU, then the DMA is activated to
send the following frames.*/
spip->dspi->PUSHR.R = cmd | (uint32_t)*txbuf++;
/* Setting up TX DMA TCD parameters for 16 bits transfers.*/
edmaChannelSetup(spip->tx_channel, /* channel. */
txbuf, /* src. */
DSPI_PUSHR16_ADDRESS(spip), /* dst. */
2, /* soff, advance by 2. */
0, /* doff, do not advance. */
1, /* ssize, 16 bits transfers.*/
1, /* dsize, 16 bits transfers.*/
2, /* nbytes, always two. */
n - 1, /* iter. */
0, /* slast, no source adjust. */
0, /* dlast, no dest.adjust. */
EDMA_TCD_MODE_DREQ); /* mode. */
edmaChannelStart(spip->tx_channel);
}
/**
* @brief Starts transmission using FIFO pre-filling for frames up to 8 bits.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be exchanged
* @param[in] txbuf the pointer to the transmit buffer
*
* @notapi
*/
static void spi_tx_prefill8(SPIDriver *spip,
size_t n,
const uint8_t *txbuf) {
@ -244,6 +329,15 @@ static void spi_tx_prefill8(SPIDriver *spip,
} while (TRUE);
}
/**
* @brief Starts transmission using FIFO pre-filling for frames up to 16 bits.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be exchanged
* @param[in] txbuf the pointer to the transmit buffer
*
* @notapi
*/
static void spi_tx_prefill16(SPIDriver *spip,
size_t n,
const uint16_t *txbuf) {
@ -260,13 +354,32 @@ 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;
/* Stops the DSPI and clears the queues.*/
spip->dspi->MCR.R = SPC5_MCR_MSTR | SPC5_MCR_HALT |
SPC5_MCR_CLR_TXF | SPC5_MCR_CLR_RXF;
/* Portable SPI ISR code defined in the high level driver, note, it is
a macro.*/
_spi_isr_code(spip);
}
static void spi_serve_dma_error_irq(edma_channel_t channel,
void *p,
uint32_t esr) {
SPIDriver *spip = (SPIDriver *)p;
(void)channel;
(void)esr;
/* Stops the DSPI and clears the queues.*/
spip->dspi->MCR.R = SPC5_MCR_MSTR | SPC5_MCR_HALT |
SPC5_MCR_CLR_TXF | SPC5_MCR_CLR_RXF;
SPC5_SPI_DMA_ERROR_HOOK(spip);
}
/*===========================================================================*/
@ -375,11 +488,11 @@ void spi_lld_start(SPIDriver *spip) {
}
#endif /* SPC5_SPI_USE_DSPI3 */
}
/* Configures the peripheral.*/
spip->dspi->MCR.R = SPC5_MCR_MSTR | spip->config->mcr;
spip->dspi->MCR.R = SPC5_MCR_MSTR | SPC5_MCR_HALT | spip->config->mcr;
spip->dspi->CTAR[0].R = spip->config->ctar0;
spip->dspi->RSER.R = SPC5_RSER_EOQF_RE | SPC5_RSER_TFFF_DIRS |
SPC5_RSER_RFDF_DIRS;
spip->dspi->RSER.R = SPC5_RSER_TFFF_DIRS | SPC5_RSER_RFDF_DIRS;
spip->dspi->SR.R = spip->dspi->SR.R;
}
@ -402,7 +515,8 @@ void spi_lld_stop(SPIDriver *spip) {
spip->dspi->RSER.R = 0;
spip->dspi->SR.R = spip->dspi->SR.R;
spip->dspi->MCR.R = SPC5_MCR_MSTR | SPC5_MCR_MDIS |
SPC5_MCR_CLR_TXF | SPC5_MCR_CLR_RXF;
SPC5_MCR_CLR_TXF | SPC5_MCR_CLR_RXF |
SPC5_MCR_HALT;
#if SPC5_SPI_USE_DSPI0
if (&SPID1 == spip) {
@ -523,7 +637,8 @@ void spi_lld_exchange(SPIDriver *spip, size_t n,
}
}
/* Starting transfer.*/
spip->dspi->MCR.B.HALT = 0;
}
/**

View File

@ -88,6 +88,106 @@
#define SPC5_RSER_RFDF_DIRS (1U << 16)
/** @} */
/**
* @name CTAR registers definitions
* @{
*/
#define SPC5_CTAR_DBR (1U << 31)
#define SPC5_CTAR_FMSZ_MASK (15U << 27)
#define SPC5_CTAR_FMSZ(n) (((n) - 1) << 27)
#define SPC5_CTAR_CPOL (1U << 26)
#define SPC5_CTAR_CPHA (1U << 25)
#define SPC5_CTAR_LSBFE (1U << 24)
#define SPC5_CTAR_PCSSCK_MASK (3U << 22)
#define SPC5_CTAR_PCSSCK_PRE1 (0U << 22)
#define SPC5_CTAR_PCSSCK_PRE3 (1U << 22)
#define SPC5_CTAR_PCSSCK_PRE5 (2U << 22)
#define SPC5_CTAR_PCSSCK_PRE7 (3U << 22)
#define SPC5_CTAR_PASC_MASK (3U << 20)
#define SPC5_CTAR_PASC_PRE1 (0U << 20)
#define SPC5_CTAR_PASC_PRE3 (1U << 20)
#define SPC5_CTAR_PASC_PRE5 (2U << 20)
#define SPC5_CTAR_PASC_PRE7 (3U << 20)
#define SPC5_CTAR_PDT_MASK (3U << 18)
#define SPC5_CTAR_PDT_PRE1 (0U << 18)
#define SPC5_CTAR_PDT_PRE3 (1U << 18)
#define SPC5_CTAR_PDT_PRE5 (2U << 18)
#define SPC5_CTAR_PDT_PRE7 (3U << 18)
#define SPC5_CTAR_PBR_MASK (3U << 16)
#define SPC5_CTAR_PBR_PRE2 (0U << 16)
#define SPC5_CTAR_PBR_PRE3 (1U << 16)
#define SPC5_CTAR_PBR_PRE5 (2U << 16)
#define SPC5_CTAR_PBR_PRE7 (3U << 16)
#define SPC5_CTAR_CSSCK_MASK (15U << 12)
#define SPC5_CTAR_CSSCK_DIV2 (0U << 12)
#define SPC5_CTAR_CSSCK_DIV4 (1U << 12)
#define SPC5_CTAR_CSSCK_DIV6 (2U << 12)
#define SPC5_CTAR_CSSCK_DIV8 (3U << 12)
#define SPC5_CTAR_CSSCK_DIV16 (4U << 12)
#define SPC5_CTAR_CSSCK_DIV32 (5U << 12)
#define SPC5_CTAR_CSSCK_DIV64 (6U << 12)
#define SPC5_CTAR_CSSCK_DIV128 (7U << 12)
#define SPC5_CTAR_CSSCK_DIV256 (8U << 12)
#define SPC5_CTAR_CSSCK_DIV512 (9U << 12)
#define SPC5_CTAR_CSSCK_DIV1024 (10U << 12)
#define SPC5_CTAR_CSSCK_DIV2048 (11U << 12)
#define SPC5_CTAR_CSSCK_DIV4096 (12U << 12)
#define SPC5_CTAR_CSSCK_DIV8192 (13U << 12)
#define SPC5_CTAR_CSSCK_DIV16384 (14U << 12)
#define SPC5_CTAR_CSSCK_DIV32768 (15U << 12)
#define SPC5_CTAR_ASC_MASK (15U << 8)
#define SPC5_CTAR_ASC_DIV2 (0U << 8)
#define SPC5_CTAR_ASC_DIV4 (1U << 8)
#define SPC5_CTAR_ASC_DIV6 (2U << 8)
#define SPC5_CTAR_ASC_DIV8 (3U << 8)
#define SPC5_CTAR_ASC_DIV16 (4U << 8)
#define SPC5_CTAR_ASC_DIV32 (5U << 8)
#define SPC5_CTAR_ASC_DIV64 (6U << 8)
#define SPC5_CTAR_ASC_DIV128 (7U << 8)
#define SPC5_CTAR_ASC_DIV256 (8U << 8)
#define SPC5_CTAR_ASC_DIV512 (9U << 8)
#define SPC5_CTAR_ASC_DIV1024 (10U << 8)
#define SPC5_CTAR_ASC_DIV2048 (11U << 8)
#define SPC5_CTAR_ASC_DIV4096 (12U << 8)
#define SPC5_CTAR_ASC_DIV8192 (13U << 8)
#define SPC5_CTAR_ASC_DIV16384 (14U << 8)
#define SPC5_CTAR_ASC_DIV32768 (15U << 8)
#define SPC5_CTAR_DT_MASK (15U << 4)
#define SPC5_CTAR_DT_DIV2 (0U << 4)
#define SPC5_CTAR_DT_DIV4 (1U << 4)
#define SPC5_CTAR_DT_DIV6 (2U << 4)
#define SPC5_CTAR_DT_DIV8 (3U << 4)
#define SPC5_CTAR_DT_DIV16 (4U << 4)
#define SPC5_CTAR_DT_DIV32 (5U << 4)
#define SPC5_CTAR_DT_DIV64 (6U << 4)
#define SPC5_CTAR_DT_DIV128 (7U << 4)
#define SPC5_CTAR_DT_DIV256 (8U << 4)
#define SPC5_CTAR_DT_DIV512 (9U << 4)
#define SPC5_CTAR_DT_DIV1024 (10U << 4)
#define SPC5_CTAR_DT_DIV2048 (11U << 4)
#define SPC5_CTAR_DT_DIV4096 (12U << 4)
#define SPC5_CTAR_DT_DIV8192 (13U << 4)
#define SPC5_CTAR_DT_DIV16384 (14U << 4)
#define SPC5_CTAR_DT_DIV32768 (15U << 4)
#define SPC5_CTAR_BR_MASK (15U << 0)
#define SPC5_CTAR_BR_DIV2 (0U << 0)
#define SPC5_CTAR_BR_DIV4 (1U << 0)
#define SPC5_CTAR_BR_DIV6 (2U << 0)
#define SPC5_CTAR_BR_DIV8 (3U << 0)
#define SPC5_CTAR_BR_DIV16 (4U << 0)
#define SPC5_CTAR_BR_DIV32 (5U << 0)
#define SPC5_CTAR_BR_DIV64 (6U << 0)
#define SPC5_CTAR_BR_DIV128 (7U << 0)
#define SPC5_CTAR_BR_DIV256 (8U << 0)
#define SPC5_CTAR_BR_DIV512 (9U << 0)
#define SPC5_CTAR_BR_DIV1024 (10U << 0)
#define SPC5_CTAR_BR_DIV2048 (11U << 0)
#define SPC5_CTAR_BR_DIV4096 (12U << 0)
#define SPC5_CTAR_BR_DIV8192 (13U << 0)
#define SPC5_CTAR_BR_DIV16384 (14U << 0)
#define SPC5_CTAR_BR_DIV32768 (15U << 0)
/** @} */
/**
* @name PUSHR register definitions
* @{
@ -198,6 +298,13 @@
#if !defined(SPC5_SPI_DSPI3_DMA_IRQ_PRIO) || defined(__DOXYGEN__)
#define SPC5_SPI_DSPI3_DMA_IRQ_PRIO 10
#endif
/**
* @brief SPI DMA error hook.
*/
#if !defined(SPC5_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define SPC5_SPI_DMA_ERROR_HOOK(spip) chSysHalt()
#endif
/** @} */
/*===========================================================================*/
@ -253,6 +360,14 @@ typedef struct {
*/
spicallback_t end_cb;
/* End of the mandatory fields.*/
/**
* @brief The chip select line port.
*/
ioportid_t ssport;
/**
* @brief The chip select line pad number.
*/
uint16_t sspad;
/**
* @brief DSPI MCR value for this session.
* @note Some bits are ignored: CONT_SCKE, DCONF, ROOE, MDIS, DIS_TXF,

View File

@ -25,14 +25,24 @@
* Maximum speed SPI configuration (21MHz, CPHA=0, CPOL=0, MSb first).
*/
static const SPIConfig hs_spicfg = {
NULL
NULL,
0,
0,
0, /* MCR. */
SPC5_CTAR_FMSZ(8) | SPC5_CTAR_PBR_PRE2 | SPC5_CTAR_BR_DIV2, /* CTAR0. */
0 /* PUSHR. */
};
/*
* Low speed SPI configuration (328.125kHz, CPHA=0, CPOL=0, MSb first).
*/
static const SPIConfig ls_spicfg = {
NULL
NULL,
0,
0,
0, /* MCR. */
SPC5_CTAR_FMSZ(8) | SPC5_CTAR_PBR_PRE2 | SPC5_CTAR_BR_DIV256, /* CTAR0. */
0 /* PUSHR. */
};
/*

View File

@ -90,3 +90,4 @@
#define SPC5_SPI_DSPI2_DMA_PRIO 10
#define SPC5_SPI_DSPI1_DMA_IRQ_PRIO 10
#define SPC5_SPI_DSPI2_DMA_IRQ_PRIO 10
#define SPC5_SPI_DMA_ERROR_HOOK(spip) chSysHalt()