aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/ARM7-AT91SAM7X-GCC/board.c3
-rw-r--r--demos/ARM7-AT91SAM7X-LWIP-GCC/board.c3
-rw-r--r--demos/ARM7-AT91SAM7X-UIP-GCC/board.c3
-rw-r--r--os/io/io.dox42
-rw-r--r--os/io/platforms/STM32/spi_lld.c46
-rw-r--r--os/io/platforms/STM32/spi_lld.h12
-rw-r--r--os/io/spi.c45
-rw-r--r--os/io/spi.h13
-rw-r--r--os/io/templates/spi_lld.c21
-rw-r--r--os/io/templates/spi_lld.h12
-rw-r--r--os/kernel/src/chheap.c2
-rw-r--r--os/kernel/src/chschd.c2
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
@@ -137,6 +137,46 @@
*/
/**
+ * @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.
* @details This module implements a generic interface for MAC (Media
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;
@@ -226,6 +238,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.
*
* @param[in] spip pointer to the @p SPIDriver object
@@ -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
@@ -82,15 +82,6 @@
/*===========================================================================*/
/**
- * @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.
*/
typedef struct {
@@ -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
@@ -47,15 +47,6 @@
/*===========================================================================*/
/**
- * @brief Driver state machine possible states.
- */
-typedef enum {
- SPI_UNINIT = 0,
- SPI_IDLE = 1,
- SPI_ACTIVE = 2
-} spistate_t;
-
-/**
* @brief Driver configuration structure.
*/
typedef struct {
@@ -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);
}