From b7e7258008897b11c6c8bbdc3220a49f3eaed949 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 17 Oct 2010 19:40:36 +0000 Subject: Unfinished AT91SAM7 SPI driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2266 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/AT91SAM7/serial_lld.c | 13 ++-- os/hal/platforms/AT91SAM7/spi_lld.c | 121 +++++++++++++++++++++++++++------ os/hal/platforms/AT91SAM7/spi_lld.h | 110 +++++++++++++++++++++++++----- os/hal/platforms/STM32/spi_lld.h | 2 +- 4 files changed, 199 insertions(+), 47 deletions(-) (limited to 'os/hal') diff --git a/os/hal/platforms/AT91SAM7/serial_lld.c b/os/hal/platforms/AT91SAM7/serial_lld.c index df57e5ed4..10833f497 100644 --- a/os/hal/platforms/AT91SAM7/serial_lld.c +++ b/os/hal/platforms/AT91SAM7/serial_lld.c @@ -248,8 +248,8 @@ CH_IRQ_HANDLER(USART1IrqHandler) { } #endif -// note - DBGU_UART IRQ is the SysIrq in board.c -// since it's not vectored separately by the AIC +/* note - DBGU_UART IRQ is the SysIrq in board.c + since it's not vectored separately by the AIC.*/ /*===========================================================================*/ /* Driver exported functions. */ @@ -286,9 +286,9 @@ void sd_lld_init(void) { #if USE_SAM7_DBGU_UART sdObjectInit(&SD3, NULL, notify3); - // this is a little cheap, but OK for now since there's enough overlap - // between dbgu and usart register maps. it means we can reuse all the - // same usart interrupt handling and config that already exists + /* this is a little cheap, but OK for now since there's enough overlap + between dbgu and usart register maps. it means we can reuse all the + same usart interrupt handling and config that already exists.*/ SD3.usart = (AT91PS_USART)AT91C_BASE_DBGU; AT91C_BASE_PIOA->PIO_PDR = SAM7_DBGU_RX | SAM7_DBGU_TX; AT91C_BASE_PIOA->PIO_ASR = SAM7_DBGU_RX | SAM7_DBGU_TX; @@ -328,7 +328,8 @@ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { AIC_EnableIT(AT91C_ID_US1); } #endif - // note - no explicit start for SD3 (DBGU_UART) since it's not included in the AIC or PMC + /* Note - no explicit start for SD3 (DBGU_UART) since it's not included + in the AIC or PMC.*/ } usart_init(sdp, config); } diff --git a/os/hal/platforms/AT91SAM7/spi_lld.c b/os/hal/platforms/AT91SAM7/spi_lld.c index d614aabb5..592bc092e 100644 --- a/os/hal/platforms/AT91SAM7/spi_lld.c +++ b/os/hal/platforms/AT91SAM7/spi_lld.c @@ -34,9 +34,14 @@ /* Driver exported variables. */ /*===========================================================================*/ -#if USE_AT91SAM7_SPI || defined(__DOXYGEN__) -/** @brief SPI driver identifier.*/ -SPIDriver SPID; +#if AT91SAM7_SPI_USE_SPI0 || defined(__DOXYGEN__) +/** @brief SPI1 driver identifier.*/ +SPIDriver SPID1; +#endif + +#if AT91SAM7_SPI_USE_SPI1 || defined(__DOXYGEN__) +/** @brief SPI2 driver identifier.*/ +SPIDriver SPID2; #endif /*===========================================================================*/ @@ -81,6 +86,36 @@ void rw8(size_t n, const uint8_t *txbuf, uint8_t *rxbuf) { /* Driver interrupt handlers. */ /*===========================================================================*/ +#if AT91SAM7_SPI_USE_SPI0 || defined(__DOXYGEN__) +/** + * @brief SPI0 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(SPI0IrqHandler) { + + CH_IRQ_PROLOGUE(); + spi_lld_serve_interrupt(&SPID1); + AT91C_BASE_AIC->AIC_EOICR = 0; + CH_IRQ_EPILOGUE(); +} +#endif + +#if AT91SAM7_SPI_USE_SPI1 || defined(__DOXYGEN__) +/** + * @brief SPI1 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(SPI1IrqHandler) { + + CH_IRQ_PROLOGUE(); + spi_lld_serve_interrupt(&SPID2); + AT91C_BASE_AIC->AIC_EOICR = 0; + CH_IRQ_EPILOGUE(); +} +#endif + /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ @@ -92,8 +127,32 @@ void rw8(size_t n, const uint8_t *txbuf, uint8_t *rxbuf) { */ void spi_lld_init(void) { -#if USE_AT91SAM7_SPI - spiObjectInit(&SPID); +#if AT91SAM7_SPI_USE_SPI0 + spiObjectInit(&SPID1); + /* Software reset must be written twice (errata for revision B parts).*/ + AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SWRST; + AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SWRST; + AT91C_BASE_PIOA->PIO_PDR = SPI0_MISO | SPI0_MOSI | SPI0_SCK; + AT91C_BASE_PIOA->PIO_ASR = SPI0_MISO | SPI0_MOSI | SPI0_SCK; + AT91C_BASE_PIOA->PIO_PPUDR = SPI0_MISO | SPI0_MOSI | SPI0_SCK; + SPID1.spd_spi = AT91C_BASE_SPI0; + AIC_ConfigureIT(AT91C_ID_SPI0, + AT91C_AIC_SRCTYPE_HIGH_LEVEL | AT91SAM7_SPI0_PRIORITY, + SPI0IrqHandler); +#endif + +#if AT91SAM7_SPI_USE_SPI1 + spiObjectInit(&SPID2); + /* Software reset must be written twice (errata for revision B parts).*/ + AT91C_BASE_SPI1->SPI_CR = AT91C_SPI_SWRST; + AT91C_BASE_SPI1->SPI_CR = AT91C_SPI_SWRST; + AT91C_BASE_PIOA->PIO_PDR = SPI1_MISO | SPI1_MOSI | SPI1_SCK; + AT91C_BASE_PIOA->PIO_BSR = SPI1_MISO | SPI1_MOSI | SPI1_SCK; + AT91C_BASE_PIOA->PIO_PPUDR = SPI1_MISO | SPI1_MOSI | SPI1_SCK; + SPID2.spd_spi = AT91C_BASE_SPI1; + AIC_ConfigureIT(AT91C_ID_SPI1, + AT91C_AIC_SRCTYPE_HIGH_LEVEL | AT91SAM7_SPI1_PRIORITY, + SPI1IrqHandler); #endif } @@ -107,21 +166,29 @@ void spi_lld_init(void) { void spi_lld_start(SPIDriver *spip) { if (spip->spd_state == SPI_STOP) { - /* disable general-purpose I/O for SPI pins */ - AT91C_BASE_PIOA->PIO_PDR = SPI_MISO | SPI_MOSI | SPI_SCK; - /* select perepheral A for SPI pins*/ - AT91C_BASE_PIOA->PIO_ASR = SPI_MISO | SPI_MOSI | SPI_SCK; - /* Clock activation.*/ - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI); +#if AT91SAM7_SPI_USE_SPI0 + if (&SPID1 == spip) { + /* Clock activation.*/ + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI0); + /* Enables associated interrupt vector.*/ + AIC_EnableIT(AT91C_ID_SPI0); + } +#endif +#if AT91SAM7_SPI_USE_SPI1 + if (&SPID2 == spip) { + /* Clock activation.*/ + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI1); + /* Enables associated interrupt vector.*/ + AIC_EnableIT(AT91C_ID_SPI1); + } +#endif } - /* software reset must be written twice (errata for revision B parts) */ - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; + else + spip->spd_spi->SPI_CR = AT91C_SPI_SPIDIS; /* Configuration.*/ - AT91C_BASE_SPI->SPI_MR = spip->spd_config->spc_mr; - AT91C_BASE_SPI->SPI_CSR[MMC_CSR_NUM] = spip->spd_config->spc_csr; - /* Enable SPI */ - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; + spip->spd_spi->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS; + spip->spd_spi->SPI_CSR[0] = spip->spd_config->spc_csr; + spip->spd_spi->SPI_CR = AT91C_SPI_SPIEN; } /** @@ -134,10 +201,20 @@ void spi_lld_start(SPIDriver *spip) { void spi_lld_stop(SPIDriver *spip) { if (spip->spd_state != SPI_STOP) { - /* disable SPI */ - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS; - /* disable clocks to SPI perepheral */ - AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_SPI); +#if AT91SAM7_SPI_USE_SPI0 + if (&SPID1 == spip) { + spip->spd_spi->SPI_CR = AT91C_SPI_SPIDIS; + spip->spd_spi->PMC_PCDR = (1 << AT91C_ID_SPI0); + AIC_DisableIT(AT91C_ID_SPI0); + } +#endif +#if AT91SAM7_SPI_USE_SPI1 + if (&SPID1 == spip) { + spip->spd_spi->SPI_CR = AT91C_SPI_SPIDIS; + spip->spd_spi->PMC_PCDR = (1 << AT91C_ID_SPI1); + AIC_DisableIT(AT91C_ID_SPI0); + } +#endif } } diff --git a/os/hal/platforms/AT91SAM7/spi_lld.h b/os/hal/platforms/AT91SAM7/spi_lld.h index 4c5ed4388..db896fe18 100644 --- a/os/hal/platforms/AT91SAM7/spi_lld.h +++ b/os/hal/platforms/AT91SAM7/spi_lld.h @@ -31,11 +31,24 @@ #if CH_HAL_USE_SPI || defined(__DOXYGEN__) /*===========================================================================*/ -/* Device compatibility. SAM7X have 2 SPIs. */ +/* Device compatibility.. */ /*===========================================================================*/ -#if defined (AT91SAM7X256_H) -#define AT91C_BASE_SPI AT91C_BASE_SPI0 -#define AT91C_ID_SPI AT91C_ID_SPI0 + +#if defined (AT91C_BASE_SPI) +#define AT91C_BASE_SPI0 AT91C_BASE_SPI +#define AT91C_ID_SPI0 AT91C_ID_SPI + +#define SPI0_MISO (1 << 12) +#define SPI0_MOSI (1 << 13) +#define SPI0_SCK (1 << 14) +#else +#define SPI0_MISO (1 << 16) +#define SPI0_MOSI (1 << 17) +#define SPI0_SCK (1 << 18) + +#define SPI1_MISO (1 << 24) +#define SPI1_MOSI (1 << 23) +#define SPI1_SCK (1 << 22) #endif /*===========================================================================*/ @@ -47,26 +60,74 @@ /*===========================================================================*/ /** - * @brief SPI driver enable switch. + * @brief SPID1 enable switch (SPI0 device). * @details If set to @p TRUE the support for SPI0 is included. * @note The default is @p TRUE. */ -#if !defined(USE_AT91SAM7_SPI) || defined(__DOXYGEN__) -#define USE_AT91SAM7_SPI TRUE +#if !defined(AT91SAM7_SPI_USE_SPI0) || defined(__DOXYGEN__) +#define AT91SAM7_SPI_USE_SPI0 TRUE +#endif + +/** + * @brief SPID2 enable switch (SPI1 device). + * @details If set to @p TRUE the support for SPI1 is included. + * @note The default is @p TRUE. + */ +#if !defined(AT91SAM7_SPI_USE_SPI1) || defined(__DOXYGEN__) +#define AT91SAM7_SPI_USE_SPI1 TRUE +#endif + +/** + * @brief SPI0 device interrupt priority level setting. + */ +#if !defined(AT91SAM7_SPI0_PRIORITY) || defined(__DOXYGEN__) +#define AT91SAM7_SPI0_PRIORITY (AT91C_AIC_PRIOR_HIGHEST - 1) +#endif + +/** + * @brief SPI1 device interrupt priority level setting. + */ +#if !defined(AT91SAM7_SPI1_PRIORITY) || defined(__DOXYGEN__) +#define AT91SAM7_SPI1_PRIORITY (AT91C_AIC_PRIOR_HIGHEST - 1) #endif /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ +#if !AT91SAM7_SPI_USE_SPI0 && !AT91SAM7_SPI_USE_SPI1 +#error "SPI driver activated but no SPI peripheral assigned" +#endif + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ +/** + * @brief Type of a structure representing an SPI driver. + */ +typedef struct SPIDriver SPIDriver; + +/** + * @brief SPI notification callback type. + * + * @param[in] spip pointer to the @p SPIDriver object triggering the + * callback + */ +typedef void (*spicallback_t)(SPIDriver *spip); + /** * @brief Driver configuration structure. */ typedef struct { + /** + * @brief Operation complete callback or @p NULL. + * @note In order to use synchronous functions this field must be set to + * @p NULL, callbacks and synchronous operations are mutually + * exclusive. + */ + spicallback_t spc_endcb; + /* End of the mandatory fields.*/ /** * @brief The chip select line port. */ @@ -75,10 +136,6 @@ typedef struct { * @brief The chip select line pad number. */ uint16_t spc_sspad; - /** - * @brief SPI Mode Register initialization data. - */ - uint32_t spc_mr; /** * @brief SPI Chip Select Register initialization data. */ @@ -88,11 +145,21 @@ typedef struct { /** * @brief Structure representing a SPI driver. */ -typedef struct { +struct SPIDriver { /** * @brief Driver state. */ spistate_t spd_state; + /** + * @brief Current configuration data. + */ + const SPIConfig *spd_config; +#if SPI_USE_WAIT || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + Thread *spd_thread; +#endif /* SPI_USE_WAIT */ #if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) #if CH_USE_MUTEXES || defined(__DOXYGEN__) /** @@ -103,12 +170,15 @@ typedef struct { Semaphore spd_semaphore; #endif #endif /* SPI_USE_MUTUAL_EXCLUSION */ +#if defined(SPI_DRIVER_EXT_FIELDS) + SPI_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ /** - * @brief Current configuration data. + * @brief Pointer to the SPIx registers block. */ - const SPIConfig *spd_config; - /* End of the mandatory fields.*/ -} SPIDriver; + AT91PS_SPI spd_spi; +}; /*===========================================================================*/ /* Driver macros. */ @@ -118,8 +188,12 @@ typedef struct { /* External declarations. */ /*===========================================================================*/ -#if USE_AT91SAM7_SPI && !defined(__DOXYGEN__) -extern SPIDriver SPID; +#if AT91SAM7_SPI_USE_SPI0 && !defined(__DOXYGEN__) +extern SPIDriver SPID1; +#endif + +#if AT91SAM7_SPI_USE_SPI1 && !defined(__DOXYGEN__) +extern SPIDriver SPID2; #endif #ifdef __cplusplus diff --git a/os/hal/platforms/STM32/spi_lld.h b/os/hal/platforms/STM32/spi_lld.h index 5da92d1f7..e08a1bb64 100644 --- a/os/hal/platforms/STM32/spi_lld.h +++ b/os/hal/platforms/STM32/spi_lld.h @@ -244,7 +244,7 @@ struct SPIDriver{ */ stm32_dma_channel_t *spd_dmatx; /** - * @brief DMA priority bit mask.\ + * @brief DMA priority bit mask. */ uint32_t spd_dmaccr; }; -- cgit v1.2.3