From c9f2cc4c733932956cd163e0ef3b8e9f90732827 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Tue, 4 Apr 2023 09:53:16 +0000 Subject: [PATCH] I2C slave support in HAL high level driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@16205 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/hal/include/hal_i2c.h | 13 +++- os/hal/src/hal_i2c.c | 130 +++++++++++++++++++++++++++++++++++++++ readme.txt | 1 + 3 files changed, 143 insertions(+), 1 deletion(-) diff --git a/os/hal/include/hal_i2c.h b/os/hal/include/hal_i2c.h index ad8672cce..73d6d3e0e 100644 --- a/os/hal/include/hal_i2c.h +++ b/os/hal/include/hal_i2c.h @@ -66,6 +66,11 @@ /* Derived constants and error checks. */ /*===========================================================================*/ +/* For compatibility, some LLDs could not export this.*/ +#if !defined(I2C_SUPPORTS_SLAVE_MODE) +#define I2C_SUPPORTS_SLAVE_MODE FALSE +#endif + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ @@ -154,7 +159,13 @@ extern "C" { void i2cAcquireBus(I2CDriver *i2cp); void i2cReleaseBus(I2CDriver *i2cp); #endif - +#if I2C_SUPPORTS_SLAVE_MODE == TRUE + msg_t i2cSlaveMatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr); + msg_t i2cSlaveReceiveTimeout(I2CDriver *i2cp, uint8_t *rxbuf, + size_t rxbytes, sysinterval_t timeout); + msg_t i2cSlaveTransmitTimeout(I2CDriver *i2cp, const uint8_t *txbuf, + size_t txbytes, sysinterval_t timeout); +#endif #ifdef __cplusplus } #endif diff --git a/os/hal/src/hal_i2c.c b/os/hal/src/hal_i2c.c index be3e89754..776620129 100644 --- a/os/hal/src/hal_i2c.c +++ b/os/hal/src/hal_i2c.c @@ -299,6 +299,136 @@ void i2cReleaseBus(I2CDriver *i2cp) { } #endif /* I2C_USE_MUTUAL_EXCLUSION == TRUE */ +#if (I2C_SUPPORTS_SLAVE_MODE == TRUE) || defined(__DOXYGEN__) +/** + * @brief Listen I2C bus for address match. + * @details Use 7 bit address (10 bit,dual and general call address dosn't implement yet) . + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * + * @notapi + */ +msg_t i2cSlaveMatchAddress(I2CDriver *i2cp, i2caddr_t addr) { + + osalDbgCheck((i2cp != NULL) && (addr != 0x00)); + + chSysLock(); + + msg_t result = i2c_lld_match_address(i2cp, addr); + + chSysUnlock(); + + return result; +} + +/** + * @brief Receive data via the I2C bus as slave and call handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes size of receive buffer + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @api + */ +msg_t i2cSlaveReceiveTimeout(I2CDriver *i2cp, + uint8_t *rxbuf, + size_t rxbytes, + sysinterval_t timeout) { + msg_t rdymsg; + + osalDbgCheck((i2cp != NULL) && + (rxbytes > 0U) && + (rxbuf != NULL) && + (timeout != TIME_IMMEDIATE)); + + osalDbgAssert(i2cp->state == I2C_READY, "not ready"); + + osalSysLock(); + + i2cp->errors = I2C_NO_ERROR; + i2cp->state = I2C_ACTIVE_RX; + + rdymsg = i2c_lld_slave_receive_timeout(i2cp, rxbuf, rxbytes, timeout); + if (rdymsg == MSG_TIMEOUT) { + i2cp->state = I2C_LOCKED; + } + else { + i2cp->state = I2C_READY; + } + + osalSysUnlock(); + + return rdymsg; +} + +/** + * @brief Transmits data via the I2C bus as slave. + * @details Call this function when Master request data (in request handler) + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] txbuf pointer to the transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @api + */ +msg_t i2cSlaveTransmitTimeout(I2CDriver *i2cp, + const uint8_t *txbuf, + size_t txbytes, + sysinterval_t timeout){ + msg_t rdymsg; + + osalDbgCheck((i2cp != NULL) && + (txbytes > 0U) && + (txbuf != NULL) && + (timeout != TIME_IMMEDIATE)); + + osalDbgAssert(i2cp->state == I2C_READY, "not ready"); + + osalSysLock(); + + i2cp->errors = I2C_NO_ERROR; + i2cp->state = I2C_ACTIVE_TX; + rdymsg = i2c_lld_slave_transmit_timeout(i2cp, txbuf, txbytes, timeout); + if (rdymsg == MSG_TIMEOUT) { + i2cp->state = I2C_LOCKED; + } + else { + i2cp->state = I2C_READY; + } + + osalSysUnlock(); + + return rdymsg; +} +#endif /* I2C_SUPPORTS_SLAVE_MODE == TRUE */ + #endif /* HAL_USE_I2C == TRUE */ /** @} */ diff --git a/readme.txt b/readme.txt index 8edf7a453..b5d48f7e8 100644 --- a/readme.txt +++ b/readme.txt @@ -74,6 +74,7 @@ ***************************************************************************** *** Next *** +- NEW: I2C slave support in HAL high level driver. - NEW: Added settings for STM32 OCTOSPIv1 and OCTOSPIv2 TCR bits SSHIFT and DHQC. - NEW: Automatic removal of duplicated inclusion paths on make command lines.