From 43f9fd4180030081daae9122bd57a521ec9c58e1 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 30 Oct 2009 15:45:38 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1258 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- demos/ARM7-AT91SAM7X-GCC/board.c | 3 ++- demos/ARM7-AT91SAM7X-LWIP-GCC/board.c | 3 ++- demos/ARM7-AT91SAM7X-UIP-GCC/board.c | 3 ++- os/io/io.dox | 42 +++++++++++++++++++++++++++++++- os/io/platforms/STM32/spi_lld.c | 46 ++++++++++++++++++++++++++++++----- os/io/platforms/STM32/spi_lld.h | 12 ++------- os/io/spi.c | 45 +++++++++++++++++++++------------- os/io/spi.h | 13 +++++++++- os/io/templates/spi_lld.c | 21 +++++++++++++--- os/io/templates/spi_lld.h | 12 ++------- os/kernel/src/chheap.c | 2 +- os/kernel/src/chschd.c | 2 ++ 12 files changed, 151 insertions(+), 53 deletions(-) diff --git a/demos/ARM7-AT91SAM7X-GCC/board.c b/demos/ARM7-AT91SAM7X-GCC/board.c index 31e362845..3faae501a 100644 --- a/demos/ARM7-AT91SAM7X-GCC/board.c +++ b/demos/ARM7-AT91SAM7X-GCC/board.c @@ -25,7 +25,7 @@ #include "at91lib/aic.h" /* - * FIQ Handler weak symbol defined in vectors.s. + * FIQ Handler weak symbol defined in vectors.s. */ void FiqHandler(void); @@ -123,6 +123,7 @@ void hwinit1(void) { * Default AIC setup, the device drivers will modify it as needed. */ AT91C_BASE_AIC->AIC_ICCR = 0xFFFFFFFF; + AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF; AT91C_BASE_AIC->AIC_SVR[0] = (AT91_REG)FiqHandler; for (i = 1; i < 31; i++) { AT91C_BASE_AIC->AIC_SVR[i] = (AT91_REG)NULL; diff --git a/demos/ARM7-AT91SAM7X-LWIP-GCC/board.c b/demos/ARM7-AT91SAM7X-LWIP-GCC/board.c index 5b95524f8..e988aaa86 100644 --- a/demos/ARM7-AT91SAM7X-LWIP-GCC/board.c +++ b/demos/ARM7-AT91SAM7X-LWIP-GCC/board.c @@ -26,7 +26,7 @@ #include "at91lib/aic.h" /* - * FIQ Handler weak symbol defined in vectors.s. + * FIQ Handler weak symbol defined in vectors.s. */ void FiqHandler(void); @@ -124,6 +124,7 @@ void hwinit1(void) { * Default AIC setup, the device drivers will modify it as needed. */ AT91C_BASE_AIC->AIC_ICCR = 0xFFFFFFFF; + AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF; AT91C_BASE_AIC->AIC_SVR[0] = (AT91_REG)FiqHandler; for (i = 1; i < 31; i++) { AT91C_BASE_AIC->AIC_SVR[i] = (AT91_REG)NULL; diff --git a/demos/ARM7-AT91SAM7X-UIP-GCC/board.c b/demos/ARM7-AT91SAM7X-UIP-GCC/board.c index 348f4bb99..9dbd5f0e4 100644 --- a/demos/ARM7-AT91SAM7X-UIP-GCC/board.c +++ b/demos/ARM7-AT91SAM7X-UIP-GCC/board.c @@ -27,7 +27,7 @@ /* - * FIQ Handler weak symbol defined in vectors.s. + * FIQ Handler weak symbol defined in vectors.s. */ void FiqHandler(void); @@ -125,6 +125,7 @@ void hwinit1(void) { * Default AIC setup, the device drivers will modify it as needed. */ AT91C_BASE_AIC->AIC_ICCR = 0xFFFFFFFF; + AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF; AT91C_BASE_AIC->AIC_SVR[0] = (AT91_REG)FiqHandler; for (i = 1; i < 31; i++) { AT91C_BASE_AIC->AIC_SVR[i] = (AT91_REG)NULL; diff --git a/os/io/io.dox b/os/io/io.dox index 1c1ccda9b..f53bb3271 100644 --- a/os/io/io.dox +++ b/os/io/io.dox @@ -116,7 +116,7 @@ /** * @defgroup SERIAL Serial Driver - * @brief Generic Serial Drivers. + * @brief Generic Serial Driver. * @details This module implements a generic full duplex serial driver. The * driver implements a @p SerialDriver interface and uses I/O Queues for * communication between the upper and the lower driver. Event flags are used @@ -136,6 +136,46 @@ * @ingroup SERIAL */ +/** + * @defgroup SPI SPI Driver + * @brief Generic SPI Driver. + * @details This module implements a generic SPI driver. The driver implements + * a state machine internally: + * @dot + digraph example { + rankdir="LR"; + node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.75", height="0.75"]; + edge [fontname=Helvetica, fontsize=8]; + uninit [label="SPI_UNINIT", style="bold"]; + stop [label="SPI_STOP\nLow Power"]; + ready [label="SPI_IDLE\nClock Enabled"]; + active [label="SPI_ACTIVE\nBus Active"]; + uninit -> stop [label="spiInit()"]; + stop -> ready [label="spiStart()"]; + ready -> ready [label="spiStart()"]; + ready -> stop [label="spiStop()"]; + stop -> stop [label="spiStop()"]; + ready -> active [label="spiSelect()"]; + active -> ready [label="spiUnselect()"]; + active -> active [label="spiExchange()\nspiSend()\nspiReceive()"]; + } + * @enddot + * + * The driver is not thread safe for performance reasons, if you need to access + * the SPI bus from multiple thread then use the @p spiAcquireBus() and + * @p spiReleaseBus() APIs in order to gain exclusive access. + * + * @ingroup IO + */ + +/** + * @defgroup SPI_LLD SPI Low Level Driver + * @brief @ref SPI low level driver template. + * @details This file is a template for a SPI low level driver. + * + * @ingroup SPI + */ + /** * @defgroup MAC MAC Driver * @brief Generic MAC driver. diff --git a/os/io/platforms/STM32/spi_lld.c b/os/io/platforms/STM32/spi_lld.c index d0a84ddf7..fb3021d80 100644 --- a/os/io/platforms/STM32/spi_lld.c +++ b/os/io/platforms/STM32/spi_lld.c @@ -179,7 +179,6 @@ void spi_lld_init(void) { SPID1.spd_dmarx = DMA1_Channel2; SPID1.spd_dmatx = DMA1_Channel3; SPID1.spd_dmaprio = SPI1_DMA_PRIORITY << 12; - RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; GPIOA->CRH = (GPIOA->CRH & 0x000FFFFF) | 0xB4B00000; #endif @@ -190,17 +189,30 @@ void spi_lld_init(void) { SPID2.spd_dmarx = DMA1_Channel4; SPID2.spd_dmatx = DMA1_Channel5; SPID2.spd_dmaprio = SPI2_DMA_PRIORITY << 12; - RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; GPIOB->CRL = (GPIOB->CRL & 0x000FFFFF) | 0xB4B00000; #endif } /** - * @brief Low level SPI bus setup. - * + * @brief Configures and activates the SPI peripheral. + * * @param[in] spip pointer to the @p SPIDriver object */ -void spi_lld_setup(SPIDriver *spip) { +void spi_lld_start(SPIDriver *spip) { + + /* If in stopped state then enables the SPI clock.*/ + if (spip->spd_state == SPI_STOP) { +#if USE_STM32_SPI1 + if (&SPID1 == spip) { + RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; + } +#endif +#if USE_STM32_SPI2 + if (&SPID2 == spip) { + RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; + } +#endif + } /* SPI setup.*/ spip->spd_spi->CR1 = spip->spd_config->spc_cr1 | SPI_CR1_MSTR; @@ -225,6 +237,28 @@ void spi_lld_setup(SPIDriver *spip) { } } +/** + * @brief Deactivates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + */ +void spi_lld_stop(SPIDriver *spip) { + + /* If in ready state then disables the SPI clock.*/ + if (spip->spd_state == SPI_READY) { +#if USE_STM32_SPI1 + if (&SPID1 == spip) { + RCC->APB2ENR &= ~RCC_APB2ENR_SPI1EN; + } +#endif +#if USE_STM32_SPI2 + if (&SPID2 == spip) { + RCC->APB1ENR &= ~RCC_APB1ENR_SPI2EN; + } +#endif + } +} + /** * @brief Asserts the slave select signal and prepares for transfers. * @@ -236,7 +270,7 @@ void spi_lld_select(SPIDriver *spip) { } /** - * @brief De-asserts the slave select signal. + * @brief Deasserts the slave select signal. * @details The previously selected peripheral is unselected. * * @param[in] spip pointer to the @p SPIDriver object diff --git a/os/io/platforms/STM32/spi_lld.h b/os/io/platforms/STM32/spi_lld.h index 5775b67db..7348b72a6 100644 --- a/os/io/platforms/STM32/spi_lld.h +++ b/os/io/platforms/STM32/spi_lld.h @@ -81,15 +81,6 @@ /* Driver data structures and types. */ /*===========================================================================*/ -/** - * @brief Driver state machine possible states. - */ -typedef enum { - SPI_UNINIT = 0,//!< SPI_UNINIT - SPI_IDLE = 1, //!< SPI_IDLE - SPI_ACTIVE = 2 //!< SPI_ACTIVE -} spistate_t; - /** * @brief Driver configuration structure. */ @@ -175,7 +166,8 @@ extern SPIDriver SPID2; extern "C" { #endif void spi_lld_init(void); - void spi_lld_setup(SPIDriver *spip); + void spi_lld_start(SPIDriver *spip); + void spi_lld_stop(SPIDriver *spip); void spi_lld_select(SPIDriver *spip); void spi_lld_unselect(SPIDriver *spip); msg_t spi_lld_exchange(SPIDriver *spip, size_t n, void *rxbuf, void *txbuf); diff --git a/os/io/spi.c b/os/io/spi.c index be34c469d..5cf51e76e 100644 --- a/os/io/spi.c +++ b/os/io/spi.c @@ -42,7 +42,7 @@ void spiInit(void) { */ void spiObjectInit(SPIDriver *spip) { - spip->spd_state = SPI_IDLE; + spip->spd_state = SPI_STOP; #if CH_USE_MUTEXES chMtxInit(&spip->spd_mutex); #elif CH_USE_SEMAPHORES @@ -52,20 +52,37 @@ void spiObjectInit(SPIDriver *spip) { } /** - * @brief Configures the SPI bus. + * @brief Configures and activates the SPI peripheral. * * @param[in] spip pointer to the @p SPIDriver object * @param config pointer to the @p SPIConfig object */ -void spiSetup(SPIDriver *spip, const SPIConfig *config) { +void spiStart(SPIDriver *spip, const SPIConfig *config) { - chDbgCheck((spip != NULL) && (config != NULL), "spiSetup"); - chDbgAssert(spip->spd_state == SPI_IDLE, - "spiSetup(), #1", - "not idle"); + chDbgCheck((spip != NULL) && (config != NULL), "spiStart"); + chDbgAssert((spip->spd_state == SPI_STOP) || (spip->spd_state == SPI_READY), + "spiStart(), #1", + "invalid state"); spip->spd_config = config; - spi_lld_setup(spip); + spi_lld_start(spip); + spip->spd_state = SPI_READY; +} + +/** + * @brief Deactivates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + */ +void spiStop(SPIDriver *spip) { + + chDbgCheck(spip != NULL, "spiStop"); + chDbgAssert((spip->spd_state == SPI_STOP) || (spip->spd_state == SPI_READY), + "spiStop(), #1", + "invalid state"); + + spi_lld_stop(spip); + spip->spd_state = SPI_STOP; } /** @@ -77,19 +94,16 @@ void spiSelect(SPIDriver *spip) { chDbgCheck(spip != NULL, "spiSelect"); - chSysLock(); - - chDbgAssert(spip->spd_state == SPI_IDLE, + chDbgAssert(spip->spd_state == SPI_READY, "spiSelect(), #1", "not idle"); spi_lld_select(spip); spip->spd_state = SPI_ACTIVE; - chSysUnlock(); } /** - * @brief De-asserts the slave select signal. + * @brief Deasserts the slave select signal. * @details The previously selected peripheral is unselected. * * @param[in] spip pointer to the @p SPIDriver object @@ -98,15 +112,12 @@ void spiUnselect(SPIDriver *spip) { chDbgCheck(spip != NULL, "spiUnselect"); - chSysLock(); - chDbgAssert(spip->spd_state == SPI_ACTIVE, "spiUnselect(), #1", "not locked"); spi_lld_unselect(spip); - spip->spd_state = SPI_IDLE; - chSysUnlock(); + spip->spd_state = SPI_READY; } /** diff --git a/os/io/spi.h b/os/io/spi.h index 816e9f6d4..e0a163db2 100644 --- a/os/io/spi.h +++ b/os/io/spi.h @@ -38,6 +38,16 @@ #error "SPI_USE_MUTUAL_EXCLUSION requires CH_USE_MUTEXES and/or CH_USE_SEMAPHORES" #endif +/** + * @brief Driver state machine possible states. + */ +typedef enum { + SPI_UNINIT = 0, /**< @brief Not initialized. */ + SPI_STOP = 1, /**< @brief Stopped. */ + SPI_READY = 2, /**< @brief Ready. */ + SPI_ACTIVE = 3 /**< @brief Slave selected. */ +} spistate_t; + #include "spi_lld.h" #ifdef __cplusplus @@ -45,7 +55,8 @@ extern "C" { #endif void spiInit(void); void spiObjectInit(SPIDriver *spip); - void spiSetup(SPIDriver *spip, const SPIConfig *config); + void spiStart(SPIDriver *spip, const SPIConfig *config); + void spiStop(SPIDriver *spip); void spiSelect(SPIDriver *spip); void spiUnselect(SPIDriver *spip); msg_t spiExchange(SPIDriver *spip, size_t n, void *rxbuf, void *txbuf); diff --git a/os/io/templates/spi_lld.c b/os/io/templates/spi_lld.c index e31dffc4b..c212946e0 100644 --- a/os/io/templates/spi_lld.c +++ b/os/io/templates/spi_lld.c @@ -47,11 +47,24 @@ void spi_lld_init(void) { } /** - * @brief Low level SPI bus setup. - * + * @brief Configures and activates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + */ +void spi_lld_start(SPIDriver *spip) { + + if (spip->spd_state == SPI_STOP) { + /* Clock activation.*/ + } + /* Configuration.*/ +} + +/** + * @brief Deactivates the SPI peripheral. + * * @param[in] spip pointer to the @p SPIDriver object */ -void spi_lld_setup(SPIDriver *spip) { +void spi_lld_stop(SPIDriver *spip) { } @@ -65,7 +78,7 @@ void spi_lld_select(SPIDriver *spip) { } /** - * @brief De-asserts the slave select signal. + * @brief Deasserts the slave select signal. * @details The previously selected peripheral is unselected. * * @param[in] spip pointer to the @p SPIDriver object diff --git a/os/io/templates/spi_lld.h b/os/io/templates/spi_lld.h index a8479c008..4017d2418 100644 --- a/os/io/templates/spi_lld.h +++ b/os/io/templates/spi_lld.h @@ -46,15 +46,6 @@ /* Driver data structures and types. */ /*===========================================================================*/ -/** - * @brief Driver state machine possible states. - */ -typedef enum { - SPI_UNINIT = 0, - SPI_IDLE = 1, - SPI_ACTIVE = 2 -} spistate_t; - /** * @brief Driver configuration structure. */ @@ -99,7 +90,8 @@ typedef struct { extern "C" { #endif void spi_lld_init(void); - void spi_lld_setup(SPIDriver *spip); + void spi_lld_start(SPIDriver *spip); + void spi_lld_stop(SPIDriver *spip); void spi_lld_select(SPIDriver *spip); void spi_lld_unselect(SPIDriver *spip); msg_t spi_lld_exchange(SPIDriver *spip, size_t n, void *rxbuf, void *txbuf); diff --git a/os/kernel/src/chheap.c b/os/kernel/src/chheap.c index d1dab1580..203d69d13 100644 --- a/os/kernel/src/chheap.c +++ b/os/kernel/src/chheap.c @@ -255,7 +255,7 @@ size_t chHeapStatus(MemoryHeap *heapp, size_t *sizep) { #if CH_USE_MUTEXES #define H_LOCK() chMtxLock(&hmtx) -#define H_UNLOCK() chMtxLock(&hmtx) +#define H_UNLOCK() chMtxUnock() static Mutex hmtx; #elif CH_USE_SEMAPHORES #define H_LOCK() chSemWait(&hsem) diff --git a/os/kernel/src/chschd.c b/os/kernel/src/chschd.c index 150169481..87c2e2f8c 100644 --- a/os/kernel/src/chschd.c +++ b/os/kernel/src/chschd.c @@ -268,7 +268,9 @@ void chSchDoYieldS(void) { /* Pick the first thread from the ready queue and makes it current.*/ (currp = fifo_remove(&rlist.r_queue))->p_state = PRCURR; +#if CH_TIME_QUANTUM > 0 rlist.r_preempt = CH_TIME_QUANTUM; +#endif chDbgTrace(otp, currp); chSysSwitchI(otp, currp); } -- cgit v1.2.3