From 1c9c40543009ecd95b56362e6564d26a2755b92a Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 10 Oct 2010 16:28:34 +0000 Subject: Fixed bug 3084764. More enhancements to the SPI driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2244 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/spi.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) (limited to 'os/hal/src/spi.c') diff --git a/os/hal/src/spi.c b/os/hal/src/spi.c index cd5857aa9..75589c736 100644 --- a/os/hal/src/spi.c +++ b/os/hal/src/spi.c @@ -66,11 +66,16 @@ void spiInit(void) { void spiObjectInit(SPIDriver *spip) { spip->spd_state = SPI_STOP; +#if SPI_USE_WAIT + spip->spd_thread = NULL; +#endif /* SPI_USE_WAIT */ +#if SPI_USE_MUTUAL_EXCLUSION #if CH_USE_MUTEXES chMtxInit(&spip->spd_mutex); -#elif CH_USE_SEMAPHORES +#else chSemInit(&spip->spd_semaphore, 1); #endif +#endif /* SPI_USE_MUTUAL_EXCLUSION */ spip->spd_config = NULL; } @@ -296,6 +301,64 @@ void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) { chSysUnlock(); } +#if SPI_USE_WAIT || defined(__DOXYGEN__) +/** + * @brief Awakens the thread waiting for operation completion, if any. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void _spi_wakeup(SPIDriver *spip) { + + if (spip->spd_thread != NULL) { + Thread *tp = spip->spd_thread; + spip->spd_thread = NULL; + tp->p_u.rdymsg = RDY_RESET; + chSchReadyI(tp); + } +} + +/** + * @brief Wait for operation completion. + * @details This function waits for the driver to complete the current + * operation, if an operation is not running when the function is + * invoked then it immediately returns. + * @note No more than one thread can wait on a SPI driver using + * this function. + * + * @param[in] spip pointer to the @p SPIDriver object + * @return The wait status. + * @retval RDY_OK There was not operation running when the function + * has been invoked. + * @retval RDY_RESET The operation completed. + */ +msg_t spiWait(SPIDriver *spip) { + msg_t msg; + + chDbgCheck(spip != NULL, "spiWait"); + + chSysLock(); + chDbgAssert((spip->spd_state == SPI_READY) || + (spip->spd_state == SPI_SELECTED) || + (spip->spd_state == SPI_ACTIVE) || + (spip->spd_state == SPI_SYNC), + "spiUnselect(), #1", + "invalid state"); + chDbgAssert(spip->spd_thread == NULL, "spiWait(), #3", "already waiting"); + if ((spip->spd_state == SPI_ACTIVE) || (spip->spd_state == SPI_SYNC)) { + spip->spd_thread = chThdSelf(); + chSchGoSleepS(spip->spd_thread, THD_STATE_SUSPENDED); + msg = chThdSelf()->p_u.rdymsg; + } + else + msg = RDY_OK; + chSysUnlock(); + return msg; +} + +#endif /* SPI_USE_WAIT */ + #if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) /** * @brief Gains exclusive access to the SPI bus. -- cgit v1.2.3